From 34ab659cd7fd84fd241ec824c026387eea669515 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 13 Mar 2025 12:45:11 +0100 Subject: [PATCH 001/316] Improve Vcarve generating speed --- src/Mod/CAM/Path/Op/Vcarve.py | 99 ++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/src/Mod/CAM/Path/Op/Vcarve.py b/src/Mod/CAM/Path/Op/Vcarve.py index 179c6799a7..72cd651dd2 100644 --- a/src/Mod/CAM/Path/Op/Vcarve.py +++ b/src/Mod/CAM/Path/Op/Vcarve.py @@ -280,33 +280,40 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "App::PropertyLinkList", "BaseShapes", "Path", - QT_TRANSLATE_NOOP("App::Property", "Additional base objects to be engraved"), + QT_TRANSLATE_NOOP( + "App::Property", "Additional base objects to be engraved" + ), ) obj.setEditorMode("BaseShapes", 2) # hide - obj.addProperty( - "App::PropertyBool", - "OptimizeMovements", - "Path", - QT_TRANSLATE_NOOP("App::Property", "Optimize movements"), - ) + if not hasattr(obj, "OptimizeMovements"): - obj.addProperty( - "App::PropertyBool", - "FinishingPass", - "Path", - QT_TRANSLATE_NOOP("App::Property", "Add finishing pass"), - ) + obj.addProperty( + "App::PropertyBool", + "OptimizeMovements", + "Path", + QT_TRANSLATE_NOOP("App::Property", "Optimize movements"), + ) + obj.OptimizeMovements = False - obj.addProperty( - "App::PropertyDistance", - "FinishingPassZOffset", - "Path", - QT_TRANSLATE_NOOP("App::Property", "Finishing pass Z offset"), - ) + if not hasattr(obj, "FinishingPass"): + obj.addProperty( + "App::PropertyBool", + "FinishingPass", + "Path", + QT_TRANSLATE_NOOP("App::Property", "Add finishing pass"), + ) + obj.FinishingPass = False - obj.FinishingPass = False - obj.FinishingPassZOffset = "0.00" + if not hasattr(obj, "FinishingPassZOffset"): + obj.addProperty( + "App::PropertyDistance", + "FinishingPassZOffset", + "Path", + QT_TRANSLATE_NOOP("App::Property", "Finishing pass Z offset"), + ) + + obj.FinishingPassZOffset = "0.00" def initOperation(self, obj): """initOperation(obj) ... create vcarve specific properties.""" @@ -314,7 +321,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "App::PropertyFloat", "Discretize", "Path", - QT_TRANSLATE_NOOP("App::Property", "The deflection value for discretizing arcs"), + QT_TRANSLATE_NOOP( + "App::Property", "The deflection value for discretizing arcs" + ), ) obj.addProperty( "App::PropertyFloat", @@ -334,7 +343,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): ) obj.Colinear = 10.0 - obj.Discretize = 0.01 + obj.Discretize = 0.1 obj.Tolerance = Path.Preferences.defaultGeometryTolerance() self.setupAdditionalProperties(obj) @@ -367,7 +376,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): dist = ptv[-1].distanceToPoint(ptv[0]) if dist < FreeCAD.Base.Precision.confusion(): Path.Log.debug( - "Removing bad carve point: {} from polygon origin".format(dist) + "Removing bad carve point: {} from polygon origin".format( + dist + ) ) del ptv[-1] ptv.append(ptv[0]) @@ -390,13 +401,17 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): e.Color = PRIMARY else: e.Color = SECONDARY + + vd.colorColinear(COLINEAR, obj.Colinear) + vd.colorTwins(TWIN) + vd.colorExterior(EXTERIOR1) vd.colorExterior( EXTERIOR2, - lambda v: not f.isInside(v.toPoint(f.BoundBox.ZMin), obj.Tolerance, True), + lambda v: not f.isInside( + v.toPoint(f.BoundBox.ZMin), obj.Tolerance, True + ), ) - vd.colorColinear(COLINEAR, obj.Colinear) - vd.colorTwins(TWIN) wires = _collectVoronoiWires(vd) wires = _sortVoronoiWires(wires) @@ -462,7 +477,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): path.append(Path.Command("G0 Z{}".format(obj.SafeHeight.Value))) path.append( Path.Command( - "G0 X{} Y{} Z{}".format(newPosition.x, newPosition.y, obj.SafeHeight.Value) + "G0 X{} Y{} Z{}".format( + newPosition.x, newPosition.y, obj.SafeHeight.Value + ) ) ) @@ -470,7 +487,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): vSpeed = obj.ToolController.VertFeed.Value path.append( Path.Command( - "G1 X{} Y{} Z{} F{}".format(newPosition.x, newPosition.y, newPosition.z, vSpeed) + "G1 X{} Y{} Z{} F{}".format( + newPosition.x, newPosition.y, newPosition.z, vSpeed + ) ) ) for e in wire: @@ -496,7 +515,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): _maximumUsableDepth = _get_maximumUsableDepth(wires, geom) if _maximumUsableDepth is not None: maximumUsableDepth = _maximumUsableDepth - Path.Log.debug(f"Maximum usable depth for current face: {maximumUsableDepth}") + Path.Log.debug( + f"Maximum usable depth for current face: {maximumUsableDepth}" + ) # first pass cutWires(wires, pathlist, obj.OptimizeMovements) @@ -534,7 +555,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if obj.ToolController.Tool.CuttingEdgeAngle >= 180.0: Path.Log.info( - translate("CAM_Vcarve", "Engraver cutting edge angle must be < 180 degrees.") + translate( + "CAM_Vcarve", "Engraver cutting edge angle must be < 180 degrees." + ) ) return @@ -552,9 +575,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if not faces: for model in self.model: - if model.isDerivedFrom("Sketcher::SketchObject") or model.isDerivedFrom( - "Part::Part2DObject" - ): + if model.isDerivedFrom( + "Sketcher::SketchObject" + ) or model.isDerivedFrom("Part::Part2DObject"): faces.extend(model.Shape.Faces) if faces: @@ -602,10 +625,14 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): """Debug function to display calculated voronoi edges""" if not getattr(self, "voronoiDebugCache", None): - Path.Log.error("debugVoronoi: empty debug cache. Recompute VCarve operation first") + Path.Log.error( + "debugVoronoi: empty debug cache. Recompute VCarve operation first" + ) return - vPart = FreeCAD.activeDocument().addObject("App::Part", f"{obj.Name}-VoronoiDebug") + vPart = FreeCAD.activeDocument().addObject( + "App::Part", f"{obj.Name}-VoronoiDebug" + ) wiresToShow = [] From e4c9484139dd75eb0c7ba2f455ab2a0cdadafa84 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 13 Mar 2025 19:20:12 +0100 Subject: [PATCH 002/316] migrate isInside to isPartOfDomain --- src/Mod/CAM/Path/Op/Vcarve.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Mod/CAM/Path/Op/Vcarve.py b/src/Mod/CAM/Path/Op/Vcarve.py index 72cd651dd2..f908847920 100644 --- a/src/Mod/CAM/Path/Op/Vcarve.py +++ b/src/Mod/CAM/Path/Op/Vcarve.py @@ -343,7 +343,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): ) obj.Colinear = 10.0 - obj.Discretize = 0.1 + obj.Discretize = 0.25 obj.Tolerance = Path.Preferences.defaultGeometryTolerance() self.setupAdditionalProperties(obj) @@ -359,6 +359,12 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): wires_by_face = dict() self.voronoiDebugCache = dict() + def is_exterior(vertex, face): + vector = FreeCAD.Vector(vertex.toPoint(face.BoundBox.ZMin)) + (u, v) = face.Surface.parameter(vector) + # isPartOfDomain is faster than face.IsInside(...) + return not face.isPartOfDomain(u, v) + def insert_many_wires(vd, wires): for wire in wires: Path.Log.debug("discretize value: {}".format(obj.Discretize)) @@ -402,16 +408,17 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): else: e.Color = SECONDARY + # filter our colinear edged so there are fewer ones + # to iterate over in colorExterior which is slow vd.colorColinear(COLINEAR, obj.Colinear) - vd.colorTwins(TWIN) vd.colorExterior(EXTERIOR1) - vd.colorExterior( - EXTERIOR2, - lambda v: not f.isInside( - v.toPoint(f.BoundBox.ZMin), obj.Tolerance, True - ), - ) + vd.colorExterior(EXTERIOR2, lambda v: is_exterior(v, f)) + + # if colorTwin is done before colorExterior we seem to have + # much more weird exterior edges needed to be filtered out, + # keep it here to be safe + vd.colorTwins(TWIN) wires = _collectVoronoiWires(vd) wires = _sortVoronoiWires(wires) From cec8aca628ed49a5c920a6e85c0167336e48fb72 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 18:25:01 +0000 Subject: [PATCH 003/316] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/Mod/CAM/Path/Op/Vcarve.py | 42 ++++++++++------------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/src/Mod/CAM/Path/Op/Vcarve.py b/src/Mod/CAM/Path/Op/Vcarve.py index f908847920..456409d4fa 100644 --- a/src/Mod/CAM/Path/Op/Vcarve.py +++ b/src/Mod/CAM/Path/Op/Vcarve.py @@ -280,9 +280,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "App::PropertyLinkList", "BaseShapes", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Additional base objects to be engraved" - ), + QT_TRANSLATE_NOOP("App::Property", "Additional base objects to be engraved"), ) obj.setEditorMode("BaseShapes", 2) # hide @@ -321,9 +319,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "App::PropertyFloat", "Discretize", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "The deflection value for discretizing arcs" - ), + QT_TRANSLATE_NOOP("App::Property", "The deflection value for discretizing arcs"), ) obj.addProperty( "App::PropertyFloat", @@ -382,9 +378,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): dist = ptv[-1].distanceToPoint(ptv[0]) if dist < FreeCAD.Base.Precision.confusion(): Path.Log.debug( - "Removing bad carve point: {} from polygon origin".format( - dist - ) + "Removing bad carve point: {} from polygon origin".format(dist) ) del ptv[-1] ptv.append(ptv[0]) @@ -484,9 +478,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): path.append(Path.Command("G0 Z{}".format(obj.SafeHeight.Value))) path.append( Path.Command( - "G0 X{} Y{} Z{}".format( - newPosition.x, newPosition.y, obj.SafeHeight.Value - ) + "G0 X{} Y{} Z{}".format(newPosition.x, newPosition.y, obj.SafeHeight.Value) ) ) @@ -494,9 +486,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): vSpeed = obj.ToolController.VertFeed.Value path.append( Path.Command( - "G1 X{} Y{} Z{} F{}".format( - newPosition.x, newPosition.y, newPosition.z, vSpeed - ) + "G1 X{} Y{} Z{} F{}".format(newPosition.x, newPosition.y, newPosition.z, vSpeed) ) ) for e in wire: @@ -522,9 +512,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): _maximumUsableDepth = _get_maximumUsableDepth(wires, geom) if _maximumUsableDepth is not None: maximumUsableDepth = _maximumUsableDepth - Path.Log.debug( - f"Maximum usable depth for current face: {maximumUsableDepth}" - ) + Path.Log.debug(f"Maximum usable depth for current face: {maximumUsableDepth}") # first pass cutWires(wires, pathlist, obj.OptimizeMovements) @@ -562,9 +550,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if obj.ToolController.Tool.CuttingEdgeAngle >= 180.0: Path.Log.info( - translate( - "CAM_Vcarve", "Engraver cutting edge angle must be < 180 degrees." - ) + translate("CAM_Vcarve", "Engraver cutting edge angle must be < 180 degrees.") ) return @@ -582,9 +568,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if not faces: for model in self.model: - if model.isDerivedFrom( - "Sketcher::SketchObject" - ) or model.isDerivedFrom("Part::Part2DObject"): + if model.isDerivedFrom("Sketcher::SketchObject") or model.isDerivedFrom( + "Part::Part2DObject" + ): faces.extend(model.Shape.Faces) if faces: @@ -632,14 +618,10 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): """Debug function to display calculated voronoi edges""" if not getattr(self, "voronoiDebugCache", None): - Path.Log.error( - "debugVoronoi: empty debug cache. Recompute VCarve operation first" - ) + Path.Log.error("debugVoronoi: empty debug cache. Recompute VCarve operation first") return - vPart = FreeCAD.activeDocument().addObject( - "App::Part", f"{obj.Name}-VoronoiDebug" - ) + vPart = FreeCAD.activeDocument().addObject("App::Part", f"{obj.Name}-VoronoiDebug") wiresToShow = [] From 41d20a62cd8227e94b843a3f3dca4a682bd60766 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 20 Mar 2025 12:48:52 +0100 Subject: [PATCH 004/316] Replace Array operation with array dressup --- src/Mod/CAM/Path/Dressup/Array.py | 379 ++++++++++++++++++++++++++ src/Mod/CAM/Path/Dressup/Base.py | 93 +++++++ src/Mod/CAM/Path/Dressup/Gui/Array.py | 103 +++++++ src/Mod/CAM/Path/GuiInit.py | 1 + src/Mod/CAM/Path/Op/Gui/Array.py | 15 + 5 files changed, 591 insertions(+) create mode 100644 src/Mod/CAM/Path/Dressup/Array.py create mode 100644 src/Mod/CAM/Path/Dressup/Base.py create mode 100644 src/Mod/CAM/Path/Dressup/Gui/Array.py diff --git a/src/Mod/CAM/Path/Dressup/Array.py b/src/Mod/CAM/Path/Dressup/Array.py new file mode 100644 index 0000000000..7a73811232 --- /dev/null +++ b/src/Mod/CAM/Path/Dressup/Array.py @@ -0,0 +1,379 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2015 Yorik van Havre * +# * Reimplemented as dressup in 2025 phaseloop 0: + ang = self.angle / self.copies * (1 + i) + + pl = FreeCAD.Placement() + pl.rotate(self.centre, FreeCAD.Vector(0, 0, 1), ang) + np = PathUtils.applyPlacementToPath(pl, PathUtils.getPathWithPlacement(base)) + output += np.toGCode() + + # return output + return Path.Path(output) + + +def Create(base, name="DressupArray"): + """Create(base, name='DressupPathBoundary') ... creates a dressup array.""" + + if not base.isDerivedFrom("Path::Feature"): + Path.Log.error( + translate("CAM_DressupArray", "The selected object is not a path") + "\n" + ) + return None + + obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) + job = PathUtils.findParentJob(base) + obj.Proxy = DressupArray(obj, base, job) + job.Proxy.addOperation(obj, base, True) + return obj diff --git a/src/Mod/CAM/Path/Dressup/Base.py b/src/Mod/CAM/Path/Dressup/Base.py new file mode 100644 index 0000000000..abf86550ec --- /dev/null +++ b/src/Mod/CAM/Path/Dressup/Base.py @@ -0,0 +1,93 @@ +from PySide.QtCore import QT_TRANSLATE_NOOP + +from Path.Op.Base import ObjectOp + +class DressupBase: + """ + Base class for all dressups to provide common interface with the rest of CAM + One major example is making sure all dressups export base operation settings + like coolant, tool controller, etc. + """ + + def setup_coolant_property(self, obj): + if not hasattr(obj, "CoolantMode"): + obj.addProperty( + "App::PropertyEnumeration", + "CoolantMode", + "CoolantMode", + QT_TRANSLATE_NOOP("App::Property", "Default coolant mode."), + ) + + for n in ObjectOp.opPropertyEnumerations(): + if n[0] == "CoolantMode": + setattr(obj, n[0], n[1]) + + def setup_tool_controller_property(self, obj): + if not hasattr(obj, "ToolController"): + obj.addProperty( + "App::PropertyLink", + "ToolController", + "Path", + QT_TRANSLATE_NOOP( + "App::Property", + "The tool controller that will be used to calculate the path", + ), + ) + + def __init__(self, obj, base): + + obj.addProperty( + "App::PropertyLink", + "Base", + "Base", + QT_TRANSLATE_NOOP("App::Property", "The base path to modify"), + ) + + obj.addProperty( + "App::PropertyBool", + "Active", + "Path", + QT_TRANSLATE_NOOP( + "App::Property", "Make False, to prevent operation from generating code" + ), + ) + + self.setup_coolant_property(obj) + self.setup_tool_controller_property(obj) + + def onDocumentRestored(self, obj): + """ + Called then document is being restored. Often used for object migrations, + adding missing properties, etc. + Do not overwrite - child classes should use dressupOnDocumentRestored(). + """ + self.setup_coolant_property(obj) + self.setup_tool_controller_property(obj) + + def dressupOnDocumentRestored(self, obj): + """Overwrite this method for custom handling.""" + pass + + def execute(self, obj): + """ + Export common properties from base object and + run dressupExecute() + """ + + if hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): + obj.CoolantMode = obj.Base.CoolantMode + + if hasattr(obj, "Base") and hasattr(obj.Base, "ToolController"): + obj.ToolController = obj.Base.ToolController + + return self.dressupExecute(obj) + + def dressupExecute(self, obj): + """ + Called whenever receiver should be recalculated. + Should be overwritten by subclasses. + """ + pass + + + diff --git a/src/Mod/CAM/Path/Dressup/Gui/Array.py b/src/Mod/CAM/Path/Dressup/Gui/Array.py new file mode 100644 index 0000000000..e72a994646 --- /dev/null +++ b/src/Mod/CAM/Path/Dressup/Gui/Array.py @@ -0,0 +1,103 @@ + + +from PySide.QtCore import QT_TRANSLATE_NOOP +import FreeCAD +import Path +import Path.Base.Util as PathUtil +import Path.Dressup.Array as DressupArray +import Path.Main.Stock as PathStock +import PathScripts.PathUtils as PathUtils + +from PySide import QtGui +from PySide.QtCore import QT_TRANSLATE_NOOP +import FreeCAD +import FreeCADGui +import Path +import PathGui + + +class DressupArrayViewProvider(object): + def __init__(self, vobj): + self.attach(vobj) + + def dumps(self): + return None + + def loads(self, state): + return None + + def attach(self, vobj): + self.vobj = vobj + self.obj = vobj.Object + self.panel = None + + def claimChildren(self): + return [self.obj.Base] + + def onDelete(self, vobj, args=None): + if vobj.Object and vobj.Object.Proxy: + vobj.Object.Proxy.onDelete(vobj.Object, args) + return True + + def setEdit(self, vobj, mode=0): + return True + + def unsetEdit(self, vobj, mode=0): + pass + + def setupTaskPanel(self, panel): + pass + + def clearTaskPanel(self): + pass + + +class CommandPathDressupArray: + def GetResources(self): + return { + "Pixmap": "CAM_Dressup", + "MenuText": QT_TRANSLATE_NOOP("CAM_DressupArray", "Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "CAM_DressupArray", + "Creates an array from a selected toolpath", + ), + } + + def IsActive(self): + if FreeCAD.ActiveDocument is not None: + for o in FreeCAD.ActiveDocument.Objects: + if o.Name[:3] == "Job": + return True + return False + + def Activated(self): + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelection() + if len(selection) != 1: + Path.Log.error( + translate("CAM_DressupArray", "Please select one toolpath object") + "\n" + ) + return + baseObject = selection[0] + + # everything ok! + FreeCAD.ActiveDocument.openTransaction("Create Path Array Dress-up") + FreeCADGui.addModule("Path.Dressup.Gui.Array") + FreeCADGui.doCommand( + "Path.Dressup.Gui.Array.Create(App.ActiveDocument.%s)" % baseObject.Name + ) + # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() + FreeCAD.ActiveDocument.recompute() + + +def Create(base, name="DressupPathArray"): + FreeCAD.ActiveDocument.openTransaction("Create an Array dressup") + obj = DressupArray.Create(base, name) + obj.ViewObject.Proxy = DressupArrayViewProvider(obj.ViewObject) + obj.Base.ViewObject.Visibility = False + FreeCAD.ActiveDocument.commitTransaction() + return obj + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand("CAM_DressupArray", CommandPathDressupArray()) diff --git a/src/Mod/CAM/Path/GuiInit.py b/src/Mod/CAM/Path/GuiInit.py index 65a7b798d1..94a29a5638 100644 --- a/src/Mod/CAM/Path/GuiInit.py +++ b/src/Mod/CAM/Path/GuiInit.py @@ -40,6 +40,7 @@ def Startup(): Path.Log.debug("Initializing PathGui") from Path.Base.Gui import PropertyBag from Path.Base.Gui import SetupSheet + from Path.Dressup.Gui import Array from Path.Dressup.Gui import AxisMap from Path.Dressup.Gui import Dogbone from Path.Dressup.Gui import DogboneII diff --git a/src/Mod/CAM/Path/Op/Gui/Array.py b/src/Mod/CAM/Path/Op/Gui/Array.py index 8bbd026730..93ec682081 100644 --- a/src/Mod/CAM/Path/Op/Gui/Array.py +++ b/src/Mod/CAM/Path/Op/Gui/Array.py @@ -27,6 +27,8 @@ import PathScripts import PathScripts.PathUtils as PathUtils from Path.Dressup.Utils import toolController from PySide import QtCore +from PySide import QtGui + import math import random from PySide.QtCore import QT_TRANSLATE_NOOP @@ -203,6 +205,19 @@ class ObjectArray: self.setEditorModes(obj) def execute(self, obj): + if FreeCAD.GuiUp: + + QtGui.QMessageBox.warning( + None, + QT_TRANSLATE_NOOP("CAM_ArrayOp", "Operation is depreciated"), + QT_TRANSLATE_NOOP("CAM_ArrayOp", + ("CAM -> Path Modification -> Array operation is depreciated " + "and will be removed in future FreeCAD versions.\n\n" + "Please use CAM -> Path Dressup -> Array instead.\n\n" + "DO NOT USE CURRENT ARRAY OPERATION WHEN MACHINING WITH COOLANT!\n" + "Due to a bug - collant will not be enabled for array paths." + )), + ) # backwards compatibility for PathArrays created before support for multiple bases if isinstance(obj.Base, list): base = obj.Base From 585ac82c34180aba484d2509979a7a864dfd87f4 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 20 Mar 2025 14:26:36 +0100 Subject: [PATCH 005/316] log error on invalid base object --- src/Mod/CAM/Path/Dressup/Array.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/CAM/Path/Dressup/Array.py b/src/Mod/CAM/Path/Dressup/Array.py index 7a73811232..4e860989cc 100644 --- a/src/Mod/CAM/Path/Dressup/Array.py +++ b/src/Mod/CAM/Path/Dressup/Array.py @@ -183,6 +183,7 @@ class DressupArray(DressupBase): or not obj.Base.isDerivedFrom("Path::Feature") or not obj.Base.Path ): + Path.Log.error(translate("PathArray", "Base is empty or an invalid object.")) return None # Do not generate paths and clear current Path data if operation not From e8cd9a61d6e6279fccde86003d2261f49c212b64 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 20 Mar 2025 14:28:09 +0100 Subject: [PATCH 006/316] add missing dressup import --- src/Mod/CAM/InitGui.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/CAM/InitGui.py b/src/Mod/CAM/InitGui.py index aef883fef9..3975cb7f2f 100644 --- a/src/Mod/CAM/InitGui.py +++ b/src/Mod/CAM/InitGui.py @@ -122,6 +122,7 @@ class CAMWorkbench(Workbench): drillingcmdlist = ["CAM_Drilling", "CAM_Tapping"] modcmdlist = ["CAM_OperationCopy", "CAM_Array", "CAM_SimpleCopy"] dressupcmdlist = [ + "CAM_DressupArray", "CAM_DressupAxisMap", "CAM_DressupPathBoundary", "CAM_DressupDogbone", From c249b62b6cd23e084dbc5a3875a5cc48477adde6 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 20 Mar 2025 15:02:56 +0100 Subject: [PATCH 007/316] update CMake imports --- src/Mod/CAM/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Mod/CAM/CMakeLists.txt b/src/Mod/CAM/CMakeLists.txt index de03de7190..88976ed088 100644 --- a/src/Mod/CAM/CMakeLists.txt +++ b/src/Mod/CAM/CMakeLists.txt @@ -59,6 +59,8 @@ SET(PathPythonBaseGui_SRCS SET(PathPythonDressup_SRCS Path/Dressup/__init__.py Path/Dressup/Utils.py + Path/Dressup/Array.py + Path/Dressup/Base.py Path/Dressup/Boundary.py Path/Dressup/DogboneII.py Path/Dressup/Tags.py @@ -66,6 +68,7 @@ SET(PathPythonDressup_SRCS SET(PathPythonDressupGui_SRCS Path/Dressup/Gui/__init__.py + Path/Dressup/Gui/Array.py Path/Dressup/Gui/AxisMap.py Path/Dressup/Gui/Dogbone.py Path/Dressup/Gui/DogboneII.py From f0fc6ccde1eb1dbd64884b7af0c970339fcfa43c Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 22 Mar 2025 17:10:54 -0500 Subject: [PATCH 008/316] Base: Remove deprecated Py_GetPath call Replace it with a piece of code that replicates the functionality. Also eliminate the round-trip through char * that this function was using (the final variable is stored as a std::string anyway). --- src/App/Application.cpp | 4 ++-- src/Base/Interpreter.cpp | 36 +++++++++++++++++++++++++++++++----- src/Base/Interpreter.h | 4 +++- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 6c7c5222d5..d5ff4c731b 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -2635,8 +2635,8 @@ void Application::initConfig(int argc, char ** argv) Py_DECREF(pyModule); } - const char* pythonpath = Base::Interpreter().init(argc,argv); - if (pythonpath) + std::string pythonpath = Base::Interpreter().init(argc,argv); + if (!pythonpath.empty()) mConfig["PythonSearchPath"] = pythonpath; else Base::Console().Warning("Encoding of Python paths failed\n"); diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index 561c7798d8..de026dd469 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -538,8 +538,36 @@ void InterpreterSingleton::addPythonPath(const char* Path) list.append(Py::String(Path)); } +std::string InterpreterSingleton::getPythonPath() +{ + // Construct something that looks like the output of the now-deprecated Py_GetPath + PyGILStateLocker lock; + PyObject* path = PySys_GetObject("path"); + std::string result; + const char* separator = ":"; // Use ":" on Unix-like systems, ";" on Windows +#ifdef FC_OS_WIN32 + separator = ";"; +#endif + Py_ssize_t length = PyList_Size(path); + for (Py_ssize_t i = 0; i < length; ++i) { + PyObject* item = PyList_GetItem(path, i); // Borrowed reference + if (!item) { + throw Base::RuntimeError("Failed to retrieve item from path"); + } + const char* item_str = PyUnicode_AsUTF8(item); + if (!item_str) { + throw Base::RuntimeError("Failed to convert path item to UTF-8 string"); + } + if (!result.empty()) { + result += separator; + } + result += item_str; + } + return result; +} + #if PY_VERSION_HEX < 0x030b0000 -const char* InterpreterSingleton::init(int argc, char* argv[]) +std::string InterpreterSingleton::init(int argc, char* argv[]) { if (!Py_IsInitialized()) { Py_SetProgramName(Py_DecodeLocale(argv[0], nullptr)); @@ -617,7 +645,7 @@ void initInterpreter(int argc, char* argv[]) Py_Initialize(); } } // namespace -const char* InterpreterSingleton::init(int argc, char* argv[]) +std::string InterpreterSingleton::init(int argc, char* argv[]) { try { if (!Py_IsInitialized()) { @@ -626,9 +654,7 @@ const char* InterpreterSingleton::init(int argc, char* argv[]) PythonStdOutput::init_type(); this->_global = PyEval_SaveThread(); } - - PyGILStateLocker lock; - return Py_EncodeLocale(Py_GetPath(), nullptr); + return getPythonPath(); } catch (const Base::Exception& e) { e.ReportException(); diff --git a/src/Base/Interpreter.h b/src/Base/Interpreter.h index f2787a4d22..e2196a3897 100644 --- a/src/Base/Interpreter.h +++ b/src/Base/Interpreter.h @@ -285,6 +285,8 @@ public: bool loadModule(const char* psModName); /// Add an additional python path void addPythonPath(const char* Path); + /// Get the path (replaces the deprecated Py_GetPath method) + std::string getPythonPath(); static void addType(PyTypeObject* Type, PyObject* Module, const char* Name); /// Add a module and return a PyObject to it PyObject* addModule(Py::ExtensionModuleBase*); @@ -313,7 +315,7 @@ public: */ //@{ /// init the interpreter and returns the module search path - const char* init(int argc, char* argv[]); + std::string init(int argc, char* argv[]); int runCommandLine(const char* prompt); void replaceStdOutput(); static InterpreterSingleton& Instance(); From 3cbcab042e40228da522f9cd314628c75963d8f0 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 22 Mar 2025 18:42:06 -0500 Subject: [PATCH 009/316] Main: Replace uses of Py_GetPath() Deprecated in Python 3.13 --- src/Main/MainCmd.cpp | 2 +- src/Main/MainGui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Main/MainCmd.cpp b/src/Main/MainCmd.cpp index 8dba8a5ef2..01ffa7bd78 100644 --- a/src/Main/MainCmd.cpp +++ b/src/Main/MainCmd.cpp @@ -100,7 +100,7 @@ int main(int argc, char** argv) msg << "While initializing " << appName << " the following exception occurred: '" << e.what() << "'\n\n"; msg << "Python is searching for its runtime files in the following directories:\n" - << Py_EncodeLocale(Py_GetPath(), nullptr) << "\n\n"; + << Base::Interpreter().getPythonPath() << "\n\n"; msg << "Python version information:\n" << Py_GetVersion() << "\n"; const char* pythonhome = getenv("PYTHONHOME"); if (pythonhome) { diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index bcb07ffd19..1066298cab 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -266,7 +266,7 @@ int main(int argc, char** argv) "Python version information:\n%4\n") .arg(appName, QString::fromUtf8(e.what()), - QString::fromUtf8(Py_EncodeLocale(Py_GetPath(), nullptr)), + QString::fromStdString(Base::Interpreter().getPythonPath()), QString::fromLatin1(Py_GetVersion())); const char* pythonhome = getenv("PYTHONHOME"); if (pythonhome) { From 07fcf551d0908ded54fe0309027664252a4fcf98 Mon Sep 17 00:00:00 2001 From: Paul Lee Date: Sun, 23 Mar 2025 12:06:27 +0800 Subject: [PATCH 010/316] [Draft-Faces] Bind: Improve fuse and warning 1. Face fuse per segment (original code has a whole face/segment disappear when a face is self-intersecting or reversed) 2. Return warning if face is self-intersecting Or reversed Github Issue: - https://github.com/FreeCAD/FreeCAD/issues/19721#issuecomment-2744738019 FreeCAD Forum: - https://forum.freecad.org/viewtopic.php?p=816758#p816758 - https://forum.freecad.org/viewtopic.php?p=813062#p813062 --- src/Mod/Draft/draftgeoutils/faces.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftgeoutils/faces.py b/src/Mod/Draft/draftgeoutils/faces.py index 60b8a8faa5..1c329f0fc8 100644 --- a/src/Mod/Draft/draftgeoutils/faces.py +++ b/src/Mod/Draft/draftgeoutils/faces.py @@ -120,15 +120,21 @@ 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() - return Part.Face(Part.Wire(w1.Edges + [w3] + w2.Edges + [w4])) except Part.OCCError: print("DraftGeomUtils: unable to bind wires") return None + if w3.section(w4).Vertexes: + print("DraftGeomUtils: Problem, a segment is self-intersecting, please check!") + f = Part.Face(Part.Wire(w1.Edges + [w3] + w2.Edges + [w4])) + if f.normalAt(0,0).z == -1: + print("DraftGeomUtils: Problem, a segment direction is reversed, please check!") + return f if not w1 or not w2: print("DraftGeomUtils: unable to bind wires") @@ -164,6 +170,7 @@ def bind(w1, w2, per_segment=False): if face is None: return None faces.append(face) + # Usually there is last series of face after above 'for' routine, # EXCEPT when the last edge pair touch, faces had been appended # to faces_list, and reset faces =[] @@ -185,14 +192,25 @@ def bind(w1, w2, per_segment=False): faces_fused_list = [] for faces in faces_list: if len(faces) > 1 : - faces_fused = faces[0].fuse(faces[1:]).removeSplitter().Faces[0] - faces_fused_list.append(faces_fused) + # Below not good if a face is self-intersecting or reversed + #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] + faces_fused_list.append(rf) + # faces might be empty list [], see above; skip if empty elif faces: faces_fused_list.append(faces[0]) # Only 1 face + return Part.Compound(faces_fused_list) else: - return faces[0].fuse(faces[1:]).removeSplitter().Faces[0] + # Below not good if a face is self-intersecting or reversed + #return faces[0].fuse(faces[1:]).removeSplitter().Faces[0] + rf = faces[0] + for f in faces[1:]: + rf = rf.fuse(f).removeSplitter().Faces[0] + return rf elif w1.isClosed() and w2.isClosed(): d1 = w1.BoundBox.DiagonalLength From 8ab6bd7d4b0893d8f5c2d923c1b27a567eb04206 Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Sun, 23 Mar 2025 23:29:43 +0100 Subject: [PATCH 011/316] BIM: cleanup imports in bimcommands --- src/Mod/BIM/bimcommands/BimArchUtils.py | 5 +--- src/Mod/BIM/bimcommands/BimAxis.py | 4 ++-- src/Mod/BIM/bimcommands/BimBackground.py | 1 - src/Mod/BIM/bimcommands/BimBox.py | 3 +-- src/Mod/BIM/bimcommands/BimBuilder.py | 2 -- src/Mod/BIM/bimcommands/BimBuildingPart.py | 4 ++-- src/Mod/BIM/bimcommands/BimClassification.py | 16 +++++++------ src/Mod/BIM/bimcommands/BimCommon.py | 2 -- src/Mod/BIM/bimcommands/BimCompound.py | 2 -- src/Mod/BIM/bimcommands/BimConvert.py | 1 - src/Mod/BIM/bimcommands/BimCurtainwall.py | 3 +-- src/Mod/BIM/bimcommands/BimCut.py | 2 -- src/Mod/BIM/bimcommands/BimCutPlane.py | 3 +-- src/Mod/BIM/bimcommands/BimDiff.py | 3 +-- src/Mod/BIM/bimcommands/BimDimensions.py | 2 +- src/Mod/BIM/bimcommands/BimDoor.py | 1 - src/Mod/BIM/bimcommands/BimDrawingView.py | 4 +--- src/Mod/BIM/bimcommands/BimEmptyTrash.py | 1 - src/Mod/BIM/bimcommands/BimEquipment.py | 3 +-- src/Mod/BIM/bimcommands/BimExamples.py | 3 +-- src/Mod/BIM/bimcommands/BimExtrude.py | 2 -- src/Mod/BIM/bimcommands/BimFence.py | 3 +-- src/Mod/BIM/bimcommands/BimFrame.py | 4 +--- src/Mod/BIM/bimcommands/BimFuse.py | 2 -- src/Mod/BIM/bimcommands/BimGlue.py | 1 - src/Mod/BIM/bimcommands/BimHelp.py | 3 +-- src/Mod/BIM/bimcommands/BimIfcElements.py | 5 ++-- src/Mod/BIM/bimcommands/BimIfcExplorer.py | 15 ++++++------ src/Mod/BIM/bimcommands/BimIfcProperties.py | 22 +++++++++-------- src/Mod/BIM/bimcommands/BimIfcQuantities.py | 8 ++++--- src/Mod/BIM/bimcommands/BimImagePlane.py | 1 - src/Mod/BIM/bimcommands/BimLayers.py | 12 +++++----- src/Mod/BIM/bimcommands/BimLeader.py | 2 +- src/Mod/BIM/bimcommands/BimLibrary.py | 14 ++++++----- src/Mod/BIM/bimcommands/BimMaterial.py | 2 +- src/Mod/BIM/bimcommands/BimNudge.py | 5 ++-- src/Mod/BIM/bimcommands/BimOffset.py | 2 -- src/Mod/BIM/bimcommands/BimPanel.py | 3 --- src/Mod/BIM/bimcommands/BimPipe.py | 3 +-- src/Mod/BIM/bimcommands/BimPreflight.py | 25 ++++++++++---------- src/Mod/BIM/bimcommands/BimProfile.py | 3 +-- src/Mod/BIM/bimcommands/BimProject.py | 1 - src/Mod/BIM/bimcommands/BimProjectManager.py | 13 +++++----- src/Mod/BIM/bimcommands/BimRebar.py | 3 +-- src/Mod/BIM/bimcommands/BimReextrude.py | 1 - src/Mod/BIM/bimcommands/BimReference.py | 3 +-- src/Mod/BIM/bimcommands/BimReorder.py | 3 +-- src/Mod/BIM/bimcommands/BimRewire.py | 1 - src/Mod/BIM/bimcommands/BimRoof.py | 4 +--- src/Mod/BIM/bimcommands/BimSchedule.py | 3 +-- src/Mod/BIM/bimcommands/BimSectionPlane.py | 3 +-- src/Mod/BIM/bimcommands/BimSetup.py | 9 +++---- src/Mod/BIM/bimcommands/BimShape2DView.py | 2 +- src/Mod/BIM/bimcommands/BimSimpleCopy.py | 2 -- src/Mod/BIM/bimcommands/BimSite.py | 2 +- src/Mod/BIM/bimcommands/BimSketch.py | 1 - src/Mod/BIM/bimcommands/BimSpace.py | 3 +-- src/Mod/BIM/bimcommands/BimStairs.py | 3 +-- src/Mod/BIM/bimcommands/BimTDPage.py | 4 ++-- src/Mod/BIM/bimcommands/BimTDView.py | 1 - src/Mod/BIM/bimcommands/BimText.py | 2 -- src/Mod/BIM/bimcommands/BimTogglePanels.py | 1 + src/Mod/BIM/bimcommands/BimTrash.py | 1 - src/Mod/BIM/bimcommands/BimTruss.py | 3 +-- src/Mod/BIM/bimcommands/BimTutorial.py | 11 +++++---- src/Mod/BIM/bimcommands/BimUngroup.py | 1 - src/Mod/BIM/bimcommands/BimViews.py | 2 ++ src/Mod/BIM/bimcommands/BimWall.py | 3 +-- src/Mod/BIM/bimcommands/BimWelcome.py | 4 +--- src/Mod/BIM/bimcommands/BimWindow.py | 3 ++- src/Mod/BIM/bimcommands/BimWindows.py | 9 +++---- src/Mod/BIM/bimcommands/__init__.py | 5 ++-- 72 files changed, 130 insertions(+), 179 deletions(-) diff --git a/src/Mod/BIM/bimcommands/BimArchUtils.py b/src/Mod/BIM/bimcommands/BimArchUtils.py index 9b31ef04d4..ec3de06802 100644 --- a/src/Mod/BIM/bimcommands/BimArchUtils.py +++ b/src/Mod/BIM/bimcommands/BimArchUtils.py @@ -22,18 +22,15 @@ """Misc Arch util commands""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") - - class Arch_Add: "the Arch Add command definition" diff --git a/src/Mod/BIM/bimcommands/BimAxis.py b/src/Mod/BIM/bimcommands/BimAxis.py index debbcf3682..fb23223dee 100644 --- a/src/Mod/BIM/bimcommands/BimAxis.py +++ b/src/Mod/BIM/bimcommands/BimAxis.py @@ -22,16 +22,16 @@ """The BIM Axis-related commands""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") + class Arch_Axis: "the Arch Axis command definition" diff --git a/src/Mod/BIM/bimcommands/BimBackground.py b/src/Mod/BIM/bimcommands/BimBackground.py index 9f9051fe84..eceeadd664 100644 --- a/src/Mod/BIM/bimcommands/BimBackground.py +++ b/src/Mod/BIM/bimcommands/BimBackground.py @@ -24,7 +24,6 @@ """The BIM Background command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimBox.py b/src/Mod/BIM/bimcommands/BimBox.py index 82968934b6..1d35a71545 100644 --- a/src/Mod/BIM/bimcommands/BimBox.py +++ b/src/Mod/BIM/bimcommands/BimBox.py @@ -23,7 +23,6 @@ """The BIM Box command""" -import os import FreeCAD import FreeCADGui @@ -141,7 +140,7 @@ class BIM_Box: def taskbox(self): "sets up a taskbox widget" - from PySide import QtCore, QtGui + from PySide import QtGui wid = QtGui.QWidget() ui = FreeCADGui.UiLoader() diff --git a/src/Mod/BIM/bimcommands/BimBuilder.py b/src/Mod/BIM/bimcommands/BimBuilder.py index b007a6cbdc..21528447db 100644 --- a/src/Mod/BIM/bimcommands/BimBuilder.py +++ b/src/Mod/BIM/bimcommands/BimBuilder.py @@ -24,7 +24,6 @@ """The BIM Builder command""" - import FreeCAD import FreeCADGui @@ -43,7 +42,6 @@ class BIM_Builder: } def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Builder") diff --git a/src/Mod/BIM/bimcommands/BimBuildingPart.py b/src/Mod/BIM/bimcommands/BimBuildingPart.py index e90326e7e8..bacc2b2d7f 100644 --- a/src/Mod/BIM/bimcommands/BimBuildingPart.py +++ b/src/Mod/BIM/bimcommands/BimBuildingPart.py @@ -25,12 +25,12 @@ # TODO: Refactor the Site code so it becomes a BuildingPart too -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -56,7 +56,7 @@ class Arch_Level: FreeCADGui.addModule("Arch") FreeCADGui.addModule("Draft") FreeCADGui.addModule("WorkingPlane") - FreeCADGui.doCommand("obj = Arch.makeFloor(FreeCADGui.Selection.getSelection())") + FreeCADGui.doCommand("obj = Arch.makeFloor(FreeCADGui.Selection.getSelection())") FreeCADGui.doCommand("obj.Placement = WorkingPlane.get_working_plane().get_placement()") FreeCADGui.doCommand("Draft.autogroup(obj)") FreeCAD.ActiveDocument.commitTransaction() diff --git a/src/Mod/BIM/bimcommands/BimClassification.py b/src/Mod/BIM/bimcommands/BimClassification.py index 32c1efed23..e0c272b5b4 100644 --- a/src/Mod/BIM/bimcommands/BimClassification.py +++ b/src/Mod/BIM/bimcommands/BimClassification.py @@ -22,13 +22,14 @@ """The BIM Classification command""" +import os import FreeCAD import FreeCADGui -import os QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -306,7 +307,7 @@ class BIM_Classification: # self.spanTopLevels() def updateByTree(self): - from PySide import QtCore, QtGui + from PySide import QtGui # order by hierarchy def istop(obj): @@ -368,8 +369,8 @@ class BIM_Classification: self.form.treeObjects.expandAll() def updateDefault(self): + from PySide import QtGui import Draft - from PySide import QtCore, QtGui d = self.objectslist.copy() d.update(self.matlist) @@ -389,7 +390,7 @@ class BIM_Classification: self.form.treeObjects.setCurrentItem(it) def updateClasses(self, search=""): - from PySide import QtCore, QtGui + from PySide import QtGui self.form.treeClass.clear() @@ -436,7 +437,7 @@ class BIM_Classification: first = False def addChildren(self, children, parent, search=""): - from PySide import QtCore, QtGui + from PySide import QtGui if children: for c in children: @@ -526,7 +527,8 @@ class BIM_Classification: ) if not os.path.exists(preset): return None - import codecs, re + import codecs + import re d = Item() with codecs.open(preset, "r", "utf-8") as f: @@ -663,7 +665,7 @@ class BIM_Classification: def getIcon(self,obj): """returns a QIcon for an object""" - from PySide import QtCore, QtGui + from PySide import QtGui import Arch_rc if hasattr(obj.ViewObject, "Icon"): diff --git a/src/Mod/BIM/bimcommands/BimCommon.py b/src/Mod/BIM/bimcommands/BimCommon.py index d3e720b00d..3a464ec276 100644 --- a/src/Mod/BIM/bimcommands/BimCommon.py +++ b/src/Mod/BIM/bimcommands/BimCommon.py @@ -24,7 +24,6 @@ """The BIM Common command""" - import FreeCAD import FreeCADGui @@ -47,7 +46,6 @@ class BIM_Common: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Common") diff --git a/src/Mod/BIM/bimcommands/BimCompound.py b/src/Mod/BIM/bimcommands/BimCompound.py index 216fe7fd5e..3f5d2a5366 100644 --- a/src/Mod/BIM/bimcommands/BimCompound.py +++ b/src/Mod/BIM/bimcommands/BimCompound.py @@ -24,7 +24,6 @@ """The BIM Compound command""" - import FreeCAD import FreeCADGui @@ -47,7 +46,6 @@ class BIM_Compound: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Compound") diff --git a/src/Mod/BIM/bimcommands/BimConvert.py b/src/Mod/BIM/bimcommands/BimConvert.py index 79377e2c30..8dac4243bd 100644 --- a/src/Mod/BIM/bimcommands/BimConvert.py +++ b/src/Mod/BIM/bimcommands/BimConvert.py @@ -24,7 +24,6 @@ """The BIM Convert command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimCurtainwall.py b/src/Mod/BIM/bimcommands/BimCurtainwall.py index 7dd821d0e1..d88e75ba1e 100644 --- a/src/Mod/BIM/bimcommands/BimCurtainwall.py +++ b/src/Mod/BIM/bimcommands/BimCurtainwall.py @@ -22,13 +22,12 @@ """Misc Arch util commands""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimCut.py b/src/Mod/BIM/bimcommands/BimCut.py index e9dca8d967..99b8086eb5 100644 --- a/src/Mod/BIM/bimcommands/BimCut.py +++ b/src/Mod/BIM/bimcommands/BimCut.py @@ -24,7 +24,6 @@ """The BIM Cut command""" - import FreeCAD import FreeCADGui @@ -46,7 +45,6 @@ class BIM_Cut: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Cut") diff --git a/src/Mod/BIM/bimcommands/BimCutPlane.py b/src/Mod/BIM/bimcommands/BimCutPlane.py index a19280a8ec..36d3b8abef 100644 --- a/src/Mod/BIM/bimcommands/BimCutPlane.py +++ b/src/Mod/BIM/bimcommands/BimCutPlane.py @@ -23,13 +23,12 @@ """The Arch CutPlane command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimDiff.py b/src/Mod/BIM/bimcommands/BimDiff.py index 0205a52f93..ef1c8f4724 100644 --- a/src/Mod/BIM/bimcommands/BimDiff.py +++ b/src/Mod/BIM/bimcommands/BimDiff.py @@ -22,7 +22,6 @@ """The BIM Diff command""" -import os import FreeCAD import FreeCADGui @@ -49,7 +48,7 @@ class BIM_Diff: # make the main doc the active one before running this script! # what will be compared: IDs, geometry, materials. Everything else is discarded. - from PySide import QtCore, QtGui + from PySide import QtGui import Draft MOVE_TOLERANCE = 0.2 # the max allowed move in mm diff --git a/src/Mod/BIM/bimcommands/BimDimensions.py b/src/Mod/BIM/bimcommands/BimDimensions.py index 18a8bd8f98..e700f70fdb 100644 --- a/src/Mod/BIM/bimcommands/BimDimensions.py +++ b/src/Mod/BIM/bimcommands/BimDimensions.py @@ -24,9 +24,9 @@ """The BIM DimensionAligned command""" - import FreeCAD import FreeCADGui + from draftguitools import gui_dimensions QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP diff --git a/src/Mod/BIM/bimcommands/BimDoor.py b/src/Mod/BIM/bimcommands/BimDoor.py index d6598fce1d..4a28b73022 100644 --- a/src/Mod/BIM/bimcommands/BimDoor.py +++ b/src/Mod/BIM/bimcommands/BimDoor.py @@ -24,7 +24,6 @@ """The BIM Door command""" - import FreeCAD import FreeCADGui from bimcommands import BimWindow diff --git a/src/Mod/BIM/bimcommands/BimDrawingView.py b/src/Mod/BIM/bimcommands/BimDrawingView.py index 637a68fd01..7635e33cd7 100644 --- a/src/Mod/BIM/bimcommands/BimDrawingView.py +++ b/src/Mod/BIM/bimcommands/BimDrawingView.py @@ -22,14 +22,12 @@ """The BIM DrawingView command""" - -import os import FreeCAD import FreeCADGui -from bimcommands import BimBuildingPart QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimEmptyTrash.py b/src/Mod/BIM/bimcommands/BimEmptyTrash.py index 5feeb10cff..4f2053cf63 100644 --- a/src/Mod/BIM/bimcommands/BimEmptyTrash.py +++ b/src/Mod/BIM/bimcommands/BimEmptyTrash.py @@ -24,7 +24,6 @@ """The BIM EmptyTrash command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimEquipment.py b/src/Mod/BIM/bimcommands/BimEquipment.py index e0bc19f7a7..09c215a751 100644 --- a/src/Mod/BIM/bimcommands/BimEquipment.py +++ b/src/Mod/BIM/bimcommands/BimEquipment.py @@ -22,13 +22,12 @@ """BIM equipment commands""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimExamples.py b/src/Mod/BIM/bimcommands/BimExamples.py index 6661f47308..cb1c4c9102 100644 --- a/src/Mod/BIM/bimcommands/BimExamples.py +++ b/src/Mod/BIM/bimcommands/BimExamples.py @@ -24,7 +24,6 @@ """The BIM Examples command""" - import FreeCAD import FreeCADGui @@ -44,7 +43,7 @@ class BIM_Examples: } def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui QtGui.QDesktopServices.openUrl("https://github.com/yorikvanhavre/FreeCAD-BIM-examples") diff --git a/src/Mod/BIM/bimcommands/BimExtrude.py b/src/Mod/BIM/bimcommands/BimExtrude.py index 6a37b4cd62..fad47e8439 100644 --- a/src/Mod/BIM/bimcommands/BimExtrude.py +++ b/src/Mod/BIM/bimcommands/BimExtrude.py @@ -24,7 +24,6 @@ """The BIM Extrude command""" - import FreeCAD import FreeCADGui @@ -45,7 +44,6 @@ class BIM_Extrude: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Extrude") diff --git a/src/Mod/BIM/bimcommands/BimFence.py b/src/Mod/BIM/bimcommands/BimFence.py index 2592c32c13..18ee964541 100644 --- a/src/Mod/BIM/bimcommands/BimFence.py +++ b/src/Mod/BIM/bimcommands/BimFence.py @@ -22,13 +22,12 @@ """BIM fence command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimFrame.py b/src/Mod/BIM/bimcommands/BimFrame.py index da946eb765..8009cac553 100644 --- a/src/Mod/BIM/bimcommands/BimFrame.py +++ b/src/Mod/BIM/bimcommands/BimFrame.py @@ -22,13 +22,12 @@ """BIM Frame command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -62,4 +61,3 @@ class Arch_Frame: FreeCADGui.addCommand('Arch_Frame',Arch_Frame()) - diff --git a/src/Mod/BIM/bimcommands/BimFuse.py b/src/Mod/BIM/bimcommands/BimFuse.py index b33b1edca9..dbacdaf23d 100644 --- a/src/Mod/BIM/bimcommands/BimFuse.py +++ b/src/Mod/BIM/bimcommands/BimFuse.py @@ -24,7 +24,6 @@ """The BIM Fuse command""" - import FreeCAD import FreeCADGui @@ -44,7 +43,6 @@ class BIM_Fuse: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Fuse") diff --git a/src/Mod/BIM/bimcommands/BimGlue.py b/src/Mod/BIM/bimcommands/BimGlue.py index 81f2534978..9300d521ad 100644 --- a/src/Mod/BIM/bimcommands/BimGlue.py +++ b/src/Mod/BIM/bimcommands/BimGlue.py @@ -24,7 +24,6 @@ """The BIM Glue command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimHelp.py b/src/Mod/BIM/bimcommands/BimHelp.py index 1df2bdb66b..0cda131f23 100644 --- a/src/Mod/BIM/bimcommands/BimHelp.py +++ b/src/Mod/BIM/bimcommands/BimHelp.py @@ -24,7 +24,6 @@ """The BIM Help command""" - import FreeCAD import FreeCADGui @@ -44,7 +43,7 @@ class BIM_Help: } def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui QtGui.QDesktopServices.openUrl("https://www.freecadweb.org/wiki/BIM_Workbench") diff --git a/src/Mod/BIM/bimcommands/BimIfcElements.py b/src/Mod/BIM/bimcommands/BimIfcElements.py index 123afb057b..5192271d7e 100644 --- a/src/Mod/BIM/bimcommands/BimIfcElements.py +++ b/src/Mod/BIM/bimcommands/BimIfcElements.py @@ -24,7 +24,6 @@ """This module contains FreeCAD commands for the BIM workbench""" -import os import FreeCAD import FreeCADGui @@ -50,7 +49,7 @@ class BIM_IfcElements: def Activated(self): import Draft - from PySide import QtCore, QtGui + from PySide import QtGui # build objects list self.objectslist = {} @@ -634,7 +633,7 @@ if FreeCAD.GuiUp: def getIcon(obj): """returns a QIcon for an object""" - from PySide import QtCore, QtGui + from PySide import QtGui import Arch_rc if hasattr(obj.ViewObject, "Icon"): diff --git a/src/Mod/BIM/bimcommands/BimIfcExplorer.py b/src/Mod/BIM/bimcommands/BimIfcExplorer.py index fc772f8976..cb96f40af3 100644 --- a/src/Mod/BIM/bimcommands/BimIfcExplorer.py +++ b/src/Mod/BIM/bimcommands/BimIfcExplorer.py @@ -21,6 +21,7 @@ # *************************************************************************** import os + import FreeCAD import FreeCADGui @@ -44,7 +45,7 @@ class BIM_IfcExplorer: def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui try: import ifcopenshell @@ -174,7 +175,7 @@ class BIM_IfcExplorer: "opens a file" import ifcopenshell - from PySide import QtCore, QtGui + from PySide import QtGui self.filename = "" lastfolder = FreeCAD.ParamGet( @@ -253,7 +254,7 @@ class BIM_IfcExplorer: "inserts selected objects in the active document" from importers import importIFC - from PySide import QtCore, QtGui + from PySide import QtCore doc = FreeCAD.ActiveDocument if doc and self.filename: @@ -472,7 +473,7 @@ class BIM_IfcExplorer: "adds the attributes of the given IFC entity under the given QTreeWidgetITem" import ifcopenshell - from PySide import QtCore, QtGui + from PySide import QtGui entity = self.ifc[eid] @@ -555,7 +556,7 @@ class BIM_IfcExplorer: def addProperties(self, eid, parent): "adds properties of a given entity to the given QTReeWidgetItem" - from PySide import QtCore, QtGui + from PySide import QtGui entity = self.ifc[eid] if hasattr(entity, "IsDefinedBy"): @@ -585,7 +586,7 @@ class BIM_IfcExplorer: def onSelectTree(self, item, previous): "displays attributes and properties of a tree item" - from PySide import QtCore, QtGui + from PySide import QtCore self.backnav.append(previous) eid = item.data(0, QtCore.Qt.UserRole) @@ -628,7 +629,7 @@ class BIM_IfcExplorer: def onDoubleClickTree(self, item, column): "when a property or attribute is double-clicked" - from PySide import QtCore, QtGui + from PySide import QtCore if self.tree: txt = item.text(column) diff --git a/src/Mod/BIM/bimcommands/BimIfcProperties.py b/src/Mod/BIM/bimcommands/BimIfcProperties.py index 02a8f42b16..9bb01e3fbe 100644 --- a/src/Mod/BIM/bimcommands/BimIfcProperties.py +++ b/src/Mod/BIM/bimcommands/BimIfcProperties.py @@ -26,11 +26,13 @@ import os import sys + import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -53,7 +55,7 @@ class BIM_IfcProperties: return v def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui try: import ArchIFC @@ -244,7 +246,7 @@ class BIM_IfcProperties: return result def updateByType(self): - from PySide import QtCore, QtGui + from PySide import QtGui groups = {} for name, role in self.objectslist.items(): @@ -278,7 +280,7 @@ class BIM_IfcProperties: self.spanTopLevels() def updateByTree(self): - from PySide import QtCore, QtGui + from PySide import QtGui # order by hierarchy def istop(obj): @@ -336,7 +338,7 @@ class BIM_IfcProperties: self.form.tree.expandAll() def updateDefault(self): - from PySide import QtCore, QtGui + from PySide import QtGui for name, role in self.objectslist.items(): role = role[0] @@ -432,7 +434,7 @@ class BIM_IfcProperties: return props def getSearchResults(self, obj): - from PySide import QtCore, QtGui + from PySide import QtGui text = self.form.searchField.currentText() if not text: @@ -465,7 +467,7 @@ class BIM_IfcProperties: return QtGui.QStandardItem() def updateProperties(self, sel1=None, sel2=None): - from PySide import QtCore, QtGui + from PySide import QtGui self.propmodel.clear() self.propmodel.setHorizontalHeaderLabels( @@ -628,7 +630,7 @@ class BIM_IfcProperties: del self.objectslist[name][1][prop] def addProperty(self, idx=0, pset=None, prop=None, ptype=None): - from PySide import QtCore, QtGui + from PySide import QtGui if not self.form.tree.selectedIndexes(): return @@ -685,7 +687,7 @@ class BIM_IfcProperties: self.form.comboProperty.setCurrentIndex(0) def addPset(self, idx): - from PySide import QtCore, QtGui + from PySide import QtGui if not self.form.tree.selectedIndexes(): return @@ -732,7 +734,7 @@ class BIM_IfcProperties: self.form.comboPset.setCurrentIndex(0) def removeProperty(self): - from PySide import QtCore, QtGui + from PySide import QtGui sel = self.form.treeProperties.selectedIndexes() remove = [] @@ -764,7 +766,7 @@ class BIM_IfcProperties: if FreeCAD.GuiUp: - from PySide import QtCore, QtGui + from PySide import QtGui class propertiesDelegate(QtGui.QStyledItemDelegate): def __init__(self, parent=None, container=None, ptypes=[], plabels=[], *args): diff --git a/src/Mod/BIM/bimcommands/BimIfcQuantities.py b/src/Mod/BIM/bimcommands/BimIfcQuantities.py index f1ea3d0b19..36678c5f10 100644 --- a/src/Mod/BIM/bimcommands/BimIfcQuantities.py +++ b/src/Mod/BIM/bimcommands/BimIfcQuantities.py @@ -24,13 +24,15 @@ """This module contains FreeCAD commands for the BIM workbench""" -import os import csv +import os + import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") QPROPS = [ @@ -81,7 +83,7 @@ class BIM_IfcQuantities: return v def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui # build objects list self.objectslist = {} @@ -329,7 +331,7 @@ class BIM_IfcQuantities: """Updates a single line of the table, without updating the actual object""" - from PySide import QtCore, QtGui + from PySide import QtCore i = self.get_row(name) if i == -1: diff --git a/src/Mod/BIM/bimcommands/BimImagePlane.py b/src/Mod/BIM/bimcommands/BimImagePlane.py index f171639c09..4d35e51cf7 100644 --- a/src/Mod/BIM/bimcommands/BimImagePlane.py +++ b/src/Mod/BIM/bimcommands/BimImagePlane.py @@ -24,7 +24,6 @@ """The BIM ImagePlane command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimLayers.py b/src/Mod/BIM/bimcommands/BimLayers.py index 4ad159229b..236af77e50 100644 --- a/src/Mod/BIM/bimcommands/BimLayers.py +++ b/src/Mod/BIM/bimcommands/BimLayers.py @@ -22,12 +22,12 @@ """Layers manager for FreeCAD""" -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -35,7 +35,7 @@ def getColorIcon(color): "returns a QtGui.QIcon from a color 3-float tuple" - from PySide import QtCore, QtGui + from PySide import 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) @@ -64,7 +64,7 @@ class BIM_Layers: def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui # store changes to be committed self.deleteList = [] @@ -441,7 +441,7 @@ class BIM_Layers: def onToggle(self): "toggle selected layers on/off" - from PySide import QtCore, QtGui + from PySide import QtCore state = None for index in self.dialog.tree.selectedIndexes(): @@ -460,7 +460,7 @@ class BIM_Layers: def onIsolate(self): "isolates the selected layers (turns all the others off" - from PySide import QtCore, QtGui + from PySide import QtCore onrows = [] for index in self.dialog.tree.selectedIndexes(): @@ -473,7 +473,7 @@ class BIM_Layers: def onIFC(self): "attributes this layer to an IFC project" - from PySide import QtCore, QtGui + from PySide import QtGui for index in self.dialog.tree.selectedIndexes(): if index.column() == 1: diff --git a/src/Mod/BIM/bimcommands/BimLeader.py b/src/Mod/BIM/bimcommands/BimLeader.py index 6f65590b79..f76b21ce10 100644 --- a/src/Mod/BIM/bimcommands/BimLeader.py +++ b/src/Mod/BIM/bimcommands/BimLeader.py @@ -24,9 +24,9 @@ """The BIM Leader command""" - import FreeCAD import FreeCADGui + from draftguitools import gui_lines # Line tool from Draft QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP diff --git a/src/Mod/BIM/bimcommands/BimLibrary.py b/src/Mod/BIM/bimcommands/BimLibrary.py index 40c9607ee9..a781aeb82f 100644 --- a/src/Mod/BIM/bimcommands/BimLibrary.py +++ b/src/Mod/BIM/bimcommands/BimLibrary.py @@ -25,13 +25,15 @@ from __future__ import print_function """The BIM library tool""" -import sys import os +import sys + import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") FILTERS = [ @@ -108,7 +110,7 @@ class BIM_Library_TaskPanel: def __init__(self, offlinemode=False): - from PySide import QtCore, QtGui + from PySide import QtGui self.mainDocName = FreeCAD.Gui.ActiveDocument.Document.Name self.previewDocName = "Viewer" @@ -345,7 +347,9 @@ class BIM_Library_TaskPanel: def addtolibrary(self): # DISABLED - import Part, Mesh, os + import os + import Mesh + import Part self.fileDialog = QtGui.QFileDialog.getSaveFileName( None, "Save As", self.librarypath @@ -380,7 +384,6 @@ class BIM_Library_TaskPanel: def setSearchModel(self, text): - import PartGui from PySide import QtGui def add_line(f, dp): @@ -445,7 +448,6 @@ class BIM_Library_TaskPanel: def setOnlineModel(self): from PySide import QtGui - import PartGui def addItems(root, d, path): for k, v in d.items(): @@ -813,8 +815,8 @@ class BIM_Library_TaskPanel: def getOnlineContentsAPI(self, url): """same as getOnlineContents but uses github API (faster)""" - import requests import json + import requests result = {} count = 0 diff --git a/src/Mod/BIM/bimcommands/BimMaterial.py b/src/Mod/BIM/bimcommands/BimMaterial.py index 29061417e7..581c4852b7 100644 --- a/src/Mod/BIM/bimcommands/BimMaterial.py +++ b/src/Mod/BIM/bimcommands/BimMaterial.py @@ -22,12 +22,12 @@ """This module contains FreeCAD commands for the BIM workbench""" -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") if FreeCAD.GuiUp: diff --git a/src/Mod/BIM/bimcommands/BimNudge.py b/src/Mod/BIM/bimcommands/BimNudge.py index 25186739f6..4d74d2338c 100644 --- a/src/Mod/BIM/bimcommands/BimNudge.py +++ b/src/Mod/BIM/bimcommands/BimNudge.py @@ -22,7 +22,6 @@ """BIM nudge commands""" -import os import FreeCAD import FreeCADGui @@ -36,7 +35,7 @@ class BIM_Nudge: def getNudgeValue(self, mode): "mode can be dist, up, down, left, right. dist returns a float in mm, other modes return a 3D vector" - from PySide import QtCore, QtGui + from PySide import QtGui mw = FreeCADGui.getMainWindow() if mw: @@ -136,7 +135,7 @@ class BIM_Nudge_Switch(BIM_Nudge): } def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui mw = FreeCADGui.getMainWindow() if mw: diff --git a/src/Mod/BIM/bimcommands/BimOffset.py b/src/Mod/BIM/bimcommands/BimOffset.py index 406d629882..8cfc912b48 100644 --- a/src/Mod/BIM/bimcommands/BimOffset.py +++ b/src/Mod/BIM/bimcommands/BimOffset.py @@ -24,7 +24,6 @@ """The BIM Offset command""" - import FreeCAD import FreeCADGui @@ -46,7 +45,6 @@ class BIM_Offset2D: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_Offset2D") diff --git a/src/Mod/BIM/bimcommands/BimPanel.py b/src/Mod/BIM/bimcommands/BimPanel.py index c0cbb7352f..f4f8c78203 100644 --- a/src/Mod/BIM/bimcommands/BimPanel.py +++ b/src/Mod/BIM/bimcommands/BimPanel.py @@ -22,8 +22,6 @@ """BIM Panel-related Arch_""" - -import os import FreeCAD import FreeCADGui @@ -334,7 +332,6 @@ class NestTaskPanel: def __init__(self,obj=None): import ArchNesting - from PySide import QtCore, QtGui self.form = FreeCADGui.PySideUic.loadUi(":/ui/ArchNest.ui") self.form.progressBar.hide() self.form.ButtonPreview.setEnabled(False) diff --git a/src/Mod/BIM/bimcommands/BimPipe.py b/src/Mod/BIM/bimcommands/BimPipe.py index 82bfe2fe1c..4d624a2ae5 100644 --- a/src/Mod/BIM/bimcommands/BimPipe.py +++ b/src/Mod/BIM/bimcommands/BimPipe.py @@ -22,13 +22,12 @@ """BIM Panel-related Arch_""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimPreflight.py b/src/Mod/BIM/bimcommands/BimPreflight.py index 11fc0acdf7..fb28048f19 100644 --- a/src/Mod/BIM/bimcommands/BimPreflight.py +++ b/src/Mod/BIM/bimcommands/BimPreflight.py @@ -22,9 +22,11 @@ """This module contains FreeCAD commands for the BIM workbench""" - -import sys +import importlib +import inspect import os +import sys + import FreeCAD import FreeCADGui @@ -32,10 +34,6 @@ QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate -import importlib -import inspect - - tests = [ "testAll", "testIFC4", @@ -80,7 +78,7 @@ class BIM_Preflight: class BIM_Preflight_TaskPanel: def __init__(self): - from PySide import QtCore, QtGui + from PySide import QtGui self.results = {} # to store the result message self.culprits = {} # to store objects to highlight @@ -156,12 +154,12 @@ class BIM_Preflight_TaskPanel: self.customTests[butname] = func def getStandardButtons(self): - from PySide import QtCore, QtGui + from PySide import QtGui return QtGui.QDialogButtonBox.Close def reject(self): - from PySide import QtCore, QtGui + from PySide import QtGui QtGui.QApplication.restoreOverrideCursor() FreeCADGui.Control.closeDialog() @@ -170,7 +168,7 @@ class BIM_Preflight_TaskPanel: def passed(self, test): "sets the button as passed" - from PySide import QtCore, QtGui + from PySide import QtGui getattr(self.form, test).setIcon(QtGui.QIcon(":/icons/button_valid.svg")) getattr(self.form, test).setText(translate("BIM", "Passed")) @@ -181,7 +179,7 @@ class BIM_Preflight_TaskPanel: def failed(self, test): "sets the button as failed" - from PySide import QtCore, QtGui + from PySide import QtGui getattr(self.form, test).setIcon(QtGui.QIcon(":/icons/process-stop.svg")) getattr(self.form, test).setText("Failed") @@ -192,7 +190,7 @@ class BIM_Preflight_TaskPanel: def reset(self, test): "reset the button" - from PySide import QtCore, QtGui + from PySide import QtGui getattr(self.form, test).setIcon(QtGui.QIcon(":/icons/button_right.svg")) getattr(self.form, test).setText(translate("BIM", "Test")) @@ -293,7 +291,7 @@ class BIM_Preflight_TaskPanel: def testAll(self): "runs all tests" - from PySide import QtCore, QtGui + from PySide import QtGui from draftutils import todo for test in tests: @@ -698,6 +696,7 @@ class BIM_Preflight_TaskPanel: def testQuantities(self): "tests for explicit quantities export" + import Draft from PySide import QtCore, QtGui test = "testQuantities" diff --git a/src/Mod/BIM/bimcommands/BimProfile.py b/src/Mod/BIM/bimcommands/BimProfile.py index d6cbc3b8b6..2d71d592e9 100644 --- a/src/Mod/BIM/bimcommands/BimProfile.py +++ b/src/Mod/BIM/bimcommands/BimProfile.py @@ -22,13 +22,12 @@ """BIM Panel-related Arch_""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimProject.py b/src/Mod/BIM/bimcommands/BimProject.py index 3f0f5a705c..9e22957a52 100644 --- a/src/Mod/BIM/bimcommands/BimProject.py +++ b/src/Mod/BIM/bimcommands/BimProject.py @@ -24,7 +24,6 @@ """The BIM Project command - Includes previous Arch Project""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index 83213f75df..96041080c6 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -22,10 +22,9 @@ """This module contains FreeCAD commands for the BIM workbench""" - -import os -import sys import math +import os + import FreeCAD import FreeCADGui @@ -49,7 +48,7 @@ class BIM_ProjectManager: import FreeCADGui import ArchBuildingPart - from PySide import QtCore, QtGui + from PySide import QtGui self.form = FreeCADGui.PySideUic.loadUi(":/ui/dialogProjectManager.ui") self.project = None @@ -413,7 +412,7 @@ class BIM_ProjectManager: def savePreset(self): import Arch - from PySide import QtCore, QtGui + from PySide import QtGui res = QtGui.QInputDialog.getText( None, @@ -648,7 +647,7 @@ class BIM_ProjectManager: ) d.Meta = values - from PySide import QtCore, QtGui + from PySide import QtGui filename = QtGui.QFileDialog.getSaveFileName( QtGui.QApplication.activeWindow(), @@ -670,7 +669,7 @@ class BIM_ProjectManager: """loads the contents of a template into the current file""" import FreeCADGui - from PySide import QtCore, QtGui + from PySide import QtGui filename = QtGui.QFileDialog.getOpenFileName( QtGui.QApplication.activeWindow(), diff --git a/src/Mod/BIM/bimcommands/BimRebar.py b/src/Mod/BIM/bimcommands/BimRebar.py index 02bc0cdbee..520041e0ff 100644 --- a/src/Mod/BIM/bimcommands/BimRebar.py +++ b/src/Mod/BIM/bimcommands/BimRebar.py @@ -22,13 +22,12 @@ """BIM Rebar command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimReextrude.py b/src/Mod/BIM/bimcommands/BimReextrude.py index b21f06a51a..efae914e35 100644 --- a/src/Mod/BIM/bimcommands/BimReextrude.py +++ b/src/Mod/BIM/bimcommands/BimReextrude.py @@ -24,7 +24,6 @@ """This module contains FreeCAD commands for the BIM workbench""" -import os import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimReference.py b/src/Mod/BIM/bimcommands/BimReference.py index 0a00ab5478..064581e635 100644 --- a/src/Mod/BIM/bimcommands/BimReference.py +++ b/src/Mod/BIM/bimcommands/BimReference.py @@ -22,13 +22,12 @@ """BIM Rebar command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimReorder.py b/src/Mod/BIM/bimcommands/BimReorder.py index 34eff7841c..d926afbe23 100644 --- a/src/Mod/BIM/bimcommands/BimReorder.py +++ b/src/Mod/BIM/bimcommands/BimReorder.py @@ -23,7 +23,6 @@ """This module contains FreeCAD commands for the BIM workbench""" -import os import FreeCAD import FreeCADGui @@ -57,7 +56,7 @@ class BIM_Reorder: class BIM_Reorder_TaskPanel: def __init__(self, obj): - from PySide import QtCore, QtGui + from PySide import QtGui self.obj = obj self.form = FreeCADGui.PySideUic.loadUi(":/ui/dialogReorder.ui") diff --git a/src/Mod/BIM/bimcommands/BimRewire.py b/src/Mod/BIM/bimcommands/BimRewire.py index 869bcc6076..a8fda529ee 100644 --- a/src/Mod/BIM/bimcommands/BimRewire.py +++ b/src/Mod/BIM/bimcommands/BimRewire.py @@ -24,7 +24,6 @@ """The BIM Rewire command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimRoof.py b/src/Mod/BIM/bimcommands/BimRoof.py index 97e097be76..029dc0d533 100644 --- a/src/Mod/BIM/bimcommands/BimRoof.py +++ b/src/Mod/BIM/bimcommands/BimRoof.py @@ -22,13 +22,12 @@ """BIM Roof command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -83,4 +82,3 @@ class Arch_Roof: FreeCADGui.addCommand("Arch_Roof", Arch_Roof()) - diff --git a/src/Mod/BIM/bimcommands/BimSchedule.py b/src/Mod/BIM/bimcommands/BimSchedule.py index 8018925232..2ecfdf1568 100644 --- a/src/Mod/BIM/bimcommands/BimSchedule.py +++ b/src/Mod/BIM/bimcommands/BimSchedule.py @@ -22,13 +22,12 @@ """BIM Schedule command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimSectionPlane.py b/src/Mod/BIM/bimcommands/BimSectionPlane.py index c6a326b27a..89da1c5be1 100644 --- a/src/Mod/BIM/bimcommands/BimSectionPlane.py +++ b/src/Mod/BIM/bimcommands/BimSectionPlane.py @@ -22,13 +22,12 @@ """BIM Schedule command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimSetup.py b/src/Mod/BIM/bimcommands/BimSetup.py index c5ea7ef468..d77b1b4d94 100644 --- a/src/Mod/BIM/bimcommands/BimSetup.py +++ b/src/Mod/BIM/bimcommands/BimSetup.py @@ -24,6 +24,7 @@ import os import sys + import FreeCAD import FreeCADGui @@ -396,7 +397,7 @@ class BIM_Setup: ) def setPreset(self, preset=None): - from PySide import QtCore, QtGui + from PySide import QtGui unit = None decimals = None @@ -650,11 +651,11 @@ class BIM_Setup: ifcok = True if not ifcok: # ifcopenshell not installed - import re import json - from PySide import QtGui - import zipfile + import re from urllib import request + import zipfile + from PySide import QtGui if not FreeCAD.GuiUp: reply = QtGui.QMessageBox.Yes diff --git a/src/Mod/BIM/bimcommands/BimShape2DView.py b/src/Mod/BIM/bimcommands/BimShape2DView.py index 3d69e95c34..9816e28c42 100644 --- a/src/Mod/BIM/bimcommands/BimShape2DView.py +++ b/src/Mod/BIM/bimcommands/BimShape2DView.py @@ -24,9 +24,9 @@ """The BIM ShapeView command""" - import FreeCAD import FreeCADGui + from draftguitools import gui_shape2dview QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP diff --git a/src/Mod/BIM/bimcommands/BimSimpleCopy.py b/src/Mod/BIM/bimcommands/BimSimpleCopy.py index 1bf6b5edfc..747b45f03d 100644 --- a/src/Mod/BIM/bimcommands/BimSimpleCopy.py +++ b/src/Mod/BIM/bimcommands/BimSimpleCopy.py @@ -24,7 +24,6 @@ """The BIM SimpleCopy command""" - import FreeCAD import FreeCADGui @@ -47,7 +46,6 @@ class BIM_SimpleCopy: return v def Activated(self): - import PartGui FreeCADGui.runCommand("Part_SimpleCopy") diff --git a/src/Mod/BIM/bimcommands/BimSite.py b/src/Mod/BIM/bimcommands/BimSite.py index 0fb487e83a..77ea154c10 100644 --- a/src/Mod/BIM/bimcommands/BimSite.py +++ b/src/Mod/BIM/bimcommands/BimSite.py @@ -25,12 +25,12 @@ # TODO: Refactor the Site code so it becomes a BuildingPart too -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimSketch.py b/src/Mod/BIM/bimcommands/BimSketch.py index 355d1c4732..6ccd1e3f8d 100644 --- a/src/Mod/BIM/bimcommands/BimSketch.py +++ b/src/Mod/BIM/bimcommands/BimSketch.py @@ -24,7 +24,6 @@ """The Bim Sketch command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimSpace.py b/src/Mod/BIM/bimcommands/BimSpace.py index a05e39ff0f..7874dc7d4f 100644 --- a/src/Mod/BIM/bimcommands/BimSpace.py +++ b/src/Mod/BIM/bimcommands/BimSpace.py @@ -22,13 +22,12 @@ """BIM Schedule command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimStairs.py b/src/Mod/BIM/bimcommands/BimStairs.py index 1491de5645..a47e0fc10b 100644 --- a/src/Mod/BIM/bimcommands/BimStairs.py +++ b/src/Mod/BIM/bimcommands/BimStairs.py @@ -22,13 +22,12 @@ """BIM Schedule command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimTDPage.py b/src/Mod/BIM/bimcommands/BimTDPage.py index f1f5966dd0..ebfdc703a0 100644 --- a/src/Mod/BIM/bimcommands/BimTDPage.py +++ b/src/Mod/BIM/bimcommands/BimTDPage.py @@ -24,10 +24,10 @@ """The BIM TDPage command""" +import os import FreeCAD import FreeCADGui -import os QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate @@ -49,7 +49,7 @@ class BIM_TDPage: return v def Activated(self): - from PySide import QtCore, QtGui + from PySide import QtGui import TechDraw templatedir = FreeCAD.ParamGet( diff --git a/src/Mod/BIM/bimcommands/BimTDView.py b/src/Mod/BIM/bimcommands/BimTDView.py index a80c0819d4..ae0416a2a4 100644 --- a/src/Mod/BIM/bimcommands/BimTDView.py +++ b/src/Mod/BIM/bimcommands/BimTDView.py @@ -24,7 +24,6 @@ """The BIM TD View command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimText.py b/src/Mod/BIM/bimcommands/BimText.py index f7b1fd3800..f57978df58 100644 --- a/src/Mod/BIM/bimcommands/BimText.py +++ b/src/Mod/BIM/bimcommands/BimText.py @@ -24,7 +24,6 @@ """This module contains BIM wrappers for commands from other workbenches""" - import FreeCAD import FreeCADGui @@ -87,4 +86,3 @@ class BIM_Text: FreeCADGui.addCommand("BIM_Text", BIM_Text()) - diff --git a/src/Mod/BIM/bimcommands/BimTogglePanels.py b/src/Mod/BIM/bimcommands/BimTogglePanels.py index b77da954fe..4b6e4b37c7 100644 --- a/src/Mod/BIM/bimcommands/BimTogglePanels.py +++ b/src/Mod/BIM/bimcommands/BimTogglePanels.py @@ -28,6 +28,7 @@ import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimTrash.py b/src/Mod/BIM/bimcommands/BimTrash.py index fc0db35cec..d4800cf87d 100644 --- a/src/Mod/BIM/bimcommands/BimTrash.py +++ b/src/Mod/BIM/bimcommands/BimTrash.py @@ -24,7 +24,6 @@ """The BIM Trash command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimTruss.py b/src/Mod/BIM/bimcommands/BimTruss.py index 6aab7bc40b..7652fa5fbe 100644 --- a/src/Mod/BIM/bimcommands/BimTruss.py +++ b/src/Mod/BIM/bimcommands/BimTruss.py @@ -22,13 +22,12 @@ """BIM Truss command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimTutorial.py b/src/Mod/BIM/bimcommands/BimTutorial.py index e7b53e3dbc..c43997b4e2 100644 --- a/src/Mod/BIM/bimcommands/BimTutorial.py +++ b/src/Mod/BIM/bimcommands/BimTutorial.py @@ -22,13 +22,14 @@ """This is the tutorial of the BIM workbench""" - import os + import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -91,7 +92,9 @@ class BIM_Tutorial: QtCore.QTimer.singleShot(1000, self.load) def load(self, arg=None): - import re, sys, codecs + import codecs + import re + import sys if sys.version_info.major < 3: import urllib2 @@ -212,7 +215,7 @@ class BIM_Tutorial: self.update() def update(self): - from PySide import QtCore, QtGui + from PySide import QtCore if not hasattr(self, "form") or not self.form or not hasattr(self, "dock"): return @@ -271,7 +274,7 @@ class BIM_Tutorial: QtCore.QTimer.singleShot(TESTINTERVAL, self.checkGoals) def checkGoals(self): - from PySide import QtCore, QtGui + from PySide import QtCore if not hasattr(self, "form"): return diff --git a/src/Mod/BIM/bimcommands/BimUngroup.py b/src/Mod/BIM/bimcommands/BimUngroup.py index 1b6ab04147..0784a219d8 100644 --- a/src/Mod/BIM/bimcommands/BimUngroup.py +++ b/src/Mod/BIM/bimcommands/BimUngroup.py @@ -24,7 +24,6 @@ """The BIM Ungroup command""" - import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/bimcommands/BimViews.py b/src/Mod/BIM/bimcommands/BimViews.py index 1c03676a87..0d16b21aee 100644 --- a/src/Mod/BIM/bimcommands/BimViews.py +++ b/src/Mod/BIM/bimcommands/BimViews.py @@ -23,11 +23,13 @@ """The BIM Views command""" import sys + import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + UPDATEINTERVAL = 2000 # number of milliseconds between BIM Views window update PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimWall.py b/src/Mod/BIM/bimcommands/BimWall.py index 4c65847aa0..13a973d170 100644 --- a/src/Mod/BIM/bimcommands/BimWall.py +++ b/src/Mod/BIM/bimcommands/BimWall.py @@ -22,13 +22,12 @@ """BIM wall command""" - -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/bimcommands/BimWelcome.py b/src/Mod/BIM/bimcommands/BimWelcome.py index f06e52e2c4..6a9f8456ad 100644 --- a/src/Mod/BIM/bimcommands/BimWelcome.py +++ b/src/Mod/BIM/bimcommands/BimWelcome.py @@ -22,11 +22,11 @@ """This module contains FreeCAD commands for the BIM workbench""" -import os import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") @@ -41,8 +41,6 @@ class BIM_Welcome: } def Activated(self): - from PySide import QtCore, QtGui - self.form = FreeCADGui.PySideUic.loadUi(":ui/dialogWelcome.ui") # handle the tutorial links diff --git a/src/Mod/BIM/bimcommands/BimWindow.py b/src/Mod/BIM/bimcommands/BimWindow.py index a65114acb4..076364eb3c 100644 --- a/src/Mod/BIM/bimcommands/BimWindow.py +++ b/src/Mod/BIM/bimcommands/BimWindow.py @@ -22,13 +22,14 @@ """BIM window command""" - import os + import FreeCAD import FreeCADGui QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") ALLOWEDHOSTS = ["Wall","Structure","Roof"] diff --git a/src/Mod/BIM/bimcommands/BimWindows.py b/src/Mod/BIM/bimcommands/BimWindows.py index 65839f26e4..a37de39e1a 100644 --- a/src/Mod/BIM/bimcommands/BimWindows.py +++ b/src/Mod/BIM/bimcommands/BimWindows.py @@ -22,7 +22,6 @@ """The BIM Windows Manager command""" -import os import FreeCAD import FreeCADGui @@ -52,7 +51,7 @@ class BIM_Windows: class BIM_Windows_TaskPanel: def __init__(self): - from PySide import QtCore, QtGui + from PySide import QtGui self.form = FreeCADGui.PySideUic.loadUi(":/ui/dialogWindows.ui") self.form.setWindowIcon(QtGui.QIcon(":/icons/BIM_Windows.svg")) @@ -78,7 +77,8 @@ class BIM_Windows_TaskPanel: FreeCAD.ActiveDocument.recompute() def update(self, index=None): - import Draft, Arch_rc + import Draft + import Arch_rc from PySide import QtGui self.form.windows.clear() @@ -214,7 +214,8 @@ class BIM_Windows_TaskPanel: self.update() def setMaterial(self): - import Draft, Arch_rc + import Draft + import Arch_rc from PySide import QtGui form = FreeCADGui.PySideUic.loadUi(":/ui/dialogMaterialChooser.ui") diff --git a/src/Mod/BIM/bimcommands/__init__.py b/src/Mod/BIM/bimcommands/__init__.py index 88d2ce3c47..ef6aed1f43 100644 --- a/src/Mod/BIM/bimcommands/__init__.py +++ b/src/Mod/BIM/bimcommands/__init__.py @@ -1,7 +1,8 @@ +import glob +import os + import Arch_rc import PartGui -import os -import glob # populate the list of submodules modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py")) From 7bbfa68698002591d103cb15b4c02b4777e5045a Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Sun, 23 Mar 2025 23:30:31 +0100 Subject: [PATCH 012/316] BIM: cleanup imports in importers --- src/Mod/BIM/importers/exportIFC.py | 29 ++++++------ src/Mod/BIM/importers/exportIFCHelper.py | 7 ++- src/Mod/BIM/importers/import3DS.py | 12 +++-- src/Mod/BIM/importers/importDAE.py | 25 +++++----- src/Mod/BIM/importers/importGBXML.py | 13 ++++-- src/Mod/BIM/importers/importIFC.py | 26 ++++++----- src/Mod/BIM/importers/importIFCHelper.py | 2 +- src/Mod/BIM/importers/importIFClegacy.py | 35 +++++++++----- src/Mod/BIM/importers/importIFCmulticore.py | 11 +++-- src/Mod/BIM/importers/importOBJ.py | 20 ++++---- src/Mod/BIM/importers/importSH3D.py | 15 +++--- src/Mod/BIM/importers/importSH3DHelper.py | 51 +++++++++++---------- src/Mod/BIM/importers/importSHP.py | 6 +-- src/Mod/BIM/importers/importWebGL.py | 32 ++++++------- 14 files changed, 157 insertions(+), 127 deletions(-) diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index fcec025928..55c119c692 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -18,41 +18,44 @@ # * USA * # * * # *************************************************************************** -"""Provide the exporter for IFC files used above all in Arch and BIM. -Internally it uses IfcOpenShell, which must be installed before using. -""" +__title__ = "FreeCAD IFC export" +__author__ = ("Yorik van Havre", "Jonathan Wiedemann", "Bernd Hahnebach") +__url__ = "https://www.freecad.org" + ## @package exportIFC # \ingroup ARCH # \brief IFC file format exporter # # This module provides tools to export IFC files. +"""Provide the exporter for IFC files used above all in Arch and BIM. + +Internally it uses IfcOpenShell, which must be installed before using. +""" + +import math import os import time import tempfile -import math from builtins import open as pyopen import FreeCAD -import Part -import Draft +import FreeCADGui import Arch +import Draft import DraftVecUtils +import Part import ArchIFCSchema -from importers import exportIFCHelper -from importers import exportIFCStructuralTools from DraftGeomUtils import vec -from importers.importIFCHelper import dd2dms from draftutils import params from draftutils.messages import _msg, _err -import FreeCADGui +from importers import exportIFCHelper +from importers import exportIFCStructuralTools +from importers.importIFCHelper import dd2dms -__title__ = "FreeCAD IFC export" -__author__ = ("Yorik van Havre", "Jonathan Wiedemann", "Bernd Hahnebach") -__url__ = "https://www.freecad.org" PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") diff --git a/src/Mod/BIM/importers/exportIFCHelper.py b/src/Mod/BIM/importers/exportIFCHelper.py index 8e153de3af..373243965f 100644 --- a/src/Mod/BIM/importers/exportIFCHelper.py +++ b/src/Mod/BIM/importers/exportIFCHelper.py @@ -22,12 +22,15 @@ import json import math -import FreeCAD -# import Draft import ifcopenshell from ifcopenshell import guid + +import FreeCAD +# import Draft + from draftutils import params + def getObjectsOfIfcType(objects, ifcType): results = [] for object in objects: diff --git a/src/Mod/BIM/importers/import3DS.py b/src/Mod/BIM/importers/import3DS.py index 0027c25c1b..c00c7f3902 100644 --- a/src/Mod/BIM/importers/import3DS.py +++ b/src/Mod/BIM/importers/import3DS.py @@ -19,20 +19,24 @@ #* * #*************************************************************************** -import os,FreeCAD,Mesh - __title__ = "FreeCAD 3DS importer" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" -DEBUG = True - ## @package import3DS # \ingroup ARCH # \brief 3DS file format importer # # This module provides tools to import 3DS files. +import os + +import FreeCAD +import Mesh + +DEBUG = True + + def check3DS(): "checks if collada if available" global dom3ds diff --git a/src/Mod/BIM/importers/importDAE.py b/src/Mod/BIM/importers/importDAE.py index 9a3797dae4..a2005f5ee0 100644 --- a/src/Mod/BIM/importers/importDAE.py +++ b/src/Mod/BIM/importers/importDAE.py @@ -19,18 +19,29 @@ #* * #*************************************************************************** +__title__ = "FreeCAD Collada importer" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package importDAE +# \ingroup ARCH +# \brief DAE (Collada) file format importer and exporter +# +# This module provides tools to import and export Collada (.dae) files. + import os from typing import Optional import numpy as np -from draftutils import params +import FreeCAD import Arch import Draft -import FreeCAD import Mesh import MeshPart +from draftutils import params + if FreeCAD.GuiUp: from draftutils.translate import translate else: @@ -39,16 +50,6 @@ else: return text # \endcond -## @package importDAE -# \ingroup ARCH -# \brief DAE (Collada) file format importer and exporter -# -# This module provides tools to import and export Collada (.dae) files. - -__title__ = "FreeCAD Collada importer" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - DEBUG = True diff --git a/src/Mod/BIM/importers/importGBXML.py b/src/Mod/BIM/importers/importGBXML.py index 5cc0f5ea18..e8f6ce5f1c 100644 --- a/src/Mod/BIM/importers/importGBXML.py +++ b/src/Mod/BIM/importers/importGBXML.py @@ -23,6 +23,14 @@ __title__ = "FreeCAD GbXml exporter" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" +## @package importGBXML +# \ingroup ARCH +# \brief GBXML file format exporter +# +# This module provides tools to export GBXML files. + +from builtins import open as pyopen + import FreeCAD import Draft @@ -34,11 +42,6 @@ else: return txt # \endcond -## @package importGBXML -# \ingroup ARCH -# \brief GBXML file format exporter -# -# This module provides tools to export GBXML files. def export(objectslist,filename): diff --git a/src/Mod/BIM/importers/importIFC.py b/src/Mod/BIM/importers/importIFC.py index 8689280076..dcfbda5249 100644 --- a/src/Mod/BIM/importers/importIFC.py +++ b/src/Mod/BIM/importers/importIFC.py @@ -18,40 +18,42 @@ # * USA * # * * # *************************************************************************** -"""Provide the importer for IFC files used above all in Arch and BIM. -Internally it uses IfcOpenShell, which must be installed before using. -""" +__title__ = "FreeCAD IFC importer - Enhanced IfcOpenShell-only version" +__author__ = ("Yorik van Havre", "Jonathan Wiedemann", "Bernd Hahnebach") +__url__ = "https://www.freecad.org" + ## @package importIFC # \ingroup ARCH # \brief IFC file format importer # # This module provides tools to import IFC files. +"""Provide the importer for IFC files used above all in Arch and BIM. + +Internally it uses IfcOpenShell, which must be installed before using. +""" import os import math import time import FreeCAD -import Part -import Draft import Arch -import DraftVecUtils import ArchIFCSchema -from importers import importIFCHelper -from importers import importIFCmulticore +import Draft +import DraftVecUtils +import Part from draftutils import params from draftutils.messages import _msg, _err +from importers import importIFCHelper +from importers import importIFCmulticore + if FreeCAD.GuiUp: import FreeCADGui as Gui -__title__ = "FreeCAD IFC importer - Enhanced IfcOpenShell-only version" -__author__ = ("Yorik van Havre", "Jonathan Wiedemann", "Bernd Hahnebach") -__url__ = "https://www.freecad.org" - DEBUG = False # Set to True to see debug messages. Otherwise, totally silent ZOOMOUT = True # Set to False to not zoom extents after import diff --git a/src/Mod/BIM/importers/importIFCHelper.py b/src/Mod/BIM/importers/importIFCHelper.py index d140cab8e7..3563a42a05 100644 --- a/src/Mod/BIM/importers/importIFCHelper.py +++ b/src/Mod/BIM/importers/importIFCHelper.py @@ -18,8 +18,8 @@ # * USA * # * * # *************************************************************************** + """Helper functions that are used by IFC importer and exporter.""" -import sys import math import FreeCAD diff --git a/src/Mod/BIM/importers/importIFClegacy.py b/src/Mod/BIM/importers/importIFClegacy.py index fbbf9a8f07..0881b4a28c 100644 --- a/src/Mod/BIM/importers/importIFClegacy.py +++ b/src/Mod/BIM/importers/importIFClegacy.py @@ -25,16 +25,27 @@ # # ############################################################################ - -import FreeCAD, Arch, Draft, os, sys, time, Part, DraftVecUtils, uuid, math, re -from builtins import open as pyopen -from draftutils import params -from draftutils.translate import translate - __title__="FreeCAD IFC importer" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" +import math +import os +import re +import time +import uuid + +from builtins import open as pyopen + +import FreeCAD +import Arch +import Draft +import DraftVecUtils +import Part + +from draftutils import params +from draftutils.translate import translate + # config subtractiveTypes = ["IfcOpeningElement"] # elements that must be subtracted from their parents SCHEMA = "http://www.steptools.com/support/stdev_docs/ifcbim/ifc4.exp" # only for internal parser @@ -937,7 +948,8 @@ def export(exportList,filename): have IFC export capabilities. IFC export currently requires an experimental version of IfcOpenShell available from https://github.com/aothms/IfcOpenShell""") return - import Arch,Draft + import Draft + import Arch # creating base IFC project getConfig() @@ -1139,7 +1151,8 @@ def export(exportList,filename): ifc.write() if exporttxt: - import time, os + import os + import time txtstring = "List of objects exported by FreeCAD in file\n" txtstring += filename + "\n" txtstring += "On " + time.ctime() + "\n" @@ -1181,7 +1194,8 @@ def getTuples(data,scale=1,placement=None,normal=None,close=True): elif isinstance(data,Part.Shape): t = [] if len(data.Wires) == 1: - import Part,DraftGeomUtils + import Part + import DraftGeomUtils data = Part.Wire(Part.__sortEdges__(data.Wires[0].Edges)) verts = data.Vertexes try: @@ -1261,7 +1275,6 @@ def getIfcExtrusionData(obj,scale=1,nosubs=False): edges = Part.__sortEdges__(p.Edges) for e in edges: if isinstance(e.Curve,Part.Circle): - import math follow = True if last: if not DraftVecUtils.equals(last,e.Vertexes[0].Point): @@ -1779,7 +1792,7 @@ class IfcDocument: def explorer(filename,schema="IFC2X3_TC1.exp"): "returns a PySide dialog showing the contents of an IFC file" - from PySide import QtCore,QtGui + from PySide import QtGui ifc = IfcDocument(filename,schema) schema = IfcSchema(schema) tree = QtGui.QTreeWidget() diff --git a/src/Mod/BIM/importers/importIFCmulticore.py b/src/Mod/BIM/importers/importIFCmulticore.py index f54ee00e4d..1bc7e328c5 100644 --- a/src/Mod/BIM/importers/importIFCmulticore.py +++ b/src/Mod/BIM/importers/importIFCmulticore.py @@ -18,18 +18,21 @@ # * USA * # * * # *************************************************************************** + """FreeCAD IFC importer - Multicore version""" +import os import sys import time -import os import FreeCAD -import Draft import Arch -from importers import importIFCHelper -from FreeCAD import Base import ArchIFC +import Draft + +from FreeCAD import Base + +from importers import importIFCHelper # global dicts to store ifc object/freecad object relationships diff --git a/src/Mod/BIM/importers/importOBJ.py b/src/Mod/BIM/importers/importOBJ.py index 8533ad578a..24a8616322 100644 --- a/src/Mod/BIM/importers/importOBJ.py +++ b/src/Mod/BIM/importers/importOBJ.py @@ -19,9 +19,18 @@ #* * #*************************************************************************** -import os +## @package importOBJ +# \ingroup ARCH +# \brief OBJ file format exporter +# +# This module provides tools to import & export OBJ files. +# It is an alternative to the standard Mesh OBJ exporter +# and supports exporting faces with more than 3 vertices +# and supports object colors / materials + import codecs import ntpath +import os from builtins import open as pyopen import FreeCAD @@ -31,6 +40,7 @@ import DraftGeomUtils import Mesh import MeshPart import Part + from draftutils import params if FreeCAD.GuiUp: @@ -41,14 +51,6 @@ else: return text # \endcond -## @package importOBJ -# \ingroup ARCH -# \brief OBJ file format exporter -# -# This module provides tools to import & export OBJ files. -# It is an alternative to the standard Mesh OBJ exporter -# and supports exporting faces with more than 3 vertices -# and supports object colors / materials def findVert(aVertex,aList): "finds aVertex in aList, returns index" diff --git a/src/Mod/BIM/importers/importSH3D.py b/src/Mod/BIM/importers/importSH3D.py index 5a1cc189e5..defad26c08 100644 --- a/src/Mod/BIM/importers/importSH3D.py +++ b/src/Mod/BIM/importers/importSH3D.py @@ -23,20 +23,19 @@ __title__ = "FreeCAD SweetHome3D Importer" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" -import os -import xml.sax -import zipfile - -import FreeCAD -from FreeCAD import Base - - ## @package importSH3D # \ingroup ARCH # \brief SH3D (SweetHome3D) file format importer # # This module provides tools to import SH3D files created from Sweet Home 3D. +import os +import zipfile + +import FreeCAD +from FreeCAD import Base + + DEBUG = True diff --git a/src/Mod/BIM/importers/importSH3DHelper.py b/src/Mod/BIM/importers/importSH3DHelper.py index 4198f563db..86a3cf6c2d 100644 --- a/src/Mod/BIM/importers/importSH3DHelper.py +++ b/src/Mod/BIM/importers/importSH3DHelper.py @@ -18,9 +18,10 @@ # * USA * # * * # *************************************************************************** + """Helper functions that are used by SH3D importer.""" + import itertools -import numpy as np import math import os import re @@ -29,6 +30,9 @@ import uuid import xml.etree.ElementTree as ET import zipfile +import numpy as np + +import FreeCAD as App import Arch import BOPTools.SplitFeatures import BOPTools.BOPFeatures @@ -43,8 +47,6 @@ import TechDraw from draftutils.messages import _err, _log, _msg, _wrn from draftutils.params import get_param_arch -import FreeCAD as App - if App.GuiUp: import FreeCADGui as Gui from draftutils.translate import translate @@ -1367,8 +1369,8 @@ class RoomHandler(BaseHandler): Returns: bool: True if at least one pair of edge intersect. - list(tuple): a list of tuple of v1, e1, v2, e2 where v1 is the - intersection on the first edge e1, and v2 is the intersection + list(tuple): a list of tuple of v1, e1, v2, e2 where v1 is the + intersection on the first edge e1, and v2 is the intersection on the second edge e2. """ for i in range(len(edges)): @@ -1380,7 +1382,7 @@ class RoomHandler(BaseHandler): continue for (v1, v2) in vectors: # Check that the intersections are not extremities - # If both v1 and v2 are extremities then the edges + # If both v1 and v2 are extremities then the edges # are connected which is not really a self-intersecting # situation. if v1 not in [v.Point for v in e1.Vertexes] or v2 not in [v.Point for v in e2.Vertexes]: @@ -1949,8 +1951,8 @@ class WallHandler(BaseHandler): if is_wall_straight: # In order to make sure that the edges are not self-intersecting - # create a convex hull and use these points instead. Maybe - # overkill for a 4 point wall, however not sure how to invert + # create a convex hull and use these points instead. Maybe + # overkill for a 4 point wall, however not sure how to invert # edges. points = list(map(lambda v: v.Point, face.Vertexes)) new_points = convex_hull(points) @@ -2247,7 +2249,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): # Note that we only move on the XY plane since we assume that # only the right and left face will be used for supporting the - # doorOrWndow. It might not be correct for roof windows and floor + # doorOrWndow. It might not be correct for roof windows and floor # windows... # The absolute coordinate of the corner of the doorOrWindow dow_abs_corner = dow_abs_center.add(App.Vector(-width/2, -depth/2, 0)) @@ -2264,7 +2266,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): is_opened = False wall_width = depth # Get all the walls hosting that doorOrWndow. - # + # # The main wall is used to determine the projection of the # doorOrWindow bounding_box, and thus the placement of the # resulting Arch element. The main wall is the one containing @@ -2289,7 +2291,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): # Get the left and right face for the main_wall (_, wall_lface, _, wall_rface) = self.get_faces(main_wall) - # The general process is as follow: + # The general process is as follow: # 1- Find the bounding box face whose normal is properly oriented # with respect to the doorOrWindow (+90º) # 2- Find the wall face with the same orientation. @@ -2329,7 +2331,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): self._debug_shape(wall_face, f"{label_prefix}-bb-projected-onto#{main_wall.Label}", MAGENTA) self._debug_shape(projected_face, f"{label_prefix}-bb-projection#{main_wall.Label}", RED) - # Determine the base vertex that I later use for the doorOrWindow + # Determine the base vertex that I later use for the doorOrWindow # placement base_vertex = self._get_base_vertex(main_wall, is_on_right, projected_face) @@ -2378,12 +2380,12 @@ class DoorOrWindowHandler(BaseFurnitureHandler): """Returns the wall(s) and slab(s) intersecting with the doorOrWindow bounding_box. - The main wall is the one that contains the doorOrWndow bounding_box - CenterOfGravity. Note that this will not work for open doorOrWindow - (i.e.whose bounding_box is a lot greater than the containing wall). + The main wall is the one that contains the doorOrWndow bounding_box + CenterOfGravity. Note that this will not work for open doorOrWindow + (i.e.whose bounding_box is a lot greater than the containing wall). The _create_door, has a mitigation process for that case. - The main_wall is used to get the face on which to project the + The main_wall is used to get the face on which to project the doorOrWindows bounding_box, and from there the placement of the element on the wall's face. @@ -2391,7 +2393,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): - find out whether the doorOrWindow span several floors, if so add all the walls (and slab) for that floor to the list of elements to check. - - once the list of elements to check is complete we check if the + - once the list of elements to check is complete we check if the doorOrWindow bounding_box has a volume in common with the wall. Args: @@ -2401,8 +2403,8 @@ class DoorOrWindowHandler(BaseFurnitureHandler): Returns: tuple(Arch::Wall, list(Arch::Wall)): a tuple of the main wall (if - any could be found and a list of any other Arch element that - might be host of that + any could be found and a list of any other Arch element that + might be host of that """ relevant_walls = [*self.importer.get_walls(floor)] # First find out which floor the window might be have an impact on. @@ -2453,7 +2455,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): """ debug_geometry = self.importer.preferences["DEBUG_GEOMETRY"] # Note that the 'angle' refers to the angle of the face, not its normal. - # we therefore add a '+90º' in SH3D coordinate (i.e. -90º in FC + # we therefore add a '+90º' in SH3D coordinate (i.e. -90º in FC # coordinate). # XXX: Can it be speed up by assuming that left and right are always # Face2 and Face4??? @@ -2474,7 +2476,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): """Return the base vertex used to place a doorOrWindow. Returns the vertex of the projected_face that serves as the - base for the Placement when creating the doorOrWindow. It is + base for the Placement when creating the doorOrWindow. It is the lowest vertex and closest to the wall reference point. The wall reference point depends on whether we are on the right or left side of the wall. @@ -2618,7 +2620,7 @@ class FurnitureHandler(BaseFurnitureHandler): mesh_transform.scale(-1, 1, 1) # Mirror along X if debug_geometry: self._debug_mesh(mesh, f"{name}-mirrored", mesh_transform) - # We add an initial 90º in order for a yaw-pitch-roll-rotation free + # We add an initial 90º in order for a yaw-pitch-roll-rotation free # model to appear properly in FC mesh_transform.rotateX(math.pi/2) if debug_geometry: self._debug_mesh(mesh, f"{name}-x90", mesh_transform) @@ -2636,7 +2638,7 @@ class FurnitureHandler(BaseFurnitureHandler): z_scale = height / normilized_bb.ZLength mesh_transform.scale(x_scale, y_scale, z_scale) - if debug_geometry: + if debug_geometry: model_size = App.Vector(model_bb.XLength, model_bb.YLength, model_bb.ZLength) normalized_size = App.Vector(normilized_bb.XLength, normilized_bb.YLength, normilized_bb.ZLength) final_size = App.Vector(width, depth, height) @@ -2645,7 +2647,7 @@ class FurnitureHandler(BaseFurnitureHandler): self._debug_mesh(mesh, f"{name}-scaled", mesh_transform, MAGENTA) # At that point the mesh has the proper scale. We determine the placement. - # In order to do that, we need to apply the different rotation (ypr) and + # In order to do that, we need to apply the different rotation (ypr) and # also the translation from the origin to the final point. if pitch != 0: r_pitch = App.Rotation(X_NORM, Radian=-pitch) @@ -3011,4 +3013,3 @@ def convex_hull(points, tol=1e-6): # point_coords = np.array([[p.x, p.y] for p in points]) # new_points = [points[i] for i in scipy.spatial.ConvexHull(point_coords).vertices] # return new_points[0] - diff --git a/src/Mod/BIM/importers/importSHP.py b/src/Mod/BIM/importers/importSHP.py index 1ead995ccf..09efb2c906 100644 --- a/src/Mod/BIM/importers/importSHP.py +++ b/src/Mod/BIM/importers/importSHP.py @@ -26,6 +26,7 @@ from builtins import open as pyopen import FreeCAD translate = FreeCAD.Qt.translate + def open(filename): """opens a SHP/SHX/DBF file in a new FreeCAD document""" @@ -144,11 +145,6 @@ def checkShapeFileLibrary(): f = pyopen(fp,"wb") f.write(b) f.close() - try: - import shapefile - except Exception: - FreeCAD.Console.PrintError(translate("Arch","Could not download shapefile module. Aborting.")+"\n") - return False else: FreeCAD.Console.PrintError(translate("Arch","Shapefile module not downloaded. Aborting.")+"\n") return False diff --git a/src/Mod/BIM/importers/importWebGL.py b/src/Mod/BIM/importers/importWebGL.py index d84b241fce..2bb11ddf65 100644 --- a/src/Mod/BIM/importers/importWebGL.py +++ b/src/Mod/BIM/importers/importWebGL.py @@ -35,18 +35,27 @@ # Development reload oneliner: # def re(): from importlib import reload;import importWebGL;reload(importWebGL);o=FreeCAD.getDocument("YourDocName");importWebGL.export([o.getObject("YourBodyName")],u"C:/path/to/your/file.htm"); +## @package importWebGL +# \ingroup ARCH +# \brief FreeCAD WebGL Exporter +# +# This module provides tools to export HTML files containing the +# exported objects in WebGL format and a simple three.js-based viewer. + """FreeCAD WebGL Exporter""" -from typing import NotRequired, TypedDict - -import FreeCAD -import Mesh -import Draft -import Part -import OfflineRenderingUtils import json import textwrap from builtins import open as pyopen +from typing import NotRequired, TypedDict + +import numpy as np + +import FreeCAD +import Draft +import Mesh +import OfflineRenderingUtils +import Part if FreeCAD.GuiUp: import FreeCADGui @@ -58,15 +67,6 @@ else: return txt -import numpy as np - -## @package importWebGL -# \ingroup ARCH -# \brief FreeCAD WebGL Exporter -# -# This module provides tools to export HTML files containing the -# exported objects in WebGL format and a simple three.js-based viewer. - disableCompression = False # Compress object data before sending to JS base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!#$%&()*+-:;/=>?@[]^_,.{|}~`" # safe str chars for js in all cases baseFloat = ",.-0123456789" From 0798d1ca9e7407f67a535fcf9a4ca2ed10d559de Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Sun, 23 Mar 2025 23:30:55 +0100 Subject: [PATCH 013/316] BIM: cleanup imports in nativeifc --- src/Mod/BIM/nativeifc/ifc_commands.py | 4 ++-- src/Mod/BIM/nativeifc/ifc_diff.py | 7 +++++-- src/Mod/BIM/nativeifc/ifc_export.py | 3 ++- src/Mod/BIM/nativeifc/ifc_generator.py | 17 ++++++++--------- src/Mod/BIM/nativeifc/ifc_geometry.py | 4 ++-- src/Mod/BIM/nativeifc/ifc_layers.py | 2 +- src/Mod/BIM/nativeifc/ifc_materials.py | 5 +++-- src/Mod/BIM/nativeifc/ifc_objects.py | 3 +++ src/Mod/BIM/nativeifc/ifc_observer.py | 2 +- src/Mod/BIM/nativeifc/ifc_openshell.py | 5 +++-- src/Mod/BIM/nativeifc/ifc_performance_test.py | 4 +++- src/Mod/BIM/nativeifc/ifc_psets.py | 1 - src/Mod/BIM/nativeifc/ifc_selftest.py | 17 ++++++++++------- src/Mod/BIM/nativeifc/ifc_status.py | 13 ++++++------- src/Mod/BIM/nativeifc/ifc_tools.py | 12 +++++++----- src/Mod/BIM/nativeifc/ifc_tree.py | 5 ++--- src/Mod/BIM/nativeifc/ifc_types.py | 2 +- src/Mod/BIM/nativeifc/ifc_viewproviders.py | 14 +++++++------- 18 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/Mod/BIM/nativeifc/ifc_commands.py b/src/Mod/BIM/nativeifc/ifc_commands.py index 25591cdc01..c27a0aca35 100644 --- a/src/Mod/BIM/nativeifc/ifc_commands.py +++ b/src/Mod/BIM/nativeifc/ifc_commands.py @@ -22,9 +22,9 @@ """This module contains IFC-related FreeCAD commands""" - import FreeCAD import FreeCADGui + from . import ifc_openshell translate = FreeCAD.Qt.translate @@ -155,7 +155,7 @@ class IFC_MakeProject: def Activated(self): from importers import exportIFC # lazy loading from . import ifc_tools - from PySide import QtCore, QtGui + from PySide import QtGui doc = FreeCAD.ActiveDocument objs = FreeCADGui.Selection.getSelection() diff --git a/src/Mod/BIM/nativeifc/ifc_diff.py b/src/Mod/BIM/nativeifc/ifc_diff.py index 43cf4822be..4200903ead 100644 --- a/src/Mod/BIM/nativeifc/ifc_diff.py +++ b/src/Mod/BIM/nativeifc/ifc_diff.py @@ -23,12 +23,15 @@ """Diffing tool for NativeIFC project objects""" import difflib + +import ifcopenshell + import FreeCAD import FreeCADGui -import ifcopenshell -from . import ifc_tools import Arch_rc +from . import ifc_tools + translate = FreeCAD.Qt.translate diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index 91001de2df..4f26ccd32d 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -22,9 +22,10 @@ import tempfile +import ifcopenshell + import FreeCAD import Draft -import ifcopenshell from importers import exportIFC from importers import exportIFCHelper diff --git a/src/Mod/BIM/nativeifc/ifc_generator.py b/src/Mod/BIM/nativeifc/ifc_generator.py index 4c01bf2501..5242f575ef 100644 --- a/src/Mod/BIM/nativeifc/ifc_generator.py +++ b/src/Mod/BIM/nativeifc/ifc_generator.py @@ -24,25 +24,24 @@ The only entry point in this module is the generate_geometry() function which is used by the execute() method of ifc_objects""" - +import multiprocessing import re -import FreeCAD -from FreeCAD import Base -import Part import ifcopenshell import ifcopenshell.util.element - -import multiprocessing - -import FreeCADGui - from pivy import coin from PySide import QtCore +import FreeCAD +import FreeCADGui +import Part + +from FreeCAD import Base + from . import ifc_tools from . import ifc_export + def generate_geometry(obj, cached=False): """Sets the geometry of the given object from a corresponding IFC element. This is the main function called by the execute method of FreeCAD document objects diff --git a/src/Mod/BIM/nativeifc/ifc_geometry.py b/src/Mod/BIM/nativeifc/ifc_geometry.py index 1cdda68be9..e3d6701c68 100644 --- a/src/Mod/BIM/nativeifc/ifc_geometry.py +++ b/src/Mod/BIM/nativeifc/ifc_geometry.py @@ -22,11 +22,11 @@ """This module contains geometry editing and geometry properties-related tools""" -import FreeCAD - import ifcopenshell import ifcopenshell.util.unit +import FreeCAD + from . import ifc_tools diff --git a/src/Mod/BIM/nativeifc/ifc_layers.py b/src/Mod/BIM/nativeifc/ifc_layers.py index f4fa9ab0dc..d5b5b61b1e 100644 --- a/src/Mod/BIM/nativeifc/ifc_layers.py +++ b/src/Mod/BIM/nativeifc/ifc_layers.py @@ -22,12 +22,12 @@ """This NativeIFC module deals with layers""" - import ifcopenshell import ifcopenshell.util.element from . import ifc_tools + def load_layers(obj): """Loads all the layers of an IFC file""" diff --git a/src/Mod/BIM/nativeifc/ifc_materials.py b/src/Mod/BIM/nativeifc/ifc_materials.py index e925116a26..4e0ad54d26 100644 --- a/src/Mod/BIM/nativeifc/ifc_materials.py +++ b/src/Mod/BIM/nativeifc/ifc_materials.py @@ -22,13 +22,14 @@ """This NativeIFC module deals with materials""" -import FreeCAD - import ifcopenshell import ifcopenshell.util.element +import FreeCAD + from . import ifc_tools + def create_material(element, parent, recursive=False): """Creates a material object in the given project or parent material""" diff --git a/src/Mod/BIM/nativeifc/ifc_objects.py b/src/Mod/BIM/nativeifc/ifc_objects.py index c3350dab3e..079574bec1 100644 --- a/src/Mod/BIM/nativeifc/ifc_objects.py +++ b/src/Mod/BIM/nativeifc/ifc_objects.py @@ -24,12 +24,15 @@ import FreeCAD import FreeCADGui + translate = FreeCAD.Qt.translate + # the property groups below should not be treated as psets NON_PSETS = ["Base", "IFC", "", "Geometry", "Dimension", "Linear/radial dimension", "SectionPlane", "Axis", "PhysicalProperties", "BuildingPart", "IFC Attributes"] + class ifc_object: """Base class for all IFC-based objects""" diff --git a/src/Mod/BIM/nativeifc/ifc_observer.py b/src/Mod/BIM/nativeifc/ifc_observer.py index f650c91101..66097658ec 100644 --- a/src/Mod/BIM/nativeifc/ifc_observer.py +++ b/src/Mod/BIM/nativeifc/ifc_observer.py @@ -22,9 +22,9 @@ """Document observer to act on documents containing NativeIFC objects""" - import FreeCAD + params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC") diff --git a/src/Mod/BIM/nativeifc/ifc_openshell.py b/src/Mod/BIM/nativeifc/ifc_openshell.py index f38b866ee4..747dd3f01c 100644 --- a/src/Mod/BIM/nativeifc/ifc_openshell.py +++ b/src/Mod/BIM/nativeifc/ifc_openshell.py @@ -24,9 +24,10 @@ """Utilities to help people verify and update their version of ifcopenshell""" +from packaging.version import Version + import FreeCAD import FreeCADGui -from packaging.version import Version from addonmanager_utilities import create_pip_call translate = FreeCAD.Qt.translate @@ -139,7 +140,7 @@ class IFC_UpdateIOS: try: import ifcopenshell - version = ifcopenshell.version + version = ifcopenshell.version try: Version(version) except InvalidVersion: diff --git a/src/Mod/BIM/nativeifc/ifc_performance_test.py b/src/Mod/BIM/nativeifc/ifc_performance_test.py index 7fb7740cd1..8687751ba0 100644 --- a/src/Mod/BIM/nativeifc/ifc_performance_test.py +++ b/src/Mod/BIM/nativeifc/ifc_performance_test.py @@ -22,8 +22,10 @@ import os import time -import FreeCAD import unittest + +import FreeCAD + from . import ifc_import diff --git a/src/Mod/BIM/nativeifc/ifc_psets.py b/src/Mod/BIM/nativeifc/ifc_psets.py index bc4d993690..c6ebb74462 100644 --- a/src/Mod/BIM/nativeifc/ifc_psets.py +++ b/src/Mod/BIM/nativeifc/ifc_psets.py @@ -22,7 +22,6 @@ """This NativeIFC module deals with properties and property sets""" - import os import re diff --git a/src/Mod/BIM/nativeifc/ifc_selftest.py b/src/Mod/BIM/nativeifc/ifc_selftest.py index 25300dd909..fa016529ca 100644 --- a/src/Mod/BIM/nativeifc/ifc_selftest.py +++ b/src/Mod/BIM/nativeifc/ifc_selftest.py @@ -22,13 +22,18 @@ """Unit test for the Native IFC module""" +import difflib import os -import time import tempfile -import FreeCAD -import Draft -import Arch import unittest + +import ifcopenshell +from ifcopenshell.util import element + +import FreeCAD +import Arch +import Draft + from . import ifc_import from . import ifc_tools from . import ifc_geometry @@ -37,9 +42,7 @@ from . import ifc_layers from . import ifc_psets from . import ifc_objects from . import ifc_generator -import ifcopenshell -from ifcopenshell.util import element -import difflib + IFC_FILE_PATH = None # downloaded IFC file path FCSTD_FILE_PATH = None # saved FreeCAD file diff --git a/src/Mod/BIM/nativeifc/ifc_status.py b/src/Mod/BIM/nativeifc/ifc_status.py index a75375b509..1cf88936e8 100644 --- a/src/Mod/BIM/nativeifc/ifc_status.py +++ b/src/Mod/BIM/nativeifc/ifc_status.py @@ -23,13 +23,12 @@ """This contains nativeifc status widgets and functionality""" - -import os import csv +import os + import FreeCAD import FreeCADGui - translate = FreeCAD.Qt.translate params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC") text_on = translate("BIM", "Strict IFC mode is ON (all objects are IFC)") @@ -100,7 +99,7 @@ def on_add_property(): sel = FreeCADGui.Selection.getSelection() if not sel: return - from PySide import QtCore, QtGui # lazy loading + from PySide import QtGui # lazy loading from . import ifc_psets obj = sel[0] psets = list(set([obj.getGroupOfProperty(p) for p in obj.PropertiesList])) @@ -179,7 +178,6 @@ def on_add_pset(): sel = FreeCADGui.Selection.getSelection() if not sel: return - from PySide import QtCore, QtGui # lazy loading from . import ifc_psets obj = sel[0] mw = FreeCADGui.getMainWindow() @@ -273,7 +271,7 @@ def on_new(): def set_menu(locked=False): """Sets the File menu items""" - from PySide import QtCore, QtGui # lazy loading + from PySide import QtGui # lazy loading # switch Std_Save and IFC_Save mw = FreeCADGui.getMainWindow() @@ -452,7 +450,6 @@ def lock_document(): def find_toplevel(objs): """Finds the top-level objects from the list""" - import Draft # filter out any object that depend on another from the list nobjs = [] for obj in objs: @@ -474,6 +471,8 @@ def find_toplevel(objs): def filter_out(objs): """Filter out objects that should not be converted to IFC""" + import Draft + nobjs = [] for obj in objs: if obj.isDerivedFrom("Part::Feature"): diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index 3330f6e007..2d12a29a07 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -23,9 +23,15 @@ """This is the main NativeIFC module""" import os + +from PySide import QtCore + import FreeCAD -import Draft import Arch +import ArchBuildingPart +import Draft + +from draftviewproviders import view_layer translate = FreeCAD.Qt.translate @@ -59,10 +65,6 @@ from . import ifc_status from . import ifc_export from . import ifc_psets -from draftviewproviders import view_layer -import ArchBuildingPart -from PySide import QtCore - SCALE = 1000.0 # IfcOpenShell works in meters, FreeCAD works in mm SHORT = False # If True, only Step ID attribute is created ROUND = 8 # rounding value for placements diff --git a/src/Mod/BIM/nativeifc/ifc_tree.py b/src/Mod/BIM/nativeifc/ifc_tree.py index 334e3e1931..8e7f4455e0 100644 --- a/src/Mod/BIM/nativeifc/ifc_tree.py +++ b/src/Mod/BIM/nativeifc/ifc_tree.py @@ -22,7 +22,6 @@ """This NativeIFC module handles the retrieval and display of geometry compositions of objects""" - import FreeCAD TAB = 2 @@ -80,7 +79,7 @@ def show_geometry_tree(element): import Arch_rc import FreeCADGui # lazy import from . import ifc_tools - from PySide import QtGui, QtWidgets + from PySide import QtWidgets if isinstance(element, FreeCAD.DocumentObject): element = ifc_tools.get_ifc_element(element) @@ -147,7 +146,7 @@ def show_properties(current, previous): import FreeCADGui from . import ifc_tools # lazy loading - from PySide import QtCore, QtGui, QtWidgets + from PySide import QtCore, QtWidgets ifcid = int(current.text(0).split("=", 1)[0].strip(" ").strip("#")) sel = FreeCADGui.Selection.getSelection() diff --git a/src/Mod/BIM/nativeifc/ifc_types.py b/src/Mod/BIM/nativeifc/ifc_types.py index 295d3cc8dd..5ec97cdf13 100644 --- a/src/Mod/BIM/nativeifc/ifc_types.py +++ b/src/Mod/BIM/nativeifc/ifc_types.py @@ -22,8 +22,8 @@ """Diffing tool for NativeIFC project objects""" - import FreeCAD + from . import ifc_tools translate = FreeCAD.Qt.translate diff --git a/src/Mod/BIM/nativeifc/ifc_viewproviders.py b/src/Mod/BIM/nativeifc/ifc_viewproviders.py index 13f0c6bd43..0ef818f3c5 100644 --- a/src/Mod/BIM/nativeifc/ifc_viewproviders.py +++ b/src/Mod/BIM/nativeifc/ifc_viewproviders.py @@ -86,7 +86,7 @@ class ifc_vp_object: from . import ifc_psets from . import ifc_materials from . import ifc_types - from PySide import QtCore, QtGui # lazy import + from PySide import QtGui # lazy import if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': return @@ -419,7 +419,7 @@ class ifc_vp_document(ifc_vp_object): def setupContextMenu(self, vobj, menu): - from PySide import QtCore, QtGui # lazy import + from PySide import QtGui # lazy import if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': return @@ -463,7 +463,7 @@ class ifc_vp_document(ifc_vp_object): def replace_file(self, obj, newfile): """Asks the user if the attached file path needs to be replaced""" - from PySide import QtCore, QtGui # lazy import + from PySide import QtGui # lazy import msg = "Replace the stored IFC file path in object " msg += self.Object.Label + " with the new one: " @@ -484,7 +484,7 @@ class ifc_vp_document(ifc_vp_object): return False def schema_warning(self): - from PySide import QtCore, QtGui # lazy import + from PySide import QtGui # lazy import msg = "Warning: This operation will change the whole IFC file contents " msg += "and will not give versionable results. It is best to not do " @@ -516,7 +516,7 @@ class ifc_vp_group: self.Object = vobj.Object def getIcon(self): - from PySide import QtCore, QtGui # lazy loading + from PySide import QtGui # lazy loading import Draft_rc import Arch_rc @@ -602,7 +602,7 @@ class ifc_vp_material: def setupContextMenu(self, vobj, menu): from . import ifc_tools # lazy import from . import ifc_psets - from PySide import QtCore, QtGui # lazy import + from PySide import QtGui # lazy import if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': return @@ -660,7 +660,7 @@ def get_filepath(project): """Saves the associated IFC file to another file""" from . import ifc_tools # lazy import - from PySide import QtCore, QtGui # lazy import + from PySide import QtGui # lazy import sf = QtGui.QFileDialog.getSaveFileName( None, From 6eb6e4423257fea32221782507e281487e086836 Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Sun, 23 Mar 2025 23:31:38 +0100 Subject: [PATCH 014/316] BIM: cleanup imports in utils --- src/Mod/BIM/utils/buildPsets.py | 2 +- src/Mod/BIM/utils/ifctree.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Mod/BIM/utils/buildPsets.py b/src/Mod/BIM/utils/buildPsets.py index f08ba2277e..8a03674e16 100644 --- a/src/Mod/BIM/utils/buildPsets.py +++ b/src/Mod/BIM/utils/buildPsets.py @@ -25,9 +25,9 @@ a qto_definitions.csv files in the directory ../Presets.""" import os -from zipfile import ZipFile from urllib.request import urlopen import xml.sax +from zipfile import ZipFile URL = "https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/annex-a-psd.zip" diff --git a/src/Mod/BIM/utils/ifctree.py b/src/Mod/BIM/utils/ifctree.py index a1e3e38969..f007753207 100644 --- a/src/Mod/BIM/utils/ifctree.py +++ b/src/Mod/BIM/utils/ifctree.py @@ -32,11 +32,12 @@ my ryzen9 machine, for 2700 objects. Larger files like the King Arch file (20 Mb / 750 000 objects) would import in 18 minutes... """ -import FreeCAD -import ifcopenshell -from PySide2 import QtCore, QtGui, QtWidgets import time +import ifcopenshell + +from PySide import QtWidgets + class ViewProvider: From ba67de4c0510a877b98f49837a713d6ff39417aa Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Sun, 23 Mar 2025 23:32:16 +0100 Subject: [PATCH 015/316] BIM: cleanup imports at module root --- src/Mod/BIM/Arch.py | 3 ++ src/Mod/BIM/ArchAxis.py | 49 +++++++++---------- src/Mod/BIM/ArchAxisSystem.py | 35 +++++++------- src/Mod/BIM/ArchBuilding.py | 40 ++++++++-------- src/Mod/BIM/ArchBuildingPart.py | 38 ++++++++------- src/Mod/BIM/ArchCommands.py | 37 ++++++++------- src/Mod/BIM/ArchComponent.py | 31 ++++++------ src/Mod/BIM/ArchCurtainWall.py | 51 ++++++++++---------- src/Mod/BIM/ArchCutPlane.py | 30 ++++++------ src/Mod/BIM/ArchEquipment.py | 32 ++++++------- src/Mod/BIM/ArchFence.py | 2 +- src/Mod/BIM/ArchFloor.py | 26 ++++++----- src/Mod/BIM/ArchFrame.py | 37 +++++++-------- src/Mod/BIM/ArchGrid.py | 35 +++++++------- src/Mod/BIM/ArchIFC.py | 1 + src/Mod/BIM/ArchIFCSchema.py | 3 +- src/Mod/BIM/ArchIFCView.py | 2 +- src/Mod/BIM/ArchMaterial.py | 38 +++++++-------- src/Mod/BIM/ArchPanel.py | 56 +++++++++++----------- src/Mod/BIM/ArchPipe.py | 40 ++++++++-------- src/Mod/BIM/ArchPrecast.py | 23 +++++---- src/Mod/BIM/ArchProfile.py | 7 ++- src/Mod/BIM/ArchProject.py | 23 ++++----- src/Mod/BIM/ArchRebar.py | 36 +++++++------- src/Mod/BIM/ArchReference.py | 44 +++++++++-------- src/Mod/BIM/ArchRoof.py | 51 ++++++++++---------- src/Mod/BIM/ArchSchedule.py | 43 +++++++++-------- src/Mod/BIM/ArchSectionPlane.py | 70 +++++++++++++++------------- src/Mod/BIM/ArchSite.py | 30 ++++++------ src/Mod/BIM/ArchSpace.py | 59 +++++++++++------------ src/Mod/BIM/ArchStairs.py | 31 ++++++------ src/Mod/BIM/ArchStructure.py | 60 +++++++++++++----------- src/Mod/BIM/ArchTruss.py | 16 +++---- src/Mod/BIM/ArchVRM.py | 19 ++++---- src/Mod/BIM/ArchWall.py | 42 ++++++++++------- src/Mod/BIM/ArchWindow.py | 64 ++++++++++++------------- src/Mod/BIM/BimStatus.py | 1 + src/Mod/BIM/InitGui.py | 12 +++-- src/Mod/BIM/OfflineRenderingUtils.py | 9 ++-- src/Mod/BIM/TestArch.py | 7 ++- 40 files changed, 637 insertions(+), 596 deletions(-) diff --git a/src/Mod/BIM/Arch.py b/src/Mod/BIM/Arch.py index 0ccc7ab635..6dd9422cf6 100644 --- a/src/Mod/BIM/Arch.py +++ b/src/Mod/BIM/Arch.py @@ -34,9 +34,11 @@ __url__ = "https://www.freecad.org" '''The Arch module provides tools specialized in BIM modeling.''' import FreeCAD + if FreeCAD.GuiUp: import FreeCADGui FreeCADGui.updateLocale() + QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate @@ -51,6 +53,7 @@ from ArchWindowPresets import * from ArchStructure import * + # make functions def makeAxis(num=1,size=1000,name=None): diff --git a/src/Mod/BIM/ArchAxis.py b/src/Mod/BIM/ArchAxis.py index 71cbaaa16c..43ad905999 100644 --- a/src/Mod/BIM/ArchAxis.py +++ b/src/Mod/BIM/ArchAxis.py @@ -19,29 +19,6 @@ #* * #*************************************************************************** -import math - -import FreeCAD -import ArchCommands -import Draft -import Part -from FreeCAD import Vector -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui, re - from PySide import QtCore, QtGui - from draftutils.translate import translate - from pivy import coin - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - __title__ = "FreeCAD Axis System" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" @@ -53,6 +30,31 @@ __url__ = "https://www.freecad.org" # This module provides tools to build axis # An axis is a collection of planar axes with a number/tag +import math + +import FreeCAD +import ArchCommands +import Draft +import Part + +from FreeCAD import Vector +from draftutils import params + +if FreeCAD.GuiUp: + import re + from pivy import coin + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + class _Axis: @@ -789,4 +791,3 @@ class _AxisTaskPanel: QtGui.QApplication.translate("Arch", "Distance", None), QtGui.QApplication.translate("Arch", "Angle", None), QtGui.QApplication.translate("Arch", "Label", None)]) - diff --git a/src/Mod/BIM/ArchAxisSystem.py b/src/Mod/BIM/ArchAxisSystem.py index df12fbb93d..dbafd5b984 100644 --- a/src/Mod/BIM/ArchAxisSystem.py +++ b/src/Mod/BIM/ArchAxisSystem.py @@ -19,23 +19,6 @@ #* * #*************************************************************************** -import FreeCAD -import DraftGeomUtils -if FreeCAD.GuiUp: - import FreeCADGui - import Draft - from PySide import QtCore, QtGui - from draftutils.translate import translate - from pivy import coin - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - __title__ = "FreeCAD Axis System" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" @@ -47,6 +30,24 @@ __url__ = "https://www.freecad.org" # This module provides tools to build axis systems # An axis system is a collection of multiple axes +import FreeCAD +import DraftGeomUtils + +if FreeCAD.GuiUp: + from pivy import coin + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + import Draft + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + class _AxisSystem: diff --git a/src/Mod/BIM/ArchBuilding.py b/src/Mod/BIM/ArchBuilding.py index 652f958594..fa34f5e013 100644 --- a/src/Mod/BIM/ArchBuilding.py +++ b/src/Mod/BIM/ArchBuilding.py @@ -20,25 +20,6 @@ #* * #*************************************************************************** -import FreeCAD -import ArchCommands -import ArchFloor -import Draft -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - __title__ = "FreeCAD Building" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" @@ -50,6 +31,27 @@ __url__ = "https://www.freecad.org" # This module provides tools to build building objects. # Buildings are primarily containers for Arch objects +import FreeCAD +import ArchCommands +import ArchFloor +import Draft + +from draftutils import params + +if FreeCAD.GuiUp: + from PySide import QtCore + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + + BuildingTypes = ['Undefined', 'Agricultural - Barn', 'Agricultural - Chicken coop or chickenhouse', diff --git a/src/Mod/BIM/ArchBuildingPart.py b/src/Mod/BIM/ArchBuildingPart.py index 14f340e1fa..47d75930f9 100644 --- a/src/Mod/BIM/ArchBuildingPart.py +++ b/src/Mod/BIM/ArchBuildingPart.py @@ -20,19 +20,32 @@ #* * #*************************************************************************** -import FreeCAD -import Draft -import ArchCommands -import DraftVecUtils -import ArchIFC -import tempfile +__title__ = "FreeCAD Arch BuildingPart" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchBuildingPart +# \ingroup ARCH +# \brief The BuildingPart object and tools +# +# This module provides tools to build BuildingPart objects. +# BuildingParts are used to group different Arch objects + import os +import tempfile + +import FreeCAD +import ArchCommands +import ArchIFC +import Draft +import DraftVecUtils + from draftutils import params if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP import draftutils.units as units else: # \cond @@ -43,17 +56,6 @@ else: # \endcond unicode = str -## @package ArchBuildingPart -# \ingroup ARCH -# \brief The BuildingPart object and tools -# -# This module provides tools to build BuildingPart objects. -# BuildingParts are used to group different Arch objects - -__title__ = "FreeCAD Arch BuildingPart" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - BuildingTypes = ['Undefined', 'Agricultural - Barn', diff --git a/src/Mod/BIM/ArchCommands.py b/src/Mod/BIM/ArchCommands.py index 5878504fd8..8dfbf682f2 100644 --- a/src/Mod/BIM/ArchCommands.py +++ b/src/Mod/BIM/ArchCommands.py @@ -20,23 +20,6 @@ #* * #*************************************************************************** -import FreeCAD -import ArchComponent -import Draft -import DraftVecUtils -from FreeCAD import Vector -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtGui,QtCore - from draftutils.translate import translate -else: - # \cond - def translate(ctxt,txt): - return txt - # \endcond - __title__ = "FreeCAD Arch Commands" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" @@ -48,6 +31,25 @@ __url__ = "https://www.freecad.org" # This module provides general functions used by Arch tools # and utility commands +import FreeCAD +import ArchComponent +import Draft +import DraftVecUtils + +from FreeCAD import Vector +from draftutils import params + +if FreeCAD.GuiUp: + from PySide import QtGui,QtCore + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + # \endcond + + # module functions ############################################### def getStringList(objects): @@ -1379,4 +1381,3 @@ def makeIfcSpreadsheet(archobj=None): FreeCAD.ActiveDocument.removeObject(ifc_spreadsheet) else : return ifc_spreadsheet - diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index 93a8d32d57..2cbc411130 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -19,6 +19,17 @@ #* * #*************************************************************************** +__title__ = "FreeCAD Arch Component" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchComponent +# \ingroup ARCH +# \brief The base class of all Arch objects +# +# This module provides the base Arch component class, that +# is shared by all of the Arch BIM objects + """This module provides the base Arch component class, that is shared by all of the Arch BIM objects. @@ -27,21 +38,18 @@ Examples TODO put examples here. """ -__title__ = "FreeCAD Arch Component" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - import FreeCAD import ArchCommands import ArchIFC import Draft + from draftutils import params if FreeCAD.GuiUp: - import FreeCADGui from PySide import QtGui,QtCore - from draftutils.translate import translate from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate else: # \cond def translate(ctxt,txt): @@ -50,12 +58,6 @@ else: return txt # \endcond -## @package ArchComponent -# \ingroup ARCH -# \brief The base class of all Arch objects -# -# This module provides the base Arch component class, that -# is shared by all of the Arch BIM objects def addToComponent(compobject,addobject,mod=None): """Add an object to a component's properties. @@ -606,7 +608,8 @@ class Component(ArchIFC.IfcProduct): before being rotated. """ - import DraftGeomUtils,math + import math + import DraftGeomUtils # Get the object's center. if not isinstance(shape,list): @@ -1994,9 +1997,9 @@ class ComponentTaskPanel: return if not isinstance(self.obj.IfcProperties,dict): return - import Arch_rc import csv import os + import Arch_rc import ArchIFCSchema # get presets diff --git a/src/Mod/BIM/ArchCurtainWall.py b/src/Mod/BIM/ArchCurtainWall.py index e72a460e35..d5e4be93ae 100644 --- a/src/Mod/BIM/ArchCurtainWall.py +++ b/src/Mod/BIM/ArchCurtainWall.py @@ -24,27 +24,6 @@ __title__ = "FreeCAD Arch Curtain Wall" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" -import math -import FreeCAD -import ArchComponent -import ArchCommands -import DraftVecUtils -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - -ANGLETOLERANCE = 0.67 # vectors with angles below this are considered going in same dir - ## @package ArchCurtainWall # \ingroup ARCH # \brief The Curtain Wall object and tools @@ -69,6 +48,29 @@ the facet is triangulated and receives a third mullion (diagonal mullion). """ +import math + +import FreeCAD +import ArchCommands +import ArchComponent +import DraftVecUtils + +from draftutils import params + +if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + +ANGLETOLERANCE = 0.67 # vectors with angles below this are considered going in same dir + class CurtainWall(ArchComponent.Component): @@ -198,7 +200,8 @@ class CurtainWall(ArchComponent.Component): if not self.ensureBase(obj): return - import Part,DraftGeomUtils + import Part + import DraftGeomUtils pl = obj.Placement @@ -470,7 +473,8 @@ class CurtainWall(ArchComponent.Component): """returns a profile shape already properly oriented, ready for extrude""" - import Part,DraftGeomUtils + import Part + import DraftGeomUtils prof = getattr(obj,direction+"MullionProfile") proh = getattr(obj,direction+"MullionHeight").Value @@ -562,4 +566,3 @@ class ViewProviderCurtainWall(ArchComponent.ViewProviderComponent): colors.append(panelcolor) if self.areDifferentColors(colors,obj.ViewObject.DiffuseColor) or force: obj.ViewObject.DiffuseColor = colors - diff --git a/src/Mod/BIM/ArchCutPlane.py b/src/Mod/BIM/ArchCutPlane.py index 9e5e67ecfa..8257f57f0b 100644 --- a/src/Mod/BIM/ArchCutPlane.py +++ b/src/Mod/BIM/ArchCutPlane.py @@ -21,20 +21,6 @@ #* * #***************************************************************************** -import FreeCAD -import Part -import Draft -import ArchCommands -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate -else: - # \cond - def translate(ctxt, txt): - return txt - # \endcond - __title__="FreeCAD CutPlane" __author__ = "Jonathan Wiedemann" __url__ = "https://www.freecad.org" @@ -45,6 +31,22 @@ __url__ = "https://www.freecad.org" # # This module handles the Cut Plane object +import FreeCAD +import ArchCommands +import Draft +import Part + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt, txt): + return txt + # \endcond + + # _getShapes(FreeCADGui.Selection.getSelectionEx("", 0)) def _getShapes(sels): """Check and process the user selection. diff --git a/src/Mod/BIM/ArchEquipment.py b/src/Mod/BIM/ArchEquipment.py index 401df591bc..866382b4ab 100644 --- a/src/Mod/BIM/ArchEquipment.py +++ b/src/Mod/BIM/ArchEquipment.py @@ -24,22 +24,6 @@ __title__ = "FreeCAD Equipment" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" -import FreeCAD -import ArchComponent -import DraftVecUtils -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - ## @package ArchEquipment # \ingroup ARCH # \brief The Equipment object and tools @@ -48,7 +32,22 @@ else: # Equipment is used to represent furniture and all kinds of electrical # or hydraulic appliances in a building +import FreeCAD +import ArchComponent +import DraftVecUtils +if FreeCAD.GuiUp: + from PySide import QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond def createMeshView(obj,direction=FreeCAD.Vector(0,0,-1),outeronly=False,largestonly=False): @@ -305,4 +304,3 @@ class _ViewProviderEquipment(ArchComponent.ViewProviderComponent): self.coords.point.setValues([[p.x,p.y,p.z] for p in obj.SnapPoints]) else: self.coords.point.deleteValues(0) - diff --git a/src/Mod/BIM/ArchFence.py b/src/Mod/BIM/ArchFence.py index 49901eeddb..5ed8653aa0 100644 --- a/src/Mod/BIM/ArchFence.py +++ b/src/Mod/BIM/ArchFence.py @@ -28,9 +28,9 @@ import ArchComponent import draftobjects.patharray as patharray if FreeCAD.GuiUp: - import FreeCADGui from PySide.QtCore import QT_TRANSLATE_NOOP import PySide.QtGui as QtGui + import FreeCADGui else: # \cond def translate(ctxt, txt): diff --git a/src/Mod/BIM/ArchFloor.py b/src/Mod/BIM/ArchFloor.py index cbde18279c..653c416ac5 100644 --- a/src/Mod/BIM/ArchFloor.py +++ b/src/Mod/BIM/ArchFloor.py @@ -20,6 +20,18 @@ #* * #*************************************************************************** +__title__ = "FreeCAD Arch Floor" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchFloor +# \ingroup ARCH +# \brief The Floor object and tools +# +# This module provides tools to build Floor objects. +# Floors are used to group different Arch objects situated +# at a same level + """This module provides tools to build Floor objects. Floors are used to group different Arch objects situated at a same level. @@ -33,12 +45,13 @@ import ArchCommands import ArchIFC import Draft import DraftVecUtils + from draftutils import params if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP else: # \cond def translate(ctxt,txt): @@ -47,17 +60,6 @@ else: return txt # \endcond -## @package ArchFloor -# \ingroup ARCH -# \brief The Floor object and tools -# -# This module provides tools to build Floor objects. -# Floors are used to group different Arch objects situated -# at a same level - -__title__ = "FreeCAD Arch Floor" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" def makeFloor(objectslist=None,baseobj=None,name=None): """Obsolete, superseded by ArchBuildingPart.makeFloor. diff --git a/src/Mod/BIM/ArchFrame.py b/src/Mod/BIM/ArchFrame.py index c7e09460b9..cc26b181db 100644 --- a/src/Mod/BIM/ArchFrame.py +++ b/src/Mod/BIM/ArchFrame.py @@ -19,21 +19,9 @@ #* * #*************************************************************************** -import FreeCAD -import ArchComponent -import Draft -import DraftVecUtils -if FreeCAD.GuiUp: - import FreeCADGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond +__title__ = "FreeCAD Arch Frame" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" ## @package ArchFrame # \ingroup ARCH @@ -43,10 +31,22 @@ else: # Frames are objects made of a profile and an object with # edges along which the profile gets extruded -__title__ = "FreeCAD Arch Frame" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" +import FreeCAD +import ArchComponent +import Draft +import DraftVecUtils +if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond class _Frame(ArchComponent.Component): @@ -228,4 +228,3 @@ class _ViewProviderFrame(ArchComponent.ViewProviderComponent): if self.Object.Profile: p = [self.Object.Profile] return ArchComponent.ViewProviderComponent.claimChildren(self)+p - diff --git a/src/Mod/BIM/ArchGrid.py b/src/Mod/BIM/ArchGrid.py index dd14d12c5f..6873fe651a 100644 --- a/src/Mod/BIM/ArchGrid.py +++ b/src/Mod/BIM/ArchGrid.py @@ -19,23 +19,6 @@ #* * #*************************************************************************** -import math - -import FreeCAD -import Part -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - __title__ = "FreeCAD Axis System" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" @@ -46,6 +29,24 @@ __url__ = "https://www.freecad.org" # # This module provides tools to build grid systems +import math + +import FreeCAD +import Part + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + class ArchGrid: diff --git a/src/Mod/BIM/ArchIFC.py b/src/Mod/BIM/ArchIFC.py index 2f96f4aff0..5b417b2acb 100644 --- a/src/Mod/BIM/ArchIFC.py +++ b/src/Mod/BIM/ArchIFC.py @@ -36,6 +36,7 @@ else: def QT_TRANSLATE_NOOP(ctx,txt): return txt + def uncamel(t): return ''.join(map(lambda x: x if x.islower() else " "+x, t[3:]))[1:] diff --git a/src/Mod/BIM/ArchIFCSchema.py b/src/Mod/BIM/ArchIFCSchema.py index 48aade83ca..affaa1fe73 100644 --- a/src/Mod/BIM/ArchIFCSchema.py +++ b/src/Mod/BIM/ArchIFCSchema.py @@ -26,10 +26,11 @@ Provides the data as IfcContexts, IfcProducts and IfcTypes. """ -import os import json +import os import FreeCAD + from draftutils import params ifcVersions = ["IFC4", "IFC2X3"] diff --git a/src/Mod/BIM/ArchIFCView.py b/src/Mod/BIM/ArchIFCView.py index 47325a2cd5..24ab0ac370 100644 --- a/src/Mod/BIM/ArchIFCView.py +++ b/src/Mod/BIM/ArchIFCView.py @@ -25,8 +25,8 @@ import FreeCAD import ArchIFC if FreeCAD.GuiUp: - import FreeCADGui from PySide import QtCore, QtGui + import FreeCADGui from draftutils.translate import translate else: def translate(ctxt,txt): diff --git a/src/Mod/BIM/ArchMaterial.py b/src/Mod/BIM/ArchMaterial.py index 30b0be4c36..77f3819ae9 100644 --- a/src/Mod/BIM/ArchMaterial.py +++ b/src/Mod/BIM/ArchMaterial.py @@ -19,23 +19,6 @@ #* * #*************************************************************************** -import FreeCAD -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui, os - import Arch_rc # Needed for access to icons # lgtm [py/unused_import] - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - __title__ = "Arch Material Management" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" @@ -47,6 +30,25 @@ __url__ = "https://www.freecad.org" # This module provides tools to add materials to # Arch objects +import FreeCAD + +from draftutils import params + +if FreeCAD.GuiUp: + import os + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + import Arch_rc # Needed for access to icons # lgtm [py/unused_import] + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + class _ArchMaterialContainer: @@ -895,5 +897,3 @@ class _ArchMultiMaterialTaskPanel: def reject(self): FreeCADGui.ActiveDocument.resetEdit() return True - - diff --git a/src/Mod/BIM/ArchPanel.py b/src/Mod/BIM/ArchPanel.py index d2b7f60f42..65be53c4d4 100644 --- a/src/Mod/BIM/ArchPanel.py +++ b/src/Mod/BIM/ArchPanel.py @@ -19,29 +19,9 @@ #* * #*************************************************************************** -import math - -import FreeCAD -import ArchCommands -import ArchComponent -import Draft -import DraftVecUtils -import Part -from FreeCAD import Vector -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond +__title__ = "FreeCAD Panel" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" ## @package ArchPanel # \ingroup ARCH @@ -51,9 +31,30 @@ else: # Panels consist of a closed shape that gets extruded to # produce a flat object. -__title__ = "FreeCAD Panel" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" +import math + +import FreeCAD +import ArchCommands +import ArchComponent +import Draft +import DraftVecUtils +import Part + +from FreeCAD import Vector +from draftutils import params + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond class _Panel(ArchComponent.Component): @@ -1075,6 +1076,3 @@ class SheetTaskPanel(ArchComponent.ComponentTaskPanel): FreeCADGui.Control.closeDialog() FreeCADGui.runCommand("Draft_Edit") - - - diff --git a/src/Mod/BIM/ArchPipe.py b/src/Mod/BIM/ArchPipe.py index 0d3f67d9a7..f04506516c 100644 --- a/src/Mod/BIM/ArchPipe.py +++ b/src/Mod/BIM/ArchPipe.py @@ -20,22 +20,9 @@ #* * #*************************************************************************** -import FreeCAD -import ArchComponent -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - import Arch_rc - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond +__title__ = "Arch Pipe tools" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" ## @package ArchPipe # \ingroup ARCH @@ -44,10 +31,23 @@ else: # This module provides tools to build Pipe and Pipe connector objects. # Pipes are tubular objects extruded along a base line. -__title__ = "Arch Pipe tools" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" +import FreeCAD +import ArchComponent +from draftutils import params + +if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + import Arch_rc + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond class _ArchPipe(ArchComponent.Component): @@ -451,5 +451,3 @@ class _ArchPipeConnector(ArchComponent.Component): if pipe.OffsetEnd != offset: pipe.OffsetEnd = offset pipe.Proxy.execute(pipe) - - diff --git a/src/Mod/BIM/ArchPrecast.py b/src/Mod/BIM/ArchPrecast.py index 138772679d..687d60c34c 100644 --- a/src/Mod/BIM/ArchPrecast.py +++ b/src/Mod/BIM/ArchPrecast.py @@ -23,16 +23,26 @@ __title__ = "FreeCAD Precast concrete module" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" +## @package ArchPrecast +# \ingroup ARCH +# \brief Precast options for ArchStructure +# +# This module provides additional presets for the Arch Structure +# tool, to build a series of precast concrete elements + """This module contains tools to build basic precast concrete elements: Beams, pillars, slabs and panels""" -import ArchCommands,ArchComponent,FreeCAD +import FreeCAD +import ArchCommands +import ArchComponent + from FreeCAD import Vector from draftutils import params if FreeCAD.GuiUp: - from draftutils.translate import translate from PySide.QtCore import QT_TRANSLATE_NOOP + from draftutils.translate import translate else: # \cond def translate(ctxt,txt): @@ -41,12 +51,6 @@ else: return txt # \endcond -## @package ArchPrecast -# \ingroup ARCH -# \brief Precast options for ArchStructure -# -# This module provides additional presets for the Arch Structure -# tool, to build a series of precast concrete elements class _Precast(ArchComponent.Component): @@ -684,7 +688,8 @@ class _PrecastStairs(_Precast): if length < tread: length = tread # minimum - import math,Part + import math + import Part p = [Vector(0,0,0)] # relative moves if downlength: diff --git a/src/Mod/BIM/ArchProfile.py b/src/Mod/BIM/ArchProfile.py index 7e34aa8bbd..d9395cd7be 100644 --- a/src/Mod/BIM/ArchProfile.py +++ b/src/Mod/BIM/ArchProfile.py @@ -35,14 +35,15 @@ import os import FreeCAD import Draft + from FreeCAD import Vector from draftutils import params if FreeCAD.GuiUp: - import FreeCADGui from PySide import QtCore, QtGui - from draftutils.translate import translate from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate else: # \cond def translate(ctxt,txt): @@ -465,5 +466,3 @@ class ProfileTaskPanel: def retranslateUi(self, TaskPanel): self.form.setWindowTitle(self.type+" "+QtGui.QApplication.translate("Arch", "Profile", None)) - - diff --git a/src/Mod/BIM/ArchProject.py b/src/Mod/BIM/ArchProject.py index feb2279e58..70c281867e 100644 --- a/src/Mod/BIM/ArchProject.py +++ b/src/Mod/BIM/ArchProject.py @@ -20,6 +20,16 @@ #* * #*************************************************************************** +__title__ = "FreeCAD Project" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchProject +# \ingroup ARCH +# \brief The Project object and tools +# +# This module provides tools to build Project objects. + """This module provides tools to build Project objects. Project objects are objects specifically for better IFC compatibility, allowing the user to tweak certain IFC relevant values. @@ -28,26 +38,17 @@ certain IFC relevant values. import FreeCAD import ArchIFC import ArchIFCView + if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP else: def translate(ctxt,txt): return txt def QT_TRANSLATE_NOOP(ctxt,txt): return txt -## @package ArchProject -# \ingroup ARCH -# \brief The Project object and tools -# -# This module provides tools to build Project objects. - -__title__ = "FreeCAD Project" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - class _Project(ArchIFC.IfcContext): """The project object. diff --git a/src/Mod/BIM/ArchRebar.py b/src/Mod/BIM/ArchRebar.py index 83e6f235b0..ca7e7a40ec 100644 --- a/src/Mod/BIM/ArchRebar.py +++ b/src/Mod/BIM/ArchRebar.py @@ -20,17 +20,30 @@ #*************************************************************************** # Modified Amritpal Singh on 07-07-2017 +__title__ = "FreeCAD Rebar" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchRebar +# \ingroup ARCH +# \brief The Rebar object and tools +# +# This module provides tools to build Rebar objects. +# Rebars (or Reinforcing Bars) are metallic bars placed +# inside concrete structures to reinforce them. + import FreeCAD -import Draft -import ArchComponent -import DraftVecUtils import ArchCommands +import ArchComponent +import Draft +import DraftVecUtils + from draftutils import params if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP else: # \cond def translate(ctxt,txt): @@ -43,18 +56,6 @@ else: from bimcommands import BimRebar _CommandRebar = BimRebar.Arch_Rebar -## @package ArchRebar -# \ingroup ARCH -# \brief The Rebar object and tools -# -# This module provides tools to build Rebar objects. -# Rebars (or Reinforcing Bars) are metallic bars placed -# inside concrete structures to reinforce them. - -__title__ = "FreeCAD Rebar" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - class _Rebar(ArchComponent.Component): @@ -447,9 +448,9 @@ class _ViewProviderRebar(ArchComponent.ViewProviderComponent): self.centerlinegroup.removeChild(self.centerline) if hasattr(obj.Proxy,"wires"): if obj.Proxy.wires: + import re from pivy import coin import Part - import re self.centerline = coin.SoSeparator() comp = Part.makeCompound(obj.Proxy.wires) buf = re.findall(r"point \[(.*?)\]",comp.writeInventor().replace("\n","")) @@ -570,4 +571,3 @@ def getLengthOfRebar(rebar): else: FreeCAD.Console.PrintError("Cannot calculate rebar length from its base object\n") return None - diff --git a/src/Mod/BIM/ArchReference.py b/src/Mod/BIM/ArchReference.py index 2a6fa18396..f5ffe91445 100644 --- a/src/Mod/BIM/ArchReference.py +++ b/src/Mod/BIM/ArchReference.py @@ -23,26 +23,6 @@ __title__ = "FreeCAD Arch External Reference" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" - -import FreeCAD -import os -import zipfile -import re -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - ## @package ArchReference # \ingroup ARCH # \brief The Reference object and tools @@ -51,6 +31,27 @@ else: # References can take a shape from a Part-based object in # another file. +import os +import re +import zipfile + +import FreeCAD + +from draftutils import params + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + class ArchReference: @@ -973,6 +974,3 @@ class ArchReferenceTaskPanel: FreeCAD.loadFile(self.obj.File) FreeCADGui.Control.closeDialog() FreeCADGui.ActiveDocument.resetEdit() - - - diff --git a/src/Mod/BIM/ArchRoof.py b/src/Mod/BIM/ArchRoof.py index a5392ec381..8509a557d0 100644 --- a/src/Mod/BIM/ArchRoof.py +++ b/src/Mod/BIM/ArchRoof.py @@ -19,28 +19,9 @@ #* * #*************************************************************************** -import math - -import ArchComponent -import DraftGeomUtils -import DraftVecUtils -import FreeCAD -import Part - -from FreeCAD import Vector - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt, txt): - return txt - def QT_TRANSLATE_NOOP(ctxt, txt): - return txt - # \endcond +__title__ = "FreeCAD Roof" +__author__ = "Yorik van Havre", "Jonathan Wiedemann" +__url__ = "https://www.freecad.org" ## @package ArchRoof # \ingroup ARCH @@ -50,9 +31,28 @@ else: # Roofs are built from a closed contour and a series of # slopes. -__title__ = "FreeCAD Roof" -__author__ = "Yorik van Havre", "Jonathan Wiedemann" -__url__ = "https://www.freecad.org" +import math + +import FreeCAD +import ArchComponent +import DraftGeomUtils +import DraftVecUtils +import Part + +from FreeCAD import Vector + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt, txt): + return txt + def QT_TRANSLATE_NOOP(ctxt, txt): + return txt + # \endcond def adjust_list_len (lst, newLn, val): @@ -955,4 +955,3 @@ class _RoofTaskPanel: QtGui.QApplication.translate("Arch", "Thickness (mm)", None), QtGui.QApplication.translate("Arch", "Overhang (mm)", None), QtGui.QApplication.translate("Arch", "Height (mm)", None)]) - diff --git a/src/Mod/BIM/ArchSchedule.py b/src/Mod/BIM/ArchSchedule.py index 6cf4e8384d..efd6a3534e 100644 --- a/src/Mod/BIM/ArchSchedule.py +++ b/src/Mod/BIM/ArchSchedule.py @@ -20,21 +20,9 @@ #* * #*************************************************************************** -import FreeCAD -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond +__title__ = "Arch Schedule" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" ## @package ArchSchedule # \ingroup ARCH @@ -44,16 +32,28 @@ else: # Schedules are objects that can count and gather information # about objects in the document, and fill a spreadsheet with the result -__title__ = "Arch Schedule" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" +import FreeCAD + +from draftutils import params + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") VERBOSE = True # change this for silent recomputes - class _ArchScheduleDocObserver: "doc observer to monitor all recomputes" @@ -254,7 +254,8 @@ class _ArchSchedule: ifcfile = None elts = None if val: - import Draft,Arch + import Draft + import Arch if objs: objs = objs.split(";") objs = [FreeCAD.ActiveDocument.getObject(o) for o in objs] @@ -1000,5 +1001,3 @@ class ArchScheduleTaskPanel: self.obj.AutoUpdate = self.form.checkAutoUpdate.isChecked() FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() - - diff --git a/src/Mod/BIM/ArchSectionPlane.py b/src/Mod/BIM/ArchSectionPlane.py index 8a6bd08d73..be7c487266 100644 --- a/src/Mod/BIM/ArchSectionPlane.py +++ b/src/Mod/BIM/ArchSectionPlane.py @@ -19,34 +19,6 @@ #* * #*************************************************************************** -import FreeCAD -import math -import Draft -import ArchCommands -import DraftVecUtils -import ArchComponent -import re -import tempfile -import uuid -import time - -from FreeCAD import Vector -from draftutils import params - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from pivy import coin - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - ## @package ArchSectionPlane # \ingroup ARCH # \brief The Section plane object and tools @@ -55,6 +27,35 @@ else: # It also contains functionality to produce SVG rendering of # section planes, to be used in the TechDraw module +import math +import re +import tempfile +import time +import uuid + +import FreeCAD +import ArchCommands +import ArchComponent +import Draft +import DraftVecUtils + +from FreeCAD import Vector +from draftutils import params + +if FreeCAD.GuiUp: + from pivy import coin + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + ISRENDERING = False # flag to prevent concurrent runs of the coin renderer @@ -94,7 +95,8 @@ def getCutShapes(objs,cutplane,onlySolids,clip,joinArch,showHidden,groupSshapesB obtained from performing a series of booleans against the given cut plane """ - import Part,DraftGeomUtils + import Part + import DraftGeomUtils shapes = [] hshapes = [] sshapes = [] @@ -364,7 +366,8 @@ def getSVG(source, if should_update_svg_cache: svgcache = '' # render using the Arch Vector Renderer - import ArchVRM, WorkingPlane + import ArchVRM + import WorkingPlane wp = WorkingPlane.PlaneBase() pl = FreeCAD.Placement(source.Placement) if source.ViewObject and hasattr(source.ViewObject,"CutMargin"): @@ -416,7 +419,8 @@ def getSVG(source, if should_update_svg_cache: svgcache = "" # render using the TechDraw module - import TechDraw, Part + import TechDraw + import Part if vshapes: baseshape = Part.makeCompound(vshapes) style = {'stroke': "SVGLINECOLOR", @@ -560,7 +564,8 @@ def getDXF(obj): allOn = getattr(obj, "AllOn", True) showHidden = getattr(obj, "ShowHidden", False) result = [] - import TechDraw, Part + import TechDraw + import Part if not obj.Source: return result source = obj.Source @@ -1348,4 +1353,3 @@ class SectionPlaneTaskPanel: self.resizeButton.setToolTip(QtGui.QApplication.translate("Arch", "Resizes the plane to fit the objects in the list above", None)) self.recenterButton.setText(QtGui.QApplication.translate("Arch", "Center", None)) self.recenterButton.setToolTip(QtGui.QApplication.translate("Arch", "Centers the plane on the objects in the list above", None)) - diff --git a/src/Mod/BIM/ArchSite.py b/src/Mod/BIM/ArchSite.py index ee67ead19f..5854471da5 100644 --- a/src/Mod/BIM/ArchSite.py +++ b/src/Mod/BIM/ArchSite.py @@ -20,6 +20,18 @@ #* * #*************************************************************************** +__title__= "FreeCAD Site" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchSite +# \ingroup ARCH +# \brief The Site object and tools +# +# This module provides tools to build Site objects. +# Sites are containers for Arch objects, and also define a +# terrain surface + """This module provides tools to build Site objects. Sites are containers for Arch objects, and also define a terrain surface. """ @@ -33,13 +45,14 @@ import ArchCommands import ArchComponent import ArchIFC import Draft + from draftutils import params if FreeCAD.GuiUp: - import FreeCADGui from PySide import QtGui,QtCore - from draftutils.translate import translate from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate else: # \cond def translate(ctxt,txt): @@ -48,18 +61,6 @@ else: return txt # \endcond -## @package ArchSite -# \ingroup ARCH -# \brief The Site object and tools -# -# This module provides tools to build Site objects. -# Sites are containers for Arch objects, and also define a -# terrain surface - -__title__= "FreeCAD Site" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - def toNode(shape): @@ -1180,4 +1181,3 @@ class _ViewProviderSite: def loads(self,state): return None - diff --git a/src/Mod/BIM/ArchSpace.py b/src/Mod/BIM/ArchSpace.py index 7c6f74a608..b6e97f59fa 100644 --- a/src/Mod/BIM/ArchSpace.py +++ b/src/Mod/BIM/ArchSpace.py @@ -24,6 +24,36 @@ __title__= "FreeCAD Arch Space" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" +## @package ArchSpace +# \ingroup ARCH +# \brief The Space object and tools +# +# This module provides tools to build Space objects. +# Spaces define an open volume inside or outside a +# building, ie. a room. + +import re + +import FreeCAD +import ArchComponent +import ArchCommands +import Draft + +from draftutils import params + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond + SpaceTypes = [ "Undefined", "Exterior", @@ -151,35 +181,6 @@ AreaCalculationType = [ ] -import FreeCAD -import ArchComponent -import ArchCommands -import Draft -from draftutils import params -import re - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - -## @package ArchSpace -# \ingroup ARCH -# \brief The Space object and tools -# -# This module provides tools to build Space objects. -# Spaces define an open volume inside or outside a -# building, ie. a room. - - class _Space(ArchComponent.Component): "A space object" diff --git a/src/Mod/BIM/ArchStairs.py b/src/Mod/BIM/ArchStairs.py index ec504b237f..590166d1bc 100644 --- a/src/Mod/BIM/ArchStairs.py +++ b/src/Mod/BIM/ArchStairs.py @@ -23,17 +23,29 @@ __title__= "FreeCAD Arch Stairs" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" +## @package ArchStairs +# \ingroup ARCH +# \brief The Stairs object and tools +# +# This module provides tools to build Stairs objects. -import FreeCAD,ArchComponent,Draft,DraftVecUtils,math,ArchPipe -import Part, DraftGeomUtils +import math + +import FreeCAD +import ArchComponent +import ArchPipe +import Draft +import DraftVecUtils +import DraftGeomUtils +import Part from FreeCAD import Vector from draftutils import params if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP else: # \cond def translate(ctxt,txt): @@ -42,16 +54,9 @@ else: return txt # \endcond -## @package ArchStairs -# \ingroup ARCH -# \brief The Stairs object and tools -# -# This module provides tools to build Stairs objects. - zeroMM = FreeCAD.Units.Quantity('0mm') - class _Stairs(ArchComponent.Component): "A stairs object" @@ -373,7 +378,7 @@ class _Stairs(ArchComponent.Component): if baseProxy and obj.ArchSketchData and \ hasattr(baseProxy, 'getStairsBaseShapeEdgesInfo'): propSetUuid = self.ArchSkPropSetPickedUuid - info = baseProxy.getStairsBaseShapeEdgesInfo(obj.Base, + info = baseProxy.getStairsBaseShapeEdgesInfo(obj.Base, propSetUuid=propSetUuid) if info: flightAxis = info.get('flightAxis') @@ -443,7 +448,7 @@ class _Stairs(ArchComponent.Component): edgeL = [Part.sortEdges(obj.Base.Shape.Edges)[0]] else: # Should not happen? edgeL = [] - #lenAxis = len(flightAxis) + len(landingAxis) + #lenAxis = len(flightAxis) + len(landingAxis) # Build Stairs if there is no obj.Base or even obj.Base is not valid else: @@ -1570,5 +1575,3 @@ class _ViewProviderStairs(ArchComponent.ViewProviderComponent): lst.extend(obj.Subtractions) return lst return [] - - diff --git a/src/Mod/BIM/ArchStructure.py b/src/Mod/BIM/ArchStructure.py index dd67c0407c..f1750a26d0 100644 --- a/src/Mod/BIM/ArchStructure.py +++ b/src/Mod/BIM/ArchStructure.py @@ -20,26 +20,9 @@ #*************************************************************************** #Modified 2016-01-03 JAndersM -import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands -from FreeCAD import Vector -import ArchProfile -from draftutils import params -from draftutils import gui_utils - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP - import ArchPrecast - import draftguitools.gui_trackers as DraftTrackers -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond +__title__= "FreeCAD Structure" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" ## @package ArchStructure # \ingroup ARCH @@ -50,9 +33,31 @@ else: # elements that have a structural function, that is, that # support other parts of the building. -__title__= "FreeCAD Structure" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" +import FreeCAD +import ArchComponent +import ArchCommands +import ArchProfile +import Draft +import DraftVecUtils + +from FreeCAD import Vector +from draftutils import params +from draftutils import gui_utils + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + import ArchPrecast + import draftguitools.gui_trackers as DraftTrackers + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond #Reads preset profiles and categorizes them @@ -786,7 +791,8 @@ class _Structure(ArchComponent.Component): "creates the structure shape" - import Part, DraftGeomUtils + import Part + import DraftGeomUtils if self.clone(obj): return @@ -905,7 +911,8 @@ class _Structure(ArchComponent.Component): IfcType = obj.IfcType else: IfcType = None - import Part,DraftGeomUtils + import Part + import DraftGeomUtils data = ArchComponent.Component.getExtrusionData(self,obj) if data: if not isinstance(data[0],list): @@ -1544,7 +1551,8 @@ class _StructuralSystem(ArchComponent.Component): # OBSOLETE - All Arch objects def execute(self,obj): "creates the structure shape" - import Part, DraftGeomUtils + import Part + import DraftGeomUtils # creating base shape pl = obj.Placement diff --git a/src/Mod/BIM/ArchTruss.py b/src/Mod/BIM/ArchTruss.py index 51b189b723..5db3bf06bf 100644 --- a/src/Mod/BIM/ArchTruss.py +++ b/src/Mod/BIM/ArchTruss.py @@ -24,14 +24,21 @@ __title__ = "FreeCAD Arch Truss" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" +## @package ArchTruss +# \ingroup ARCH +# \brief The Truss object and tools +# +# This module provides tools to build Truss objects. + import math + import FreeCAD import ArchComponent if FreeCAD.GuiUp: + from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP else: # \cond def translate(ctxt,txt): @@ -40,12 +47,6 @@ else: return txt # \endcond -## @package ArchTruss -# \ingroup ARCH -# \brief The Truss object and tools -# -# This module provides tools to build Truss objects. - rodmodes = ("/|/|/|", "/\\/\\/\\", "/|\\|/|\\", @@ -328,4 +329,3 @@ class ViewProviderTruss(ArchComponent.ViewProviderComponent): import Arch_rc return ":/icons/Arch_Truss_Tree.svg" - diff --git a/src/Mod/BIM/ArchVRM.py b/src/Mod/BIM/ArchVRM.py index 4ce391b912..a670c09078 100644 --- a/src/Mod/BIM/ArchVRM.py +++ b/src/Mod/BIM/ArchVRM.py @@ -21,15 +21,6 @@ "The FreeCAD Arch Vector Rendering Module" -import math - -import FreeCAD -import ArchCommands -import DraftVecUtils -import DraftGeomUtils -import Part -from draftutils import params - ## @package ArchVRM # \ingroup ARCH # \brief The Arch Vector Rendering Module @@ -39,6 +30,16 @@ from draftutils import params # It is used by the "Solid" mode of Arch views in TechDraw and Drawing, # and is called from ArchSectionPlane code. +import math + +import FreeCAD +import ArchCommands +import DraftVecUtils +import DraftGeomUtils +import Part + +from draftutils import params + MAXLOOP = 10 # the max number of loop before abort # WARNING: in this module, faces are lists whose first item is the actual OCC face, the diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index c839b3e9ca..76fc74d122 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -19,6 +19,18 @@ #* * #*************************************************************************** +__title__ = "FreeCAD Wall" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" + +## @package ArchWall +# \ingroup ARCH +# \brief The Wall object and tools +# +# This module provides tools to build Wall objects. Walls are simple objects, +# usually vertical, typically obtained by giving a thickness to a base line, +# then extruding it vertically. + """This module provides tools to build Wall objects. Walls are simple objects, usually vertical, typically obtained by giving a thickness to a base line, then extruding it vertically. @@ -29,17 +41,24 @@ TODO put examples here. """ -import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands,math +import math + +import FreeCAD +import ArchCommands +import ArchComponent +import ArchSketchObject +import Draft +import DraftVecUtils + from FreeCAD import Vector from draftutils import params -import ArchSketchObject if FreeCAD.GuiUp: - import FreeCADGui from PySide import QtCore, QtGui - from draftutils.translate import translate from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui import draftguitools.gui_trackers as DraftTrackers + from draftutils.translate import translate else: # \cond def translate(ctxt,txt): @@ -48,19 +67,6 @@ else: return txt # \endcond -## @package ArchWall -# \ingroup ARCH -# \brief The Wall object and tools -# -# This module provides tools to build Wall objects. Walls are simple objects, -# usually vertical, typically obtained by giving a thickness to a base line, -# then extruding it vertically. - -__title__ = "FreeCAD Wall" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" - - def mergeShapes(w1,w2): """Not currently implemented. @@ -905,7 +911,7 @@ class _Wall(ArchComponent.Component): elif hasattr(obj.Base, 'Proxy') and obj.ArchSketchData and \ hasattr(obj.Base.Proxy, 'getWallBaseShapeEdgesInfo'): - wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base, + wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base, propSetUuid=propSetUuid) #get wall edges (not wires); use original edges if getWallBaseShapeEdgesInfo() provided none if wallBaseShapeEdgesInfo: diff --git a/src/Mod/BIM/ArchWindow.py b/src/Mod/BIM/ArchWindow.py index 93eea82a52..051674dd56 100644 --- a/src/Mod/BIM/ArchWindow.py +++ b/src/Mod/BIM/ArchWindow.py @@ -19,32 +19,9 @@ #* * #*************************************************************************** -import os - -import FreeCAD -import ArchCommands -import ArchComponent -import Draft -import DraftVecUtils -import ArchWindowPresets -from FreeCAD import Units -from FreeCAD import Vector -from draftutils import params -from draftutils.messages import _wrn - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - from draftutils.translate import translate - from PySide.QtCore import QT_TRANSLATE_NOOP - import draftguitools.gui_trackers as DraftTrackers -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond +__title__ = "FreeCAD Window" +__author__ = "Yorik van Havre" +__url__ = "https://www.freecad.org" ## @package ArchWindow # \ingroup ARCH @@ -55,9 +32,33 @@ else: # of wires, and that can be inserted into other Arch objects, # by defining a volume that gets subtracted from them. -__title__ = "FreeCAD Window" -__author__ = "Yorik van Havre" -__url__ = "https://www.freecad.org" +import os + +import FreeCAD +import ArchCommands +import ArchComponent +import ArchWindowPresets +import Draft +import DraftVecUtils + +from FreeCAD import Units +from FreeCAD import Vector +from draftutils import params +from draftutils.messages import _wrn + +if FreeCAD.GuiUp: + from PySide import QtCore, QtGui + from PySide.QtCore import QT_TRANSLATE_NOOP + import FreeCADGui + import draftguitools.gui_trackers as DraftTrackers + from draftutils.translate import translate +else: + # \cond + def translate(ctxt,txt): + return txt + def QT_TRANSLATE_NOOP(ctxt,txt): + return txt + # \endcond # presets WindowPartTypes = ["Frame","Solid panel","Glass panel","Louvre"] @@ -66,8 +67,6 @@ WindowOpeningModes = ["None","Arc 90","Arc 90 inv","Arc 45","Arc 45 inv","Arc 18 WindowPresets = ArchWindowPresets.WindowPresets - - def recolorize(attr): # names is [docname,objname] """Recolorizes an object or a [documentname,objectname] list @@ -1417,6 +1416,3 @@ class _ArchWindowTaskPanel: if self.obj: self.obj.ViewObject.Proxy.invertHinge() - - - diff --git a/src/Mod/BIM/BimStatus.py b/src/Mod/BIM/BimStatus.py index 9da009da0d..e4bb4dd66d 100644 --- a/src/Mod/BIM/BimStatus.py +++ b/src/Mod/BIM/BimStatus.py @@ -25,6 +25,7 @@ """This module contains FreeCAD commands for the BIM workbench""" import os + import FreeCAD import FreeCADGui diff --git a/src/Mod/BIM/InitGui.py b/src/Mod/BIM/InitGui.py index 2add05b491..d07c2296c2 100644 --- a/src/Mod/BIM/InitGui.py +++ b/src/Mod/BIM/InitGui.py @@ -23,6 +23,7 @@ """The BIM workbench""" import os + import FreeCAD import FreeCADGui import Arch_rc @@ -315,7 +316,9 @@ class BIMWorkbench(Workbench): # load webtools try: - import BIMServer, Git, Sketchfab + import BIMServer + import Git + import Sketchfab except ImportError: pass else: @@ -330,7 +333,9 @@ class BIMWorkbench(Workbench): # load flamingo try: - import CommandsPolar, CommandsFrame, CommandsPipe + import CommandsPolar + import CommandsFrame + import CommandsPipe except ImportError: flamingo = None else: @@ -369,7 +374,8 @@ class BIMWorkbench(Workbench): # load fasteners try: - import FastenerBase, FastenersCmd + import FastenerBase + import FastenersCmd except ImportError: fasteners = None else: diff --git a/src/Mod/BIM/OfflineRenderingUtils.py b/src/Mod/BIM/OfflineRenderingUtils.py index 1f566bf5be..2a490aa5f9 100755 --- a/src/Mod/BIM/OfflineRenderingUtils.py +++ b/src/Mod/BIM/OfflineRenderingUtils.py @@ -102,14 +102,13 @@ OfflineRenderingUtils.viewer(scene) OfflineRenderingUtils.save(doc,filename=baseFileName+"_exported.FCStd",colors=colors,camera=camera) """ -import sys +import binascii +import inspect import os +import sys +import tempfile import xml.sax import zipfile -import tempfile -import inspect -import binascii - diff --git a/src/Mod/BIM/TestArch.py b/src/Mod/BIM/TestArch.py index 31b6e55e9f..9057faee09 100644 --- a/src/Mod/BIM/TestArch.py +++ b/src/Mod/BIM/TestArch.py @@ -27,8 +27,6 @@ import os import unittest import FreeCAD as App -from FreeCAD import Units - import Arch import Draft import Part @@ -36,6 +34,7 @@ import Sketcher import TechDraw import WorkingPlane +from FreeCAD import Units from draftutils.messages import _msg if App.GuiUp: @@ -841,7 +840,7 @@ class ArchTest(unittest.TestCase): App.ActiveDocument.recompute() # To calculate area # Create the wall - trace = Part.LineSegment(App.Vector (3000.0, 1000.0, 0.0), + trace = Part.LineSegment(App.Vector (3000.0, 1000.0, 0.0), App.Vector (-3000.0, 1000.0, 0.0)) wp = WorkingPlane.get_working_plane() base = App.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace") @@ -862,7 +861,7 @@ class ArchTest(unittest.TestCase): self.assertAlmostEqual( expectedArea.Value, actualArea.Value, - msg = (f"Invalid area value. " + + msg = (f"Invalid area value. " + f"Expected: {expectedArea.UserString}, actual: {actualArea.UserString}")) def test_SpaceFromSingleWall(self): From 2bca01f0cf819b7f97004ea48c64dca94cccb8ab Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Sun, 23 Mar 2025 23:38:14 +0100 Subject: [PATCH 016/316] unit tests for array dressup --- src/Mod/CAM/CAMTests/TestPathDressupArray.py | 150 +++++++++++++++++++ src/Mod/CAM/Path/Dressup/Array.py | 16 +- 2 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 src/Mod/CAM/CAMTests/TestPathDressupArray.py diff --git a/src/Mod/CAM/CAMTests/TestPathDressupArray.py b/src/Mod/CAM/CAMTests/TestPathDressupArray.py new file mode 100644 index 0000000000..aa470391f6 --- /dev/null +++ b/src/Mod/CAM/CAMTests/TestPathDressupArray.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2025 phaseloop * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + + +import FreeCAD +import Path +from Path.Dressup.Array import DressupArray +import Path.Main.Job as PathJob +import Path.Op.Profile as PathProfile + +from CAMTests.PathTestUtils import PathTestBase + + +class TestEngrave: + def __init__(self, path): + self.Path = Path.Path(path) + self.ToolController = None # default tool 5mm + self.CoolantMode = "None" + self.Name = "Engrave" + + def isDerivedFrom(self, type): + if type == "Path::Feature": + return True + return False + +class TestFeature: + def __init__(self): + self.Path = Path.Path() + self.Name = "" + + def addProperty(self, typ, name, category, tip): + setattr(self, name, None) + + def setEditorMode(self, prop, mode): + pass + + +class TestDressupArray(PathTestBase): + """Unit tests for the Array dressup.""" + + def test00(self): + """Verify array with zero copies provides original path.""" + + source_gcode = ( + "G0 X0 Y0 Z0\n" + "G1 X10 Y10 Z0\n" + ) + + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + ) + + base = TestEngrave(source_gcode) + obj = TestFeature() + da = DressupArray(obj, base, None) + da.execute(obj) + self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") + + def test01(self): + """Verify linear x/y/z 1D array with 1 copy.""" + + source_gcode = ( + "G0 X0 Y0 Z0\n" + "G1 X10 Y10 Z0\n" + ) + + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + + "G0 X12.000000 Y12.000000 Z5.000000\n" + "G1 X22.000000 Y22.000000 Z5.000000\n" + ) + + base = TestEngrave(source_gcode) + obj = TestFeature() + da = DressupArray(obj, base, None) + obj.Copies = 1 + obj.Offset = FreeCAD.Vector(12, 12, 5) + + da.execute(obj) + self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") + + def test01(self): + """Verify linear x/y/z 2D array.""" + + source_gcode = ( + "G0 X0 Y0 Z0\n" + "G1 X10 Y10 Z0\n" + ) + + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + + "G0 X0.000000 Y6.000000 Z0.000000\n" + "G1 X10.000000 Y16.000000 Z0.000000\n" + + "G0 X12.000000 Y6.000000 Z0.000000\n" + "G1 X22.000000 Y16.000000 Z0.000000\n" + + "G0 X12.000000 Y0.000000 Z0.000000\n" + "G1 X22.000000 Y10.000000 Z0.000000\n" + + "G0 X24.000000 Y0.000000 Z0.000000\n" + "G1 X34.000000 Y10.000000 Z0.000000\n" + + "G0 X24.000000 Y6.000000 Z0.000000\n" + "G1 X34.000000 Y16.000000 Z0.000000\n" + ) + + base = TestEngrave(source_gcode) + obj = TestFeature() + da = DressupArray(obj, base, None) + obj.Type = "Linear2D" + obj.Copies = 0 + obj.CopiesX = 2 + obj.CopiesY = 1 + + obj.Offset = FreeCAD.Vector(12, 6, 0) + + da.execute(obj) + self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") + + + + + + + diff --git a/src/Mod/CAM/Path/Dressup/Array.py b/src/Mod/CAM/Path/Dressup/Array.py index 4e860989cc..4a421ae8d3 100644 --- a/src/Mod/CAM/Path/Dressup/Array.py +++ b/src/Mod/CAM/Path/Dressup/Array.py @@ -22,13 +22,9 @@ import FreeCAD -import FreeCADGui import Path -import PathScripts import PathScripts.PathUtils as PathUtils from Path.Dressup.Base import DressupBase -from PySide import QtCore -import math import random from PySide.QtCore import QT_TRANSLATE_NOOP @@ -124,7 +120,13 @@ class DressupArray(DressupBase): obj.Base = base obj.Active = True + # assigning array tells the type of possible enum choices obj.Type = ["Linear1D", "Linear2D", "Polar"] + # assign value + obj.Type = "Linear1D" + + obj.Copies = 0 + obj.JitterPercent = 0 self.setEditorModes(obj) obj.Proxy = self @@ -186,7 +188,7 @@ class DressupArray(DressupBase): Path.Log.error(translate("PathArray", "Base is empty or an invalid object.")) return None - # Do not generate paths and clear current Path data if operation not + # Do not generate paths and clear current Path data if operation not active if not obj.Active: if obj.Path: obj.Path = Path.Path() @@ -270,7 +272,9 @@ class PathArray: base = self.base # build copies - output = "" + # initially output contains original base path, copies are added on top of that + output = PathUtils.getPathWithPlacement(base).toGCode() + random.seed(self.seed) if self.arrayType == "Linear1D": From f072bde2d0f37e92770d39280477b11bdc3c81df Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 23 Mar 2025 22:43:52 +0000 Subject: [PATCH 017/316] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/Mod/CAM/CAMTests/TestPathDressupArray.py | 72 +++++++------------- src/Mod/CAM/Path/Dressup/Array.py | 17 ++--- src/Mod/CAM/Path/Dressup/Base.py | 24 +++---- src/Mod/CAM/Path/Dressup/Gui/Array.py | 3 +- src/Mod/CAM/Path/Op/Gui/Array.py | 17 +++-- 5 files changed, 51 insertions(+), 82 deletions(-) diff --git a/src/Mod/CAM/CAMTests/TestPathDressupArray.py b/src/Mod/CAM/CAMTests/TestPathDressupArray.py index aa470391f6..6f8081db00 100644 --- a/src/Mod/CAM/CAMTests/TestPathDressupArray.py +++ b/src/Mod/CAM/CAMTests/TestPathDressupArray.py @@ -42,6 +42,7 @@ class TestEngrave: return True return False + class TestFeature: def __init__(self): self.Path = Path.Path() @@ -60,15 +61,9 @@ class TestDressupArray(PathTestBase): def test00(self): """Verify array with zero copies provides original path.""" - source_gcode = ( - "G0 X0 Y0 Z0\n" - "G1 X10 Y10 Z0\n" - ) - - expected_gcode = ( - "G0 X0.000000 Y0.000000 Z0.000000\n" - "G1 X10.000000 Y10.000000 Z0.000000\n" - ) + source_gcode = "G0 X0 Y0 Z0\n" "G1 X10 Y10 Z0\n" + + expected_gcode = "G0 X0.000000 Y0.000000 Z0.000000\n" "G1 X10.000000 Y10.000000 Z0.000000\n" base = TestEngrave(source_gcode) obj = TestFeature() @@ -79,17 +74,13 @@ class TestDressupArray(PathTestBase): def test01(self): """Verify linear x/y/z 1D array with 1 copy.""" - source_gcode = ( - "G0 X0 Y0 Z0\n" - "G1 X10 Y10 Z0\n" - ) - - expected_gcode = ( - "G0 X0.000000 Y0.000000 Z0.000000\n" - "G1 X10.000000 Y10.000000 Z0.000000\n" + source_gcode = "G0 X0 Y0 Z0\n" "G1 X10 Y10 Z0\n" - "G0 X12.000000 Y12.000000 Z5.000000\n" - "G1 X22.000000 Y22.000000 Z5.000000\n" + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + "G0 X12.000000 Y12.000000 Z5.000000\n" + "G1 X22.000000 Y22.000000 Z5.000000\n" ) base = TestEngrave(source_gcode) @@ -104,29 +95,21 @@ class TestDressupArray(PathTestBase): def test01(self): """Verify linear x/y/z 2D array.""" - source_gcode = ( - "G0 X0 Y0 Z0\n" - "G1 X10 Y10 Z0\n" - ) - + source_gcode = "G0 X0 Y0 Z0\n" "G1 X10 Y10 Z0\n" + expected_gcode = ( - "G0 X0.000000 Y0.000000 Z0.000000\n" - "G1 X10.000000 Y10.000000 Z0.000000\n" - - "G0 X0.000000 Y6.000000 Z0.000000\n" - "G1 X10.000000 Y16.000000 Z0.000000\n" - - "G0 X12.000000 Y6.000000 Z0.000000\n" - "G1 X22.000000 Y16.000000 Z0.000000\n" - - "G0 X12.000000 Y0.000000 Z0.000000\n" - "G1 X22.000000 Y10.000000 Z0.000000\n" - - "G0 X24.000000 Y0.000000 Z0.000000\n" - "G1 X34.000000 Y10.000000 Z0.000000\n" - - "G0 X24.000000 Y6.000000 Z0.000000\n" - "G1 X34.000000 Y16.000000 Z0.000000\n" + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + "G0 X0.000000 Y6.000000 Z0.000000\n" + "G1 X10.000000 Y16.000000 Z0.000000\n" + "G0 X12.000000 Y6.000000 Z0.000000\n" + "G1 X22.000000 Y16.000000 Z0.000000\n" + "G0 X12.000000 Y0.000000 Z0.000000\n" + "G1 X22.000000 Y10.000000 Z0.000000\n" + "G0 X24.000000 Y0.000000 Z0.000000\n" + "G1 X34.000000 Y10.000000 Z0.000000\n" + "G0 X24.000000 Y6.000000 Z0.000000\n" + "G1 X34.000000 Y16.000000 Z0.000000\n" ) base = TestEngrave(source_gcode) @@ -141,10 +124,3 @@ class TestDressupArray(PathTestBase): da.execute(obj) self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") - - - - - - - diff --git a/src/Mod/CAM/Path/Dressup/Array.py b/src/Mod/CAM/Path/Dressup/Array.py index 4a421ae8d3..398ada044e 100644 --- a/src/Mod/CAM/Path/Dressup/Array.py +++ b/src/Mod/CAM/Path/Dressup/Array.py @@ -115,7 +115,7 @@ class DressupArray(DressupBase): "Path", QT_TRANSLATE_NOOP("App::Property", "Seed value for jitter randomness"), ) - + self.obj = obj obj.Base = base @@ -179,12 +179,8 @@ class DressupArray(DressupBase): return True def dressupExecute(self, obj): - - if ( - not obj.Base - or not obj.Base.isDerivedFrom("Path::Feature") - or not obj.Base.Path - ): + + if not obj.Base or not obj.Base.isDerivedFrom("Path::Feature") or not obj.Base.Path: Path.Log.error(translate("PathArray", "Base is empty or an invalid object.")) return None @@ -312,7 +308,6 @@ class PathArray: ) pos = self._calculateJitter(pos) - pl = FreeCAD.Placement() # do not process the index 0,0. It will be processed by the base Paths themselves if not (i == 0 and j == 0): @@ -323,7 +318,7 @@ class PathArray: for cm in PathUtils.getPathWithPlacement(base).Commands ] ) - output+= np.toGCode() + output += np.toGCode() else: for i in range(self.copiesX + 1): for j in range(self.copiesY + 1): @@ -372,9 +367,7 @@ def Create(base, name="DressupArray"): """Create(base, name='DressupPathBoundary') ... creates a dressup array.""" if not base.isDerivedFrom("Path::Feature"): - Path.Log.error( - translate("CAM_DressupArray", "The selected object is not a path") + "\n" - ) + Path.Log.error(translate("CAM_DressupArray", "The selected object is not a path") + "\n") return None obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) diff --git a/src/Mod/CAM/Path/Dressup/Base.py b/src/Mod/CAM/Path/Dressup/Base.py index abf86550ec..a53f14554d 100644 --- a/src/Mod/CAM/Path/Dressup/Base.py +++ b/src/Mod/CAM/Path/Dressup/Base.py @@ -2,12 +2,13 @@ from PySide.QtCore import QT_TRANSLATE_NOOP from Path.Op.Base import ObjectOp + class DressupBase: """ Base class for all dressups to provide common interface with the rest of CAM One major example is making sure all dressups export base operation settings like coolant, tool controller, etc. - """ + """ def setup_coolant_property(self, obj): if not hasattr(obj, "CoolantMode"): @@ -25,14 +26,14 @@ class DressupBase: def setup_tool_controller_property(self, obj): if not hasattr(obj, "ToolController"): obj.addProperty( - "App::PropertyLink", - "ToolController", - "Path", - QT_TRANSLATE_NOOP( - "App::Property", - "The tool controller that will be used to calculate the path", - ), - ) + "App::PropertyLink", + "ToolController", + "Path", + QT_TRANSLATE_NOOP( + "App::Property", + "The tool controller that will be used to calculate the path", + ), + ) def __init__(self, obj, base): @@ -42,7 +43,7 @@ class DressupBase: "Base", QT_TRANSLATE_NOOP("App::Property", "The base path to modify"), ) - + obj.addProperty( "App::PropertyBool", "Active", @@ -88,6 +89,3 @@ class DressupBase: Should be overwritten by subclasses. """ pass - - - diff --git a/src/Mod/CAM/Path/Dressup/Gui/Array.py b/src/Mod/CAM/Path/Dressup/Gui/Array.py index e72a994646..98fb4f3b87 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/Array.py +++ b/src/Mod/CAM/Path/Dressup/Gui/Array.py @@ -1,5 +1,3 @@ - - from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path @@ -98,6 +96,7 @@ def Create(base, name="DressupPathArray"): FreeCAD.ActiveDocument.commitTransaction() return obj + if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand("CAM_DressupArray", CommandPathDressupArray()) diff --git a/src/Mod/CAM/Path/Op/Gui/Array.py b/src/Mod/CAM/Path/Op/Gui/Array.py index 93ec682081..0e670d76d7 100644 --- a/src/Mod/CAM/Path/Op/Gui/Array.py +++ b/src/Mod/CAM/Path/Op/Gui/Array.py @@ -210,13 +210,16 @@ class ObjectArray: QtGui.QMessageBox.warning( None, QT_TRANSLATE_NOOP("CAM_ArrayOp", "Operation is depreciated"), - QT_TRANSLATE_NOOP("CAM_ArrayOp", - ("CAM -> Path Modification -> Array operation is depreciated " - "and will be removed in future FreeCAD versions.\n\n" - "Please use CAM -> Path Dressup -> Array instead.\n\n" - "DO NOT USE CURRENT ARRAY OPERATION WHEN MACHINING WITH COOLANT!\n" - "Due to a bug - collant will not be enabled for array paths." - )), + QT_TRANSLATE_NOOP( + "CAM_ArrayOp", + ( + "CAM -> Path Modification -> Array operation is depreciated " + "and will be removed in future FreeCAD versions.\n\n" + "Please use CAM -> Path Dressup -> Array instead.\n\n" + "DO NOT USE CURRENT ARRAY OPERATION WHEN MACHINING WITH COOLANT!\n" + "Due to a bug - collant will not be enabled for array paths." + ), + ), ) # backwards compatibility for PathArrays created before support for multiple bases if isinstance(obj.Base, list): From 81ccf9cc5ae3d5085c7aa37dd43c41e7d851defd Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Mon, 24 Mar 2025 00:05:29 +0100 Subject: [PATCH 018/316] update cmake list --- src/Mod/CAM/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/CAM/CMakeLists.txt b/src/Mod/CAM/CMakeLists.txt index 88976ed088..51c7797e03 100644 --- a/src/Mod/CAM/CMakeLists.txt +++ b/src/Mod/CAM/CMakeLists.txt @@ -318,6 +318,7 @@ SET(Tests_SRCS CAMTests/TestPathAdaptive.py CAMTests/TestPathCore.py CAMTests/TestPathDepthParams.py + CAMTests/TestPathDressupArray.py CAMTests/TestPathDressupDogbone.py CAMTests/TestPathDressupDogboneII.py CAMTests/TestPathDressupHoldingTags.py From d18ba9010d4b9ce18bd0cc54a0682dc92e0b6e50 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Wed, 26 Mar 2025 11:03:21 +0100 Subject: [PATCH 019/316] BIM: Remove calls to obsolete Draft.getParam See #20198. --- src/Mod/BIM/bimcommands/BimProjectManager.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index 83213f75df..c0bf3d6ff2 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -145,6 +145,7 @@ class BIM_ProjectManager: import Draft import FreeCADGui import Part + from draftutils import params vaxes = [] haxes = [] @@ -307,8 +308,8 @@ class BIM_ProjectManager: outtext = Draft.make_text( [buildingname], FreeCAD.Vector( - Draft.getParam("textheight", 0.20) * 0.3, - -Draft.getParam("textheight", 0.20) * 1.43, + params.get_param("textheight") * 0.3, + -params.get_param("textheight") * 1.43, 0, ), ) @@ -325,8 +326,8 @@ class BIM_ProjectManager: axisV.Label = translate("BIM", "Vertical Axes") axisV.ViewObject.BubblePosition = "Both" axisV.ViewObject.LineWidth = self.form.lineWidth.value() - axisV.ViewObject.FontSize = Draft.getParam("textheight", 0.20) - axisV.ViewObject.BubbleSize = Draft.getParam("textheight", 0.20) * 1.43 + axisV.ViewObject.FontSize = params.get_param("textheight") + axisV.ViewObject.BubbleSize = params.get_param("textheight") * 1.43 axisV.ViewObject.LineColor = color axisH = None if self.form.countHAxes.value() and distHAxes: @@ -337,8 +338,8 @@ class BIM_ProjectManager: axisH.ViewObject.BubblePosition = "Both" axisH.ViewObject.NumberingStyle = "A,B,C" axisH.ViewObject.LineWidth = self.form.lineWidth.value() - axisH.ViewObject.FontSize = Draft.getParam("textheight", 0.20) - axisH.ViewObject.BubbleSize = Draft.getParam("textheight", 0.20) * 1.43 + axisH.ViewObject.FontSize = params.get_param("textheight") + axisH.ViewObject.BubbleSize = params.get_param("textheight") * 1.43 axisH.Placement.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 90) axisH.ViewObject.LineColor = color if axisV and axisH: From 0c9c23dc18086c1b255d8b9b1440501cd5ca6c7b Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Wed, 26 Mar 2025 15:49:30 +0100 Subject: [PATCH 020/316] Draft: remove obsolete param functions See #20198 These functions are no longer used in the Draft WB or in the BIM WB. There is a small risk that 3rd party code relies on them and breaks, but that can be addressed when such is reported as a problem. --- src/Mod/Draft/Draft.py | 4 -- src/Mod/Draft/draftutils/utils.py | 78 ------------------------------- 2 files changed, 82 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 8899b38bf4..1d05ec41fc 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -54,10 +54,6 @@ from draftutils.utils import ARROW_TYPES as arrowtypes from draftutils.utils import (type_check, typecheck, - get_param, - getParam, - set_param, - setParam, precision, tolerance) diff --git a/src/Mod/Draft/draftutils/utils.py b/src/Mod/Draft/draftutils/utils.py index 284f5d7bc1..cb97c82441 100644 --- a/src/Mod/Draft/draftutils/utils.py +++ b/src/Mod/Draft/draftutils/utils.py @@ -183,84 +183,6 @@ def type_check(args_and_types, name="?"): typecheck = type_check -def get_param(param, default=None): - """Return a parameter value from the current parameter database. - - The parameter database is located in the tree - :: - 'User parameter:BaseApp/Preferences/Mod/Draft' - - In the case that `param` is `'linewidth'` or `'color'` it will get - the values from the View parameters - :: - 'User parameter:BaseApp/Preferences/View/DefaultShapeLineWidth' - 'User parameter:BaseApp/Preferences/View/DefaultShapeLineColor' - - Parameters - ---------- - param : str - A string that indicates a parameter in the parameter database. - - default : optional - It indicates the default value of the given parameter. - It defaults to `None`, in which case it will use a specific - value depending on the type of parameter determined - with `get_param_type`. - - Returns - ------- - int, or str, or float, or bool - Depending on `param` and its type. - """ - if param == "linewidth": - return params.get_param("DefaultShapeLineWidth", path="View") - elif param == "color": - return params.get_param("DefaultShapeLineColor", path="View") - else: - return params.get_param(param) - - -getParam = get_param - - -def set_param(param, value): - """Set a Draft parameter with the given value. - - The parameter database is located in the tree - :: - 'User parameter:BaseApp/Preferences/Mod/Draft' - - In the case that `param` is `'linewidth'` or `'color'` it will set - the View parameters - :: - 'User parameter:BaseApp/Preferences/View/DefaultShapeLineWidth' - 'User parameter:BaseApp/Preferences/View/DefaultShapeLineColor' - - Parameters - ---------- - param : str - A string that indicates a parameter in the parameter database. - - value : int, or str, or float, or bool - The appropriate value of the parameter. - Depending on `param` and its type, determined with `get_param_type`, - it sets the appropriate value by calling `ParameterGrp.SetInt`, - `ParameterGrp.SetString`, `ParameterGrp.SetFloat`, - `ParameterGrp.SetBool`, or `ParameterGrp.SetUnsinged`. - """ - if param == "linewidth": - return params.set_param("DefaultShapeLineWidth", value, path="View") - elif param == "color": - return params.set_param("DefaultShapeLineColor", value, path="View") - else: - return params.set_param(param, value) - - - - -setParam = set_param - - def precision(): """Return the precision value from the parameter database. From 1dddbb2aa5af009b2b822506e1c273aa647e134c Mon Sep 17 00:00:00 2001 From: Lawrence Woestman Date: Wed, 26 Mar 2025 14:50:36 -0700 Subject: [PATCH 021/316] CAM: Enabled coolant in the refactored_grbl post, with test --- .../CAM/CAMTests/TestRefactoredGrblPost.py | 19 +++++++++++++++++++ .../Path/Post/scripts/refactored_grbl_post.py | 1 + 2 files changed, 20 insertions(+) diff --git a/src/Mod/CAM/CAMTests/TestRefactoredGrblPost.py b/src/Mod/CAM/CAMTests/TestRefactoredGrblPost.py index a942985053..eed8364a92 100644 --- a/src/Mod/CAM/CAMTests/TestRefactoredGrblPost.py +++ b/src/Mod/CAM/CAMTests/TestRefactoredGrblPost.py @@ -332,3 +332,22 @@ M2 result = gcode.splitlines()[15] expected = "(comment)" self.assertEqual(result, expected) + + def test100(self): + """ + Test if coolant is enabled. + """ + nl = "\n" + + c = Path.Command("M7") + c1 = Path.Command("M8") + c2 = Path.Command("M9") + + self.profile_op.Path = Path.Path([c, c1, c2]) + + self.job.PostProcessorArgs = "--no-header --no-show-editor" + gcode = self.post.export()[0][1] + # print(f"--------{nl}{gcode}--------{nl}") + self.assertEqual(gcode.splitlines()[15], "M7") + self.assertEqual(gcode.splitlines()[16], "M8") + self.assertEqual(gcode.splitlines()[17], "M9") diff --git a/src/Mod/CAM/Path/Post/scripts/refactored_grbl_post.py b/src/Mod/CAM/Path/Post/scripts/refactored_grbl_post.py index 811448ad06..ea47280a8b 100644 --- a/src/Mod/CAM/Path/Post/scripts/refactored_grbl_post.py +++ b/src/Mod/CAM/Path/Post/scripts/refactored_grbl_post.py @@ -75,6 +75,7 @@ class Refactored_Grbl(PostProcessor): # Set any values here that need to override the default values set # in the parent routine. # + values["ENABLE_COOLANT"] = True # # If this is set to True, then commands that are placed in # comments that look like (MC_RUN_COMMAND: blah) will be output. From 354cc849357d4c9ef2465d37f9528471f381ea36 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 27 Mar 2025 13:11:47 +0100 Subject: [PATCH 022/316] Draft: add font name dropdown to preferences (#20400) Fixes #20330. --- .../Resources/ui/preferences-drafttexts.ui | 39 ++++++++++--------- src/Mod/Draft/draftutils/params.py | 26 +++++++++++++ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui index 2191e02e2c..0dfb1dfcfc 100644 --- a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui +++ b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui @@ -75,22 +75,20 @@ in the Annotation scale widget. If the scale is 1:100 the multiplier is 100. - Font name or family + Font name - + + + + 280 + 0 + + - The default font for texts, dimensions and labels. It can be a font name such -as "Arial", a style such as "sans", "serif" or "mono", or a family such as -"Arial,Helvetica,sans", or a name with a style such as "Arial:Bold". - - - - - - Internal font + The default font for texts, dimensions and labels textfont @@ -100,6 +98,13 @@ as "Arial", a style such as "sans", "serif" or &qu + + + + Qt::Horizontal + + + @@ -138,13 +143,6 @@ as "Arial", a style such as "sans", "serif" or &qu - - - - Qt::Horizontal - - - @@ -695,6 +693,11 @@ used for linear dimensions. QComboBox
Gui/PrefWidgets.h
+ + Gui::PrefFontBox + QFontComboBox +
Gui/PrefWidgets.h
+
Gui::PrefSpinBox QSpinBox diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index 70d86a19fb..a08f2bec32 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -367,6 +367,29 @@ def _param_from_PrefFileChooser(widget): return path, entry, "" +def _param_from_PrefFontBox(widget): + if App.GuiUp: + from PySide import QtGui + font = QtGui.QFont() + font.setStyleHint(QtGui.QFont.StyleHint.SansSerif) + value = font.defaultFamily() + else: + value = "" + for elem in list(widget): + if "name" in elem.keys(): + att_name = elem.attrib["name"] + if att_name == "prefEntry": + entry = elem.find("cstring").text + elif att_name == "prefPath": + path = elem.find("cstring").text + # We must set the parameter if it does not exist, else + # the Gui::PrefFontBox will show the wrong value. + param_grp = App.ParamGet("User parameter:BaseApp/Preferences/" + path) + if entry not in param_grp.GetStrings(): + param_grp.SetString(entry, value) + return path, entry, value + + def _get_param_dictionary(): # print("Creating preferences dictionary...") @@ -595,6 +618,9 @@ def _get_param_dictionary(): elif att_class == "Gui::PrefFileChooser": path, entry, value = _param_from_PrefFileChooser(widget) typ = "string" + elif att_class == "Gui::PrefFontBox": + path, entry, value = _param_from_PrefFontBox(widget) + typ = "string" if path is not None: if path in param_dict: From 9744dc55279165c4472427be1dc311123ac1784a Mon Sep 17 00:00:00 2001 From: marioalexis Date: Wed, 19 Mar 2025 00:47:36 -0300 Subject: [PATCH 023/316] Fem: Remove function based on Elmer results --- src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp | 77 ------------------- src/Mod/Fem/Gui/ViewProviderFemPostObject.h | 1 - 2 files changed, 78 deletions(-) diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 7d8d048585..234f68dc9f 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -869,12 +869,6 @@ bool ViewProviderFemPostObject::setupPipeline() if (!dset) { return false; } - std::string FieldName; - auto numFields = dset->GetPointData()->GetNumberOfArrays(); - for (int i = 0; i < numFields; ++i) { - FieldName = std::string(dset->GetPointData()->GetArrayName(i)); - addAbsoluteField(dset, FieldName); - } m_outline->SetInputData(dset); m_points->SetInputData(dset); @@ -1112,74 +1106,3 @@ void ViewProviderFemPostObject::onSelectionChanged(const Gui::SelectionChanges& } } } - -// if there is a real and an imaginary field, an absolute field is added -void ViewProviderFemPostObject::addAbsoluteField(vtkDataSet* dset, std::string FieldName) -{ - // real field names have the suffix " re", given by Elmer - // if the field does not have this suffix, we can return - auto suffix = FieldName.substr(FieldName.size() - 3, FieldName.size() - 1); - if (strcmp(suffix.c_str(), " re") != 0) { - return; - } - - // absolute fields might have already been created, then do nothing - auto strAbsoluteFieldName = FieldName.substr(0, FieldName.size() - 2) + "abs"; - vtkDataArray* testArray = dset->GetPointData()->GetArray(strAbsoluteFieldName.c_str()); - if (testArray) { - return; - } - - // safety check - vtkDataArray* realDdata = dset->GetPointData()->GetArray(FieldName.c_str()); - if (!realDdata) { - return; - } - - // now check if the imaginary counterpart exists - auto strImaginaryFieldName = FieldName.substr(0, FieldName.size() - 2) + "im"; - vtkDataArray* imagDdata = dset->GetPointData()->GetArray(strImaginaryFieldName.c_str()); - if (!imagDdata) { - return; - } - - // create a new array and copy over the real data - // since one cannot directly access the values of a vtkDataSet - // we need to copy them over in a loop - vtkSmartPointer absoluteData = vtkSmartPointer::New(); - absoluteData->SetNumberOfComponents(realDdata->GetNumberOfComponents()); - auto numTuples = realDdata->GetNumberOfTuples(); - absoluteData->SetNumberOfTuples(numTuples); - double tuple[] = {0, 0, 0}; - for (vtkIdType i = 0; i < numTuples; ++i) { - absoluteData->SetTuple(i, tuple); - } - // name the array - auto strAbsFieldName = FieldName.substr(0, FieldName.size() - 2) + "abs"; - absoluteData->SetName(strAbsFieldName.c_str()); - - // add array to data set - dset->GetPointData()->AddArray(absoluteData); - - // step through all mesh points and calculate them - double realValue = 0; - double imaginaryValue = 0; - double absoluteValue = 0; - for (int i = 0; i < dset->GetNumberOfPoints(); ++i) { - if (absoluteData->GetNumberOfComponents() == 1) { - realValue = realDdata->GetComponent(i, 0); - imaginaryValue = imagDdata->GetComponent(i, 0); - absoluteValue = sqrt(pow(realValue, 2) + pow(imaginaryValue, 2)); - absoluteData->SetComponent(i, 0, absoluteValue); - } - // if field is a vector - else { - for (int j = 0; j < absoluteData->GetNumberOfComponents(); ++j) { - realValue = realDdata->GetComponent(i, j); - imaginaryValue = imagDdata->GetComponent(i, j); - absoluteValue = sqrt(pow(realValue, 2) + pow(imaginaryValue, 2)); - absoluteData->SetComponent(i, j, absoluteValue); - } - } - } -} diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.h b/src/Mod/Fem/Gui/ViewProviderFemPostObject.h index 3909502d9e..19aa86be95 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.h @@ -170,7 +170,6 @@ private: void WritePointData(vtkPoints* points, vtkDataArray* normals, vtkDataArray* tcoords); void WriteColorData(bool ResetColorBarRange); void WriteTransparency(); - void addAbsoluteField(vtkDataSet* dset, std::string FieldName); void deleteColorBar(); App::Enumeration m_coloringEnum, m_vectorEnum; From c8ccbeb421b8638f34b0bbbbf36d6a5aa826286b Mon Sep 17 00:00:00 2001 From: marioalexis Date: Wed, 19 Mar 2025 00:59:59 -0300 Subject: [PATCH 024/316] Fem: Add calculator filter --- src/Mod/Fem/App/AppFem.cpp | 1 + src/Mod/Fem/App/FemPostFilter.cpp | 129 +++++++ src/Mod/Fem/App/FemPostFilter.h | 36 ++ src/Mod/Fem/App/PreCompiled.h | 1 + src/Mod/Fem/Gui/AppFemGui.cpp | 1 + src/Mod/Fem/Gui/CMakeLists.txt | 2 + src/Mod/Fem/Gui/Command.cpp | 37 ++ src/Mod/Fem/Gui/PreCompiled.h | 1 + src/Mod/Fem/Gui/Resources/Fem.qrc | 1 + .../icons/FEM_PostFilterCalculator.svg | 324 ++++++++++++++++++ src/Mod/Fem/Gui/TaskPostBoxes.cpp | 130 +++++++ src/Mod/Fem/Gui/TaskPostBoxes.h | 35 +- src/Mod/Fem/Gui/TaskPostCalculator.ui | 127 +++++++ src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp | 35 ++ src/Mod/Fem/Gui/ViewProviderFemPostFilter.h | 18 + src/Mod/Fem/Gui/Workbench.cpp | 2 + 16 files changed, 879 insertions(+), 1 deletion(-) create mode 100644 src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterCalculator.svg create mode 100644 src/Mod/Fem/Gui/TaskPostCalculator.ui diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index b8a8cb6d17..df13a6cf96 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -189,6 +189,7 @@ PyMOD_INIT_FUNC(Fem) Fem::FemPostPipeline ::init(); Fem::FemPostFilter ::init(); Fem::FemPostBranchFilter ::init(); + Fem::FemPostCalculatorFilter ::init(); Fem::FemPostClipFilter ::init(); Fem::FemPostContoursFilter ::init(); Fem::FemPostCutFilter ::init(); diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index dc46efa3e8..ddf41382d1 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -1297,3 +1297,132 @@ short int FemPostWarpVectorFilter::mustExecute() const return App::DocumentObject::mustExecute(); } } + + +// *************************************************************************** +// calculator filter +PROPERTY_SOURCE(Fem::FemPostCalculatorFilter, Fem::FemPostFilter) + +FemPostCalculatorFilter::FemPostCalculatorFilter() + : FemPostFilter() +{ + ADD_PROPERTY_TYPE(FieldName, + ("Calculator"), + "Calculator", + App::Prop_None, + "Name of the calculated field"); + ADD_PROPERTY_TYPE(Function, + (""), + "Calculator", + App::Prop_None, + "Expression of the unction to evaluate"); + ADD_PROPERTY_TYPE(ReplacementValue, + (0.0f), + "Calculator", + App::Prop_None, + "Value used to replace invalid operations"); + ADD_PROPERTY_TYPE(ReplaceInvalid, + (false), + "Calculator", + App::Prop_None, + "Replace invalid values"); + + FilterPipeline calculator; + m_calculator = vtkSmartPointer::New(); + m_calculator->SetResultArrayName(FieldName.getValue()); + calculator.source = m_calculator; + calculator.target = m_calculator; + addFilterPipeline(calculator, "calculator"); + setActiveFilterPipeline("calculator"); +} + +FemPostCalculatorFilter::~FemPostCalculatorFilter() = default; + +DocumentObjectExecReturn* FemPostCalculatorFilter::execute() +{ + updateAvailableFields(); + + return FemPostFilter::execute(); +} + +void FemPostCalculatorFilter::onChanged(const Property* prop) +{ + if (prop == &Function) { + m_calculator->SetFunction(Function.getValue()); + } + else if (prop == &FieldName) { + m_calculator->SetResultArrayName(FieldName.getValue()); + } + else if (prop == &ReplaceInvalid) { + m_calculator->SetReplaceInvalidValues(ReplaceInvalid.getValue()); + } + else if (prop == &ReplacementValue) { + m_calculator->SetReplacementValue(ReplacementValue.getValue()); + } + else if (prop == &Data) { + updateAvailableFields(); + } + Fem::FemPostFilter::onChanged(prop); +} + +short int FemPostCalculatorFilter::mustExecute() const +{ + if (Function.isTouched() || FieldName.isTouched()) { + return 1; + } + else { + return FemPostFilter::mustExecute(); + } +} + +void FemPostCalculatorFilter::updateAvailableFields() +{ + // clear all variables + m_calculator->RemoveAllVariables(); + m_calculator->AddCoordinateScalarVariable("coordsX", 0); + m_calculator->AddCoordinateScalarVariable("coordsY", 1); + m_calculator->AddCoordinateScalarVariable("coordsZ", 2); + m_calculator->AddCoordinateVectorVariable("coords"); + + std::vector scalars; + std::vector vectors; + // std::vector tensors; + + vtkSmartPointer data = getInputData(); + vtkDataSet* dset = vtkDataSet::SafeDownCast(data); + if (!dset) { + return; + } + vtkPointData* pd = dset->GetPointData(); + + // get all vector fields + for (int i = 0; i < pd->GetNumberOfArrays(); ++i) { + std::string name1 = pd->GetArrayName(i); + std::string name2 = name1; + std::replace(name2.begin(), name2.end(), ' ', '_'); + if (pd->GetArray(i)->GetNumberOfComponents() == 3) { + m_calculator->AddVectorVariable(name2.c_str(), name1.c_str()); + // add components as scalar variable + m_calculator->AddScalarVariable((name2 + "_X").c_str(), name1.c_str(), 0); + m_calculator->AddScalarVariable((name2 + "_Y").c_str(), name1.c_str(), 1); + m_calculator->AddScalarVariable((name2 + "_Z").c_str(), name1.c_str(), 2); + } + else if (pd->GetArray(i)->GetNumberOfComponents() == 1) { + m_calculator->AddScalarVariable(name2.c_str(), name1.c_str()); + } + } +} + +const std::vector FemPostCalculatorFilter::getScalarVariables() +{ + std::vector scalars = m_calculator->GetScalarVariableNames(); + scalars.insert(scalars.begin(), {"coordsX", "coordsY", "coordsZ"}); + return scalars; +} + +const std::vector FemPostCalculatorFilter::getVectorVariables() +{ + std::vector vectors = m_calculator->GetVectorVariableNames(); + vectors.insert(vectors.begin(), "coords"); + return vectors; +} diff --git a/src/Mod/Fem/App/FemPostFilter.h b/src/Mod/Fem/App/FemPostFilter.h index f748a4d914..d137b68bcf 100644 --- a/src/Mod/Fem/App/FemPostFilter.h +++ b/src/Mod/Fem/App/FemPostFilter.h @@ -23,6 +23,7 @@ #ifndef Fem_FemPostFilter_H #define Fem_FemPostFilter_H +#include #include #include #include @@ -372,6 +373,41 @@ private: App::Enumeration m_vectorFields; }; +// *************************************************************************** +// calculator filter +class FemExport FemPostCalculatorFilter: public FemPostFilter +{ + + PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostCalculatorFilter); + +public: + FemPostCalculatorFilter(); + ~FemPostCalculatorFilter() override; + + App::PropertyString FieldName; + App::PropertyString Function; + App::PropertyFloat ReplacementValue; + App::PropertyBool ReplaceInvalid; + + const char* getViewProviderName() const override + { + return "FemGui::ViewProviderFemPostCalculator"; + } + short int mustExecute() const override; + + const std::vector getScalarVariables(); + const std::vector getVectorVariables(); + +protected: + App::DocumentObjectExecReturn* execute() override; + void onChanged(const App::Property* prop) override; + + void updateAvailableFields(); + +private: + vtkSmartPointer m_calculator; +}; + } // namespace Fem diff --git a/src/Mod/Fem/App/PreCompiled.h b/src/Mod/Fem/App/PreCompiled.h index b68e1b1bcf..dc915b7df7 100644 --- a/src/Mod/Fem/App/PreCompiled.h +++ b/src/Mod/Fem/App/PreCompiled.h @@ -155,6 +155,7 @@ // VTK #include #include +#include #include #include #include diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index cc0aa8dc7f..65364059eb 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -162,6 +162,7 @@ PyMOD_INIT_FUNC(FemGui) FemGui::ViewProviderFemPostObject ::init(); FemGui::ViewProviderFemPostPipeline ::init(); FemGui::ViewProviderFemPostBranchFilter ::init(); + FemGui::ViewProviderFemPostCalculator ::init(); FemGui::ViewProviderFemPostClip ::init(); FemGui::ViewProviderFemPostContours ::init(); FemGui::ViewProviderFemPostCut ::init(); diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 6fb0572ecd..6e1686e383 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -87,6 +87,7 @@ if(BUILD_FEM_VTK) CylinderWidget.ui PlaneWidget.ui SphereWidget.ui + TaskPostCalculator.ui TaskPostClip.ui TaskPostContours.ui TaskPostCut.ui @@ -281,6 +282,7 @@ if(BUILD_FEM_VTK) SphereWidget.ui TaskPostBoxes.h TaskPostBoxes.cpp + TaskPostCalculator.ui TaskPostClip.ui TaskPostContours.ui TaskPostCut.ui diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index e71185cacd..3736c5bb51 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -2338,6 +2338,42 @@ bool CmdFemPostContoursFilter::isActive() } +//================================================================================================ +DEF_STD_CMD_A(CmdFemPostCalculatorFilter) + +CmdFemPostCalculatorFilter::CmdFemPostCalculatorFilter() + : Command("FEM_PostFilterCalculator") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Calculator filter"); + sToolTipText = QT_TR_NOOP("Create new fields from current data"); + sWhatsThis = "FEM_PostFilterCalculator"; + sStatusTip = sToolTipText; + sPixmap = "FEM_PostFilterCalculator"; +} + +void CmdFemPostCalculatorFilter::activated(int) +{ + setupFilter(this, "Calculator"); +} + +bool CmdFemPostCalculatorFilter::isActive() +{ + // only allow one object + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { + return false; + } + for (auto obj : selection) { + if (obj.pObject->isDerivedFrom()) { + return true; + } + } + return false; +} + + //================================================================================================ DEF_STD_CMD_ACL(CmdFemPostFunctions) @@ -2783,6 +2819,7 @@ void CreateFemCommands() // vtk post processing #ifdef FC_USE_VTK rcCmdMgr.addCommand(new CmdFemPostApllyChanges); + rcCmdMgr.addCommand(new CmdFemPostCalculatorFilter); rcCmdMgr.addCommand(new CmdFemPostClipFilter); rcCmdMgr.addCommand(new CmdFemPostContoursFilter); rcCmdMgr.addCommand(new CmdFemPostCutFilter); diff --git a/src/Mod/Fem/Gui/PreCompiled.h b/src/Mod/Fem/Gui/PreCompiled.h index ef1398cef0..41128a9151 100644 --- a/src/Mod/Fem/Gui/PreCompiled.h +++ b/src/Mod/Fem/Gui/PreCompiled.h @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index dd132e54fc..e2508777a3 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -72,6 +72,7 @@ icons/FEM_MaterialSolid.svg + icons/FEM_PostFilterCalculator.svg icons/FEM_PostFilterClipRegion.svg icons/FEM_PostFilterClipScalar.svg icons/FEM_PostFilterContours.svg diff --git a/src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterCalculator.svg b/src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterCalculator.svg new file mode 100644 index 0000000000..ec2fa44b67 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterCalculator.svg @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + + + + + + + + + calc + calculator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + f(x) + diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.cpp b/src/Mod/Fem/Gui/TaskPostBoxes.cpp index e9e6f3c610..dbd9dacbc4 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.cpp +++ b/src/Mod/Fem/Gui/TaskPostBoxes.cpp @@ -52,6 +52,7 @@ #include #include +#include "ui_TaskPostCalculator.h" #include "ui_TaskPostClip.h" #include "ui_TaskPostContours.h" #include "ui_TaskPostCut.h" @@ -323,6 +324,9 @@ void TaskDlgPost::open() void TaskDlgPost::clicked(int button) { if (button == QDialogButtonBox::Apply) { + for (auto box : m_boxes) { + box->apply(); + } recompute(); } } @@ -2123,4 +2127,130 @@ void TaskPostWarpVector::onMinValueChanged(double) } +// *************************************************************************** +// calculator filter +static const std::vector calculatorOperators = { + "+", "-", "*", "/", "-", "^", "abs", "cos", "sin", "tan", "exp", + "log", "pow", "sqrt", "iHat", "jHat", "kHat", "cross", "dot", "mag", "norm"}; + +TaskPostCalculator::TaskPostCalculator(ViewProviderFemPostCalculator* view, QWidget* parent) + : TaskPostBox(view, + Gui::BitmapFactory().pixmap("FEM_PostFilterCalculator"), + tr("Calculator options"), + parent) + , ui(new Ui_TaskPostCalculator) +{ + // we load the views widget + proxy = new QWidget(this); + ui->setupUi(proxy); + setupConnections(); + this->groupLayout()->addWidget(proxy); + + // load the default values + auto obj = getObject(); + ui->let_field_name->blockSignals(true); + ui->let_field_name->setText(QString::fromUtf8(obj->FieldName.getValue())); + ui->let_field_name->blockSignals(false); + + ui->let_function->blockSignals(true); + ui->let_function->setText(QString::fromUtf8(obj->Function.getValue())); + ui->let_function->blockSignals(false); + + ui->ckb_replace_invalid->setChecked(obj->ReplaceInvalid.getValue()); + ui->dsb_replacement_value->setEnabled(obj->ReplaceInvalid.getValue()); + ui->dsb_replacement_value->setValue(obj->ReplacementValue.getValue()); + ui->dsb_replacement_value->setMaximum(std::numeric_limits::max()); + ui->dsb_replacement_value->setMinimum(std::numeric_limits::lowest()); + + // fill available fields + for (const auto& f : obj->getScalarVariables()) { + ui->cb_scalars->addItem(QString::fromStdString(f)); + } + for (const auto& f : obj->getVectorVariables()) { + ui->cb_vectors->addItem(QString::fromStdString(f)); + } + + QStringList qOperators; + for (const auto& o : calculatorOperators) { + qOperators << QString::fromStdString(o); + } + ui->cb_operators->addItems(qOperators); + + ui->cb_scalars->setCurrentIndex(-1); + ui->cb_vectors->setCurrentIndex(-1); + ui->cb_operators->setCurrentIndex(-1); +} + +TaskPostCalculator::~TaskPostCalculator() = default; + +void TaskPostCalculator::setupConnections() +{ + connect(ui->dsb_replacement_value, + qOverload(&QDoubleSpinBox::valueChanged), + this, + &TaskPostCalculator::onReplacementValueChanged); + connect(ui->ckb_replace_invalid, + &QCheckBox::toggled, + this, + &TaskPostCalculator::onReplaceInvalidChanged); + connect(ui->cb_scalars, + qOverload(&QComboBox::activated), + this, + &TaskPostCalculator::onScalarsActivated); + connect(ui->cb_vectors, + qOverload(&QComboBox::activated), + this, + &TaskPostCalculator::onVectorsActivated); + connect(ui->cb_operators, + qOverload(&QComboBox::activated), + this, + &TaskPostCalculator::onOperatorsActivated); +} + +void TaskPostCalculator::onReplaceInvalidChanged(bool state) +{ + auto obj = static_cast(getObject()); + obj->ReplaceInvalid.setValue(state); + ui->dsb_replacement_value->setEnabled(state); + recompute(); +} + +void TaskPostCalculator::onReplacementValueChanged(double value) +{ + auto obj = static_cast(getObject()); + obj->ReplacementValue.setValue(value); + recompute(); +} + +void TaskPostCalculator::onScalarsActivated(int index) +{ + QString item = ui->cb_scalars->itemText(index); + ui->let_function->insert(item); +} + +void TaskPostCalculator::onVectorsActivated(int index) +{ + QString item = ui->cb_vectors->itemText(index); + ui->let_function->insert(item); +} + +void TaskPostCalculator::onOperatorsActivated(int index) +{ + QString item = ui->cb_operators->itemText(index); + ui->let_function->insert(item); +} + +void TaskPostCalculator::apply() +{ + auto obj = getObject(); + std::string function = ui->let_function->text().toStdString(); + std::string name = ui->let_field_name->text().toStdString(); + obj->Function.setValue(function); + obj->FieldName.setValue(name); + recompute(); + + auto view = getTypedView(); + view->Field.setValue(obj->FieldName.getValue()); +} + #include "moc_TaskPostBoxes.cpp" diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.h b/src/Mod/Fem/Gui/TaskPostBoxes.h index b33729e03b..74842dcc5e 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.h +++ b/src/Mod/Fem/Gui/TaskPostBoxes.h @@ -32,6 +32,7 @@ class QComboBox; class Ui_TaskPostDisplay; +class Ui_TaskPostCalculator; class Ui_TaskPostClip; class Ui_TaskPostContours; class Ui_TaskPostDataAlongLine; @@ -141,12 +142,15 @@ public: QWidget* parent = nullptr); ~TaskPostBox() override; - virtual void applyPythonCode() = 0; + virtual void applyPythonCode() {}; virtual bool isGuiTaskOnly() { return false; } // return true if only gui properties are manipulated + // executed when the apply button is pressed in the task dialog + virtual void apply() {}; + protected: App::DocumentObject* getObject() const { @@ -555,6 +559,35 @@ private: std::unique_ptr ui; }; + +// *************************************************************************** +// calculator filter +class ViewProviderFemPostCalculator; + +class TaskPostCalculator: public TaskPostBox +{ + Q_OBJECT + +public: + explicit TaskPostCalculator(ViewProviderFemPostCalculator* view, QWidget* parent = nullptr); + ~TaskPostCalculator() override; + +protected: + void apply() override; + +private: + void setupConnections(); + void onReplaceInvalidChanged(bool state); + void onReplacementValueChanged(double value); + void onScalarsActivated(int index); + void onVectorsActivated(int index); + void onOperatorsActivated(int index); + +private: + QWidget* proxy; + std::unique_ptr ui; +}; + } // namespace FemGui #endif // GUI_TASKVIEW_TaskPostDisplay_H diff --git a/src/Mod/Fem/Gui/TaskPostCalculator.ui b/src/Mod/Fem/Gui/TaskPostCalculator.ui new file mode 100644 index 0000000000..3d90b1eea0 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostCalculator.ui @@ -0,0 +1,127 @@ + + + TaskPostCalculator + + + + 0 + 0 + 250 + 115 + + + + Form + + + + + + + + + + + + + + Field Name: + + + + + + + + + + + + + Mathematical expression + + + + + + + + + + + + + Available fields + + + + + + + + Scalars: + + + + + + + + + + Vectors: + + + + + + + + + + Operators: + + + + + + + + + + + + + + + + + + + + Replace invalid data: + + + Replacement value for invalid operations + + + + + + + + + + + + + + + + + Gui::DoubleSpinBox + QWidget +
Gui/SpinBox.h
+
+
+
diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp index 22ce73853d..fe0ad21fcf 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp @@ -215,3 +215,38 @@ void ViewProviderFemPostWarpVector::setupTaskDialog(TaskDlgPost* dlg) // add the display options FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg); } + + +// *************************************************************************** +// calculator filter +PROPERTY_SOURCE(FemGui::ViewProviderFemPostCalculator, FemGui::ViewProviderFemPostObject) + +ViewProviderFemPostCalculator::ViewProviderFemPostCalculator() +{ + sPixmap = "FEM_PostFilterCalculator"; +} + +ViewProviderFemPostCalculator::~ViewProviderFemPostCalculator() = default; + +void ViewProviderFemPostCalculator::updateData(const App::Property* prop) +{ + auto obj = getObject(); + if (prop == &obj->Data) { + // update color bar + ViewProviderFemPostObject::updateData(prop); + updateMaterial(); + } + else { + return ViewProviderFemPostObject::updateData(prop); + } +} + +void ViewProviderFemPostCalculator::setupTaskDialog(TaskDlgPost* dlg) +{ + // add the function box + assert(dlg->getView() == this); + dlg->appendBox(new TaskPostCalculator(this)); + + // add the display options + FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg); +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h index 52194b87f1..e728e5fcd0 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h @@ -154,6 +154,24 @@ protected: void setupTaskDialog(TaskDlgPost* dlg) override; }; + +// *************************************************************************** +// calculator filter +class FemGuiExport ViewProviderFemPostCalculator: public ViewProviderFemPostObject +{ + PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemPostCalculator); + +public: + /// constructor. + ViewProviderFemPostCalculator(); + ~ViewProviderFemPostCalculator() override; + + void updateData(const App::Property* prop) override; + +protected: + void setupTaskDialog(TaskDlgPost* dlg) override; +}; + } // namespace FemGui diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 345632754e..04a08828df 100644 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -209,6 +209,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const << "FEM_PostFilterDataAlongLine" << "FEM_PostFilterLinearizedStresses" << "FEM_PostFilterDataAtPoint" + << "FEM_PostFilterCalculator" << "Separator" << "FEM_PostCreateFunctions"; #endif @@ -356,6 +357,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "FEM_PostFilterDataAlongLine" << "FEM_PostFilterLinearizedStresses" << "FEM_PostFilterDataAtPoint" + << "FEM_PostFilterCalculator" << "Separator" << "FEM_PostCreateFunctions"; #endif From 406a834a6d5247668e824fc198918c60f3f0b02d Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 27 Mar 2025 09:31:07 -0300 Subject: [PATCH 025/316] Base: Add volume charge density unit --- src/App/Application.cpp | 1 + src/App/PropertyUnits.cpp | 11 +++++++++++ src/App/PropertyUnits.h | 13 +++++++++++++ src/Base/Unit.cpp | 4 +++- src/Base/Unit.h | 1 + src/Base/UnitsSchemaInternal.cpp | 8 ++++++-- src/Base/UnitsSchemaMKS.cpp | 4 ++++ 7 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 6c7c5222d5..54099df40c 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -2045,6 +2045,7 @@ void Application::initTypes() App::PropertyElectricalResistance ::init(); App::PropertyElectricCharge ::init(); App::PropertySurfaceChargeDensity ::init(); + App::PropertyVolumeChargeDensity ::init(); App::PropertyElectricCurrent ::init(); App::PropertyElectricPotential ::init(); App::PropertyElectromagneticPotential ::init(); diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index b4ed219cd9..f2c30c6dce 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -403,6 +403,17 @@ PropertySurfaceChargeDensity::PropertySurfaceChargeDensity() setUnit(Base::Unit::SurfaceChargeDensity); } +//************************************************************************** +// PropertyVolumeChargeDensity +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPESYSTEM_SOURCE(App::PropertyVolumeChargeDensity, App::PropertyQuantity) + +PropertyVolumeChargeDensity::PropertyVolumeChargeDensity() +{ + setUnit(Base::Unit::VolumeChargeDensity); +} + //************************************************************************** // PropertyElectricCurrent //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index e81a8fd9c3..2e2cca365c 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -374,6 +374,19 @@ public: ~PropertySurfaceChargeDensity() override = default; }; +/** VolumeChargeDensity property + * This is a property for representing volume charge density. It is basically a float + * property. On the Gui it has a quantity like C/m^3. + */ +class AppExport PropertyVolumeChargeDensity: public PropertyQuantity +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + +public: + PropertyVolumeChargeDensity(); + ~PropertyVolumeChargeDensity() override = default; +}; + /** ElectricCurrent property * This is a property for representing electric currents. It is basically a * float property. On the Gui it has a quantity like A. diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index 17a30adb44..baa782972d 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -587,7 +587,7 @@ std::string Unit::getString() const std::string Unit::getTypeString() const { - static std::array, 56> unitSpecs {{ + static std::array, 57> unitSpecs {{ { Unit::Acceleration, "Acceleration" }, { Unit::AmountOfSubstance, "AmountOfSubstance" }, { Unit::Angle, "Angle" }, @@ -604,6 +604,7 @@ std::string Unit::getTypeString() const { Unit::ElectricalResistance, "ElectricalResistance" }, { Unit::ElectricCharge, "ElectricCharge" }, { Unit::SurfaceChargeDensity, "SurfaceChargeDensity" }, + { Unit::VolumeChargeDensity, "VolumeChargeDensity" }, { Unit::ElectricCurrent, "ElectricCurrent" }, { Unit::ElectricPotential, "ElectricPotential" }, { Unit::ElectromagneticPotential, "ElectromagneticPotential" }, @@ -683,6 +684,7 @@ const Unit Unit::ElectricalInductance (2, 1, -2, -2); const Unit Unit::ElectricalResistance (2, 1, -3, -2); const Unit Unit::ElectricCharge (0, 0, 1, 1); const Unit Unit::SurfaceChargeDensity (-2, 0, 1, 1); +const Unit Unit::VolumeChargeDensity (-3, 0, 1, 1); const Unit Unit::ElectricPotential (2, 1, -3, -1); const Unit Unit::ElectromagneticPotential (1, 1, -2, -1); const Unit Unit::Force (1, 1, -2); diff --git a/src/Base/Unit.h b/src/Base/Unit.h index b47d5c26ae..77b2273b3d 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -111,6 +111,7 @@ public: static const Unit ElectricPotential; static const Unit ElectricCharge; static const Unit SurfaceChargeDensity; + static const Unit VolumeChargeDensity; static const Unit MagneticFieldStrength; static const Unit MagneticFlux; static const Unit MagneticFluxDensity; diff --git a/src/Base/UnitsSchemaInternal.cpp b/src/Base/UnitsSchemaInternal.cpp index 4ef3fd217d..c1bf33c321 100644 --- a/src/Base/UnitsSchemaInternal.cpp +++ b/src/Base/UnitsSchemaInternal.cpp @@ -370,8 +370,12 @@ UnitsSchemaInternal::schemaTranslate(const Quantity& quant, double& factor, std: factor = 1.0; } else if (unit == Unit::SurfaceChargeDensity) { - unitString = "C/m^2"; - factor = 1e-6; + unitString = "C/mm^2"; + factor = 1.0; + } + else if (unit == Unit::VolumeChargeDensity) { + unitString = "C/mm^3"; + factor = 1.0; } else if (unit == Unit::CurrentDensity) { if (UnitValue <= 1e3) { diff --git a/src/Base/UnitsSchemaMKS.cpp b/src/Base/UnitsSchemaMKS.cpp index 0727c161c4..42ea0b0c79 100644 --- a/src/Base/UnitsSchemaMKS.cpp +++ b/src/Base/UnitsSchemaMKS.cpp @@ -320,6 +320,10 @@ UnitsSchemaMKS::schemaTranslate(const Quantity& quant, double& factor, std::stri unitString = "C/m^2"; factor = 1e-6; } + else if (unit == Unit::VolumeChargeDensity) { + unitString = "C/m^3"; + factor = 1e-9; + } else if (unit == Unit::CurrentDensity) { if (UnitValue <= 1e3) { unitString = "A/m^2"; From a8372c1f557cbef97a70805521eec21162b493c0 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 27 Mar 2025 09:40:07 -0300 Subject: [PATCH 026/316] Fem: Rename property SurfaceChargeDensity to ElectricFluxDensity --- .../Resources/ui/ElectrostaticPotential.ui | 6 +++--- .../constraint_electrostaticpotential.py | 15 ++++++++++++-- .../task_constraint_electrostaticpotential.py | 20 +++++++++---------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui b/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui index 3956a7e83d..50fc5e15c5 100644 --- a/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui +++ b/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui @@ -416,14 +416,14 @@ Note: has no effect if a solid was selected - Surface Charge Density: + Electric Flux Density: - + - Surface charge density + Normal component of electric displacement field C/m^2 diff --git a/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py b/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py index 50ac56a951..0c9e37a748 100644 --- a/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py @@ -145,9 +145,11 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject) prop.append( _PropHelper( type="App::PropertySurfaceChargeDensity", - name="SurfaceChargeDensity", + name="ElectricFluxDensity", group="Parameter", - doc="Free surface charge density", + doc="Electric displacement field D.\n" + + "For interfaces, it represents the difference\n" + + "between the normal component in the two media", value="0 C/m^2", ) ) @@ -299,3 +301,12 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject) except Base.PropertyError: pass + + # set electric flux density from old surface charge density + try: + obj.ElectricFluxDensity = obj.getPropertyByName("SurfaceChargeDensity") + obj.setPropertyStatus("SurfaceChargeDensity", "-LockDynamic") + obj.removeProperty("SurfaceChargeDensity") + + except Base.PropertyError: + pass diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py index 3d1826e126..e4d1b39c06 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py @@ -171,9 +171,9 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.electric_infinity_changed, ) QtCore.QObject.connect( - self.parameter_widget.qsb_surface_charge_density, + self.parameter_widget.qsb_electric_flux_density, QtCore.SIGNAL("valueChanged(Base::Quantity)"), - self.surface_charge_density_changed, + self.electric_flux_density_changed, ) self.init_parameter_widget() @@ -232,7 +232,7 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.electric_infinity = self.obj.ElectricInfinity self.capacitance_body_enabled = self.obj.CapacitanceBodyEnabled self.capacitance_body = self.obj.CapacitanceBody - self.surface_charge_density = self.obj.SurfaceChargeDensity + self.electric_flux_density = self.obj.ElectricFluxDensity def _set_params(self): self.obj.Potential = self.potential @@ -258,7 +258,7 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.obj.CapacitanceBodyEnabled = self.capacitance_body_enabled self.obj.CapacitanceBody = self.capacitance_body - self.obj.SurfaceChargeDensity = self.surface_charge_density + self.obj.ElectricFluxDensity = self.electric_flux_density def init_parameter_widget(self): self._get_params() @@ -313,11 +313,11 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.obj, "CapacitanceBody" ) - self.parameter_widget.qsb_surface_charge_density.setProperty( - "value", self.surface_charge_density + self.parameter_widget.qsb_electric_flux_density.setProperty( + "value", self.electric_flux_density ) - FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_surface_charge_density).bind( - self.obj, "SurfaceChargeDensity" + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_electric_flux_density).bind( + self.obj, "ElectricFluxDensity" ) self.bc_enum = self.obj.getEnumerationsOfProperty("BoundaryCondition") @@ -397,8 +397,8 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.capacitance_body = value self.parameter_widget.spb_capacitance_body.setValue(value) - def surface_charge_density_changed(self, value): - self.surface_charge_density = value + def electric_flux_density_changed(self, value): + self.electric_flux_density = value def boundary_condition_changed(self, index): self.boundary_condition = self.bc_enum[index] From 10426ca011a9243eadfd949d0672e2d7b663dd6c Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 27 Mar 2025 10:18:16 -0300 Subject: [PATCH 027/316] Fem: Add electric charge density object --- src/Mod/Fem/CMakeLists.txt | 3 + src/Mod/Fem/Gui/CMakeLists.txt | 2 + src/Mod/Fem/Gui/Command.cpp | 19 + src/Mod/Fem/Gui/Resources/Fem.qrc | 2 + .../FEM_ConstraintElectricChargeDensity.svg | 430 ++++++++++++++++++ .../ConstraintElectricChargeDensity.iv | 74 +++ .../Gui/Resources/ui/ElectricChargeDensity.ui | 187 ++++++++ src/Mod/Fem/Gui/Workbench.cpp | 3 +- src/Mod/Fem/ObjectsFem.py | 14 + src/Mod/Fem/femcommands/commands.py | 17 + .../constraint_electricchargedensity.py | 87 ++++ .../elmer/equations/electrostatic_writer.py | 61 ++- src/Mod/Fem/femsolver/elmer/writer.py | 1 + .../task_constraint_electricchargedensity.py | 171 +++++++ .../view_constraint_electricchargedensity.py | 51 +++ 15 files changed, 1119 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg create mode 100644 src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv create mode 100644 src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui create mode 100644 src/Mod/Fem/femobjects/constraint_electricchargedensity.py create mode 100644 src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py create mode 100644 src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 44aff6f11c..aabc377464 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -180,6 +180,7 @@ SET(FemObjects_SRCS femobjects/constraint_bodyheatsource.py femobjects/constraint_centrif.py femobjects/constraint_currentdensity.py + femobjects/constraint_electricchargedensity.py femobjects/constraint_electrostaticpotential.py femobjects/constraint_flowvelocity.py femobjects/constraint_initialflowvelocity.py @@ -582,6 +583,7 @@ SET(FemGuiTaskPanels_SRCS femtaskpanels/task_constraint_bodyheatsource.py femtaskpanels/task_constraint_centrif.py femtaskpanels/task_constraint_currentdensity.py + femtaskpanels/task_constraint_electricchargedensity.py femtaskpanels/task_constraint_electrostaticpotential.py femtaskpanels/task_constraint_flowvelocity.py femtaskpanels/task_constraint_initialflowvelocity.py @@ -627,6 +629,7 @@ SET(FemGuiViewProvider_SRCS femviewprovider/view_constraint_bodyheatsource.py femviewprovider/view_constraint_centrif.py femviewprovider/view_constraint_currentdensity.py + femviewprovider/view_constraint_electricchargedensity.py femviewprovider/view_constraint_electrostaticpotential.py femviewprovider/view_constraint_flowvelocity.py femviewprovider/view_constraint_initialflowvelocity.py diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 6fb0572ecd..cbe6e488db 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -369,6 +369,7 @@ SET(FemGuiIcon_SVG SET(FemGuiSymbol_IV Resources/symbols/ConstraintContact.iv Resources/symbols/ConstraintDisplacement.iv + Resources/symbols/ConstraintElectricChargeDensity.iv Resources/symbols/ConstraintElectrostaticPotential.iv Resources/symbols/ConstraintCurrentDensity.iv Resources/symbols/ConstraintFixed.iv @@ -405,6 +406,7 @@ SET(FemGuiPythonUI_SRCS Resources/ui/ConstraintSectionPrint.ui Resources/ui/CurrentDensity.ui Resources/ui/DlgSettingsNetgen.ui + Resources/ui/ElectricChargeDensity.ui Resources/ui/ElectrostaticPotential.ui Resources/ui/ElementFluid1D.ui Resources/ui/ElementGeometry1D.ui diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index e71185cacd..20c52dbcbf 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -1416,6 +1416,9 @@ void CmdFemCompEmConstraints::activated(int iMsg) else if (iMsg == 2) { rcCmdMgr.runCommandByName("FEM_ConstraintMagnetization"); } + else if (iMsg == 3) { + rcCmdMgr.runCommandByName("FEM_ConstraintElectricChargeDensity"); + } else { return; } @@ -1441,6 +1444,8 @@ Gui::Action* CmdFemCompEmConstraints::createAction() cmd1->setIcon(Gui::BitmapFactory().iconFromTheme("FEM_ConstraintCurrentDensity")); QAction* cmd2 = pcAction->addAction(QString()); cmd2->setIcon(Gui::BitmapFactory().iconFromTheme("FEM_ConstraintMagnetization")); + QAction* cmd3 = pcAction->addAction(QString()); + cmd3->setIcon(Gui::BitmapFactory().iconFromTheme("FEM_ConstraintElectricChargeDensity")); _pcAction = pcAction; languageChange(); @@ -1502,6 +1507,20 @@ void CmdFemCompEmConstraints::languageChange() cmd2->setStatusTip(QApplication::translate("FEM_ConstraintMagnetization", ConstraintMagnetization->getStatusTip())); } + + Gui::Command* ConstraintElectricChargeDensity = + rcCmdMgr.getCommandByName("FEM_ConstraintElectricChargeDensity"); + if (ConstraintElectricChargeDensity) { + QAction* cmd3 = a[3]; + cmd3->setText(QApplication::translate("FEM_ConstraintElectricChargeDensity", + ConstraintElectricChargeDensity->getMenuText())); + cmd3->setToolTip( + QApplication::translate("FEM_ConstraintElectricChargeDensity", + ConstraintElectricChargeDensity->getToolTipText())); + cmd3->setStatusTip( + QApplication::translate("FEM_ConstraintElectricChargeDensity", + ConstraintElectricChargeDensity->getStatusTip())); + } } bool CmdFemCompEmConstraints::isActive() diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index dd132e54fc..4033dfc273 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -15,6 +15,7 @@ icons/FEM_ConstraintContact.svg icons/FEM_ConstraintCurrentDensity.svg icons/FEM_ConstraintDisplacement.svg + icons/FEM_ConstraintElectricChargeDensity.svg icons/FEM_ConstraintElectrostaticPotential.svg icons/FEM_ConstraintFixed.svg icons/FEM_ConstraintFlowVelocity.svg @@ -127,6 +128,7 @@ ui/ConstraintTie.ui ui/CurrentDensity.ui ui/DlgSettingsNetgen.ui + ui/ElectricChargeDensity.ui ui/ElectrostaticPotential.ui ui/ElementFluid1D.ui ui/ElementGeometry1D.ui diff --git a/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg b/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg new file mode 100644 index 0000000000..4e8402350a --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg @@ -0,0 +1,430 @@ + + + + FEM_ConstraintElectrostaticPotential + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + FEM_ConstraintElectrostaticPotential + + + [bitacovir] + + + PartDesign_MoveTip + 12-02-2021 + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv b/src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv new file mode 100644 index 0000000000..1689168a72 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv @@ -0,0 +1,74 @@ +#Inventor V2.1 ascii + +# SPDX-License-Identifier: LGPL-2.1-or-later + +#/*************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# ************************************************************************** + + +Separator { + + Separator { + + Translation { + translation 0 0.5 0 + + } + Sphere { + radius 0.5 + + } + Translation { + translation 0 2.0 0 + + } + BaseColor { + rgb 0.17 0.46 1.0 + + } + Sphere { + radius 0.5 + + } + Translation { + translation 0 -1.375 0 + + } + BaseColor { + rgb 1 1 1 + + } + Cylinder { + radius 0.1 + height 0.75 + + } + Translation { + translation 0 .625 0 + + } + Cone { + bottomRadius 0.25 + height 0.5 + + } + } +} diff --git a/src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui b/src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui new file mode 100644 index 0000000000..77def88519 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui @@ -0,0 +1,187 @@ + + + Form + + + + 0 + 0 + 350 + 40 + + + + Analysis feature properties + + + + + + + + + + + Mode: + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + Free surface charge density + + + + + Density: + + + + + + + true + + + C/mm^2 + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + + + 1 + + + + + + + Free volume charge density + + + + + Density: + + + + + + + true + + + C/mm^3 + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + + + 2 + + + + + + + Free total charge + + + + + Total Charge: + + + + + + + true + + + C + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + + + + + + + + + + + Gui::QuantitySpinBox + QWidget +
Gui/QuantitySpinBox.h
+
+
+ + +
diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 345632754e..7740d29c19 100644 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -246,7 +246,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const elec->setCommand("&Electromagnetic boundary conditions"); *elec << "FEM_ConstraintElectrostaticPotential" << "FEM_ConstraintCurrentDensity" - << "FEM_ConstraintMagnetization"; + << "FEM_ConstraintMagnetization" + << "FEM_ConstraintElectricChargeDensity"; Gui::MenuItem* fluid = new Gui::MenuItem; fluid->setCommand("&Fluid boundary conditions"); diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index b8893e5d20..17a8b436f9 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -132,6 +132,20 @@ def makeConstraintDisplacement(doc, name="ConstraintDisplacement"): return obj +def makeConstraintElectricChargeDensity(doc, name="ElectricChargeDensity"): + """makeConstraintElectricChargeDensity(document, [name]): + makes a Fem ElectricChargeDensity object""" + obj = doc.addObject("Fem::ConstraintPython", name) + from femobjects import constraint_electricchargedensity + + constraint_electricchargedensity.ConstraintElectricChargeDensity(obj) + if FreeCAD.GuiUp: + from femviewprovider import view_constraint_electricchargedensity + + view_constraint_electricchargedensity.VPConstraintElectricChargeDensity(obj.ViewObject) + return obj + + def makeConstraintElectrostaticPotential(doc, name="ConstraintElectrostaticPotential"): """makeConstraintElectrostaticPotential(document, [name]): makes a Fem ElectrostaticPotential object""" diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 69bed9352f..89dad73b83 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -221,6 +221,22 @@ class _ConstraintCurrentDensity(CommandManager): self.do_activated = "add_obj_on_gui_set_edit" +class _ConstraintElectricChargeDensity(CommandManager): + "The FEM_ConstraintElectricChargeDensity command definition" + + def __init__(self): + super().__init__() + self.pixmap = "FEM_ConstraintElectricChargeDensity" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintElectricChargeDensity", "Electric charge density" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintElectricChargeDensity", "Creates a electric charge density" + ) + self.is_active = "with_analysis" + self.do_activated = "add_obj_on_gui_set_edit" + + class _ConstraintElectrostaticPotential(CommandManager): "The FEM_ConstraintElectrostaticPotential command definition" @@ -1171,6 +1187,7 @@ FreeCADGui.addCommand("FEM_ConstantVacuumPermittivity", _ConstantVacuumPermittiv FreeCADGui.addCommand("FEM_ConstraintBodyHeatSource", _ConstraintBodyHeatSource()) FreeCADGui.addCommand("FEM_ConstraintCentrif", _ConstraintCentrif()) FreeCADGui.addCommand("FEM_ConstraintCurrentDensity", _ConstraintCurrentDensity()) +FreeCADGui.addCommand("FEM_ConstraintElectricChargeDensity", _ConstraintElectricChargeDensity()) FreeCADGui.addCommand("FEM_ConstraintElectrostaticPotential", _ConstraintElectrostaticPotential()) FreeCADGui.addCommand("FEM_ConstraintFlowVelocity", _ConstraintFlowVelocity()) FreeCADGui.addCommand("FEM_ConstraintInitialFlowVelocity", _ConstraintInitialFlowVelocity()) diff --git a/src/Mod/Fem/femobjects/constraint_electricchargedensity.py b/src/Mod/Fem/femobjects/constraint_electricchargedensity.py new file mode 100644 index 0000000000..fb2b9a6b16 --- /dev/null +++ b/src/Mod/Fem/femobjects/constraint_electricchargedensity.py @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM constraint electric charge density document object" +__author__ = "Mario Passaglia" +__url__ = "https://www.freecad.org" + +## @package constraint_electricchargedensity +# \ingroup FEM +# \brief constraint electric charge density object + +from . import base_fempythonobject + +_PropHelper = base_fempythonobject._PropHelper + + +class ConstraintElectricChargeDensity(base_fempythonobject.BaseFemPythonObject): + + Type = "Fem::ConstraintElectricChargeDensity" + + def __init__(self, obj): + super().__init__(obj) + + for prop in self._get_properties(): + prop.add_to_object(obj) + + def _get_properties(self): + prop = [] + + prop.append( + _PropHelper( + type="App::PropertyVolumeChargeDensity", + name="SourceChargeDensity", + group="Electric Charge Density", + doc="Free electric charge per unit volume at the sources", + value="0 C/mm^3", + ) + ) + prop.append( + _PropHelper( + type="App::PropertySurfaceChargeDensity", + name="InterfaceChargeDensity", + group="Electric Charge Density", + doc="Free electric charge per unit surface at the boundaries", + value="0 C/mm^2", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectricCharge", + name="TotalCharge", + group="Electric Charge Density", + doc="Total free electric charge", + value="0 C", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="Mode", + group="Electric Charge Density", + doc="Switch quantity input mode", + value=["Interface", "Source", "Total Interface", "Total Source"], + ) + ) + + return prop diff --git a/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py b/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py index 6ffba76461..bc49f4ee05 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py @@ -30,6 +30,8 @@ __url__ = "https://www.freecad.org" ## \addtogroup FEM # @{ +from FreeCAD import Units + from .. import sifio @@ -133,8 +135,8 @@ class ESwriter: elif obj.BoundaryCondition == "Neumann": self.write.boundary( name, - "Surface Charge Density", - obj.SurfaceChargeDensity.getValueAs("C/m^2").Value, + "Electric Flux", + obj.ElectricFluxDensity.getValueAs("C/m^2").Value, ) if obj.PotentialConstant: self.write.boundary(name, "Potential Constant", True) @@ -146,5 +148,60 @@ class ESwriter: self.write.boundary(name, "Capacitance Body", obj.CapacitanceBody) self.write.handled(obj) + for obj in self.write.getMember("Fem::ConstraintElectricChargeDensity"): + if obj.Mode not in ["Interface", "Total Interface"]: + continue + + size = 0 + items = [] + for feat, sub_elem in obj.References: + for name in sub_elem: + sub = feat.getSubObject(name) + if sub.ShapeType == "Face": + size += sub.Area + items.append(name) + elif sub.ShapeType == "Edge": + size += sub.Length + items.append(name) + + if items: + if obj.Mode == "Interface": + density = obj.InterfaceChargeDensity.getValueAs("C/m^2").Value + elif obj.Mode == "Total Interface": + area = Units.Quantity(f"{size} mm^2") + density = (obj.TotalCharge / area).getValueAs("C/m^2").Value + for name in items: + self.write.boundary(name, "! FreeCAD Name", obj.Label) + self.write.boundary(name, "Surface Charge Density", round(density, 6)) + self.write.handled(obj) + + def handleElectrostaticBodyForces(self): + for obj in self.write.getMember("Fem::ConstraintElectricChargeDensity"): + if obj.Mode not in ["Source", "Total Source"]: + continue + + size = 0 + items = [] + for feat, sub_elem in obj.References: + for name in sub_elem: + sub = feat.getSubObject(name) + if sub.ShapeType == "Solid": + size += sub.Volume + items.append(name) + elif sub.ShapeType == "Face": + size += sub.Area + items.append(name) + + if items: + if obj.Mode == "Source": + density = obj.SourceChargeDensity.getValueAs("C/m^3").Value + elif obj.Mode == "Total Source": + vol = Units.Quantity(f"{size} mm^3") + density = (obj.TotalCharge / vol).getValueAs("C/m^3").Value + for name in items: + self.write.bodyForce(name, "! FreeCAD Name", obj.Label) + self.write.bodyForce(name, "Charge Density", round(density, 6)) + self.write.handled(obj) + ## @} diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index 834d87bcc1..b55833c754 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -471,6 +471,7 @@ class Writer: if activeIn: ESW.handleElectrostaticConstants() ESW.handleElectrostaticBndConditions() + ESW.handleElectrostaticBodyForces() ESW.handleElectrostaticMaterial(activeIn) # ------------------------------------------------------------------------------------------- diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py b/src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py new file mode 100644 index 0000000000..1d082454ae --- /dev/null +++ b/src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py @@ -0,0 +1,171 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM constraint electric charge density task panel" +__author__ = "Mario Passaglia" +__url__ = "https://www.freecad.org" + +## @package task_constraint_electricchargedensity +# \ingroup FEM +# \brief task panel for constraint electric charge density object + +from PySide import QtCore + +import FreeCAD +import FreeCADGui + +from femguiutils import selection_widgets + +from femtools import membertools +from . import base_femtaskpanel + + +class _TaskPanel(base_femtaskpanel._BaseTaskPanel): + + def __init__(self, obj): + super().__init__(obj) + + self.parameter_widget = FreeCADGui.PySideUic.loadUi( + FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/ElectricChargeDensity.ui" + ) + + self.init_parameter_widget() + + QtCore.QObject.connect( + self.parameter_widget.qsb_source_charge_density, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.source_charge_density_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_interface_charge_density, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.interface_charge_density_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_total_charge, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.total_charge_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.cb_mode, + QtCore.SIGNAL("currentIndexChanged(int)"), + self.mode_changed, + ) + + # geometry selection widget + # start with Solid in list! + self.selection_widget = selection_widgets.GeometryElementsSelection( + obj.References, ["Solid", "Face", "Edge"], False, False + ) + + # form made from param and selection widget + self.form = [self.parameter_widget, self.selection_widget] + + analysis = obj.getParentGroup() + self._mesh = None + self._part = None + if analysis is not None: + self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") + if self._mesh is not None: + self._part = self._mesh.Shape + self._partVisible = None + self._meshVisible = None + + def open(self): + if self._mesh is not None and self._part is not None: + self._meshVisible = self._mesh.ViewObject.isVisible() + self._partVisible = self._part.ViewObject.isVisible() + self._mesh.ViewObject.hide() + self._part.ViewObject.show() + + def reject(self): + self.restore_visibility() + self.selection_widget.finish_selection() + return super().reject() + + def accept(self): + self.obj.References = self.selection_widget.references + self.obj.SourceChargeDensity = self.source_charge_density + self.obj.InterfaceChargeDensity = self.interface_charge_density + self.obj.TotalCharge = self.total_charge + self.obj.Mode = self.mode + + self.selection_widget.finish_selection() + self.restore_visibility() + return super().accept() + + def restore_visibility(self): + if self._mesh is not None and self._part is not None: + if self._meshVisible: + self._mesh.ViewObject.show() + else: + self._mesh.ViewObject.hide() + if self._partVisible: + self._part.ViewObject.show() + else: + self._part.ViewObject.hide() + + def init_parameter_widget(self): + self.source_charge_density = self.obj.SourceChargeDensity + self.interface_charge_density = self.obj.InterfaceChargeDensity + self.total_charge = self.obj.TotalCharge + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_source_charge_density).bind( + self.obj, "SourceChargeDensity" + ) + self.parameter_widget.qsb_source_charge_density.setProperty( + "value", self.source_charge_density + ) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_interface_charge_density).bind( + self.obj, "InterfaceChargeDensity" + ) + self.parameter_widget.qsb_interface_charge_density.setProperty( + "value", self.interface_charge_density + ) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_total_charge).bind( + self.obj, "TotalCharge" + ) + self.parameter_widget.qsb_total_charge.setProperty("value", self.total_charge) + + self.mode = self.obj.Mode + self.mode_enum = self.obj.getEnumerationsOfProperty("Mode") + self.parameter_widget.cb_mode.addItems(self.mode_enum) + index = self.mode_enum.index(self.mode) + self.parameter_widget.cb_mode.setCurrentIndex(index) + self.mode_changed(index) + + def source_charge_density_changed(self, base_quantity_value): + self.source_charge_density = base_quantity_value + + def interface_charge_density_changed(self, base_quantity_value): + self.interface_charge_density = base_quantity_value + + def total_charge_changed(self, base_quantity_value): + self.total_charge = base_quantity_value + + def mode_changed(self, index): + self.mode = self.mode_enum[index] + if self.mode in ["Total Interface", "Total Source"]: + index = 2 + self.parameter_widget.sw_mode.setCurrentIndex(index) diff --git a/src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py b/src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py new file mode 100644 index 0000000000..59517f2c4e --- /dev/null +++ b/src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM constraint electric charge view provider" +__author__ = "Mario Passaglia" +__url__ = "https://www.freecad.org" + +## @package view_constraint_electricchargedensity +# \ingroup FEM +# \brief view provider for the constraint electric charge density object + +from femtaskpanels import task_constraint_electricchargedensity +from . import view_base_femconstraint + + +class VPConstraintElectricChargeDensity(view_base_femconstraint.VPBaseFemConstraint): + + def __init__(self, vobj): + super().__init__(vobj) + mat = vobj.ShapeAppearance[0] + mat.DiffuseColor = (1.0, 0.0, 0.2, 0.0) + vobj.ShapeAppearance = mat + + def setEdit(self, vobj, mode=0): + return view_base_femconstraint.VPBaseFemConstraint.setEdit( + self, vobj, mode, task_constraint_electricchargedensity._TaskPanel + ) + + def attach(self, vobj): + super().attach(vobj) + vobj.loadSymbol(self.resource_symbol_dir + "ConstraintElectricChargeDensity.iv") From d8b9681a8f5fa10fd1b85f941468d5c9bcea490a Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 27 Mar 2025 10:19:08 -0300 Subject: [PATCH 028/316] Fem: Update test --- src/Mod/Fem/femtest/app/test_object.py | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Mod/Fem/femtest/app/test_object.py b/src/Mod/Fem/femtest/app/test_object.py index f2b154b5be..cbd67e9c84 100644 --- a/src/Mod/Fem/femtest/app/test_object.py +++ b/src/Mod/Fem/femtest/app/test_object.py @@ -159,6 +159,10 @@ class TestObjectType(unittest.TestCase): "Fem::ConstraintElectrostaticPotential", type_of_obj(ObjectsFem.makeConstraintElectrostaticPotential(doc)), ) + self.assertEqual( + "Fem::ConstraintElectricChargeDensity", + type_of_obj(ObjectsFem.makeConstraintElectricChargeDensity(doc)), + ) self.assertEqual("Fem::ConstraintFixed", type_of_obj(ObjectsFem.makeConstraintFixed(doc))) self.assertEqual( "Fem::ConstraintRigidBody", type_of_obj(ObjectsFem.makeConstraintRigidBody(doc)) @@ -334,6 +338,12 @@ class TestObjectType(unittest.TestCase): "Fem::ConstraintElectrostaticPotential", ) ) + self.assertTrue( + is_of_type( + ObjectsFem.makeConstraintElectricChargeDensity(doc), + "Fem::ConstraintElectricChargeDensity", + ) + ) self.assertTrue(is_of_type(ObjectsFem.makeConstraintFixed(doc), "Fem::ConstraintFixed")) self.assertTrue( is_of_type(ObjectsFem.makeConstraintRigidBody(doc), "Fem::ConstraintRigidBody") @@ -552,6 +562,18 @@ class TestObjectType(unittest.TestCase): ) ) + # ConstraintElectricChargeDensity + constraint_electric_charge_density = ObjectsFem.makeConstraintElectricChargeDensity(doc) + self.assertTrue(is_derived_from(constraint_electric_charge_density, "App::DocumentObject")) + self.assertTrue( + is_derived_from(constraint_electric_charge_density, "Fem::ConstraintPython") + ) + self.assertTrue( + is_derived_from( + constraint_electric_charge_density, "Fem::ConstraintElectricChargeDensity" + ) + ) + # ConstraintFixed constraint_fixed = ObjectsFem.makeConstraintFixed(doc) self.assertTrue(is_derived_from(constraint_fixed, "App::DocumentObject")) @@ -913,6 +935,11 @@ class TestObjectType(unittest.TestCase): "Fem::ConstraintPython" ) ) + self.assertTrue( + ObjectsFem.makeConstraintElectricChargeDensity(doc).isDerivedFrom( + "Fem::ConstraintPython" + ) + ) self.assertTrue(ObjectsFem.makeConstraintFixed(doc).isDerivedFrom("Fem::ConstraintFixed")) self.assertTrue( ObjectsFem.makeConstraintRigidBody(doc).isDerivedFrom("Fem::ConstraintRigidBody") @@ -1077,6 +1104,7 @@ def create_all_fem_objects_doc(doc): analysis.addObject(ObjectsFem.makeConstraintCurrentDensity(doc)) analysis.addObject(ObjectsFem.makeConstraintDisplacement(doc)) analysis.addObject(ObjectsFem.makeConstraintElectrostaticPotential(doc)) + analysis.addObject(ObjectsFem.makeConstraintElectricChargeDensity(doc)) analysis.addObject(ObjectsFem.makeConstraintFixed(doc)) analysis.addObject(ObjectsFem.makeConstraintRigidBody(doc)) analysis.addObject(ObjectsFem.makeConstraintFlowVelocity(doc)) From fb5ded6e53b1109ba5c0bbffe18ee109d18b2760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leif-J=C3=B6ran=20Olsson?= Date: Thu, 27 Mar 2025 14:18:04 +0100 Subject: [PATCH 029/316] Fixing ambiguiguous python shebang in installed script freecad-thumbnailer. Removed skip ci according to instruction. --- src/Tools/freecad-thumbnailer.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tools/freecad-thumbnailer.in b/src/Tools/freecad-thumbnailer.in index 641c9f97d4..0a6fe451cd 100644 --- a/src/Tools/freecad-thumbnailer.in +++ b/src/Tools/freecad-thumbnailer.in @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 """Support file to show FreeCAD thumbnails on Free Desktop Environments (like GNOME or KDE) Installation: From 4ac8f0b141bc3802774005f4b5c5416e08c07369 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Thu, 27 Mar 2025 13:03:43 +0100 Subject: [PATCH 030/316] Draft: fix status bar widgets display timing issue Fixes #17044. --- .../Draft/draftutils/init_draft_statusbar.py | 75 +++++++++++-------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/src/Mod/Draft/draftutils/init_draft_statusbar.py b/src/Mod/Draft/draftutils/init_draft_statusbar.py index 43ef0b63fd..80e048f6e4 100644 --- a/src/Mod/Draft/draftutils/init_draft_statusbar.py +++ b/src/Mod/Draft/draftutils/init_draft_statusbar.py @@ -287,6 +287,46 @@ def init_draft_statusbar_snap(): snap_action.addAction(Gui.Command.get(cmd).getAction()[0]) +def show_draft_statusbar_scale(): + """ + shows draft statusbar scale widget + """ + mw = Gui.getMainWindow() + sb = mw.statusBar() + + scale_widget = sb.findChild(QtWidgets.QToolBar, "draft_scale_widget") + if scale_widget: + scale_widget.show() + else: + scale_widget = mw.findChild(QtWidgets.QToolBar, "draft_scale_widget") + if scale_widget: + sb.insertPermanentWidget(3, scale_widget) + scale_widget.show() + else: + init_draft_statusbar_scale() + + +def show_draft_statusbar_snap(): + """ + shows draft statusbar snap widget + """ + mw = Gui.getMainWindow() + sb = mw.statusBar() + + snap_widget = sb.findChild(QtWidgets.QToolBar, "draft_snap_widget") + if snap_widget: + snap_widget.setOrientation(QtCore.Qt.Orientation.Horizontal) + snap_widget.show() + else: + snap_widget = mw.findChild(QtWidgets.QToolBar, "draft_snap_widget") + if snap_widget: + sb.insertPermanentWidget(2, snap_widget) + snap_widget.setOrientation(QtCore.Qt.Orientation.Horizontal) + snap_widget.show() + else: + init_draft_statusbar_snap() + + def hide_draft_statusbar_scale(): """ hides draft statusbar scale widget @@ -323,36 +363,10 @@ def show_draft_statusbar(): """ shows draft statusbar if present or initializes it """ - mw = Gui.getMainWindow() - sb = mw.statusBar() - if params.get_param("DisplayStatusbarScaleWidget"): - scale_widget = sb.findChild(QtWidgets.QToolBar, "draft_scale_widget") - if scale_widget: - scale_widget.show() - else: - scale_widget = mw.findChild(QtWidgets.QToolBar, "draft_scale_widget") - if scale_widget: - sb.insertPermanentWidget(3, scale_widget) - scale_widget.show() - else: - t = QtCore.QTimer() - t.singleShot(500, init_draft_statusbar_scale) - + QtCore.QTimer().singleShot(500, show_draft_statusbar_scale) if params.get_param("DisplayStatusbarSnapWidget"): - snap_widget = sb.findChild(QtWidgets.QToolBar, "draft_snap_widget") - if snap_widget: - snap_widget.setOrientation(QtCore.Qt.Orientation.Horizontal) - snap_widget.show() - else: - snap_widget = mw.findChild(QtWidgets.QToolBar, "draft_snap_widget") - if snap_widget: - sb.insertPermanentWidget(2, snap_widget) - snap_widget.setOrientation(QtCore.Qt.Orientation.Horizontal) - snap_widget.show() - else: - t = QtCore.QTimer() - t.singleShot(500, init_draft_statusbar_snap) + QtCore.QTimer().singleShot(500, show_draft_statusbar_snap) def hide_draft_statusbar(): @@ -361,8 +375,7 @@ def hide_draft_statusbar(): """ # Delay required in case the Draft WB is autoloaded, # else show_draft_statusbar will not yet be done. - t = QtCore.QTimer() - t.singleShot(500, hide_draft_statusbar_scale) - t.singleShot(500, hide_draft_statusbar_snap) + QtCore.QTimer().singleShot(500, hide_draft_statusbar_scale) + QtCore.QTimer().singleShot(500, hide_draft_statusbar_snap) ## @} From 8c6e77ee972ef1c99d2ab6a84c7ef4b04cc1bf07 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 27 Mar 2025 15:42:54 -0300 Subject: [PATCH 031/316] Base: Improve schema translation for electrical units --- src/Base/UnitsSchemaInternal.cpp | 34 +++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/Base/UnitsSchemaInternal.cpp b/src/Base/UnitsSchemaInternal.cpp index c1bf33c321..f06286ff3e 100644 --- a/src/Base/UnitsSchemaInternal.cpp +++ b/src/Base/UnitsSchemaInternal.cpp @@ -370,18 +370,42 @@ UnitsSchemaInternal::schemaTranslate(const Quantity& quant, double& factor, std: factor = 1.0; } else if (unit == Unit::SurfaceChargeDensity) { - unitString = "C/mm^2"; - factor = 1.0; + if (UnitValue <= 1e-4) { + unitString = "C/m^2"; + factor = 1e-6; + } + else if (UnitValue <= 1e-2) { + unitString = "C/cm^2"; + factor = 1e-2; + } + else { + unitString = "C/mm^2"; + factor = 1; + } } else if (unit == Unit::VolumeChargeDensity) { - unitString = "C/mm^3"; - factor = 1.0; + if (UnitValue <= 1e-4) { + unitString = "C/m^3"; + factor = 1e-9; + } + else if (UnitValue <= 1e-2) { + unitString = "C/cm^3"; + factor = 1e-3; + } + else { + unitString = "C/mm^3"; + factor = 1; + } } else if (unit == Unit::CurrentDensity) { - if (UnitValue <= 1e3) { + if (UnitValue <= 1e-4) { unitString = "A/m^2"; factor = 1e-6; } + else if (UnitValue <= 1e-2) { + unitString = "A/cm^2"; + factor = 1e-2; + } else { unitString = "A/mm^2"; factor = 1; From db8b58f73eb1935718efce3b5046017881853d64 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sun, 23 Mar 2025 22:43:34 -0300 Subject: [PATCH 032/316] Fem: Fix return value in FemPostPipelinePy::read --- src/Mod/Fem/App/FemPostPipelinePyImp.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/Mod/Fem/App/FemPostPipelinePyImp.cpp b/src/Mod/Fem/App/FemPostPipelinePyImp.cpp index d75f8dff41..83c282fc56 100644 --- a/src/Mod/Fem/App/FemPostPipelinePyImp.cpp +++ b/src/Mod/Fem/App/FemPostPipelinePyImp.cpp @@ -58,26 +58,22 @@ PyObject* FemPostPipelinePy::read(PyObject* args) &unitobj, &value_type)) { if (!values) { - // single argument version was called! - if (!PyUnicode_Check(files)) { PyErr_SetString(PyExc_TypeError, "argument must be file path"); return nullptr; } const char* path = PyUnicode_AsUTF8(files); getFemPostPipelinePtr()->read(Base::FileInfo(path)); + Py_Return; } else if (values && unitobj) { - // multistep version! - if (!(PyTuple_Check(files) || PyList_Check(files)) || !(PyTuple_Check(values) || PyList_Check(values))) { - - std::string error = std::string( - "Files and values must be list of strings and number respectively."); - throw Base::TypeError(error); + PyErr_SetString(PyExc_TypeError, + "Files and values must be list of strings and number respectively"); + return nullptr; } // extract the result objects @@ -89,7 +85,8 @@ PyObject* FemPostPipelinePy::read(PyObject* args) for (Py::Sequence::size_type i = 0; i < size; i++) { auto path = Py::Object(file_list[i]); if (!path.isString()) { - throw Base::TypeError("File path must be string"); + PyErr_SetString(PyExc_TypeError, "File path must be string"); + return nullptr; } file_result[i] = Base::FileInfo(path.as_string()); } @@ -103,8 +100,8 @@ PyObject* FemPostPipelinePy::read(PyObject* args) for (Py::Sequence::size_type i = 0; i < size; i++) { auto value = Py::Object(values_list[i]); if (!value.isNumeric()) { - std::string error = std::string("Values must be numbers"); - throw Base::TypeError(error); + PyErr_SetString(PyExc_TypeError, "Values must be numbers"); + return nullptr; } value_result[i] = Py::Float(value).as_double(); } From 5a6fd53b3a071a1932392c17c72af7769af42e73 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Fri, 28 Mar 2025 19:46:28 +0100 Subject: [PATCH 033/316] fix issues --- src/Mod/CAM/Path/Tool/Bit.py | 46 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/Mod/CAM/Path/Tool/Bit.py b/src/Mod/CAM/Path/Tool/Bit.py index b2b2905128..20a21382e9 100644 --- a/src/Mod/CAM/Path/Tool/Bit.py +++ b/src/Mod/CAM/Path/Tool/Bit.py @@ -118,22 +118,14 @@ def _findRelativePath(path, typ): return relative -# Unused due to bug fix related to relative paths -""" -def findRelativePathShape(path): - return _findRelativePath(path, 'Shape') - - -def findRelativePathTool(path): - return _findRelativePath(path, 'Bit') -""" - - def findRelativePathLibrary(path): return _findRelativePath(path, "Library") class ToolBit(object): + + TOOL_TYPES = [ "EndMill", "BallEndMill", "BullNoseMill", "Drill", "VBit", "Probe", "Laser", "Other"] + def __init__(self, obj, shapeFile, path=None): Path.Log.track(obj.Label, shapeFile, path) self.obj = obj @@ -155,6 +147,14 @@ class ToolBit(object): "Base", QT_TRANSLATE_NOOP("App::Property", "The file of the tool"), ) + + obj.addProperty( + "App::PropertyEnumeration", + "ToolType", + "Base", + QT_TRANSLATE_NOOP("App::Property", "The type of the tool"), + ) + obj.addProperty( "App::PropertyString", "ShapeName", @@ -168,10 +168,13 @@ class ToolBit(object): QT_TRANSLATE_NOOP("App::Property", "List of all properties inherited from the bit"), ) + # set enum types by assigning array + obj.ToolType = self.TOOL_TYPES if path: obj.File = path if shapeFile is None: obj.BitShape = "endmill.fcstd" + obj.ToolType = "EndMill" self._setupBitShape(obj) self.unloadBitBody(obj) else: @@ -196,6 +199,16 @@ class ToolBit(object): obj.setEditorMode("BitBody", 2) obj.setEditorMode("File", 1) obj.setEditorMode("Shape", 2) + + if not hasattr(obj, "ToolType"): + obj.addProperty( + "App::PropertyString", + "ToolType", + "Base", + QT_TRANSLATE_NOOP("App::Property", "The type of the tool"), + ) + obj.ToolType = self.TOOL_TYPES + if not hasattr(obj, "BitPropertyNames"): obj.addProperty( "App::PropertyStringList", @@ -438,6 +451,10 @@ class ToolBit(object): attrs = {} attrs["version"] = 2 attrs["name"] = obj.Label + + if obj.ToolType: + attrs["type"] = obj.ToolType + if Path.Preferences.toolsStoreAbsolutePaths(): attrs["shape"] = obj.BitShape else: @@ -451,8 +468,7 @@ class ToolBit(object): for name in obj.BitPropertyNames: params[name] = PathUtil.getPropertyValueString(obj, name) attrs["parameter"] = params - params = {} - attrs["attribute"] = params + attrs["attribute"] = {} return attrs @@ -467,6 +483,10 @@ class ToolBitFactory(object): Path.Log.track(attrs, path) obj = Factory.Create(name, attrs["shape"], path) obj.Label = attrs["name"] + + if "type" in attrs: + obj.ToolType = attrs["type"] + params = attrs["parameter"] for prop in params: PathUtil.setProperty(obj, prop, params[prop]) From 2f5f8f32e756e188f0171eb0f3a4933fdeb64c4c Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 28 Mar 2025 18:34:11 +0100 Subject: [PATCH 034/316] Remove old Coin code <=3 ubuntu 22.04 use libcoin v 4. https://launchpad.net/ubuntu/jammy/+package/libcoin-dev --- src/Gui/Quarter/QuarterWidget.cpp | 6 ----- src/Gui/SoTextLabel.cpp | 34 -------------------------- src/Gui/View3DInventorViewer.cpp | 27 -------------------- src/Gui/ViewProviderAnnotation.cpp | 7 ------ src/Mod/Sandbox/Gui/GLGraphicsView.cpp | 4 --- 5 files changed, 78 deletions(-) diff --git a/src/Gui/Quarter/QuarterWidget.cpp b/src/Gui/Quarter/QuarterWidget.cpp index 3560d595de..b69b87ca5d 100644 --- a/src/Gui/Quarter/QuarterWidget.cpp +++ b/src/Gui/Quarter/QuarterWidget.cpp @@ -76,9 +76,7 @@ #include #include -#if COIN_MAJOR_VERSION >= 4 #include -#endif #include #include @@ -1245,11 +1243,7 @@ QuarterWidget::setNavigationModeFile(const QUrl & url) QFile file(filenametmp); if (file.open(QIODevice::ReadOnly)){ QByteArray fileContents = file.readAll(); -#if COIN_MAJOR_VERSION >= 4 stateMachine = ScXML::readBuffer(SbByteBuffer(fileContents.size(), fileContents.constData())); -#else - stateMachine = ScXML::readBuffer(fileContents.constData()); -#endif file.close(); } } diff --git a/src/Gui/SoTextLabel.cpp b/src/Gui/SoTextLabel.cpp index 6e533bea98..695ba378e3 100644 --- a/src/Gui/SoTextLabel.cpp +++ b/src/Gui/SoTextLabel.cpp @@ -51,12 +51,7 @@ #include #include #include - -#if COIN_MAJOR_VERSION > 3 #include -#else -#include -#endif #include "SoTextLabel.h" #include "SoFCInteractiveElement.h" @@ -65,31 +60,6 @@ using namespace Gui; -/*! -\code - -s=""" - #Inventor V2.1 ascii - - Annotation { - Translation { translation 4 0 0 } - FontStyle { - size 20 - style BOLD - } - BaseColor { - rgb 0.0 0.0 0.0 - } - - - SoTextLabel { string ["Text label", "Second line"] backgroundColor 1.0 0.447059 0.337255} - } -""" - -App.ActiveDocument.addObject("App::InventorObject","iv").Buffer=s - -\endcode -*/ SO_NODE_SOURCE(SoTextLabel) @@ -215,11 +185,7 @@ void SoTextLabel::GLRender(SoGLRenderAction *action) // disable textures for all units SoGLTextureEnabledElement::set(state, this, false); -#if COIN_MAJOR_VERSION > 3 SoMultiTextureEnabledElement::set(state, this, false); -#else - SoGLTexture3EnabledElement::set(state, this, false); -#endif glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT); glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 3103b1afde..f8c3e5df70 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1707,16 +1707,11 @@ void View3DInventorViewer::savePicture(int width, int height, int sample, const auto root = new SoSeparator; root->ref(); -#if (COIN_MAJOR_VERSION >= 4) - // The behaviour in Coin4 has changed so that when using the same instance of 'SoFCOffscreenRenderer' - // multiple times internally the biggest viewport size is stored and set to the SoGLRenderAction. - // The trick is to add a callback node and override the viewport size with what we want. if (useCoinOffscreenRenderer) { auto cbvp = new SoCallback; cbvp->setCallback(setViewportCB); root->addChild(cbvp); } -#endif SoCamera* camera = getSoRenderManager()->getCamera(); @@ -3524,7 +3519,6 @@ void View3DInventorViewer::viewSelection() float(bbox.MaxX), float(bbox.MaxY), float(bbox.MaxZ)); -#if (COIN_MAJOR_VERSION >= 4) float aspectratio = getSoRenderManager()->getViewportRegion().getViewportAspectRatio(); switch (cam->viewportMapping.getValue()) { case SoCamera::CROP_VIEWPORT_FILL_FRAME: @@ -3536,27 +3530,6 @@ void View3DInventorViewer::viewSelection() break; } cam->viewBoundingBox(box,aspectratio,1.0); -#else - SoTempPath path(2); - path.ref(); - auto pcGroup = new SoGroup; - pcGroup->ref(); - auto pcTransform = new SoTransform; - pcGroup->addChild(pcTransform); - pcTransform->translation = box.getCenter(); - auto *pcCube = new SoCube; - pcGroup->addChild(pcCube); - float sizeX,sizeY,sizeZ; - box.getSize(sizeX,sizeY,sizeZ); - pcCube->width = sizeX; - pcCube->height = sizeY; - pcCube->depth = sizeZ; - path.append(pcGroup); - path.append(pcCube); - cam->viewAll(&path,getSoRenderManager()->getViewportRegion()); - path.unrefNoDelete(); - pcGroup->unref(); -#endif } } diff --git a/src/Gui/ViewProviderAnnotation.cpp b/src/Gui/ViewProviderAnnotation.cpp index c1cb67e3ce..785a96f368 100644 --- a/src/Gui/ViewProviderAnnotation.cpp +++ b/src/Gui/ViewProviderAnnotation.cpp @@ -248,15 +248,8 @@ void ViewProviderAnnotation::updateData(const App::Property* prop) const char* cs = line.c_str(); if (line.empty()) cs = " "; // empty lines make coin crash, we use a space instead -#if (COIN_MAJOR_VERSION <= 3) - QByteArray latin1str; - latin1str = (QString::fromUtf8(cs)).toLatin1(); - pLabel->string.set1Value(index, SbString(latin1str.constData())); - pLabel3d->string.set1Value(index, SbString(latin1str.constData())); -#else pLabel->string.set1Value(index, SbString(cs)); pLabel3d->string.set1Value(index, SbString(cs)); -#endif index++; } } diff --git a/src/Mod/Sandbox/Gui/GLGraphicsView.cpp b/src/Mod/Sandbox/Gui/GLGraphicsView.cpp index 544762e22b..316dc31aa0 100644 --- a/src/Mod/Sandbox/Gui/GLGraphicsView.cpp +++ b/src/Mod/Sandbox/Gui/GLGraphicsView.cpp @@ -454,11 +454,7 @@ GraphicsScene::setNavigationModeFile(const QUrl & url) QFile file(QString::fromLatin1(filenametmp)); if (file.open(QIODevice::ReadOnly)) { QByteArray fileContents = file.readAll(); -#if COIN_MAJOR_VERSION >= 4 stateMachine = ScXML::readBuffer(SbByteBuffer(fileContents.size(), fileContents.constData())); -#else - stateMachine = ScXML::readBuffer(fileContents.constData()); -#endif file.close(); } } From 96e8a9e83c1889bb70e4187493016a69b0c75c96 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Sat, 29 Mar 2025 12:21:36 +0100 Subject: [PATCH 035/316] Remove old GCC<=8 (#20508) GCC version is always greater than 8 --- src/Base/swigpyrun.cpp | 2 -- src/Mod/Part/App/GeometryMigrationExtension.cpp | 4 ---- src/Mod/Sketcher/App/ExternalGeometryExtension.cpp | 4 ---- src/Mod/Sketcher/App/SketchGeometryExtension.cpp | 5 ----- src/Mod/Sketcher/App/SolverGeometryExtension.cpp | 5 ----- src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.cpp | 4 ---- 6 files changed, 24 deletions(-) diff --git a/src/Base/swigpyrun.cpp b/src/Base/swigpyrun.cpp index 3213ad2a48..87fc3f59c5 100644 --- a/src/Base/swigpyrun.cpp +++ b/src/Base/swigpyrun.cpp @@ -31,10 +31,8 @@ #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#if __GNUC__ >= 8 #pragma GCC diagnostic ignored "-Wcast-function-type" #endif -#endif #include "PyExport.h" #include "Exception.h" namespace Swig_python diff --git a/src/Mod/Part/App/GeometryMigrationExtension.cpp b/src/Mod/Part/App/GeometryMigrationExtension.cpp index 2ecebe6298..43388eeecc 100644 --- a/src/Mod/Part/App/GeometryMigrationExtension.cpp +++ b/src/Mod/Part/App/GeometryMigrationExtension.cpp @@ -52,11 +52,7 @@ std::unique_ptr GeometryMigrationExtension::copy() cons copyAttributes(cpy.get()); -#if defined (__GNUC__) && (__GNUC__ <=4) - return std::move(cpy); -#else return cpy; -#endif } PyObject * GeometryMigrationExtension::getPyObject() diff --git a/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp b/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp index ced70dde49..7053525dc6 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp +++ b/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp @@ -82,11 +82,7 @@ std::unique_ptr ExternalGeometryExtension::copy() const copyAttributes(cpy.get()); -#if defined(__GNUC__) && (__GNUC__ <= 4) - return std::move(cpy); -#else return cpy; -#endif } PyObject* ExternalGeometryExtension::getPyObject() diff --git a/src/Mod/Sketcher/App/SketchGeometryExtension.cpp b/src/Mod/Sketcher/App/SketchGeometryExtension.cpp index 00929143b6..4759004f4e 100644 --- a/src/Mod/Sketcher/App/SketchGeometryExtension.cpp +++ b/src/Mod/Sketcher/App/SketchGeometryExtension.cpp @@ -103,12 +103,7 @@ std::unique_ptr SketchGeometryExtension::copy() const auto cpy = std::make_unique(); copyAttributes(cpy.get()); - -#if defined(__GNUC__) && (__GNUC__ <= 4) - return std::move(cpy); -#else return cpy; -#endif } PyObject* SketchGeometryExtension::getPyObject() diff --git a/src/Mod/Sketcher/App/SolverGeometryExtension.cpp b/src/Mod/Sketcher/App/SolverGeometryExtension.cpp index 89c94a2dfe..f0e83cf6bd 100644 --- a/src/Mod/Sketcher/App/SolverGeometryExtension.cpp +++ b/src/Mod/Sketcher/App/SolverGeometryExtension.cpp @@ -53,12 +53,7 @@ std::unique_ptr SolverGeometryExtension::copy() const auto cpy = std::make_unique(); copyAttributes(cpy.get()); - -#if defined(__GNUC__) && (__GNUC__ <= 4) - return std::move(cpy); -#else return cpy; -#endif } PyObject* SolverGeometryExtension::getPyObject() diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.cpp index 05feb2c345..b2d177b524 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.cpp @@ -57,11 +57,7 @@ std::unique_ptr ViewProviderSketchGeometryExtension::co copyAttributes(cpy.get()); -#if defined(__GNUC__) && (__GNUC__ <= 4) - return std::move(cpy); -#else return cpy; -#endif } void ViewProviderSketchGeometryExtension::restoreAttributes(Base::XMLReader& reader) From 81e0b408fa8e7e45eaf70e19ab0b28a36959fe8a Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 11:47:55 +0100 Subject: [PATCH 036/316] App: Use std::numeric_limits and std::numbers instead of defines --- src/App/Datums.cpp | 12 +++++----- src/App/Expression.cpp | 41 +++++++++++++--------------------- src/App/ExpressionParser.l | 8 +++---- src/App/Link.cpp | 3 ++- src/App/ObjectIdentifier.cpp | 17 ++++++++------ src/App/ObjectIdentifier.h | 22 +++++++++++------- src/App/PreCompiled.h | 2 +- src/App/PropertyStandard.cpp | 5 +++-- src/App/PropertyUnits.cpp | 4 ++-- src/App/lex.ExpressionParser.c | 4 ++-- 10 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/App/Datums.cpp b/src/App/Datums.cpp index f595277856..0d315ed859 100644 --- a/src/App/Datums.cpp +++ b/src/App/Datums.cpp @@ -33,10 +33,6 @@ #include "Datums.h" -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - using namespace App; PROPERTY_SOURCE(App::DatumElement, App::GeoFeature) @@ -243,14 +239,16 @@ App::DocumentObjectExecReturn* LocalCoordinateSystem::execute() const std::vector& LocalCoordinateSystem::getSetupData() { + using std::numbers::pi; + static const std::vector setupData = { // clang-format off {App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation()}, - {App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)}, - {App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation(Base::Vector3d(1,-1, 1), M_PI * 2 / 3)}, + {App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1, 1, 1), pi * 2 / 3)}, + {App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation(Base::Vector3d(1,-1, 1), pi * 2 / 3)}, {App::Plane::getClassTypeId(), PlaneRoles[0], tr("XY-plane"), Base::Rotation()}, {App::Plane::getClassTypeId(), PlaneRoles[1], tr("XZ-plane"), Base::Rotation(1.0, 0.0, 0.0, 1.0)}, - {App::Plane::getClassTypeId(), PlaneRoles[2], tr("YZ-plane"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)}, + {App::Plane::getClassTypeId(), PlaneRoles[2], tr("YZ-plane"), Base::Rotation(Base::Vector3d(1, 1, 1), pi * 2 / 3)}, {App::Point::getClassTypeId(), PointRoles[0], tr("Origin"), Base::Rotation()} // clang-format on }; diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index 115db3dd9b..1baebc48bd 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -34,6 +34,8 @@ #include #include +#include +#include #include #include #include @@ -62,19 +64,6 @@ using namespace App; FC_LOG_LEVEL_INIT("Expression", true, true) -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifndef M_E -#define M_E 2.71828182845904523536 -#endif -#ifndef DOUBLE_MAX -# define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ -#endif -#ifndef DOUBLE_MIN -# define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ -#endif - #if defined(_MSC_VER) #define strtoll _strtoi64 #pragma warning(disable : 4003) @@ -336,22 +325,22 @@ static inline int essentiallyInteger(double a, long &l, int &i) { double intpart; if (std::modf(a,&intpart) == 0.0) { if (intpart<0.0) { - if (intpart >= INT_MIN) { + if (intpart >= std::numeric_limits::min()) { i = static_cast(intpart); l = i; return 1; } - if (intpart >= LONG_MIN) { + if (intpart >= std::numeric_limits::min()) { l = static_cast(intpart); return 2; } } - else if (intpart <= INT_MAX) { + else if (intpart <= std::numeric_limits::max()) { i = static_cast(intpart); l = i; return 1; } - else if (intpart <= static_cast(LONG_MAX)) { + else if (intpart <= static_cast(std::numeric_limits::max())) { l = static_cast(intpart); return 2; } @@ -363,12 +352,12 @@ static inline bool essentiallyInteger(double a, long &l) { double intpart; if (std::modf(a,&intpart) == 0.0) { if (intpart<0.0) { - if (intpart >= LONG_MIN) { + if (intpart >= std::numeric_limits::min()) { l = static_cast(intpart); return true; } } - else if (intpart <= static_cast(LONG_MAX)) { + else if (intpart <= static_cast(std::numeric_limits::max())) { l = static_cast(intpart); return true; } @@ -2150,6 +2139,8 @@ Base::Vector3d FunctionExpression::extractVectorArgument( Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std::vector &args) { + using std::numbers::pi; + if(!expr || !expr->getOwner()) _EXPR_THROW("Invalid owner.", expr); @@ -2186,7 +2177,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std Py::Object pyobj = args[0]->getPyValue(); if (PyObject_TypeCheck(pyobj.ptr(), &Base::MatrixPy::Type)) { auto m = static_cast(pyobj.ptr())->value(); - if (fabs(m.determinant()) <= DBL_EPSILON) + if (fabs(m.determinant()) <= std::numeric_limits::epsilon()) _EXPR_THROW("Cannot invert singular matrix.", expr); m.inverseGauss(); return Py::asObject(new Base::MatrixPy(m)); @@ -2227,7 +2218,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std Rotation rotation = Base::Rotation( Vector3d(static_cast(f == MROTATEX), static_cast(f == MROTATEY), static_cast(f == MROTATEZ)), - rotationAngle.getValue() * M_PI / 180.0); + rotationAngle.getValue() * pi / 180.0); Base::Matrix4D rotationMatrix; rotation.getValue(rotationMatrix); @@ -2366,7 +2357,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std switch (f) { case VANGLE: - return Py::asObject(new QuantityPy(new Quantity(vector1.GetAngle(vector2) * 180 / M_PI, Unit::Angle))); + return Py::asObject(new QuantityPy(new Quantity(vector1.GetAngle(vector2) * 180 / pi, Unit::Angle))); case VCROSS: return Py::asObject(new Base::VectorPy(vector1.Cross(vector2))); case VDOT: @@ -2425,7 +2416,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std _EXPR_THROW("Unit must be either empty or an angle.", expr); // Convert value to radians - value *= M_PI / 180.0; + value *= pi / 180.0; unit = Unit(); break; case ACOS: @@ -2434,7 +2425,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std if (!v1.isDimensionless()) _EXPR_THROW("Unit must be empty.", expr); unit = Unit::Angle; - scaler = 180.0 / M_PI; + scaler = 180.0 / pi; break; case EXP: case LOG: @@ -2466,7 +2457,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std if (v1.getUnit() != v2.getUnit()) _EXPR_THROW("Units must be equal.",expr); unit = Unit::Angle; - scaler = 180.0 / M_PI; + scaler = 180.0 / pi; break; case MOD: if (e2.isNone()) diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index 49e6e3672c..bed2fc5f33 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -341,15 +341,15 @@ EXPO [eE][-+]?[0-9]+ {DIGIT}+{EXPO} COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}+ { COUNTCHARS; yylval.ivalue = strtoll( yytext, NULL, 10 ); - if (yylval.ivalue == LLONG_MIN) + if (yylval.ivalue == std::numeric_limits::min) throw Base::UnderflowError("Integer underflow"); - else if (yylval.ivalue == LLONG_MAX) + else if (yylval.ivalue == std::numeric_limits::max) throw Base::OverflowError("Integer overflow"); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; } -"pi" COUNTCHARS; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi -"e" COUNTCHARS; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e +"pi" COUNTCHARS; yylval.constant.fvalue = std::numbers::pi; yylval.constant.name = "pi"; return CONSTANT; // constant pi +"e" COUNTCHARS; yylval.constant.fvalue = std::numbers::e; yylval.constant.name = "e"; return CONSTANT; // constant e "None" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "None"; return CONSTANT; "True" COUNTCHARS; yylval.constant.fvalue = 1; yylval.constant.name = "True"; return CONSTANT; diff --git a/src/App/Link.cpp b/src/App/Link.cpp index 2762040d42..9312aa13d2 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -2624,7 +2624,8 @@ Link::Link() { LINK_PROPS_ADD(LINK_PARAMS_LINK); LinkExtension::initExtension(this); - static const PropertyIntegerConstraint::Constraints s_constraints = {0, INT_MAX, 1}; + static const PropertyIntegerConstraint::Constraints s_constraints = { + 0, std::numeric_limits::max(), 1}; ElementCount.setConstraints(&s_constraints); } diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index 28637d638a..0c80b13672 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -130,7 +130,7 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, } if (!property.empty()) { addComponent(SimpleComponent(property)); - if (index != INT_MAX) { + if (index != std::numeric_limits::max()) { addComponent(ArrayComponent(index)); } } @@ -179,7 +179,7 @@ ObjectIdentifier::ObjectIdentifier(const Property& prop, int index) setDocumentObjectName(docObj); addComponent(SimpleComponent(String(prop.getName()))); - if (index != INT_MAX) { + if (index != std::numeric_limits::max()) { addComponent(ArrayComponent(index)); } } @@ -703,8 +703,9 @@ Py::Object ObjectIdentifier::Component::get(const Py::Object& pyobj) const } else { assert(isRange()); + constexpr int max = std::numeric_limits::max(); Py::Object slice(PySlice_New(Py::Long(begin).ptr(), - end != INT_MAX ? Py::Long(end).ptr() : nullptr, + end != max ? Py::Long(end).ptr() : nullptr, step != 1 ? Py::Long(step).ptr() : nullptr), true); PyObject* r = PyObject_GetItem(pyobj.ptr(), slice.ptr()); @@ -742,8 +743,9 @@ void ObjectIdentifier::Component::set(Py::Object& pyobj, const Py::Object& value } else { assert(isRange()); + constexpr int max = std::numeric_limits::max(); Py::Object slice(PySlice_New(Py::Long(begin).ptr(), - end != INT_MAX ? Py::Long(end).ptr() : nullptr, + end != max ? Py::Long(end).ptr() : nullptr, step != 1 ? Py::Long(step).ptr() : nullptr), true); if (PyObject_SetItem(pyobj.ptr(), slice.ptr(), value.ptr()) < 0) { @@ -770,8 +772,9 @@ void ObjectIdentifier::Component::del(Py::Object& pyobj) const } else { assert(isRange()); + constexpr int max = std::numeric_limits::max(); Py::Object slice(PySlice_New(Py::Long(begin).ptr(), - end != INT_MAX ? Py::Long(end).ptr() : nullptr, + end != max ? Py::Long(end).ptr() : nullptr, step != 1 ? Py::Long(step).ptr() : nullptr), true); if (PyObject_DelItem(pyobj.ptr(), slice.ptr()) < 0) { @@ -897,11 +900,11 @@ void ObjectIdentifier::Component::toString(std::ostream& ss, bool toPython) cons break; case Component::RANGE: ss << '['; - if (begin != INT_MAX) { + if (begin != std::numeric_limits::max()) { ss << begin; } ss << ':'; - if (end != INT_MAX) { + if (end != std::numeric_limits::max()) { ss << end; } if (step != 1) { diff --git a/src/App/ObjectIdentifier.h b/src/App/ObjectIdentifier.h index c62f69c47c..60cb5e19c6 100644 --- a/src/App/ObjectIdentifier.h +++ b/src/App/ObjectIdentifier.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -211,13 +212,13 @@ public: Component(const String& _name = String(), typeEnum _type = SIMPLE, - int begin = INT_MAX, - int end = INT_MAX, + int begin = std::numeric_limits::max(), + int end = std::numeric_limits::max(), int step = 1); // explicit bombs Component(String&& _name, typeEnum _type = SIMPLE, - int begin = INT_MAX, - int end = INT_MAX, + int begin = std::numeric_limits::max(), + int end = std::numeric_limits::max(), int step = 1); // explicit bombs static Component SimpleComponent(const char* _component); @@ -227,7 +228,9 @@ public: static Component ArrayComponent(int _index); - static Component RangeComponent(int _begin, int _end = INT_MAX, int _step = 1); + static Component RangeComponent(int _begin, + int _end = std::numeric_limits::max(), + int _step = 1); static Component MapComponent(const String& _key); static Component MapComponent(String&& _key); @@ -325,7 +328,9 @@ public: return Component::ArrayComponent(_index); } - static Component RangeComponent(int _begin, int _end = INT_MAX, int _step = 1) + static Component RangeComponent(int _begin, + int _end = std::numeric_limits::max(), + int _step = 1) { return Component::RangeComponent(_begin, _end, _step); } @@ -342,11 +347,12 @@ public: explicit ObjectIdentifier(const App::PropertyContainer* _owner = nullptr, const std::string& property = std::string(), - int index = INT_MAX); + int index = std::numeric_limits::max()); ObjectIdentifier(const App::PropertyContainer* _owner, bool localProperty); - ObjectIdentifier(const App::Property& prop, int index = INT_MAX); // explicit bombs + ObjectIdentifier(const App::Property& prop, + int index = std::numeric_limits::max()); // explicit bombs FC_DEFAULT_CTORS(ObjectIdentifier) { diff --git a/src/App/PreCompiled.h b/src/App/PreCompiled.h index 38d675970a..bd32e3058f 100644 --- a/src/App/PreCompiled.h +++ b/src/App/PreCompiled.h @@ -50,7 +50,6 @@ #include #include #include -#include #ifdef FC_OS_WIN32 #include @@ -74,6 +73,7 @@ #include #include #include +#include #include #include #include diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 77f12cd513..4ef6b2e335 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -1250,7 +1250,7 @@ void PropertyFloatConstraint::setPyObject(PyObject* value) double stepSize = valConstr[3]; // need a value > 0 - if (stepSize < DBL_EPSILON) { + if (stepSize < std::numeric_limits::epsilon()) { throw Base::ValueError("Step size must be greater than zero"); } @@ -1282,7 +1282,8 @@ TYPESYSTEM_SOURCE(App::PropertyPrecision, App::PropertyFloatConstraint) //************************************************************************** // Construction/Destruction // -const PropertyFloatConstraint::Constraints PrecisionStandard = {0.0, DBL_MAX, 0.001}; +const PropertyFloatConstraint::Constraints PrecisionStandard = { + 0.0, std::numeric_limits::max(), 0.001}; PropertyPrecision::PropertyPrecision() { diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index f2c30c6dce..153b64bfa2 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #endif #include @@ -37,7 +36,8 @@ using namespace Base; using namespace std; -const PropertyQuantityConstraint::Constraints LengthStandard = {0.0, DBL_MAX, 1.0}; +const PropertyQuantityConstraint::Constraints LengthStandard = { + 0.0, std::numeric_limits::max(), 1.0}; const PropertyQuantityConstraint::Constraints AngleStandard = {-360, 360, 1.0}; //************************************************************************** diff --git a/src/App/lex.ExpressionParser.c b/src/App/lex.ExpressionParser.c index 2916336b02..cc9777e092 100644 --- a/src/App/lex.ExpressionParser.c +++ b/src/App/lex.ExpressionParser.c @@ -9583,12 +9583,12 @@ YY_RULE_SETUP case 138: YY_RULE_SETUP #line 351 "ExpressionParser.l" -COUNTCHARS; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi +COUNTCHARS; yylval.constant.fvalue = std::numbers::pi; yylval.constant.name = "pi"; return CONSTANT; // constant pi YY_BREAK case 139: YY_RULE_SETUP #line 352 "ExpressionParser.l" -COUNTCHARS; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e +COUNTCHARS; yylval.constant.fvalue = std::numbers::e; yylval.constant.name = "e"; return CONSTANT; // constant e YY_BREAK case 140: YY_RULE_SETUP From ae686942a7a56423bf226e7108f5c8a20edba7e1 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 18:59:37 +0100 Subject: [PATCH 037/316] Base: Use std::numeric_limits and std::numbers instead of defines --- src/Base/FileInfo.cpp | 1 - src/Base/Matrix.cpp | 6 ++-- src/Base/MatrixPyImp.cpp | 6 ++-- src/Base/PlacementPyImp.cpp | 3 +- src/Base/PreCompiled.h | 7 +---- src/Base/Quantity.cpp | 8 +++--- src/Base/Quantity.h | 9 ------ src/Base/QuantityLexer.c | 4 +-- src/Base/QuantityParser.c | 14 +++++----- src/Base/QuantityParser.l | 4 +-- src/Base/QuantityParser.y | 14 +++++----- src/Base/QuantityPyImp.cpp | 8 +++--- src/Base/Rotation.cpp | 48 +++++++++++++++++-------------- src/Base/Tools.h | 9 ++---- src/Base/Tools2D.cpp | 12 ++++---- src/Base/Tools2D.h | 20 ++++--------- src/Base/Vector3D.h | 56 +++++++++++-------------------------- tests/src/Base/Tools.cpp | 8 +++--- 18 files changed, 97 insertions(+), 140 deletions(-) diff --git a/src/Base/FileInfo.cpp b/src/Base/FileInfo.cpp index a466d41ef2..024a190efd 100644 --- a/src/Base/FileInfo.cpp +++ b/src/Base/FileInfo.cpp @@ -32,7 +32,6 @@ #if defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD) #include #include -#include #elif defined(FC_OS_WIN32) #include #include diff --git a/src/Base/Matrix.cpp b/src/Base/Matrix.cpp index 065fc1b569..aa0623b2b7 100644 --- a/src/Base/Matrix.cpp +++ b/src/Base/Matrix.cpp @@ -429,7 +429,7 @@ bool Matrix4D::toAxisAngle(Vector3d& rclBase, rfAngle = acos(fCos); // in [0,PI] if (rfAngle > 0.0) { - if (rfAngle < D_PI) { + if (rfAngle < std::numbers::pi) { rclDir.x = (dMtrx4D[2][1] - dMtrx4D[1][2]); rclDir.y = (dMtrx4D[0][2] - dMtrx4D[2][0]); rclDir.z = (dMtrx4D[1][0] - dMtrx4D[0][1]); @@ -1013,8 +1013,8 @@ std::array Matrix4D::decompose() const residualMatrix = rotationMatrix * residualMatrix; // To keep signs of the scale factors equal if (residualMatrix.determinant() < 0) { - rotationMatrix.rotZ(D_PI); - residualMatrix.rotZ(D_PI); + rotationMatrix.rotZ(std::numbers::pi); + residualMatrix.rotZ(std::numbers::pi); } rotationMatrix.inverseGauss(); // extract scale diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index 029f57af2c..9aaa9e8d63 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -218,7 +218,7 @@ PyObject* MatrixPy::number_power_handler(PyObject* self, PyObject* other, PyObje } if (b < 0) { - if (fabs(a.determinant()) > DBL_EPSILON) { + if (fabs(a.determinant()) > std::numeric_limits::epsilon()) { a.inverseGauss(); } else { @@ -667,7 +667,7 @@ PyObject* MatrixPy::invert() { PY_TRY { - if (fabs(getMatrixPtr()->determinant()) > DBL_EPSILON) { + if (fabs(getMatrixPtr()->determinant()) > std::numeric_limits::epsilon()) { getMatrixPtr()->inverseGauss(); Py_Return; } @@ -682,7 +682,7 @@ PyObject* MatrixPy::inverse() { PY_TRY { - if (fabs(getMatrixPtr()->determinant()) > DBL_EPSILON) { + if (fabs(getMatrixPtr()->determinant()) > std::numeric_limits::epsilon()) { Base::Matrix4D m = *getMatrixPtr(); m.inverseGauss(); return new MatrixPy(m); diff --git a/src/Base/PlacementPyImp.cpp b/src/Base/PlacementPyImp.cpp index d57791d69f..8513895157 100644 --- a/src/Base/PlacementPyImp.cpp +++ b/src/Base/PlacementPyImp.cpp @@ -99,7 +99,8 @@ int PlacementPy::PyInit(PyObject* args, PyObject* /*kwd*/) &angle)) { // NOTE: The first parameter defines the translation, the second the rotation axis // and the last parameter defines the rotation angle in degree. - Base::Rotation rot(static_cast(d)->value(), angle / 180.0 * D_PI); + Base::Rotation rot(static_cast(d)->value(), + angle / 180.0 * std::numbers::pi); *getPlacementPtr() = Base::Placement(static_cast(o)->value(), rot); return 0; } diff --git a/src/Base/PreCompiled.h b/src/Base/PreCompiled.h index 1e5fa96dbb..5a26c2e4f6 100644 --- a/src/Base/PreCompiled.h +++ b/src/Base/PreCompiled.h @@ -36,13 +36,8 @@ #include #include #include -#include #include -#ifdef FC_OS_WIN32 -#define _USE_MATH_DEFINES -#endif // FC_OS_WIN32 #include -#include #include #ifdef FC_OS_WIN32 @@ -61,7 +56,6 @@ #include #include #include -#include #endif // STL @@ -69,6 +63,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index 41002c6f66..e566227b17 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -22,9 +22,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#define _USE_MATH_DEFINES #include #include +#include #endif #include @@ -443,8 +443,8 @@ const Quantity Quantity::AngSecond(1.0 / 3600.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); const Quantity Quantity::Degree(1.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // degree (internal standard angle) -const Quantity Quantity::Radian(180 / M_PI, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // radian -const Quantity Quantity::Gon(360.0 / 400.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // gon +const Quantity Quantity::Radian(180 / std::numbers::pi, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // radian +const Quantity Quantity::Gon(360.0 / 400.0, Unit(0, 0, 0, 0, 0, 0, 0, 1)); // gon // === Parser & Scanner stuff =============================================== @@ -568,7 +568,7 @@ Quantity Quantity::parse(const std::string& string) QuantityParser::yy_scan_string(string.c_str()); QuantityParser::StringBufferCleaner cleaner(my_string_buffer); // set the global return variables - QuantResult = Quantity(DOUBLE_MIN); + QuantResult = Quantity(std::numeric_limits::min()); // run the parser QuantityParser::yyparse(); diff --git a/src/Base/Quantity.h b/src/Base/Quantity.h index 94351aa6ea..ccfc33cb96 100644 --- a/src/Base/Quantity.h +++ b/src/Base/Quantity.h @@ -27,15 +27,6 @@ #include "Unit.h" #include -// NOLINTBEGIN -#ifndef DOUBLE_MAX -#define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ -#endif -#ifndef DOUBLE_MIN -#define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ -#endif -// NOLINTEND - namespace Base { class UnitsSchema; diff --git a/src/Base/QuantityLexer.c b/src/Base/QuantityLexer.c index c21f3d9fa8..547916b50b 100644 --- a/src/Base/QuantityLexer.c +++ b/src/Base/QuantityLexer.c @@ -1613,12 +1613,12 @@ YY_RULE_SETUP case 135: YY_RULE_SETUP #line 228 "QuantityParser.l" -{yylval = Quantity(M_PI) ; return NUM;} // constant pi +{yylval = Quantity(std::numbers::pi) ; return NUM;} // constant pi YY_BREAK case 136: YY_RULE_SETUP #line 229 "QuantityParser.l" -{yylval = Quantity(M_E) ; return NUM;} // constant e +{yylval = Quantity(std::numbers::e) ; return NUM;} // constant e YY_BREAK case 137: YY_RULE_SETUP diff --git a/src/Base/QuantityParser.c b/src/Base/QuantityParser.c index bb8ae3915b..e38a289ab8 100644 --- a/src/Base/QuantityParser.c +++ b/src/Base/QuantityParser.c @@ -68,12 +68,12 @@ #define YYSTYPE Quantity #define yyparse Quantity_yyparse #define yyerror Quantity_yyerror - #ifndef DOUBLE_MAX - # define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ - #endif - #ifndef DOUBLE_MIN - # define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ - #endif + + + + + + #line 79 "QuantityParser.c" /* yacc.c:339 */ @@ -1301,7 +1301,7 @@ yyreduce: { case 2: #line 34 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = Quantity(DOUBLE_MIN); /* empty input */ } + { QuantResult = Quantity(std::numeric_limits::min()); /* empty input */ } #line 1305 "QuantityParser.c" /* yacc.c:1646 */ break; diff --git a/src/Base/QuantityParser.l b/src/Base/QuantityParser.l index 1a52592715..bd697d4dea 100644 --- a/src/Base/QuantityParser.l +++ b/src/Base/QuantityParser.l @@ -225,8 +225,8 @@ CGRP '\,'[0-9][0-9][0-9] ","?{DIGIT}+{EXPO}? { yylval = Quantity(num_change(yytext,',','.'));return NUM; } -"pi" {yylval = Quantity(M_PI) ; return NUM;} // constant pi -"e" {yylval = Quantity(M_E) ; return NUM;} // constant e +"pi" {yylval = Quantity(std::numbers::pi) ; return NUM;} // constant pi +"e" {yylval = Quantity(std::numbers::e) ; return NUM;} // constant e "acos" return ACOS; "asin" return ASIN; diff --git a/src/Base/QuantityParser.y b/src/Base/QuantityParser.y index 906b9cab6f..b652151c81 100644 --- a/src/Base/QuantityParser.y +++ b/src/Base/QuantityParser.y @@ -25,12 +25,12 @@ #define YYSTYPE Quantity #define yyparse Quantity_yyparse #define yyerror Quantity_yyerror - #ifndef DOUBLE_MAX - # define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ - #endif - #ifndef DOUBLE_MIN - # define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ - #endif + + + + + + %} @@ -49,7 +49,7 @@ %% - input: { QuantResult = Quantity(DOUBLE_MIN); /* empty input */ } + input: { QuantResult = Quantity(std::numeric_limits::min()); /* empty input */ } | num { QuantResult = $1 ; } | unit { QuantResult = $1 ; } | quantity { QuantResult = $1 ; } diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp index 85078c38f6..5b999d6aaa 100644 --- a/src/Base/QuantityPyImp.cpp +++ b/src/Base/QuantityPyImp.cpp @@ -88,7 +88,7 @@ int QuantityPy::PyInit(PyObject* args, PyObject* /*kwd*/) } PyErr_Clear(); // set by PyArg_ParseTuple() - double f = DOUBLE_MAX; + double f = std::numeric_limits::max(); if (PyArg_ParseTuple(args, "dO!", &f, &(Base::UnitPy::Type), &object)) { *self = Quantity(f, *(static_cast(object)->getUnitPtr())); return 0; @@ -110,7 +110,7 @@ int QuantityPy::PyInit(PyObject* args, PyObject* /*kwd*/) int i8 = 0; PyErr_Clear(); // set by PyArg_ParseTuple() if (PyArg_ParseTuple(args, "|diiiiiiii", &f, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8)) { - if (f < DOUBLE_MAX) { + if (f < std::numeric_limits::max()) { *self = Quantity(f, Unit {static_cast(i1), static_cast(i2), @@ -207,7 +207,7 @@ PyObject* QuantityPy::getValueAs(PyObject* args) } if (!quant.isValid()) { - double f = DOUBLE_MAX; + double f = std::numeric_limits::max(); int i1 = 0; int i2 = 0; int i3 = 0; @@ -218,7 +218,7 @@ PyObject* QuantityPy::getValueAs(PyObject* args) int i8 = 0; PyErr_Clear(); if (PyArg_ParseTuple(args, "d|iiiiiiii", &f, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8)) { - if (f < DOUBLE_MAX) { + if (f < std::numeric_limits::max()) { quant = Quantity(f, Unit {static_cast(i1), static_cast(i2), diff --git a/src/Base/Rotation.cpp b/src/Base/Rotation.cpp index da65a99808..e9e1776e80 100644 --- a/src/Base/Rotation.cpp +++ b/src/Base/Rotation.cpp @@ -245,11 +245,12 @@ void Rotation::setValue(const Matrix4D& m) void Rotation::setValue(const Vector3d& axis, double fAngle) { + using std::numbers::pi; // Taken from // // normalization of the angle to be in [0, 2pi[ _angle = fAngle; - double theAngle = fAngle - floor(fAngle / (2.0 * D_PI)) * (2.0 * D_PI); + double theAngle = fAngle - floor(fAngle / (2.0 * pi)) * (2.0 * pi); this->quat[3] = cos(theAngle / 2.0); Vector3d norm = axis; @@ -691,9 +692,9 @@ void Rotation::setYawPitchRoll(double y, double p, double r) { // The Euler angles (yaw,pitch,roll) are in XY'Z''-notation // convert to radians - y = (y / 180.0) * D_PI; - p = (p / 180.0) * D_PI; - r = (r / 180.0) * D_PI; + y = (y / 180.0) * std::numbers::pi; + p = (p / 180.0) * std::numbers::pi; + r = (r / 180.0) * std::numbers::pi; double c1 = cos(y / 2.0); double s1 = sin(y / 2.0); @@ -710,6 +711,8 @@ void Rotation::setYawPitchRoll(double y, double p, double r) void Rotation::getYawPitchRoll(double& y, double& p, double& r) const { + using std::numbers::pi; + double q00 = quat[0] * quat[0]; double q11 = quat[1] * quat[1]; double q22 = quat[2] * quat[2]; @@ -722,30 +725,31 @@ void Rotation::getYawPitchRoll(double& y, double& p, double& r) const double q23 = quat[2] * quat[3]; double qd2 = 2.0 * (q13 - q02); + // Tolerance copied from OCC "gp_Quaternion.cxx" + constexpr double tolerance = 16 * std::numeric_limits::epsilon(); // handle gimbal lock - if (fabs(qd2 - 1.0) <= 16 * DBL_EPSILON) { // Tolerance copied from OCC "gp_Quaternion.cxx" + if (fabs(qd2 - 1.0) <= tolerance) { // north pole y = 0.0; - p = D_PI / 2.0; + p = pi / 2.0; r = 2.0 * atan2(quat[0], quat[3]); } - else if (fabs(qd2 + 1.0) - <= 16 * DBL_EPSILON) { // Tolerance copied from OCC "gp_Quaternion.cxx" + else if (fabs(qd2 + 1.0) <= tolerance) { // south pole y = 0.0; - p = -D_PI / 2.0; + p = -pi / 2.0; r = 2.0 * atan2(quat[0], quat[3]); } else { y = atan2(2.0 * (q01 + q23), (q00 + q33) - (q11 + q22)); - p = qd2 > 1.0 ? D_PI / 2.0 : (qd2 < -1.0 ? -D_PI / 2.0 : asin(qd2)); + p = qd2 > 1.0 ? pi / 2.0 : (qd2 < -1.0 ? -pi / 2.0 : asin(qd2)); r = atan2(2.0 * (q12 + q03), (q22 + q33) - (q00 + q11)); } // convert to degree - y = (y / D_PI) * 180; - p = (p / D_PI) * 180; - r = (r / D_PI) * 180; + y = (y / pi) * 180; + p = (p / pi) * 180; + r = (r / pi) * 180; } bool Rotation::isSame(const Rotation& q) const @@ -978,15 +982,17 @@ void Rotation::setEulerAngles(EulerSequence theOrder, double theBeta, double theGamma) { + using std::numbers::pi; + if (theOrder == Invalid || theOrder >= EulerSequenceLast) { throw Base::ValueError("invalid euler sequence"); } EulerSequence_Parameters o = translateEulerSequence(theOrder); - theAlpha *= D_PI / 180.0; - theBeta *= D_PI / 180.0; - theGamma *= D_PI / 180.0; + theAlpha *= pi / 180.0; + theBeta *= pi / 180.0; + theGamma *= pi / 180.0; double a = theAlpha; double b = theBeta; @@ -1048,7 +1054,7 @@ void Rotation::getEulerAngles(EulerSequence theOrder, EulerSequence_Parameters o = translateEulerSequence(theOrder); if (o.isTwoAxes) { double sy = sqrt(M(o.i, o.j) * M(o.i, o.j) + M(o.i, o.k) * M(o.i, o.k)); - if (sy > 16 * DBL_EPSILON) { + if (sy > 16 * std::numeric_limits::epsilon()) { theAlpha = atan2(M(o.i, o.j), M(o.i, o.k)); theGamma = atan2(M(o.j, o.i), -M(o.k, o.i)); } @@ -1060,7 +1066,7 @@ void Rotation::getEulerAngles(EulerSequence theOrder, } else { double cy = sqrt(M(o.i, o.i) * M(o.i, o.i) + M(o.j, o.i) * M(o.j, o.i)); - if (cy > 16 * DBL_EPSILON) { + if (cy > 16 * std::numeric_limits::epsilon()) { theAlpha = atan2(M(o.k, o.j), M(o.k, o.k)); theGamma = atan2(M(o.j, o.i), M(o.i, o.i)); } @@ -1081,7 +1087,7 @@ void Rotation::getEulerAngles(EulerSequence theOrder, theGamma = aFirst; } - theAlpha *= 180.0 / D_PI; - theBeta *= 180.0 / D_PI; - theGamma *= 180.0 / D_PI; + theAlpha *= 180.0 / std::numbers::pi; + theBeta *= 180.0 / std::numbers::pi; + theGamma *= 180.0 / std::numbers::pi; } diff --git a/src/Base/Tools.h b/src/Base/Tools.h index f0d767ab00..182d804000 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -28,6 +28,7 @@ #include #endif #include +#include #include #include #include @@ -127,20 +128,16 @@ inline T sgn(T t) return (t > 0) ? T(1) : T(-1); } -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - template inline T toRadians(T d) { - return static_cast((d * M_PI) / 180.0); + return static_cast((d * std::numbers::pi) / 180.0); } template inline T toDegrees(T r) { - return static_cast((r / M_PI) * 180.0); + return static_cast((r / std::numbers::pi) * 180.0); } inline float fromPercent(const long value) diff --git a/src/Base/Tools2D.cpp b/src/Base/Tools2D.cpp index 625f152ca5..59bc296830 100644 --- a/src/Base/Tools2D.cpp +++ b/src/Base/Tools2D.cpp @@ -43,7 +43,7 @@ double Vector2d::GetAngle(const Vector2d& vec) const if ((fDivid < -1e-10) || (fDivid > 1e-10)) { fNum = (*this * vec) / fDivid; if (fNum < -1) { - return D_PI; + return std::numbers::pi; } if (fNum > 1) { return 0.0; @@ -52,7 +52,7 @@ double Vector2d::GetAngle(const Vector2d& vec) const return acos(fNum); } - return -FLOAT_MAX; // division by zero + return -std::numeric_limits::max(); // division by zero } void Vector2d::ProjectToLine(const Vector2d& point, const Vector2d& line) @@ -173,13 +173,13 @@ bool Line2d::Intersect(const Line2d& rclLine, Vector2d& rclV) const m1 = (clV2.y - clV1.y) / (clV2.x - clV1.x); } else { - m1 = DOUBLE_MAX; + m1 = std::numeric_limits::max(); } if (fabs(rclLine.clV2.x - rclLine.clV1.x) > 1e-10) { m2 = (rclLine.clV2.y - rclLine.clV1.y) / (rclLine.clV2.x - rclLine.clV1.x); } else { - m2 = DOUBLE_MAX; + m2 = std::numeric_limits::max(); } if (m1 == m2) { /****** RETURN ERR (parallel lines) *************/ return false; @@ -189,11 +189,11 @@ bool Line2d::Intersect(const Line2d& rclLine, Vector2d& rclV) const b2 = rclLine.clV1.y - m2 * rclLine.clV1.x; // calc intersection - if (m1 == DOUBLE_MAX) { + if (m1 == std::numeric_limits::max()) { rclV.x = clV1.x; rclV.y = m2 * rclV.x + b2; } - else if (m2 == DOUBLE_MAX) { + else if (m2 == std::numeric_limits::max()) { rclV.x = rclLine.clV1.x; rclV.y = m1 * rclV.x + b1; } diff --git a/src/Base/Tools2D.h b/src/Base/Tools2D.h index 9bc10d19c3..a76fd88bb2 100644 --- a/src/Base/Tools2D.h +++ b/src/Base/Tools2D.h @@ -32,15 +32,6 @@ #include #endif -// NOLINTBEGIN -#ifndef DOUBLE_MAX -#define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ -#endif -#ifndef DOUBLE_MIN -#define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ -#endif -// NOLINTEND - namespace Base { @@ -462,8 +453,8 @@ inline bool Line2d::Contains(const Vector2d& rclV) const inline BoundBox2d::BoundBox2d() { - MinX = MinY = DOUBLE_MAX; - MaxX = MaxY = -DOUBLE_MAX; + MinX = MinY = std::numeric_limits::max(); + MaxX = MaxY = -std::numeric_limits::max(); } inline BoundBox2d::BoundBox2d(double fX1, double fY1, double fX2, double fY2) @@ -480,7 +471,8 @@ inline bool BoundBox2d::IsValid() const inline bool BoundBox2d::IsInfinite() const { - return MaxX >= DOUBLE_MAX && MaxY >= DOUBLE_MAX && MinX <= -DOUBLE_MAX && MinY <= -DOUBLE_MAX; + constexpr double max = std::numeric_limits::max(); + return MaxX >= max && MaxY >= max && MinX <= -max && MinY <= -max; } inline bool BoundBox2d::IsEqual(const BoundBox2d& bbox, double tolerance) const @@ -525,8 +517,8 @@ inline Vector2d BoundBox2d::GetCenter() const inline void BoundBox2d::SetVoid() { - MinX = MinY = DOUBLE_MAX; - MaxX = MaxY = -DOUBLE_MAX; + MinX = MinY = std::numeric_limits::max(); + MaxX = MaxY = -std::numeric_limits::max(); } inline void BoundBox2d::Add(const Vector2d& v) diff --git a/src/Base/Vector3D.h b/src/Base/Vector3D.h index 62ad1fb5f1..6b8ec5423c 100644 --- a/src/Base/Vector3D.h +++ b/src/Base/Vector3D.h @@ -24,34 +24,9 @@ #ifndef BASE_VECTOR3D_H #define BASE_VECTOR3D_H - +#include #include -#include - -#ifndef F_PI -#define F_PI 3.1415926f -#endif - -#ifndef D_PI -#define D_PI 3.141592653589793 -#endif - -#ifndef FLOAT_MAX -#define FLOAT_MAX 3.402823466E+38F -#endif - -#ifndef FLOAT_MIN -#define FLOAT_MIN 1.175494351E-38F -#endif - -#ifndef DOUBLE_MAX -#define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ -#endif - -#ifndef DOUBLE_MIN -#define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ -#endif - +#include namespace Base { @@ -60,21 +35,22 @@ struct float_traits { }; +// TODO: Remove these specializations and use the default implementation for all types. template<> struct float_traits { using float_type = float; - [[nodiscard]] static constexpr float_type pi() + [[nodiscard]] static consteval float_type pi() { - return F_PI; + return std::numbers::pi_v; } - [[nodiscard]] static constexpr float_type epsilon() + [[nodiscard]] static consteval float_type epsilon() { - return FLT_EPSILON; + return std::numeric_limits::epsilon(); } - [[nodiscard]] static constexpr float_type maximum() + [[nodiscard]] static consteval float_type maximum() { - return FLT_MAX; + return std::numeric_limits::max(); } }; @@ -82,17 +58,17 @@ template<> struct float_traits { using float_type = double; - [[nodiscard]] static constexpr float_type pi() + [[nodiscard]] static consteval float_type pi() { - return D_PI; + return std::numbers::pi_v; } - [[nodiscard]] static constexpr float_type epsilon() + [[nodiscard]] static consteval float_type epsilon() { - return DBL_EPSILON; + return std::numeric_limits::epsilon(); } - [[nodiscard]] static constexpr float_type maximum() + [[nodiscard]] static consteval float_type maximum() { - return DBL_MAX; + return std::numeric_limits::max(); } }; @@ -275,7 +251,7 @@ template float_type x = v1.x - v2.x; float_type y = v1.y - v2.y; float_type z = v1.z - v2.z; - return static_cast(sqrt((x * x) + (y * y) + (z * z))); + return static_cast(std::sqrt((x * x) + (y * y) + (z * z))); } /// Returns the squared distance between two points diff --git a/tests/src/Base/Tools.cpp b/tests/src/Base/Tools.cpp index 6bcb0b4c0b..39fc056fd9 100644 --- a/tests/src/Base/Tools.cpp +++ b/tests/src/Base/Tools.cpp @@ -39,16 +39,16 @@ TEST(Tools, TestSignum) TEST(Tools, TestRadian) { EXPECT_EQ(Base::toRadians(90), 1); - EXPECT_DOUBLE_EQ(Base::toRadians(180), M_PI); - EXPECT_DOUBLE_EQ(Base::toRadians(90.0), M_PI / 2.0); + EXPECT_DOUBLE_EQ(Base::toRadians(180), std::numbers::pi); + EXPECT_DOUBLE_EQ(Base::toRadians(90.0), std::numbers::pi / 2.0); EXPECT_DOUBLE_EQ(Base::toRadians(0.0), 0.0); } TEST(Tools, TestDegree) { EXPECT_EQ(Base::toDegrees(3), 171); - EXPECT_DOUBLE_EQ(Base::toDegrees(M_PI), 180.0); - EXPECT_DOUBLE_EQ(Base::toDegrees(M_PI / 2.0), 90.0); + EXPECT_DOUBLE_EQ(Base::toDegrees(std::numbers::pi), 180.0); + EXPECT_DOUBLE_EQ(Base::toDegrees(std::numbers::pi / 2.0), 90.0); EXPECT_DOUBLE_EQ(Base::toDegrees(0.0), 0.0); } From 34bc1d45ea7b20fd8fff2cd6a796002cbe835b82 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 18:59:58 +0100 Subject: [PATCH 038/316] Gui: Use std::numeric_limits and std::numbers instead of defines --- src/Gui/CallTips.cpp | 4 +- src/Gui/Clipping.cpp | 15 ++-- src/Gui/DemoMode.cpp | 2 +- src/Gui/Dialogs/DlgParameterImp.cpp | 4 +- src/Gui/EditableDatumLabel.cpp | 4 +- src/Gui/InputField.cpp | 4 +- src/Gui/Inventor/SoFCBackgroundGradient.cpp | 22 +++-- src/Gui/NaviCube.cpp | 52 +++++------ src/Gui/Navigation/NavigationAnimation.cpp | 10 ++- src/Gui/Navigation/NavigationStyle.cpp | 6 +- src/Gui/OverlayManager.cpp | 2 +- src/Gui/PreCompiled.h | 3 +- .../DlgSettingsCacheDirectory.cpp | 2 +- .../DlgSettingsDocumentImp.cpp | 2 +- src/Gui/QuantitySpinBox.cpp | 4 +- src/Gui/Quarter/SoQTQuarterAdaptor.cpp | 8 +- src/Gui/Selection/SelectionFilter.h | 5 +- src/Gui/Selection/SoFCSelectionContext.h | 5 +- src/Gui/ShortcutManager.cpp | 2 +- src/Gui/SoDatumLabel.cpp | 90 +++++++++++-------- src/Gui/SoFCCSysDragger.cpp | 16 ++-- src/Gui/SoTextLabel.cpp | 1 - src/Gui/SoTouchEvents.cpp | 10 ++- src/Gui/SpinBox.cpp | 28 +++--- src/Gui/Transform.cpp | 3 +- src/Gui/VectorListEditor.cpp | 13 +-- src/Gui/View3DInventorRiftViewer.cpp | 4 +- src/Gui/View3DInventorViewer.cpp | 25 +++--- src/Gui/View3DPy.cpp | 4 +- src/Gui/ViewProviderAnnotation.cpp | 2 +- src/Gui/propertyeditor/PropertyItem.cpp | 6 +- src/Gui/propertyeditor/PropertyItem.h | 12 +-- src/Gui/propertyeditor/PropertyModel.cpp | 2 +- 33 files changed, 204 insertions(+), 168 deletions(-) diff --git a/src/Gui/CallTips.cpp b/src/Gui/CallTips.cpp index 93221d7366..e3712f9c22 100644 --- a/src/Gui/CallTips.cpp +++ b/src/Gui/CallTips.cpp @@ -748,7 +748,7 @@ QString CallTipsList::stripWhiteSpace(const QString& str) const { QString stripped = str; QStringList lines = str.split(QLatin1String("\n")); - int minspace=INT_MAX; + int minspace=std::numeric_limits::max(); int line=0; for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it, ++line) { if (it->size() > 0 && line > 0) { @@ -766,7 +766,7 @@ QString CallTipsList::stripWhiteSpace(const QString& str) const } // remove all leading tabs from each line - if (minspace > 0 && minspace < INT_MAX) { + if (minspace > 0 && minspace < std::numeric_limits::max()) { int line=0; QStringList strippedlines; for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it, ++line) { diff --git a/src/Gui/Clipping.cpp b/src/Gui/Clipping.cpp index e56eb2997b..d2495c3720 100644 --- a/src/Gui/Clipping.cpp +++ b/src/Gui/Clipping.cpp @@ -109,20 +109,21 @@ Clipping::Clipping(Gui::View3DInventor* view, QWidget* parent) d->ui.setupUi(this); setupConnections(); - d->ui.clipView->setRange(-INT_MAX, INT_MAX); + constexpr int max = std::numeric_limits::max(); + d->ui.clipView->setRange(-max, max); d->ui.clipView->setSingleStep(0.1f); - d->ui.clipX->setRange(-INT_MAX, INT_MAX); + d->ui.clipX->setRange(-max, max); d->ui.clipX->setSingleStep(0.1f); - d->ui.clipY->setRange(-INT_MAX, INT_MAX); + d->ui.clipY->setRange(-max, max); d->ui.clipY->setSingleStep(0.1f); - d->ui.clipZ->setRange(-INT_MAX, INT_MAX); + d->ui.clipZ->setRange(-max, max); d->ui.clipZ->setSingleStep(0.1f); - d->ui.dirX->setRange(-INT_MAX, INT_MAX); + d->ui.dirX->setRange(-max, max); d->ui.dirX->setSingleStep(0.1f); - d->ui.dirY->setRange(-INT_MAX, INT_MAX); + d->ui.dirY->setRange(-max, max); d->ui.dirY->setSingleStep(0.1f); - d->ui.dirZ->setRange(-INT_MAX, INT_MAX); + d->ui.dirZ->setRange(-max, max); d->ui.dirZ->setSingleStep(0.1f); d->ui.dirZ->setValue(1.0f); diff --git a/src/Gui/DemoMode.cpp b/src/Gui/DemoMode.cpp index e253246b3d..d69224d891 100644 --- a/src/Gui/DemoMode.cpp +++ b/src/Gui/DemoMode.cpp @@ -166,7 +166,7 @@ SbVec3f DemoMode::getDirection(Gui::View3DInventor* view) const SbRotation inv = rot.inverse(); SbVec3f vec(this->viewAxis); inv.multVec(vec, vec); - if (vec.length() < FLT_EPSILON) { + if (vec.length() < std::numeric_limits::epsilon()) { vec = this->viewAxis; } vec.normalize(); diff --git a/src/Gui/Dialogs/DlgParameterImp.cpp b/src/Gui/Dialogs/DlgParameterImp.cpp index 2036e65ee4..8139e994ba 100644 --- a/src/Gui/Dialogs/DlgParameterImp.cpp +++ b/src/Gui/Dialogs/DlgParameterImp.cpp @@ -905,7 +905,7 @@ void ParameterValue::onCreateUIntItem() DlgInputDialogImp::UIntBox); dlg.setWindowTitle(QObject::tr("New unsigned item")); UIntSpinBox* edit = dlg.getUIntBox(); - edit->setRange(0, UINT_MAX); + edit->setRange(0, std::numeric_limits::max()); if (dlg.exec() == QDialog::Accepted) { QString value = edit->text(); unsigned long val = value.toULong(&ok); @@ -1249,7 +1249,7 @@ void ParameterUInt::changeValue() DlgInputDialogImp::UIntBox); dlg.setWindowTitle(QObject::tr("Change value")); UIntSpinBox* edit = dlg.getUIntBox(); - edit->setRange(0, UINT_MAX); + edit->setRange(0, std::numeric_limits::max()); edit->setValue(text(2).toULong()); if (dlg.exec() == QDialog::Accepted) { QString value = edit->text(); diff --git a/src/Gui/EditableDatumLabel.cpp b/src/Gui/EditableDatumLabel.cpp index 5fa800935e..0604bc0a2d 100644 --- a/src/Gui/EditableDatumLabel.cpp +++ b/src/Gui/EditableDatumLabel.cpp @@ -152,8 +152,8 @@ void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj, bool spinBox = new QuantitySpinBox(mdi); spinBox->setUnit(Base::Unit::Length); - spinBox->setMinimum(-INT_MAX); - spinBox->setMaximum(INT_MAX); + spinBox->setMinimum(-std::numeric_limits::max()); + spinBox->setMaximum(std::numeric_limits::max()); spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); spinBox->setKeyboardTracking(false); spinBox->setFocusPolicy(Qt::ClickFocus); // prevent passing focus with tab. diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index 0d432566a9..e53fc5d1c4 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -71,8 +71,8 @@ InputField::InputField(QWidget * parent) ExpressionWidget(), validInput(true), actUnitValue(0), - Maximum(DOUBLE_MAX), - Minimum(-DOUBLE_MAX), + Maximum(std::numeric_limits::max()), + Minimum(-std::numeric_limits::max()), StepSize(1.0), HistorySize(5), SaveSize(5) diff --git a/src/Gui/Inventor/SoFCBackgroundGradient.cpp b/src/Gui/Inventor/SoFCBackgroundGradient.cpp index 37eb809127..323c18a91e 100644 --- a/src/Gui/Inventor/SoFCBackgroundGradient.cpp +++ b/src/Gui/Inventor/SoFCBackgroundGradient.cpp @@ -25,10 +25,8 @@ #ifndef _PreComp_ #include #include -#ifdef FC_OS_WIN32 - #define _USE_MATH_DEFINES -#endif #include +#include #ifdef FC_OS_MACOSX #include #else @@ -39,17 +37,23 @@ #include "SoFCBackgroundGradient.h" static const std::array big_circle = []{ - static const float pi2 = boost::math::constants::two_pi(); + constexpr float pi = std::numbers::pi_v; + constexpr float sqrt2 = std::numbers::sqrt2_v; std::array result; int c = 0; - for (GLfloat i = 0; i < pi2; i += pi2 / 32, c++) { - result[c][0] = M_SQRT2*cosf(i); result[c][1] = M_SQRT2*sinf(i); + for (GLfloat i = 0; i < 2 * pi; i += 2 * pi / 32, c++) { + result[c][0] = sqrt2 * cosf(i); + result[c][1] = sqrt2 * sinf(i); } return result; }(); static const std::array small_oval = []{ - static const float pi2 = boost::math::constants::two_pi(); + constexpr float pi = std::numbers::pi_v; + constexpr float sqrt2 = std::numbers::sqrt2_v; + static const float sqrt1_2 = std::sqrt(1 / 2.F); + std::array result; int c = 0; - for (GLfloat i = 0; i < pi2; i += pi2 / 32, c++) { - result[c][0] = 0.3*M_SQRT2*cosf(i); result[c][1] = M_SQRT1_2*sinf(i); + for (GLfloat i = 0; i < 2 * pi; i += 2 * pi / 32, c++) { + result[c][0] = 0.3 * sqrt2 * cosf(i); + result[c][1] = sqrt1_2 * sinf(i); } return result; }(); diff --git a/src/Gui/NaviCube.cpp b/src/Gui/NaviCube.cpp index 2780fdc703..5cff61a54d 100644 --- a/src/Gui/NaviCube.cpp +++ b/src/Gui/NaviCube.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include -# include +# include # ifdef FC_OS_WIN32 # include # endif @@ -553,7 +553,7 @@ void NaviCubeImplementation::addButtonFace(PickId pickId, const SbVec3f& directi case PickId::DotBackside: { int steps = 16; for (int i = 0; i < steps; i++) { - float angle = 2.0f * M_PI * ((float)i+0.5) / (float)steps; + float angle = 2.0f * std::numbers::pi_v * ((float)i+0.5) / (float)steps; pointData.emplace_back(10. * cos(angle) + 87.); pointData.emplace_back(10. * sin(angle) - 87.); } @@ -659,8 +659,8 @@ void NaviCubeImplementation::setSize(int size) void NaviCubeImplementation::prepare() { - static const float pi = boost::math::constants::pi(); - static const float pi1_2 = boost::math::constants::half_pi(); + constexpr float pi = std::numbers::pi_v; + constexpr float pi1_2 = pi / 2; createCubeFaceTextures(); @@ -817,7 +817,7 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode, float opacity) glOrtho(-2.1, 2.1, -2.1, 2.1, NEARVAL, FARVAL); } else { - const float dim = NEARVAL * float(tan(M_PI / 8.0)) * 1.1; + const float dim = NEARVAL * float(tan(std::numbers::pi / 8.0)) * 1.1; glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL); } glMatrixMode(GL_MODELVIEW); @@ -1010,15 +1010,11 @@ SbRotation NaviCubeImplementation::getNearestOrientation(PickId pickId) { angle *= -1; } - static const float pi = boost::math::constants::pi(); - static const float pi2 = boost::math::constants::two_pi(); - static const float pi1_2 = boost::math::constants::half_pi(); - static const float pi1_3 = boost::math::constants::third_pi(); - static const float pi2_3 = boost::math::constants::two_thirds_pi(); + constexpr float pi = std::numbers::pi_v; // Make angle positive if (angle < 0) { - angle += pi2; + angle += 2 * pi; } // f is a small value used to control orientation priority when the camera is almost exactly between two @@ -1030,23 +1026,23 @@ SbRotation NaviCubeImplementation::getNearestOrientation(PickId pickId) { // Find the angle to rotate to the nearest orientation if (m_Faces[pickId].type == ShapeId::Corner) { // 6 possible orientations for the corners - if (angle <= (M_PI / 6 + f)) { + if (angle <= (pi / 6 + f)) { angle = 0; } - else if (angle <= (M_PI_2 + f)) { - angle = pi1_3; + else if (angle <= (pi / 2 + f)) { + angle = pi / 3; } - else if (angle < (5 * M_PI / 6 - f)) { - angle = pi2_3; + else if (angle < (5 * pi / 6 - f)) { + angle = 2 * pi / 3; } - else if (angle <= (M_PI + M_PI / 6 + f)) { + else if (angle <= (pi + pi / 6 + f)) { angle = pi; } - else if (angle < (M_PI + M_PI_2 - f)) { - angle = pi + pi1_3; + else if (angle < (pi + pi / 2 - f)) { + angle = pi + pi / 3; } - else if (angle < (M_PI + 5 * M_PI / 6 - f)) { - angle = pi + pi2_3; + else if (angle < (pi + 5 * pi / 6 - f)) { + angle = pi + 2 * pi / 3; } else { angle = 0; @@ -1054,17 +1050,17 @@ SbRotation NaviCubeImplementation::getNearestOrientation(PickId pickId) { } else { // 4 possible orientations for the main and edge faces - if (angle <= (M_PI_4 + f)) { + if (angle <= (pi / 4 + f)) { angle = 0; } - else if (angle <= (3 * M_PI_4 + f)) { - angle = pi1_2; + else if (angle <= (3 * pi / 4 + f)) { + angle = pi / 2; } - else if (angle < (M_PI + M_PI_4 - f)) { + else if (angle < (pi + pi / 4 - f)) { angle = pi; } - else if (angle < (M_PI + 3 * M_PI_4 - f)) { - angle = pi + pi1_2; + else if (angle < (pi + 3 * pi / 4 - f)) { + angle = pi + pi / 2; } else { angle = 0; @@ -1089,7 +1085,7 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) } else { PickId pickId = pickFace(x, y); long step = Base::clamp(long(m_NaviStepByTurn), 4L, 36L); - float rotStepAngle = (2 * M_PI) / step; + float rotStepAngle = (2 * std::numbers::pi) / step; if (m_Faces[pickId].type == ShapeId::Main || m_Faces[pickId].type == ShapeId::Edge || m_Faces[pickId].type == ShapeId::Corner) { // Handle the cube faces diff --git a/src/Gui/Navigation/NavigationAnimation.cpp b/src/Gui/Navigation/NavigationAnimation.cpp index 943af87706..29b0529006 100644 --- a/src/Gui/Navigation/NavigationAnimation.cpp +++ b/src/Gui/Navigation/NavigationAnimation.cpp @@ -25,6 +25,8 @@ #include "NavigationAnimation.h" #include +#include + using namespace Gui; NavigationAnimation::NavigationAnimation(NavigationStyle* navigation) @@ -69,8 +71,8 @@ void FixedTimeAnimation::initialize() SbVec3f rotationAxisPost; float angle; SbRotation(navigation->getCamera()->orientation.getValue().inverse() * targetOrientation).getValue(rotationAxisPost, angle); - if (angle > M_PI) { - angle -= float(2 * M_PI); + if (angle > std::numbers::pi) { + angle -= float(2 * std::numbers::pi); } // Convert post-multiplication axis to a pre-multiplication axis @@ -130,9 +132,9 @@ SpinningAnimation::SpinningAnimation(NavigationStyle* navigation, const SbVec3f& : NavigationAnimation(navigation) , rotationAxis(axis) { - setDuration((2 * M_PI / velocity) * 1000.0); + setDuration((2 * std::numbers::pi / velocity) * 1000.0); setStartValue(0.0); - setEndValue(2 * M_PI); + setEndValue(2 * std::numbers::pi); setLoopCount(-1); } diff --git a/src/Gui/Navigation/NavigationStyle.cpp b/src/Gui/Navigation/NavigationStyle.cpp index 3f48db267d..9a0e3fca08 100644 --- a/src/Gui/Navigation/NavigationStyle.cpp +++ b/src/Gui/Navigation/NavigationStyle.cpp @@ -39,6 +39,9 @@ # include #endif +#include +#include + #include #include @@ -719,7 +722,8 @@ void NavigationStyle::zoom(SoCamera * cam, float diffvalue) const float distorigo = newpos.length(); // sqrt(FLT_MAX) == ~ 1e+19, which should be both safe for further // calculations and ok for the end-user and app-programmer. - if (distorigo > float(sqrt(FLT_MAX))) { + float maxDistance = std::sqrt(std::numeric_limits::max()); + if (distorigo > maxDistance) { // do nothing here } else { diff --git a/src/Gui/OverlayManager.cpp b/src/Gui/OverlayManager.cpp index f7b437e54b..41cb897bc8 100644 --- a/src/Gui/OverlayManager.cpp +++ b/src/Gui/OverlayManager.cpp @@ -1819,7 +1819,7 @@ bool OverlayManager::eventFilter(QObject *o, QEvent *ev) } if (hit <= 0) { - d->_lastPos.setX(INT_MAX); + d->_lastPos.setX(std::numeric_limits::max()); if (ev->type() == QEvent::Wheel) { d->wheelDelay = QTime::currentTime().addMSecs(OverlayParams::getDockOverlayWheelDelay()); d->wheelPos = pos; diff --git a/src/Gui/PreCompiled.h b/src/Gui/PreCompiled.h index c3a5f43345..c665016cf7 100644 --- a/src/Gui/PreCompiled.h +++ b/src/Gui/PreCompiled.h @@ -50,8 +50,6 @@ #include #include #include -#include -#include #ifdef FC_OS_WIN32 #include @@ -69,6 +67,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp b/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp index 0c395195e6..9e5bd6b5ba 100644 --- a/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp +++ b/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp @@ -182,7 +182,7 @@ void ApplicationCache::setPeriod(ApplicationCache::Period period) numDays = 365; break; case Period::Never: - numDays = INT_MAX; + numDays = std::numeric_limits::max(); break; } } diff --git a/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp b/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp index 4297531a3f..cb352c303f 100644 --- a/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp +++ b/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp @@ -60,7 +60,7 @@ DlgSettingsDocumentImp::DlgSettingsDocumentImp(QWidget* parent) ui->prefSaveBackupDateFormat->setToolTip(tip); ui->FormatTimeDocsLabel->setText(link); - ui->prefCountBackupFiles->setMaximum(INT_MAX); + ui->prefCountBackupFiles->setMaximum(std::numeric_limits::max()); ui->prefCompression->setMinimum(Z_NO_COMPRESSION); ui->prefCompression->setMaximum(Z_BEST_COMPRESSION); connect(ui->prefLicenseType, qOverload(&QComboBox::currentIndexChanged), diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index abfbb04e34..cc18e8be11 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -66,8 +66,8 @@ public: pendingEmit(false), checkRangeInExpression(false), unitValue(0), - maximum(DOUBLE_MAX), - minimum(-DOUBLE_MAX), + maximum(std::numeric_limits::max()), + minimum(-std::numeric_limits::max()), singleStep(1.0), q_ptr(q) { diff --git a/src/Gui/Quarter/SoQTQuarterAdaptor.cpp b/src/Gui/Quarter/SoQTQuarterAdaptor.cpp index ecfbf9a142..e98bd2d77f 100644 --- a/src/Gui/Quarter/SoQTQuarterAdaptor.cpp +++ b/src/Gui/Quarter/SoQTQuarterAdaptor.cpp @@ -20,6 +20,8 @@ #include "PreCompiled.h" +#include + #include #include #include @@ -303,7 +305,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertOrtho2Perspective(const So SbRotation camrot = in->orientation.getValue(); - float focaldist = float(in->height.getValue() / (2.0*tan(M_PI / 8.0))); // NOLINT + float focaldist = float(in->height.getValue() / (2.0*tan(std::numbers::pi / 8.0))); // NOLINT SbVec3f offset(0,0,focaldist-in->focalDistance.getValue()); @@ -313,7 +315,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertOrtho2Perspective(const So out->focalDistance.setValue(focaldist); // 45° is the default value of this field in SoPerspectiveCamera. - out->heightAngle = (float)(M_PI / 4.0); // NOLINT + out->heightAngle = (float)(std::numbers::pi / 4.0); // NOLINT } void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertPerspective2Ortho(const SoPerspectiveCamera* in, @@ -568,7 +570,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seeksensorCB(void* data, SoSensor bool end = (par == 1.0F); - par = (float)((1.0 - cos(M_PI * par)) * 0.5); // NOLINT + par = (float)((1.0 - cos(std::numbers::pi * par)) * 0.5); // NOLINT thisp->getSoRenderManager()->getCamera()->position = thisp->m_camerastartposition + (thisp->m_cameraendposition - thisp->m_camerastartposition) * par; diff --git a/src/Gui/Selection/SelectionFilter.h b/src/Gui/Selection/SelectionFilter.h index 90d3430bb7..563acd90af 100644 --- a/src/Gui/Selection/SelectionFilter.h +++ b/src/Gui/Selection/SelectionFilter.h @@ -172,8 +172,9 @@ private: struct Node_Slice { - explicit Node_Slice(int min=1,int max=INT_MAX):Min(min),Max(max){} - int Min,Max; + explicit Node_Slice(int min = 1, int max = std::numeric_limits::max()) + : Min(min), Max(max) {} + int Min, Max; }; diff --git a/src/Gui/Selection/SoFCSelectionContext.h b/src/Gui/Selection/SoFCSelectionContext.h index 3d92e00b1a..d9cb345bbf 100644 --- a/src/Gui/Selection/SoFCSelectionContext.h +++ b/src/Gui/Selection/SoFCSelectionContext.h @@ -23,7 +23,6 @@ #ifndef GUI_SOFCSELECTIONCONTEXT_H #define GUI_SOFCSELECTIONCONTEXT_H -#include #include #include #include @@ -79,11 +78,11 @@ struct GuiExport SoFCSelectionContext : SoFCSelectionContextBase } bool isHighlightAll() const{ - return highlightIndex==INT_MAX && (selectionIndex.empty() || isSelectAll()); + return highlightIndex == std::numeric_limits::max() && (selectionIndex.empty() || isSelectAll()); } void highlightAll() { - highlightIndex = INT_MAX; + highlightIndex = std::numeric_limits::max(); } void removeHighlight() { diff --git a/src/Gui/ShortcutManager.cpp b/src/Gui/ShortcutManager.cpp index c7103f7c7a..2f49e8fd7d 100644 --- a/src/Gui/ShortcutManager.cpp +++ b/src/Gui/ShortcutManager.cpp @@ -409,7 +409,7 @@ void ShortcutManager::onTimer() timer.stop(); QAction *found = nullptr; - int priority = -INT_MAX; + int priority = -std::numeric_limits::max(); int seq_length = 0; for (const auto &info : pendingActions) { if (info.action) { diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index fff3978b6f..978a7721a1 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -34,8 +34,8 @@ # endif # include -# include # include +# include # include # include @@ -78,11 +78,12 @@ void glDrawLine(const SbVec3f& p1, const SbVec3f& p2){ glEnd(); } -void glDrawArc(const SbVec3f& center, float radius, float startAngle=0., float endAngle=2.0*M_PI, int countSegments=0){ +void glDrawArc(const SbVec3f& center, float radius, float startAngle=0., + float endAngle=2.0*std::numbers::pi, int countSegments=0){ float range = endAngle - startAngle; if (countSegments == 0){ - countSegments = std::max(6, abs(int(25.0 * range / M_PI))); + countSegments = std::max(6, abs(int(25.0 * range / std::numbers::pi))); } float segment = range / (countSegments-1); @@ -238,11 +239,12 @@ public: private: void getBBox(const std::vector& corners, SbBox3f& box, SbVec3f& center) const { + constexpr float floatMax = std::numeric_limits::max(); if (corners.size() > 1) { - float minX = FLT_MAX; - float minY = FLT_MAX; - float maxX = -FLT_MAX; - float maxY = -FLT_MAX; + float minX = floatMax; + float minY = floatMax; + float maxX = -floatMax; + float maxY = -floatMax; for (SbVec3f it : corners) { minX = (it[0] < minX) ? it[0] : minX; minY = (it[1] < minY) ? it[1] : minY; @@ -288,14 +290,15 @@ private: SbVec3f dir; SbVec3f normal; + constexpr float floatEpsilon = std::numeric_limits::epsilon(); if (label->datumtype.getValue() == SoDatumLabel::DISTANCE) { dir = (p2-p1); } else if (label->datumtype.getValue() == SoDatumLabel::DISTANCEX) { - dir = SbVec3f( (p2[0] - p1[0] >= FLT_EPSILON) ? 1 : -1, 0, 0); + dir = SbVec3f( (p2[0] - p1[0] >= floatEpsilon) ? 1 : -1, 0, 0); } else if (label->datumtype.getValue() == SoDatumLabel::DISTANCEY) { - dir = SbVec3f(0, (p2[1] - p1[1] >= FLT_EPSILON) ? 1 : -1, 0); + dir = SbVec3f(0, (p2[1] - p1[1] >= floatEpsilon) ? 1 : -1, 0); } dir.normalize(); @@ -546,11 +549,11 @@ private: float startangle = atan2f(vc1[1], vc1[0]); float endangle = atan2f(vc2[1], vc2[0]); if (endangle < startangle) { - endangle += 2. * M_PI; + endangle += 2. * std::numbers::pi; } SbVec3f textCenter; - if (endangle - startangle <= M_PI) { + if (endangle - startangle <= std::numbers::pi) { textCenter = ctr + vm * (length + imgHeight); } else { textCenter = ctr - vm * (length + 2. * imgHeight); @@ -628,14 +631,16 @@ SbVec3f SoDatumLabel::getLabelTextCenterDistance(const SbVec3f& p1, const SbVec3 SbVec3f dir; SbVec3f normal; + + constexpr float floatEpsilon = std::numeric_limits::epsilon(); if (datumtype.getValue() == SoDatumLabel::DISTANCE) { dir = (p2 - p1); } else if (datumtype.getValue() == SoDatumLabel::DISTANCEX) { - dir = SbVec3f((p2[0] - p1[0] >= FLT_EPSILON) ? 1 : -1, 0, 0); + dir = SbVec3f((p2[0] - p1[0] >= floatEpsilon) ? 1 : -1, 0, 0); } else if (datumtype.getValue() == SoDatumLabel::DISTANCEY) { - dir = SbVec3f(0, (p2[1] - p1[1] >= FLT_EPSILON) ? 1 : -1, 0); + dir = SbVec3f(0, (p2[1] - p1[1] >= floatEpsilon) ? 1 : -1, 0); } dir.normalize(); @@ -689,7 +694,7 @@ SbVec3f SoDatumLabel::getLabelTextCenterArcLength(const SbVec3f& ctr, const SbVe float endangle = atan2f(vc2[1], vc2[0]); if (endangle < startangle) { - endangle += 2. * M_PI; + endangle += 2. * std::numbers::pi; } // Text location @@ -697,7 +702,7 @@ SbVec3f SoDatumLabel::getLabelTextCenterArcLength(const SbVec3f& ctr, const SbVe vm.normalize(); SbVec3f textCenter; - if (endangle - startangle <= M_PI) { + if (endangle - startangle <= std::numbers::pi) { textCenter = ctr + vm * (length + this->imgHeight); } else { textCenter = ctr - vm * (length + 2. * this->imgHeight); @@ -709,12 +714,13 @@ SbVec3f SoDatumLabel::getLabelTextCenterArcLength(const SbVec3f& ctr, const SbVe void SoDatumLabel::generateDistancePrimitives(SoAction * action, const SbVec3f& p1, const SbVec3f& p2) { SbVec3f dir; + constexpr float floatEpsilon = std::numeric_limits::epsilon(); if (this->datumtype.getValue() == DISTANCE) { dir = (p2-p1); } else if (this->datumtype.getValue() == DISTANCEX) { - dir = SbVec3f( (p2[0] - p1[0] >= FLT_EPSILON) ? 1 : -1, 0, 0); + dir = SbVec3f( (p2[0] - p1[0] >= floatEpsilon) ? 1 : -1, 0, 0); } else if (this->datumtype.getValue() == DISTANCEY) { - dir = SbVec3f(0, (p2[1] - p1[1] >= FLT_EPSILON) ? 1 : -1, 0); + dir = SbVec3f(0, (p2[1] - p1[1] >= floatEpsilon) ? 1 : -1, 0); } dir.normalize(); @@ -957,7 +963,8 @@ void SoDatumLabel::generateArcLengthPrimitives(SoAction * action, const SbVec3f& void SoDatumLabel::generatePrimitives(SoAction * action) { // Initialisation check (needs something more sensible) prevents an infinite loop bug - if (this->imgHeight <= FLT_EPSILON || this->imgWidth <= FLT_EPSILON) { + constexpr float floatEpsilon = std::numeric_limits::epsilon(); + if (this->imgHeight <= floatEpsilon | this->imgWidth <= floatEpsilon) { return; } @@ -1161,6 +1168,8 @@ void SoDatumLabel::getDimension(float scale, int& srcw, int& srch) void SoDatumLabel::drawDistance(const SbVec3f* points, float scale, int srch, float& angle, SbVec3f& textOffset) { + using std::numbers::pi; + float length = this->param1.getValue(); float length2 = this->param2.getValue(); @@ -1168,12 +1177,13 @@ void SoDatumLabel::drawDistance(const SbVec3f* points, float scale, int srch, fl SbVec3f p2 = points[1]; SbVec3f dir; + constexpr float floatEpsilon = std::numeric_limits::epsilon(); if (this->datumtype.getValue() == DISTANCE) { dir = (p2-p1); } else if (this->datumtype.getValue() == DISTANCEX) { - dir = SbVec3f( (p2[0] - p1[0] >= FLT_EPSILON) ? 1 : -1, 0, 0); + dir = SbVec3f( (p2[0] - p1[0] >= floatEpsilon) ? 1 : -1, 0, 0); } else if (this->datumtype.getValue() == DISTANCEY) { - dir = SbVec3f(0, (p2[1] - p1[1] >= FLT_EPSILON) ? 1 : -1, 0); + dir = SbVec3f(0, (p2[1] - p1[1] >= floatEpsilon) ? 1 : -1, 0); } dir.normalize(); @@ -1192,10 +1202,10 @@ void SoDatumLabel::drawDistance(const SbVec3f* points, float scale, int srch, fl // Get magnitude of angle between horizontal angle = atan2f(dir[1],dir[0]); - if (angle > M_PI_2+M_PI/12) { - angle -= (float)M_PI; - } else if (angle <= -M_PI_2+M_PI/12) { - angle += (float)M_PI; + if (angle > pi/2 + pi/12) { + angle -= (float)pi; + } else if (angle <= -pi/2 + pi/12) { + angle += (float)pi; } textOffset = midpos + normal * length + dir * length2; @@ -1291,7 +1301,7 @@ void SoDatumLabel::drawDistance(const SbVec3f* points) float startangle1 = this->param3.getValue(); float radius1 = this->param5.getValue(); SbVec3f center = points[2]; - int countSegments = std::max(6, abs(int(50.0 * range1 / (2 * M_PI)))); + int countSegments = std::max(6, abs(int(50.0 * range1 / (2 * std::numbers::pi)))); double segment = range1 / (countSegments - 1); glBegin(GL_LINE_STRIP); @@ -1307,7 +1317,7 @@ void SoDatumLabel::drawDistance(const SbVec3f* points) float startangle2 = this->param6.getValue(); float radius2 = this->param8.getValue(); SbVec3f center = points[3]; - int countSegments = std::max(6, abs(int(50.0 * range2 / (2 * M_PI)))); + int countSegments = std::max(6, abs(int(50.0 * range2 / (2 * std::numbers::pi)))); double segment = range2 / (countSegments - 1); glBegin(GL_LINE_STRIP); @@ -1342,10 +1352,10 @@ void SoDatumLabel::drawRadiusOrDiameter(const SbVec3f* points, float& angle, SbV // Get magnitude of angle between horizontal angle = atan2f(dir[1],dir[0]); - if (angle > M_PI_2+M_PI/12) { - angle -= (float)M_PI; - } else if (angle <= -M_PI_2+M_PI/12) { - angle += (float)M_PI; + if (angle > std::numbers::pi/2 + std::numbers::pi/12) { + angle -= (float)std::numbers::pi; + } else if (angle <= -std::numbers::pi/2 + std::numbers::pi/12) { + angle += (float)std::numbers::pi; } textOffset = pos; @@ -1401,7 +1411,7 @@ void SoDatumLabel::drawRadiusOrDiameter(const SbVec3f* points, float& angle, SbV float startangle = this->param3.getValue(); float range = this->param4.getValue(); if (range != 0.0) { - int countSegments = std::max(6, abs(int(50.0 * range / (2 * M_PI)))); + int countSegments = std::max(6, abs(int(50.0 * range / (2 * std::numbers::pi)))); double segment = range / (countSegments - 1); glBegin(GL_LINE_STRIP); @@ -1521,6 +1531,8 @@ void SoDatumLabel::drawSymmetric(const SbVec3f* points) void SoDatumLabel::drawArcLength(const SbVec3f* points, float& angle, SbVec3f& textOffset) { + using std::numbers::pi; + SbVec3f ctr = points[0]; SbVec3f p1 = points[1]; SbVec3f p2 = points[2]; @@ -1535,7 +1547,7 @@ void SoDatumLabel::drawArcLength(const SbVec3f* points, float& angle, SbVec3f& t float startangle = atan2f(vc1[1], vc1[0]); float endangle = atan2f(vc2[1], vc2[0]); if (endangle < startangle) { - endangle += 2.0F * (float)M_PI; + endangle += 2.0F * (float)pi; } float range = endangle - startangle; @@ -1547,10 +1559,10 @@ void SoDatumLabel::drawArcLength(const SbVec3f* points, float& angle, SbVec3f& t dir.normalize(); // Get magnitude of angle between horizontal angle = atan2f(dir[1],dir[0]); - if (angle > M_PI_2+M_PI/12) { - angle -= (float)M_PI; - } else if (angle <= -M_PI_2+M_PI/12) { - angle += (float)M_PI; + if (angle > pi/2 + pi/12) { + angle -= (float)pi; + } else if (angle <= -pi/2 + pi/12) { + angle += (float)pi; } // Text location textOffset = getLabelTextCenterArcLength(ctr, p1, p2); @@ -1566,7 +1578,7 @@ void SoDatumLabel::drawArcLength(const SbVec3f* points, float& angle, SbVec3f& t SbVec3f pnt4 = p2 + (length-radius) * vm; // Draw arc - if (range <= M_PI) { + if (range <= pi) { glDrawArc(ctr + (length-radius)*vm, radius, startangle, endangle); } else { @@ -1606,7 +1618,7 @@ void SoDatumLabel::drawText(SoState *state, int srcw, int srch, float angle, con const SbViewVolume & vv = SoViewVolumeElement::get(state); SbVec3f z = vv.zVector(); - bool flip = norm.getValue().dot(z) > FLT_EPSILON; + bool flip = norm.getValue().dot(z) > std::numeric_limits::epsilon(); static bool init = false; static bool npot = false; @@ -1678,7 +1690,7 @@ void SoDatumLabel::drawText(SoState *state, int srcw, int srch, float angle, con // Apply a rotation and translation matrix glTranslatef(textOffset[0], textOffset[1], textOffset[2]); - glRotatef((GLfloat) angle * 180 / M_PI, 0,0,1); + glRotatef((GLfloat) angle * 180 / std::numbers::pi, 0,0,1); glBegin(GL_QUADS); glColor3f(1.F, 1.F, 1.F); diff --git a/src/Gui/SoFCCSysDragger.cpp b/src/Gui/SoFCCSysDragger.cpp index 39130d3b9e..21142b5def 100644 --- a/src/Gui/SoFCCSysDragger.cpp +++ b/src/Gui/SoFCCSysDragger.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #include #include @@ -743,7 +744,7 @@ RDragger::RDragger() } SO_KIT_ADD_FIELD(rotation, (SbVec3f(0.0, 0.0, 1.0), 0.0)); - SO_KIT_ADD_FIELD(rotationIncrement, (M_PI / 8.0)); + SO_KIT_ADD_FIELD(rotationIncrement, (std::numbers::pi / 8.0)); SO_KIT_ADD_FIELD(rotationIncrementCount, (0)); SO_KIT_INIT_INSTANCE(); @@ -808,7 +809,7 @@ SoGroup* RDragger::buildGeometry() unsigned int segments = 15; - float angleIncrement = static_cast(M_PI / 2.0) / static_cast(segments); + float angleIncrement = (std::numbers::pi_v / 2.f) / static_cast(segments); SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement); SbVec3f point(arcRadius, 0.0, 0.0); for (unsigned int index = 0; index <= segments; ++index) { @@ -965,9 +966,10 @@ void RDragger::drag() appendRotation(getStartMotionMatrix(), localRotation, SbVec3f(0.0, 0.0, 0.0))); } - Base::Quantity quantity(static_cast(rotationIncrementCount.getValue()) * (180.0 / M_PI) - * rotationIncrement.getValue(), - Base::Unit::Angle); + Base::Quantity quantity( + static_cast(rotationIncrementCount.getValue()) + * (180.0 / std::numbers::pi)* rotationIncrement.getValue(), + Base::Unit::Angle); QString message = QStringLiteral("%1 %2").arg(QObject::tr("Rotation:"), QString::fromStdString(quantity.getUserString())); @@ -1179,7 +1181,7 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_ADD_FIELD(translationIncrementCountZ, (0)); SO_KIT_ADD_FIELD(rotation, (SbVec3f(0.0, 0.0, 1.0), 0.0)); - SO_KIT_ADD_FIELD(rotationIncrement, (M_PI / 8.0)); + SO_KIT_ADD_FIELD(rotationIncrement, (std::numbers::pi / 8.0)); SO_KIT_ADD_FIELD(rotationIncrementCountX, (0)); SO_KIT_ADD_FIELD(rotationIncrementCountY, (0)); SO_KIT_ADD_FIELD(rotationIncrementCountZ, (0)); @@ -1272,7 +1274,7 @@ SoFCCSysDragger::SoFCCSysDragger() SoRotation* localRotation; SbRotation tempRotation; - auto angle = static_cast(M_PI / 2.0); + auto angle = static_cast(std::numbers::pi / 2.0); // Translator localRotation = SO_GET_ANY_PART(this, "xTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbVec3f(0.0, 0.0, -1.0), angle); diff --git a/src/Gui/SoTextLabel.cpp b/src/Gui/SoTextLabel.cpp index 6e533bea98..07f0839d04 100644 --- a/src/Gui/SoTextLabel.cpp +++ b/src/Gui/SoTextLabel.cpp @@ -31,7 +31,6 @@ # else # include # endif -# include # include # include # include diff --git a/src/Gui/SoTouchEvents.cpp b/src/Gui/SoTouchEvents.cpp index 628fb089c3..8b99c606e8 100644 --- a/src/Gui/SoTouchEvents.cpp +++ b/src/Gui/SoTouchEvents.cpp @@ -22,6 +22,8 @@ #include "PreCompiled.h" +#include + #include #include #include @@ -86,8 +88,8 @@ SoGesturePinchEvent::SoGesturePinchEvent(QPinchGesture* qpinch, QWidget *widget) deltaZoom = qpinch->scaleFactor(); totalZoom = qpinch->totalScaleFactor(); - deltaAngle = -unbranchAngle((qpinch->rotationAngle()-qpinch->lastRotationAngle()) / 180.0 * M_PI); - totalAngle = -qpinch->totalRotationAngle() / 180 * M_PI; + deltaAngle = -unbranchAngle((qpinch->rotationAngle()-qpinch->lastRotationAngle()) / 180.0 * std::numbers::pi); + totalAngle = -qpinch->totalRotationAngle() / 180 * std::numbers::pi; state = SbGestureState(qpinch->state()); @@ -111,7 +113,9 @@ SbBool SoGesturePinchEvent::isSoGesturePinchEvent(const SoEvent *ev) const */ double SoGesturePinchEvent::unbranchAngle(double ang) { - return ang - 2.0 * M_PI * floor((ang + M_PI) / (2.0 * M_PI)); + using std::numbers::pi; + + return ang - 2.0 * pi * floor((ang + pi) / (2.0 * pi)); } diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index 207ec81335..a4fdb99add 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -238,7 +238,7 @@ UnsignedValidator::UnsignedValidator( QObject * parent ) : QValidator( parent ) { b = 0; - t = UINT_MAX; + t = std::numeric_limits::max(); } UnsignedValidator::UnsignedValidator( uint minimum, uint maximum, QObject * parent ) @@ -295,27 +295,31 @@ public: uint mapToUInt( int v ) const { uint ui; - if ( v == INT_MIN ) { + if ( v == std::numeric_limits::min() ) { ui = 0; - } else if ( v == INT_MAX ) { - ui = UINT_MAX; + } else if ( v == std::numeric_limits::max() ) { + ui = std::numeric_limits::max(); } else if ( v < 0 ) { - v -= INT_MIN; ui = (uint)v; + v -= std::numeric_limits::min(); + ui = static_cast(v); } else { - ui = (uint)v; ui -= INT_MIN; + ui = static_cast(v); + ui -= std::numeric_limits::min(); } return ui; } int mapToInt( uint v ) const { int in; - if ( v == UINT_MAX ) { - in = INT_MAX; + if ( v == std::numeric_limits::max() ) { + in = std::numeric_limits::max(); } else if ( v == 0 ) { - in = INT_MIN; - } else if ( v > INT_MAX ) { - v += INT_MIN; in = (int)v; + in = std::numeric_limits::min(); + } else if ( v > std::numeric_limits::max() ) { + v += std::numeric_limits::min(); + in = static_cast(v); } else { - in = v; in += INT_MIN; + in = v; + in += std::numeric_limits::min(); } return in; } }; diff --git a/src/Gui/Transform.cpp b/src/Gui/Transform.cpp index e1d22d1105..b6b0e68b81 100644 --- a/src/Gui/Transform.cpp +++ b/src/Gui/Transform.cpp @@ -378,6 +378,7 @@ Base::Vector3d Transform::getDirection() const Base::Placement Transform::getPlacementData() const { + using std::numbers::pi; int index = ui->rotationInput->currentIndex(); Base::Rotation rot; Base::Vector3d pos; @@ -388,7 +389,7 @@ Base::Placement Transform::getPlacementData() const if (index == 0) { Base::Vector3d dir = getDirection(); - rot.setValue(Base::Vector3d(dir.x,dir.y,dir.z),ui->angle->value().getValue()*D_PI/180.0); + rot.setValue(Base::Vector3d(dir.x,dir.y,dir.z),ui->angle->value().getValue()*pi/180.0); } else if (index == 1) { rot.setYawPitchRoll( diff --git a/src/Gui/VectorListEditor.cpp b/src/Gui/VectorListEditor.cpp index 9450145b7f..0e432920d1 100644 --- a/src/Gui/VectorListEditor.cpp +++ b/src/Gui/VectorListEditor.cpp @@ -255,8 +255,8 @@ QWidget *VectorTableDelegate::createEditor(QWidget *parent, const QStyleOptionVi { auto editor = new QDoubleSpinBox(parent); editor->setDecimals(decimals); - editor->setMinimum(INT_MIN); - editor->setMaximum(INT_MAX); + editor->setMinimum(std::numeric_limits::min()); + editor->setMaximum(std::numeric_limits::max()); editor->setSingleStep(0.1); return editor; @@ -299,11 +299,14 @@ VectorListEditor::VectorListEditor(int decimals, QWidget* parent) ui->tableWidget->setModel(model); ui->widget->hide(); - ui->coordX->setRange(INT_MIN, INT_MAX); + ui->coordX->setRange(std::numeric_limits::min(), + std::numeric_limits::max()); ui->coordX->setDecimals(decimals); - ui->coordY->setRange(INT_MIN, INT_MAX); + ui->coordY->setRange(std::numeric_limits::min(), + std::numeric_limits::max()); ui->coordY->setDecimals(decimals); - ui->coordZ->setRange(INT_MIN, INT_MAX); + ui->coordZ->setRange(std::numeric_limits::min(), + std::numeric_limits::max()); ui->coordZ->setDecimals(decimals); ui->toolButtonMouse->setDisabled(true); diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 7dc8c49a62..3dd1a92647 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -43,7 +43,7 @@ View3DInventorRiftViewer::View3DInventorRiftViewer() : CoinRiftWidget() rotation1 = new SoRotationXYZ ; rotation1->axis.setValue(SoRotationXYZ::X); - rotation1->angle.setValue(-M_PI/2); + rotation1->angle.setValue(-std::numbers::pi/2); workplace->addChild(rotation1); rotation2 = new SoRotationXYZ ; @@ -104,7 +104,7 @@ void View3DInventorRiftViewer::setSceneGraph(SoNode *sceneGraph) void View3DInventorRiftViewer::keyPressEvent(QKeyEvent *event) { static const float increment = 0.02; // move two centimeter per key - static const float rotIncrement = M_PI/4; // move two 90° per key + static const float rotIncrement = std::numbers::pi / 4; // move two 90° per key if (event->key() == Qt::Key_Plus) { diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 3103b1afde..819cce36ab 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # ifdef FC_OS_WIN32 # include # endif @@ -3267,7 +3266,7 @@ void View3DInventorViewer::setCameraType(SoType type) // heightAngle. Setting it to 45 deg also causes an issue with a too // close camera but we don't have this other ugly effect. - static_cast(cam)->heightAngle = (float)(M_PI / 4.0); // NOLINT + static_cast(cam)->heightAngle = (float)(std::numbers::pi / 4.0); // NOLINT } lightRotation->rotation.connectFrom(&cam->orientation); @@ -3426,7 +3425,7 @@ void View3DInventorViewer::viewAll() SoCamera* cam = this->getSoRenderManager()->getCamera(); if (cam && cam->getTypeId().isDerivedFrom(SoPerspectiveCamera::getClassTypeId())) { - static_cast(cam)->heightAngle = (float)(M_PI / 4.0); // NOLINT + static_cast(cam)->heightAngle = (float)(std::numbers::pi / 4.0); // NOLINT } if (isAnimationEnabled()) { @@ -3632,26 +3631,28 @@ void View3DInventorViewer::alignToSelection() angle *= -1; } + using std::numbers::pi; + // Make angle positive if (angle < 0) { - angle += 2 * M_PI; + angle += 2 * pi; } // Find the angle to rotate to the nearest horizontal or vertical alignment with directionX. // f is a small value used to get more deterministic behavior when the camera is at directionX +- 45 degrees. const float f = 0.00001F; - if (angle <= M_PI_4 + f) { + if (angle <= pi/4 + f) { angle = 0; } - else if (angle <= 3 * M_PI_4 + f) { - angle = M_PI_2; + else if (angle <= 3 * pi/4 + f) { + angle = pi/2; } - else if (angle < M_PI + M_PI_4 - f) { - angle = M_PI; + else if (angle < pi + pi/4 - f) { + angle = pi; } - else if (angle < M_PI + 3 * M_PI_4 - f) { - angle = M_PI + M_PI_2; + else if (angle < pi + 3 * pi/4 - f) { + angle = pi + pi/2; } else { angle = 0; @@ -3960,7 +3961,7 @@ void View3DInventorViewer::drawAxisCross() const float NEARVAL = 0.1F; const float FARVAL = 10.0F; - const float dim = NEARVAL * float(tan(M_PI / 8.0)); // FOV is 45 deg (45/360 = 1/8) + const float dim = NEARVAL * float(tan(std::numbers::pi / 8.0)); // FOV is 45 deg (45/360 = 1/8) glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL); diff --git a/src/Gui/View3DPy.cpp b/src/Gui/View3DPy.cpp index b99918ddba..dab66a874b 100644 --- a/src/Gui/View3DPy.cpp +++ b/src/Gui/View3DPy.cpp @@ -658,7 +658,7 @@ Py::Object View3DInventorPy::viewRotateLeft() SbRotation rot = cam->orientation.getValue(); SbVec3f vdir(0, 0, -1); rot.multVec(vdir, vdir); - SbRotation nrot(vdir, (float)M_PI/2); + SbRotation nrot(vdir, (float)std::numbers::pi/2); cam->orientation.setValue(rot*nrot); } catch (const Base::Exception& e) { @@ -681,7 +681,7 @@ Py::Object View3DInventorPy::viewRotateRight() SbRotation rot = cam->orientation.getValue(); SbVec3f vdir(0, 0, -1); rot.multVec(vdir, vdir); - SbRotation nrot(vdir, (float)-M_PI/2); + SbRotation nrot(vdir, (float)-std::numbers::pi/2); cam->orientation.setValue(rot*nrot); } catch (const Base::Exception& e) { diff --git a/src/Gui/ViewProviderAnnotation.cpp b/src/Gui/ViewProviderAnnotation.cpp index c1cb67e3ce..6d04cd2bfa 100644 --- a/src/Gui/ViewProviderAnnotation.cpp +++ b/src/Gui/ViewProviderAnnotation.cpp @@ -155,7 +155,7 @@ void ViewProviderAnnotation::onChanged(const App::Property* prop) } } else if (prop == &Rotation) { - pRotationXYZ->angle = (Rotation.getValue()/360)*(2*M_PI); + pRotationXYZ->angle = (Rotation.getValue()/360)*(2*std::numbers::pi); } else { ViewProviderDocumentObject::onChanged(prop); diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index e07d3fdf20..94bbd659f7 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -968,7 +968,8 @@ QWidget* PropertyIntegerItem::createEditor(QWidget* parent, void PropertyIntegerItem::setEditorData(QWidget* editor, const QVariant& data) const { auto sb = qobject_cast(editor); - sb->setRange(INT_MIN, INT_MAX); + sb->setRange(std::numeric_limits::min(), + std::numeric_limits::max()); sb->setValue(data.toInt()); } @@ -1128,7 +1129,8 @@ QWidget* PropertyFloatItem::createEditor(QWidget* parent, const std::function(editor); - sb->setRange((double)INT_MIN, (double)INT_MAX); + sb->setRange(static_cast(std::numeric_limits::min()), + static_cast(std::numeric_limits::max())); sb->setValue(data.toDouble()); } diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index c27300cadb..b8182c4fd8 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -360,8 +360,8 @@ protected: PropertyIntegerConstraintItem(); private: - int min = INT_MIN; - int max = INT_MAX; + int min = std::numeric_limits::min(); + int max = std::numeric_limits::max(); int steps = 1; }; @@ -434,8 +434,8 @@ protected: PropertyUnitConstraintItem(); private: - double min = double(INT_MIN); - double max = double(INT_MAX); + double min = static_cast(std::numeric_limits::min()); + double max = static_cast(std::numeric_limits::max()); double steps = 0.1; }; @@ -472,8 +472,8 @@ protected: PropertyFloatConstraintItem(); private: - double min = double(INT_MIN); - double max = double(INT_MAX); + double min = static_cast(std::numeric_limits::min()); + double max = static_cast(std::numeric_limits::max()); double steps = 0.1; }; diff --git a/src/Gui/propertyeditor/PropertyModel.cpp b/src/Gui/propertyeditor/PropertyModel.cpp index bb5e565f8d..aa93d2563a 100644 --- a/src/Gui/propertyeditor/PropertyModel.cpp +++ b/src/Gui/propertyeditor/PropertyModel.cpp @@ -96,7 +96,7 @@ bool PropertyModel::setData(const QModelIndex& index, const QVariant& value, int // now? double d = data.toDouble(); double v = value.toDouble(); - if (fabs(d - v) > DBL_EPSILON) { + if (fabs(d - v) > std::numeric_limits::epsilon()) { return item->setData(value); } } From 984c0d43fdb954dccfdca6dd29b168962ba4017b Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:00:11 +0100 Subject: [PATCH 039/316] Assembly: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Assembly/App/AssemblyObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Assembly/App/AssemblyObject.cpp b/src/Mod/Assembly/App/AssemblyObject.cpp index a7164bad36..ebae1cfedb 100644 --- a/src/Mod/Assembly/App/AssemblyObject.cpp +++ b/src/Mod/Assembly/App/AssemblyObject.cpp @@ -1125,7 +1125,7 @@ std::shared_ptr AssemblyObject::makeMbdJointOfType(App::DocumentObjec } else if (type == JointType::Angle) { double angle = fabs(Base::toRadians(getJointDistance(joint))); - if (fmod(angle, 2 * M_PI) < Precision::Confusion()) { + if (fmod(angle, 2 * std::numbers::pi) < Precision::Confusion()) { return CREATE::With(); } else { From a7b71335b74b07c6dfe06e4312c94760b5da32db Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:00:18 +0100 Subject: [PATCH 040/316] CAM: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/CAM/App/Area.cpp | 12 ++++++------ src/Mod/CAM/App/PathSegmentWalker.cpp | 18 +++++------------- src/Mod/CAM/App/Voronoi.cpp | 17 ++++++++--------- src/Mod/CAM/App/Voronoi.h | 10 ++-------- src/Mod/CAM/App/VoronoiEdgePyImp.cpp | 14 ++++++++------ src/Mod/CAM/Gui/ViewProviderPath.cpp | 4 ++-- src/Mod/CAM/PathSimulator/AppGL/linmath.h | 2 +- src/Mod/CAM/libarea/Adaptive.cpp | 17 +++++++++-------- src/Mod/CAM/libarea/Adaptive.hpp | 4 ---- src/Mod/CAM/libarea/Box2D.h | 2 +- src/Mod/CAM/libarea/Curve.h | 2 +- src/Mod/CAM/libarea/kurve/geometry.h | 2 +- 12 files changed, 44 insertions(+), 60 deletions(-) diff --git a/src/Mod/CAM/App/Area.cpp b/src/Mod/CAM/App/Area.cpp index df87a8f527..82892eef4d 100644 --- a/src/Mod/CAM/App/Area.cpp +++ b/src/Mod/CAM/App/Area.cpp @@ -26,7 +26,6 @@ #define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNING #ifndef _PreComp_ -#include #include #include @@ -452,7 +451,7 @@ void Area::addWire(CArea& area, if (reversed) { type = -type; } - if (fabs(first - last) > M_PI) { + if (fabs(first - last) > std::numbers::pi) { // Split arc(circle) larger than half circle. Because gcode // can't handle full circle? gp_Pnt mid = curve.Value((last - first) * 0.5 + first); @@ -1221,7 +1220,8 @@ struct WireJoiner info.iEnd[i] = info.iStart[i] = (int)adjacentList.size(); // populate adjacent list - for (auto vit = vmap.qbegin(bgi::nearest(pt[i], INT_MAX)); vit != vmap.qend(); + constexpr int intMax = std::numeric_limits::max(); + for (auto vit = vmap.qbegin(bgi::nearest(pt[i], intMax)); vit != vmap.qend(); ++vit) { ++rcount; if (vit->pt().SquareDistance(pt[i]) > tol) { @@ -2631,7 +2631,7 @@ TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_POCK for (int j = 0; j < steps; ++j, offset += stepover) { Point p1(-r, offset), p2(r, offset); if (a > Precision::Confusion()) { - double r = a * M_PI / 180.0; + double r = a * std::numbers::pi / 180.0; p1.Rotate(r); p2.Rotate(r); } @@ -3703,7 +3703,7 @@ std::list Area::sortWires(const std::list& shapes, double max_dist = sort_mode == SortModeGreedy ? threshold * threshold : 0; while (!shape_list.empty()) { AREA_TRACE("sorting " << shape_list.size() << ' ' << AREA_XYZ(pstart)); - double best_d = DBL_MAX; + double best_d = std::numeric_limits::max(); auto best_it = shape_list.begin(); for (auto it = best_it; it != shape_list.end(); ++it) { double d; @@ -4155,7 +4155,7 @@ void Area::toPath(Toolpath& path, } } - if (fabs(first - last) > M_PI) { + if (fabs(first - last) > std::numbers::pi) { // Split arc(circle) larger than half circle. gp_Pnt mid = curve.Value((last - first) * 0.5 + first); addGArc(verbose, diff --git a/src/Mod/CAM/App/PathSegmentWalker.cpp b/src/Mod/CAM/App/PathSegmentWalker.cpp index 2cd883ef09..5b9a54b6cb 100644 --- a/src/Mod/CAM/App/PathSegmentWalker.cpp +++ b/src/Mod/CAM/App/PathSegmentWalker.cpp @@ -31,14 +31,6 @@ #define ARC_MIN_SEGMENTS 20.0 // minimum # segments to interpolate an arc -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef M_PI_2 -#define M_PI_2 1.57079632679489661923 /* pi/2 */ -#endif - namespace Path { @@ -195,7 +187,7 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start if (nrot != lrot) { double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); - double angle = amax / 180 * M_PI; + double angle = amax / 180 * std::numbers::pi; int segments = std::max(ARC_MIN_SEGMENTS, 3.0 / (deviation / angle)); double da = (a - A) / segments; @@ -257,16 +249,16 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start Base::Vector3d anorm = (last0 - center0) % (next0 - center0); if (anorm.*pz < 0) { if (name == "G3" || name == "G03") { - angle = M_PI * 2 - angle; + angle = std::numbers::pi * 2 - angle; } } else if (anorm.*pz > 0) { if (name == "G2" || name == "G02") { - angle = M_PI * 2 - angle; + angle = std::numbers::pi * 2 - angle; } } else if (angle == 0) { - angle = M_PI * 2; + angle = std::numbers::pi * 2; } double amax = std::max(fmod(fabs(a - A), 360), @@ -337,7 +329,7 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start if (nrot != lrot) { double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); - double angle = amax / 180 * M_PI; + double angle = amax / 180 * std::numbers::pi; int segments = std::max(ARC_MIN_SEGMENTS, 3.0 / (deviation / angle)); double da = (a - A) / segments; diff --git a/src/Mod/CAM/App/Voronoi.cpp b/src/Mod/CAM/App/Voronoi.cpp index 55aeb601c3..0ccad2e191 100644 --- a/src/Mod/CAM/App/Voronoi.cpp +++ b/src/Mod/CAM/App/Voronoi.cpp @@ -22,8 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#define _USE_MATH_DEFINES -#include #endif #include @@ -260,10 +258,10 @@ double Voronoi::diagram_type::angleOfSegment(int i, Voronoi::diagram_type::angle double ang = 0; if (p0.x() == p1.x()) { if (p0.y() < p1.y()) { - ang = M_PI_2; + ang = std::numbers::pi / 2; } else { - ang = -M_PI_2; + ang = -std::numbers::pi / 2; } } else { @@ -292,7 +290,8 @@ bool Voronoi::diagram_type::segmentsAreConnected(int i, int j) const void Voronoi::colorColinear(Voronoi::color_type color, double degree) { - double rad = degree * M_PI / 180; + using std::numbers::pi; + double rad = degree * pi / 180; Voronoi::diagram_type::angle_map_t angle; int psize = vd->points.size(); @@ -306,11 +305,11 @@ void Voronoi::colorColinear(Voronoi::color_type color, double degree) double a0 = vd->angleOfSegment(i0, &angle); double a1 = vd->angleOfSegment(i1, &angle); double a = a0 - a1; - if (a > M_PI_2) { - a -= M_PI; + if (a > pi / 2) { + a -= pi; } - else if (a < -M_PI_2) { - a += M_PI; + else if (a < -pi / 2) { + a += pi; } if (fabs(a) < rad) { it->color(color); diff --git a/src/Mod/CAM/App/Voronoi.h b/src/Mod/CAM/App/Voronoi.h index d7a4ac5c8c..ff77698bfb 100644 --- a/src/Mod/CAM/App/Voronoi.h +++ b/src/Mod/CAM/App/Voronoi.h @@ -22,7 +22,6 @@ #ifndef PATH_VORONOI_H #define PATH_VORONOI_H -#include #include #include #include @@ -33,11 +32,6 @@ #include #include -#if (SIZE_MAX == UINT_MAX) -#define PATH_VORONOI_COLOR_MASK 0x07FFFFFFul -#else -#define PATH_VORONOI_COLOR_MASK 0x07FFFFFFFFFFFFFFul -#endif namespace Path { @@ -51,8 +45,8 @@ public: ~Voronoi() override; using color_type = std::size_t; - static const int InvalidIndex = INT_MAX; - static const color_type ColorMask = PATH_VORONOI_COLOR_MASK; + static const int InvalidIndex = std::numeric_limits::max(); + static const color_type ColorMask = std::numeric_limits::max() >> 5; // types using coordinate_type = double; diff --git a/src/Mod/CAM/App/VoronoiEdgePyImp.cpp b/src/Mod/CAM/App/VoronoiEdgePyImp.cpp index 9015e49d52..bf47258083 100644 --- a/src/Mod/CAM/App/VoronoiEdgePyImp.cpp +++ b/src/Mod/CAM/App/VoronoiEdgePyImp.cpp @@ -466,12 +466,12 @@ PyObject* VoronoiEdgePy::isBorderline(PyObject* args) PyObject* VoronoiEdgePy::toShape(PyObject* args) { double z0 = 0.0; - double z1 = DBL_MAX; + double z1 = std::numeric_limits::max(); int dbg = 0; if (!PyArg_ParseTuple(args, "|ddp", &z0, &z1, &dbg)) { throw Py::RuntimeError("no, one or two arguments of type double accepted"); } - if (z1 == DBL_MAX) { + if (z1 == std::numeric_limits::max()) { z1 = z0; } VoronoiEdge* e = getVoronoiEdgePtr(); @@ -688,6 +688,8 @@ PyObject* VoronoiEdgePy::getDistances(PyObject* args) PyObject* VoronoiEdgePy::getSegmentAngle(PyObject* args) { + using std::numbers::pi; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); if (e->ptr->cell()->contains_segment() && e->ptr->twin()->cell()->contains_segment()) { @@ -697,11 +699,11 @@ PyObject* VoronoiEdgePy::getSegmentAngle(PyObject* args) double a0 = e->dia->angleOfSegment(i0); double a1 = e->dia->angleOfSegment(i1); double a = a0 - a1; - if (a > M_PI_2) { - a -= M_PI; + if (a > pi / 2) { + a -= pi; } - else if (a < -M_PI_2) { - a += M_PI; + else if (a < -pi / 2) { + a += pi; } return Py::new_reference_to(Py::Float(a)); } diff --git a/src/Mod/CAM/Gui/ViewProviderPath.cpp b/src/Mod/CAM/Gui/ViewProviderPath.cpp index 25276bdacb..44698df05a 100644 --- a/src/Mod/CAM/Gui/ViewProviderPath.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPath.cpp @@ -183,11 +183,11 @@ ViewProviderPath::ViewProviderPath() ShowCountConstraints.LowerBound = 0; - ShowCountConstraints.UpperBound = INT_MAX; + ShowCountConstraints.UpperBound = std::numeric_limits::max(); ShowCountConstraints.StepSize = 1; ShowCount.setConstraints(&ShowCountConstraints); StartIndexConstraints.LowerBound = 0; - StartIndexConstraints.UpperBound = INT_MAX; + StartIndexConstraints.UpperBound = std::numeric_limits::max(); StartIndexConstraints.StepSize = 1; StartIndex.setConstraints(&StartIndexConstraints); ADD_PROPERTY_TYPE(StartPosition, diff --git a/src/Mod/CAM/PathSimulator/AppGL/linmath.h b/src/Mod/CAM/PathSimulator/AppGL/linmath.h index 7ebdc2cfba..c0feb2caa0 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/linmath.h +++ b/src/Mod/CAM/PathSimulator/AppGL/linmath.h @@ -5,7 +5,7 @@ #define LINMATH_H #include -#include +#include #ifdef LINMATH_NO_INLINE #define LINMATH_H_FUNC static diff --git a/src/Mod/CAM/libarea/Adaptive.cpp b/src/Mod/CAM/libarea/Adaptive.cpp index 3b45c3254a..535d25efe4 100644 --- a/src/Mod/CAM/libarea/Adaptive.cpp +++ b/src/Mod/CAM/libarea/Adaptive.cpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace ClipperLib { @@ -116,7 +117,7 @@ inline double Angle3Points(const DoublePoint& p1, const DoublePoint& p2, const D double t1 = atan2(p2.Y - p1.Y, p2.X - p1.X); double t2 = atan2(p3.Y - p2.Y, p3.X - p2.X); double a = fabs(t2 - t1); - return min(a, 2 * M_PI - a); + return min(a, 2 * std::numbers::pi - a); } inline DoublePoint DirectionV(const IntPoint& pt1, const IntPoint& pt2) @@ -1096,8 +1097,8 @@ private: class Interpolation { public: - const double MIN_ANGLE = -M_PI / 4; - const double MAX_ANGLE = M_PI / 4; + const double MIN_ANGLE = -std::numbers::pi / 4; + const double MAX_ANGLE = std::numbers::pi / 4; void clear() { @@ -1542,7 +1543,7 @@ double Adaptive2d::CalcCutArea(Clipper& clip, double minFi = fi1; double maxFi = fi2; if (maxFi < minFi) { - maxFi += 2 * M_PI; + maxFi += 2 * std::numbers::pi; } if (preventConventional && interPathLen >= RESOLUTION_FACTOR) { @@ -2359,7 +2360,7 @@ bool Adaptive2d::MakeLeadPath(bool leadIn, IntPoint(currentPoint.X + nextDir.X * stepSize, currentPoint.Y + nextDir.Y * stepSize); Path checkPath; double adaptFactor = 0.4; - double alfa = M_PI / 64; + double alfa = std::numbers::pi / 64; double pathLen = 0; checkPath.push_back(nextPoint); for (int i = 0; i < 10000; i++) { @@ -2802,7 +2803,7 @@ void Adaptive2d::ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths) IntPoint clp; // to store closest point vector gyro; // used to average tool direction vector angleHistory; // use to predict deflection angle - double angle = M_PI; + double angle = std::numbers::pi; engagePoint = toolPos; Interpolation interp; // interpolation instance @@ -2846,7 +2847,7 @@ void Adaptive2d::ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths) } } - angle = M_PI / 4; // initial pass angle + angle = std::numbers::pi / 4; // initial pass angle bool recalcArea = false; double cumulativeCutArea = 0; // init gyro @@ -2991,7 +2992,7 @@ void Adaptive2d::ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths) rotateStep++; // if new tool pos. outside boundary rotate until back in recalcArea = true; - newToolDir = rotate(newToolDir, M_PI / 90); + newToolDir = rotate(newToolDir, std::numbers::pi / 90); newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), long(toolPos.Y + newToolDir.Y * stepScaled)); } diff --git a/src/Mod/CAM/libarea/Adaptive.hpp b/src/Mod/CAM/libarea/Adaptive.hpp index 497aa2792a..9f57b5407f 100644 --- a/src/Mod/CAM/libarea/Adaptive.hpp +++ b/src/Mod/CAM/libarea/Adaptive.hpp @@ -36,10 +36,6 @@ #define __LONG_MAX__ 2147483647 #endif -#ifndef M_PI -#define M_PI 3.141592653589793238 -#endif - // #define DEV_MODE #define NTOL 1.0e-7 // numeric tolerance diff --git a/src/Mod/CAM/libarea/Box2D.h b/src/Mod/CAM/libarea/Box2D.h index 23ee202ac7..b0c02d9e3f 100644 --- a/src/Mod/CAM/libarea/Box2D.h +++ b/src/Mod/CAM/libarea/Box2D.h @@ -29,7 +29,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once #include // for memcpy() prototype -#include // for sqrt() prototype +#include // for sqrt() prototype class CBox2D { diff --git a/src/Mod/CAM/libarea/Curve.h b/src/Mod/CAM/libarea/Curve.h index f6f62eee14..35ea485a52 100644 --- a/src/Mod/CAM/libarea/Curve.h +++ b/src/Mod/CAM/libarea/Curve.h @@ -31,7 +31,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include +#include #include "Point.h" #include "Box2D.h" diff --git a/src/Mod/CAM/libarea/kurve/geometry.h b/src/Mod/CAM/libarea/kurve/geometry.h index 88cbbf5b1a..8c8dc5a6ca 100644 --- a/src/Mod/CAM/libarea/kurve/geometry.h +++ b/src/Mod/CAM/libarea/kurve/geometry.h @@ -17,7 +17,7 @@ #endif #endif -#include +#include #include #include #include From fd28d6f27f3e7a69190c58856611b9e1ff315d01 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:00:34 +0100 Subject: [PATCH 041/316] Drawing: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Drawing/App/DrawingExport.cpp | 14 +++++++++----- src/Mod/Drawing/Gui/TaskOrthoViews.cpp | 10 +++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Mod/Drawing/App/DrawingExport.cpp b/src/Mod/Drawing/App/DrawingExport.cpp index 1f654caf60..516458e917 100644 --- a/src/Mod/Drawing/App/DrawingExport.cpp +++ b/src/Mod/Drawing/App/DrawingExport.cpp @@ -207,9 +207,10 @@ void SVGOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) } // arc of circle else { + using std::numbers::pi; // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths - char xar = '0'; // x-axis-rotation - char las = (l - f > D_PI) ? '1' : '0'; // large-arc-flag + char xar = '0'; // x-axis-rotation + char las = (l - f > pi) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << ""; @@ -255,7 +256,8 @@ void SVGOutput::printEllipse(const BRepAdaptor_Curve& c, int id, std::ostream& o } // arc of ellipse else { - char las = (l - f > D_PI) ? '1' : '0'; // large-arc-flag + using std::numbers::pi; + char las = (l - f > pi) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << "" << std::endl; @@ -460,6 +462,8 @@ void DXFOutput::printHeader(std::ostream& out) void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) { + using std::numbers::pi; + gp_Circ circ = c.Circle(); const gp_Pnt& p = circ.Location(); double r = circ.Radius(); @@ -502,8 +506,8 @@ void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) double bx = e.X() - p.X(); double by = e.Y() - p.Y(); - double start_angle = atan2(ay, ax) * 180 / D_PI; - double end_angle = atan2(by, bx) * 180 / D_PI; + double start_angle = atan2(ay, ax) * 180 / pi; + double end_angle = atan2(by, bx) * 180 / pi; if (a > 0) { double temp = start_angle; diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.cpp b/src/Mod/Drawing/Gui/TaskOrthoViews.cpp index 98d8a2897f..319dbcb186 100644 --- a/src/Mod/Drawing/Gui/TaskOrthoViews.cpp +++ b/src/Mod/Drawing/Gui/TaskOrthoViews.cpp @@ -256,7 +256,7 @@ void orthoview::set_projection(const gp_Ax2& cs) // angle between desired projection and actual projection float rotation = X_dir.Angle(actual_X); - if (rotation != 0 && abs(M_PI - rotation) > 0.05) { + if (rotation != 0 && abs(std::numbers::pi - rotation) > 0.05) { if (!Z_dir.IsEqual(actual_X.Crossed(X_dir), 0.05)) { rotation = -rotation; } @@ -266,7 +266,7 @@ void orthoview::set_projection(const gp_Ax2& cs) // this_view->Direction.setValue(Z_dir.X(), Z_dir.Y(), Z_dir.Z()); this_view->Direction.setValue(x, y, z); - this_view->Rotation.setValue(180 * rotation / M_PI); + this_view->Rotation.setValue(180 * rotation / std::numbers::pi); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -613,8 +613,8 @@ void OrthoViews::set_orientation(int index) // set orientation of single view dir = primary.XDirection(); n = -views[index]->rel_y; } - - rotation = n * rotate_coeff * M_PI / 2; // rotate_coeff is -1 or 1 for 1st or 3rd angle + // rotate_coeff is -1 or 1 for 1st or 3rd angle + rotation = n * rotate_coeff * std::numbers::pi / 2; cs = primary.Rotated(gp_Ax1(gp_Pnt(0, 0, 0), dir), rotation); views[index]->set_projection(cs); } @@ -780,7 +780,7 @@ void OrthoViews::set_Axo(int rel_x, rotations[1] = -0.6156624905260762; } else { - rotations[0] = 1.3088876392502007 - M_PI / 2; + rotations[0] = 1.3088876392502007 - std::numbers::pi / 2; rotations[1] = -0.6156624905260762; } From d0dc4c00ef3535f6650cc34cb8ce3517cf87e32b Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:00:41 +0100 Subject: [PATCH 042/316] FEM: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Fem/App/FemConstraint.cpp | 5 +- src/Mod/Fem/App/FemConstraintTransform.cpp | 8 ++- src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp | 4 +- src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp | 25 +++---- src/Mod/Fem/Gui/TaskFemConstraintContact.cpp | 8 +-- .../Fem/Gui/TaskFemConstraintDisplacement.cpp | 25 +++---- .../Gui/TaskFemConstraintFluidBoundary.cpp | 19 +++--- src/Mod/Fem/Gui/TaskFemConstraintForce.cpp | 2 +- src/Mod/Fem/Gui/TaskFemConstraintGear.cpp | 4 +- src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp | 8 +-- src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp | 2 +- src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp | 8 +-- .../Fem/Gui/TaskFemConstraintRigidBody.cpp | 65 ++++++++++--------- src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp | 4 +- .../Fem/Gui/TaskFemConstraintTemperature.cpp | 6 +- .../Fem/Gui/TaskFemConstraintTransform.cpp | 17 ++--- ...ViewProviderFemConstraintFluidBoundary.cpp | 6 +- .../Gui/ViewProviderFemConstraintForce.cpp | 2 +- .../Fem/Gui/ViewProviderFemConstraintGear.cpp | 6 +- .../Gui/ViewProviderFemConstraintPressure.cpp | 2 +- .../Gui/ViewProviderFemConstraintPulley.cpp | 32 ++++----- .../Fem/Gui/ViewProviderFemPostFunction.cpp | 29 +++++---- 22 files changed, 153 insertions(+), 134 deletions(-) diff --git a/src/Mod/Fem/App/FemConstraint.cpp b/src/Mod/Fem/App/FemConstraint.cpp index 6e48bdc599..322e824335 100644 --- a/src/Mod/Fem/App/FemConstraint.cpp +++ b/src/Mod/Fem/App/FemConstraint.cpp @@ -75,7 +75,10 @@ using Adaptor3d_HSurface = Adaptor3d_Surface; using BRepAdaptor_HSurface = BRepAdaptor_Surface; #endif -static const App::PropertyFloatConstraint::Constraints scaleConstraint = {0.0, DBL_MAX, 0.1}; +static const App::PropertyFloatConstraint::Constraints scaleConstraint = { + 0.0, + std::numeric_limits::max(), + 0.1}; PROPERTY_SOURCE(Fem::Constraint, App::DocumentObject) diff --git a/src/Mod/Fem/App/FemConstraintTransform.cpp b/src/Mod/Fem/App/FemConstraintTransform.cpp index b1947866ab..aaa7299009 100644 --- a/src/Mod/Fem/App/FemConstraintTransform.cpp +++ b/src/Mod/Fem/App/FemConstraintTransform.cpp @@ -116,12 +116,14 @@ namespace Base::Rotation anglesToRotation(double xAngle, double yAngle, double zAngle) { + using std::numbers::pi; + static Base::Vector3d a(1, 0, 0); static Base::Vector3d b(0, 1, 0); static int count = 0; - double xRad = xAngle * D_PI / 180.0; - double yRad = yAngle * D_PI / 180.0; - double zRad = zAngle * D_PI / 180.0; + double xRad = xAngle * pi / 180.0; + double yRad = yAngle * pi / 180.0; + double zRad = zAngle * pi / 180.0; if (xAngle != 0) { a[1] = 0; a[2] = 0; diff --git a/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp b/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp index e70b285702..cbded442f1 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp +++ b/src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp @@ -43,8 +43,8 @@ DlgSettingsFemCcxImp::DlgSettingsFemCcxImp(QWidget* parent) { ui->setupUi(this); // set ranges - ui->dsb_ccx_analysis_time->setMaximum(FLOAT_MAX); - ui->dsb_ccx_initial_time_step->setMaximum(FLOAT_MAX); + ui->dsb_ccx_analysis_time->setMaximum(std::numeric_limits::max()); + ui->dsb_ccx_initial_time_step->setMaximum(std::numeric_limits::max()); connect(ui->fc_ccx_binary_path, &Gui::PrefFileChooser::fileNameChanged, diff --git a/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp b/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp index 72d355449c..d054494ca6 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp @@ -66,18 +66,19 @@ TaskFemConstraintBearing::TaskFemConstraintBearing(ViewProviderFemConstraint* Co this->groupLayout()->addWidget(proxy); // setup ranges - ui->spinDiameter->setMinimum(-FLOAT_MAX); - ui->spinDiameter->setMaximum(FLOAT_MAX); - ui->spinOtherDiameter->setMinimum(-FLOAT_MAX); - ui->spinOtherDiameter->setMaximum(FLOAT_MAX); - ui->spinCenterDistance->setMinimum(-FLOAT_MAX); - ui->spinCenterDistance->setMaximum(FLOAT_MAX); - ui->spinForce->setMinimum(-FLOAT_MAX); - ui->spinForce->setMaximum(FLOAT_MAX); - ui->spinTensionForce->setMinimum(-FLOAT_MAX); - ui->spinTensionForce->setMaximum(FLOAT_MAX); - ui->spinDistance->setMinimum(-FLOAT_MAX); - ui->spinDistance->setMaximum(FLOAT_MAX); + constexpr float max = std::numeric_limits::max(); + ui->spinDiameter->setMinimum(-max); + ui->spinDiameter->setMaximum(max); + ui->spinOtherDiameter->setMinimum(-max); + ui->spinOtherDiameter->setMaximum(max); + ui->spinCenterDistance->setMinimum(-max); + ui->spinCenterDistance->setMaximum(max); + ui->spinForce->setMinimum(-max); + ui->spinForce->setMaximum(max); + ui->spinTensionForce->setMinimum(-max); + ui->spinTensionForce->setMaximum(max); + ui->spinDistance->setMinimum(-max); + ui->spinDistance->setMaximum(max); // Get the feature data Fem::ConstraintBearing* pcConstraint = ConstraintView->getObject(); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp b/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp index 2b49edb781..65c1744127 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp @@ -96,27 +96,27 @@ TaskFemConstraintContact::TaskFemConstraintContact(ViewProviderFemConstraintCont // Fill data into dialog elements ui->spbSlope->setUnit(pcConstraint->Slope.getUnit()); ui->spbSlope->setMinimum(0); - ui->spbSlope->setMaximum(FLOAT_MAX); + ui->spbSlope->setMaximum(std::numeric_limits::max()); ui->spbSlope->setValue(pcConstraint->Slope.getQuantityValue()); ui->spbSlope->bind(pcConstraint->Slope); ui->spbAdjust->setUnit(pcConstraint->Adjust.getUnit()); ui->spbAdjust->setMinimum(0); - ui->spbAdjust->setMaximum(FLOAT_MAX); + ui->spbAdjust->setMaximum(std::numeric_limits::max()); ui->spbAdjust->setValue(pcConstraint->Adjust.getQuantityValue()); ui->spbAdjust->bind(pcConstraint->Adjust); ui->ckbFriction->setChecked(friction); ui->spbFrictionCoeff->setMinimum(0); - ui->spbFrictionCoeff->setMaximum(FLOAT_MAX); + ui->spbFrictionCoeff->setMaximum(std::numeric_limits::max()); ui->spbFrictionCoeff->setValue(pcConstraint->FrictionCoefficient.getValue()); ui->spbFrictionCoeff->setEnabled(friction); ui->spbFrictionCoeff->bind(pcConstraint->FrictionCoefficient); ui->spbStickSlope->setUnit(pcConstraint->StickSlope.getUnit()); ui->spbStickSlope->setMinimum(0); - ui->spbStickSlope->setMaximum(FLOAT_MAX); + ui->spbStickSlope->setMaximum(std::numeric_limits::max()); ui->spbStickSlope->setValue(pcConstraint->StickSlope.getQuantityValue()); ui->spbStickSlope->setEnabled(friction); ui->spbStickSlope->bind(pcConstraint->StickSlope); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp index e4c490860b..b760434e77 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp @@ -74,18 +74,19 @@ TaskFemConstraintDisplacement::TaskFemConstraintDisplacement( this->groupLayout()->addWidget(proxy); // setup ranges - ui->spinxDisplacement->setMinimum(-FLOAT_MAX); - ui->spinxDisplacement->setMaximum(FLOAT_MAX); - ui->spinyDisplacement->setMinimum(-FLOAT_MAX); - ui->spinyDisplacement->setMaximum(FLOAT_MAX); - ui->spinzDisplacement->setMinimum(-FLOAT_MAX); - ui->spinzDisplacement->setMaximum(FLOAT_MAX); - ui->spinxRotation->setMinimum(-FLOAT_MAX); - ui->spinxRotation->setMaximum(FLOAT_MAX); - ui->spinyRotation->setMinimum(-FLOAT_MAX); - ui->spinyRotation->setMaximum(FLOAT_MAX); - ui->spinzRotation->setMinimum(-FLOAT_MAX); - ui->spinzRotation->setMaximum(FLOAT_MAX); + constexpr float max = std::numeric_limits::max(); + ui->spinxDisplacement->setMinimum(-max); + ui->spinxDisplacement->setMaximum(max); + ui->spinyDisplacement->setMinimum(-max); + ui->spinyDisplacement->setMaximum(max); + ui->spinzDisplacement->setMinimum(-max); + ui->spinzDisplacement->setMaximum(max); + ui->spinxRotation->setMinimum(-max); + ui->spinxRotation->setMaximum(max); + ui->spinyRotation->setMinimum(-max); + ui->spinyRotation->setMaximum(max); + ui->spinzRotation->setMinimum(-max); + ui->spinzRotation->setMaximum(max); // Get the feature data Fem::ConstraintDisplacement* pcConstraint = diff --git a/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp b/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp index ff11970ea9..fb9a3fe912 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp @@ -145,18 +145,19 @@ TaskFemConstraintFluidBoundary::TaskFemConstraintFluidBoundary( &TaskFemConstraintFluidBoundary::onReferenceDeleted); // setup ranges - ui->spinBoundaryValue->setMinimum(-FLOAT_MAX); - ui->spinBoundaryValue->setMaximum(FLOAT_MAX); + constexpr float max = std::numeric_limits::max(); + ui->spinBoundaryValue->setMinimum(-max); + ui->spinBoundaryValue->setMaximum(max); ui->spinTurbulentIntensityValue->setMinimum(0.0); - ui->spinTurbulentIntensityValue->setMaximum(FLOAT_MAX); + ui->spinTurbulentIntensityValue->setMaximum(max); ui->spinTurbulentLengthValue->setMinimum(0.0); - ui->spinTurbulentLengthValue->setMaximum(FLOAT_MAX); + ui->spinTurbulentLengthValue->setMaximum(max); ui->spinTemperatureValue->setMinimum(-273.15); - ui->spinTemperatureValue->setMaximum(FLOAT_MAX); + ui->spinTemperatureValue->setMaximum(max); ui->spinHeatFluxValue->setMinimum(0.0); - ui->spinHeatFluxValue->setMaximum(FLOAT_MAX); + ui->spinHeatFluxValue->setMaximum(max); ui->spinHTCoeffValue->setMinimum(0.0); - ui->spinHTCoeffValue->setMaximum(FLOAT_MAX); + ui->spinHTCoeffValue->setMaximum(max); connect(ui->comboBoundaryType, qOverload(&QComboBox::currentIndexChanged), @@ -352,8 +353,8 @@ TaskFemConstraintFluidBoundary::TaskFemConstraintFluidBoundary( // Fill data into dialog elements double f = pcConstraint->BoundaryValue.getValue(); - ui->spinBoundaryValue->setMinimum(FLOAT_MIN); // previous set the min to ZERO is not flexible - ui->spinBoundaryValue->setMaximum(FLOAT_MAX); + ui->spinBoundaryValue->setMinimum(std::numeric_limits::min()); // ZERO is not flexible + ui->spinBoundaryValue->setMaximum(std::numeric_limits::max()); ui->spinBoundaryValue->setValue(f); ui->listReferences->clear(); for (std::size_t i = 0; i < Objects.size(); i++) { diff --git a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp index 236fdef904..fb8f7f9855 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp @@ -75,7 +75,7 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce* C // Fill data into dialog elements ui->spinForce->setUnit(pcConstraint->Force.getUnit()); ui->spinForce->setMinimum(0); - ui->spinForce->setMaximum(FLOAT_MAX); + ui->spinForce->setMaximum(std::numeric_limits::max()); ui->spinForce->setValue(force); ui->listReferences->clear(); for (std::size_t i = 0; i < Objects.size(); i++) { diff --git a/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp b/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp index 3a116dff1c..9e139f899c 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp @@ -87,10 +87,10 @@ TaskFemConstraintGear::TaskFemConstraintGear(ViewProviderFemConstraint* Constrai // Fill data into dialog elements ui->spinDiameter->setMinimum(0); - ui->spinDiameter->setMaximum(FLOAT_MAX); + ui->spinDiameter->setMaximum(std::numeric_limits::max()); ui->spinDiameter->setValue(dia); ui->spinForce->setMinimum(0); - ui->spinForce->setMaximum(FLOAT_MAX); + ui->spinForce->setMaximum(std::numeric_limits::max()); ui->spinForce->setValue(force); ui->spinForceAngle->setMinimum(-360); ui->spinForceAngle->setMaximum(360); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp b/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp index 41651983ef..0241563cbb 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp @@ -119,16 +119,16 @@ TaskFemConstraintHeatflux::TaskFemConstraintHeatflux( ui->sw_heatflux->setCurrentIndex(constrType->getValue()); ui->qsb_ambienttemp_conv->setMinimum(0); - ui->qsb_ambienttemp_conv->setMaximum(FLOAT_MAX); + ui->qsb_ambienttemp_conv->setMaximum(std::numeric_limits::max()); ui->qsb_film_coef->setMinimum(0); - ui->qsb_film_coef->setMaximum(FLOAT_MAX); + ui->qsb_film_coef->setMaximum(std::numeric_limits::max()); ui->dsb_emissivity->setMinimum(0); - ui->dsb_emissivity->setMaximum(FLOAT_MAX); + ui->dsb_emissivity->setMaximum(std::numeric_limits::max()); ui->qsb_ambienttemp_rad->setMinimum(0); - ui->qsb_ambienttemp_rad->setMaximum(FLOAT_MAX); + ui->qsb_ambienttemp_rad->setMaximum(std::numeric_limits::max()); ui->qsb_ambienttemp_conv->setValue(pcConstraint->AmbientTemp.getQuantityValue()); ui->qsb_film_coef->setValue(pcConstraint->FilmCoef.getQuantityValue()); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp b/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp index 030cfc9c1c..41406cc1a2 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp @@ -64,7 +64,7 @@ TaskFemConstraintPressure::TaskFemConstraintPressure( // Fill data into dialog elements ui->if_pressure->setUnit(pcConstraint->Pressure.getUnit()); ui->if_pressure->setMinimum(0); - ui->if_pressure->setMaximum(FLOAT_MAX); + ui->if_pressure->setMaximum(std::numeric_limits::max()); ui->if_pressure->setValue(pcConstraint->Pressure.getQuantityValue()); ui->if_pressure->bind(pcConstraint->Pressure); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp b/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp index 710b041a61..ebc8ac670e 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp @@ -76,15 +76,15 @@ TaskFemConstraintPulley::TaskFemConstraintPulley(ViewProviderFemConstraintPulley // Fill data into dialog elements ui->spinOtherDiameter->setMinimum(0); - ui->spinOtherDiameter->setMaximum(FLOAT_MAX); + ui->spinOtherDiameter->setMaximum(std::numeric_limits::max()); ui->spinOtherDiameter->setValue(otherdia); ui->spinCenterDistance->setMinimum(0); - ui->spinCenterDistance->setMaximum(FLOAT_MAX); + ui->spinCenterDistance->setMaximum(std::numeric_limits::max()); ui->spinCenterDistance->setValue(centerdist); ui->checkIsDriven->setChecked(isdriven); - ui->spinForce->setMinimum(-FLOAT_MAX); + ui->spinForce->setMinimum(-std::numeric_limits::max()); ui->spinTensionForce->setMinimum(0); - ui->spinTensionForce->setMaximum(FLOAT_MAX); + ui->spinTensionForce->setMaximum(std::numeric_limits::max()); ui->spinTensionForce->setValue(tensionforce); // Adjust ui diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp index 70da10d875..c1f5e17ee9 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -48,6 +48,7 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( QWidget* parent) : TaskFemConstraintOnBoundary(ConstraintView, parent, "FEM_ConstraintRigidBody") { // Note change "RigidBody" in line above to new constraint name + constexpr float floatMax = std::numeric_limits::max(); proxy = new QWidget(this); ui = new Ui_TaskFemConstraintRigidBody(); ui->setupUi(proxy); @@ -137,12 +138,12 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( App::ObjectIdentifier::parse(pcConstraint, std::string("ReferenceNode.y"))); ui->qsb_ref_node_z->bind( App::ObjectIdentifier::parse(pcConstraint, std::string("ReferenceNode.z"))); - ui->qsb_ref_node_x->setMinimum(-FLOAT_MAX); - ui->qsb_ref_node_x->setMaximum(FLOAT_MAX); - ui->qsb_ref_node_y->setMinimum(-FLOAT_MAX); - ui->qsb_ref_node_y->setMaximum(FLOAT_MAX); - ui->qsb_ref_node_z->setMinimum(-FLOAT_MAX); - ui->qsb_ref_node_z->setMaximum(FLOAT_MAX); + ui->qsb_ref_node_x->setMinimum(-floatMax); + ui->qsb_ref_node_x->setMaximum(floatMax); + ui->qsb_ref_node_y->setMinimum(-floatMax); + ui->qsb_ref_node_y->setMaximum(floatMax); + ui->qsb_ref_node_z->setMinimum(-floatMax); + ui->qsb_ref_node_z->setMaximum(floatMax); ui->qsb_disp_x->setValue(disp.x); ui->qsb_disp_y->setValue(disp.y); @@ -150,12 +151,12 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( ui->qsb_disp_x->bind(App::ObjectIdentifier::parse(pcConstraint, std::string("Displacement.x"))); ui->qsb_disp_y->bind(App::ObjectIdentifier::parse(pcConstraint, std::string("Displacement.y"))); ui->qsb_disp_z->bind(App::ObjectIdentifier::parse(pcConstraint, std::string("Displacement.z"))); - ui->qsb_disp_x->setMinimum(-FLOAT_MAX); - ui->qsb_disp_x->setMaximum(FLOAT_MAX); - ui->qsb_disp_y->setMinimum(-FLOAT_MAX); - ui->qsb_disp_y->setMaximum(FLOAT_MAX); - ui->qsb_disp_z->setMinimum(-FLOAT_MAX); - ui->qsb_disp_z->setMaximum(FLOAT_MAX); + ui->qsb_disp_x->setMinimum(-floatMax); + ui->qsb_disp_x->setMaximum(floatMax); + ui->qsb_disp_y->setMinimum(-floatMax); + ui->qsb_disp_y->setMaximum(floatMax); + ui->qsb_disp_z->setMinimum(-floatMax); + ui->qsb_disp_z->setMaximum(floatMax); ui->spb_rot_axis_x->setValue(rotDir.x); ui->spb_rot_axis_y->setValue(rotDir.y); @@ -169,14 +170,14 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Axis.z"))); ui->qsb_rot_angle->bind( App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Angle"))); - ui->spb_rot_axis_x->setMinimum(-FLOAT_MAX); - ui->spb_rot_axis_x->setMaximum(FLOAT_MAX); - ui->spb_rot_axis_y->setMinimum(-FLOAT_MAX); - ui->spb_rot_axis_y->setMaximum(FLOAT_MAX); - ui->spb_rot_axis_z->setMinimum(-FLOAT_MAX); - ui->spb_rot_axis_z->setMaximum(FLOAT_MAX); - ui->qsb_rot_angle->setMinimum(-FLOAT_MAX); - ui->qsb_rot_angle->setMaximum(FLOAT_MAX); + ui->spb_rot_axis_x->setMinimum(-floatMax); + ui->spb_rot_axis_x->setMaximum(floatMax); + ui->spb_rot_axis_y->setMinimum(-floatMax); + ui->spb_rot_axis_y->setMaximum(floatMax); + ui->spb_rot_axis_z->setMinimum(-floatMax); + ui->spb_rot_axis_z->setMaximum(floatMax); + ui->qsb_rot_angle->setMinimum(-floatMax); + ui->qsb_rot_angle->setMaximum(floatMax); ui->qsb_force_x->setValue(forceX); ui->qsb_force_y->setValue(forceY); @@ -184,12 +185,12 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( ui->qsb_force_x->bind(pcConstraint->ForceX); ui->qsb_force_y->bind(pcConstraint->ForceY); ui->qsb_force_z->bind(pcConstraint->ForceZ); - ui->qsb_force_x->setMinimum(-FLOAT_MAX); - ui->qsb_force_x->setMaximum(FLOAT_MAX); - ui->qsb_force_y->setMinimum(-FLOAT_MAX); - ui->qsb_force_y->setMaximum(FLOAT_MAX); - ui->qsb_force_z->setMinimum(-FLOAT_MAX); - ui->qsb_force_z->setMaximum(FLOAT_MAX); + ui->qsb_force_x->setMinimum(-floatMax); + ui->qsb_force_x->setMaximum(floatMax); + ui->qsb_force_y->setMinimum(-floatMax); + ui->qsb_force_y->setMaximum(floatMax); + ui->qsb_force_z->setMinimum(-floatMax); + ui->qsb_force_z->setMaximum(floatMax); ui->qsb_moment_x->setValue(momentX); ui->qsb_moment_y->setValue(momentY); @@ -197,12 +198,12 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( ui->qsb_moment_x->bind(pcConstraint->MomentX); ui->qsb_moment_y->bind(pcConstraint->MomentY); ui->qsb_moment_z->bind(pcConstraint->MomentZ); - ui->qsb_moment_x->setMinimum(-FLOAT_MAX); - ui->qsb_moment_x->setMaximum(FLOAT_MAX); - ui->qsb_moment_y->setMinimum(-FLOAT_MAX); - ui->qsb_moment_y->setMaximum(FLOAT_MAX); - ui->qsb_moment_z->setMinimum(-FLOAT_MAX); - ui->qsb_moment_z->setMaximum(FLOAT_MAX); + ui->qsb_moment_x->setMinimum(-floatMax); + ui->qsb_moment_x->setMaximum(floatMax); + ui->qsb_moment_y->setMinimum(-floatMax); + ui->qsb_moment_y->setMaximum(floatMax); + ui->qsb_moment_z->setMinimum(-floatMax); + ui->qsb_moment_z->setMaximum(floatMax); QStringList modeList; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp b/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp index 4f09a745b8..e21fb5b299 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp @@ -76,11 +76,11 @@ TaskFemConstraintSpring::TaskFemConstraintSpring(ViewProviderFemConstraintSpring // Fill data into dialog elements ui->qsb_norm->setUnit(pcConstraint->NormalStiffness.getUnit()); - ui->qsb_norm->setMaximum(FLOAT_MAX); + ui->qsb_norm->setMaximum(std::numeric_limits::max()); ui->qsb_norm->setValue(pcConstraint->NormalStiffness.getQuantityValue()); ui->qsb_tan->setUnit(pcConstraint->TangentialStiffness.getUnit()); - ui->qsb_tan->setMaximum(FLOAT_MAX); + ui->qsb_tan->setMaximum(std::numeric_limits::max()); ui->qsb_tan->setValue(pcConstraint->TangentialStiffness.getQuantityValue()); ui->cb_elmer_stiffness->clear(); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp b/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp index c989436740..ff648c41e7 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp @@ -68,9 +68,9 @@ TaskFemConstraintTemperature::TaskFemConstraintTemperature( // Fill data into dialog elements ui->qsb_temperature->setMinimum(0); - ui->qsb_temperature->setMaximum(FLOAT_MAX); - ui->qsb_cflux->setMinimum(-FLOAT_MAX); - ui->qsb_cflux->setMaximum(FLOAT_MAX); + ui->qsb_temperature->setMaximum(std::numeric_limits::max()); + ui->qsb_cflux->setMinimum(-std::numeric_limits::max()); + ui->qsb_cflux->setMaximum(std::numeric_limits::max()); App::PropertyEnumeration* constrType = &pcConstraint->ConstraintType; QStringList qTypeList; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp b/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp index d53e476f37..894b27b62e 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp @@ -130,14 +130,15 @@ TaskFemConstraintTransform::TaskFemConstraintTransform( ui->qsb_rot_angle->bind( App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Angle"))); - ui->spb_rot_axis_x->setMinimum(-FLOAT_MAX); - ui->spb_rot_axis_x->setMaximum(FLOAT_MAX); - ui->spb_rot_axis_y->setMinimum(-FLOAT_MAX); - ui->spb_rot_axis_y->setMaximum(FLOAT_MAX); - ui->spb_rot_axis_z->setMinimum(-FLOAT_MAX); - ui->spb_rot_axis_z->setMaximum(FLOAT_MAX); - ui->qsb_rot_angle->setMinimum(-FLOAT_MAX); - ui->qsb_rot_angle->setMaximum(FLOAT_MAX); + float max = std::numeric_limits::max(); + ui->spb_rot_axis_x->setMinimum(-max); + ui->spb_rot_axis_x->setMaximum(max); + ui->spb_rot_axis_y->setMinimum(-max); + ui->spb_rot_axis_y->setMaximum(max); + ui->spb_rot_axis_z->setMinimum(-max); + ui->spb_rot_axis_z->setMaximum(max); + ui->qsb_rot_angle->setMinimum(-max); + ui->qsb_rot_angle->setMaximum(max); std::string transform_type = pcConstraint->TransformType.getValueAsString(); if (transform_type == "Rectangular") { diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintFluidBoundary.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintFluidBoundary.cpp index 9ac1828bd9..9813172d33 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintFluidBoundary.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintFluidBoundary.cpp @@ -145,8 +145,8 @@ void ViewProviderFemConstraintFluidBoundary::updateData(const App::Property* pro for (const auto& point : points) { SbVec3f base(point.x, point.y, point.z); - if (forceDirection.GetAngle(normal) - < M_PI_2) { // Move arrow so it doesn't disappear inside the solid + if (forceDirection.GetAngle(normal) < std::numbers::pi + / 2) { // Move arrow so it doesn't disappear inside the solid base = base + dir * scaledlength; // OvG: Scaling } #ifdef USE_MULTIPLE_COPY @@ -191,7 +191,7 @@ void ViewProviderFemConstraintFluidBoundary::updateData(const App::Property* pro for (const auto& point : points) { SbVec3f base(point.x, point.y, point.z); - if (forceDirection.GetAngle(normal) < M_PI_2) { + if (forceDirection.GetAngle(normal) < std::numbers::pi / 2) { base = base + dir * scaledlength; // OvG: Scaling } #ifdef USE_MULTIPLE_COPY diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp index 2c100a3a93..20d7832d3e 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintForce.cpp @@ -88,7 +88,7 @@ void ViewProviderFemConstraintForce::transformSymbol(const Base::Vector3d& point // Place each symbol outside the boundary Base::Vector3d dir = (rev ? -1.0 : 1.0) * obj->DirectionVector.getValue(); float symTraY = dir.Dot(normal) < 0 ? -1 * symLen : 0.0f; - float rotAngle = rev ? F_PI : 0.0f; + float rotAngle = rev ? std::numbers::pi_v : 0.0f; SbMatrix mat0, mat1; mat0.setTransform(SbVec3f(0, symTraY, 0), SbRotation(SbVec3f(0, 0, 1), rotAngle), diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp index 33cd6ecd8a..95609843a4 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintGear.cpp @@ -88,7 +88,7 @@ void ViewProviderFemConstraintGear::updateData(const App::Property* prop) if (dia < 2 * radius) { dia = 2 * radius; } - double angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + double angle = pcConstraint->ForceAngle.getValue() / 180 * std::numbers::pi; SbVec3f b(base.x, base.y, base.z); SbVec3f ax(axis.x, axis.y, axis.z); @@ -118,7 +118,7 @@ void ViewProviderFemConstraintGear::updateData(const App::Property* prop) if (dia < 2 * radius) { dia = 2 * radius; } - double angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + double angle = pcConstraint->ForceAngle.getValue() / 180 * std::numbers::pi; SbVec3f ax(axis.x, axis.y, axis.z); SbVec3f dir(direction.x, direction.y, direction.z); @@ -143,7 +143,7 @@ void ViewProviderFemConstraintGear::updateData(const App::Property* prop) direction = Base::Vector3d(0, 1, 0); } double dia = pcConstraint->Diameter.getValue(); - double angle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + double angle = pcConstraint->ForceAngle.getValue() / 180 * std::numbers::pi; SbVec3f ax(axis.x, axis.y, axis.z); SbVec3f dir(direction.x, direction.y, direction.z); diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintPressure.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintPressure.cpp index b58c9f5596..737b34994b 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintPressure.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintPressure.cpp @@ -82,7 +82,7 @@ void ViewProviderFemConstraintPressure::transformSymbol(const Base::Vector3d& po SbMatrix& mat) const { auto obj = this->getObject(); - float rotAngle = obj->Reversed.getValue() ? F_PI : 0.0f; + float rotAngle = obj->Reversed.getValue() ? std::numbers::pi_v : 0.0f; float s = obj->getScaleFactor(); // Symbol length from .iv file float symLen = 4.0f; diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp index 2a43326fe1..4cd2bc084f 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintPulley.cpp @@ -66,6 +66,8 @@ bool ViewProviderFemConstraintPulley::setEdit(int ModNum) void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) { + using std::numbers::pi; + // Gets called whenever a property of the attached object changes Fem::ConstraintPulley* pcConstraint = this->getObject(); @@ -82,7 +84,7 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) if (dia < 2 * radius) { dia = 2 * radius; } - double forceAngle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + double forceAngle = pcConstraint->ForceAngle.getValue() / 180 * pi; double beltAngle = pcConstraint->BeltAngle.getValue(); double rat1 = 0.8, rat2 = 0.2; double f1 = pcConstraint->BeltForce1.getValue(); @@ -106,9 +108,9 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) 0, dia / 2 * cos(forceAngle + beltAngle)), SbRotation(SbVec3f(0, 1, 0), - SbVec3f(sin(forceAngle + beltAngle + M_PI_2), + SbVec3f(sin(forceAngle + beltAngle + pi / 2), 0, - cos(forceAngle + beltAngle + M_PI_2)))); + cos(forceAngle + beltAngle + pi / 2)))); GuiTools::createPlacement(sep, SbVec3f(0, dia / 8 + dia / 2 * rat1, 0), SbRotation()); sep->addChild(GuiTools::createArrow(dia / 8 + dia / 2 * rat1, dia / 8)); pShapeSep->addChild(sep); // child 3 @@ -118,9 +120,9 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) 0, -dia / 2 * cos(forceAngle - beltAngle)), SbRotation(SbVec3f(0, 1, 0), - SbVec3f(-sin(forceAngle - beltAngle - M_PI_2), + SbVec3f(-sin(forceAngle - beltAngle - pi / 2), 0, - -cos(forceAngle - beltAngle - M_PI_2)))); + -cos(forceAngle - beltAngle - pi / 2)))); GuiTools::createPlacement(sep, SbVec3f(0, dia / 8 + dia / 2 * rat2, 0), SbRotation()); sep->addChild(GuiTools::createArrow(dia / 8 + dia / 2 * rat2, dia / 8)); pShapeSep->addChild(sep); // child 4 @@ -134,7 +136,7 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) if (dia < 2 * radius) { dia = 2 * radius; } - double forceAngle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + double forceAngle = pcConstraint->ForceAngle.getValue() / 180 * pi; double beltAngle = pcConstraint->BeltAngle.getValue(); double rat1 = 0.8, rat2 = 0.2; double f1 = pcConstraint->BeltForce1.getValue(); @@ -153,9 +155,9 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) 0, dia / 2 * cos(forceAngle + beltAngle)), SbRotation(SbVec3f(0, 1, 0), - SbVec3f(sin(forceAngle + beltAngle + M_PI_2), + SbVec3f(sin(forceAngle + beltAngle + pi / 2), 0, - cos(forceAngle + beltAngle + M_PI_2)))); + cos(forceAngle + beltAngle + pi / 2)))); GuiTools::updatePlacement(sep, 2, SbVec3f(0, dia / 8 + dia / 2 * rat1, 0), @@ -169,9 +171,9 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) 0, -dia / 2 * cos(forceAngle - beltAngle)), SbRotation(SbVec3f(0, 1, 0), - SbVec3f(-sin(forceAngle - beltAngle - M_PI_2), + SbVec3f(-sin(forceAngle - beltAngle - pi / 2), 0, - -cos(forceAngle - beltAngle - M_PI_2)))); + -cos(forceAngle - beltAngle - pi / 2)))); GuiTools::updatePlacement(sep, 2, SbVec3f(0, dia / 8 + dia / 2 * rat2, 0), @@ -187,7 +189,7 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) if (dia < 2 * radius) { dia = 2 * radius; } - double forceAngle = pcConstraint->ForceAngle.getValue() / 180 * M_PI; + double forceAngle = pcConstraint->ForceAngle.getValue() / 180 * pi; double beltAngle = pcConstraint->BeltAngle.getValue(); const SoSeparator* sep = static_cast(pShapeSep->getChild(3)); @@ -197,9 +199,9 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) 0, dia / 2 * cos(forceAngle + beltAngle)), SbRotation(SbVec3f(0, 1, 0), - SbVec3f(sin(forceAngle + beltAngle + M_PI_2), + SbVec3f(sin(forceAngle + beltAngle + pi / 2), 0, - cos(forceAngle + beltAngle + M_PI_2)))); + cos(forceAngle + beltAngle + pi / 2)))); sep = static_cast(pShapeSep->getChild(4)); GuiTools::updatePlacement(sep, 0, @@ -207,9 +209,9 @@ void ViewProviderFemConstraintPulley::updateData(const App::Property* prop) 0, -dia / 2 * cos(forceAngle - beltAngle)), SbRotation(SbVec3f(0, 1, 0), - SbVec3f(-sin(forceAngle - beltAngle - M_PI_2), + SbVec3f(-sin(forceAngle - beltAngle - pi / 2), 0, - -cos(forceAngle - beltAngle - M_PI_2)))); + -cos(forceAngle - beltAngle - pi / 2)))); } } else if ((prop == &pcConstraint->BeltForce1) || (prop == &pcConstraint->BeltForce2)) { diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp index be2daae11e..200622da31 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp @@ -756,7 +756,10 @@ void CylinderWidget::radiusChanged(double) PROPERTY_SOURCE(FemGui::ViewProviderFemPostPlaneFunction, FemGui::ViewProviderFemPostFunction) // NOTE: The technical lower limit is at 1e-4 that the Coin3D manipulator can handle -static const App::PropertyFloatConstraint::Constraints scaleConstraint = {1e-4, DBL_MAX, 1.0}; +static const App::PropertyFloatConstraint::Constraints scaleConstraint = { + 1e-4, + std::numeric_limits::max(), + 1.0}; ViewProviderFemPostPlaneFunction::ViewProviderFemPostPlaneFunction() : m_detectscale(false) @@ -1178,6 +1181,8 @@ SoGroup* postBox() SoGroup* postCylinder() { + using std::numbers::pi; + SoCoordinate3* points = new SoCoordinate3(); int nCirc = 20; const int nSide = 8; @@ -1189,8 +1194,8 @@ SoGroup* postCylinder() for (int i = 0; i < 2; ++i) { for (int j = 0; j < nCirc + 1; ++j) { points->point.set1Value(idx, - SbVec3f(std::cos(2 * M_PI / nCirc * j), - std::sin(2 * M_PI / nCirc * j), + SbVec3f(std::cos(2 * pi / nCirc * j), + std::sin(2 * pi / nCirc * j), -h / 2. + h * i)); ++idx; } @@ -1199,8 +1204,8 @@ SoGroup* postCylinder() for (int i = 0; i < nSide; ++i) { for (int j = 0; j < 2; ++j) { points->point.set1Value(idx, - SbVec3f(std::cos(2 * M_PI / nSide * i), - std::sin(2 * M_PI / nSide * i), + SbVec3f(std::cos(2 * pi / nSide * i), + std::sin(2 * pi / nSide * i), -h / 2. + h * j)); ++idx; } @@ -1243,24 +1248,26 @@ SoGroup* postPlane() SoGroup* postSphere() { + using std::numbers::pi; + SoCoordinate3* points = new SoCoordinate3(); points->point.setNum(2 * 84); int idx = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 21; j++) { points->point.set1Value(idx, - SbVec3f(std::sin(2 * M_PI / 20 * j) * std::cos(M_PI / 4 * i), - std::sin(2 * M_PI / 20 * j) * std::sin(M_PI / 4 * i), - std::cos(2 * M_PI / 20 * j))); + SbVec3f(std::sin(2 * pi / 20 * j) * std::cos(pi / 4 * i), + std::sin(2 * pi / 20 * j) * std::sin(pi / 4 * i), + std::cos(2 * pi / 20 * j))); ++idx; } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 21; j++) { points->point.set1Value(idx, - SbVec3f(std::sin(M_PI / 4 * i) * std::cos(2 * M_PI / 20 * j), - std::sin(M_PI / 4 * i) * std::sin(2 * M_PI / 20 * j), - std::cos(M_PI / 4 * i))); + SbVec3f(std::sin(pi / 4 * i) * std::cos(2 * pi / 20 * j), + std::sin(pi / 4 * i) * std::sin(2 * pi / 20 * j), + std::cos(pi / 4 * i))); ++idx; } } From 821327b4cd9f3ff953c8610399ab7dd63bfc1f64 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:00:50 +0100 Subject: [PATCH 043/316] Import: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Import/App/AppImportPy.cpp | 1 - src/Mod/Import/App/ExportOCAF.cpp | 1 - src/Mod/Import/App/ExportOCAF.h | 1 - src/Mod/Import/App/ImportOCAF.cpp | 1 - src/Mod/Import/App/ImportOCAF.h | 1 - src/Mod/Import/App/ImportOCAF2.h | 1 - src/Mod/Import/App/ImportOCAFAssembly.cpp | 1 - src/Mod/Import/App/ImportOCAFAssembly.h | 1 - src/Mod/Import/App/Tools.h | 4 ++-- src/Mod/Import/App/dxf/ImpExpDxf.cpp | 8 ++++---- src/Mod/Import/App/dxf/dxf.cpp | 8 +++----- src/Mod/Import/Gui/AppImportGuiPy.cpp | 1 - 12 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/Mod/Import/App/AppImportPy.cpp b/src/Mod/Import/App/AppImportPy.cpp index 31fd806866..7aa936f1c2 100644 --- a/src/Mod/Import/App/AppImportPy.cpp +++ b/src/Mod/Import/App/AppImportPy.cpp @@ -27,7 +27,6 @@ #ifndef _PreComp_ #include #include -#include #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wextra-semi" diff --git a/src/Mod/Import/App/ExportOCAF.cpp b/src/Mod/Import/App/ExportOCAF.cpp index b4b7ad3a14..814140ce64 100644 --- a/src/Mod/Import/App/ExportOCAF.cpp +++ b/src/Mod/Import/App/ExportOCAF.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include // for Precision::Confusion() diff --git a/src/Mod/Import/App/ExportOCAF.h b/src/Mod/Import/App/ExportOCAF.h index 847b437cda..d74ab481d9 100644 --- a/src/Mod/Import/App/ExportOCAF.h +++ b/src/Mod/Import/App/ExportOCAF.h @@ -23,7 +23,6 @@ #ifndef IMPORT_EXPORTOCAF_H #define IMPORT_EXPORTOCAF_H -#include #include #include #include diff --git a/src/Mod/Import/App/ImportOCAF.cpp b/src/Mod/Import/App/ImportOCAF.cpp index 0d155d5201..89d40ec7d7 100644 --- a/src/Mod/Import/App/ImportOCAF.cpp +++ b/src/Mod/Import/App/ImportOCAF.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include // for Precision::Confusion() #include #endif diff --git a/src/Mod/Import/App/ImportOCAF.h b/src/Mod/Import/App/ImportOCAF.h index 18ae55312a..239cdc9787 100644 --- a/src/Mod/Import/App/ImportOCAF.h +++ b/src/Mod/Import/App/ImportOCAF.h @@ -23,7 +23,6 @@ #ifndef IMPORT_IMPORTOCAF_H #define IMPORT_IMPORTOCAF_H -#include #include #include #include diff --git a/src/Mod/Import/App/ImportOCAF2.h b/src/Mod/Import/App/ImportOCAF2.h index a850e3d583..fd264eb6d5 100644 --- a/src/Mod/Import/App/ImportOCAF2.h +++ b/src/Mod/Import/App/ImportOCAF2.h @@ -23,7 +23,6 @@ #ifndef IMPORT_IMPORTOCAF2_H #define IMPORT_IMPORTOCAF2_H -#include #include #include #include diff --git a/src/Mod/Import/App/ImportOCAFAssembly.cpp b/src/Mod/Import/App/ImportOCAFAssembly.cpp index 4d60e779aa..3a904ce589 100644 --- a/src/Mod/Import/App/ImportOCAFAssembly.cpp +++ b/src/Mod/Import/App/ImportOCAFAssembly.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #endif diff --git a/src/Mod/Import/App/ImportOCAFAssembly.h b/src/Mod/Import/App/ImportOCAFAssembly.h index ee18ab30a2..dad46e8cba 100644 --- a/src/Mod/Import/App/ImportOCAFAssembly.h +++ b/src/Mod/Import/App/ImportOCAFAssembly.h @@ -23,7 +23,6 @@ #ifndef IMPORT_ImportOCAFAssembly_H #define IMPORT_ImportOCAFAssembly_H -#include #include #include #include diff --git a/src/Mod/Import/App/Tools.h b/src/Mod/Import/App/Tools.h index 9d99cf5dae..56b704e010 100644 --- a/src/Mod/Import/App/Tools.h +++ b/src/Mod/Import/App/Tools.h @@ -41,7 +41,7 @@ struct ShapeHasher #if OCC_VERSION_HEX >= 0x070800 return std::hash {}(shape); #else - return shape.HashCode(INT_MAX); + return shape.HashCode(std::numeric_limits::max()); #endif } }; @@ -53,7 +53,7 @@ struct LabelHasher #if OCC_VERSION_HEX >= 0x070800 return std::hash {}(label); #else - return TDF_LabelMapHasher::HashCode(label, INT_MAX); + return TDF_LabelMapHasher::HashCode(label, std::numeric_limits::max()); #endif } }; diff --git a/src/Mod/Import/App/dxf/ImpExpDxf.cpp b/src/Mod/Import/App/dxf/ImpExpDxf.cpp index 13f16b3ece..913d53aae6 100644 --- a/src/Mod/Import/App/dxf/ImpExpDxf.cpp +++ b/src/Mod/Import/App/dxf/ImpExpDxf.cpp @@ -977,8 +977,8 @@ void ImpExpDxfWrite::exportEllipse(BRepAdaptor_Curve& c) // rotation appears to be the clockwise(?) angle between major & +Y?? double rotation = xaxis.AngleWithRef(gp_Dir(0, 1, 0), gp_Dir(0, 0, 1)); - // 2*M_PI = 6.28319 is invalid(doesn't display in LibreCAD), but 2PI = 6.28318 is valid! - // writeEllipse(center, major, minor, rotation, 0.0, 2 * M_PI, true ); + // 2*pi = 6.28319 is invalid(doesn't display in LibreCAD), but 2PI = 6.28318 is valid! + // writeEllipse(center, major, minor, rotation, 0.0, 2 * std::numbers::pi, true ); writeEllipse(center, major, minor, rotation, 0.0, 6.28318, true); } @@ -1036,8 +1036,8 @@ void ImpExpDxfWrite::exportEllipseArc(BRepAdaptor_Curve& c) // a > 0 ==> v2 is CCW from v1 (righthanded)? // a < 0 ==> v2 is CW from v1 (lefthanded)? - double startAngle = fmod(f, 2.0 * M_PI); // revolutions - double endAngle = fmod(l, 2.0 * M_PI); + double startAngle = fmod(f, 2.0 * std::numbers::pi); // revolutions + double endAngle = fmod(l, 2.0 * std::numbers::pi); bool endIsCW = (a < 0) ? true : false; // if !endIsCW swap(start,end) // not sure if this is a hack or not. seems to make valid arcs. if (!endIsCW) { diff --git a/src/Mod/Import/App/dxf/dxf.cpp b/src/Mod/Import/App/dxf/dxf.cpp index 54b40ad234..0799e021ba 100644 --- a/src/Mod/Import/App/dxf/dxf.cpp +++ b/src/Mod/Import/App/dxf/dxf.cpp @@ -5,8 +5,6 @@ #include "PreCompiled.h" -// required by windows for M_PI definition -#define _USE_MATH_DEFINES #include #include #include @@ -1584,10 +1582,10 @@ void CDxfWrite::writeAngularDimBlock(const double* textMidPoint, double span = fabs(endAngle - startAngle); double offset = span * 0.10; if (startAngle < 0) { - startAngle += 2 * M_PI; + startAngle += 2 * std::numbers::pi; } if (endAngle < 0) { - endAngle += 2 * M_PI; + endAngle += 2 * std::numbers::pi; } Base::Vector3d startOff(cos(startAngle + offset), sin(startAngle + offset), 0.0); Base::Vector3d endOff(cos(endAngle - offset), sin(endAngle - offset), 0.0); @@ -2130,7 +2128,7 @@ bool CDxfRead::ReadEllipse() Base::Vector3d majorAxisEnd; // relative to centre double eccentricity = 0; double startAngleRadians = 0; - double endAngleRadians = 2 * M_PI; + double endAngleRadians = 2 * std::numbers::pi; Setup3DVectorAttribute(ePrimaryPoint, centre); Setup3DVectorAttribute(ePoint2, majorAxisEnd); diff --git a/src/Mod/Import/Gui/AppImportGuiPy.cpp b/src/Mod/Import/Gui/AppImportGuiPy.cpp index 246a1dafb2..2a6143c21e 100644 --- a/src/Mod/Import/Gui/AppImportGuiPy.cpp +++ b/src/Mod/Import/Gui/AppImportGuiPy.cpp @@ -25,7 +25,6 @@ #define WNT // avoid conflict with GUID #endif #ifndef _PreComp_ -#include #include #include From eb69b72a2b71a2cdad8908744139f3d0a8873f7f Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:03 +0100 Subject: [PATCH 044/316] Inspection: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Inspection/App/InspectionFeature.cpp | 27 ++++++++++--------- src/Mod/Inspection/Gui/PreCompiled.h | 1 - .../Inspection/Gui/ViewProviderInspection.h | 2 +- src/Mod/Inspection/Gui/VisualInspection.cpp | 5 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Mod/Inspection/App/InspectionFeature.cpp b/src/Mod/Inspection/App/InspectionFeature.cpp index bb0cdee9eb..ce6868327f 100644 --- a/src/Mod/Inspection/App/InspectionFeature.cpp +++ b/src/Mod/Inspection/App/InspectionFeature.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include #include +#include #include #include @@ -316,7 +317,7 @@ InspectNominalMesh::~InspectNominalMesh() float InspectNominalMesh::getDistance(const Base::Vector3f& point) const { if (!_box.IsInBox(point)) { - return FLT_MAX; // must be inside bbox + return std::numeric_limits::max(); // must be inside bbox } std::vector indices; @@ -327,7 +328,7 @@ float InspectNominalMesh::getDistance(const Base::Vector3f& point) const indices.insert(indices.begin(), inds.begin(), inds.end()); } - float fMinDist = FLT_MAX; + float fMinDist = std::numeric_limits::max(); bool positive = true; for (unsigned long it : indices) { MeshCore::MeshGeomFacet geomFace = _mesh.GetFacet(it); @@ -393,7 +394,7 @@ InspectNominalFastMesh::~InspectNominalFastMesh() float InspectNominalFastMesh::getDistance(const Base::Vector3f& point) const { if (!_box.IsInBox(point)) { - return FLT_MAX; // must be inside bbox + return std::numeric_limits::max(); // must be inside bbox } std::set indices; @@ -413,7 +414,7 @@ float InspectNominalFastMesh::getDistance(const Base::Vector3f& point) const } #endif - float fMinDist = FLT_MAX; + float fMinDist = std::numeric_limits::max(); bool positive = true; for (unsigned long it : indices) { MeshCore::MeshGeomFacet geomFace = _mesh.GetFacet(it); @@ -457,7 +458,7 @@ float InspectNominalPoints::getDistance(const Base::Vector3f& point) const _pGrid->Position(pointd, x, y, z); _pGrid->GetElements(x, y, z, indices); - double fMinDist = DBL_MAX; + double fMinDist = std::numeric_limits::max(); for (unsigned long it : indices) { Base::Vector3d pt = _rKernel.getPoint(it); double fDist = Base::Distance(pointd, pt); @@ -501,7 +502,7 @@ float InspectNominalShape::getDistance(const Base::Vector3f& point) const BRepBuilderAPI_MakeVertex mkVert(pnt3d); distss->LoadS2(mkVert.Vertex()); - float fMinDist = FLT_MAX; + float fMinDist = std::numeric_limits::max(); if (distss->Perform() && distss->NbSolution() > 0) { fMinDist = (float)distss->Value(); // the shape is a solid, check if the vertex is inside @@ -713,7 +714,7 @@ struct DistanceInspection { Base::Vector3f pnt = actual->getPoint(index); - float fMinDist = FLT_MAX; + float fMinDist = std::numeric_limits::max(); for (auto it : nominal) { float fDist = it->getDistance(pnt); if (fabs(fDist) < fabs(fMinDist)) { @@ -722,10 +723,10 @@ struct DistanceInspection } if (fMinDist > this->radius) { - fMinDist = FLT_MAX; + fMinDist = std::numeric_limits::max(); } else if (-fMinDist > this->radius) { - fMinDist = -FLT_MAX; + fMinDist = -std::numeric_limits::max(); } return fMinDist; @@ -884,7 +885,7 @@ App::DocumentObjectExecReturn* Feature::execute() float fRMS = 0; int countRMS = 0; for (std::vector::iterator it = vals.begin(); it != vals.end(); ++it) { - if (fabs(*it) < FLT_MAX) { + if (fabs(*it) < std::numeric_limits::max()) { fRMS += (*it) * (*it); countRMS++; } @@ -904,7 +905,7 @@ App::DocumentObjectExecReturn* Feature::execute() DistanceInspectionRMS res; Base::Vector3f pnt = actual->getPoint(index); - float fMinDist = FLT_MAX; + float fMinDist = std::numeric_limits::max(); for (auto it : inspectNominal) { float fDist = it->getDistance(pnt); if (fabs(fDist) < fabs(fMinDist)) { @@ -913,10 +914,10 @@ App::DocumentObjectExecReturn* Feature::execute() } if (fMinDist > this->SearchRadius.getValue()) { - fMinDist = FLT_MAX; + fMinDist = std::numeric_limits::max(); } else if (-fMinDist > this->SearchRadius.getValue()) { - fMinDist = -FLT_MAX; + fMinDist = -std::numeric_limits::max(); } else { res.m_sumsq += fMinDist * fMinDist; diff --git a/src/Mod/Inspection/Gui/PreCompiled.h b/src/Mod/Inspection/Gui/PreCompiled.h index d6afd093c4..d304568b6a 100644 --- a/src/Mod/Inspection/Gui/PreCompiled.h +++ b/src/Mod/Inspection/Gui/PreCompiled.h @@ -35,7 +35,6 @@ #ifdef _PreComp_ // STL -#include // Inventor #include diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.h b/src/Mod/Inspection/Gui/ViewProviderInspection.h index f311da9b45..ca3a575502 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.h +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.h @@ -107,7 +107,7 @@ private: SoCoordinate3* pcCoords; private: - float search_radius {FLT_MAX}; + float search_radius {std::numeric_limits::max()}; static bool addflag; static App::PropertyFloatConstraint::Constraints floatRange; }; diff --git a/src/Mod/Inspection/Gui/VisualInspection.cpp b/src/Mod/Inspection/Gui/VisualInspection.cpp index afaaad9845..4170624344 100644 --- a/src/Mod/Inspection/Gui/VisualInspection.cpp +++ b/src/Mod/Inspection/Gui/VisualInspection.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #endif #include @@ -100,9 +99,9 @@ VisualInspection::VisualInspection(QWidget* parent, Qt::WindowFlags fl) ui->textLabel2->hide(); ui->thickness->hide(); ui->searchRadius->setUnit(Base::Unit::Length); - ui->searchRadius->setRange(0, DBL_MAX); + ui->searchRadius->setRange(0, std::numeric_limits::max()); ui->thickness->setUnit(Base::Unit::Length); - ui->thickness->setRange(0, DBL_MAX); + ui->thickness->setRange(0, std::numeric_limits::max()); App::Document* doc = App::GetApplication().getActiveDocument(); // disable Ok button and enable of at least one item in each view is on From 42e219a9fd1248e2ae416d4f0808cb387bbc8ea7 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:10 +0100 Subject: [PATCH 045/316] Material: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Material/App/PreCompiled.h | 1 - src/Mod/Material/Gui/ArrayDelegate.cpp | 2 +- src/Mod/Material/Gui/BaseDelegate.cpp | 2 +- src/Mod/Material/Gui/MaterialDelegate.cpp | 2 +- src/Mod/Material/Gui/PreCompiled.h | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Mod/Material/App/PreCompiled.h b/src/Mod/Material/App/PreCompiled.h index 085b2d5ca4..255a52e0de 100644 --- a/src/Mod/Material/App/PreCompiled.h +++ b/src/Mod/Material/App/PreCompiled.h @@ -42,7 +42,6 @@ #ifdef _PreComp_ // standard -#include #include // STL diff --git a/src/Mod/Material/Gui/ArrayDelegate.cpp b/src/Mod/Material/Gui/ArrayDelegate.cpp index 38f6f14246..91ff581927 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.cpp +++ b/src/Mod/Material/Gui/ArrayDelegate.cpp @@ -125,7 +125,7 @@ QWidget* ArrayDelegate::createWidget(QWidget* parent, const QVariant& item) cons else if (_type == Materials::MaterialValue::Integer) { Gui::UIntSpinBox* spinner = new Gui::UIntSpinBox(parent); spinner->setMinimum(0); - spinner->setMaximum(UINT_MAX); + spinner->setMaximum(std::numeric_limits::max()); spinner->setValue(item.toUInt()); widget = spinner; } diff --git a/src/Mod/Material/Gui/BaseDelegate.cpp b/src/Mod/Material/Gui/BaseDelegate.cpp index 27123a2a0e..12291aaf93 100644 --- a/src/Mod/Material/Gui/BaseDelegate.cpp +++ b/src/Mod/Material/Gui/BaseDelegate.cpp @@ -414,7 +414,7 @@ BaseDelegate::createWidget(QWidget* parent, const QVariant& item, const QModelIn if (type == Materials::MaterialValue::Integer) { auto spinner = new Gui::UIntSpinBox(parent); spinner->setMinimum(0); - spinner->setMaximum(UINT_MAX); + spinner->setMaximum(std::numeric_limits::max()); spinner->setValue(item.toUInt()); widget = spinner; } diff --git a/src/Mod/Material/Gui/MaterialDelegate.cpp b/src/Mod/Material/Gui/MaterialDelegate.cpp index 7e58258bc0..ad36b74462 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.cpp +++ b/src/Mod/Material/Gui/MaterialDelegate.cpp @@ -424,7 +424,7 @@ QWidget* MaterialDelegate::createWidget(QWidget* parent, if (type == Materials::MaterialValue::Integer) { auto spinner = new Gui::IntSpinBox(parent); spinner->setMinimum(0); - spinner->setMaximum(INT_MAX); + spinner->setMaximum(std::numeric_limits::max()); spinner->setValue(item.toInt()); widget = spinner; } diff --git a/src/Mod/Material/Gui/PreCompiled.h b/src/Mod/Material/Gui/PreCompiled.h index 85b68f8801..aef9192070 100644 --- a/src/Mod/Material/Gui/PreCompiled.h +++ b/src/Mod/Material/Gui/PreCompiled.h @@ -42,7 +42,6 @@ #ifdef _PreComp_ // standard -#include #include #include From bc462c44cc5034a3a51240e8228c784c184fbe98 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:17 +0100 Subject: [PATCH 046/316] Measure: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Measure/App/MeasureAngle.cpp | 2 +- src/Mod/Measure/App/PreCompiled.h | 1 - src/Mod/Measure/Gui/PreCompiled.h | 1 - src/Mod/Measure/Gui/ViewProviderMeasureAngle.cpp | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Mod/Measure/App/MeasureAngle.cpp b/src/Mod/Measure/App/MeasureAngle.cpp index 73021f0b4e..5e72fbe5b4 100644 --- a/src/Mod/Measure/App/MeasureAngle.cpp +++ b/src/Mod/Measure/App/MeasureAngle.cpp @@ -108,7 +108,7 @@ bool MeasureAngle::isPrioritizedSelection(const App::MeasureSelection& selection getVec(*ob2, sub2, vec2); - double angle = std::fmod(vec1.GetAngle(vec2), D_PI); + double angle = std::fmod(vec1.GetAngle(vec2), std::numbers::pi); return angle > Base::Precision::Angular(); } diff --git a/src/Mod/Measure/App/PreCompiled.h b/src/Mod/Measure/App/PreCompiled.h index c3f684ddc1..ee6e3a5092 100644 --- a/src/Mod/Measure/App/PreCompiled.h +++ b/src/Mod/Measure/App/PreCompiled.h @@ -30,7 +30,6 @@ #ifdef _PreComp_ // standard -#include #include // STL diff --git a/src/Mod/Measure/Gui/PreCompiled.h b/src/Mod/Measure/Gui/PreCompiled.h index a2a4065edf..c897421afa 100644 --- a/src/Mod/Measure/Gui/PreCompiled.h +++ b/src/Mod/Measure/Gui/PreCompiled.h @@ -44,7 +44,6 @@ #ifdef _PreComp_ // standard -#include #include // STL diff --git a/src/Mod/Measure/Gui/ViewProviderMeasureAngle.cpp b/src/Mod/Measure/Gui/ViewProviderMeasureAngle.cpp index 5c1efba5f3..33cfbd62b2 100644 --- a/src/Mod/Measure/Gui/ViewProviderMeasureAngle.cpp +++ b/src/Mod/Measure/Gui/ViewProviderMeasureAngle.cpp @@ -325,7 +325,7 @@ void ViewProviderMeasureAngle::redrawAnnotation() { auto obj = dynamic_cast(getMeasureObject()); double angleDeg = obj->Angle.getValue(); - constexpr double radiansPerDegree = M_PI / 180.0; + constexpr double radiansPerDegree = std::numbers::pi / 180.0; this->fieldAngle = angleDeg * radiansPerDegree; // Set matrix From a9c66476f8c23af28217357c96d33d690fa5d2fe Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:24 +0100 Subject: [PATCH 047/316] Mesh: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Mesh/App/Core/Algorithm.cpp | 13 ++-- src/Mod/Mesh/App/Core/Approximation.cpp | 62 +++++++++---------- src/Mod/Mesh/App/Core/Approximation.h | 3 +- src/Mod/Mesh/App/Core/Curvature.cpp | 8 +-- src/Mod/Mesh/App/Core/CylinderFit.cpp | 22 +++---- src/Mod/Mesh/App/Core/Decimation.cpp | 2 +- src/Mod/Mesh/App/Core/Definitions.h | 25 ++------ src/Mod/Mesh/App/Core/Elements.cpp | 12 ++-- src/Mod/Mesh/App/Core/Elements.h | 9 ++- src/Mod/Mesh/App/Core/Grid.cpp | 12 ++-- src/Mod/Mesh/App/Core/Grid.h | 2 +- src/Mod/Mesh/App/Core/Iterator.h | 1 - src/Mod/Mesh/App/Core/MeshKernel.cpp | 6 +- src/Mod/Mesh/App/Core/Projection.cpp | 2 +- src/Mod/Mesh/App/Core/Segmentation.cpp | 8 +-- src/Mod/Mesh/App/Core/Simplify.h | 5 -- src/Mod/Mesh/App/Core/Smoothing.h | 3 +- src/Mod/Mesh/App/Core/SphereFit.cpp | 18 +++--- src/Mod/Mesh/App/Core/Tools.h | 2 +- src/Mod/Mesh/App/Core/TopoAlgorithm.cpp | 47 ++++++++------ src/Mod/Mesh/App/Core/Triangulation.cpp | 11 ++-- src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp | 2 +- src/Mod/Mesh/App/FeatureMeshSolid.cpp | 6 +- src/Mod/Mesh/App/MeshFeaturePyImp.cpp | 2 +- src/Mod/Mesh/App/MeshPoint.h | 5 +- src/Mod/Mesh/App/MeshPointPyImp.cpp | 4 +- src/Mod/Mesh/App/PreCompiled.h | 1 - src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp | 8 +-- src/Mod/Mesh/App/WildMagic4/Wm4System.h | 1 - src/Mod/Mesh/Gui/Command.cpp | 2 +- src/Mod/Mesh/Gui/DlgRegularSolidImp.cpp | 32 +++++----- src/Mod/Mesh/Gui/MeshEditor.cpp | 4 +- src/Mod/Mesh/Gui/MeshSelection.cpp | 1 - src/Mod/Mesh/Gui/PreCompiled.h | 1 - src/Mod/Mesh/Gui/RemoveComponents.cpp | 4 +- src/Mod/Mesh/Gui/Segmentation.cpp | 17 ++--- src/Mod/Mesh/Gui/SegmentationBestFit.cpp | 14 ++--- src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp | 3 +- src/Mod/Mesh/Gui/SoFCMeshObject.cpp | 5 +- src/Mod/Mesh/Gui/SoPolygon.cpp | 6 +- 40 files changed, 187 insertions(+), 204 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index 9b9ebc1b64..3f513925f8 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -295,7 +295,7 @@ float MeshAlgorithm::GetAverageEdgeLength() const float MeshAlgorithm::GetMinimumEdgeLength() const { - float fLen = FLOAT_MAX; + float fLen = std::numeric_limits::max(); MeshFacetIterator cF(_rclMesh); for (cF.Init(); cF.More(); cF.Next()) { for (int i = 0; i < 3; i++) { @@ -785,19 +785,20 @@ bool MeshAlgorithm::FillupHole(const std::vector& boundary, } } + constexpr auto max = std::numeric_limits::max(); // Get the new neighbour to our reference facet MeshFacet facet; unsigned short ref_side = rFace.Side(refPoint0, refPoint1); - unsigned short tri_side = USHRT_MAX; + unsigned short tri_side = max; if (cTria.NeedsReindexing()) { // the referenced indices of the polyline refPoint0 = 0; refPoint1 = 1; } - if (ref_side < USHRT_MAX) { + if (ref_side < max) { for (const auto& face : faces) { tri_side = face.Side(refPoint0, refPoint1); - if (tri_side < USHRT_MAX) { + if (tri_side < max) { facet = face; break; } @@ -805,7 +806,7 @@ bool MeshAlgorithm::FillupHole(const std::vector& boundary, } // in case the reference facet has not an open edge print a log message - if (ref_side == USHRT_MAX || tri_side == USHRT_MAX) { + if (ref_side == max || tri_side == max) { Base::Console().Log( "MeshAlgorithm::FillupHole: Expected open edge for facet <%d, %d, %d>\n", rFace._aulPoints[0], @@ -1461,7 +1462,7 @@ bool MeshAlgorithm::NearestPointFromPoint(const Base::Vector3f& rclPt, } // calc each facet - float fMinDist = FLOAT_MAX; + float fMinDist = std::numeric_limits::max(); FacetIndex ulInd = FACET_INDEX_MAX; MeshFacetIterator pF(_rclMesh); for (pF.Init(); pF.More(); pF.Next()) { diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index 8b728ece41..cf7123a9ed 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -143,7 +143,7 @@ float PlaneFit::Fit() { _bIsFitted = true; if (CountPoints() < 3) { - return FLOAT_MAX; + return std::numeric_limits::max(); } double sxx {0.0}; @@ -207,7 +207,7 @@ float PlaneFit::Fit() akMat.EigenDecomposition(rkRot, rkDiag); } catch (const std::exception&) { - return FLOAT_MAX; + return std::numeric_limits::max(); } // We know the Eigenvalues are ordered @@ -215,7 +215,7 @@ float PlaneFit::Fit() // // points describe a line or even are identical if (rkDiag(1, 1) <= 0) { - return FLOAT_MAX; + return std::numeric_limits::max(); } Wm4::Vector3 U = rkRot.GetColumn(1); @@ -225,7 +225,7 @@ float PlaneFit::Fit() // It may happen that the result have nan values for (int i = 0; i < 3; i++) { if (boost::math::isnan(W[i])) { - return FLOAT_MAX; + return std::numeric_limits::max(); } } @@ -253,7 +253,7 @@ float PlaneFit::Fit() // In case sigma is nan if (boost::math::isnan(sigma)) { - return FLOAT_MAX; + return std::numeric_limits::max(); } // This must be caused by some round-off errors. Theoretically it's impossible @@ -318,7 +318,7 @@ Base::Vector3f PlaneFit::GetNormal() const float PlaneFit::GetDistanceToPlane(const Base::Vector3f& rcPoint) const { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (_bIsFitted) { fResult = (rcPoint - _vBase) * _vDirW; } @@ -332,7 +332,7 @@ float PlaneFit::GetStdDeviation() const // Standard deviation: SD=SQRT(VAR) // Standard error of the mean: SE=SD/SQRT(N) if (!_bIsFitted) { - return FLOAT_MAX; + return std::numeric_limits::max(); } float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; @@ -356,11 +356,11 @@ float PlaneFit::GetSignedStdDeviation() const // of normal direction the value will be // positive otherwise negative if (!_bIsFitted) { - return FLOAT_MAX; + return std::numeric_limits::max(); } float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; - float fMinDist = FLOAT_MAX; + float fMinDist = std::numeric_limits::max(); float fFactor = 0.0F; float ulPtCt = float(CountPoints()); @@ -426,7 +426,7 @@ void PlaneFit::Dimension(float& length, float& width) const std::vector PlaneFit::GetLocalPoints() const { std::vector localPoints; - if (_bIsFitted && _fLastResult < FLOAT_MAX) { + if (_bIsFitted && _fLastResult < std::numeric_limits::max()) { Base::Vector3d bs = Base::convertTo(this->_vBase); Base::Vector3d ex = Base::convertTo(this->_vDirU); Base::Vector3d ey = Base::convertTo(this->_vDirV); @@ -507,12 +507,12 @@ double QuadraticFit::GetCoeff(std::size_t ulIndex) const return _fCoeff[ulIndex]; } - return double(FLOAT_MAX); + return double(std::numeric_limits::max()); } float QuadraticFit::Fit() { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (CountPoints() > 0) { std::vector> cPts; @@ -595,14 +595,14 @@ void QuadraticFit::CalcZValues(double x, double y, double& dZ1, double& dZ2) con - 4 * _fCoeff[6] * _fCoeff[4] * x * x - 4 * _fCoeff[6] * _fCoeff[5] * y * y; if (fabs(_fCoeff[6]) < 0.000005) { - dZ1 = double(FLOAT_MAX); - dZ2 = double(FLOAT_MAX); + dZ1 = double(std::numeric_limits::max()); + dZ2 = double(std::numeric_limits::max()); return; } if (dDisk < 0.0) { - dZ1 = double(FLOAT_MAX); - dZ2 = double(FLOAT_MAX); + dZ1 = double(std::numeric_limits::max()); + dZ2 = double(std::numeric_limits::max()); return; } @@ -620,7 +620,7 @@ SurfaceFit::SurfaceFit() float SurfaceFit::Fit() { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (CountPoints() > 0) { fResult = float(PolynomFit()); @@ -671,8 +671,8 @@ bool SurfaceFit::GetCurvatureInfo(double x, double y, double z, double& rfCurv0, double SurfaceFit::PolynomFit() { - if (PlaneFit::Fit() >= FLOAT_MAX) { - return double(FLOAT_MAX); + if (PlaneFit::Fit() >= std::numeric_limits::max()) { + return double(std::numeric_limits::max()); } Base::Vector3d bs = Base::convertTo(this->_vBase); @@ -1165,7 +1165,7 @@ void CylinderFit::SetInitialValues(const Base::Vector3f& b, const Base::Vector3f float CylinderFit::Fit() { if (CountPoints() < 7) { - return FLOAT_MAX; + return std::numeric_limits::max(); } _bIsFitted = true; @@ -1180,7 +1180,7 @@ float CylinderFit::Fit() } float result = cylFit.Fit(); - if (result < FLOAT_MAX) { + if (result < std::numeric_limits::max()) { Base::Vector3d base = cylFit.GetBase(); Base::Vector3d dir = cylFit.GetAxis(); @@ -1284,7 +1284,7 @@ Base::Vector3f CylinderFit::GetAxis() const float CylinderFit::GetDistanceToCylinder(const Base::Vector3f& rcPoint) const { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (_bIsFitted) { fResult = rcPoint.DistanceToLine(_vBase, _vAxis) - _fRadius; } @@ -1298,7 +1298,7 @@ float CylinderFit::GetStdDeviation() const // Standard deviation: SD=SQRT(VAR) // Standard error of the mean: SE=SD/SQRT(N) if (!_bIsFitted) { - return FLOAT_MAX; + return std::numeric_limits::max(); } float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; @@ -1318,8 +1318,8 @@ float CylinderFit::GetStdDeviation() const void CylinderFit::GetBounding(Base::Vector3f& bottom, Base::Vector3f& top) const { - float distMin = FLT_MAX; - float distMax = FLT_MIN; + float distMin = std::numeric_limits::max(); + float distMax = std::numeric_limits::min(); std::list::const_iterator cIt; for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt) { @@ -1384,7 +1384,7 @@ float SphereFit::GetRadius() const return _fRadius; } - return FLOAT_MAX; + return std::numeric_limits::max(); } Base::Vector3f SphereFit::GetCenter() const @@ -1400,7 +1400,7 @@ float SphereFit::Fit() { _bIsFitted = true; if (CountPoints() < 4) { - return FLOAT_MAX; + return std::numeric_limits::max(); } std::vector input; @@ -1433,7 +1433,7 @@ float SphereFit::Fit() sphereFit.AddPoints(_vPoints); sphereFit.ComputeApproximations(); float result = sphereFit.Fit(); - if (result < FLOAT_MAX) { + if (result < std::numeric_limits::max()) { Base::Vector3d center = sphereFit.GetCenter(); #if defined(_DEBUG) Base::Console().Message("MeshCoreFit::Sphere Fit: Center: (%0.4f, %0.4f, %0.4f), Radius: " @@ -1455,7 +1455,7 @@ float SphereFit::Fit() float SphereFit::GetDistanceToSphere(const Base::Vector3f& rcPoint) const { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (_bIsFitted) { fResult = Base::Vector3f(rcPoint - _vCenter).Length() - _fRadius; } @@ -1469,7 +1469,7 @@ float SphereFit::GetStdDeviation() const // Standard deviation: SD=SQRT(VAR) // Standard error of the mean: SE=SD/SQRT(N) if (!_bIsFitted) { - return FLOAT_MAX; + return std::numeric_limits::max(); } float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; @@ -1533,7 +1533,7 @@ float PolynomialFit::Fit() } } catch (const std::exception&) { - return FLOAT_MAX; + return std::numeric_limits::max(); } return 0.0F; diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 1bbe71ebd5..32e7211390 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -201,7 +201,8 @@ protected: // NOLINTBEGIN std::list _vPoints; /**< Holds the points for the fit algorithm. */ bool _bIsFitted {false}; /**< Flag, whether the fit has been called. */ - float _fLastResult {FLOAT_MAX}; /**< Stores the last result of the fit */ + float _fLastResult { + std::numeric_limits::max()}; /**< Stores the last result of the fit */ // NOLINTEND }; diff --git a/src/Mod/Mesh/App/Core/Curvature.cpp b/src/Mod/Mesh/App/Core/Curvature.cpp index 07334f7785..15b2c8733b 100644 --- a/src/Mod/Mesh/App/Core/Curvature.cpp +++ b/src/Mod/Mesh/App/Core/Curvature.cpp @@ -423,14 +423,14 @@ CurvatureInfo FacetCurvature::Compute(FacetIndex index) const fMax = (float)dMax; } else { - fMin = FLT_MAX; - fMax = FLT_MAX; + fMin = std::numeric_limits::max(); + fMax = std::numeric_limits::max(); } } else { // too few points => cannot calc any properties - fMin = FLT_MAX; - fMax = FLT_MAX; + fMin = std::numeric_limits::max(); + fMax = std::numeric_limits::max(); } CurvatureInfo info; diff --git a/src/Mod/Mesh/App/Core/CylinderFit.cpp b/src/Mod/Mesh/App/Core/CylinderFit.cpp index face997e6b..cc44aa2d74 100644 --- a/src/Mod/Mesh/App/Core/CylinderFit.cpp +++ b/src/Mod/Mesh/App/Core/CylinderFit.cpp @@ -81,7 +81,7 @@ void CylinderFit::SetApproximations(double radius, const Base::Vector3d& axis) { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; _dRadius = radius; _vBase = base; @@ -94,7 +94,7 @@ void CylinderFit::SetApproximations(double radius, void CylinderFit::SetApproximations(const Base::Vector3d& base, const Base::Vector3d& axis) { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; _vBase = base; _vAxis = axis; @@ -168,7 +168,7 @@ int CylinderFit::GetNumIterations() const float CylinderFit::GetDistanceToCylinder(const Base::Vector3f& rcPoint) const { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (_bIsFitted) { Base::Vector3d pt(rcPoint.x, rcPoint.y, rcPoint.z); fResult = static_cast(pt.DistanceToLine(_vBase, _vAxis) - _dRadius); @@ -182,7 +182,7 @@ float CylinderFit::GetStdDeviation() const // Variance: VAR=(N/N-1)*[(1/N)*SUM(Xi^2)-M^2] // Standard deviation: SD=SQRT(VAR) if (!_bIsFitted) { - return FLOAT_MAX; + return std::numeric_limits::max(); } double sumXi = 0.0; @@ -239,7 +239,7 @@ void CylinderFit::ProjectToCylinder() void CylinderFit::ComputeApproximationsLine() { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; _vBase.Set(0.0, 0.0, 0.0); _vAxis.Set(0.0, 0.0, 0.0); @@ -266,13 +266,13 @@ void CylinderFit::ComputeApproximationsLine() float CylinderFit::Fit() { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; // A minimum of 5 surface points is needed to define a cylinder const int minPts = 5; if (CountPoints() < minPts) { - return FLOAT_MAX; + return std::numeric_limits::max(); } // If approximations have not been set/computed then compute some now using the line fit method @@ -308,7 +308,7 @@ float CylinderFit::Fit() // Solve the equations for the unknown corrections Eigen::LLT llt(atpa); if (llt.info() != Eigen::Success) { - return FLOAT_MAX; + return std::numeric_limits::max(); } Eigen::VectorXd x = llt.solve(atpl); @@ -327,7 +327,7 @@ float CylinderFit::Fit() // convergence bool vConverged {}; if (!computeResiduals(solDir, x, residuals, sigma0, _vConvLimit, vConverged)) { - return FLOAT_MAX; + return std::numeric_limits::max(); } if (!vConverged) { cont = true; @@ -335,13 +335,13 @@ float CylinderFit::Fit() // Update the parameters if (!updateParameters(solDir, x)) { - return FLOAT_MAX; + return std::numeric_limits::max(); } } // Check for convergence if (cont) { - return FLOAT_MAX; + return std::numeric_limits::max(); } _bIsFitted = true; diff --git a/src/Mod/Mesh/App/Core/Decimation.cpp b/src/Mod/Mesh/App/Core/Decimation.cpp index 096b438add..da40713799 100644 --- a/src/Mod/Mesh/App/Core/Decimation.cpp +++ b/src/Mod/Mesh/App/Core/Decimation.cpp @@ -123,7 +123,7 @@ void MeshSimplify::simplify(int targetSize) } // Simplification starts - alg.simplify_mesh(targetSize, FLT_MAX); + alg.simplify_mesh(targetSize, std::numeric_limits::max()); // Simplification done MeshPointArray new_points; diff --git a/src/Mod/Mesh/App/Core/Definitions.h b/src/Mod/Mesh/App/Core/Definitions.h index e8b2569d20..7802c3c512 100644 --- a/src/Mod/Mesh/App/Core/Definitions.h +++ b/src/Mod/Mesh/App/Core/Definitions.h @@ -27,7 +27,7 @@ #include #endif -#include +#include // default values #define MESH_MIN_PT_DIST 1.0e-6F @@ -36,33 +36,16 @@ #define MESH_REMOVE_MIN_LEN true #define MESH_REMOVE_G3_EDGES true -/* - * general constant definitions - */ -#define FLOAT_EPS 1.0e-4F - -#ifndef FLOAT_MAX -#define FLOAT_MAX 1e30F -#endif - -#ifndef DOUBLE_MAX -#define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ -#endif - -#ifndef DOUBLE_MIN -#define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ -#endif - namespace MeshCore { // type definitions using ElementIndex = unsigned long; -const ElementIndex ELEMENT_INDEX_MAX = ULONG_MAX; +const ElementIndex ELEMENT_INDEX_MAX = std::numeric_limits::max(); using FacetIndex = ElementIndex; -const FacetIndex FACET_INDEX_MAX = ULONG_MAX; +const FacetIndex FACET_INDEX_MAX = std::numeric_limits::max(); using PointIndex = ElementIndex; -const PointIndex POINT_INDEX_MAX = ULONG_MAX; +const PointIndex POINT_INDEX_MAX = std::numeric_limits::max(); template class Math diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index 5d365251db..428358f9ca 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -1309,9 +1309,9 @@ unsigned short MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt) co const Base::Vector3f& rcP2 = _aclPoints[1]; const Base::Vector3f& rcP3 = _aclPoints[2]; - float fD1 = FLOAT_MAX; - float fD2 = FLOAT_MAX; - float fD3 = FLOAT_MAX; + float fD1 = std::numeric_limits::max(); + float fD2 = std::numeric_limits::max(); + float fD3 = std::numeric_limits::max(); // 1st edge Base::Vector3f clDir = rcP2 - rcP1; @@ -1383,9 +1383,9 @@ void MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt, const Base::Vector3f& rcP2 = _aclPoints[1]; const Base::Vector3f& rcP3 = _aclPoints[2]; - float fD1 = FLOAT_MAX; - float fD2 = FLOAT_MAX; - float fD3 = FLOAT_MAX; + float fD1 = std::numeric_limits::max(); + float fD2 = std::numeric_limits::max(); + float fD3 = std::numeric_limits::max(); // 1st edge Base::Vector3f clDir = rcP2 - rcP1; diff --git a/src/Mod/Mesh/App/Core/Elements.h b/src/Mod/Mesh/App/Core/Elements.h index 2181301bca..1c2521576f 100644 --- a/src/Mod/Mesh/App/Core/Elements.h +++ b/src/Mod/Mesh/App/Core/Elements.h @@ -23,7 +23,6 @@ #ifndef MESH_ELEMENTS_H #define MESH_ELEMENTS_H -#include #include #include #include @@ -1147,7 +1146,7 @@ inline unsigned short MeshFacet::Side(FacetIndex ulNIndex) const return 2; } - return USHRT_MAX; + return std::numeric_limits::max(); } inline unsigned short MeshFacet::Side(PointIndex ulP0, PointIndex ulP1) const @@ -1177,7 +1176,7 @@ inline unsigned short MeshFacet::Side(PointIndex ulP0, PointIndex ulP1) const } } - return USHRT_MAX; + return std::numeric_limits::max(); } inline unsigned short MeshFacet::Side(const MeshFacet& rFace) const @@ -1185,12 +1184,12 @@ inline unsigned short MeshFacet::Side(const MeshFacet& rFace) const unsigned short side {}; for (int i = 0; i < 3; i++) { side = Side(rFace._aulPoints[i], rFace._aulPoints[(i + 1) % 3]); - if (side != USHRT_MAX) { + if (side != std::numeric_limits::max()) { return side; } } - return USHRT_MAX; + return std::numeric_limits::max(); } inline bool MeshFacet::IsEqual(const MeshFacet& rcFace) const diff --git a/src/Mod/Mesh/App/Core/Grid.cpp b/src/Mod/Mesh/App/Core/Grid.cpp index 603650ed7b..083d834f10 100644 --- a/src/Mod/Mesh/App/Core/Grid.cpp +++ b/src/Mod/Mesh/App/Core/Grid.cpp @@ -639,7 +639,7 @@ unsigned long MeshGrid::GetIndexToPosition(unsigned long ulX, unsigned long ulY, unsigned long ulZ) const { if (!CheckPos(ulX, ulY, ulZ)) { - return ULONG_MAX; + return std::numeric_limits::max(); } return (ulZ * _ulCtGridsY + ulY) * _ulCtGridsX + ulX; } @@ -654,9 +654,9 @@ bool MeshGrid::GetPositionToIndex(unsigned long id, ulZ = id / (_ulCtGridsX * _ulCtGridsY); if (!CheckPos(ulX, ulY, ulZ)) { - ulX = ULONG_MAX; - ulY = ULONG_MAX; - ulZ = ULONG_MAX; + ulX = std::numeric_limits::max(); + ulY = std::numeric_limits::max(); + ulZ = std::numeric_limits::max(); return false; } @@ -760,7 +760,7 @@ void MeshFacetGrid::RebuildGrid() unsigned long MeshFacetGrid::SearchNearestFromPoint(const Base::Vector3f& rclPt) const { ElementIndex ulFacetInd = ELEMENT_INDEX_MAX; - float fMinDist = FLOAT_MAX; + float fMinDist = std::numeric_limits::max(); Base::BoundBox3f clBB = GetBoundBox(); if (clBB.IsInBox(rclPt)) { // Point lies within @@ -1154,7 +1154,7 @@ bool MeshGridIterator::InitOnRay(const Base::Vector3f& rclPt, // needed in NextOnRay() to avoid an infinite loop _cSearchPositions.clear(); - _fMaxSearchArea = FLOAT_MAX; + _fMaxSearchArea = std::numeric_limits::max(); raulElements.clear(); diff --git a/src/Mod/Mesh/App/Core/Grid.h b/src/Mod/Mesh/App/Core/Grid.h index 3cd9990ce9..e5f9c46360 100644 --- a/src/Mod/Mesh/App/Core/Grid.h +++ b/src/Mod/Mesh/App/Core/Grid.h @@ -447,7 +447,7 @@ private: Base::Vector3f _clPt; /**< Base point of search ray. */ Base::Vector3f _clDir; /**< Direction of search ray. */ bool _bValidRay {false}; /**< Search ray ok? */ - float _fMaxSearchArea {FLOAT_MAX}; + float _fMaxSearchArea {std::numeric_limits::max()}; /** Checks if a grid position is already visited by NextOnRay(). */ struct GridElement { diff --git a/src/Mod/Mesh/App/Core/Iterator.h b/src/Mod/Mesh/App/Core/Iterator.h index 4b8c5dddd3..3b7d741d02 100644 --- a/src/Mod/Mesh/App/Core/Iterator.h +++ b/src/Mod/Mesh/App/Core/Iterator.h @@ -23,7 +23,6 @@ #ifndef MESH_ITERATOR_H #define MESH_ITERATOR_H -#include #include diff --git a/src/Mod/Mesh/App/Core/MeshKernel.cpp b/src/Mod/Mesh/App/Core/MeshKernel.cpp index be46d392c4..b2def70220 100644 --- a/src/Mod/Mesh/App/Core/MeshKernel.cpp +++ b/src/Mod/Mesh/App/Core/MeshKernel.cpp @@ -310,7 +310,7 @@ unsigned long MeshKernel::AddFacets(const std::vector& rclFAry, bool if (ulF0 != FACET_INDEX_MAX) { unsigned short usSide = _aclFacetArray[ulF0].Side(ulP0, ulP1); - assert(usSide != USHRT_MAX); + assert(usSide != std::numeric_limits::max()); _aclFacetArray[ulF0]._aulNeighbours[usSide] = FACET_INDEX_MAX; } } @@ -342,13 +342,13 @@ unsigned long MeshKernel::AddFacets(const std::vector& rclFAry, bool if (ulF0 != FACET_INDEX_MAX) { unsigned short usSide = _aclFacetArray[ulF0].Side(ulP0, ulP1); - assert(usSide != USHRT_MAX); + assert(usSide != std::numeric_limits::max()); _aclFacetArray[ulF0]._aulNeighbours[usSide] = ulF1; } if (ulF1 != FACET_INDEX_MAX) { unsigned short usSide = _aclFacetArray[ulF1].Side(ulP0, ulP1); - assert(usSide != USHRT_MAX); + assert(usSide != std::numeric_limits::max()); _aclFacetArray[ulF1]._aulNeighbours[usSide] = ulF0; } } diff --git a/src/Mod/Mesh/App/Core/Projection.cpp b/src/Mod/Mesh/App/Core/Projection.cpp index b3bd4d584e..06c676b234 100644 --- a/src/Mod/Mesh/App/Core/Projection.cpp +++ b/src/Mod/Mesh/App/Core/Projection.cpp @@ -78,7 +78,7 @@ bool MeshProjection::connectLines(std::list& polyline) const { - const float fMaxDist = float(std::sqrt(FLOAT_MAX)); // max. length of a gap + const float fMaxDist = std::sqrt(std::numeric_limits::max()); // max. length of a gap const float fMinEps = 1.0e-4F; polyline.clear(); diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index f21245dbe8..5fd0dd410f 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -201,7 +201,7 @@ std::vector PlaneSurfaceFit::Parameters() const // -------------------------------------------------------- CylinderSurfaceFit::CylinderSurfaceFit() - : radius(FLOAT_MAX) + : radius(std::numeric_limits::max()) , fitter(new CylinderFit) { axis.Set(0, 0, 0); @@ -266,7 +266,7 @@ float CylinderSurfaceFit::Fit() } float fit = fitter->Fit(); - if (fit < FLOAT_MAX) { + if (fit < std::numeric_limits::max()) { basepoint = fitter->GetBase(); axis = fitter->GetAxis(); radius = fitter->GetRadius(); @@ -309,7 +309,7 @@ std::vector CylinderSurfaceFit::Parameters() const // -------------------------------------------------------- SphereSurfaceFit::SphereSurfaceFit() - : radius(FLOAT_MAX) + : radius(std::numeric_limits::max()) , fitter(new SphereFit) { center.Set(0, 0, 0); @@ -367,7 +367,7 @@ float SphereSurfaceFit::Fit() } float fit = fitter->Fit(); - if (fit < FLOAT_MAX) { + if (fit < std::numeric_limits::max()) { center = fitter->GetCenter(); radius = fitter->GetRadius(); } diff --git a/src/Mod/Mesh/App/Core/Simplify.h b/src/Mod/Mesh/App/Core/Simplify.h index e2c0cd6672..d45a3ae7c2 100644 --- a/src/Mod/Mesh/App/Core/Simplify.h +++ b/src/Mod/Mesh/App/Core/Simplify.h @@ -13,11 +13,6 @@ #include - -#ifndef _USE_MATH_DEFINES -#define _USE_MATH_DEFINES -#endif - using vec3f = Base::Vector3f; class SymmetricMatrix { diff --git a/src/Mod/Mesh/App/Core/Smoothing.h b/src/Mod/Mesh/App/Core/Smoothing.h index 6f15ffad2a..4579f01959 100644 --- a/src/Mod/Mesh/App/Core/Smoothing.h +++ b/src/Mod/Mesh/App/Core/Smoothing.h @@ -23,7 +23,6 @@ #ifndef MESH_SMOOTHING_H #define MESH_SMOOTHING_H -#include #include #include "Definitions.h" @@ -88,7 +87,7 @@ public: void SmoothPoints(unsigned int, const std::vector&) override; private: - float maximum {FLT_MAX}; + float maximum {std::numeric_limits::max()}; }; class MeshExport LaplaceSmoothing: public AbstractSmoothing diff --git a/src/Mod/Mesh/App/Core/SphereFit.cpp b/src/Mod/Mesh/App/Core/SphereFit.cpp index 7c7c1ebaad..c53812a1b1 100644 --- a/src/Mod/Mesh/App/Core/SphereFit.cpp +++ b/src/Mod/Mesh/App/Core/SphereFit.cpp @@ -41,7 +41,7 @@ SphereFit::SphereFit() void SphereFit::SetApproximations(double radius, const Base::Vector3d& center) { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; _dRadius = radius; _vCenter = center; @@ -92,7 +92,7 @@ int SphereFit::GetNumIterations() const float SphereFit::GetDistanceToSphere(const Base::Vector3f& rcPoint) const { - float fResult = FLOAT_MAX; + float fResult = std::numeric_limits::max(); if (_bIsFitted) { fResult = Base::Vector3d((double)rcPoint.x - _vCenter.x, (double)rcPoint.y - _vCenter.y, @@ -109,7 +109,7 @@ float SphereFit::GetStdDeviation() const // Variance: VAR=(N/N-1)*[(1/N)*SUM(Xi^2)-M^2] // Standard deviation: SD=SQRT(VAR) if (!_bIsFitted) { - return FLOAT_MAX; + return std::numeric_limits::max(); } double sumXi = 0.0, sumXi2 = 0.0, dist = 0.0; @@ -156,7 +156,7 @@ void SphereFit::ProjectToSphere() void SphereFit::ComputeApproximations() { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; _vCenter.Set(0.0, 0.0, 0.0); _dRadius = 0.0; @@ -182,12 +182,12 @@ void SphereFit::ComputeApproximations() float SphereFit::Fit() { _bIsFitted = false; - _fLastResult = FLOAT_MAX; + _fLastResult = std::numeric_limits::max(); _numIter = 0; // A minimum of 4 surface points is needed to define a sphere if (CountPoints() < 4) { - return FLOAT_MAX; + return std::numeric_limits::max(); } // If approximations have not been set/computed then compute some now @@ -212,7 +212,7 @@ float SphereFit::Fit() // Solve the equations for the unknown corrections Eigen::LLT llt(atpa); if (llt.info() != Eigen::Success) { - return FLOAT_MAX; + return std::numeric_limits::max(); } Eigen::VectorXd x = llt.solve(atpl); @@ -227,7 +227,7 @@ float SphereFit::Fit() // convergence bool vConverged {}; if (!computeResiduals(x, residuals, sigma0, _vConvLimit, vConverged)) { - return FLOAT_MAX; + return std::numeric_limits::max(); } if (!vConverged) { cont = true; @@ -242,7 +242,7 @@ float SphereFit::Fit() // Check for convergence if (cont) { - return FLOAT_MAX; + return std::numeric_limits::max(); } _bIsFitted = true; diff --git a/src/Mod/Mesh/App/Core/Tools.h b/src/Mod/Mesh/App/Core/Tools.h index ab1a49bb96..4c61987538 100644 --- a/src/Mod/Mesh/App/Core/Tools.h +++ b/src/Mod/Mesh/App/Core/Tools.h @@ -209,7 +209,7 @@ public: // NOLINTBEGIN Index nearest_index; - float nearest_dist {FLOAT_MAX}; + float nearest_dist {std::numeric_limits::max()}; // NOLINTEND private: diff --git a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp index dfd38113f2..48d92741de 100644 --- a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp +++ b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp @@ -121,7 +121,7 @@ bool MeshTopoAlgorithm::SnapVertex(FacetIndex ulFacetPos, const Base::Vector3f& float fTV = (rP - rPt1) * (rPt2 - rPt1); // Point is on the edge - if (cNo3.Length() < FLOAT_EPS) { + if (cNo3.Length() < std::numeric_limits::epsilon()) { return SplitOpenEdge(ulFacetPos, i, rP); } if ((rP - rPt1) * cNo2 > 0.0F && fD2 >= fTV && fTV >= 0.0F) { @@ -290,7 +290,7 @@ float MeshTopoAlgorithm::SwapEdgeBenefit(FacetIndex f, int e) const PointIndex v2 = faces[f]._aulPoints[(e + 1) % 3]; PointIndex v3 = faces[f]._aulPoints[(e + 2) % 3]; unsigned short s = faces[n].Side(faces[f]); - if (s == USHRT_MAX) { + if (s == std::numeric_limits::max()) { std::cerr << "MeshTopoAlgorithm::SwapEdgeBenefit: error in neighbourhood " << "of faces " << f << " and " << n << std::endl; return 0.0F; // topological error @@ -600,7 +600,8 @@ bool MeshTopoAlgorithm::IsSwapEdgeLegal(FacetIndex ulFacetPos, FacetIndex ulNeig unsigned short uFSide = rclF.Side(rclN); unsigned short uNSide = rclN.Side(rclF); - if (uFSide == USHRT_MAX || uNSide == USHRT_MAX) { + constexpr auto max = std::numeric_limits::max(); + if (uFSide == max || uNSide == max) { return false; // not neighbours } @@ -686,7 +687,8 @@ void MeshTopoAlgorithm::SwapEdge(FacetIndex ulFacetPos, FacetIndex ulNeighbour) unsigned short uFSide = rclF.Side(rclN); unsigned short uNSide = rclN.Side(rclF); - if (uFSide == USHRT_MAX || uNSide == USHRT_MAX) { + constexpr auto max = std::numeric_limits::max(); + if (uFSide == max || uNSide == max) { return; // not neighbours } @@ -720,7 +722,8 @@ bool MeshTopoAlgorithm::SplitEdge(FacetIndex ulFacetPos, unsigned short uFSide = rclF.Side(rclN); unsigned short uNSide = rclN.Side(rclF); - if (uFSide == USHRT_MAX || uNSide == USHRT_MAX) { + constexpr auto max = std::numeric_limits::max(); + if (uFSide == max || uNSide == max) { return false; // not neighbours } @@ -816,13 +819,13 @@ bool MeshTopoAlgorithm::SplitOpenEdge(FacetIndex ulFacetPos, bool MeshTopoAlgorithm::Vertex_Less::operator()(const Base::Vector3f& u, const Base::Vector3f& v) const { - if (std::fabs(u.x - v.x) > FLOAT_EPS) { + if (std::fabs(u.x - v.x) > std::numeric_limits::epsilon()) { return u.x < v.x; } - if (std::fabs(u.y - v.y) > FLOAT_EPS) { + if (std::fabs(u.y - v.y) > std::numeric_limits::epsilon()) { return u.y < v.y; } - if (std::fabs(u.z - v.z) > FLOAT_EPS) { + if (std::fabs(u.z - v.z) > std::numeric_limits::epsilon()) { return u.z < v.z; } return false; @@ -980,7 +983,8 @@ bool MeshTopoAlgorithm::CollapseEdge(FacetIndex ulFacetPos, FacetIndex ulNeighbo unsigned short uFSide = rclF.Side(rclN); unsigned short uNSide = rclN.Side(rclF); - if (uFSide == USHRT_MAX || uNSide == USHRT_MAX) { + constexpr auto max = std::numeric_limits::max(); + if (uFSide == max || uNSide == max) { return false; // not neighbours } @@ -1214,7 +1218,7 @@ void MeshTopoAlgorithm::SplitFacet(FacetIndex ulFacetPos, MeshPoint& rVertex2 = _rclMesh._aclPointArray[rFace._aulPoints[2]]; auto pointIndex = [=](const Base::Vector3f& rP) { - unsigned short equalP = USHRT_MAX; + unsigned short equalP = std::numeric_limits::max(); if (Base::Distance(rVertex0, rP) < fEps) { equalP = 0; } @@ -1230,16 +1234,17 @@ void MeshTopoAlgorithm::SplitFacet(FacetIndex ulFacetPos, unsigned short equalP1 = pointIndex(rP1); unsigned short equalP2 = pointIndex(rP2); + constexpr auto max = std::numeric_limits::max(); // both points are coincident with the corner points - if (equalP1 != USHRT_MAX && equalP2 != USHRT_MAX) { + if (equalP1 != max && equalP2 != max) { return; // must not split the facet } - if (equalP1 != USHRT_MAX) { + if (equalP1 != max) { // get the edge to the second given point and perform a split edge operation SplitFacetOnOneEdge(ulFacetPos, rP2); } - else if (equalP2 != USHRT_MAX) { + else if (equalP2 != max) { // get the edge to the first given point and perform a split edge operation SplitFacetOnOneEdge(ulFacetPos, rP1); } @@ -1250,8 +1255,8 @@ void MeshTopoAlgorithm::SplitFacet(FacetIndex ulFacetPos, void MeshTopoAlgorithm::SplitFacetOnOneEdge(FacetIndex ulFacetPos, const Base::Vector3f& rP) { - float fMinDist = FLOAT_MAX; - unsigned short iEdgeNo = USHRT_MAX; + float fMinDist = std::numeric_limits::max(); + unsigned short iEdgeNo = std::numeric_limits::max(); MeshFacet& rFace = _rclMesh._aclFacetArray[ulFacetPos]; for (unsigned short i = 0; i < 3; i++) { @@ -1281,8 +1286,10 @@ void MeshTopoAlgorithm::SplitFacetOnTwoEdges(FacetIndex ulFacetPos, const Base::Vector3f& rP2) { // search for the matching edges - unsigned short iEdgeNo1 = USHRT_MAX, iEdgeNo2 = USHRT_MAX; - float fMinDist1 = FLOAT_MAX, fMinDist2 = FLOAT_MAX; + unsigned short iEdgeNo1 = std::numeric_limits::max(); + unsigned short iEdgeNo2 = std::numeric_limits::max(); + float fMinDist1 = std::numeric_limits::max(); + float fMinDist2 = std::numeric_limits::max(); MeshFacet& rFace = _rclMesh._aclFacetArray[ulFacetPos]; for (unsigned short i = 0; i < 3; i++) { @@ -1392,7 +1399,7 @@ void MeshTopoAlgorithm::SplitFacet(FacetIndex ulFacetPos, { MeshFacet& rFace = _rclMesh._aclFacetArray[ulFacetPos]; unsigned short side = rFace.Side(P1, P2); - if (side != USHRT_MAX) { + if (side != std::numeric_limits::max()) { PointIndex V1 = rFace._aulPoints[(side + 1) % 3]; PointIndex V2 = rFace._aulPoints[(side + 2) % 3]; FacetIndex size = _rclMesh._aclFacetArray.size(); @@ -1455,12 +1462,12 @@ void MeshTopoAlgorithm::HarmonizeNeighbours(FacetIndex facet1, FacetIndex facet2 MeshFacet& rFace2 = _rclMesh._aclFacetArray[facet2]; unsigned short side = rFace1.Side(rFace2); - if (side != USHRT_MAX) { + if (side != std::numeric_limits::max()) { rFace1._aulNeighbours[side] = facet2; } side = rFace2.Side(rFace1); - if (side != USHRT_MAX) { + if (side != std::numeric_limits::max()) { rFace2._aulNeighbours[side] = facet1; } } diff --git a/src/Mod/Mesh/App/Core/Triangulation.cpp b/src/Mod/Mesh/App/Core/Triangulation.cpp index f78a00ec42..7d6855b573 100644 --- a/src/Mod/Mesh/App/Core/Triangulation.cpp +++ b/src/Mod/Mesh/App/Core/Triangulation.cpp @@ -144,7 +144,7 @@ Base::Matrix4D AbstractPolygonTriangulator::GetTransformToFitPlane() const planeFit.AddPoint(point); } - if (planeFit.Fit() >= FLOAT_MAX) { + if (planeFit.Fit() >= std::numeric_limits::max()) { throw Base::RuntimeError("Plane fit failed"); } @@ -215,7 +215,7 @@ void AbstractPolygonTriangulator::PostProcessing(const std::vector= uMinPts && polyFit.Fit() < FLOAT_MAX) { + if (polyFit.CountPoints() >= uMinPts && polyFit.Fit() < std::numeric_limits::max()) { for (auto& newpoint : _newpoints) { newpoint.z = static_cast(polyFit.Value(newpoint.x, newpoint.y)); } @@ -377,7 +377,9 @@ bool EarClippingTriangulator::Triangulate::InsideTriangle(float Ax, cCROSSap = cx * apy - cy * apx; bCROSScp = bx * cpy - by * cpx; - return ((aCROSSbp >= FLOAT_EPS) && (bCROSScp >= FLOAT_EPS) && (cCROSSap >= FLOAT_EPS)); + return ((aCROSSbp >= std::numeric_limits::epsilon()) + && (bCROSScp >= std::numeric_limits::epsilon()) + && (cCROSSap >= std::numeric_limits::epsilon())); } bool EarClippingTriangulator::Triangulate::Snip(const std::vector& contour, @@ -399,7 +401,8 @@ bool EarClippingTriangulator::Triangulate::Snip(const std::vector (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) { + constexpr float eps = std::numeric_limits::epsilon(); + if (eps > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) { return false; } diff --git a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp index f402424c98..7cdb9060fe 100644 --- a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp @@ -119,7 +119,7 @@ App::DocumentObjectExecReturn* SegmentByMesh::execute() // now we have too many facets since we have (invisible) facets near to the back clipping // plane, so we need the nearest facet to the front clipping plane // - float fDist = FLOAT_MAX; + float fDist = std::numeric_limits::max(); MeshCore::FacetIndex uIdx = MeshCore::FACET_INDEX_MAX; MeshFacetIterator cFIt(rMeshKernel); diff --git a/src/Mod/Mesh/App/FeatureMeshSolid.cpp b/src/Mod/Mesh/App/FeatureMeshSolid.cpp index 490428e5d2..e2d1a53e76 100644 --- a/src/Mod/Mesh/App/FeatureMeshSolid.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSolid.cpp @@ -29,8 +29,10 @@ namespace Mesh { -const App::PropertyIntegerConstraint::Constraints intSampling = {0, INT_MAX, 1}; -const App::PropertyLength::Constraints floatRange = {0.0, FLT_MAX, 1.0}; +const App::PropertyIntegerConstraint::Constraints intSampling = {0, + std::numeric_limits::max(), + 1}; +const App::PropertyLength::Constraints floatRange = {0.0, std::numeric_limits::max(), 1.0}; } // namespace Mesh using namespace Mesh; diff --git a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp index aaaf58aff0..f3770dac7b 100644 --- a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp +++ b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp @@ -73,7 +73,7 @@ PyObject* MeshFeaturePy::harmonizeNormals(PyObject* args) PyObject* MeshFeaturePy::smooth(PyObject* args) { int iter = 1; - float d_max = FLOAT_MAX; + float d_max = std::numeric_limits::max(); if (!PyArg_ParseTuple(args, "|if", &iter, &d_max)) { return nullptr; } diff --git a/src/Mod/Mesh/App/MeshPoint.h b/src/Mod/Mesh/App/MeshPoint.h index 1b5043b7f2..a29270108e 100644 --- a/src/Mod/Mesh/App/MeshPoint.h +++ b/src/Mod/Mesh/App/MeshPoint.h @@ -23,7 +23,6 @@ #ifndef MESH_MESHPOINT_H #define MESH_MESHPOINT_H -#include #include #include @@ -51,7 +50,7 @@ public: /// simple constructor explicit MeshPoint(const Vector3d& vec = Vector3d(), const MeshObject* obj = nullptr, - unsigned int index = UINT_MAX) + unsigned int index = std::numeric_limits::max()) : Vector3d(vec) , Index(index) , Mesh(obj) @@ -59,7 +58,7 @@ public: bool isBound() const { - return Index != UINT_MAX; + return Index != std::numeric_limits::max(); } unsigned int Index; diff --git a/src/Mod/Mesh/App/MeshPointPyImp.cpp b/src/Mod/Mesh/App/MeshPointPyImp.cpp index 00f0509655..a4b62e1569 100644 --- a/src/Mod/Mesh/App/MeshPointPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPointPyImp.cpp @@ -86,7 +86,7 @@ PyObject* MeshPointPy::unbound(PyObject* args) if (!PyArg_ParseTuple(args, "")) { return nullptr; } - getMeshPointPtr()->Index = UINT_MAX; + getMeshPointPtr()->Index = std::numeric_limits::max(); getMeshPointPtr()->Mesh = nullptr; Py_Return; } @@ -98,7 +98,7 @@ Py::Long MeshPointPy::getIndex() const Py::Boolean MeshPointPy::getBound() const { - return {getMeshPointPtr()->Index != UINT_MAX}; + return {getMeshPointPtr()->Index != std::numeric_limits::max()}; } Py::Object MeshPointPy::getNormal() const diff --git a/src/Mod/Mesh/App/PreCompiled.h b/src/Mod/Mesh/App/PreCompiled.h index 4d4317c9d0..7484b92f22 100644 --- a/src/Mod/Mesh/App/PreCompiled.h +++ b/src/Mod/Mesh/App/PreCompiled.h @@ -39,7 +39,6 @@ // standard #include -#include #include #include #include diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp b/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp index efa1a2f762..f497f0851e 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp +++ b/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp @@ -19,9 +19,9 @@ namespace Wm4 { -template<> WM4_FOUNDATION_ITEM const float Math::EPSILON = FLT_EPSILON; +template<> WM4_FOUNDATION_ITEM const float Math::EPSILON = std::numeric_limits::epsilon(); template<> WM4_FOUNDATION_ITEM const float Math::ZERO_TOLERANCE = 1e-06f; -template<> WM4_FOUNDATION_ITEM const float Math::MAX_REAL = FLT_MAX; +template<> WM4_FOUNDATION_ITEM const float Math::MAX_REAL = std::numeric_limits::max(); template<> WM4_FOUNDATION_ITEM const float Math::PI = (float)(4.0*atan(1.0)); template<> WM4_FOUNDATION_ITEM const float Math::TWO_PI = 2.0f*Math::PI; template<> WM4_FOUNDATION_ITEM const float Math::HALF_PI = 0.5f*Math::PI; @@ -34,9 +34,9 @@ template<> WM4_FOUNDATION_ITEM const float Math::LN_10 = Math::Log template<> WM4_FOUNDATION_ITEM const float Math::INV_LN_2 = 1.0f/Math::LN_2; template<> WM4_FOUNDATION_ITEM const float Math::INV_LN_10 = 1.0f/Math::LN_10; -template<> WM4_FOUNDATION_ITEM const double Math::EPSILON = DBL_EPSILON; +template<> WM4_FOUNDATION_ITEM const double Math::EPSILON = std::numeric_limits::epsilon(); template<> WM4_FOUNDATION_ITEM const double Math::ZERO_TOLERANCE = 1e-08; -template<> WM4_FOUNDATION_ITEM const double Math::MAX_REAL = DBL_MAX; +template<> WM4_FOUNDATION_ITEM const double Math::MAX_REAL = std::numeric_limits::max(); template<> WM4_FOUNDATION_ITEM const double Math::PI = 4.0*atan(1.0); template<> WM4_FOUNDATION_ITEM const double Math::TWO_PI = 2.0*Math::PI; template<> WM4_FOUNDATION_ITEM const double Math::HALF_PI = 0.5*Math::PI; diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4System.h b/src/Mod/Mesh/App/WildMagic4/Wm4System.h index 13d1c815a0..3bd3051a1d 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4System.h +++ b/src/Mod/Mesh/App/WildMagic4/Wm4System.h @@ -23,7 +23,6 @@ // common standard library headers #include #include -#include #include #include #include diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 6411e6ac8d..6bfe41ea90 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -1798,7 +1798,7 @@ void CmdMeshScale::activated(int) QObject::tr("Enter scaling factor:"), 1, 0, - DBL_MAX, + std::numeric_limits::max(), 5, &ok, Qt::MSWindowsFixedSizeDialogHint); diff --git a/src/Mod/Mesh/Gui/DlgRegularSolidImp.cpp b/src/Mod/Mesh/Gui/DlgRegularSolidImp.cpp index 10e996b5fa..1c541831fa 100644 --- a/src/Mod/Mesh/Gui/DlgRegularSolidImp.cpp +++ b/src/Mod/Mesh/Gui/DlgRegularSolidImp.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #endif @@ -55,45 +54,46 @@ DlgRegularSolidImp::DlgRegularSolidImp(QWidget* parent, Qt::WindowFlags fl) Gui::Command::doCommand(Gui::Command::Doc, "import Mesh,BuildRegularGeoms"); // set limits + constexpr double doubleMax = std::numeric_limits::max(); // Box - ui->boxLength->setMaximum(DBL_MAX); + ui->boxLength->setMaximum(doubleMax); ui->boxLength->setMinimum(0); - ui->boxWidth->setMaximum(DBL_MAX); + ui->boxWidth->setMaximum(doubleMax); ui->boxWidth->setMinimum(0); - ui->boxHeight->setMaximum(DBL_MAX); + ui->boxHeight->setMaximum(doubleMax); ui->boxHeight->setMinimum(0); // Cylinder - ui->cylinderRadius->setMaximum(DBL_MAX); + ui->cylinderRadius->setMaximum(doubleMax); ui->cylinderRadius->setMinimum(0); - ui->cylinderLength->setMaximum(DBL_MAX); + ui->cylinderLength->setMaximum(doubleMax); ui->cylinderLength->setMinimum(0); - ui->cylinderEdgeLength->setMaximum(DBL_MAX); + ui->cylinderEdgeLength->setMaximum(doubleMax); ui->cylinderEdgeLength->setMinimum(0); ui->cylinderCount->setMaximum(1000); // Cone - ui->coneRadius1->setMaximum(DBL_MAX); + ui->coneRadius1->setMaximum(doubleMax); ui->coneRadius1->setMinimum(0); - ui->coneRadius2->setMaximum(DBL_MAX); + ui->coneRadius2->setMaximum(doubleMax); ui->coneRadius2->setMinimum(0); - ui->coneLength->setMaximum(DBL_MAX); + ui->coneLength->setMaximum(doubleMax); ui->coneLength->setMinimum(0); - ui->coneEdgeLength->setMaximum(DBL_MAX); + ui->coneEdgeLength->setMaximum(doubleMax); ui->coneEdgeLength->setMinimum(0); ui->coneCount->setMaximum(1000); // Sphere - ui->sphereRadius->setMaximum(DBL_MAX); + ui->sphereRadius->setMaximum(doubleMax); ui->sphereRadius->setMinimum(0); ui->sphereCount->setMaximum(1000); // Ellipsoid - ui->ellipsoidRadius1->setMaximum(DBL_MAX); + ui->ellipsoidRadius1->setMaximum(doubleMax); ui->ellipsoidRadius1->setMinimum(0); - ui->ellipsoidRadius2->setMaximum(DBL_MAX); + ui->ellipsoidRadius2->setMaximum(doubleMax); ui->ellipsoidRadius2->setMinimum(0); ui->ellipsoidCount->setMaximum(1000); // Torus - ui->toroidRadius1->setMaximum(DBL_MAX); + ui->toroidRadius1->setMaximum(doubleMax); ui->toroidRadius1->setMinimum(0); - ui->toroidRadius2->setMaximum(DBL_MAX); + ui->toroidRadius2->setMaximum(doubleMax); ui->toroidRadius2->setMinimum(0); ui->toroidCount->setMaximum(1000); } diff --git a/src/Mod/Mesh/Gui/MeshEditor.cpp b/src/Mod/Mesh/Gui/MeshEditor.cpp index 9c15efd34f..9ffa3ce5a3 100644 --- a/src/Mod/Mesh/Gui/MeshEditor.cpp +++ b/src/Mod/Mesh/Gui/MeshEditor.cpp @@ -318,7 +318,7 @@ void MeshFaceAddition::showMarker(SoPickedPoint* pp) } int point_index = -1; - float distance = FLT_MAX; + float distance = std::numeric_limits::max(); Base::Vector3f pnt; SbVec3f face_pnt; @@ -654,7 +654,7 @@ float MeshFillHole::findClosestPoint(const SbLine& ray, SbVec3f& closestPoint) const { // now check which vertex of the polygon is closest to the ray - float minDist = FLT_MAX; + float minDist = std::numeric_limits::max(); vertex_index = MeshCore::POINT_INDEX_MAX; const MeshCore::MeshKernel& rMesh = myMesh->Mesh.getValue().getKernel(); diff --git a/src/Mod/Mesh/Gui/MeshSelection.cpp b/src/Mod/Mesh/Gui/MeshSelection.cpp index 56876c9b52..728a3a978c 100644 --- a/src/Mod/Mesh/Gui/MeshSelection.cpp +++ b/src/Mod/Mesh/Gui/MeshSelection.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include -#include #include #include diff --git a/src/Mod/Mesh/Gui/PreCompiled.h b/src/Mod/Mesh/Gui/PreCompiled.h index 5db5693792..8fe2574154 100644 --- a/src/Mod/Mesh/Gui/PreCompiled.h +++ b/src/Mod/Mesh/Gui/PreCompiled.h @@ -39,7 +39,6 @@ // standard #include -#include // STL #include diff --git a/src/Mod/Mesh/Gui/RemoveComponents.cpp b/src/Mod/Mesh/Gui/RemoveComponents.cpp index 0f8c9644d5..5e54c225b7 100644 --- a/src/Mod/Mesh/Gui/RemoveComponents.cpp +++ b/src/Mod/Mesh/Gui/RemoveComponents.cpp @@ -41,9 +41,9 @@ RemoveComponents::RemoveComponents(QWidget* parent, Qt::WindowFlags fl) { ui->setupUi(this); setupConnections(); - ui->spSelectComp->setRange(1, INT_MAX); + ui->spSelectComp->setRange(1, std::numeric_limits::max()); ui->spSelectComp->setValue(10); - ui->spDeselectComp->setRange(1, INT_MAX); + ui->spDeselectComp->setRange(1, std::numeric_limits::max()); ui->spDeselectComp->setValue(10); Gui::Selection().clearSelection(); diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp index 235ecd43d4..050e9f5327 100644 --- a/src/Mod/Mesh/Gui/Segmentation.cpp +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -44,18 +44,19 @@ Segmentation::Segmentation(Mesh::Feature* mesh, QWidget* parent, Qt::WindowFlags , ui(new Ui_Segmentation) , myMesh(mesh) { + constexpr int max = std::numeric_limits::max(); ui->setupUi(this); - ui->numPln->setRange(1, INT_MAX); + ui->numPln->setRange(1, max); ui->numPln->setValue(100); - ui->crvCyl->setRange(0, INT_MAX); - ui->numCyl->setRange(1, INT_MAX); + ui->crvCyl->setRange(0, max); + ui->numCyl->setRange(1, max); ui->numCyl->setValue(100); - ui->crvSph->setRange(0, INT_MAX); - ui->numSph->setRange(1, INT_MAX); + ui->crvSph->setRange(0, max); + ui->numSph->setRange(1, max); ui->numSph->setValue(100); - ui->crv1Free->setRange(-INT_MAX, INT_MAX); - ui->crv2Free->setRange(-INT_MAX, INT_MAX); - ui->numFree->setRange(1, INT_MAX); + ui->crv1Free->setRange(-max, max); + ui->crv2Free->setRange(-max, max); + ui->numFree->setRange(1, max); ui->numFree->setValue(100); ui->checkBoxSmooth->setChecked(false); diff --git a/src/Mod/Mesh/Gui/SegmentationBestFit.cpp b/src/Mod/Mesh/Gui/SegmentationBestFit.cpp index 464ffda0aa..2a147ac04b 100644 --- a/src/Mod/Mesh/Gui/SegmentationBestFit.cpp +++ b/src/Mod/Mesh/Gui/SegmentationBestFit.cpp @@ -57,7 +57,7 @@ public: std::vector values; MeshCore::PlaneFit fit; fit.AddPoints(pts.points); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetBase(); Base::Vector3f axis = fit.GetNormal(); values.push_back(base.x); @@ -90,7 +90,7 @@ public: #endif } - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base, top; fit.GetBounding(base, top); Base::Vector3f axis = fit.GetAxis(); @@ -145,7 +145,7 @@ public: std::vector values; MeshCore::SphereFit fit; fit.AddPoints(pts.points); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetCenter(); float radius = fit.GetRadius(); values.push_back(base.x); @@ -228,7 +228,7 @@ ParametersDialog::ParametersDialog(std::vector& val, QDoubleSpinBox* doubleSpinBox = new QDoubleSpinBox(groupBox); doubleSpinBox->setObjectName(it.first); - doubleSpinBox->setRange(-INT_MAX, INT_MAX); + doubleSpinBox->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); doubleSpinBox->setValue(it.second); layout->addWidget(doubleSpinBox, index, 1, 1, 1); spinBoxes.push_back(doubleSpinBox); @@ -335,11 +335,11 @@ SegmentationBestFit::SegmentationBestFit(Mesh::Feature* mesh, QWidget* parent, Q ui->setupUi(this); setupConnections(); - ui->numPln->setRange(1, INT_MAX); + ui->numPln->setRange(1, std::numeric_limits::max()); ui->numPln->setValue(100); - ui->numCyl->setRange(1, INT_MAX); + ui->numCyl->setRange(1, std::numeric_limits::max()); ui->numCyl->setValue(100); - ui->numSph->setRange(1, INT_MAX); + ui->numSph->setRange(1, std::numeric_limits::max()); ui->numSph->setValue(100); Gui::SelectionObject obj(myMesh); diff --git a/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp b/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp index 080e0584b2..be7c40a5ea 100644 --- a/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp +++ b/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp @@ -30,7 +30,6 @@ #ifndef _PreComp_ #include -#include #ifdef FC_OS_MACOSX #include #include @@ -459,7 +458,7 @@ void SoFCIndexedFaceSet::initClass() } SoFCIndexedFaceSet::SoFCIndexedFaceSet() - : renderTriangleLimit(UINT_MAX) + : renderTriangleLimit(std::numeric_limits::max()) { SO_NODE_CONSTRUCTOR(SoFCIndexedFaceSet); SO_NODE_ADD_FIELD(updateGLArray, (false)); diff --git a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp index 7ff55890e4..904f6fdf48 100644 --- a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp +++ b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include -#include #ifdef FC_OS_WIN32 #include #endif @@ -607,7 +606,7 @@ void SoFCMeshObjectShape::initClass() } SoFCMeshObjectShape::SoFCMeshObjectShape() - : renderTriangleLimit(UINT_MAX) + : renderTriangleLimit(std::numeric_limits::max()) { SO_NODE_CONSTRUCTOR(SoFCMeshObjectShape); setName(SoFCMeshObjectShape::getClassTypeId().getName()); @@ -1235,7 +1234,7 @@ void SoFCMeshSegmentShape::initClass() } SoFCMeshSegmentShape::SoFCMeshSegmentShape() - : renderTriangleLimit(UINT_MAX) + : renderTriangleLimit(std::numeric_limits::max()) { SO_NODE_CONSTRUCTOR(SoFCMeshSegmentShape); SO_NODE_ADD_FIELD(index, (0)); diff --git a/src/Mod/Mesh/Gui/SoPolygon.cpp b/src/Mod/Mesh/Gui/SoPolygon.cpp index acc5701058..a5b242c82b 100644 --- a/src/Mod/Mesh/Gui/SoPolygon.cpp +++ b/src/Mod/Mesh/Gui/SoPolygon.cpp @@ -31,7 +31,6 @@ #include #endif #include -#include #include #include @@ -145,8 +144,9 @@ void SoPolygon::computeBBox(SoAction* action, SbBox3f& box, SbVec3f& center) if (!points) { return; } - float maxX = -FLT_MAX, minX = FLT_MAX, maxY = -FLT_MAX, minY = FLT_MAX, maxZ = -FLT_MAX, - minZ = FLT_MAX; + constexpr float floatMax = std::numeric_limits::max(); + float maxX = -floatMax, minX = floatMax, maxY = -floatMax, minY = floatMax, maxZ = -floatMax, + minZ = floatMax; int32_t len = coords->getNum(); int32_t beg = startIndex.getValue(); int32_t cnt = numVertices.getValue(); From 9086f0ff14ca0d3a37c095e94e6ad6415eb1fad8 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:33 +0100 Subject: [PATCH 048/316] MeshPart: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/MeshPart/App/CurveProjector.cpp | 14 +++++++------- src/Mod/MeshPart/App/CurveProjector.h | 3 ++- src/Mod/MeshPart/App/MeshFlatteningLscmRelax.cpp | 9 +++------ src/Mod/MeshPart/App/PreCompiled.h | 1 + src/Mod/MeshPart/Gui/CrossSections.cpp | 6 +++--- src/Mod/MeshPart/Gui/PreCompiled.h | 1 - src/Mod/MeshPart/Gui/Tessellation.cpp | 4 ++-- 7 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/Mod/MeshPart/App/CurveProjector.cpp b/src/Mod/MeshPart/App/CurveProjector.cpp index ceab83bff4..db9926b50d 100644 --- a/src/Mod/MeshPart/App/CurveProjector.cpp +++ b/src/Mod/MeshPart/App/CurveProjector.cpp @@ -180,7 +180,7 @@ void CurveProjectorShape::projectCurve(const TopoDS_Edge& aEdge, / ((cP1 - cP0) * (cP1 - cP0)); // is the Point on the Edge of the facet? if (l < 0.0 || l > 1.0) { - PointOnEdge[i] = Base::Vector3f(FLOAT_MAX, 0, 0); + PointOnEdge[i] = Base::Vector3f(std::numeric_limits::max(), 0, 0); } else { cSplitPoint = (1 - l) * cP0 + l * cP1; @@ -191,11 +191,11 @@ void CurveProjectorShape::projectCurve(const TopoDS_Edge& aEdge, // no intersection } else if (Alg.NbPoints() == 0) { - PointOnEdge[i] = Base::Vector3f(FLOAT_MAX, 0, 0); + PointOnEdge[i] = Base::Vector3f(std::numeric_limits::max(), 0, 0); // more the one intersection (@ToDo) } else if (Alg.NbPoints() > 1) { - PointOnEdge[i] = Base::Vector3f(FLOAT_MAX, 0, 0); + PointOnEdge[i] = Base::Vector3f(std::numeric_limits::max(), 0, 0); Base::Console().Log("MeshAlgos::projectCurve(): More then one intersection in " "Facet %lu, Edge %d\n", uCurFacetIdx, @@ -234,7 +234,7 @@ bool CurveProjectorShape::findStartPoint(const MeshKernel& MeshK, MeshCore::FacetIndex& FaceIndex) { Base::Vector3f TempResultPoint; - float MinLength = FLOAT_MAX; + float MinLength = std::numeric_limits::max(); bool bHit = false; // go through the whole Mesh @@ -363,7 +363,7 @@ bool CurveProjectorSimple::findStartPoint(const MeshKernel& MeshK, MeshCore::FacetIndex& FaceIndex) { Base::Vector3f TempResultPoint; - float MinLength = FLOAT_MAX; + float MinLength = std::numeric_limits::max(); bool bHit = false; // go through the whole Mesh @@ -465,11 +465,11 @@ void CurveProjectorWithToolMesh::makeToolMesh(const TopoDS_Edge& aEdge, // build up the new mesh - Base::Vector3f lp(FLOAT_MAX, 0, 0), ln, p1, p2, p3, p4, p5, p6; + Base::Vector3f lp(std::numeric_limits::max(), 0, 0), ln, p1, p2, p3, p4, p5, p6; float ToolSize = 0.2f; for (const auto& It2 : LineSegs) { - if (lp.x != FLOAT_MAX) { + if (lp.x != std::numeric_limits::max()) { p1 = lp + (ln * (-ToolSize)); p2 = lp + (ln * ToolSize); p3 = lp; diff --git a/src/Mod/MeshPart/App/CurveProjector.h b/src/Mod/MeshPart/App/CurveProjector.h index f2c84e4c2b..d8fd6386d1 100644 --- a/src/Mod/MeshPart/App/CurveProjector.h +++ b/src/Mod/MeshPart/App/CurveProjector.h @@ -66,7 +66,8 @@ public: std::hash hasher; return hasher(x) < hasher(y); #else - return x.HashCode(INT_MAX - 1) < y.HashCode(INT_MAX - 1); + constexpr int max = std::numeric_limits::max(); + return x.HashCode(max - 1) < y.HashCode(max - 1); #endif } }; diff --git a/src/Mod/MeshPart/App/MeshFlatteningLscmRelax.cpp b/src/Mod/MeshPart/App/MeshFlatteningLscmRelax.cpp index 1071e0c9c8..4c73f3f651 100644 --- a/src/Mod/MeshPart/App/MeshFlatteningLscmRelax.cpp +++ b/src/Mod/MeshPart/App/MeshFlatteningLscmRelax.cpp @@ -26,14 +26,11 @@ #include #include #include +#include #include #include #endif -#ifndef M_PI -#define M_PI 3.14159265358979323846f -#endif - #include #include "MeshFlatteningLscmRelax.h" @@ -649,7 +646,7 @@ void LscmRelax::rotate_by_min_bound_area() // rotate vector by 90 degree and find min area for (int i = 0; i < n + 1; i++ ) { - phi = i * M_PI / n; + phi = i * std::numbers::pi / n; Eigen::VectorXd x_proj = this->flat_vertices.transpose() * Vector2(std::cos(phi), std::sin(phi)); Eigen::VectorXd y_proj = this->flat_vertices.transpose() * Vector2(-std::sin(phi), std::cos(phi)); double x_distance = x_proj.maxCoeff() - x_proj.minCoeff(); @@ -663,7 +660,7 @@ void LscmRelax::rotate_by_min_bound_area() } } Eigen::Matrix rot; - min_phi += x_dominant * M_PI / 2; + min_phi += x_dominant * std::numbers::pi / 2; rot << std::cos(min_phi), std::sin(min_phi), -std::sin(min_phi), std::cos(min_phi); this->flat_vertices = rot * this->flat_vertices; } diff --git a/src/Mod/MeshPart/App/PreCompiled.h b/src/Mod/MeshPart/App/PreCompiled.h index 7c1101f012..6b867c5e80 100644 --- a/src/Mod/MeshPart/App/PreCompiled.h +++ b/src/Mod/MeshPart/App/PreCompiled.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/MeshPart/Gui/CrossSections.cpp b/src/Mod/MeshPart/Gui/CrossSections.cpp index 01ba18888e..2ba73eeeac 100644 --- a/src/Mod/MeshPart/Gui/CrossSections.cpp +++ b/src/Mod/MeshPart/Gui/CrossSections.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include @@ -179,9 +178,10 @@ CrossSections::CrossSections(const Base::BoundBox3d& bb, QWidget* parent, Qt::Wi ui->setupUi(this); setupConnections(); - ui->position->setRange(-DBL_MAX, DBL_MAX); + constexpr double max = std::numeric_limits::max(); + ui->position->setRange(-max, max); ui->position->setUnit(Base::Unit::Length); - ui->distance->setRange(0, DBL_MAX); + ui->distance->setRange(0, max); ui->distance->setUnit(Base::Unit::Length); ui->spinEpsilon->setMinimum(0.0001); vp = new ViewProviderCrossSections(); diff --git a/src/Mod/MeshPart/Gui/PreCompiled.h b/src/Mod/MeshPart/Gui/PreCompiled.h index 7b8b8dda80..408fcd88ed 100644 --- a/src/Mod/MeshPart/Gui/PreCompiled.h +++ b/src/Mod/MeshPart/Gui/PreCompiled.h @@ -34,7 +34,6 @@ #ifdef _PreComp_ // STL -#include #include // Qt Toolkit diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp index f063bd91be..c726659bbe 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.cpp +++ b/src/Mod/MeshPart/Gui/Tessellation.cpp @@ -71,11 +71,11 @@ Tessellation::Tessellation(QWidget* parent) relative = handle->GetBool("RelativeLinearDeflection", relative); ui->relativeDeviation->setChecked(relative); - ui->spinSurfaceDeviation->setMaximum(INT_MAX); + ui->spinSurfaceDeviation->setMaximum(std::numeric_limits::max()); ui->spinSurfaceDeviation->setValue(value); ui->spinAngularDeviation->setValue(angle); - ui->spinMaximumEdgeLength->setRange(0, INT_MAX); + ui->spinMaximumEdgeLength->setRange(0, std::numeric_limits::max()); ui->comboFineness->setCurrentIndex(2); onComboFinenessCurrentIndexChanged(2); From aad5e589559e1a1a053a58a89fac8fde9c423efe Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:46 +0100 Subject: [PATCH 049/316] Part: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Part/App/AppPartPy.cpp | 11 +- src/Mod/Part/App/Attacher.cpp | 2 +- src/Mod/Part/App/FeatureExtrusion.cpp | 10 +- src/Mod/Part/App/FeatureRevolution.cpp | 2 +- src/Mod/Part/App/Geometry.cpp | 35 ++--- src/Mod/Part/App/PreCompiled.h | 2 + src/Mod/Part/App/PrimitiveFeature.cpp | 4 +- src/Mod/Part/App/ShapeMapHasher.h | 2 +- src/Mod/Part/App/Tools.cpp | 4 +- src/Mod/Part/App/TopoShape.cpp | 43 +++--- src/Mod/Part/App/TopoShapeEdgePyImp.cpp | 7 +- src/Mod/Part/App/TopoShapeExpansion.cpp | 11 +- src/Mod/Part/App/TopoShapeMapper.h | 12 +- src/Mod/Part/App/TopoShapePyImp.cpp | 3 +- src/Mod/Part/App/WireJoiner.cpp | 21 ++- src/Mod/Part/App/modelRefine.cpp | 5 +- src/Mod/Part/Gui/CrossSections.cpp | 6 +- src/Mod/Part/Gui/DlgFilletEdges.cpp | 6 +- src/Mod/Part/Gui/DlgPrimitives.cpp | 138 +++++++++--------- src/Mod/Part/Gui/DlgRevolution.cpp | 15 +- src/Mod/Part/Gui/Mirroring.cpp | 11 +- src/Mod/Part/Gui/PreCompiled.h | 1 - src/Mod/Part/Gui/PropertyEnumAttacherItem.cpp | 5 +- src/Mod/Part/Gui/SectionCutting.cpp | 11 +- src/Mod/Part/Gui/SoBrepEdgeSet.cpp | 7 +- src/Mod/Part/Gui/SoBrepFaceSet.cpp | 9 +- src/Mod/Part/Gui/SoBrepPointSet.cpp | 7 +- src/Mod/Part/Gui/SoFCShapeObject.cpp | 8 +- src/Mod/Part/Gui/TaskOffset.cpp | 3 +- src/Mod/Part/Gui/TaskThickness.cpp | 3 +- src/Mod/Part/Gui/ViewProvider2DObject.cpp | 13 +- .../Part/Gui/ViewProviderAttachExtension.cpp | 4 - src/Mod/Part/Gui/ViewProviderExt.cpp | 2 +- .../Part/Gui/ViewProviderGridExtension.cpp | 4 +- src/Mod/Part/Gui/ViewProviderReference.cpp | 3 - tests/src/Mod/Part/App/FeatureExtrusion.cpp | 16 +- tests/src/Mod/Part/App/FeatureRevolution.cpp | 16 +- tests/src/Mod/Part/App/TopoShapeExpansion.cpp | 44 +++--- 38 files changed, 259 insertions(+), 247 deletions(-) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 0a9042c300..b6734ca17b 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -1622,7 +1622,8 @@ private: } Py::Object makeRevolution(const Py::Tuple& args) { - double vmin = DBL_MAX, vmax=-DBL_MAX; + constexpr double doubleMax = std::numeric_limits::max(); + double vmin = doubleMax, vmax=-doubleMax; double angle=360; PyObject *pPnt=nullptr, *pDir=nullptr, *pCrv; Handle(Geom_Curve) curve; @@ -1641,10 +1642,10 @@ private: if (curve.IsNull()) { throw Py::Exception(PyExc_TypeError, "geometry is not a curve"); } - if (vmin == DBL_MAX) + if (vmin == doubleMax) vmin = curve->FirstParameter(); - if (vmax == -DBL_MAX) + if (vmax == -doubleMax) vmax = curve->LastParameter(); break; } @@ -1675,9 +1676,9 @@ private: throw Py::Exception(PartExceptionOCCError, "invalid curve in edge"); } - if (vmin == DBL_MAX) + if (vmin == doubleMax) vmin = adapt.FirstParameter(); - if (vmax == -DBL_MAX) + if (vmax == -doubleMax) vmax = adapt.LastParameter(); break; } diff --git a/src/Mod/Part/App/Attacher.cpp b/src/Mod/Part/App/Attacher.cpp index 5009ce260b..255d54b702 100644 --- a/src/Mod/Part/App/Attacher.cpp +++ b/src/Mod/Part/App/Attacher.cpp @@ -1912,7 +1912,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vectormapReverse) { - rot = rot * Base::Rotation(Base::Vector3d(0, 1, 0), D_PI); + rot = rot * Base::Rotation(Base::Vector3d(0, 1, 0), std::numbers::pi); } Base::Placement plm = Base::Placement( diff --git a/src/Mod/Part/App/FeatureExtrusion.cpp b/src/Mod/Part/App/FeatureExtrusion.cpp index 800199733c..abffc334bd 100644 --- a/src/Mod/Part/App/FeatureExtrusion.cpp +++ b/src/Mod/Part/App/FeatureExtrusion.cpp @@ -200,6 +200,8 @@ bool Extrusion::fetchAxisLink(const App::PropertyLinkSub& axisLink, Base::Vector ExtrusionParameters Extrusion::computeFinalParameters() { + using std::numbers::pi; + ExtrusionParameters result; Base::Vector3d dir; switch (this->DirMode.getValue()) { @@ -244,11 +246,11 @@ ExtrusionParameters Extrusion::computeFinalParameters() result.solid = this->Solid.getValue(); - result.taperAngleFwd = this->TaperAngle.getValue() * M_PI / 180.0; - if (fabs(result.taperAngleFwd) > M_PI * 0.5 - Precision::Angular()) + result.taperAngleFwd = this->TaperAngle.getValue() * pi / 180.0; + if (fabs(result.taperAngleFwd) > pi * 0.5 - Precision::Angular()) throw Base::ValueError("Magnitude of taper angle matches or exceeds 90 degrees. That is too much."); - result.taperAngleRev = this->TaperAngleRev.getValue() * M_PI / 180.0; - if (fabs(result.taperAngleRev) > M_PI * 0.5 - Precision::Angular()) + result.taperAngleRev = this->TaperAngleRev.getValue() * pi / 180.0; + if (fabs(result.taperAngleRev) > pi * 0.5 - Precision::Angular()) throw Base::ValueError("Magnitude of taper angle matches or exceeds 90 degrees. That is too much."); result.faceMakerClass = this->FaceMakerClass.getValue(); diff --git a/src/Mod/Part/App/FeatureRevolution.cpp b/src/Mod/Part/App/FeatureRevolution.cpp index e27007f98a..2a59f99bce 100644 --- a/src/Mod/Part/App/FeatureRevolution.cpp +++ b/src/Mod/Part/App/FeatureRevolution.cpp @@ -143,7 +143,7 @@ App::DocumentObjectExecReturn *Revolution::execute() gp_Ax1 revAx(pnt, dir); //read out revolution angle - double angle = Angle.getValue()/180.0f*M_PI; + double angle = Angle.getValue()/180.0f * std::numbers::pi; if (fabs(angle) < Precision::Angular()) angle = angle_edge; diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index bb3d7d2a8d..571b91cd18 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -2640,7 +2640,7 @@ GeomCurve* GeomCircle::createArc(double first, double last) const GeomBSplineCurve* GeomCircle::toNurbs(double first, double last) const { // for an arc of circle use the generic method - if (first != 0 || last != 2*M_PI) { + if (first != 0 || last != 2 * std::numbers::pi) { return GeomConic::toNurbs(first, last); } @@ -2674,8 +2674,8 @@ GeomBSplineCurve* GeomCircle::toNurbs(double first, double last) const TColStd_Array1OfReal knots(1, 3); knots(1) = 0; - knots(2) = M_PI; - knots(3) = 2*M_PI; + knots(2) = std::numbers::pi; + knots(3) = 2 * std::numbers::pi; Handle(Geom_BSplineCurve) spline = new Geom_BSplineCurve(poles, weights,knots, mults, 3, Standard_False, Standard_True); @@ -2906,9 +2906,9 @@ void GeomArcOfCircle::getRange(double& u, double& v, bool emulateCCWXY) const } if (v < u) - v += 2*M_PI; - if (v-u > 2*M_PI) - v -= 2*M_PI; + v += 2 * std::numbers::pi; + if (v-u > 2 * std::numbers::pi) + v -= 2 * std::numbers::pi; } } @@ -3086,7 +3086,7 @@ GeomCurve* GeomEllipse::createArc(double first, double last) const GeomBSplineCurve* GeomEllipse::toNurbs(double first, double last) const { // for an arc of ellipse use the generic method - if (first != 0 || last != 2*M_PI) { + if (first != 0 || last != 2 * std::numbers::pi) { return GeomConic::toNurbs(first, last); } @@ -3465,9 +3465,9 @@ void GeomArcOfEllipse::getRange(double& u, double& v, bool emulateCCWXY) const std::swap(u,v); u = -u; v = -v; if (v < u) - v += 2*M_PI; - if (v-u > 2*M_PI) - v -= 2*M_PI; + v += 2 * std::numbers::pi; + if (v-u > 2 * std::numbers::pi) + v -= 2 * std::numbers::pi; } } } @@ -4683,11 +4683,12 @@ void GeomLineSegment::Restore (Base::XMLReader &reader) // for other objects, the best effort may be just to leave default values. reader.setPartialRestore(true); + constexpr double increment{std::numeric_limits::epsilon()}; if(start.x == 0) { - end = start + Base::Vector3d(DBL_EPSILON,0,0); + end = start + Base::Vector3d(increment, 0, 0); } else { - end = start + Base::Vector3d(start.x*DBL_EPSILON,0,0); + end = start + Base::Vector3d(start.x * increment, 0, 0); } setPoints(start, end); @@ -5409,7 +5410,7 @@ gp_Vec GeomCone::getDN(double u, double v, int Nu, int Nv) const { gp_XYZ Xdir = Pos.XDirection().XYZ(); gp_XYZ Ydir = Pos.YDirection().XYZ(); - Standard_Real Um = U + Nu * M_PI_2; // M_PI * 0.5 + Standard_Real Um = U + Nu * std::numbers::pi/2; Xdir.Multiply(cos(Um)); Ydir.Multiply(sin(Um)); Xdir.Add(Ydir); @@ -6228,11 +6229,11 @@ GeomArcOfCircle *createFilletGeometry(const GeomLineSegment *lineSeg1, const Geo if (endAngle < startAngle) std::swap(startAngle, endAngle); - if (endAngle > 2*M_PI ) - endAngle -= 2*M_PI; + if (endAngle > 2 * std::numbers::pi) + endAngle -= 2 * std::numbers::pi; - if (startAngle < 0 ) - endAngle += 2*M_PI; + if (startAngle < 0) + endAngle += 2 * std::numbers::pi; // Create Arc Segment GeomArcOfCircle *arc = new GeomArcOfCircle(); diff --git a/src/Mod/Part/App/PreCompiled.h b/src/Mod/Part/App/PreCompiled.h index ca53f56d20..a537ca9c03 100644 --- a/src/Mod/Part/App/PreCompiled.h +++ b/src/Mod/Part/App/PreCompiled.h @@ -43,6 +43,7 @@ #include #include #include +#include // STL #include @@ -52,6 +53,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Part/App/PrimitiveFeature.cpp b/src/Mod/Part/App/PrimitiveFeature.cpp index 095ce83a3c..02d13f8825 100644 --- a/src/Mod/Part/App/PrimitiveFeature.cpp +++ b/src/Mod/Part/App/PrimitiveFeature.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +# include # include # include # include @@ -57,7 +57,7 @@ namespace Part { const App::PropertyQuantityConstraint::Constraints torusRangeV = {-180.0, 180.0, 1.0}; const App::PropertyQuantityConstraint::Constraints angleRangeU = {0.0, 360.0, 1.0}; const App::PropertyQuantityConstraint::Constraints angleRangeV = {-90.0, 90.0, 1.0}; - const App::PropertyQuantityConstraint::Constraints quantityRange = {0.0, FLT_MAX, 0.1}; + const App::PropertyQuantityConstraint::Constraints quantityRange = {0.0, std::numeric_limits::max(), 0.1}; } using namespace Part; diff --git a/src/Mod/Part/App/ShapeMapHasher.h b/src/Mod/Part/App/ShapeMapHasher.h index 6b0fe94c4c..24ab2a5b30 100644 --- a/src/Mod/Part/App/ShapeMapHasher.h +++ b/src/Mod/Part/App/ShapeMapHasher.h @@ -38,7 +38,7 @@ public: size_t operator()(const TopoDS_Shape& theShape) const { #if OCC_VERSION_HEX < 0x070800 - return theShape.HashCode(INT_MAX); + return theShape.HashCode(std::numeric_limits::max()); #else return std::hash{}(theShape); #endif diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 93ce969ec9..12cfe3f949 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -773,9 +773,9 @@ bool Part::Tools::isConcave(const TopoDS_Face &face, const gp_Pnt &pointOfVue, c // check normals orientation gp_Dir dirdU(dU); - result = (dirdU.Angle(direction) - M_PI_2) <= Precision::Confusion(); + result = (dirdU.Angle(direction) - std::numbers::pi/2) <= Precision::Confusion(); gp_Dir dirdV(dV); - result = result || ((dirdV.Angle(direction) - M_PI_2) <= Precision::Confusion()); + result = result || ((dirdV.Angle(direction) - std::numbers::pi/2) <= Precision::Confusion()); return result; } diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 8d70e4c3c1..951b6086dc 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -2004,7 +2004,7 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdeg //circular profile Handle(Geom_Circle) aCirc = new Geom_Circle (gp::XOY(), theRadius); - aCirc->Rotate (gp::OZ(), M_PI/2.); + aCirc->Rotate (gp::OZ(), std::numbers::pi/2.); //perpendicular section Handle(Law_Function) myEvol = ::CreateBsFunction (myPath->FirstParameter(), myPath->LastParameter(), theRadius); @@ -2116,6 +2116,8 @@ TopoDS_Shape TopoShape::makeHelix(Standard_Real pitch, Standard_Real height, Standard_Boolean leftHanded, Standard_Boolean newStyle) const { + using std::numbers::pi; + if (fabs(pitch) < Precision::Confusion()) Standard_Failure::Raise("Pitch of helix too small"); @@ -2140,24 +2142,24 @@ TopoDS_Shape TopoShape::makeHelix(Standard_Real pitch, Standard_Real height, } gp_Pnt2d aPnt(0, 0); - gp_Dir2d aDir(2. * M_PI, pitch); + gp_Dir2d aDir(2. * pi, pitch); Standard_Real coneDir = 1.0; if (leftHanded) { - aDir.SetCoord(-2. * M_PI, pitch); + aDir.SetCoord(-2. * pi, pitch); coneDir = -1.0; } gp_Ax2d aAx2d(aPnt, aDir); Handle(Geom2d_Line) line = new Geom2d_Line(aAx2d); gp_Pnt2d beg = line->Value(0); - gp_Pnt2d end = line->Value(sqrt(4.0*M_PI*M_PI+pitch*pitch)*(height/pitch)); + gp_Pnt2d end = line->Value(sqrt(4.0*pi*pi+pitch*pitch)*(height/pitch)); if (newStyle) { // See discussion at 0001247: Part Conical Helix Height/Pitch Incorrect if (angle >= Precision::Confusion()) { // calculate end point for conical helix Standard_Real v = height / cos(angle); - Standard_Real u = coneDir * (height/pitch) * 2.0 * M_PI; + Standard_Real u = coneDir * (height/pitch) * 2.0 * pi; gp_Pnt2d cend(u, v); end = cend; } @@ -2179,6 +2181,8 @@ TopoDS_Shape TopoShape::makeLongHelix(Standard_Real pitch, Standard_Real height, Standard_Real radius, Standard_Real angle, Standard_Boolean leftHanded) const { + using std::numbers::pi; + if (pitch < Precision::Confusion()) Standard_Failure::Raise("Pitch of helix too small"); @@ -2206,10 +2210,10 @@ TopoDS_Shape TopoShape::makeLongHelix(Standard_Real pitch, Standard_Real height, Standard_Real partTurn = turns - wholeTurns; gp_Pnt2d aPnt(0, 0); - gp_Dir2d aDir(2. * M_PI, pitch); + gp_Dir2d aDir(2. * pi, pitch); Standard_Real coneDir = 1.0; if (leftHanded) { - aDir.SetCoord(-2. * M_PI, pitch); + aDir.SetCoord(-2. * pi, pitch); coneDir = -1.0; } gp_Ax2d aAx2d(aPnt, aDir); @@ -2223,10 +2227,10 @@ TopoDS_Shape TopoShape::makeLongHelix(Standard_Real pitch, Standard_Real height, for (unsigned long i = 0; i < wholeTurns; i++) { if (isCylinder) { - end = line->Value(sqrt(4.0*M_PI*M_PI+pitch*pitch)*(i+1)); + end = line->Value(sqrt(4.0*pi*pi+pitch*pitch)*(i+1)); } else { - u = coneDir * (i+1) * 2.0 * M_PI; + u = coneDir * (i+1) * 2.0 * pi; v = ((i+1) * pitch) / cos(angle); end = gp_Pnt2d(u, v); } @@ -2238,10 +2242,10 @@ TopoDS_Shape TopoShape::makeLongHelix(Standard_Real pitch, Standard_Real height, if (partTurn > Precision::Confusion()) { if (isCylinder) { - end = line->Value(sqrt(4.0*M_PI*M_PI+pitch*pitch)*turns); + end = line->Value(sqrt(4.0*pi*pi+pitch*pitch)*turns); } else { - u = coneDir * turns * 2.0 * M_PI; + u = coneDir * turns * 2.0 * pi; v = height / cos(angle); end = gp_Pnt2d(u, v); } @@ -2283,9 +2287,9 @@ TopoDS_Shape TopoShape::makeSpiralHelix(Standard_Real radiusbottom, Standard_Rea gp_Pnt2d beg(0, 0); gp_Pnt2d end(0, 0); - gp_Vec2d dir(breakperiod * 2.0 * M_PI, 1 / nbPeriods); + gp_Vec2d dir(breakperiod * 2.0 * std::numbers::pi, 1 / nbPeriods); if (leftHanded == Standard_True) - dir = gp_Vec2d(-breakperiod * 2.0 * M_PI, 1 / nbPeriods); + dir = gp_Vec2d(-breakperiod * 2.0 * std::numbers::pi, 1 / nbPeriods); Handle(Geom2d_TrimmedCurve) segm; TopoDS_Edge edgeOnSurf; BRepBuilderAPI_MakeWire mkWire; @@ -2314,6 +2318,7 @@ TopoDS_Shape TopoShape::makeThread(Standard_Real pitch, Standard_Real height, Standard_Real radius) const { + using std::numbers::pi; if (pitch < Precision::Confusion()) Standard_Failure::Raise("Pitch of thread too small"); @@ -2332,21 +2337,21 @@ TopoDS_Shape TopoShape::makeThread(Standard_Real pitch, Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(cylAx2 , radius+depth); //Threading : Define 2D Curves - gp_Pnt2d aPnt(2. * M_PI , height / 2.); - gp_Dir2d aDir(2. * M_PI , height / 4.); + gp_Pnt2d aPnt(2. * pi , height / 2.); + gp_Dir2d aDir(2. * pi , height / 4.); gp_Ax2d aAx2d(aPnt , aDir); - Standard_Real aMajor = 2. * M_PI; + Standard_Real aMajor = 2. * pi; Standard_Real aMinor = pitch; Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(aAx2d , aMajor , aMinor); Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(aAx2d , aMajor , aMinor / 4); - Handle(Geom2d_TrimmedCurve) aArc1 = new Geom2d_TrimmedCurve(anEllipse1 , 0 , M_PI); - Handle(Geom2d_TrimmedCurve) aArc2 = new Geom2d_TrimmedCurve(anEllipse2 , 0 , M_PI); + Handle(Geom2d_TrimmedCurve) aArc1 = new Geom2d_TrimmedCurve(anEllipse1 , 0 , pi); + Handle(Geom2d_TrimmedCurve) aArc2 = new Geom2d_TrimmedCurve(anEllipse2 , 0 , pi); gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0); - gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI); + gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(pi); Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1 , anEllipsePnt2); diff --git a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp index 6b39d05fd8..b3257c90fd 100644 --- a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp @@ -126,7 +126,8 @@ int TopoShapeEdgePy::PyInit(PyObject* args, PyObject* /*kwd*/) PyErr_Clear(); PyObject *pcObj, *pcObj2; - double first=DBL_MAX, last=DBL_MAX; + double first = std::numeric_limits::max(); + double last = std::numeric_limits::max(); if (PyArg_ParseTuple(args, "O!|dd", &(Part::GeometryPy::Type), &pcObj, &first, &last)) { Geometry* geom = static_cast(pcObj)->getGeometryPtr(); Handle(Geom_Curve) curve = Handle(Geom_Curve)::DownCast(geom->handle()); @@ -135,9 +136,9 @@ int TopoShapeEdgePy::PyInit(PyObject* args, PyObject* /*kwd*/) return -1; } - if (first==DBL_MAX) + if (first == std::numeric_limits::max()) first = curve->FirstParameter(); - if (last==DBL_MAX) + if (last == std::numeric_limits::max()) last = curve->LastParameter(); try { diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 5118bcf94b..39fd232357 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -1611,6 +1611,7 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape, bool delayed = false; while (true) { + constexpr int intMin = std::numeric_limits::min(); // Construct the names for modification/generation info collected in // the previous step @@ -1632,7 +1633,7 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape, const auto& first_key = names.begin()->first; auto& first_info = names.begin()->second; - if (!delayed && first_key.shapetype >= 3 && first_info.index > INT_MIN + 1) { + if (!delayed && first_key.shapetype >= 3 && first_info.index > intMin + 1) { // This name is mapped from high level (shell, solid, etc.) // Delay till next round. // @@ -1680,10 +1681,10 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape, // 'K' marks the additional source shape of this // generate (or modified) shape. ss2 << elementMapPrefix() << 'K'; - if (other_info.index == INT_MIN) { + if (other_info.index == intMin) { ss2 << '0'; } - else if (other_info.index == INT_MIN + 1) { + else if (other_info.index == intMin + 1) { ss2 << "00"; } else { @@ -1740,10 +1741,10 @@ TopoShape& TopoShape::makeShapeWithElementMap(const TopoDS_Shape& shape, else { ss << modgenPostfix(); } - if (first_info.index == INT_MIN) { + if (first_info.index == intMin) { ss << '0'; } - else if (first_info.index == INT_MIN + 1) { + else if (first_info.index == intMin + 1) { ss << "00"; } else if (abs(first_info.index) > 1) { diff --git a/src/Mod/Part/App/TopoShapeMapper.h b/src/Mod/Part/App/TopoShapeMapper.h index 5ec165efab..0febe93d47 100644 --- a/src/Mod/Part/App/TopoShapeMapper.h +++ b/src/Mod/Part/App/TopoShapeMapper.h @@ -46,7 +46,7 @@ struct ShapeHasher #if OCC_VERSION_HEX >= 0x070800 return std::hash {}(s.getShape()); #else - return s.getShape().HashCode(INT_MAX); + return s.getShape().HashCode(std::numeric_limits::max()); #endif } inline size_t operator()(const TopoDS_Shape& s) const @@ -54,7 +54,7 @@ struct ShapeHasher #if OCC_VERSION_HEX >= 0x070800 return std::hash {}(s); #else - return s.HashCode(INT_MAX); + return s.HashCode(std::numeric_limits::max()); #endif } inline bool operator()(const TopoShape& a, const TopoShape& b) const @@ -78,8 +78,8 @@ struct ShapeHasher size_t res = std::hash {}(s.first.getShape()); hash_combine(res, std::hash {}(s.second.getShape())); #else - size_t res = s.first.getShape().HashCode(INT_MAX); - hash_combine(res, s.second.getShape().HashCode(INT_MAX)); + size_t res = s.first.getShape().HashCode(std::numeric_limits::max()); + hash_combine(res, s.second.getShape().HashCode(std::numeric_limits::max())); #endif return res; } @@ -89,8 +89,8 @@ struct ShapeHasher size_t res = std::hash {}(s.first); hash_combine(res, std::hash {}(s.second)); #else - size_t res = s.first.HashCode(INT_MAX); - hash_combine(res, s.second.HashCode(INT_MAX)); + size_t res = s.first.HashCode(std::numeric_limits::max()); + hash_combine(res, s.second.HashCode(std::numeric_limits::max())); #endif return res; } diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index 246c0c7e1a..c0b2ca1d2e 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -117,7 +117,8 @@ static Py_hash_t _TopoShapeHash(PyObject* self) #if OCC_VERSION_HEX >= 0x070800 return std::hash {}(static_cast(self)->getTopoShapePtr()->getShape()); #else - return static_cast(self)->getTopoShapePtr()->getShape().HashCode(INT_MAX); + return static_cast(self)->getTopoShapePtr()->getShape().HashCode( + std::numeric_limits::max()); #endif } diff --git a/src/Mod/Part/App/WireJoiner.cpp b/src/Mod/Part/App/WireJoiner.cpp index 0987454766..abe3cf1326 100644 --- a/src/Mod/Part/App/WireJoiner.cpp +++ b/src/Mod/Part/App/WireJoiner.cpp @@ -784,11 +784,12 @@ public: const bool isLinear) { std::unique_ptr geo; - for (auto vit = vmap.qbegin(bgi::nearest(p1, INT_MAX)); vit != vmap.qend(); ++vit) { + constexpr int max = std::numeric_limits::max(); + for (auto vit = vmap.qbegin(bgi::nearest(p1, max)); vit != vmap.qend(); ++vit) { auto& vinfo = *vit; if (canShowShape()) { #if OCC_VERSION_HEX < 0x070800 - FC_MSG("addcheck " << vinfo.edge().HashCode(INT_MAX)); + FC_MSG("addcheck " << vinfo.edge().HashCode(max)); #else FC_MSG("addcheck " << std::hash {}(vinfo.edge())); #endif @@ -1568,7 +1569,8 @@ public: } info.iEnd[ic] = info.iStart[ic] = (int)adjacentList.size(); - for (auto vit = vmap.qbegin(bgi::nearest(pt[ic], INT_MAX)); vit != vmap.qend(); + constexpr int max = std::numeric_limits::max(); + for (auto vit = vmap.qbegin(bgi::nearest(pt[ic], max)); vit != vmap.qend(); ++vit) { auto& vinfo = *vit; if (vinfo.pt().SquareDistance(pt[ic]) > myTol2) { @@ -2717,7 +2719,8 @@ public: FC_MSG("init:"); for (const auto& shape : sourceEdges) { #if OCC_VERSION_HEX < 0x070800 - FC_MSG(shape.getShape().TShape().get() << ", " << shape.getShape().HashCode(INT_MAX)); + constexpr int max = std::numeric_limits::max(); + FC_MSG(shape.getShape().TShape().get() << ", " << shape.getShape().HashCode(max)); #else FC_MSG(shape.getShape().TShape().get() << ", " << std::hash {}(shape.getShape())); @@ -2736,7 +2739,8 @@ public: for (int i = 1; i <= wireData->NbEdges(); ++i) { auto shape = wireData->Edge(i); #if OCC_VERSION_HEX < 0x070800 - FC_MSG(shape.TShape().get() << ", " << shape.HashCode(INT_MAX)); + constexpr int max = std::numeric_limits::max(); + FC_MSG(shape.TShape().get() << ", " << shape.HashCode(max)); #else FC_MSG(shape.TShape().get() << ", " << std::hash {}(shape)); #endif @@ -2800,9 +2804,10 @@ public: for (TopTools_ListIteratorOfListOfShape it(hist->Modified(shape.getShape())); it.More(); it.Next()) { #if OCC_VERSION_HEX < 0x070800 - FC_MSG(shape.getShape().TShape().get() - << ", " << shape.getShape().HashCode(INT_MAX) << " -> " - << it.Value().TShape().get() << ", " << it.Value().HashCode(INT_MAX)); + constexpr int max = std::numeric_limits::max(); + FC_MSG(shape.getShape().TShape().get() + << ", " << shape.getShape().HashCode(max) << " -> " + << it.Value().TShape().get() << ", " << it.Value().HashCode(max)); #else FC_MSG(shape.getShape().TShape().get() << ", " << std::hash {}(shape.getShape()) << " -> " diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index ebf58c6c27..0c6338f979 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include # include # include @@ -613,8 +614,8 @@ bool wireEncirclesAxis(const TopoDS_Wire& wire, const Handle(Geom_CylindricalSur // For an exact calculation, only two results would be possible: // totalArc = 0.0: The wire does not encircle the axis - // totalArc = 2 * M_PI * radius: The wire encircles the axis - return (fabs(totalArc) > M_PI * radius); + // totalArc = 2 * std::numbers::pi * radius: The wire encircles the axis + return (fabs(totalArc) > std::numbers::pi * radius); } TopoDS_Face FaceTypedCylinder::buildFace(const FaceVectorType &faces) const diff --git a/src/Mod/Part/Gui/CrossSections.cpp b/src/Mod/Part/Gui/CrossSections.cpp index ae425a6776..ed2f1f8dad 100644 --- a/src/Mod/Part/Gui/CrossSections.cpp +++ b/src/Mod/Part/Gui/CrossSections.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # include # include @@ -126,9 +125,10 @@ CrossSections::CrossSections(const Base::BoundBox3d& bb, QWidget* parent, Qt::Wi ui->setupUi(this); setupConnections(); - ui->position->setRange(-DBL_MAX, DBL_MAX); + constexpr double max = std::numeric_limits::max(); + ui->position->setRange(-max, max); ui->position->setUnit(Base::Unit::Length); - ui->distance->setRange(0, DBL_MAX); + ui->distance->setRange(0, max); ui->distance->setUnit(Base::Unit::Length); vp = new ViewProviderCrossSections(); diff --git a/src/Mod/Part/Gui/DlgFilletEdges.cpp b/src/Mod/Part/Gui/DlgFilletEdges.cpp index 7a1ece5eec..ea0356bd02 100644 --- a/src/Mod/Part/Gui/DlgFilletEdges.cpp +++ b/src/Mod/Part/Gui/DlgFilletEdges.cpp @@ -89,7 +89,7 @@ QWidget *FilletRadiusDelegate::createEditor(QWidget *parent, const QStyleOptionV Gui::QuantitySpinBox *editor = new Gui::QuantitySpinBox(parent); editor->setUnit(Base::Unit::Length); editor->setMinimum(0.0); - editor->setMaximum(INT_MAX); + editor->setMaximum(std::numeric_limits::max()); editor->setSingleStep(0.1); return editor; @@ -234,11 +234,11 @@ DlgFilletEdges::DlgFilletEdges(FilletType type, Part::FilletBase* fillet, QWidge ui->setupUi(this); setupConnections(); - ui->filletStartRadius->setMaximum(INT_MAX); + ui->filletStartRadius->setMaximum(std::numeric_limits::max()); ui->filletStartRadius->setMinimum(0); ui->filletStartRadius->setUnit(Base::Unit::Length); - ui->filletEndRadius->setMaximum(INT_MAX); + ui->filletEndRadius->setMaximum(std::numeric_limits::max()); ui->filletEndRadius->setMinimum(0); ui->filletEndRadius->setUnit(Base::Unit::Length); diff --git a/src/Mod/Part/Gui/DlgPrimitives.cpp b/src/Mod/Part/Gui/DlgPrimitives.cpp index bde63661a4..ef411ecb96 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.cpp +++ b/src/Mod/Part/Gui/DlgPrimitives.cpp @@ -239,8 +239,8 @@ PlanePrimitive::PlanePrimitive(std::shared_ptr ui, Part::Plane : AbstractPrimitive(feature) , ui(ui) { - ui->planeLength->setRange(0, INT_MAX); - ui->planeWidth->setRange(0, INT_MAX); + ui->planeLength->setRange(0, std::numeric_limits::max()); + ui->planeWidth->setRange(0, std::numeric_limits::max()); if (feature) { ui->planeLength->setValue(feature->Length.getQuantityValue()); @@ -308,9 +308,9 @@ BoxPrimitive::BoxPrimitive(std::shared_ptr ui, Part::Box* feat : AbstractPrimitive(feature) , ui(ui) { - ui->boxLength->setRange(0, INT_MAX); - ui->boxWidth->setRange(0, INT_MAX); - ui->boxHeight->setRange(0, INT_MAX); + ui->boxLength->setRange(0, std::numeric_limits::max()); + ui->boxWidth->setRange(0, std::numeric_limits::max()); + ui->boxHeight->setRange(0, std::numeric_limits::max()); if (feature) { ui->boxLength->setValue(feature->Length.getQuantityValue()); @@ -388,8 +388,8 @@ CylinderPrimitive::CylinderPrimitive(std::shared_ptr ui, Part: : AbstractPrimitive(feature) , ui(ui) { - ui->cylinderRadius->setRange(0, INT_MAX); - ui->cylinderHeight->setRange(0, INT_MAX); + ui->cylinderRadius->setRange(0, std::numeric_limits::max()); + ui->cylinderHeight->setRange(0, std::numeric_limits::max()); ui->cylinderAngle->setRange(0, 360); if (feature) { @@ -488,9 +488,9 @@ ConePrimitive::ConePrimitive(std::shared_ptr ui, Part::Cone* f : AbstractPrimitive(feature) , ui(ui) { - ui->coneRadius1->setRange(0, INT_MAX); - ui->coneRadius2->setRange(0, INT_MAX); - ui->coneHeight->setRange(0, INT_MAX); + ui->coneRadius1->setRange(0, std::numeric_limits::max()); + ui->coneRadius2->setRange(0, std::numeric_limits::max()); + ui->coneHeight->setRange(0, std::numeric_limits::max()); ui->coneAngle->setRange(0, 360); if (feature) { @@ -579,7 +579,7 @@ SpherePrimitive::SpherePrimitive(std::shared_ptr ui, Part::Sph : AbstractPrimitive(feature) , ui(ui) { - ui->sphereRadius->setRange(0, INT_MAX); + ui->sphereRadius->setRange(0, std::numeric_limits::max()); ui->sphereAngle1->setRange(-90, 90); ui->sphereAngle2->setRange(-90, 90); ui->sphereAngle3->setRange(0, 360); @@ -670,9 +670,9 @@ EllipsoidPrimitive::EllipsoidPrimitive(std::shared_ptr ui, Par : AbstractPrimitive(feature) , ui(ui) { - ui->ellipsoidRadius1->setRange(0, INT_MAX); - ui->ellipsoidRadius2->setRange(0, INT_MAX); - ui->ellipsoidRadius3->setRange(0, INT_MAX); + ui->ellipsoidRadius1->setRange(0, std::numeric_limits::max()); + ui->ellipsoidRadius2->setRange(0, std::numeric_limits::max()); + ui->ellipsoidRadius3->setRange(0, std::numeric_limits::max()); ui->ellipsoidAngle1->setRange(-90, 90); ui->ellipsoidAngle2->setRange(-90, 90); ui->ellipsoidAngle3->setRange(0, 360); @@ -784,8 +784,8 @@ TorusPrimitive::TorusPrimitive(std::shared_ptr ui, Part::Torus : AbstractPrimitive(feature) , ui(ui) { - ui->torusRadius1->setRange(0, INT_MAX); - ui->torusRadius2->setRange(0, INT_MAX); + ui->torusRadius1->setRange(0, std::numeric_limits::max()); + ui->torusRadius2->setRange(0, std::numeric_limits::max()); ui->torusAngle1->setRange(-180, 180); ui->torusAngle2->setRange(-180, 180); ui->torusAngle3->setRange(0, 360); @@ -886,8 +886,8 @@ PrismPrimitive::PrismPrimitive(std::shared_ptr ui, Part::Prism : AbstractPrimitive(feature) , ui(ui) { - ui->prismCircumradius->setRange(0, INT_MAX); - ui->prismHeight->setRange(0, INT_MAX); + ui->prismCircumradius->setRange(0, std::numeric_limits::max()); + ui->prismHeight->setRange(0, std::numeric_limits::max()); if (feature) { ui->prismPolygon->setValue(feature->Polygon.getValue()); @@ -984,26 +984,28 @@ WedgePrimitive::WedgePrimitive(std::shared_ptr ui, Part::Wedge : AbstractPrimitive(feature) , ui(ui) { - ui->wedgeXmin->setMinimum(INT_MIN); - ui->wedgeXmin->setMaximum(INT_MAX); - ui->wedgeYmin->setMinimum(INT_MIN); - ui->wedgeYmin->setMaximum(INT_MAX); - ui->wedgeZmin->setMinimum(INT_MIN); - ui->wedgeZmin->setMaximum(INT_MAX); - ui->wedgeX2min->setMinimum(INT_MIN); - ui->wedgeX2min->setMaximum(INT_MAX); - ui->wedgeZ2min->setMinimum(INT_MIN); - ui->wedgeZ2min->setMaximum(INT_MAX); - ui->wedgeXmax->setMinimum(INT_MIN); - ui->wedgeXmax->setMaximum(INT_MAX); - ui->wedgeYmax->setMinimum(INT_MIN); - ui->wedgeYmax->setMaximum(INT_MAX); - ui->wedgeZmax->setMinimum(INT_MIN); - ui->wedgeZmax->setMaximum(INT_MAX); - ui->wedgeX2max->setMinimum(INT_MIN); - ui->wedgeX2max->setMaximum(INT_MAX); - ui->wedgeZ2max->setMinimum(INT_MIN); - ui->wedgeZ2max->setMaximum(INT_MAX); + constexpr int min = std::numeric_limits::min(); + constexpr int max = std::numeric_limits::max(); + ui->wedgeXmin->setMinimum(min); + ui->wedgeXmin->setMaximum(max); + ui->wedgeYmin->setMinimum(min); + ui->wedgeYmin->setMaximum(max); + ui->wedgeZmin->setMinimum(min); + ui->wedgeZmin->setMaximum(max); + ui->wedgeX2min->setMinimum(min); + ui->wedgeX2min->setMaximum(max); + ui->wedgeZ2min->setMinimum(min); + ui->wedgeZ2min->setMaximum(max); + ui->wedgeXmax->setMinimum(min); + ui->wedgeXmax->setMaximum(max); + ui->wedgeYmax->setMinimum(min); + ui->wedgeYmax->setMaximum(max); + ui->wedgeZmax->setMinimum(min); + ui->wedgeZmax->setMaximum(max); + ui->wedgeX2max->setMinimum(min); + ui->wedgeX2max->setMaximum(max); + ui->wedgeZ2max->setMinimum(min); + ui->wedgeZ2max->setMaximum(max); if (feature) { ui->wedgeXmin->setValue(feature->Xmin.getQuantityValue()); @@ -1151,9 +1153,9 @@ HelixPrimitive::HelixPrimitive(std::shared_ptr ui, Part::Helix : AbstractPrimitive(feature) , ui(ui) { - ui->helixPitch->setRange(0, INT_MAX); - ui->helixHeight->setRange(0, INT_MAX); - ui->helixRadius->setRange(0, INT_MAX); + ui->helixPitch->setRange(0, std::numeric_limits::max()); + ui->helixHeight->setRange(0, std::numeric_limits::max()); + ui->helixRadius->setRange(0, std::numeric_limits::max()); ui->helixAngle->setRange(-89.9, 89.9); if (feature) { @@ -1252,9 +1254,9 @@ SpiralPrimitive::SpiralPrimitive(std::shared_ptr ui, Part::Spi : AbstractPrimitive(feature) , ui(ui) { - ui->spiralGrowth->setRange(0, INT_MAX); - ui->spiralRotation->setRange(0, INT_MAX); - ui->spiralRadius->setRange(0, INT_MAX); + ui->spiralGrowth->setRange(0, std::numeric_limits::max()); + ui->spiralRotation->setRange(0, std::numeric_limits::max()); + ui->spiralRadius->setRange(0, std::numeric_limits::max()); if (feature) { ui->spiralGrowth->setValue(feature->Growth.getQuantityValue()); @@ -1331,7 +1333,7 @@ CirclePrimitive::CirclePrimitive(std::shared_ptr ui, Part::Cir : AbstractPrimitive(feature) , ui(ui) { - ui->circleRadius->setRange(0, INT_MAX); + ui->circleRadius->setRange(0, std::numeric_limits::max()); ui->circleAngle1->setRange(0, 360); ui->circleAngle2->setRange(0, 360); @@ -1411,8 +1413,8 @@ EllipsePrimitive::EllipsePrimitive(std::shared_ptr ui, Part::E : AbstractPrimitive(feature) , ui(ui) { - ui->ellipseMajorRadius->setRange(0, INT_MAX); - ui->ellipseMinorRadius->setRange(0, INT_MAX); + ui->ellipseMajorRadius->setRange(0, std::numeric_limits::max()); + ui->ellipseMinorRadius->setRange(0, std::numeric_limits::max()); ui->ellipseAngle1->setRange(0, 360); ui->ellipseAngle2->setRange(0, 360); @@ -1502,7 +1504,7 @@ PolygonPrimitive::PolygonPrimitive(std::shared_ptr ui, Part::R : AbstractPrimitive(feature) , ui(ui) { - ui->regularPolygonCircumradius->setRange(0, INT_MAX); + ui->regularPolygonCircumradius->setRange(0, std::numeric_limits::max()); if (feature) { ui->regularPolygonPolygon->setValue(feature->Polygon.getValue()); @@ -1569,18 +1571,20 @@ LinePrimitive::LinePrimitive(std::shared_ptr ui, Part::Line* f : AbstractPrimitive(feature) , ui(ui) { - ui->edgeX1->setMaximum(INT_MAX); - ui->edgeX1->setMinimum(INT_MIN); - ui->edgeY1->setMaximum(INT_MAX); - ui->edgeY1->setMinimum(INT_MIN); - ui->edgeZ1->setMaximum(INT_MAX); - ui->edgeZ1->setMinimum(INT_MIN); - ui->edgeX2->setMaximum(INT_MAX); - ui->edgeX2->setMinimum(INT_MIN); - ui->edgeY2->setMaximum(INT_MAX); - ui->edgeY2->setMinimum(INT_MIN); - ui->edgeZ2->setMaximum(INT_MAX); - ui->edgeZ2->setMinimum(INT_MIN); + constexpr int min = std::numeric_limits::min(); + constexpr int max = std::numeric_limits::max(); + ui->edgeX1->setMaximum(max); + ui->edgeX1->setMinimum(min); + ui->edgeY1->setMaximum(max); + ui->edgeY1->setMinimum(min); + ui->edgeZ1->setMaximum(max); + ui->edgeZ1->setMinimum(min); + ui->edgeX2->setMaximum(max); + ui->edgeX2->setMinimum(min); + ui->edgeY2->setMaximum(max); + ui->edgeY2->setMinimum(min); + ui->edgeZ2->setMaximum(max); + ui->edgeZ2->setMinimum(min); if (feature) { ui->edgeX1->setValue(feature->X1.getQuantityValue()); @@ -1688,12 +1692,14 @@ VertexPrimitive::VertexPrimitive(std::shared_ptr ui, Part::Ver : AbstractPrimitive(feature) , ui(ui) { - ui->vertexX->setMaximum(INT_MAX); - ui->vertexY->setMaximum(INT_MAX); - ui->vertexZ->setMaximum(INT_MAX); - ui->vertexX->setMinimum(INT_MIN); - ui->vertexY->setMinimum(INT_MIN); - ui->vertexZ->setMinimum(INT_MIN); + constexpr int min = std::numeric_limits::min(); + constexpr int max = std::numeric_limits::max(); + ui->vertexX->setMaximum(max); + ui->vertexY->setMaximum(max); + ui->vertexZ->setMaximum(max); + ui->vertexX->setMinimum(min); + ui->vertexY->setMinimum(min); + ui->vertexZ->setMinimum(min); if (feature) { ui->vertexX->setValue(feature->X.getQuantityValue()); diff --git a/src/Mod/Part/Gui/DlgRevolution.cpp b/src/Mod/Part/Gui/DlgRevolution.cpp index 950552184b..04672dd218 100644 --- a/src/Mod/Part/Gui/DlgRevolution.cpp +++ b/src/Mod/Part/Gui/DlgRevolution.cpp @@ -103,16 +103,17 @@ DlgRevolution::DlgRevolution(QWidget* parent, Qt::WindowFlags fl) ui->setupUi(this); setupConnections(); - ui->xPos->setRange(-DBL_MAX,DBL_MAX); - ui->yPos->setRange(-DBL_MAX,DBL_MAX); - ui->zPos->setRange(-DBL_MAX,DBL_MAX); + constexpr double max = std::numeric_limits::max(); + ui->xPos->setRange(-max, max); + ui->yPos->setRange(-max, max); + ui->zPos->setRange(-max, max); ui->xPos->setUnit(Base::Unit::Length); ui->yPos->setUnit(Base::Unit::Length); ui->zPos->setUnit(Base::Unit::Length); - ui->xDir->setRange(-DBL_MAX,DBL_MAX); - ui->yDir->setRange(-DBL_MAX,DBL_MAX); - ui->zDir->setRange(-DBL_MAX,DBL_MAX); + ui->xDir->setRange(-max, max); + ui->yDir->setRange(-max, max); + ui->zDir->setRange(-max, max); ui->xDir->setUnit(Base::Unit()); ui->yDir->setUnit(Base::Unit()); ui->zDir->setUnit(Base::Unit()); @@ -307,7 +308,7 @@ bool DlgRevolution::validate() //check angle if (!axisLinkHasAngle){ - if (fabs(this->getAngle() / 180.0 * M_PI) < Precision::Angular()) { + if (fabs(this->getAngle() / 180.0 * std::numbers::pi) < Precision::Angular()) { QMessageBox::critical(this, windowTitle(), tr("Revolution angle span is zero. It must be non-zero.")); ui->angle->setFocus(); diff --git a/src/Mod/Part/Gui/Mirroring.cpp b/src/Mod/Part/Gui/Mirroring.cpp index ad456338cb..09881413da 100644 --- a/src/Mod/Part/Gui/Mirroring.cpp +++ b/src/Mod/Part/Gui/Mirroring.cpp @@ -24,9 +24,6 @@ #ifndef _PreComp_ -// to avoid compiler warnings of redefining contents of basic.h -// later by #include -# define _USE_MATH_DEFINES # include # include @@ -40,7 +37,6 @@ # include # include -# include # include # include # include @@ -182,9 +178,10 @@ Mirroring::Mirroring(QWidget* parent) : QWidget(parent), ui(new Ui_Mirroring) { ui->setupUi(this); - ui->baseX->setRange(-DBL_MAX, DBL_MAX); - ui->baseY->setRange(-DBL_MAX, DBL_MAX); - ui->baseZ->setRange(-DBL_MAX, DBL_MAX); + constexpr double max = std::numeric_limits::max(); + ui->baseX->setRange(-max, max); + ui->baseY->setRange(-max, max); + ui->baseZ->setRange(-max, max); ui->baseX->setUnit(Base::Unit::Length); ui->baseY->setUnit(Base::Unit::Length); ui->baseZ->setUnit(Base::Unit::Length); diff --git a/src/Mod/Part/Gui/PreCompiled.h b/src/Mod/Part/Gui/PreCompiled.h index 2f667b09ab..2eabeb2acf 100644 --- a/src/Mod/Part/Gui/PreCompiled.h +++ b/src/Mod/Part/Gui/PreCompiled.h @@ -45,7 +45,6 @@ #ifdef _PreComp_ // standard -#include #include // STL diff --git a/src/Mod/Part/Gui/PropertyEnumAttacherItem.cpp b/src/Mod/Part/Gui/PropertyEnumAttacherItem.cpp index 4907910d5d..15956d3bd9 100644 --- a/src/Mod/Part/Gui/PropertyEnumAttacherItem.cpp +++ b/src/Mod/Part/Gui/PropertyEnumAttacherItem.cpp @@ -24,10 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# ifdef _MSC_VER -# define _USE_MATH_DEFINES -# include -# endif //_MSC_VER +# include #endif // _PreComp_ #include diff --git a/src/Mod/Part/Gui/SectionCutting.cpp b/src/Mod/Part/Gui/SectionCutting.cpp index 55043207c6..0885ffa9ed 100644 --- a/src/Mod/Part/Gui/SectionCutting.cpp +++ b/src/Mod/Part/Gui/SectionCutting.cpp @@ -23,10 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ - -// to avoid compiler warnings of redefining contents of basic.h -// later by #include -# define _USE_MATH_DEFINES // NOLINT # include # include @@ -136,9 +132,10 @@ SectionCut::SectionCut(QWidget* parent) void SectionCut::initSpinBoxes() { - ui->cutX->setRange(-INT_MAX, INT_MAX); - ui->cutY->setRange(-INT_MAX, INT_MAX); - ui->cutZ->setRange(-INT_MAX, INT_MAX); + constexpr int max = std::numeric_limits::max(); + ui->cutX->setRange(-max, max); + ui->cutY->setRange(-max, max); + ui->cutZ->setRange(-max, max); } void SectionCut::initControls(const Base::BoundBox3d& BoundCompound) diff --git a/src/Mod/Part/Gui/SoBrepEdgeSet.cpp b/src/Mod/Part/Gui/SoBrepEdgeSet.cpp index dbb959bea4..6d8c5d2bba 100644 --- a/src/Mod/Part/Gui/SoBrepEdgeSet.cpp +++ b/src/Mod/Part/Gui/SoBrepEdgeSet.cpp @@ -32,7 +32,6 @@ # include # endif # include -# include # include # include # include @@ -85,7 +84,7 @@ void SoBrepEdgeSet::GLRender(SoGLRenderAction *action) selContext2->sl.push_back(-1); }else if(ctx) selContext2->sl = ctx->sl; - if(selContext2->highlightIndex==INT_MAX) { + if(selContext2->highlightIndex == std::numeric_limits::max()) { selContext2->hl.clear(); selContext2->hl.push_back(-1); }else if(ctx) @@ -93,7 +92,7 @@ void SoBrepEdgeSet::GLRender(SoGLRenderAction *action) ctx = selContext2; } - if(ctx && ctx->highlightIndex==INT_MAX) { + if(ctx && ctx->highlightIndex == std::numeric_limits::max()) { if(ctx->selectionIndex.empty() || ctx->isSelectAll()) { if(ctx2) { ctx2->selectionColor = ctx->highlightColor; @@ -329,7 +328,7 @@ void SoBrepEdgeSet::doAction(SoAction* action) if (!detail) { SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext); ctx->highlightColor = hlaction->getColor(); - ctx->highlightIndex = INT_MAX; + ctx->highlightIndex = std::numeric_limits::max(); ctx->hl.clear(); ctx->hl.push_back(-1); touch(); diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.cpp b/src/Mod/Part/Gui/SoBrepFaceSet.cpp index 14e716f20c..1f0c9be301 100644 --- a/src/Mod/Part/Gui/SoBrepFaceSet.cpp +++ b/src/Mod/Part/Gui/SoBrepFaceSet.cpp @@ -30,7 +30,6 @@ #ifndef _PreComp_ # include -# include # include # include # include @@ -194,7 +193,7 @@ void SoBrepFaceSet::doAction(SoAction* action) const SoDetail* detail = hlaction->getElement(); if (!detail) { SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext); - ctx->highlightIndex = INT_MAX; + ctx->highlightIndex = std::numeric_limits::max(); ctx->highlightColor = hlaction->getColor(); touch(); }else { @@ -549,7 +548,7 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action) // Transparency complicates stuff even more, but not here. It will be handled inside // overrideMaterialBinding() // - if(ctx && ctx->highlightIndex==INT_MAX) { + if(ctx && ctx->highlightIndex == std::numeric_limits::max()) { if(ctx->selectionIndex.empty() || ctx->isSelectAll()) { if(ctx2) { ctx2->selectionColor = ctx->highlightColor; @@ -1222,7 +1221,7 @@ void SoBrepFaceSet::renderHighlight(SoGLRenderAction *action, SelContextPtr ctx) mb.sendFirst(); // make sure we have the correct material int id = ctx->highlightIndex; - if (id!=INT_MAX && id >= this->partIndex.getNum()) { + if (id != std::numeric_limits::max() && id >= this->partIndex.getNum()) { SoDebugError::postWarning("SoBrepFaceSet::renderHighlight", "highlightIndex out of range"); } else { @@ -1234,7 +1233,7 @@ void SoBrepFaceSet::renderHighlight(SoGLRenderAction *action, SelContextPtr ctx) // coords int start=0; int length; - if(id==INT_MAX) { + if(id == std::numeric_limits::max()) { length = numindices; id = 0; } else { diff --git a/src/Mod/Part/Gui/SoBrepPointSet.cpp b/src/Mod/Part/Gui/SoBrepPointSet.cpp index def234fcd6..e8cef49446 100644 --- a/src/Mod/Part/Gui/SoBrepPointSet.cpp +++ b/src/Mod/Part/Gui/SoBrepPointSet.cpp @@ -32,7 +32,6 @@ # include # endif # include -# include # include # include # include @@ -82,7 +81,7 @@ void SoBrepPointSet::GLRender(SoGLRenderAction *action) if(selContext2->checkGlobal(ctx)) ctx = selContext2; - if(ctx && ctx->highlightIndex==INT_MAX) { + if(ctx && ctx->highlightIndex == std::numeric_limits::max()) { if(ctx->selectionIndex.empty() || ctx->isSelectAll()) { if(ctx2) { ctx2->selectionColor = ctx->highlightColor; @@ -192,7 +191,7 @@ void SoBrepPointSet::renderHighlight(SoGLRenderAction *action, SelContextPtr ctx int id = ctx->highlightIndex; const SbVec3f * coords3d = coords->getArrayPtr3(); if(coords3d) { - if(id == INT_MAX) { + if(id == std::numeric_limits::max()) { glBegin(GL_POINTS); for(int idx=startIndex.getValue();idxgetNum();++idx) glVertex3fv((const GLfloat*) (coords3d + idx)); @@ -269,7 +268,7 @@ void SoBrepPointSet::doAction(SoAction* action) SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext); const SoDetail* detail = hlaction->getElement(); if (!detail) { - ctx->highlightIndex = INT_MAX; + ctx->highlightIndex = std::numeric_limits::max(); ctx->highlightColor = hlaction->getColor(); touch(); return; diff --git a/src/Mod/Part/Gui/SoFCShapeObject.cpp b/src/Mod/Part/Gui/SoFCShapeObject.cpp index 50691d970b..1ee21830ce 100644 --- a/src/Mod/Part/Gui/SoFCShapeObject.cpp +++ b/src/Mod/Part/Gui/SoFCShapeObject.cpp @@ -32,7 +32,6 @@ # include # endif # include -# include # include # include # include @@ -160,9 +159,10 @@ void SoFCControlPoints::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &cen const SbVec3f * points = coords->getArrayPtr3(); if (!points) return; - float maxX=-FLT_MAX, minX=FLT_MAX, - maxY=-FLT_MAX, minY=FLT_MAX, - maxZ=-FLT_MAX, minZ=FLT_MAX; + constexpr float floatMax = std::numeric_limits::max(); + float maxX=-floatMax, minX=floatMax, + maxY=-floatMax, minY=floatMax, + maxZ=-floatMax, minZ=floatMax; int32_t len = coords->getNum(); if (len > 0) { for (int32_t i=0; iui.spinOffset->setUnit(Base::Unit::Length); - d->ui.spinOffset->setRange(-INT_MAX, INT_MAX); + d->ui.spinOffset->setRange(-std::numeric_limits::max(), + std::numeric_limits::max()); d->ui.spinOffset->setSingleStep(0.1); d->ui.facesButton->hide(); diff --git a/src/Mod/Part/Gui/TaskThickness.cpp b/src/Mod/Part/Gui/TaskThickness.cpp index 09ed63c457..cc5e27dafc 100644 --- a/src/Mod/Part/Gui/TaskThickness.cpp +++ b/src/Mod/Part/Gui/TaskThickness.cpp @@ -91,7 +91,8 @@ ThicknessWidget::ThicknessWidget(Part::Thickness* thickness, QWidget* parent) d->ui.fillOffset->hide(); QSignalBlocker blockOffset(d->ui.spinOffset); - d->ui.spinOffset->setRange(-INT_MAX, INT_MAX); + d->ui.spinOffset->setRange(-std::numeric_limits::max(), + std::numeric_limits::max()); d->ui.spinOffset->setSingleStep(0.1); d->ui.spinOffset->setValue(d->thickness->Value.getValue()); diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.cpp b/src/Mod/Part/Gui/ViewProvider2DObject.cpp index 50f8a20502..b54dab267f 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.cpp +++ b/src/Mod/Part/Gui/ViewProvider2DObject.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # include @@ -57,7 +56,8 @@ using namespace std; // Construction/Destruction const char* ViewProvider2DObjectGrid::GridStyleEnums[]= {"Dashed","Light",nullptr}; -App::PropertyQuantityConstraint::Constraints ViewProvider2DObjectGrid::GridSizeRange = {0.001,DBL_MAX,1.0}; +App::PropertyQuantityConstraint::Constraints ViewProvider2DObjectGrid::GridSizeRange = { + 0.001, std::numeric_limits::max(), 1.0}; PROPERTY_SOURCE(PartGui::ViewProvider2DObjectGrid, PartGui::ViewProvider2DObject) @@ -106,10 +106,11 @@ SoSeparator* ViewProvider2DObjectGrid::createGrid() else { // make sure that nine of the numbers are exactly zero because log(0) // is not defined - float xMin = std::abs(MinX) < FLT_EPSILON ? 0.01f : MinX; - float xMax = std::abs(MaxX) < FLT_EPSILON ? 0.01f : MaxX; - float yMin = std::abs(MinY) < FLT_EPSILON ? 0.01f : MinY; - float yMax = std::abs(MaxY) < FLT_EPSILON ? 0.01f : MaxY; + constexpr float floatEpsilon = std::numeric_limits::epsilon(); + float xMin = std::abs(MinX) < floatEpsilon ? 0.01f : MinX; + float xMax = std::abs(MaxX) < floatEpsilon ? 0.01f : MaxX; + float yMin = std::abs(MinY) < floatEpsilon ? 0.01f : MinY; + float yMax = std::abs(MaxY) < floatEpsilon ? 0.01f : MaxY; MiX = -exp(ceil(log(std::abs(xMin)))); MiX = std::min(MiX,(float)-exp(ceil(log(std::abs(0.1f*xMax))))); MaX = exp(ceil(log(std::abs(xMax)))); diff --git a/src/Mod/Part/Gui/ViewProviderAttachExtension.cpp b/src/Mod/Part/Gui/ViewProviderAttachExtension.cpp index 848fa93336..0a99471950 100644 --- a/src/Mod/Part/Gui/ViewProviderAttachExtension.cpp +++ b/src/Mod/Part/Gui/ViewProviderAttachExtension.cpp @@ -23,10 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# ifdef _MSC_VER -# define _USE_MATH_DEFINES -# include -# endif # include # include #endif diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 0c23016cd6..6c771fa64e 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -976,7 +976,7 @@ void ViewProviderPartExt::updateVisual() //deflection = std::min(deflection, 20.0); // create or use the mesh on the data structure - Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; + Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * std::numbers::pi; IMeshTools_Parameters meshParams; meshParams.Deflection = deflection; diff --git a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp index d0d0a84eee..f624823a22 100644 --- a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp +++ b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # include # include @@ -60,7 +59,8 @@ using namespace std; EXTENSION_PROPERTY_SOURCE(PartGui::ViewProviderGridExtension, Gui::ViewProviderExtension) -App::PropertyQuantityConstraint::Constraints ViewProviderGridExtension::GridSizeRange = { 0.001,DBL_MAX,1.0 }; +App::PropertyQuantityConstraint::Constraints ViewProviderGridExtension::GridSizeRange = { + 0.001, std::numeric_limits::max(), 1.0 }; namespace PartGui { diff --git a/src/Mod/Part/Gui/ViewProviderReference.cpp b/src/Mod/Part/Gui/ViewProviderReference.cpp index d6f272d076..b679a7d60a 100644 --- a/src/Mod/Part/Gui/ViewProviderReference.cpp +++ b/src/Mod/Part/Gui/ViewProviderReference.cpp @@ -23,9 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -// to avoid compiler warnings of redefining contents of basic.h -// later by #include "ViewProvider.h" -# define _USE_MATH_DEFINES # include # include diff --git a/tests/src/Mod/Part/App/FeatureExtrusion.cpp b/tests/src/Mod/Part/App/FeatureExtrusion.cpp index 4529d7def6..18c017f0a3 100644 --- a/tests/src/Mod/Part/App/FeatureExtrusion.cpp +++ b/tests/src/Mod/Part/App/FeatureExtrusion.cpp @@ -172,7 +172,7 @@ TEST_F(FeatureExtrusionTest, testExecuteAngled) { // Arrange const double ang = 30; - const double tangent = tan(ang / 180.0 * M_PI); + const double tangent = tan(ang / 180.0 * std::numbers::pi); // The shape is a truncated pyramid elongated by a truncated triangular prism in the middle. // Calc the volume of full size pyramid and prism, and subtract top volumes to truncate. @@ -209,7 +209,7 @@ TEST_F(FeatureExtrusionTest, testExecuteAngledRev) { // Arrange const double ang = 30; - const double tangent = tan(ang / 180.0 * M_PI); + const double tangent = tan(ang / 180.0 * std::numbers::pi); // The shape is a truncated pyramid elongated by a truncated triangular prism in the middle, // plus a rectangular prism. // Calc the volume of full size pyramid and prism, and subtract top volumes to truncate. @@ -249,7 +249,7 @@ TEST_F(FeatureExtrusionTest, testExecuteEdge) { // Arrange const double ang = 30; - const double tangent = tan(ang / 180.0 * M_PI); + const double tangent = tan(ang / 180.0 * std::numbers::pi); BRepBuilderAPI_MakeEdge e1(gp_Pnt(0, 0, 0), gp_Pnt(ext1, ext1, ext1)); auto edge = _doc->addObject("Edge"); edge->Shape.setValue(e1); @@ -270,7 +270,7 @@ TEST_F(FeatureExtrusionTest, testExecuteEdge) TEST_F(FeatureExtrusionTest, testExecuteDir) { // Arrange - const double sin45 = sin(45 / 180.0 * M_PI); + const double sin45 = sin(45 / 180.0 * std::numbers::pi); _extrusion->Dir.setValue(Base::Vector3d(0, 1, 1)); _extrusion->DirMode.setValue((long)0); // Act @@ -319,8 +319,10 @@ TEST_F(FeatureExtrusionTest, testFaceWithHoles) double volume = PartTestHelpers::getVolume(ts.getShape()); Base::BoundBox3d bb = ts.getBoundBox(); // Assert - EXPECT_FLOAT_EQ(volume, len * wid * ext1 - radius * radius * M_PI * ext1); + EXPECT_FLOAT_EQ(volume, len * wid * ext1 - radius * radius * std::numbers::pi * ext1); EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, len, wid, ext1))); - EXPECT_FLOAT_EQ(PartTestHelpers::getArea(face1), len * wid + radius * radius * M_PI); - EXPECT_FLOAT_EQ(PartTestHelpers::getArea(face2), len * wid - radius * radius * M_PI); + EXPECT_FLOAT_EQ(PartTestHelpers::getArea(face1), + len * wid + radius * radius * std::numbers::pi); + EXPECT_FLOAT_EQ(PartTestHelpers::getArea(face2), + len * wid - radius * radius * std::numbers::pi); } diff --git a/tests/src/Mod/Part/App/FeatureRevolution.cpp b/tests/src/Mod/Part/App/FeatureRevolution.cpp index 38eeafa562..90247e11b3 100644 --- a/tests/src/Mod/Part/App/FeatureRevolution.cpp +++ b/tests/src/Mod/Part/App/FeatureRevolution.cpp @@ -46,7 +46,7 @@ protected: TEST_F(FeatureRevolutionTest, testExecute) { // Arrange - double puckVolume = len * len * M_PI * wid; // Area is PIr2; apply height + double puckVolume = len * len * std::numbers::pi * wid; // Area is PIr2; apply height // Act _revolution->execute(); Part::TopoShape ts = _revolution->Shape.getValue(); @@ -62,8 +62,8 @@ TEST_F(FeatureRevolutionTest, testExecuteBase) // Arrange double rad = len + 1.0; double rad2 = 1.0; - double outerPuckVolume = rad * rad * M_PI * wid; // Area is PIr2; apply height - double innerPuckVolume = rad2 * rad2 * M_PI * wid; // Area is PIr2; apply height + double outerPuckVolume = rad * rad * std::numbers::pi * wid; // Area is PIr2; apply height + double innerPuckVolume = rad2 * rad2 * std::numbers::pi * wid; // Area is PIr2; apply height _revolution->Base.setValue(Base::Vector3d(len + 1, 0, 0)); // Act _revolution->execute(); @@ -79,7 +79,7 @@ TEST_F(FeatureRevolutionTest, testExecuteBase) TEST_F(FeatureRevolutionTest, testAxis) { // Arrange - double puckVolume = wid * wid * M_PI * len; // Area is PIr2 times height + double puckVolume = wid * wid * std::numbers::pi * len; // Area is PIr2 times height _revolution->Axis.setValue(Base::Vector3d(1, 0, 0)); // Act _revolution->execute(); @@ -98,7 +98,7 @@ TEST_F(FeatureRevolutionTest, testAxisLink) auto edge = _doc->addObject("Edge"); edge->Shape.setValue(e1); _revolution->AxisLink.setValue(edge); - // double puckVolume = wid * wid * M_PI * len; // Area is PIr2; apply height + // double puckVolume = wid * wid * std::numbers::pi * len; // Area is PIr2; apply height // Act _revolution->execute(); Part::TopoShape ts = _revolution->Shape.getValue(); @@ -115,7 +115,7 @@ TEST_F(FeatureRevolutionTest, testAxisLink) TEST_F(FeatureRevolutionTest, testSymmetric) { // Arrange - double puckVolume = len * len * M_PI * wid; // Area is PIr2 times height + double puckVolume = len * len * std::numbers::pi * wid; // Area is PIr2 times height _revolution->Symmetric.setValue(true); // Act _revolution->execute(); @@ -130,8 +130,8 @@ TEST_F(FeatureRevolutionTest, testSymmetric) TEST_F(FeatureRevolutionTest, testAngle) { // Arrange - double puckVolume = len * len * M_PI * wid; // Area is PIr2 times height - _revolution->Angle.setValue(90); // NOLINT magic number + double puckVolume = len * len * std::numbers::pi * wid; // Area is PIr2 times height + _revolution->Angle.setValue(90); // NOLINT magic number // Act _revolution->execute(); Part::TopoShape ts = _revolution->Shape.getValue(); diff --git a/tests/src/Mod/Part/App/TopoShapeExpansion.cpp b/tests/src/Mod/Part/App/TopoShapeExpansion.cpp index 81a2f4ee5a..ba6046852f 100644 --- a/tests/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/tests/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -608,10 +608,10 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceNull) double area3 = getArea(topoShape.getShape()); // Assert EXPECT_FALSE(face1.IsEqual(newFace.getShape())); - EXPECT_DOUBLE_EQ(area, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area1, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area2, Len * Wid - M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area3, Len * Wid + M_PI * Rad * Rad); + EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area2, Len * Wid - std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area3, Len * Wid + std::numbers::pi * Rad * Rad); EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); } @@ -632,8 +632,8 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceSimple) // Assert EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered EXPECT_FALSE(face1.IsEqual(newFace.getShape())); - EXPECT_DOUBLE_EQ(area, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area1, Len * Wid + M_PI * Rad * Rad); + EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); EXPECT_DOUBLE_EQ(area2, Len * Wid); EXPECT_DOUBLE_EQ(area3, Len * Wid); EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); @@ -656,8 +656,8 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceParams) // Assert EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered EXPECT_FALSE(face1.IsEqual(newFace.getShape())); - EXPECT_DOUBLE_EQ(area, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area1, Len * Wid + M_PI * Rad * Rad); + EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); EXPECT_DOUBLE_EQ(area2, Len * Wid); EXPECT_DOUBLE_EQ(area3, Len * Wid); EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); @@ -680,10 +680,10 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceFromFace) // Assert EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered EXPECT_FALSE(face1.IsEqual(newFace.getShape())); - EXPECT_DOUBLE_EQ(area, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area1, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area2, Len * Wid - M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area3, Len * Wid - M_PI * Rad * Rad); + EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area1, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area2, Len * Wid - std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area3, Len * Wid - std::numbers::pi * Rad * Rad); EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); } @@ -705,8 +705,8 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceOpenWire) // Assert EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered EXPECT_FALSE(face1.IsEqual(newFace.getShape())); - EXPECT_DOUBLE_EQ(area, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area1, 0); // Len * Wid - M_PI * Rad * Rad); + EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area1, 0); // Len * Wid - std::numbers::pi * Rad * Rad); EXPECT_DOUBLE_EQ(area2, Len * Wid); EXPECT_DOUBLE_EQ(area3, Len * Wid); EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); @@ -730,10 +730,10 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceClosedWire) // Assert EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered EXPECT_FALSE(face1.IsEqual(newFace.getShape())); - EXPECT_DOUBLE_EQ(area, Len * Wid + M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area1, 0); // Len * Wid - M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area2, M_PI * Rad * Rad); - EXPECT_DOUBLE_EQ(area3, M_PI * Rad * Rad); + EXPECT_DOUBLE_EQ(area, Len * Wid + std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area1, 0); // Len * Wid - std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area2, std::numbers::pi * Rad * Rad); + EXPECT_DOUBLE_EQ(area3, std::numbers::pi * Rad * Rad); EXPECT_STREQ(newFace.shapeName().c_str(), "Face"); } @@ -837,7 +837,7 @@ TEST_F(TopoShapeExpansionTest, splitWires) // Assert EXPECT_EQ(inner.size(), 1); EXPECT_DOUBLE_EQ(getLength(wire.getShape()), 2 + 2 + 3 + 3); - EXPECT_DOUBLE_EQ(getLength(inner.front().getShape()), M_PI * Rad * 2); + EXPECT_DOUBLE_EQ(getLength(inner.front().getShape()), std::numbers::pi * Rad * 2); EXPECT_EQ(wire.getShape().Orientation(), TopAbs_REVERSED); for (TopoShape& shape : inner) { EXPECT_EQ(shape.getShape().Orientation(), TopAbs_FORWARD); @@ -1284,7 +1284,7 @@ TEST_F(TopoShapeExpansionTest, makeElementShellOpen) const float Wid = 2; auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(Len, Wid); auto transform {gp_Trsf()}; - transform.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)), M_PI / 2); + transform.SetRotation(gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)), std::numbers::pi / 2); auto face2 = face1; // Shallow copy face2.Move(TopLoc_Location(transform)); TopoDS_Compound compound1; @@ -1562,7 +1562,7 @@ TEST_F(TopoShapeExpansionTest, makeElementDraft) std::vector subShapes = cube1TS.getSubTopoShapes(TopAbs_FACE); std::vector faces {subShapes[0], subShapes[1], subShapes[2], subShapes[3]}; const gp_Dir pullDirection {0, 0, 1}; - double angle {M_PI * 10 + double angle {std::numbers::pi * 10 / 8}; // Angle should be between Pi and Pi * 1.5 ( 180 and 270 degrees ) const gp_Pln plane {}; // Act @@ -1580,7 +1580,7 @@ TEST_F(TopoShapeExpansionTest, makeElementDraftTopoShapes) // Arrange auto [cube1TS, cube2TS] = CreateTwoTopoShapeCubes(); const gp_Dir pullDirection {0, 0, 1}; - double angle {M_PI * 10 + double angle {std::numbers::pi * 10 / 8}; // Angle should be between Pi and Pi * 1.5 ( 180 and 270 degrees ) const gp_Pln plane {}; // Act From 98876d070d673b169c0c773aff00d6e354b0e2c0 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:53 +0100 Subject: [PATCH 050/316] PartDesign: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/PartDesign/App/FeatureChamfer.cpp | 4 +++- src/Mod/PartDesign/App/FeatureDraft.cpp | 2 +- src/Mod/PartDesign/App/FeatureExtrude.cpp | 13 +++++++----- src/Mod/PartDesign/App/FeatureFillet.cpp | 2 +- src/Mod/PartDesign/App/FeatureGroove.cpp | 2 +- src/Mod/PartDesign/App/FeatureHelix.cpp | 10 +++++----- src/Mod/PartDesign/App/FeatureHole.cpp | 8 ++++---- .../PartDesign/App/FeatureLinearPattern.cpp | 3 ++- .../PartDesign/App/FeaturePolarPattern.cpp | 3 ++- src/Mod/PartDesign/App/FeaturePrimitive.cpp | 4 ++-- .../Gui/TaskPrimitiveParameters.cpp | 20 +++++++++---------- .../PartDesign/Gui/TaskScaledParameters.cpp | 2 +- src/Mod/PartDesign/Gui/Utils.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp | 2 +- .../PartDesign/Gui/ViewProviderDatumCS.cpp | 6 ++++-- .../Gui/ViewProviderTransformed.cpp | 2 +- 16 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp b/src/Mod/PartDesign/App/FeatureChamfer.cpp index 9a0bfab347..c09aa683d2 100644 --- a/src/Mod/PartDesign/App/FeatureChamfer.cpp +++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp @@ -35,6 +35,8 @@ # include #endif +#include + #include #include #include @@ -49,7 +51,7 @@ using namespace PartDesign; PROPERTY_SOURCE(PartDesign::Chamfer, PartDesign::DressUp) const char* ChamferTypeEnums[] = {"Equal distance", "Two distances", "Distance and Angle", nullptr}; -const App::PropertyQuantityConstraint::Constraints Chamfer::floatSize = {0.0, FLT_MAX, 0.1}; +const App::PropertyQuantityConstraint::Constraints Chamfer::floatSize = {0.0, std::numeric_limits::max(), 0.1}; const App::PropertyAngle::Constraints Chamfer::floatAngle = {0.0, 180.0, 1.0}; static App::DocumentObjectExecReturn *validateParameters(int chamferType, double size, double size2, double angle); diff --git a/src/Mod/PartDesign/App/FeatureDraft.cpp b/src/Mod/PartDesign/App/FeatureDraft.cpp index 7b74b486fc..d317b77863 100644 --- a/src/Mod/PartDesign/App/FeatureDraft.cpp +++ b/src/Mod/PartDesign/App/FeatureDraft.cpp @@ -244,7 +244,7 @@ App::DocumentObjectExecReturn *Draft::execute() if (c.GetType() != GeomAbs_Line) throw Base::TypeError("Neutral plane reference edge must be linear"); double a = c.Line().Angle(gp_Lin(c.Value(c.FirstParameter()), pullDirection)); - if (std::fabs(a - M_PI_2) > Precision::Confusion()) + if (std::fabs(a - std::numbers::pi/2) > Precision::Confusion()) throw Base::ValueError("Neutral plane reference edge must be normal to pull direction"); neutralPlane = gp_Pln(c.Value(c.FirstParameter()), pullDirection); } else { diff --git a/src/Mod/PartDesign/App/FeatureExtrude.cpp b/src/Mod/PartDesign/App/FeatureExtrude.cpp index 73659cc6bd..fbe4560184 100644 --- a/src/Mod/PartDesign/App/FeatureExtrude.cpp +++ b/src/Mod/PartDesign/App/FeatureExtrude.cpp @@ -50,7 +50,8 @@ using namespace PartDesign; PROPERTY_SOURCE(PartDesign::FeatureExtrude, PartDesign::ProfileBased) -App::PropertyQuantityConstraint::Constraints FeatureExtrude::signedLengthConstraint = { -DBL_MAX, DBL_MAX, 1.0 }; +App::PropertyQuantityConstraint::Constraints FeatureExtrude::signedLengthConstraint = { + -std::numeric_limits::max(), std::numeric_limits::max(), 1.0 }; double FeatureExtrude::maxAngle = 90 - Base::toDegrees(Precision::Angular()); App::PropertyAngle::Constraints FeatureExtrude::floatAngle = { -maxAngle, maxAngle, 1.0 }; @@ -714,11 +715,13 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt } } else { + using std::numbers::pi; + Part::ExtrusionParameters params; params.dir = dir; params.solid = makeface; - params.taperAngleFwd = this->TaperAngle.getValue() * M_PI / 180.0; - params.taperAngleRev = this->TaperAngle2.getValue() * M_PI / 180.0; + params.taperAngleFwd = this->TaperAngle.getValue() * pi / 180.0; + params.taperAngleRev = this->TaperAngle2.getValue() * pi / 180.0; if (L2 == 0.0 && Midplane.getValue()) { params.lengthFwd = L / 2; params.lengthRev = L / 2; @@ -732,8 +735,8 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt } if (std::fabs(params.taperAngleFwd) >= Precision::Angular() || std::fabs(params.taperAngleRev) >= Precision::Angular()) { - if (fabs(params.taperAngleFwd) > M_PI * 0.5 - Precision::Angular() - || fabs(params.taperAngleRev) > M_PI * 0.5 - Precision::Angular()) { + if (fabs(params.taperAngleFwd) > pi * 0.5 - Precision::Angular() + || fabs(params.taperAngleRev) > pi * 0.5 - Precision::Angular()) { return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP( "Exception", "Magnitude of taper angle matches or exceeds 90 degrees")); diff --git a/src/Mod/PartDesign/App/FeatureFillet.cpp b/src/Mod/PartDesign/App/FeatureFillet.cpp index 25d60c2778..c44653a76f 100644 --- a/src/Mod/PartDesign/App/FeatureFillet.cpp +++ b/src/Mod/PartDesign/App/FeatureFillet.cpp @@ -44,7 +44,7 @@ using namespace PartDesign; PROPERTY_SOURCE(PartDesign::Fillet, PartDesign::DressUp) -const App::PropertyQuantityConstraint::Constraints floatRadius = {0.0,FLT_MAX,0.1}; +const App::PropertyQuantityConstraint::Constraints floatRadius = {0.0, std::numeric_limits::max(), 0.1}; Fillet::Fillet() { diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index 66f27fdcd3..3df6e019eb 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -270,7 +270,7 @@ void Groove::generateRevolution(TopoDS_Shape& revol, angleOffset = angle2 * -1.0; } else if (method == RevolMethod::ThroughAll) { - angleTotal = 2 * M_PI; + angleTotal = 2 * std::numbers::pi; } else if (midplane) { // Rotate the face by half the angle to get Groove symmetric to sketch plane diff --git a/src/Mod/PartDesign/App/FeatureHelix.cpp b/src/Mod/PartDesign/App/FeatureHelix.cpp index 94cfab1c86..7acc3f267b 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.cpp +++ b/src/Mod/PartDesign/App/FeatureHelix.cpp @@ -61,8 +61,8 @@ const char* Helix::ModeEnums[] = { "pitch-height-angle", "pitch-turns-angle", "h PROPERTY_SOURCE(PartDesign::Helix, PartDesign::ProfileBased) // we purposely use not FLT_MAX because this would not be computable -const App::PropertyFloatConstraint::Constraints Helix::floatTurns = { Precision::Confusion(), INT_MAX, 1.0 }; -const App::PropertyFloatConstraint::Constraints Helix::floatTolerance = { 0.1, INT_MAX, 1.0 }; +const App::PropertyFloatConstraint::Constraints Helix::floatTurns = { Precision::Confusion(), std::numeric_limits::max(), 1.0 }; +const App::PropertyFloatConstraint::Constraints Helix::floatTolerance = { 0.1, std::numeric_limits::max(), 1.0 }; const App::PropertyAngle::Constraints Helix::floatAngle = { -89.0, 89.0, 1.0 }; Helix::Helix() @@ -442,13 +442,13 @@ TopoDS_Shape Helix::generateHelixPath(double breakAtTurn) // because of the radius factor we used above, we must reverse after the // startOffset movement (that brings the path back to the desired position) if (reversed) { - mov.SetRotation(gp_Ax1(origo, dir_axis2), M_PI); + mov.SetRotation(gp_Ax1(origo, dir_axis2), std::numbers::pi); TopLoc_Location loc(mov); path.Move(loc); } if (turned) { // turn the helix so that the starting point aligns with the profile - mov.SetRotation(gp_Ax1(origo, dir_axis1), M_PI); + mov.SetRotation(gp_Ax1(origo, dir_axis1), std::numbers::pi); TopLoc_Location loc(mov); path.Move(loc); } @@ -495,7 +495,7 @@ double Helix::safePitch() } } - double angle = Angle.getValue() / 180.0 * M_PI; + double angle = Angle.getValue() / 180.0 * std::numbers::pi; gp_Dir direction(axisVec.x, axisVec.y, axisVec.z); gp_Dir directionStart(startVec.x, startVec.y, startVec.z); TopoDS_Shape sketchshape = getVerifiedFace(); diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index 18dbb723ec..d3fc78e2f9 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -732,7 +732,7 @@ PROPERTY_SOURCE(PartDesign::Hole, PartDesign::ProfileBased) const App::PropertyAngle::Constraints Hole::floatAngle = { Base::toDegrees(Precision::Angular()), 180.0 - Base::toDegrees(Precision::Angular()), 1.0 }; // OCC can only create holes with a min diameter of 10 times the Precision::Confusion() -const App::PropertyQuantityConstraint::Constraints diameterRange = { 10 * Precision::Confusion(), FLT_MAX, 1.0 }; +const App::PropertyQuantityConstraint::Constraints diameterRange = { 10 * Precision::Confusion(), std::numeric_limits::max(), 1.0 }; Hole::Hole() { @@ -2244,7 +2244,7 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len // | base-sharpV Rmaj H // the little adjustment of p1 and p4 is here to prevent coincidencies - double marginX = std::tan(62.5 * M_PI / 180.0) * marginZ; + double marginX = std::tan(62.5 * std::numbers::pi / 180.0) * marginZ; gp_Pnt p1 = toPnt( (RmajC - 5 * H / 6 + marginX) * xDir @@ -2281,7 +2281,7 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len // | base-sharpV Rmaj // the little adjustment of p1 and p4 is here to prevent coincidencies - double marginX = std::tan(60.0 * M_PI / 180.0) * marginZ; + double marginX = std::tan(60.0 * std::numbers::pi / 180.0) * marginZ; gp_Pnt p1 = toPnt( (RmajC - h + marginX) * xDir + marginZ * zDir @@ -2343,7 +2343,7 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len // Reverse the direction of the helix. So that it goes into the material gp_Trsf mov; - mov.SetRotation(gp_Ax1(origo, dir_axis2), M_PI); + mov.SetRotation(gp_Ax1(origo, dir_axis2), std::numbers::pi); TopLoc_Location loc1(mov); helix.Move(loc1); diff --git a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp index 58455b4624..9d01fc33ab 100644 --- a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp +++ b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp @@ -49,7 +49,8 @@ namespace PartDesign { PROPERTY_SOURCE(PartDesign::LinearPattern, PartDesign::Transformed) -const App::PropertyIntegerConstraint::Constraints LinearPattern::intOccurrences = { 1, INT_MAX, 1 }; +const App::PropertyIntegerConstraint::Constraints LinearPattern::intOccurrences = { + 1, std::numeric_limits::max(), 1 }; const char* LinearPattern::ModeEnums[] = { "length", "offset", nullptr }; diff --git a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp index 0647a3ee17..7272147711 100644 --- a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp +++ b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp @@ -48,7 +48,8 @@ namespace PartDesign { PROPERTY_SOURCE(PartDesign::PolarPattern, PartDesign::Transformed) -const App::PropertyIntegerConstraint::Constraints PolarPattern::intOccurrences = { 1, INT_MAX, 1 }; +const App::PropertyIntegerConstraint::Constraints PolarPattern::intOccurrences = { + 1, std::numeric_limits::max(), 1 }; const App::PropertyAngle::Constraints PolarPattern::floatAngle = { Base::toDegrees(Precision::Angular()), 360.0, 1.0 }; const char* PolarPattern::ModeEnums[] = {"angle", "offset", nullptr}; diff --git a/src/Mod/PartDesign/App/FeaturePrimitive.cpp b/src/Mod/PartDesign/App/FeaturePrimitive.cpp index 21cc034d8d..72e772765a 100644 --- a/src/Mod/PartDesign/App/FeaturePrimitive.cpp +++ b/src/Mod/PartDesign/App/FeaturePrimitive.cpp @@ -56,8 +56,8 @@ const App::PropertyQuantityConstraint::Constraints angleRangeU = { 0.0, 360.0, 1 const App::PropertyQuantityConstraint::Constraints angleRangeV = { -90.0, 90.0, 1.0 }; // it turned out that OCC cannot e.g. create a box with a width of Precision::Confusion() // with two times Precision::Confusion() all geometric primitives can be created -const App::PropertyQuantityConstraint::Constraints quantityRange = { 2 * Precision::Confusion(), FLT_MAX, 0.1 }; -const App::PropertyQuantityConstraint::Constraints quantityRangeZero = { 0.0, FLT_MAX, 0.1 }; +const App::PropertyQuantityConstraint::Constraints quantityRange = { 2 * Precision::Confusion(), std::numeric_limits::max(), 0.1 }; +const App::PropertyQuantityConstraint::Constraints quantityRangeZero = { 0.0, std::numeric_limits::max(), 0.1 }; PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesign::FeaturePrimitive, PartDesign::FeatureAddSub) diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp index 539ed47128..a6d37a9362 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp @@ -222,26 +222,26 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->wedgeZ2max->bind(getObject()->Z2max); ui->wedgeZ2min->setValue(getObject()->Z2min.getValue()); ui->wedgeZ2min->bind(getObject()->Z2min); - ui->wedgeXmin->setMinimum(INT_MIN); + ui->wedgeXmin->setMinimum(std::numeric_limits::min()); ui->wedgeXmin->setMaximum(ui->wedgeXmax->rawValue()); // must be < than wedgeXmax - ui->wedgeYmin->setMinimum(INT_MIN); + ui->wedgeYmin->setMinimum(std::numeric_limits::min()); ui->wedgeYmin->setMaximum(ui->wedgeYmax->rawValue()); // must be < than wedgeYmax - ui->wedgeZmin->setMinimum(INT_MIN); + ui->wedgeZmin->setMinimum(std::numeric_limits::min()); ui->wedgeZmin->setMaximum(ui->wedgeZmax->rawValue()); // must be < than wedgeZmax - ui->wedgeX2min->setMinimum(INT_MIN); + ui->wedgeX2min->setMinimum(std::numeric_limits::min());; ui->wedgeX2min->setMaximum(ui->wedgeX2max->rawValue()); // must be <= than wedgeXmax - ui->wedgeZ2min->setMinimum(INT_MIN); + ui->wedgeZ2min->setMinimum(std::numeric_limits::min());; ui->wedgeZ2min->setMaximum(ui->wedgeZ2max->rawValue()); // must be <= than wedgeXmax ui->wedgeXmax->setMinimum(ui->wedgeXmin->rawValue()); - ui->wedgeXmax->setMaximum(INT_MAX); + ui->wedgeXmax->setMaximum(std::numeric_limits::max()); ui->wedgeYmax->setMinimum(ui->wedgeYmin->rawValue()); - ui->wedgeYmax->setMaximum(INT_MAX); + ui->wedgeYmax->setMaximum(std::numeric_limits::max()); ui->wedgeZmax->setMinimum(ui->wedgeZmin->rawValue()); - ui->wedgeZmax->setMaximum(INT_MAX); + ui->wedgeZmax->setMaximum(std::numeric_limits::max()); ui->wedgeX2max->setMinimum(ui->wedgeX2min->rawValue()); - ui->wedgeX2max->setMaximum(INT_MAX); + ui->wedgeX2max->setMaximum(std::numeric_limits::max()); ui->wedgeZ2max->setMinimum(ui->wedgeZ2min->rawValue()); - ui->wedgeZ2max->setMaximum(INT_MAX); + ui->wedgeZ2max->setMaximum(std::numeric_limits::max()); break; } diff --git a/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp b/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp index c6b30c4b75..ffb399a6ed 100644 --- a/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp @@ -78,7 +78,7 @@ void TaskScaledParameters::setupParameterUI(QWidget* widget) auto pcScaled = getObject(); ui->spinFactor->bind(pcScaled->Factor); - ui->spinOccurrences->setMaximum(INT_MAX); + ui->spinOccurrences->setMaximum(std::numeric_limits::max()); ui->spinOccurrences->bind(pcScaled->Occurrences); ui->spinFactor->setEnabled(true); ui->spinOccurrences->setEnabled(true); diff --git a/src/Mod/PartDesign/Gui/Utils.cpp b/src/Mod/PartDesign/Gui/Utils.cpp index 3976f848cf..09346de5d7 100644 --- a/src/Mod/PartDesign/Gui/Utils.cpp +++ b/src/Mod/PartDesign/Gui/Utils.cpp @@ -327,7 +327,7 @@ void fixSketchSupport (Sketcher::SketchObject* sketch) // Offset to base plane // Find out which direction we need to offset double a = sketchVector.GetAngle(pnt); - if ((a < -M_PI_2) || (a > M_PI_2)) + if ((a < -std::numbers::pi/2) || (a > std::numbers::pi/2)) offset *= -1.0; std::string Datum = doc->getUniqueObjectName("DatumPlane"); diff --git a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp index 8f44733ad8..66ad7b123d 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderAddSub.cpp @@ -121,7 +121,7 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() { Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure - Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; + Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * std::numbers::pi; BRepMesh_IncrementalMesh(cShape, deflection, Standard_False, AngDeflectionRads, Standard_True); // We must reset the location here because the transformation data diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp index 2961cc4a4e..6c7f7f77c3 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp @@ -45,8 +45,10 @@ using namespace PartDesignGui; PROPERTY_SOURCE(PartDesignGui::ViewProviderDatumCoordinateSystem,PartDesignGui::ViewProviderDatum) -const App::PropertyFloatConstraint::Constraints ZoomConstraint = {0.0,DBL_MAX,0.2}; -const App::PropertyIntegerConstraint::Constraints FontConstraint = {1,INT_MAX,1}; +const App::PropertyFloatConstraint::Constraints ZoomConstraint = { + 0.0, std::numeric_limits::max(), 0.2}; +const App::PropertyIntegerConstraint::Constraints FontConstraint = { + 1,std::numeric_limits::max(), 1}; ViewProviderDatumCoordinateSystem::ViewProviderDatumCoordinateSystem() { diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp index cca6ab97d7..b3edfa0efe 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -228,7 +228,7 @@ void ViewProviderTransformed::showRejectedShape(TopoDS_Shape shape) // create or use the mesh on the data structure // Note: This DOES have an effect on shape - Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; + Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * std::numbers::pi; BRepMesh_IncrementalMesh(shape, deflection, Standard_False, AngDeflectionRads, Standard_True); // We must reset the location here because the transformation data From 044997b1ac033ca39ecfa303e8b8144cc0667487 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:01:59 +0100 Subject: [PATCH 051/316] Point: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Points/App/PointsGrid.cpp | 2 +- src/Mod/Points/App/PointsGrid.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Points/App/PointsGrid.cpp b/src/Mod/Points/App/PointsGrid.cpp index 162b7cbc21..6b43641d5a 100644 --- a/src/Mod/Points/App/PointsGrid.cpp +++ b/src/Mod/Points/App/PointsGrid.cpp @@ -808,7 +808,7 @@ bool PointsGridIterator::InitOnRay(const Base::Vector3d& rclPt, // needed in NextOnRay() to avoid an infinite loop _cSearchPositions.clear(); - _fMaxSearchArea = FLOAT_MAX; + _fMaxSearchArea = std::numeric_limits::max(); raulElements.clear(); diff --git a/src/Mod/Points/App/PointsGrid.h b/src/Mod/Points/App/PointsGrid.h index 6965751178..52a6fc248a 100644 --- a/src/Mod/Points/App/PointsGrid.h +++ b/src/Mod/Points/App/PointsGrid.h @@ -293,7 +293,7 @@ private: Base::Vector3d _clPt; /**< Base point of search ray. */ Base::Vector3d _clDir; /**< Direction of search ray. */ bool _bValidRay {false}; /**< Search ray ok? */ - float _fMaxSearchArea {FLOAT_MAX}; + float _fMaxSearchArea {std::numeric_limits::max()}; /** Checks if a grid position is already visited by NextOnRay(). */ struct GridElement { From 7efa4c183040e5456b5d26512e1da4bb9a1951e9 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:02:09 +0100 Subject: [PATCH 052/316] ReverseEngineering: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/ReverseEngineering/App/RegionGrowing.cpp | 4 ++-- .../ReverseEngineering/App/SurfaceTriangulation.cpp | 12 ++++++------ src/Mod/ReverseEngineering/Gui/Command.cpp | 6 +++--- src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp | 2 +- src/Mod/ReverseEngineering/Gui/Segmentation.cpp | 4 ++-- .../ReverseEngineering/Gui/SegmentationManual.cpp | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Mod/ReverseEngineering/App/RegionGrowing.cpp b/src/Mod/ReverseEngineering/App/RegionGrowing.cpp index 1bdcd2cd83..68ce1df37f 100644 --- a/src/Mod/ReverseEngineering/App/RegionGrowing.cpp +++ b/src/Mod/ReverseEngineering/App/RegionGrowing.cpp @@ -88,7 +88,7 @@ void RegionGrowing::perform(int ksearch) reg.setInputCloud(cloud); // reg.setIndices (indices); reg.setInputNormals(normals); - reg.setSmoothnessThreshold(3.0 / 180.0 * M_PI); + reg.setSmoothnessThreshold(3.0 / 180.0 * std::numbers::pi); reg.setCurvatureThreshold(1.0); std::vector clusters; @@ -142,7 +142,7 @@ void RegionGrowing::perform(const std::vector& myNormals) reg.setInputCloud(cloud); // reg.setIndices (indices); reg.setInputNormals(normals); - reg.setSmoothnessThreshold(3.0 / 180.0 * M_PI); + reg.setSmoothnessThreshold(3.0 / 180.0 * std::numbers::pi); reg.setCurvatureThreshold(1.0); std::vector clusters; diff --git a/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp index 7da03c93a7..a718e20d6d 100644 --- a/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp +++ b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp @@ -114,9 +114,9 @@ void SurfaceTriangulation::perform(int ksearch) gp3.setSearchRadius(searchRadius); gp3.setMu(mu); gp3.setMaximumNearestNeighbors(100); - gp3.setMaximumSurfaceAngle(M_PI / 4); // 45 degrees - gp3.setMinimumAngle(M_PI / 18); // 10 degrees - gp3.setMaximumAngle(2 * M_PI / 3); // 120 degrees + gp3.setMaximumSurfaceAngle(std::numbers::pi / 4); // 45 degrees + gp3.setMinimumAngle(std::numbers::pi / 18); // 10 degrees + gp3.setMaximumAngle(2 * std::numbers::pi / 3); // 120 degrees gp3.setNormalConsistency(false); gp3.setConsistentVertexOrdering(true); @@ -171,9 +171,9 @@ void SurfaceTriangulation::perform(const std::vector& normals) gp3.setSearchRadius(searchRadius); gp3.setMu(mu); gp3.setMaximumNearestNeighbors(100); - gp3.setMaximumSurfaceAngle(M_PI / 4); // 45 degrees - gp3.setMinimumAngle(M_PI / 18); // 10 degrees - gp3.setMaximumAngle(2 * M_PI / 3); // 120 degrees + gp3.setMaximumSurfaceAngle(std::numbers::pi / 4); // 45 degrees + gp3.setMinimumAngle(std::numbers::pi / 18); // 10 degrees + gp3.setMaximumAngle(2 * std::numbers::pi / 3); // 120 degrees gp3.setNormalConsistency(true); gp3.setConsistentVertexOrdering(true); diff --git a/src/Mod/ReverseEngineering/Gui/Command.cpp b/src/Mod/ReverseEngineering/Gui/Command.cpp index aac035434c..2b184c39fa 100644 --- a/src/Mod/ReverseEngineering/Gui/Command.cpp +++ b/src/Mod/ReverseEngineering/Gui/Command.cpp @@ -272,7 +272,7 @@ void CmdApproxCylinder::activated(int) fit.SetInitialValues(base, axis); } - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base, top; fit.GetBounding(base, top); float height = Base::Distance(base, top); @@ -329,7 +329,7 @@ void CmdApproxSphere::activated(int) const MeshCore::MeshKernel& kernel = mesh.getKernel(); MeshCore::SphereFit fit; fit.AddPoints(kernel.GetPoints()); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetCenter(); std::stringstream str; @@ -378,7 +378,7 @@ void CmdApproxPolynomial::activated(int) const MeshCore::MeshKernel& kernel = mesh.getKernel(); MeshCore::SurfaceFit fit; fit.AddPoints(kernel.GetPoints()); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::BoundBox3f bbox = fit.GetBoundings(); std::vector poles = fit.toBezier(bbox.MinX, bbox.MaxX, bbox.MinY, bbox.MaxY); diff --git a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp index d109879661..de9da74cec 100644 --- a/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp +++ b/src/Mod/ReverseEngineering/Gui/FitBSplineSurface.cpp @@ -122,7 +122,7 @@ void FitBSplineSurfaceWidget::onMakePlacementClicked() }); MeshCore::PlaneFit fit; fit.AddPoints(data); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetBase(); Base::Vector3f dirU = fit.GetDirU(); Base::Vector3f norm = fit.GetNormal(); diff --git a/src/Mod/ReverseEngineering/Gui/Segmentation.cpp b/src/Mod/ReverseEngineering/Gui/Segmentation.cpp index 54ab2b9d49..6a47a77e86 100644 --- a/src/Mod/ReverseEngineering/Gui/Segmentation.cpp +++ b/src/Mod/ReverseEngineering/Gui/Segmentation.cpp @@ -59,7 +59,7 @@ Segmentation::Segmentation(Mesh::Feature* mesh, QWidget* parent, Qt::WindowFlags , myMesh(mesh) { ui->setupUi(this); - ui->numPln->setRange(1, INT_MAX); + ui->numPln->setRange(1, std::numeric_limits::max()); ui->numPln->setValue(100); ui->checkBoxSmooth->setChecked(false); @@ -115,7 +115,7 @@ void Segmentation::accept() std::vector indexes = kernel.GetFacetPoints(jt); MeshCore::PlaneFit fit; fit.AddPoints(kernel.GetPoints(indexes)); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetBase(); Base::Vector3f axis = fit.GetNormal(); MeshCore::AbstractSurfaceFit* fitter = diff --git a/src/Mod/ReverseEngineering/Gui/SegmentationManual.cpp b/src/Mod/ReverseEngineering/Gui/SegmentationManual.cpp index 55b7d376cb..0b0bac5e83 100644 --- a/src/Mod/ReverseEngineering/Gui/SegmentationManual.cpp +++ b/src/Mod/ReverseEngineering/Gui/SegmentationManual.cpp @@ -47,7 +47,7 @@ SegmentationManual::SegmentationManual(QWidget* parent, Qt::WindowFlags fl) { ui->setupUi(this); setupConnections(); - ui->spSelectComp->setRange(1, INT_MAX); + ui->spSelectComp->setRange(1, std::numeric_limits::max()); ui->spSelectComp->setValue(10); Gui::Selection().clearSelection(); @@ -215,7 +215,7 @@ void SegmentationManual::onPlaneDetectClicked() MeshCore::PlaneFit fit; fit.AddPoints(points); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetBase(); Base::Vector3f axis = fit.GetNormal(); return new MeshCore::PlaneSurfaceFit(base, axis); @@ -239,7 +239,7 @@ void SegmentationManual::onCylinderDetectClicked() Base::Vector3f axis = fit.GetInitialAxisFromNormals(normal); fit.SetInitialValues(base, axis); } - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetBase(); Base::Vector3f axis = fit.GetAxis(); float radius = fit.GetRadius(); @@ -259,7 +259,7 @@ void SegmentationManual::onSphereDetectClicked() MeshCore::SphereFit fit; fit.AddPoints(points); - if (fit.Fit() < FLOAT_MAX) { + if (fit.Fit() < std::numeric_limits::max()) { Base::Vector3f base = fit.GetCenter(); float radius = fit.GetRadius(); return new MeshCore::SphereSurfaceFit(base, radius); From e8d836f3900ac055fcd1cbc3454b3f70d0322484 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:02:17 +0100 Subject: [PATCH 053/316] Robots: Use std::numeric_limits and std::numbers instead of defines --- .../App/kdl_cp/chainiksolverpos_nr_jl.cpp | 15 ++----- src/Mod/Robot/App/kdl_cp/frames.cpp | 8 ++-- .../App/kdl_cp/path_roundedcomposite.hpp | 2 +- src/Mod/Robot/App/kdl_cp/utilities/rall2d.h | 2 +- src/Mod/Robot/Gui/ViewProviderRobotObject.cpp | 40 ++++++++++--------- 5 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/Mod/Robot/App/kdl_cp/chainiksolverpos_nr_jl.cpp b/src/Mod/Robot/App/kdl_cp/chainiksolverpos_nr_jl.cpp index 1ed3c4d72a..3814a77b79 100644 --- a/src/Mod/Robot/App/kdl_cp/chainiksolverpos_nr_jl.cpp +++ b/src/Mod/Robot/App/kdl_cp/chainiksolverpos_nr_jl.cpp @@ -21,17 +21,10 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#include + #include "chainiksolverpos_nr_jl.hpp" -// FreeCAD change -#ifndef M_PI - #define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef M_PI_2 - #define M_PI_2 1.57079632679489661923 /* pi/2 */ -#endif - namespace KDL { ChainIkSolverPos_NR_JL::ChainIkSolverPos_NR_JL(const Chain& _chain, const JntArray& _q_min, const JntArray& _q_max, ChainFkSolverPos& _fksolver,ChainIkSolverVel& _iksolver, @@ -60,14 +53,14 @@ namespace KDL for(unsigned int j=0; j q_max(j)) //q_out(j) = q_max(j); // FreeCAD change - q_out(j) = q_out(j) - M_PI *2; + q_out(j) = q_out(j) - std::numbers::pi *2; } } diff --git a/src/Mod/Robot/App/kdl_cp/frames.cpp b/src/Mod/Robot/App/kdl_cp/frames.cpp index 67baff97a5..ff24c29f6e 100644 --- a/src/Mod/Robot/App/kdl_cp/frames.cpp +++ b/src/Mod/Robot/App/kdl_cp/frames.cpp @@ -26,9 +26,7 @@ ***************************************************************************/ #include "frames.hpp" - -#define _USE_MATH_DEFINES // For MSVC -#include +#include namespace KDL { @@ -244,7 +242,7 @@ void Rotation::GetRPY(double& roll,double& pitch,double& yaw) const { double epsilon=1E-12; pitch = atan2(-data[6], sqrt( sqr(data[0]) +sqr(data[3]) ) ); - if ( fabs(pitch) > (M_PI/2.0-epsilon) ) { + if ( fabs(pitch) > (std::numbers::pi/2.0-epsilon) ) { yaw = atan2( -data[1], data[4]); roll = 0.0 ; } else { @@ -358,7 +356,7 @@ double Rotation::GetRotAngle(Vector& axis,double eps) const { return 0; } if (ca < -1+t) { - // The case of angles consisting of multiples of M_PI: + // The case of angles consisting of multiples of std::numbers::pi: // two solutions, choose a positive Z-component of the axis double x = sqrt( (data[0]+1.0)/2); double y = sqrt( (data[4]+1.0)/2); diff --git a/src/Mod/Robot/App/kdl_cp/path_roundedcomposite.hpp b/src/Mod/Robot/App/kdl_cp/path_roundedcomposite.hpp index 79c2657f57..ddb4bf7cc2 100644 --- a/src/Mod/Robot/App/kdl_cp/path_roundedcomposite.hpp +++ b/src/Mod/Robot/App/kdl_cp/path_roundedcomposite.hpp @@ -96,7 +96,7 @@ class Path_RoundedComposite : public Path * - 3101 if the eq. radius <= 0 * - 3102 if the first segment in a rounding has zero length. * - 3103 if the second segment in a rounding has zero length. - * - 3104 if the angle between the first and the second segment is close to M_PI. + * - 3104 if the angle between the first and the second segment is close to std::numbers::pi. * (meaning that the segments are on top of each other) * - 3105 if the distance needed for the rounding is larger then the first segment. * - 3106 if the distance needed for the rounding is larger then the second segment. diff --git a/src/Mod/Robot/App/kdl_cp/utilities/rall2d.h b/src/Mod/Robot/App/kdl_cp/utilities/rall2d.h index ef90674391..b80c27d13a 100644 --- a/src/Mod/Robot/App/kdl_cp/utilities/rall2d.h +++ b/src/Mod/Robot/App/kdl_cp/utilities/rall2d.h @@ -26,7 +26,7 @@ #ifndef Rall2D_H #define Rall2D_H -#include +#include #include #include "utility.h" diff --git a/src/Mod/Robot/Gui/ViewProviderRobotObject.cpp b/src/Mod/Robot/Gui/ViewProviderRobotObject.cpp index ec3ecd8feb..5b1852c2ba 100644 --- a/src/Mod/Robot/Gui/ViewProviderRobotObject.cpp +++ b/src/Mod/Robot/Gui/ViewProviderRobotObject.cpp @@ -173,6 +173,8 @@ void ViewProviderRobotObject::onChanged(const App::Property* prop) void ViewProviderRobotObject::updateData(const App::Property* prop) { + using std::numbers::pi; + Robot::RobotObject* robObj = static_cast(pcObject); if (prop == &robObj->RobotVrmlFile) { // read also from file @@ -269,33 +271,33 @@ void ViewProviderRobotObject::updateData(const App::Property* prop) } if (Axis1Node) { Axis1Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis1.getValue() * (M_PI / 180)); + robObj->Axis1.getValue() * (pi / 180)); } if (Axis2Node) { Axis2Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis2.getValue() * (M_PI / 180)); + robObj->Axis2.getValue() * (pi / 180)); } if (Axis3Node) { Axis3Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis3.getValue() * (M_PI / 180)); + robObj->Axis3.getValue() * (pi / 180)); } if (Axis4Node) { Axis4Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis4.getValue() * (M_PI / 180)); + robObj->Axis4.getValue() * (pi / 180)); } if (Axis5Node) { Axis5Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis5.getValue() * (M_PI / 180)); + robObj->Axis5.getValue() * (pi / 180)); } if (Axis6Node) { Axis6Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis6.getValue() * (M_PI / 180)); + robObj->Axis6.getValue() * (pi / 180)); } } else if (prop == &robObj->Axis1) { if (Axis1Node) { Axis1Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis1.getValue() * (M_PI / 180)); + robObj->Axis1.getValue() * (pi / 180)); if (toolShape) { toolShape->setTransformation( (robObj->Tcp.getValue() * (robObj->ToolBase.getValue().inverse())).toMatrix()); @@ -305,7 +307,7 @@ void ViewProviderRobotObject::updateData(const App::Property* prop) else if (prop == &robObj->Axis2) { if (Axis2Node) { Axis2Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis2.getValue() * (M_PI / 180)); + robObj->Axis2.getValue() * (pi / 180)); if (toolShape) { toolShape->setTransformation( (robObj->Tcp.getValue() * (robObj->ToolBase.getValue().inverse())).toMatrix()); @@ -315,7 +317,7 @@ void ViewProviderRobotObject::updateData(const App::Property* prop) else if (prop == &robObj->Axis3) { if (Axis3Node) { Axis3Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis3.getValue() * (M_PI / 180)); + robObj->Axis3.getValue() * (pi / 180)); if (toolShape) { toolShape->setTransformation( (robObj->Tcp.getValue() * (robObj->ToolBase.getValue().inverse())).toMatrix()); @@ -325,7 +327,7 @@ void ViewProviderRobotObject::updateData(const App::Property* prop) else if (prop == &robObj->Axis4) { if (Axis4Node) { Axis4Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis4.getValue() * (M_PI / 180)); + robObj->Axis4.getValue() * (pi / 180)); if (toolShape) { toolShape->setTransformation( (robObj->Tcp.getValue() * (robObj->ToolBase.getValue().inverse())).toMatrix()); @@ -335,7 +337,7 @@ void ViewProviderRobotObject::updateData(const App::Property* prop) else if (prop == &robObj->Axis5) { if (Axis5Node) { Axis5Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis5.getValue() * (M_PI / 180)); + robObj->Axis5.getValue() * (pi / 180)); if (toolShape) { toolShape->setTransformation( (robObj->Tcp.getValue() * (robObj->ToolBase.getValue().inverse())).toMatrix()); @@ -345,7 +347,7 @@ void ViewProviderRobotObject::updateData(const App::Property* prop) else if (prop == &robObj->Axis6) { if (Axis6Node) { Axis6Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), - robObj->Axis6.getValue() * (M_PI / 180)); + robObj->Axis6.getValue() * (pi / 180)); if (toolShape) { toolShape->setTransformation( (robObj->Tcp.getValue() * (robObj->ToolBase.getValue().inverse())).toMatrix()); @@ -395,27 +397,29 @@ void ViewProviderRobotObject::setAxisTo(float A1, float A6, const Base::Placement& Tcp) { + using std::numbers::pi; + Robot::RobotObject* robObj = static_cast(pcObject); if (Axis1Node) { // FIXME Ugly hack for the wrong transformation of the Kuka 500 robot VRML the minus sign on // Axis 1 - Axis1Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A1 * (M_PI / 180)); + Axis1Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A1 * (pi / 180)); } if (Axis2Node) { - Axis2Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A2 * (M_PI / 180)); + Axis2Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A2 * (pi / 180)); } if (Axis3Node) { - Axis3Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A3 * (M_PI / 180)); + Axis3Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A3 * (pi / 180)); } if (Axis4Node) { - Axis4Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A4 * (M_PI / 180)); + Axis4Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A4 * (pi / 180)); } if (Axis5Node) { - Axis5Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A5 * (M_PI / 180)); + Axis5Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A5 * (pi / 180)); } if (Axis6Node) { - Axis6Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A6 * (M_PI / 180)); + Axis6Node->rotation.setValue(SbVec3f(0.0, 1.0, 0.0), A6 * (pi / 180)); } // update tool position if (toolShape) { From b4eb28e50e848ca466cb03970a5d8c05d68fa37d Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:02:24 +0100 Subject: [PATCH 054/316] Sketcher: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Sketcher/App/Sketch.cpp | 19 ++--- src/Mod/Sketcher/App/SketchAnalysis.cpp | 5 +- src/Mod/Sketcher/App/SketchAnalysis.h | 6 +- src/Mod/Sketcher/App/SketchObject.cpp | 74 ++++++++++-------- src/Mod/Sketcher/App/SketchObject.h | 6 +- src/Mod/Sketcher/App/SketchObjectPyImp.cpp | 6 +- src/Mod/Sketcher/App/planegcs/Constraints.cpp | 10 ++- src/Mod/Sketcher/App/planegcs/GCS.cpp | 17 +++- src/Mod/Sketcher/App/planegcs/Geo.h | 3 - src/Mod/Sketcher/Gui/CommandConstraints.cpp | 7 +- .../Sketcher/Gui/CommandSketcherBSpline.cpp | 1 - .../Sketcher/Gui/CommandSketcherOverlay.cpp | 1 - src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 13 ++-- .../Gui/CommandSketcherVirtualSpace.cpp | 1 - src/Mod/Sketcher/Gui/DrawSketchHandler.cpp | 18 +++-- src/Mod/Sketcher/Gui/DrawSketchHandlerArc.h | 6 +- .../Gui/DrawSketchHandlerArcOfEllipse.h | 19 +++-- .../Gui/DrawSketchHandlerArcOfHyperbola.h | 8 +- .../Sketcher/Gui/DrawSketchHandlerArcSlot.h | 14 ++-- .../Sketcher/Gui/DrawSketchHandlerExtend.h | 17 ++-- src/Mod/Sketcher/Gui/DrawSketchHandlerLine.h | 9 ++- .../Sketcher/Gui/DrawSketchHandlerLineSet.h | 16 ++-- .../Sketcher/Gui/DrawSketchHandlerOffset.h | 4 +- .../Sketcher/Gui/DrawSketchHandlerPolygon.h | 3 +- .../Sketcher/Gui/DrawSketchHandlerRectangle.h | 74 ++++++++++-------- .../Sketcher/Gui/DrawSketchHandlerRotate.h | 11 +-- src/Mod/Sketcher/Gui/DrawSketchHandlerSlot.h | 16 ++-- .../Sketcher/Gui/DrawSketchHandlerTranslate.h | 10 ++- .../Gui/EditModeConstraintCoinManager.cpp | 48 ++++++------ src/Mod/Sketcher/Gui/PreCompiled.h | 1 - src/Mod/Sketcher/Gui/SnapManager.cpp | 9 ++- src/Mod/Sketcher/Gui/SoZoomTranslation.cpp | 1 - .../Sketcher/Gui/TaskSketcherConstraints.cpp | 5 +- src/Mod/Sketcher/Gui/TaskSketcherElements.cpp | 7 +- .../Gui/TaskSketcherGeneral.ui.autosave | 77 +++++++++++++++++++ src/Mod/Sketcher/Gui/Utils.cpp | 3 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 12 +-- tests/src/Mod/Sketcher/App/SketchObject.cpp | 8 +- .../Mod/Sketcher/App/SketchObjectChanges.cpp | 4 +- .../Mod/Sketcher/App/SketcherTestHelpers.cpp | 6 +- .../Mod/Sketcher/App/planegcs/Constraints.cpp | 5 +- 41 files changed, 355 insertions(+), 225 deletions(-) create mode 100644 src/Mod/Sketcher/Gui/TaskSketcherGeneral.ui.autosave diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index fef264d601..24d350825d 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -3060,6 +3060,7 @@ int Sketch::addAngleAtPointConstraint(int geoId1, ConstraintType cTyp, bool driving) { + using std::numbers::pi; if (!(cTyp == Angle || cTyp == Tangent || cTyp == Perpendicular)) { // assert(0);//none of the three types. Why are we here?? return -1; @@ -3132,28 +3133,28 @@ int Sketch::addAngleAtPointConstraint(int geoId1, // the desired angle value (and we are to decide if 180* should be added to it) double angleDesire = 0.0; if (cTyp == Tangent) { - angleOffset = -M_PI / 2; + angleOffset = -pi / 2; angleDesire = 0.0; } if (cTyp == Perpendicular) { angleOffset = 0; - angleDesire = M_PI / 2; + angleDesire = pi / 2; } if (*value == 0.0) { // autodetect tangency internal/external (and same for perpendicularity) double angleErr = GCSsys.calculateAngleViaPoint(*crv1, *crv2, p) - angleDesire; // bring angleErr to -pi..pi - if (angleErr > M_PI) { - angleErr -= M_PI * 2; + if (angleErr > pi) { + angleErr -= pi * 2; } - if (angleErr < -M_PI) { - angleErr += M_PI * 2; + if (angleErr < -pi) { + angleErr += pi * 2; } // the autodetector - if (fabs(angleErr) > M_PI / 2) { - angleDesire += M_PI; + if (fabs(angleErr) > pi / 2) { + angleDesire += pi; } *angle = angleDesire; @@ -4542,7 +4543,7 @@ bool Sketch::updateNonDrivingConstraints() } else if ((*it).constr->Type == Angle) { - (*it).constr->setValue(std::fmod(*((*it).value), 2.0 * M_PI)); + (*it).constr->setValue(std::fmod(*((*it).value), 2.0 * std::numbers::pi)); } else if ((*it).constr->Type == Diameter && (*it).constr->First >= 0) { diff --git a/src/Mod/Sketcher/App/SketchAnalysis.cpp b/src/Mod/Sketcher/App/SketchAnalysis.cpp index e2e4751771..81d20781ef 100644 --- a/src/Mod/Sketcher/App/SketchAnalysis.cpp +++ b/src/Mod/Sketcher/App/SketchAnalysis.cpp @@ -591,7 +591,7 @@ void SketchAnalysis::analyseMissingPointOnPointCoincident(double angleprecision) if (fabs(tgv1 * tgv2) > fabs(cos(angleprecision))) { vc.Type = Sketcher::Tangent; } - else if (fabs(tgv1 * tgv2) < fabs(cos(M_PI / 2 - angleprecision))) { + else if (fabs(tgv1 * tgv2) < fabs(cos(std::numbers::pi / 2 - angleprecision))) { vc.Type = Sketcher::Perpendicular; } } @@ -726,7 +726,8 @@ void SketchAnalysis::makeMissingVerticalHorizontalOneByOne() bool SketchAnalysis::checkVertical(Base::Vector3d dir, double angleprecision) { - return (dir.x == 0. && dir.y != 0.) || (fabs(dir.y / dir.x) > tan(M_PI / 2 - angleprecision)); + return (dir.x == 0. && dir.y != 0.) + || (fabs(dir.y / dir.x) > tan(std::numbers::pi / 2 - angleprecision)); } bool SketchAnalysis::checkHorizontal(Base::Vector3d dir, double angleprecision) diff --git a/src/Mod/Sketcher/App/SketchAnalysis.h b/src/Mod/Sketcher/App/SketchAnalysis.h index 4695254d29..dc354b6d80 100644 --- a/src/Mod/Sketcher/App/SketchAnalysis.h +++ b/src/Mod/Sketcher/App/SketchAnalysis.h @@ -94,7 +94,7 @@ public: int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000, bool includeconstruction = true); /// Point on Point constraint simple routine Analyse step (see constructor) - void analyseMissingPointOnPointCoincident(double angleprecision = M_PI / 8); + void analyseMissingPointOnPointCoincident(double angleprecision = std::numbers::pi / 8); /// Point on Point constraint simple routine Get step (see constructor) std::vector& getMissingPointOnPointConstraints() { @@ -113,7 +113,7 @@ public: void makeMissingPointOnPointCoincidentOneByOne(); /// Vertical/Horizontal constraints simple routine Detect step (see constructor) - int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI / 8); + int detectMissingVerticalHorizontalConstraints(double angleprecision = std::numbers::pi / 8); /// Vertical/Horizontal constraints simple routine Get step (see constructor) std::vector& getMissingVerticalHorizontalConstraints() { @@ -168,7 +168,7 @@ public: /// /// It applies coincidents - vertical/horizontal constraints and equality constraints. int autoconstraint(double precision = Precision::Confusion() * 1000, - double angleprecision = M_PI / 8, + double angleprecision = std::numbers::pi / 8, bool includeconstruction = true); // helper functions, which may be used by more complex methods, and/or called directly by user diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 64b717d48d..e7f62dfb41 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1143,7 +1143,7 @@ void SketchObject::reverseAngleConstraintToSupplementary(Constraint* constr, int } else { double actAngle = constr->getValue(); - constr->setValue(M_PI - actAngle); + constr->setValue(std::numbers::pi - actAngle); } } @@ -3248,12 +3248,12 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1, std::swap(startAngle, endAngle); } - if (endAngle > 2 * M_PI) { - endAngle -= 2 * M_PI; + if (endAngle > 2 * std::numbers::pi) { + endAngle -= 2 * std::numbers::pi; } if (startAngle < 0) { - endAngle += 2 * M_PI; + endAngle += 2 * std::numbers::pi; } // Create Arc Segment @@ -4905,6 +4905,8 @@ std::vector SketchObject::getSymmetric(const std::vector& int refGeoId, Sketcher::PointPos refPosId) { + using std::numbers::pi; + std::vector symmetricVals; bool refIsLine = refPosId == Sketcher::PointPos::none; int cgeoid = getHighestCurveIndex() + 1; @@ -4980,8 +4982,8 @@ std::vector SketchObject::getSymmetric(const std::vector& Base::Vector3d scp = cp + 2.0 * (cp.Perpendicular(refGeoLine->getStartPoint(), vectline) - cp); - double theta1 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f * M_PI); - double theta2 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f * M_PI); + double theta1 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f * std::numbers::pi); + double theta2 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f * std::numbers::pi); geoaoc->setCenter(scp); geoaoc->setRange(theta1, theta2, true); @@ -5028,12 +5030,12 @@ std::vector SketchObject::getSymmetric(const std::vector& double theta1, theta2; geosymaoe->getRange(theta1, theta2, true); - theta1 = 2.0 * M_PI - theta1; - theta2 = 2.0 * M_PI - theta2; + theta1 = 2.0 * pi - theta1; + theta2 = 2.0 * pi - theta2; std::swap(theta1, theta2); if (theta1 < 0) { - theta1 += 2.0 * M_PI; - theta2 += 2.0 * M_PI; + theta1 += 2.0 * pi; + theta2 += 2.0 * pi; } geosymaoe->setRange(theta1, theta2, true); @@ -5178,8 +5180,8 @@ std::vector SketchObject::getSymmetric(const std::vector& Base::Vector3d sep = ep + 2.0 * (refpoint - ep); Base::Vector3d scp = cp + 2.0 * (refpoint - cp); - double theta1 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f * M_PI); - double theta2 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f * M_PI); + double theta1 = Base::fmod(atan2(ssp.y - scp.y, ssp.x - scp.x), 2.f * pi); + double theta2 = Base::fmod(atan2(sep.y - scp.y, sep.x - scp.x), 2.f * pi); geoaoc->setCenter(scp); geoaoc->setRange(theta1, theta2, true); @@ -8568,6 +8570,8 @@ void processEdge(const TopoDS_Edge& edge, gp_Ax3& sketchAx3, TopoDS_Shape& aProjFace) { + using std::numbers::pi; + BRepAdaptor_Curve curve(edge); if (curve.GetType() == GeomAbs_Line) { geos.emplace_back(projectLine(curve, gPlane, invPlm)); @@ -8641,11 +8645,11 @@ void processEdge(const TopoDS_Edge& edge, int tours = 0; double startAngle = baseAngle + alpha; // bring startAngle back in [-pi/2 , 3pi/2[ - while (startAngle < -M_PI / 2.0 && tours < 10) { - startAngle = baseAngle + ++tours * 2.0 * M_PI + alpha; + while (startAngle < -pi / 2.0 && tours < 10) { + startAngle = baseAngle + ++tours * 2.0 * pi + alpha; } - while (startAngle >= 3.0 * M_PI / 2.0 && tours > -10) { - startAngle = baseAngle + --tours * 2.0 * M_PI + alpha; + while (startAngle >= 3.0 * pi / 2.0 && tours > -10) { + startAngle = baseAngle + --tours * 2.0 * pi + alpha; } // apply same offset to end angle @@ -8661,7 +8665,7 @@ void processEdge(const TopoDS_Edge& edge, // P2 = P2 already defined P1 = ProjPointOnPlane_XYZ(beg, sketchPlane); } - else if (endAngle < M_PI) { + else if (endAngle < pi) { // P2 = P2, already defined P1 = ProjPointOnPlane_XYZ(end, sketchPlane); } @@ -8671,16 +8675,16 @@ void processEdge(const TopoDS_Edge& edge, } } } - else if (startAngle < M_PI) { - if (endAngle < M_PI) { + else if (startAngle < pi) { + if (endAngle < pi) { P1 = ProjPointOnPlane_XYZ(beg, sketchPlane); P2 = ProjPointOnPlane_XYZ(end, sketchPlane); } - else if (endAngle < 2.0 * M_PI - startAngle) { + else if (endAngle < 2.0 * pi - startAngle) { P2 = ProjPointOnPlane_XYZ(beg, sketchPlane); // P1 = P1, already defined } - else if (endAngle < 2.0 * M_PI) { + else if (endAngle < 2.0 * pi) { P2 = ProjPointOnPlane_XYZ(end, sketchPlane); // P1 = P1, already defined } @@ -8690,15 +8694,15 @@ void processEdge(const TopoDS_Edge& edge, } } else { - if (endAngle < 2 * M_PI) { + if (endAngle < 2 * pi) { P1 = ProjPointOnPlane_XYZ(beg, sketchPlane); P2 = ProjPointOnPlane_XYZ(end, sketchPlane); } - else if (endAngle < 4 * M_PI - startAngle) { + else if (endAngle < 4 * pi - startAngle) { P1 = ProjPointOnPlane_XYZ(beg, sketchPlane); // P2 = P2, already defined } - else if (endAngle < 3 * M_PI) { + else if (endAngle < 3 * pi) { // P1 = P1, already defined P2 = ProjPointOnPlane_XYZ(end, sketchPlane); } @@ -8818,7 +8822,7 @@ void processEdge(const TopoDS_Edge& edge, gp_Vec2d PB = ProjVecOnPlane_UV(origAxisMinor, sketchPlane); double t_max = 2.0 * PA.Dot(PB) / (PA.SquareMagnitude() - PB.SquareMagnitude()); t_max = 0.5 * atan(t_max);// gives new major axis is most cases, but not all - double t_min = t_max + 0.5 * M_PI; + double t_min = t_max + 0.5 * pi; // ON_max = OM(t_max) gives the point, which projected on the sketch plane, // becomes the apoapse of the projected ellipse. @@ -9313,7 +9317,7 @@ void SketchObject::rebuildExternalGeometry(std::optional extToAdd processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace); } - if (fabs(dnormal.Angle(snormal) - M_PI_2) < Precision::Confusion()) { + if (fabs(dnormal.Angle(snormal) - std::numbers::pi/2) < Precision::Confusion()) { // The face is normal to the sketch plane // We don't want to keep the projection of all the edges of the face. // We need a single line that goes from min to max of all the projections. @@ -11310,6 +11314,8 @@ int SketchObject::port_reversedExternalArcs(bool justAnalyze) /// false - fail (this indicates an error, or that a constraint locking isn't supported). bool SketchObject::AutoLockTangencyAndPerpty(Constraint* cstr, bool bForce, bool bLock) { + using std::numbers::pi; + try { // assert ( cstr->Type == Tangent || cstr->Type == Perpendicular); /*tangency type already set. If not bForce - don't touch.*/ @@ -11359,25 +11365,25 @@ bool SketchObject::AutoLockTangencyAndPerpty(Constraint* cstr, bool bForce, bool // the desired angle value (and we are to decide if 180* should be added to it) double angleDesire = 0.0; if (cstr->Type == Tangent) { - angleOffset = -M_PI / 2; + angleOffset = -pi / 2; angleDesire = 0.0; } if (cstr->Type == Perpendicular) { angleOffset = 0; - angleDesire = M_PI / 2; + angleDesire = pi / 2; } double angleErr = calculateAngleViaPoint(geoId1, geoId2, p.x, p.y) - angleDesire; // bring angleErr to -pi..pi - if (angleErr > M_PI) - angleErr -= M_PI * 2; - if (angleErr < -M_PI) - angleErr += M_PI * 2; + if (angleErr > pi) + angleErr -= pi * 2; + if (angleErr < -pi) + angleErr += pi * 2; // the autodetector - if (fabs(angleErr) > M_PI / 2) - angleDesire += M_PI; + if (fabs(angleErr) > pi / 2) + angleDesire += pi; // external tangency. The angle stored is offset by Pi/2 so that a value of 0.0 is // invalid and treated as "undecided". diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 05a484c7be..4d17218403 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -841,13 +841,13 @@ public: public: // Analyser functions int autoConstraint(double precision = Precision::Confusion() * 1000, - double angleprecision = M_PI / 20, + double angleprecision = std::numbers::pi / 20, bool includeconstruction = true); int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000, bool includeconstruction = true); - void analyseMissingPointOnPointCoincident(double angleprecision = M_PI / 8); - int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI / 8); + void analyseMissingPointOnPointCoincident(double angleprecision = std::numbers::pi / 8); + int detectMissingVerticalHorizontalConstraints(double angleprecision = std::numbers::pi / 8); int detectMissingEqualityConstraints(double precision); std::vector& getMissingPointOnPointConstraints(); diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index eaf4156d1a..28cc485a3f 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -1918,7 +1918,7 @@ PyObject* SketchObjectPy::insertBSplineKnot(PyObject* args) PyObject* SketchObjectPy::autoconstraint(PyObject* args) { double precision = Precision::Confusion() * 1000; - double angleprecision = M_PI / 8; + double angleprecision = std::numbers::pi / 8; PyObject* includeconstruction = Py_True; @@ -1960,7 +1960,7 @@ PyObject* SketchObjectPy::detectMissingPointOnPointConstraints(PyObject* args) PyObject* SketchObjectPy::detectMissingVerticalHorizontalConstraints(PyObject* args) { - double angleprecision = M_PI / 8; + double angleprecision = std::numbers::pi / 8; if (!PyArg_ParseTuple(args, "|d", &angleprecision)) { return nullptr; @@ -1984,7 +1984,7 @@ PyObject* SketchObjectPy::detectMissingEqualityConstraints(PyObject* args) PyObject* SketchObjectPy::analyseMissingPointOnPointCoincident(PyObject* args) { - double angleprecision = M_PI / 8; + double angleprecision = std::numbers::pi / 8; if (!PyArg_ParseTuple(args, "|d", &angleprecision)) { return nullptr; diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.cpp b/src/Mod/Sketcher/App/planegcs/Constraints.cpp index 539dfd9f95..336d20e3d2 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.cpp +++ b/src/Mod/Sketcher/App/planegcs/Constraints.cpp @@ -24,8 +24,8 @@ #pragma warning(disable : 4251) #endif -#define _USE_MATH_DEFINES #include +#include #include #define DEBUG_DERIVS 0 @@ -864,6 +864,8 @@ double ConstraintP2PAngle::grad(double* param) double ConstraintP2PAngle::maxStep(MAP_pD_D& dir, double lim) { + constexpr double pi_18 = std::numbers::pi / 18; + MAP_pD_D::iterator it = dir.find(angle()); if (it != dir.end()) { double step = std::abs(it->second); @@ -1444,6 +1446,8 @@ double ConstraintL2LAngle::grad(double* param) double ConstraintL2LAngle::maxStep(MAP_pD_D& dir, double lim) { + constexpr double pi_18 = std::numbers::pi / 18; + MAP_pD_D::iterator it = dir.find(angle()); if (it != dir.end()) { double step = std::abs(it->second); @@ -3536,10 +3540,10 @@ void ConstraintArcLength::errorgrad(double* err, double* grad, double* param) double startA = *arc.startAngle; // Assume positive angles and CCW arc while (startA < 0.) { - startA += 2. * M_PI; + startA += 2. * std::numbers::pi; } while (endA < startA) { - endA += 2. * M_PI; + endA += 2. * std::numbers::pi; } if (err) { *err = rad * (endA - startA) - *distance(); diff --git a/src/Mod/Sketcher/App/planegcs/GCS.cpp b/src/Mod/Sketcher/App/planegcs/GCS.cpp index f397db6a10..bc63d84608 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/planegcs/GCS.cpp @@ -47,10 +47,10 @@ #endif #include -#include #include #include #include +#include #include "GCS.h" #include "qp_eq.h" @@ -1029,6 +1029,8 @@ int System::addConstraintPerpendicularLine2Arc(Point& p1, int tagId, bool driving) { + using std::numbers::pi; + addConstraintP2PCoincident(p2, a.start, tagId, driving); double dx = *(p2.x) - *(p1.x); double dy = *(p2.y) - *(p1.y); @@ -1046,6 +1048,8 @@ int System::addConstraintPerpendicularArc2Line(Arc& a, int tagId, bool driving) { + using std::numbers::pi; + addConstraintP2PCoincident(p1, a.end, tagId, driving); double dx = *(p2.x) - *(p1.x); double dy = *(p2.y) - *(p1.y); @@ -1063,8 +1067,10 @@ int System::addConstraintPerpendicularCircle2Arc(Point& center, int tagId, bool driving) { + using std::numbers::pi; + addConstraintP2PDistance(a.start, center, radius, tagId, driving); - double incrAngle = *(a.startAngle) < *(a.endAngle) ? pi_2 : -pi_2; + double incrAngle = *(a.startAngle) < *(a.endAngle) ? pi / 2 : -pi / 2; double tangAngle = *a.startAngle + incrAngle; double dx = *(a.start.x) - *(center.x); double dy = *(a.start.y) - *(center.y); @@ -1082,8 +1088,10 @@ int System::addConstraintPerpendicularArc2Circle(Arc& a, int tagId, bool driving) { + using std::numbers::pi; + addConstraintP2PDistance(a.end, center, radius, tagId, driving); - double incrAngle = *(a.startAngle) < *(a.endAngle) ? -pi_2 : pi_2; + double incrAngle = *(a.startAngle) < *(a.endAngle) ? -pi / 2 : pi / 2; double tangAngle = *a.endAngle + incrAngle; double dx = *(a.end.x) - *(center.x); double dy = *(a.end.y) - *(center.y); @@ -2270,12 +2278,13 @@ int System::solve_LM(SubSystem* subsys, bool isRedundantsolving) x_new = x + h; h_norm = h.squaredNorm(); + constexpr double epsilon = std::numeric_limits::epsilon(); if (h_norm <= eps1 * eps1 * x.norm()) { // relative change in p is small, stop stop = 3; break; } - else if (h_norm >= (x.norm() + eps1) / (DBL_EPSILON * DBL_EPSILON)) { + else if (h_norm >= (x.norm() + eps1) / (epsilon * epsilon)) { // almost singular stop = 4; break; diff --git a/src/Mod/Sketcher/App/planegcs/Geo.h b/src/Mod/Sketcher/App/planegcs/Geo.h index 4604c55b26..bbfdf39736 100644 --- a/src/Mod/Sketcher/App/planegcs/Geo.h +++ b/src/Mod/Sketcher/App/planegcs/Geo.h @@ -53,9 +53,6 @@ public: }; using VEC_P = std::vector; -static constexpr double pi = boost::math::constants::pi(); -static constexpr double pi_2 = pi / 2.0; -static constexpr double pi_18 = pi / 18.0; /// Class DeriVector2 holds a vector value and its derivative on the /// parameter that the derivatives are being calculated for now. x,y is the diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index d46109ce7f..8ed676bb93 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -24,7 +24,6 @@ #ifndef _PreComp_ #include #include -#include #endif #include @@ -114,10 +113,10 @@ void finishDatumConstraint(Gui::Command* cmd, if (lastConstraintType == Radius || lastConstraintType == Diameter) { labelPosition = hGrp->GetFloat("RadiusDiameterConstraintDisplayBaseAngle", 15.0) - * (M_PI / 180);// Get radius/diameter constraint display angle + * (std::numbers::pi / 180);// Get radius/diameter constraint display angle labelPositionRandomness = hGrp->GetFloat("RadiusDiameterConstraintDisplayAngleRandomness", 0.0) - * (M_PI / 180);// Get randomness + * (std::numbers::pi / 180);// Get randomness // Adds a random value around the base angle, so that possibly overlapping labels get likely // a different position. @@ -320,7 +319,7 @@ bool SketcherGui::calculateAngle(Sketcher::SketchObject* Obj, int& GeoId1, int& } else { // if all points are collinear - double length = DBL_MAX; + double length = std::numeric_limits::max(); for (int i = 0; i <= 1; i++) { for (int j = 0; j <= 1; j++) { double tmp = Base::DistanceP2(p2[j], p1[i]); diff --git a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp index 3b6e6819d0..ee3f9b5381 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp @@ -24,7 +24,6 @@ #ifndef _PreComp_ #include #include -#include #endif #include diff --git a/src/Mod/Sketcher/Gui/CommandSketcherOverlay.cpp b/src/Mod/Sketcher/Gui/CommandSketcherOverlay.cpp index 4dc6673d96..0e0158f73e 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherOverlay.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherOverlay.cpp @@ -24,7 +24,6 @@ #ifndef _PreComp_ #include #include -#include #endif #include diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index 1fbfc714cb..4058d4e827 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include @@ -1205,6 +1204,8 @@ public: void mouseMove(Base::Vector2d onSketchPos) override { + using std::numbers::pi; + if (Mode == STATUS_SEEK_First) { if (QApplication::keyboardModifiers() == Qt::ControlModifier) @@ -1218,14 +1219,14 @@ public: Base::Vector2d endpoint = onSketchPos; if (snapMode == SnapMode::Snap5Degree) { - angle = round(angle / (M_PI / 36)) * M_PI / 36; + angle = round(angle / (pi / 36)) * pi / 36; endpoint = EditCurve[0] + length * Base::Vector2d(cos(angle), sin(angle)); } if (showCursorCoords()) { SbString text; std::string lengthString = lengthToDisplayFormat(length, 1); - std::string angleString = angleToDisplayFormat(angle * 180.0 / M_PI, 1); + std::string angleString = angleToDisplayFormat(angle * 180.0 / pi, 1); text.sprintf(" (%s, %s)", lengthString.c_str(), angleString.c_str()); setPositionText(endpoint, text); } @@ -1781,6 +1782,8 @@ public: void mouseMove(Base::Vector2d onSketchPos) override { + using std::numbers::pi; + if (Mode == STATUS_SEEK_First) { if (QApplication::keyboardModifiers() == Qt::ControlModifier) @@ -1794,14 +1797,14 @@ public: Base::Vector2d endpoint = onSketchPos; if (snapMode == SnapMode::Snap5Degree) { - angle = round(angle / (M_PI / 36)) * M_PI / 36; + angle = round(angle / (pi / 36)) * pi / 36; endpoint = EditCurve[0] + length * Base::Vector2d(cos(angle), sin(angle)); } if (showCursorCoords()) { SbString text; std::string lengthString = lengthToDisplayFormat(length, 1); - std::string angleString = angleToDisplayFormat(angle * 180.0 / M_PI, 1); + std::string angleString = angleToDisplayFormat(angle * 180.0 / pi, 1); text.sprintf(" (%s, %s)", lengthString.c_str(), angleString.c_str()); setPositionText(endpoint, text); } diff --git a/src/Mod/Sketcher/Gui/CommandSketcherVirtualSpace.cpp b/src/Mod/Sketcher/Gui/CommandSketcherVirtualSpace.cpp index 6fcfdbfdf9..4af8107eb2 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherVirtualSpace.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherVirtualSpace.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #endif #include diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index e378625ac1..b6ff76dfd8 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -425,6 +425,8 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested const Base::Vector2d& Dir, AutoConstraint::TargetType type) { + using std::numbers::pi; + suggestedConstraints.clear(); SketchObject* obj = sketchgui->getSketchObject(); @@ -550,18 +552,18 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested // Number of Degree of deviation from horizontal or vertical lines const double angleDev = 2; - const double angleDevRad = angleDev * M_PI / 180.; + const double angleDevRad = angleDev * pi / 180.; AutoConstraint constr; constr.Type = Sketcher::None; constr.GeoId = GeoEnum::GeoUndef; constr.PosId = PointPos::none; double angle = std::abs(atan2(Dir.y, Dir.x)); - if (angle < angleDevRad || (M_PI - angle) < angleDevRad) { + if (angle < angleDevRad || (pi - angle) < angleDevRad) { // Suggest horizontal constraint constr.Type = Sketcher::Horizontal; } - else if (std::abs(angle - M_PI_2) < angleDevRad) { + else if (std::abs(angle - pi / 2) < angleDevRad) { // Suggest vertical constraint constr.Type = Sketcher::Vertical; } @@ -665,7 +667,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested double angle = atan2(projPnt.y, projPnt.x); while (angle < startAngle) { - angle += 2 * D_PI; // Bring it to range of arc + angle += 2 * pi; // Bring it to range of arc } // if the point is on correct side of arc @@ -714,10 +716,10 @@ int DrawSketchHandler::seekAutoConstraint(std::vector& suggested aoe->getMinorRadius() * ((tmpPos.x - center.x) * majdir.x + (tmpPos.y - center.y) * majdir.y)) - startAngle, - 2.f * M_PI); + 2.f * pi); while (angle < startAngle) { - angle += 2 * D_PI; // Bring it to range of arc + angle += 2 * pi; // Bring it to range of arc } // if the point is on correct side of arc @@ -978,7 +980,7 @@ void DrawSketchHandler::drawDirectionAtCursor(const Base::Vector2d& position, SbString text; std::string lengthString = lengthToDisplayFormat(length, 1); - std::string angleString = angleToDisplayFormat(angle * 180.0 / M_PI, 1); + std::string angleString = angleToDisplayFormat(angle * 180.0 / std::numbers::pi, 1); text.sprintf(" (%s, %s)", lengthString.c_str(), angleString.c_str()); setPositionText(position, text); } @@ -1009,7 +1011,7 @@ void DrawSketchHandler::drawDoubleAtCursor(const Base::Vector2d& position, SbString text; std::string doubleString = unit == Base::Unit::Length ? lengthToDisplayFormat(val, 1) - : angleToDisplayFormat(val * 180.0 / M_PI, 1); + : angleToDisplayFormat(val * 180.0 / std::numbers::pi, 1); text.sprintf(" (%s)", doubleString.c_str()); setPositionText(position, text); } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArc.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArc.h index af25729b50..54123fb115 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArc.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArc.h @@ -132,7 +132,7 @@ private: if (constructionMethod() == ConstructionMethod::Center) { secondPoint = onSketchPos; double angle1 = (onSketchPos - centerPoint).Angle() - startAngle; - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi; arcAngle = abs(angle1 - arcAngle) < abs(angle2 - arcAngle) ? angle1 : angle2; if (arcAngle > 0) { @@ -183,7 +183,7 @@ private: } startAngle = std::max(angle1, angle2); endAngle = std::min(angle1, angle2); - arcAngle = 2 * M_PI - (startAngle - endAngle); + arcAngle = 2 * std::numbers::pi - (startAngle - endAngle); } } @@ -562,7 +562,7 @@ void DSHArcControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchPo if (onViewParameters[OnViewParameter::Fifth]->isSet) { double arcAngle = Base::toRadians(onViewParameters[OnViewParameter::Fifth]->getValue()); - if (fmod(fabs(arcAngle), 2 * M_PI) < Precision::Confusion()) { + if (fmod(fabs(arcAngle), 2 * std::numbers::pi) < Precision::Confusion()) { unsetOnViewParameter(onViewParameters[OnViewParameter::Fifth].get()); return; } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h index 5185010b1c..a4ebaad0f1 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h @@ -68,6 +68,8 @@ public: void mouseMove(Base::Vector2d onSketchPos) override { + using std::numbers::pi; + if (Mode == STATUS_SEEK_First) { setPositionText(onSketchPos); seekAndRenderAutoConstraint(sugConstr1, @@ -78,7 +80,7 @@ public: double rx0 = onSketchPos.x - EditCurve[0].x; double ry0 = onSketchPos.y - EditCurve[0].y; for (int i = 0; i < 16; i++) { - double angle = i * M_PI / 16.0; + double angle = i * pi / 16.0; double rx1 = rx0 * cos(angle) + ry0 * sin(angle); double ry1 = -rx0 * sin(angle) + ry0 * cos(angle); EditCurve[1 + i] = Base::Vector2d(EditCurve[0].x + rx1, EditCurve[0].y + ry1); @@ -115,7 +117,7 @@ public: / (sin(angleatpoint) * cos(phi)); for (int i = 1; i < 16; i++) { - double angle = i * M_PI / 16.0; + double angle = i * pi / 16.0; double rx1 = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi); double ry1 = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi); EditCurve[1 + i] = Base::Vector2d(EditCurve[0].x + rx1, EditCurve[0].y + ry1); @@ -161,7 +163,7 @@ public: + (onSketchPos.y - centerPoint.y) * sin(phi))) - startAngle; - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * pi; arcAngle = abs(angle1 - arcAngle) < abs(angle2 - arcAngle) ? angle1 : angle2; for (int i = 0; i < 34; i++) { @@ -178,7 +180,7 @@ public: SbString text; std::string aString = lengthToDisplayFormat(a, 1); std::string bString = lengthToDisplayFormat(b, 1); - std::string angleString = angleToDisplayFormat(arcAngle * 180.0 / M_PI, 1); + std::string angleString = angleToDisplayFormat(arcAngle * 180.0 / pi, 1); text.sprintf(" (R%s, R%s, %s)", aString.c_str(), bString.c_str(), @@ -222,6 +224,9 @@ public: bool releaseButton(Base::Vector2d onSketchPos) override { Q_UNUSED(onSketchPos); + + using std::numbers::pi; + if (Mode == STATUS_Close) { unsetCursor(); resetPositionText(); @@ -245,7 +250,7 @@ public: + (endPoint.y - centerPoint.y) * sin(phi))) - startAngle; - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * pi; arcAngle = abs(angle1 - arcAngle) < abs(angle2 - arcAngle) ? angle1 : angle2; bool isOriginalArcCCW = true; @@ -281,8 +286,8 @@ public: perp.Scale(abs(b)); majAxisPoint = centerPoint + perp; minAxisPoint = centerPoint + minAxisDir; - endAngle += M_PI / 2; - startAngle += M_PI / 2; + endAngle += pi / 2; + startAngle += pi / 2; } int currentgeoid = getHighestCurveIndex(); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h index 620f1bc0a1..9f96e3f169 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h @@ -103,7 +103,7 @@ public: if (!boost::math::isnan(b)) { for (int i = 15; i >= -15; i--) { // P(U) = O + MajRad*Cosh(U)*XDir + MinRad*Sinh(U)*YDir - // double angle = i*M_PI/16.0; + // double angle = i*std::numbers::pi/16.0; double angle = i * angleatpoint / 15; double rx = a * cosh(angle) * cos(phi) - b * sinh(angle) * sin(phi); double ry = a * cosh(angle) * sin(phi) + b * sinh(angle) * cos(phi); @@ -150,7 +150,7 @@ public: /*double angle1 = angleatpoint - startAngle; - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi ; arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;*/ arcAngle = angleatpoint - startAngle; @@ -290,8 +290,8 @@ public: perp.Scale(abs(b)); majAxisPoint = centerPoint + perp; minAxisPoint = centerPoint + minAxisDir; - endAngle += M_PI / 2; - startAngle += M_PI / 2; + endAngle += std::numbers::pi / 2; + startAngle += std::numbers::pi / 2; } int currentgeoid = getHighestCurveIndex(); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcSlot.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcSlot.h index 354930156a..cbd996489a 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcSlot.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcSlot.h @@ -133,7 +133,7 @@ private: startAngle = startAngleBackup; double angle1 = (onSketchPos - centerPoint).Angle() - startAngle; - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi; arcAngle = abs(angle1 - arcAngle) < abs(angle2 - arcAngle) ? angle1 : angle2; reverseIfNecessary(); @@ -305,6 +305,8 @@ private: void createShape(bool onlyeditoutline) override { + using std::numbers::pi; + ShapeGeometry.clear(); if (radius < Precision::Confusion()) { @@ -331,14 +333,14 @@ private: isConstructionMode()); addArcToShapeGeometry(toVector3d(startPoint), - angleReversed ? endAngle : startAngle + M_PI, - angleReversed ? endAngle + M_PI : startAngle + 2 * M_PI, + angleReversed ? endAngle : startAngle + pi, + angleReversed ? endAngle + pi : startAngle + 2 * pi, r, isConstructionMode()); addArcToShapeGeometry(toVector3d(endPoint), - angleReversed ? startAngle + M_PI : endAngle, - angleReversed ? startAngle + 2 * M_PI : M_PI + endAngle, + angleReversed ? startAngle + pi : endAngle, + angleReversed ? startAngle + 2 * pi : pi + endAngle, r, isConstructionMode()); @@ -635,7 +637,7 @@ void DSHArcSlotControllerBase::doEnforceControlParameters(Base::Vector2d& onSket if (onViewParameters[OnViewParameter::Fifth]->isSet) { double arcAngle = Base::toRadians(onViewParameters[OnViewParameter::Fifth]->getValue()); - if (fmod(fabs(arcAngle), 2 * M_PI) < Precision::Confusion()) { + if (fmod(fabs(arcAngle), 2 * std::numbers::pi) < Precision::Confusion()) { unsetOnViewParameter(onViewParameters[OnViewParameter::Fifth].get()); } else { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h index f6561f017d..587db8d527 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h @@ -110,6 +110,9 @@ public: void mouseMove(Base::Vector2d onSketchPos) override { Q_UNUSED(onSketchPos); + + using std::numbers::pi; + if (Mode == STATUS_SEEK_Second) { const Part::Geometry* geom = sketchgui->getSketchObject()->getGeometry(BaseGeoId); if (geom->is()) { @@ -142,7 +145,7 @@ public: */ bool inCurve = (projection.Length() < recenteredLine.Length() && projection.GetAngle(recenteredLine) - < 0.1); // Two possible values here, M_PI and 0, but 0.1 is to + < 0.1); // Two possible values here, pi and 0, but 0.1 is to // avoid floating point problems. if (inCurve) { Increment = SavedExtendFromStart @@ -185,8 +188,8 @@ public: bool isCCWFromStart = crossProduct(angle, startAngle) < 0; if (outOfArc) { if (isCCWFromStart) { - modStartAngle -= 2 * M_PI - angleToStartAngle; - modArcAngle += 2 * M_PI - angleToStartAngle; + modStartAngle -= 2 * pi - angleToStartAngle; + modArcAngle += 2 * pi - angleToStartAngle; } else { modStartAngle -= angleToStartAngle; @@ -199,8 +202,8 @@ public: modArcAngle -= angleToStartAngle; } else { - modStartAngle += 2 * M_PI - angleToStartAngle; - modArcAngle -= 2 * M_PI - angleToStartAngle; + modStartAngle += 2 * pi - angleToStartAngle; + modArcAngle -= 2 * pi - angleToStartAngle; } } } @@ -208,7 +211,7 @@ public: bool isCWFromEnd = crossProduct(angle, endAngle) >= 0; if (outOfArc) { if (isCWFromEnd) { - modArcAngle += 2 * M_PI - angleToEndAngle; + modArcAngle += 2 * pi - angleToEndAngle; } else { modArcAngle += angleToEndAngle; @@ -219,7 +222,7 @@ public: modArcAngle -= angleToEndAngle; } else { - modArcAngle -= 2 * M_PI - angleToEndAngle; + modArcAngle -= 2 * pi - angleToEndAngle; } } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerLine.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerLine.h index efbe278b5e..50f7ea7377 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerLine.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerLine.h @@ -646,16 +646,17 @@ void DSHLineController::addConstraints() }; auto constraintp4angle = [&]() { + using std::numbers::pi; + double angle = Base::toRadians(p4); - if (fabs(angle - M_PI) < Precision::Confusion() - || fabs(angle + M_PI) < Precision::Confusion() + if (fabs(angle - pi) < Precision::Confusion() || fabs(angle + pi) < Precision::Confusion() || fabs(angle) < Precision::Confusion()) { Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Horizontal',%d)) ", firstCurve); } - else if (fabs(angle - M_PI / 2) < Precision::Confusion() - || fabs(angle + M_PI / 2) < Precision::Confusion()) { + else if (fabs(angle - pi / 2) < Precision::Confusion() + || fabs(angle + pi / 2) < Precision::Confusion()) { Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Vertical',%d)) ", firstCurve); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h index 798f9f674b..37b0f6834e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h @@ -188,6 +188,8 @@ public: void mouseMove(Base::Vector2d onSketchPos) override { + using std::numbers::pi; + suppressTransition = false; if (Mode == STATUS_SEEK_First) { setPositionText(onSketchPos); @@ -222,7 +224,7 @@ public: if (showCursorCoords()) { SbString text; std::string lengthString = lengthToDisplayFormat(length, 1); - std::string angleString = angleToDisplayFormat(angle * 180.0 / M_PI, 1); + std::string angleString = angleToDisplayFormat(angle * 180.0 / pi, 1); text.sprintf(" (%s, %s)", lengthString.c_str(), angleString.c_str()); setPositionText(EditCurve[1], text); } @@ -289,14 +291,14 @@ public: arcAngle = 0.f; } if (arcRadius >= 0 && arcAngle > 0) { - arcAngle -= 2 * M_PI; + arcAngle -= 2 * pi; } if (arcRadius < 0 && arcAngle < 0) { - arcAngle += 2 * M_PI; + arcAngle += 2 * pi; } if (SnapMode == SNAP_MODE_45Degree) { - arcAngle = round(arcAngle / (M_PI / 4)) * M_PI / 4; + arcAngle = round(arcAngle / (pi / 4)) * pi / 4; } endAngle = startAngle + arcAngle; @@ -316,7 +318,7 @@ public: if (showCursorCoords()) { SbString text; std::string radiusString = lengthToDisplayFormat(std::abs(arcRadius), 1); - std::string angleString = angleToDisplayFormat(arcAngle * 180.0 / M_PI, 1); + std::string angleString = angleToDisplayFormat(arcAngle * 180.0 / pi, 1); text.sprintf(" (R%s, %s)", radiusString.c_str(), angleString.c_str()); setPositionText(onSketchPos, text); } @@ -536,8 +538,8 @@ public: // #3974: if in radians, the printf %f defaults to six decimals, which leads to // loss of precision - double arcAngle = - abs(round((endAngle - startAngle) / (M_PI / 4)) * 45); // in degrees + double arcAngle = abs(round((endAngle - startAngle) / (std::numbers::pi / 4)) + * 45); // in degrees Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('Angle',%i,App.Units." diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h index 0bf9697039..509d347027 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h @@ -932,7 +932,7 @@ private: void findOffsetLength() { - double newOffsetLength = DBL_MAX; + double newOffsetLength = std::numeric_limits::max(); BRepBuilderAPI_MakeVertex mkVertex({endpoint.x, endpoint.y, 0.0}); TopoDS_Vertex vertex = mkVertex.Vertex(); @@ -960,7 +960,7 @@ private: } } - if (newOffsetLength != DBL_MAX) { + if (newOffsetLength != std::numeric_limits::max()) { offsetLength = newOffsetLength; } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h index 0a6a242da7..54ce11d364 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h @@ -242,7 +242,8 @@ private: return; } - double angleOfSeparation = 2.0 * M_PI / static_cast(numberOfCorners); // NOLINT + double angleOfSeparation = + 2.0 * std::numbers::pi / static_cast(numberOfCorners); // NOLINT double cos_v = cos(angleOfSeparation); double sin_v = sin(angleOfSeparation); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerRectangle.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerRectangle.h index 8070c64436..f3ba68f73f 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerRectangle.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerRectangle.h @@ -111,6 +111,8 @@ public: private: void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override { + using std::numbers::pi; + switch (state()) { case SelectMode::SeekFirst: { toolWidgetManager.drawPositionAtCursor(onSketchPos); @@ -144,8 +146,8 @@ private: corner2 = Base::Vector2d(corner1.x, onSketchPos.y); cornersReversed = true; } - angle123 = M_PI / 2; - angle412 = M_PI / 2; + angle123 = pi / 2; + angle412 = pi / 2; } else if (constructionMethod() == ConstructionMethod::CenterAndCorner) { toolWidgetManager.drawDirectionAtCursor(onSketchPos, center); @@ -162,8 +164,8 @@ private: corner2 = Base::Vector2d(corner1.x, onSketchPos.y); cornersReversed = true; } - angle123 = M_PI / 2; - angle412 = M_PI / 2; + angle123 = pi / 2; + angle412 = pi / 2; } else if (constructionMethod() == ConstructionMethod::ThreePoints) { toolWidgetManager.drawDirectionAtCursor(onSketchPos, corner1); @@ -174,8 +176,8 @@ private: perpendicular.y = (corner2 - corner1).x; corner3 = corner2 + perpendicular; corner4 = corner1 + perpendicular; - angle123 = M_PI / 2; - angle412 = M_PI / 2; + angle123 = pi / 2; + angle412 = pi / 2; corner2Initial = corner2; side = getPointSideOfVector(corner3, corner2 - corner1, corner1); } @@ -189,8 +191,8 @@ private: perpendicular.y = (onSketchPos - center).x; corner2 = center + perpendicular; corner4 = center - perpendicular; - angle123 = M_PI / 2; - angle412 = M_PI / 2; + angle123 = pi / 2; + angle412 = pi / 2; side = getPointSideOfVector(corner2, corner3 - corner1, corner1); } @@ -247,7 +249,7 @@ private: acos((a.x * b.x + a.y * b.y) / (sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y))); } - angle412 = M_PI - angle123; + angle412 = pi - angle123; if (roundCorners) { radius = std::min(length, width) / 6 // NOLINT * std::min(sqrt(1 - cos(angle412) * cos(angle412)), @@ -276,7 +278,7 @@ private: acos((a.x * b.x + a.y * b.y) / (sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y))); } - angle123 = M_PI - angle412; + angle123 = pi - angle412; if (roundCorners) { radius = std::min(length, width) / 6 // NOLINT * std::min(sqrt(1 - cos(angle412) * cos(angle412)), @@ -677,7 +679,7 @@ private: width = vecW.Length(); angle = vecL.Angle(); if (length < Precision::Confusion() || width < Precision::Confusion() - || fmod(fabs(angle123), M_PI) < Precision::Confusion()) { + || fmod(fabs(angle123), std::numbers::pi) < Precision::Confusion()) { return; } @@ -738,9 +740,11 @@ private: void createFirstRectangleFillets(Base::Vector2d vecL, Base::Vector2d vecW, double L1, double L2) { + using std::numbers::pi; + // center points required later for special case of round corner frame with // radiusFrame = 0. - double end = angle - M_PI / 2; + double end = angle - pi / 2; Base::Vector2d b1 = (vecL + vecW) / (vecL + vecW).Length(); Base::Vector2d b2 = (vecL - vecW) / (vecL - vecW).Length(); @@ -749,16 +753,18 @@ private: center3 = toVector3d(corner3 - b1 * L2); center4 = toVector3d(corner4 + b2 * L1); - addArcToShapeGeometry(center1, end - M_PI + angle412, end, radius, isConstructionMode()); - addArcToShapeGeometry(center2, end, end - M_PI - angle123, radius, isConstructionMode()); - addArcToShapeGeometry(center3, end + angle412, end - M_PI, radius, isConstructionMode()); - addArcToShapeGeometry(center4, end - M_PI, end - angle123, radius, isConstructionMode()); + addArcToShapeGeometry(center1, end - pi + angle412, end, radius, isConstructionMode()); + addArcToShapeGeometry(center2, end, end - pi - angle123, radius, isConstructionMode()); + addArcToShapeGeometry(center3, end + angle412, end - pi, radius, isConstructionMode()); + addArcToShapeGeometry(center4, end - pi, end - angle123, radius, isConstructionMode()); } void createSecondRectangleGeometries(Base::Vector2d vecL, Base::Vector2d vecW, double L1, double L2) { - double end = angle - M_PI / 2; + using std::numbers::pi; + + double end = angle - pi / 2; if (radius < Precision::Confusion()) { radiusFrame = 0.; @@ -800,22 +806,22 @@ private: Base::Vector2d b2 = (vecL - vecW) / (vecL - vecW).Length(); addArcToShapeGeometry(toVector3d(frameCorner1 + b1 * L2F), - end - M_PI + angle412, + end - pi + angle412, end, radiusFrame, isConstructionMode()); addArcToShapeGeometry(toVector3d(frameCorner2 - b2 * L1F), end, - end - M_PI - angle123, + end - pi - angle123, radiusFrame, isConstructionMode()); addArcToShapeGeometry(toVector3d(frameCorner3 - b1 * L2F), end + angle412, - end - M_PI, + end - pi, radiusFrame, isConstructionMode()); addArcToShapeGeometry(toVector3d(frameCorner4 + b2 * L1F), - end - M_PI, + end - pi, end - angle123, radiusFrame, isConstructionMode()); @@ -1313,7 +1319,7 @@ private: firstCurve + 1, Sketcher::PointPos::none, firstCurve + 3); - if (fabs(angle123 - M_PI / 2) < Precision::Confusion()) { + if (fabs(angle123 - std::numbers::pi / 2) < Precision::Confusion()) { addToShapeConstraints(Sketcher::Perpendicular, firstCurve, Sketcher::PointPos::none, @@ -1932,7 +1938,7 @@ void DSHRectangleControllerBase::doEnforceControlParameters(Base::Vector2d& onSk if (onViewParameters[OnViewParameter::Sixth]->isSet) { double angle = Base::toRadians(onViewParameters[OnViewParameter::Sixth]->getValue()); - if (fmod(angle, M_PI) < Precision::Confusion()) { + if (fmod(angle, std::numbers::pi) < Precision::Confusion()) { unsetOnViewParameter(onViewParameters[OnViewParameter::Sixth].get()); return; } @@ -1944,8 +1950,8 @@ void DSHRectangleControllerBase::doEnforceControlParameters(Base::Vector2d& onSk int sign = handler->side != sign1 ? 1 : -1; - double angle123 = - (handler->corner2Initial - handler->corner1).Angle() + M_PI + sign * angle; + double angle123 = (handler->corner2Initial - handler->corner1).Angle() + + std::numbers::pi + sign * angle; onSketchPos.x = handler->corner2Initial.x + cos(angle123) * width; onSketchPos.y = handler->corner2Initial.y + sin(angle123) * width; @@ -1969,12 +1975,12 @@ void DSHRectangleControllerBase::doEnforceControlParameters(Base::Vector2d& onSk if (onViewParameters[OnViewParameter::Sixth]->isSet) { double c = Base::toRadians(onViewParameters[OnViewParameter::Sixth]->getValue()); - if (fmod(c, M_PI) < Precision::Confusion()) { + if (fmod(c, std::numbers::pi) < Precision::Confusion()) { unsetOnViewParameter(onViewParameters[OnViewParameter::Sixth].get()); return; } - double a = asin(width * sin(M_PI - c) + double a = asin(width * sin(std::numbers::pi - c) / (handler->corner3 - handler->corner1).Length()); int sign1 = handler->getPointSideOfVector(onSketchPos, @@ -2399,6 +2405,8 @@ void DSHRectangleController::doChangeDrawSketchHandlerMode() template<> void DSHRectangleController::addConstraints() { + using std::numbers::pi; + App::DocumentObject* obj = handler->sketchgui->getObject(); int firstCurve = handler->firstCurve; @@ -2569,15 +2577,15 @@ void DSHRectangleController::addConstraints() if (handler->constructionMethod() == ConstructionMethod::ThreePoints) { if (angleSet) { - if (fabs(angle - M_PI) < Precision::Confusion() - || fabs(angle + M_PI) < Precision::Confusion() + if (fabs(angle - pi) < Precision::Confusion() + || fabs(angle + pi) < Precision::Confusion() || fabs(angle) < Precision::Confusion()) { Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Horizontal',%d)) ", firstCurve); } - else if (fabs(angle - M_PI / 2) < Precision::Confusion() - || fabs(angle + M_PI / 2) < Precision::Confusion()) { + else if (fabs(angle - pi / 2) < Precision::Confusion() + || fabs(angle + pi / 2) < Precision::Confusion()) { Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Vertical',%d)) ", firstCurve); @@ -2591,7 +2599,7 @@ void DSHRectangleController::addConstraints() } } if (innerAngleSet) { - if (fabs(innerAngle - M_PI / 2) > Precision::Confusion()) { + if (fabs(innerAngle - pi / 2) > Precision::Confusion()) { // if 90? then perpendicular already created. Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Angle',%d,%d,%d,%d,%f)) ", @@ -2617,7 +2625,7 @@ void DSHRectangleController::addConstraints() obj); } if (innerAngleSet) { - if (fabs(innerAngle - M_PI / 2) > Precision::Confusion()) { + if (fabs(innerAngle - pi / 2) > Precision::Confusion()) { // if 90? then perpendicular already created. Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Angle',%d,%d,%d,%d,%f)) ", diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h index 32266e9d38..03be54ee61 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h @@ -103,7 +103,7 @@ private: endpoint = centerPoint + length * Base::Vector2d(cos(endAngle), sin(endAngle)); double angle1 = endAngle - startAngle; - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi; totalAngle = abs(angle1 - totalAngle) < abs(angle2 - totalAngle) ? angle1 : angle2; CreateAndDrawShapeGeometry(); @@ -408,10 +408,11 @@ private: // the new geometry. /*if (cstr->Type == DistanceX || cstr->Type == DistanceY) { //DistanceX/Y can be applied only if the rotation if 90 or 180. - if (fabs(fmod(individualAngle, M_PI)) < Precision::Confusion()) { + if (fabs(fmod(individualAngle, std::numbers::pi)) < + Precision::Confusion()) { // ok and nothing to do actually } - else if (fabs(fmod(individualAngle, M_PI * 0.5)) < + else if (fabs(fmod(individualAngle, std::numbers::pi * 0.5)) < Precision::Confusion()) { cstr->Type = cstr->Type == DistanceX ? DistanceY : DistanceX; } @@ -567,7 +568,7 @@ void DSHRotateControllerBase::doEnforceControlParameters(Base::Vector2d& onSketc double arcAngle = Base::toRadians(onViewParameters[OnViewParameter::Third]->getValue()); - if (fmod(fabs(arcAngle), 2 * M_PI) < Precision::Confusion()) { + if (fmod(fabs(arcAngle), 2 * std::numbers::pi) < Precision::Confusion()) { unsetOnViewParameter(onViewParameters[OnViewParameter::Third].get()); return; } @@ -580,7 +581,7 @@ void DSHRotateControllerBase::doEnforceControlParameters(Base::Vector2d& onSketc double arcAngle = Base::toRadians(onViewParameters[OnViewParameter::Fourth]->getValue()); - if (fmod(fabs(arcAngle), 2 * M_PI) < Precision::Confusion()) { + if (fmod(fabs(arcAngle), 2 * std::numbers::pi) < Precision::Confusion()) { unsetOnViewParameter(onViewParameters[OnViewParameter::Fourth].get()); return; } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerSlot.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerSlot.h index 1108aa244e..46b27d58b3 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerSlot.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerSlot.h @@ -241,6 +241,8 @@ private: void createShape(bool onlyeditoutline) override { + using std::numbers::pi; + ShapeGeometry.clear(); if (length < Precision::Confusion() || radius < Precision::Confusion()) { @@ -248,14 +250,14 @@ private: } Part::GeomArcOfCircle* arc1 = addArcToShapeGeometry(toVector3d(startPoint), - M_PI / 2 + angle, - 1.5 * M_PI + angle, + pi / 2 + angle, + 1.5 * pi + angle, radius, isConstructionMode()); Part::GeomArcOfCircle* arc2 = addArcToShapeGeometry(toVector3d(secondPoint), - 1.5 * M_PI + angle, - M_PI / 2 + angle, + 1.5 * pi + angle, + pi / 2 + angle, radius, isConstructionMode()); @@ -323,13 +325,15 @@ private: void checkHorizontalVertical() { + using std::numbers::pi; + isHorizontal = false; isVertical = false; - if (fmod(fabs(angle), M_PI) < Precision::Confusion()) { + if (fmod(fabs(angle), pi) < Precision::Confusion()) { isHorizontal = true; } - else if (fmod(fabs(angle + M_PI / 2), M_PI) < Precision::Confusion()) { + else if (fmod(fabs(angle + pi / 2), pi) < Precision::Confusion()) { isVertical = true; } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h index bac2d51208..f1412f8d7c 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h @@ -584,7 +584,8 @@ void DSHTranslateControllerBase::doEnforceControlParameters(Base::Vector2d& onSk } if (onViewParameters[OnViewParameter::Fourth]->isSet) { - double angle = onViewParameters[OnViewParameter::Fourth]->getValue() * M_PI / 180; + double angle = + onViewParameters[OnViewParameter::Fourth]->getValue() * std::numbers::pi / 180; onSketchPos.x = handler->referencePoint.x + cos(angle) * length; onSketchPos.y = handler->referencePoint.y + sin(angle) * length; } @@ -607,7 +608,8 @@ void DSHTranslateControllerBase::doEnforceControlParameters(Base::Vector2d& onSk } if (onViewParameters[OnViewParameter::Sixth]->isSet) { - double angle = onViewParameters[OnViewParameter::Sixth]->getValue() * M_PI / 180; + double angle = + onViewParameters[OnViewParameter::Sixth]->getValue() * std::numbers::pi / 180; onSketchPos.x = handler->referencePoint.x + cos(angle) * length; onSketchPos.y = handler->referencePoint.y + sin(angle) * length; } @@ -647,7 +649,7 @@ void DSHTranslateController::adaptParameters(Base::Vector2d onSketchPos) Base::Vector2d vec2d = Base::Vector2d(handler->firstTranslationVector.x, handler->firstTranslationVector.y); double angle = vec2d.Angle(); - double range = angle * 180 / M_PI; + double range = angle * 180 / std::numbers::pi; if (!onViewParameters[OnViewParameter::Fourth]->isSet) { setOnViewParameterValue(OnViewParameter::Fourth, range, Base::Unit::Angle); @@ -669,7 +671,7 @@ void DSHTranslateController::adaptParameters(Base::Vector2d onSketchPos) Base::Vector2d vec2d = Base::Vector2d(handler->secondTranslationVector.x, handler->secondTranslationVector.y); double angle = vec2d.Angle(); - double range = angle * 180 / M_PI; + double range = angle * 180 / std::numbers::pi; if (!onViewParameters[OnViewParameter::Sixth]->isSet) { setOnViewParameterValue(OnViewParameter::Sixth, range, Base::Unit::Angle); diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index e368a8d7de..f69d71d71e 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -114,6 +114,8 @@ void EditModeConstraintCoinManager::updateVirtualSpace() void EditModeConstraintCoinManager::processConstraints(const GeoListFacade& geolistfacade) { + using std::numbers::pi; + const auto& constrlist = ViewProviderSketchCoinAttorney::getConstraints(viewProvider); auto zConstrH = ViewProviderSketchCoinAttorney::getViewOrientationFactor(viewProvider) @@ -262,7 +264,7 @@ Restart: const Part::GeomCircle* circle = static_cast(geo); ra = circle->getRadius(); - angle = M_PI / 4; + angle = pi / 4; midpos = circle->getCenter(); } else if (geo->is()) { @@ -281,7 +283,7 @@ Restart: rb = ellipse->getMinorRadius(); Base::Vector3d majdir = ellipse->getMajorAxisDir(); angle = atan2(majdir.y, majdir.x); - angleplus = M_PI / 4; + angleplus = pi / 4; midpos = ellipse->getCenter(); } else if (geo->is()) { @@ -460,7 +462,7 @@ Restart: norm1.Normalize(); dir1 = norm1; - dir1.RotateZ(-M_PI / 2.0); + dir1.RotateZ(-pi / 2.0); } else if (Constr->FirstPos == Sketcher::PointPos::none) { @@ -485,7 +487,7 @@ Restart: else if (geo1->is()) { const Part::GeomCircle* circle = static_cast(geo1); - norm1 = Base::Vector3d(cos(M_PI / 4), sin(M_PI / 4), 0); + norm1 = Base::Vector3d(cos(pi / 4), sin(pi / 4), 0); dir1 = Base::Vector3d(-norm1.y, norm1.x, 0); midpos1 = circle->getCenter() + circle->getRadius() * norm1; } @@ -514,7 +516,7 @@ Restart: else if (geo2->is()) { const Part::GeomCircle* circle = static_cast(geo2); - norm2 = Base::Vector3d(cos(M_PI / 4), sin(M_PI / 4), 0); + norm2 = Base::Vector3d(cos(pi / 4), sin(pi / 4), 0); dir2 = Base::Vector3d(-norm2.y, norm2.x, 0); midpos2 = circle->getCenter() + circle->getRadius() * norm2; } @@ -576,7 +578,7 @@ Restart: const Part::GeomCircle* circle = static_cast(geo1); r1a = circle->getRadius(); - angle1 = M_PI / 4; + angle1 = pi / 4; midpos1 = circle->getCenter(); } else if (geo1->is()) { @@ -595,7 +597,7 @@ Restart: r1b = ellipse->getMinorRadius(); Base::Vector3d majdir = ellipse->getMajorAxisDir(); angle1 = atan2(majdir.y, majdir.x); - angle1plus = M_PI / 4; + angle1plus = pi / 4; midpos1 = ellipse->getCenter(); } else if (geo1->is()) { @@ -641,7 +643,7 @@ Restart: const Part::GeomCircle* circle = static_cast(geo2); r2a = circle->getRadius(); - angle2 = M_PI / 4; + angle2 = pi / 4; midpos2 = circle->getCenter(); } else if (geo2->is()) { @@ -660,7 +662,7 @@ Restart: r2b = ellipse->getMinorRadius(); Base::Vector3d majdir = ellipse->getMajorAxisDir(); angle2 = atan2(majdir.y, majdir.x); - angle2plus = M_PI / 4; + angle2plus = pi / 4; midpos2 = ellipse->getCenter(); } else if (geo2->is()) { @@ -968,7 +970,7 @@ Restart: // otherwise We still use findHelperAngles before to find if helper // is needed. helperStartAngle1 = endAngle; - helperRange1 = 2 * M_PI - (endAngle - startAngle); + helperRange1 = 2 * pi - (endAngle - startAngle); numPoints++; } @@ -991,7 +993,7 @@ Restart: if (helperRange2 != 0.) { helperStartAngle2 = endAngle; - helperRange2 = 2 * M_PI - (endAngle - startAngle); + helperRange2 = 2 * pi - (endAngle - startAngle); numPoints++; } @@ -1089,7 +1091,7 @@ Restart: // getSolvedSketch().calculateNormalAtPoint(Constr->Second, pos.x, pos.y); norm.Normalize(); Base::Vector3d dir = norm; - dir.RotateZ(-M_PI / 2.0); + dir.RotateZ(-pi / 2.0); relPos = seekConstraintPosition( pos, @@ -1340,7 +1342,7 @@ Restart: p1[1] = line1->getEndPoint(); p2[0] = line2->getStartPoint(); p2[1] = line2->getEndPoint(); - double length = DBL_MAX; + double length = std::numeric_limits::max(); for (int i = 0; i <= 1; i++) { for (int j = 0; j <= 1; j++) { double tmp = (p2[j] - p1[i]).Length(); @@ -1385,12 +1387,12 @@ Restart: // TODO: Check // dir1 = getSolvedSketch().calculateNormalAtPoint(Constr->First, // p.x, p.y); - dir1.RotateZ(-M_PI / 2); // convert to vector of tangency by rotating + dir1.RotateZ(-pi / 2); // convert to vector of tangency by rotating dir2 = getNormal(geolistfacade, Constr->Second, p); // TODO: Check // dir2 = getSolvedSketch().calculateNormalAtPoint(Constr->Second, // p.x, p.y); - dir2.RotateZ(-M_PI / 2); + dir2.RotateZ(-pi / 2); startangle = atan2(dir1.y, dir1.x); range = atan2(dir1.x * dir2.y - dir1.y * dir2.x, @@ -1632,26 +1634,28 @@ void EditModeConstraintCoinManager::findHelperAngles(double& helperStartAngle, double startAngle, double endAngle) { + using std::numbers::pi; + double margin = 0.2; // about 10deg if (angle < 0) { - angle = angle + 2 * M_PI; + angle = angle + 2 * pi; } // endAngle can be more than 2*pi as its startAngle + arcAngle - if (endAngle > 2 * M_PI && angle < endAngle - 2 * M_PI) { - angle = angle + 2 * M_PI; + if (endAngle > 2 * pi && angle < endAngle - 2 * pi) { + angle = angle + 2 * pi; } if (!(angle > startAngle && angle < endAngle)) { - if ((angle < startAngle && startAngle - angle < angle + 2 * M_PI - endAngle) - || (angle > endAngle && startAngle + 2 * M_PI - angle < angle - endAngle)) { + if ((angle < startAngle && startAngle - angle < angle + 2 * pi - endAngle) + || (angle > endAngle && startAngle + 2 * pi - angle < angle - endAngle)) { if (angle > startAngle) { - angle -= 2 * M_PI; + angle -= 2 * pi; } helperStartAngle = angle - margin; helperRange = startAngle - angle + margin; } else { if (angle < endAngle) { - angle += 2 * M_PI; + angle += 2 * pi; } helperStartAngle = endAngle; helperRange = angle - endAngle + margin; diff --git a/src/Mod/Sketcher/Gui/PreCompiled.h b/src/Mod/Sketcher/Gui/PreCompiled.h index 8d2c1892ce..d4a2ac5e7c 100644 --- a/src/Mod/Sketcher/Gui/PreCompiled.h +++ b/src/Mod/Sketcher/Gui/PreCompiled.h @@ -32,7 +32,6 @@ #ifdef _PreComp_ // standard -#include #include #include diff --git a/src/Mod/Sketcher/Gui/SnapManager.cpp b/src/Mod/Sketcher/Gui/SnapManager.cpp index 399688add4..fd34a6df0e 100644 --- a/src/Mod/Sketcher/Gui/SnapManager.cpp +++ b/src/Mod/Sketcher/Gui/SnapManager.cpp @@ -122,7 +122,8 @@ void SnapManager::ParameterObserver::updateSnapAngleParameter(const std::string& { ParameterGrp::handle hGrp = getParameterGrpHandle(); - client.snapAngle = fmod(hGrp->GetFloat(parametername.c_str(), 5.) * M_PI / 180, 2 * M_PI); + client.snapAngle = fmod(hGrp->GetFloat(parametername.c_str(), 5.) * std::numbers::pi / 180, + 2 * std::numbers::pi); } void SnapManager::ParameterObserver::subscribeToParameters() @@ -222,7 +223,7 @@ bool SnapManager::snapAtAngle(double& x, double& y) double length = (pointToOverride - referencePoint).Length(); double angle1 = (pointToOverride - referencePoint).Angle(); - double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI; + double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi; lastMouseAngle = abs(angle1 - lastMouseAngle) < abs(angle2 - lastMouseAngle) ? angle1 : angle2; double angle = round(lastMouseAngle / snapAngle) * snapAngle; @@ -368,10 +369,10 @@ bool SnapManager::snapToArcMiddle(Base::Vector3d& pointToOverride, const Part::G double u, v; arc->getRange(u, v, true); if (v < u) { - v += 2 * M_PI; + v += 2 * std::numbers::pi; } double angle = v - u; - int revert = angle < M_PI ? 1 : -1; + int revert = angle < std::numbers::pi ? 1 : -1; /*To know if we are close to the middle of the arc, we are going to compare the angle of the * (mouse cursor - center) to the angle of the middle of the arc. If it's less than 10% of the diff --git a/src/Mod/Sketcher/Gui/SoZoomTranslation.cpp b/src/Mod/Sketcher/Gui/SoZoomTranslation.cpp index c1981f7a68..e42a545aff 100644 --- a/src/Mod/Sketcher/Gui/SoZoomTranslation.cpp +++ b/src/Mod/Sketcher/Gui/SoZoomTranslation.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp index 5a6a4237e7..397d501703 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp @@ -720,8 +720,9 @@ ConstraintFilterList::ConstraintFilterList(QWidget* parent) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Sketcher/General"); - int filterState = hGrp->GetInt("ConstraintFilterState", - INT_MAX);// INT_MAX = 1111111111111111111111111111111 in binary. + int filterState = hGrp->GetInt( + "ConstraintFilterState", + std::numeric_limits::max()); // INT_MAX = 01111111111111111111111111111111 in binary. normalFilterCount = filterItems.size() - 2;// All filter but selected and associated selectedFilterIndex = normalFilterCount; diff --git a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp index e5df986f5d..551b9fa90f 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp @@ -1124,8 +1124,9 @@ ElementFilterList::ElementFilterList(QWidget* parent) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Sketcher/General"); - int filterState = hGrp->GetInt("ElementFilterState", - INT_MAX);// INT_MAX = 1111111111111111111111111111111 in binary. + int filterState = hGrp->GetInt( + "ElementFilterState", + std::numeric_limits::max());// INT_MAX = 01111111111111111111111111111111 in binary. for (auto const& filterItem : filterItems) { Q_UNUSED(filterItem); @@ -1320,7 +1321,7 @@ void TaskSketcherElements::onListMultiFilterItemChanged(QListWidgetItem* item) } // Save the state of the filter. - int filterState = INT_MIN;// INT_MIN = 000000000000000000000000000000 in binary. + int filterState = 0; // All bits are cleared. for (int i = filterList->count() - 1; i >= 0; i--) { bool isChecked = filterList->item(i)->checkState() == Qt::Checked; filterState = filterState << 1;// we shift left first, else the list is shifted at the end. diff --git a/src/Mod/Sketcher/Gui/TaskSketcherGeneral.ui.autosave b/src/Mod/Sketcher/Gui/TaskSketcherGeneral.ui.autosave new file mode 100644 index 0000000000..3b73e8be00 --- /dev/null +++ b/src/Mod/Sketcher/Gui/TaskSketcherGeneral.ui.autosave @@ -0,0 +1,77 @@ + + + TaskSketcherGeneral + + + + 0 + 0 + 253 + 61 + + + + + .AppleSystemUIFont + + + + Form + + + + + + + 0 + 0 + + + + Link + + + + + + + + 0 + 0 + + + + DOF + + + + + + + + 1 + 0 + + + + Auto Recompute + + + + + + + + Gui::StatefulLabel + QLabel +
Gui/Widgets.h
+
+ + Gui::UrlLabel + QLabel +
Gui/Widgets.h
+
+
+ + +
diff --git a/src/Mod/Sketcher/Gui/Utils.cpp b/src/Mod/Sketcher/Gui/Utils.cpp index 9a6f1ee223..6fc5562cf7 100644 --- a/src/Mod/Sketcher/Gui/Utils.cpp +++ b/src/Mod/Sketcher/Gui/Utils.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include @@ -432,7 +431,7 @@ double SketcherGui::GetPointAngle(const Base::Vector2d& p1, const Base::Vector2d { double dX = p2.x - p1.x; double dY = p2.y - p1.y; - return dY >= 0 ? atan2(dY, dX) : atan2(dY, dX) + 2 * M_PI; + return dY >= 0 ? atan2(dY, dX) : atan2(dY, dX) + 2 * std::numbers::pi; } // Set the two points on circles at minimal distance diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 1bde48de8d..3c27a517df 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -861,7 +861,7 @@ void ViewProviderSketch::getCoordsOnSketchPlane(const SbVec3f& point, const SbVe // line Base::Vector3d R1(point[0], point[1], point[2]), RA(normal[0], normal[1], normal[2]); - if (fabs(RN * RA) < FLT_EPSILON) + if (fabs(RN * RA) < std::numeric_limits::epsilon()) throw Base::ZeroDivisionError("View direction is parallel to sketch plane"); // intersection point on plane Base::Vector3d S = R1 + ((RN * (R0 - R1)) / (RN * RA)) * RA; @@ -1930,9 +1930,9 @@ void ViewProviderSketch::moveConstraint(Sketcher::Constraint* Constr, int constN || Constr->Type == Weight) dir = (p2 - p1).Normalize(); else if (Constr->Type == DistanceX) - dir = Base::Vector3d((p2.x - p1.x >= FLT_EPSILON) ? 1 : -1, 0, 0); + dir = Base::Vector3d((p2.x - p1.x >= std::numeric_limits::epsilon()) ? 1 : -1, 0, 0); else if (Constr->Type == DistanceY) - dir = Base::Vector3d(0, (p2.y - p1.y >= FLT_EPSILON) ? 1 : -1, 0); + dir = Base::Vector3d(0, (p2.y - p1.y >= std::numeric_limits::epsilon()) ? 1 : -1, 0); if (Constr->Type == Radius || Constr->Type == Diameter || Constr->Type == Weight) { Constr->LabelDistance = vec.x * dir.x + vec.y * dir.y; @@ -2029,9 +2029,9 @@ void ViewProviderSketch::moveAngleConstraint(Sketcher::Constraint* constr, int c Base::Vector3d p = getSolvedSketch().getPoint(constr->Third, constr->ThirdPos); p0 = Base::Vector3d(p.x, p.y, 0); Base::Vector3d dir1 = getSolvedSketch().calculateNormalAtPoint(constr->First, p.x, p.y); - dir1.RotateZ(-M_PI / 2);// convert to vector of tangency by rotating + dir1.RotateZ(-std::numbers::pi / 2);// convert to vector of tangency by rotating Base::Vector3d dir2 = getSolvedSketch().calculateNormalAtPoint(constr->Second, p.x, p.y); - dir2.RotateZ(-M_PI / 2); + dir2.RotateZ(-std::numbers::pi / 2); Base::Vector3d vec = Base::Vector3d(toPos.x, toPos.y, 0) - p0; factor = factor * Base::sgn((dir1 + dir2) * vec); @@ -3996,7 +3996,7 @@ double ViewProviderSketch::getRotation(SbVec3f pos0, SbVec3f pos1) const getCoordsOnSketchPlane(pos0, vol.getProjectionDirection(), x0, y0); getCoordsOnSketchPlane(pos1, vol.getProjectionDirection(), x1, y1); - return -atan2((y1 - y0), (x1 - x0)) * 180 / M_PI; + return -atan2((y1 - y0), (x1 - x0)) * 180 / std::numbers::pi; } catch (const Base::ZeroDivisionError&) { return 0; diff --git a/tests/src/Mod/Sketcher/App/SketchObject.cpp b/tests/src/Mod/Sketcher/App/SketchObject.cpp index 954308353c..36c1db0f26 100644 --- a/tests/src/Mod/Sketcher/App/SketchObject.cpp +++ b/tests/src/Mod/Sketcher/App/SketchObject.cpp @@ -237,7 +237,7 @@ TEST_F(SketchObjectTest, testGetPointFromGeomArcOfCircle) { // Arrange Base::Vector3d coordsCenter(1.0, 2.0, 0.0); - double radius = 3.0, startParam = M_PI / 3, endParam = M_PI * 1.5; + double radius = 3.0, startParam = std::numbers::pi / 3, endParam = std::numbers::pi * 1.5; Part::GeomArcOfCircle arcOfCircle; arcOfCircle.setCenter(coordsCenter); arcOfCircle.setRadius(radius); @@ -267,7 +267,7 @@ TEST_F(SketchObjectTest, testGetPointFromGeomArcOfEllipse) Base::Vector3d coordsCenter(1.0, 2.0, 0.0); double majorRadius = 4.0; double minorRadius = 3.0; - double startParam = M_PI / 3, endParam = M_PI * 1.5; + double startParam = std::numbers::pi / 3, endParam = std::numbers::pi * 1.5; Part::GeomArcOfEllipse arcOfEllipse; arcOfEllipse.setCenter(coordsCenter); arcOfEllipse.setMajorRadius(majorRadius); @@ -298,7 +298,7 @@ TEST_F(SketchObjectTest, testGetPointFromGeomArcOfHyperbola) Base::Vector3d coordsCenter(1.0, 2.0, 0.0); double majorRadius = 4.0; double minorRadius = 3.0; - double startParam = M_PI / 3, endParam = M_PI * 1.5; + double startParam = std::numbers::pi / 3, endParam = std::numbers::pi * 1.5; Part::GeomArcOfHyperbola arcOfHyperbola; arcOfHyperbola.setCenter(coordsCenter); arcOfHyperbola.setMajorRadius(majorRadius); @@ -330,7 +330,7 @@ TEST_F(SketchObjectTest, testGetPointFromGeomArcOfParabola) // Arrange Base::Vector3d coordsCenter(1.0, 2.0, 0.0); double focal = 3.0; - double startParam = M_PI / 3, endParam = M_PI * 1.5; + double startParam = std::numbers::pi / 3, endParam = std::numbers::pi * 1.5; Part::GeomArcOfParabola arcOfParabola; arcOfParabola.setCenter(coordsCenter); arcOfParabola.setFocal(focal); diff --git a/tests/src/Mod/Sketcher/App/SketchObjectChanges.cpp b/tests/src/Mod/Sketcher/App/SketchObjectChanges.cpp index 2b0f69aa76..5d2519bea6 100644 --- a/tests/src/Mod/Sketcher/App/SketchObjectChanges.cpp +++ b/tests/src/Mod/Sketcher/App/SketchObjectChanges.cpp @@ -846,7 +846,7 @@ TEST_F(SketchObjectTest, testJoinCurves) // Arrange // Make two curves Base::Vector3d coordsCenter(0.0, 0.0, 0.0); - double radius = 3.0, startParam = M_PI / 2, endParam = M_PI; + double radius = 3.0, startParam = std::numbers::pi / 2, endParam = std::numbers::pi; Part::GeomArcOfCircle arcOfCircle; arcOfCircle.setCenter(coordsCenter); arcOfCircle.setRadius(radius); @@ -877,7 +877,7 @@ TEST_F(SketchObjectTest, testJoinCurvesWhenTangent) // Arrange // Make two curves Base::Vector3d coordsCenter(0.0, 0.0, 0.0); - double radius = 3.0, startParam = M_PI / 2, endParam = M_PI; + double radius = 3.0, startParam = std::numbers::pi / 2, endParam = std::numbers::pi; Part::GeomArcOfCircle arcOfCircle; arcOfCircle.setCenter(coordsCenter); arcOfCircle.setRadius(radius); diff --git a/tests/src/Mod/Sketcher/App/SketcherTestHelpers.cpp b/tests/src/Mod/Sketcher/App/SketcherTestHelpers.cpp index ae4fb2414e..51aade677f 100644 --- a/tests/src/Mod/Sketcher/App/SketcherTestHelpers.cpp +++ b/tests/src/Mod/Sketcher/App/SketcherTestHelpers.cpp @@ -56,7 +56,7 @@ void setupArcOfCircle(Part::GeomArcOfCircle& arcOfCircle) { Base::Vector3d coordsCenter(1.0, 2.0, 0.0); double radius = 3.0; - double startParam = M_PI / 3, endParam = M_PI * 1.5; + double startParam = std::numbers::pi / 3, endParam = std::numbers::pi * 1.5; arcOfCircle.setCenter(coordsCenter); arcOfCircle.setRadius(radius); arcOfCircle.setRange(startParam, endParam, true); @@ -77,7 +77,7 @@ void setupArcOfHyperbola(Part::GeomArcOfHyperbola& arcOfHyperbola) Base::Vector3d coordsCenter(1.0, 2.0, 0.0); double majorRadius = 4.0; double minorRadius = 3.0; - double startParam = M_PI / 3, endParam = M_PI * 1.5; + double startParam = std::numbers::pi / 3, endParam = std::numbers::pi * 1.5; arcOfHyperbola.setCenter(coordsCenter); arcOfHyperbola.setMajorRadius(majorRadius); arcOfHyperbola.setMinorRadius(minorRadius); @@ -88,7 +88,7 @@ void setupArcOfParabola(Part::GeomArcOfParabola& aop) { Base::Vector3d coordsCenter(1.0, 2.0, 0.0); double focal = 3.0; - double startParam = -M_PI * 1.5, endParam = M_PI * 1.5; + double startParam = -std::numbers::pi * 1.5, endParam = std::numbers::pi * 1.5; aop.setCenter(coordsCenter); aop.setFocal(focal); aop.setRange(startParam, endParam, true); diff --git a/tests/src/Mod/Sketcher/App/planegcs/Constraints.cpp b/tests/src/Mod/Sketcher/App/planegcs/Constraints.cpp index 4f0b90b997..89cb81dc12 100644 --- a/tests/src/Mod/Sketcher/App/planegcs/Constraints.cpp +++ b/tests/src/Mod/Sketcher/App/planegcs/Constraints.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #include +#include #include @@ -54,8 +55,8 @@ TEST_F(ConstraintsTest, tangentBSplineAndArc) // NOLINT arcEnd.y = &arcEndY; arcCenter.x = &arcCenterX; arcCenter.y = &arcCenterY; - double arcRadius = 5.0, arcStartAngle = 0.0, arcEndAngle = M_PI / 2; - double desiredAngle = M_PI; + double arcRadius = 5.0, arcStartAngle = 0.0, arcEndAngle = std::numbers::pi / 2; + double desiredAngle = std::numbers::pi; double bSplineStartX = 0.0, bSplineEndX = 16.0; double bSplineStartY = 10.0, bSplineEndY = -10.0; GCS::Point bSplineStart, bSplineEnd; From dc19a631a527de6892d2d6f6866094e93f3c7f46 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:02:32 +0100 Subject: [PATCH 055/316] Spreadsheet: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Spreadsheet/Gui/SheetTableView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp index f8a35e3287..10013b96b5 100644 --- a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp @@ -698,9 +698,9 @@ void SheetTableView::copySelection() void SheetTableView::_copySelection(const std::vector& ranges, bool copy) { - int minRow = INT_MAX; + int minRow = std::numeric_limits::max(); int maxRow = 0; - int minCol = INT_MAX; + int minCol = std::numeric_limits::max(); int maxCol = 0; for (auto& range : ranges) { minRow = std::min(minRow, range.from().row()); From f5244d404cf4a06509648f4957fe8aae5a96e948 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:02:39 +0100 Subject: [PATCH 056/316] Surface: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Surface/App/FeatureExtend.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Mod/Surface/App/FeatureExtend.cpp b/src/Mod/Surface/App/FeatureExtend.cpp index 83701ba824..518a300d18 100644 --- a/src/Mod/Surface/App/FeatureExtend.cpp +++ b/src/Mod/Surface/App/FeatureExtend.cpp @@ -42,7 +42,9 @@ using namespace Surface; -const App::PropertyIntegerConstraint::Constraints SampleRange = {2, INT_MAX, 1}; +const App::PropertyIntegerConstraint::Constraints SampleRange = {2, + std::numeric_limits::max(), + 1}; const App::PropertyFloatConstraint::Constraints ToleranceRange = {0.0, 10.0, 0.01}; const App::PropertyFloatConstraint::Constraints ExtendRange = {-0.5, 10.0, 0.01}; PROPERTY_SOURCE(Surface::Extend, Part::Spline) From bfdaa9aab25d9c1f2626f77b7786fb84fdb5207b Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:02:45 +0100 Subject: [PATCH 057/316] Techdraw: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/TechDraw/App/CenterLine.cpp | 2 +- src/Mod/TechDraw/App/CosmeticVertex.cpp | 4 +- src/Mod/TechDraw/App/DrawBrokenView.cpp | 2 +- src/Mod/TechDraw/App/DrawComplexSection.cpp | 5 +- src/Mod/TechDraw/App/DrawGeomHatch.cpp | 6 +- src/Mod/TechDraw/App/DrawLeaderLine.cpp | 4 +- src/Mod/TechDraw/App/DrawPage.cpp | 2 +- src/Mod/TechDraw/App/DrawProjGroup.cpp | 6 +- src/Mod/TechDraw/App/DrawProjectSplit.cpp | 4 +- src/Mod/TechDraw/App/DrawUtil.cpp | 42 +++-- src/Mod/TechDraw/App/DrawUtil.h | 9 +- src/Mod/TechDraw/App/DrawView.cpp | 6 +- src/Mod/TechDraw/App/DrawViewDimension.cpp | 8 +- src/Mod/TechDraw/App/DrawViewPart.cpp | 10 +- src/Mod/TechDraw/App/EdgeWalker.cpp | 8 +- src/Mod/TechDraw/App/Geometry.cpp | 36 ++-- src/Mod/TechDraw/App/GeometryObject.cpp | 16 +- src/Mod/TechDraw/App/HatchLine.cpp | 6 +- src/Mod/TechDraw/App/ShapeUtils.cpp | 6 +- src/Mod/TechDraw/App/TechDrawExport.cpp | 12 +- src/Mod/TechDraw/Gui/CommandCreateDims.cpp | 8 +- src/Mod/TechDraw/Gui/CommandExtensionDims.cpp | 4 +- src/Mod/TechDraw/Gui/CommandExtensionPack.cpp | 2 +- src/Mod/TechDraw/Gui/DimensionValidators.cpp | 20 +-- src/Mod/TechDraw/Gui/DrawGuiUtil.cpp | 2 +- src/Mod/TechDraw/Gui/PathBuilder.cpp | 6 +- src/Mod/TechDraw/Gui/QGIHighlight.cpp | 2 +- src/Mod/TechDraw/Gui/QGILeaderLine.cpp | 2 +- src/Mod/TechDraw/Gui/QGISectionLine.cpp | 4 +- src/Mod/TechDraw/Gui/QGIViewBalloon.cpp | 16 +- src/Mod/TechDraw/Gui/QGIViewDimension.cpp | 157 ++++++++++-------- src/Mod/TechDraw/Gui/QGIViewPart.cpp | 2 +- src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp | 2 +- src/Mod/TechDraw/Gui/QGTracker.cpp | 7 +- src/Mod/TechDraw/Gui/TaskComplexSection.cpp | 7 +- src/Mod/TechDraw/Gui/TaskCosmeticLine.cpp | 2 +- src/Mod/TechDraw/Gui/TaskDimension.cpp | 10 +- src/Mod/TechDraw/Gui/TaskSectionView.cpp | 6 +- .../Gui/ViewProviderCosmeticExtension.cpp | 5 +- .../TechDraw/Gui/ViewProviderDrawingView.cpp | 5 +- 40 files changed, 243 insertions(+), 220 deletions(-) diff --git a/src/Mod/TechDraw/App/CenterLine.cpp b/src/Mod/TechDraw/App/CenterLine.cpp index a61d4ad12a..3ca87f7832 100644 --- a/src/Mod/TechDraw/App/CenterLine.cpp +++ b/src/Mod/TechDraw/App/CenterLine.cpp @@ -392,7 +392,7 @@ std::pair CenterLine::rotatePointsAroundMid(cons const double angleDeg) { std::pair result; - double angleRad = angleDeg * M_PI / 180.0; + double angleRad = angleDeg * std::numbers::pi / 180.0; result.first.x = ((p1.x - mid.x) * cos(angleRad)) - ((p1.y - mid.y) * sin(angleRad)) + mid.x; result.first.y = ((p1.x - mid.x) * sin(angleRad)) + ((p1.y - mid.y) * cos(angleRad)) + mid.y; diff --git a/src/Mod/TechDraw/App/CosmeticVertex.cpp b/src/Mod/TechDraw/App/CosmeticVertex.cpp index a33e6c2dd8..35275c0546 100644 --- a/src/Mod/TechDraw/App/CosmeticVertex.cpp +++ b/src/Mod/TechDraw/App/CosmeticVertex.cpp @@ -166,7 +166,7 @@ Base::Vector3d CosmeticVertex::rotatedAndScaled(const double scale, const double // invert the Y coordinate so the rotation math works out // the stored point is inverted scaledPoint = DU::invertY(scaledPoint); - scaledPoint.RotateZ(rotDegrees * M_PI / DegreesHalfCircle); + scaledPoint.RotateZ(rotDegrees * std::numbers::pi / DegreesHalfCircle); scaledPoint = DU::invertY(scaledPoint); } return scaledPoint; @@ -182,7 +182,7 @@ Base::Vector3d CosmeticVertex::makeCanonicalPoint(DrawViewPart* dvp, Base::Vecto Base::Vector3d result = point; if (rotDeg != 0.0) { // unrotate the point - double rotRad = rotDeg * M_PI / DegreesHalfCircle; + double rotRad = rotDeg * std::numbers::pi / DegreesHalfCircle; // we always rotate around the origin. result.RotateZ(-rotRad); } diff --git a/src/Mod/TechDraw/App/DrawBrokenView.cpp b/src/Mod/TechDraw/App/DrawBrokenView.cpp index 4dd3a15a02..af7c91fc54 100644 --- a/src/Mod/TechDraw/App/DrawBrokenView.cpp +++ b/src/Mod/TechDraw/App/DrawBrokenView.cpp @@ -1113,7 +1113,7 @@ Base::Vector3d DrawBrokenView::makePerpendicular(Base::Vector3d inDir) const gp_Pnt origin(0.0, 0.0, 0.0); auto dir = getProjectionCS().Direction(); gp_Ax1 axis(origin, dir); - auto gRotated = gDir.Rotated(axis, M_PI_2); + auto gRotated = gDir.Rotated(axis, std::numbers::pi/2); return Base::convertTo(gRotated); } diff --git a/src/Mod/TechDraw/App/DrawComplexSection.cpp b/src/Mod/TechDraw/App/DrawComplexSection.cpp index eda78c83e3..198d5da1ec 100644 --- a/src/Mod/TechDraw/App/DrawComplexSection.cpp +++ b/src/Mod/TechDraw/App/DrawComplexSection.cpp @@ -100,7 +100,6 @@ #include #endif -#define _USE_MATH_DEFINES #include #include @@ -387,7 +386,7 @@ void DrawComplexSection::makeAlignedPieces(const TopoDS_Shape& rawShape) } //we only want to reverse the segment normal if it is not perpendicular to section normal if (segmentNormal.Dot(gProjectionUnit) != 0.0 - && segmentNormal.Angle(gProjectionUnit) <= M_PI_2) { + && segmentNormal.Angle(gProjectionUnit) <= std::numbers::pi/2) { segmentNormal.Reverse(); } @@ -957,7 +956,7 @@ gp_Vec DrawComplexSection::projectVector(const gp_Vec& vec) const // being slightly wrong. see https://forum.freecad.org/viewtopic.php?t=79017&sid=612a62a60f5db955ee071a7aaa362dbb bool DrawComplexSection::validateOffsetProfile(TopoDS_Wire profile, Base::Vector3d direction, double angleThresholdDeg) const { - double angleThresholdRad = angleThresholdDeg * M_PI / 180.0; // 5 degrees + double angleThresholdRad = angleThresholdDeg * std::numbers::pi / 180.0; // 5 degrees TopExp_Explorer explEdges(profile, TopAbs_EDGE); for (; explEdges.More(); explEdges.Next()) { std::pair segmentEnds = getSegmentEnds(TopoDS::Edge(explEdges.Current())); diff --git a/src/Mod/TechDraw/App/DrawGeomHatch.cpp b/src/Mod/TechDraw/App/DrawGeomHatch.cpp index 66366a000e..72412cf557 100644 --- a/src/Mod/TechDraw/App/DrawGeomHatch.cpp +++ b/src/Mod/TechDraw/App/DrawGeomHatch.cpp @@ -385,6 +385,8 @@ std::vector DrawGeomHatch::getTrimmedLines(DrawViewPart* source, /* static */ std::vector DrawGeomHatch::makeEdgeOverlay(PATLineSpec hatchLine, Bnd_Box bBox, double scale, double rotation) { + using std::numbers::pi; + const size_t MaxNumberOfEdges = Preferences::getPreferenceGroup("PAT")->GetInt("MaxSeg", 10000l); std::vector result; @@ -399,12 +401,12 @@ std::vector DrawGeomHatch::makeEdgeOverlay(PATLineSpec hatchLine, B double interval = hatchLine.getInterval() * scale; double offset = hatchLine.getOffset() * scale; double angle = hatchLine.getAngle() + rotation; - origin.RotateZ(rotation * M_PI / 180.); + origin.RotateZ(rotation * pi / 180.); if (scale == 0. || interval == 0.) return {}; - Base::Vector3d hatchDirection(cos(angle * M_PI / 180.), sin(angle * M_PI / 180.), 0.); + Base::Vector3d hatchDirection(cos(angle * pi / 180.), sin(angle * pi / 180.), 0.); Base::Vector3d hatchPerpendicular(-hatchDirection.y, hatchDirection.x, 0.); Base::Vector3d hatchIntervalAndOffset = offset * hatchDirection + interval * hatchPerpendicular; diff --git a/src/Mod/TechDraw/App/DrawLeaderLine.cpp b/src/Mod/TechDraw/App/DrawLeaderLine.cpp index 124b5164b2..bca5eea111 100644 --- a/src/Mod/TechDraw/App/DrawLeaderLine.cpp +++ b/src/Mod/TechDraw/App/DrawLeaderLine.cpp @@ -375,7 +375,7 @@ std::vector DrawLeaderLine::getScaledAndRotatedPoints(bool doSc double rotationRad{0.0}; if (doRotate) { - rotationRad = dvp->Rotation.getValue() * M_PI / DegreesHalfCircle; + rotationRad = dvp->Rotation.getValue() * std::numbers::pi / DegreesHalfCircle; } std::vector pointsAll = WayPoints.getValues(); @@ -409,7 +409,7 @@ DrawLeaderLine::makeCanonicalPoints(const std::vector& inPoints, double rotationRad{0.0}; if (doRotate) { - rotationRad = - dvp->Rotation.getValue() * M_PI / DegreesHalfCircle; + rotationRad = - dvp->Rotation.getValue() * std::numbers::pi / DegreesHalfCircle; } std::vector result; diff --git a/src/Mod/TechDraw/App/DrawPage.cpp b/src/Mod/TechDraw/App/DrawPage.cpp index 2ad8f2c926..bd5c908e68 100644 --- a/src/Mod/TechDraw/App/DrawPage.cpp +++ b/src/Mod/TechDraw/App/DrawPage.cpp @@ -118,7 +118,7 @@ void DrawPage::onChanged(const App::Property* prop) for (auto* obj : getViews()) { auto* view = dynamic_cast(obj); if (view && view->ScaleType.isValue("Page")) { - if (std::abs(view->Scale.getValue() - Scale.getValue()) > FLT_EPSILON) { + if (std::abs(view->Scale.getValue() - Scale.getValue()) > std::numeric_limits::epsilon()) { view->Scale.setValue(Scale.getValue()); } } diff --git a/src/Mod/TechDraw/App/DrawProjGroup.cpp b/src/Mod/TechDraw/App/DrawProjGroup.cpp index 2b491aff97..2b05d8ab60 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroup.cpp @@ -142,7 +142,7 @@ void DrawProjGroup::onChanged(const App::Property* prop) if (prop == &ScaleType) { if (ScaleType.isValue("Page")) { double newScale = page->Scale.getValue(); - if (std::abs(getScale() - newScale) > FLT_EPSILON) { + if (std::abs(getScale() - newScale) > std::numeric_limits::epsilon()) { Scale.setValue(newScale); updateChildrenScale(); } @@ -1146,9 +1146,9 @@ void DrawProjGroup::spin(const SpinDirection& spindirection) { double angle; if (spindirection == SpinDirection::CW) - angle = M_PI / 2.0;// Top -> Right -> Bottom -> Left -> Top + angle = std::numbers::pi / 2.0;// Top -> Right -> Bottom -> Left -> Top if (spindirection == SpinDirection::CCW) - angle = -M_PI / 2.0;// Top -> Left -> Bottom -> Right -> Top + angle = -std::numbers::pi / 2.0;// Top -> Left -> Bottom -> Right -> Top spin(angle); } diff --git a/src/Mod/TechDraw/App/DrawProjectSplit.cpp b/src/Mod/TechDraw/App/DrawProjectSplit.cpp index dd4b1825a0..7853e729b6 100644 --- a/src/Mod/TechDraw/App/DrawProjectSplit.cpp +++ b/src/Mod/TechDraw/App/DrawProjectSplit.cpp @@ -345,10 +345,12 @@ std::vector DrawProjectSplit::sortEdges(std::vector& //************************* std::string edgeSortItem::dump() { + using std::numbers::pi; + std::string result; std::stringstream builder; builder << "edgeSortItem - s: " << DrawUtil::formatVector(start) << " e: " << DrawUtil::formatVector(end) << - " sa: " << startAngle * 180.0/M_PI << " ea: " << endAngle* 180.0/M_PI << " idx: " << idx; + " sa: " << startAngle * 180.0/pi << " ea: " << endAngle* 180.0/pi << " idx: " << idx; return builder.str(); } diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index bbe2edda84..5e0dfc7a1c 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -203,7 +203,7 @@ double DrawUtil::angleWithX(Base::Vector3d inVec) { double result = atan2(inVec.y, inVec.x); if (result < 0) { - result += 2.0 * M_PI; + result += 2.0 * std::numbers::pi; } return result; @@ -225,7 +225,7 @@ double DrawUtil::angleWithX(TopoDS_Edge e, bool reverse) } double result = atan2(u.y, u.x); if (result < 0) { - result += 2.0 * M_PI; + result += 2.0 * std::numbers::pi; } return result; @@ -251,7 +251,7 @@ double DrawUtil::angleWithX(TopoDS_Edge e, TopoDS_Vertex v, double tolerance) c->D1(param, paramPoint, derivative); double angle = atan2(derivative.Y(), derivative.X()); if (angle < 0) {//map from [-PI:PI] to [0:2PI] - angle += 2.0 * M_PI; + angle += 2.0 * std::numbers::pi; } return angle; } @@ -289,7 +289,7 @@ double DrawUtil::incidenceAngleAtVertex(TopoDS_Edge e, TopoDS_Vertex v, double t //map to [0:2PI] if (incidenceAngle < 0.0) { - incidenceAngle = M_2PI + incidenceAngle; + incidenceAngle = 2*std::numbers::pi + incidenceAngle; } return incidenceAngle; @@ -1059,7 +1059,7 @@ Base::Vector3d DrawUtil::toAppSpace(const DrawViewPart& dvp, const Base::Vector // remove the effect of the Rotation property double rotDeg = dvp.Rotation.getValue(); - double rotRad = rotDeg * M_PI / 180.0; + double rotRad = rotDeg * std::numbers::pi / 180.0; if (rotDeg != 0.0) { // we always rotate around the origin. appPoint.RotateZ(-rotRad); @@ -1396,11 +1396,13 @@ double DrawUtil::sqr(double x) void DrawUtil::angleNormalize(double& fi) { - while (fi <= -M_PI) { - fi += M_2PI; + using std::numbers::pi; + + while (fi <= -pi) { + fi += 2*pi; } - while (fi > M_PI) { - fi -= M_2PI; + while (fi > pi) { + fi -= 2*pi; } } @@ -1414,13 +1416,14 @@ double DrawUtil::angleComposition(double fi, double delta) double DrawUtil::angleDifference(double fi1, double fi2, bool reflex) { + using std::numbers::pi; angleNormalize(fi1); angleNormalize(fi2); fi1 -= fi2; - if ((fi1 > +M_PI || fi1 <= -M_PI) != reflex) { - fi1 += fi1 > 0.0 ? -M_2PI : +M_2PI; + if ((fi1 > +pi || fi1 <= -pi) != reflex) { + fi1 += fi1 > 0.0 ? -2*pi : +2*pi; } return fi1; @@ -1559,6 +1562,7 @@ void DrawUtil::intervalMarkLinear(std::vector>& marking, void DrawUtil::intervalMarkCircular(std::vector>& marking, double start, double length, bool value) { + using std::numbers::pi; if (length == 0.0) { return; } @@ -1566,15 +1570,15 @@ void DrawUtil::intervalMarkCircular(std::vector>& markin length = -length; start -= length; } - if (length > M_2PI) { - length = M_2PI; + if (length > 2*pi) { + length = 2*pi; } angleNormalize(start); double end = start + length; - if (end > M_PI) { - end -= M_2PI; + if (end > pi) { + end -= 2*pi; } // Just make sure the point is stored, its index is read last @@ -1785,13 +1789,15 @@ void DrawUtil::findCircularArcRectangleIntersections(const Base::Vector2d& circl const Base::BoundBox2d& rectangle, std::vector& intersections) { + using std::numbers::pi; + findCircleRectangleIntersections(circleCenter, circleRadius, rectangle, intersections); if (arcRotation < 0.0) { arcRotation = -arcRotation; arcBaseAngle -= arcRotation; - if (arcBaseAngle <= -M_PI) { - arcBaseAngle += M_2PI; + if (arcBaseAngle <= -pi) { + arcBaseAngle += 2*pi; } } @@ -1799,7 +1805,7 @@ void DrawUtil::findCircularArcRectangleIntersections(const Base::Vector2d& circl for (unsigned int i = 0; i < intersections.size();) { double pointAngle = (intersections[i] - circleCenter).Angle(); if (pointAngle < arcBaseAngle - Precision::Confusion()) { - pointAngle += M_2PI; + pointAngle += 2*pi; } if (pointAngle > arcBaseAngle + arcRotation + Precision::Confusion()) { diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 5a4e10d9b8..7490e58622 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -50,10 +50,6 @@ #include -#ifndef M_2PI -#define M_2PI ((M_PI)*2.0) -#endif - constexpr double DegreesHalfCircle{180.0}; #define VERTEXTOLERANCE (2.0 * Precision::Confusion()) @@ -108,7 +104,8 @@ public: static bool isFirstVert(TopoDS_Edge e, TopoDS_Vertex v, double tolerance = VERTEXTOLERANCE); static bool isLastVert(TopoDS_Edge e, TopoDS_Vertex v, double tolerance = VERTEXTOLERANCE); - static bool fpCompare(const double& d1, const double& d2, double tolerance = FLT_EPSILON); + static bool fpCompare(const double& d1, const double& d2, + double tolerance = std::numeric_limits::epsilon()); static std::pair boxIntersect2d(Base::Vector3d point, Base::Vector3d dir, double xRange, double yRange); static bool apparentIntersection(const Handle(Geom_Curve) curve1, @@ -147,7 +144,7 @@ public: static Base::Vector3d toR3(const gp_Ax2& fromSystem, const Base::Vector3d& fromPoint); static bool checkParallel(const Base::Vector3d v1, const Base::Vector3d v2, - double tolerance = FLT_EPSILON); + double tolerance = std::numeric_limits::epsilon()); //! rotate vector by angle radians around axis through org static Base::Vector3d vecRotate(Base::Vector3d vec, double angle, Base::Vector3d axis, Base::Vector3d org = Base::Vector3d(0.0, 0.0, 0.0)); diff --git a/src/Mod/TechDraw/App/DrawView.cpp b/src/Mod/TechDraw/App/DrawView.cpp index d3b52a6e4b..4b01917bf6 100644 --- a/src/Mod/TechDraw/App/DrawView.cpp +++ b/src/Mod/TechDraw/App/DrawView.cpp @@ -130,7 +130,7 @@ void DrawView::checkScale() TechDraw::DrawPage *page = findParentPage(); if(page) { if (ScaleType.isValue("Page")) { - if(std::abs(page->Scale.getValue() - Scale.getValue()) > FLT_EPSILON) { + if(std::abs(page->Scale.getValue() - Scale.getValue()) > std::numeric_limits::epsilon()) { Scale.setValue(page->Scale.getValue()); Scale.purgeTouched(); } @@ -190,7 +190,7 @@ void DrawView::onChanged(const App::Property* prop) } if (ScaleType.isValue("Page")) { Scale.setStatus(App::Property::ReadOnly, true); - if(std::abs(page->Scale.getValue() - getScale()) > FLT_EPSILON) { + if(std::abs(page->Scale.getValue() - getScale()) > std::numeric_limits::epsilon()) { Scale.setValue(page->Scale.getValue()); } } else if ( ScaleType.isValue("Custom") ) { @@ -200,7 +200,7 @@ void DrawView::onChanged(const App::Property* prop) Scale.setStatus(App::Property::ReadOnly, true); if (!checkFit(page)) { double newScale = autoScale(page->getPageWidth(), page->getPageHeight()); - if(std::abs(newScale - getScale()) > FLT_EPSILON) { + if(std::abs(newScale - getScale()) > std::numeric_limits::epsilon()) { Scale.setValue(newScale); } } diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index 72a7af43a0..a16883c267 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -105,11 +105,11 @@ const char* DrawViewDimension::TypeEnums[] = {"Distance", const char* DrawViewDimension::MeasureTypeEnums[] = {"True", "Projected", nullptr}; // constraint to set the step size to 0.1 -static const App::PropertyQuantityConstraint::Constraints ToleranceConstraint = {-DBL_MAX, - DBL_MAX, - 0.1}; +static const App::PropertyQuantityConstraint::Constraints ToleranceConstraint = { + -std::numeric_limits::max(), std::numeric_limits::max(), 0.1}; // constraint to force positive values -static const App::PropertyQuantityConstraint::Constraints PositiveConstraint = {0.0, DBL_MAX, 0.1}; +static const App::PropertyQuantityConstraint::Constraints PositiveConstraint = { + 0.0, std::numeric_limits::max(), 0.1}; DrawViewDimension::DrawViewDimension() { diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index d0359df991..117001a094 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -986,7 +986,7 @@ double DrawViewPart::getSizeAlongVector(Base::Vector3d alignmentVector) if (getEdgeCompound().IsNull()) { return 1.0; } - TopoDS_Shape rotatedShape = ShapeUtils::rotateShape(getEdgeCompound(), OXYZ, alignmentAngle * 180.0 / M_PI); + TopoDS_Shape rotatedShape = ShapeUtils::rotateShape(getEdgeCompound(), OXYZ, alignmentAngle * 180.0 / std::numbers::pi); Bnd_Box shapeBox; shapeBox.SetGap(0.0); BRepBndLib::AddOptimal(rotatedShape, shapeBox); @@ -1105,7 +1105,7 @@ gp_Ax2 DrawViewPart::getRotatedCS(const Base::Vector3d basePoint) const // Base::Console().Message("DVP::getRotatedCS() - %s - %s\n", getNameInDocument(), Label.getValue()); gp_Ax2 unrotated = getProjectionCS(basePoint); gp_Ax1 rotationAxis(Base::convertTo(basePoint), unrotated.Direction()); - double angleRad = Rotation.getValue() * M_PI / 180.0; + double angleRad = Rotation.getValue() * std::numbers::pi / 180.0; gp_Ax2 rotated = unrotated.Rotated(rotationAxis, -angleRad); return rotated; } @@ -1302,9 +1302,9 @@ void DrawViewPart::spin(const SpinDirection& spindirection) { double angle; if (spindirection == SpinDirection::CW) - angle = M_PI / 2.0;// Top -> Right -> Bottom -> Left -> Top + angle = std::numbers::pi / 2.0;// Top -> Right -> Bottom -> Left -> Top if (spindirection == SpinDirection::CCW) - angle = -M_PI / 2.0;// Top -> Left -> Bottom -> Right -> Top + angle = -std::numbers::pi / 2.0;// Top -> Left -> Bottom -> Right -> Top spin(angle); } @@ -1338,7 +1338,7 @@ std::pair DrawViewPart::getDirsFromFront(ProjDir gp_Dir gNewDir; gp_Dir gNewXDir; - double angle = M_PI / 2.0;//90* + double angle = std::numbers::pi / 2.0;//90* if (viewType == ProjDirection::Right) { newCS = anchorCS.Rotated(gUpAxis, angle); diff --git a/src/Mod/TechDraw/App/EdgeWalker.cpp b/src/Mod/TechDraw/App/EdgeWalker.cpp index ae3d5b0af7..d30f1d9607 100644 --- a/src/Mod/TechDraw/App/EdgeWalker.cpp +++ b/src/Mod/TechDraw/App/EdgeWalker.cpp @@ -307,11 +307,11 @@ std::vector EdgeWalker::makeWalkerEdges(std::vector edg TopoDS_Vertex edgeVertex1 = TopExp::FirstVertex(e); TopoDS_Vertex edgeVertex2 = TopExp::LastVertex(e); std::size_t vertex1Index = findUniqueVert(edgeVertex1, verts); - if (vertex1Index == SIZE_MAX) { + if (vertex1Index == std::numeric_limits::max()) { continue; } std::size_t vertex2Index = findUniqueVert(edgeVertex2, verts); - if (vertex2Index == SIZE_MAX) { + if (vertex2Index == std::numeric_limits::max()) { continue; } @@ -338,7 +338,7 @@ size_t EdgeWalker::findUniqueVert(TopoDS_Vertex vx, std::vector & } idx++; } - return SIZE_MAX; + return std::numeric_limits::max(); } std::vector EdgeWalker::sortStrip(std::vector fw, bool includeBiggest) @@ -556,7 +556,7 @@ std::string embedItem::dump() std::stringstream builder; builder << "embedItem - vertex: " << iVertex << " incidenceList: "; for (auto& ii : incidenceList) { - builder << " e:" << ii.iEdge << "/a:" << (ii.angle * (180.0/M_PI)) << "/ed:" << ii.eDesc; + builder << " e:" << ii.iEdge << "/a:" << (ii.angle * (180.0/std::numbers::pi)) << "/ed:" << ii.eDesc; } return builder.str(); } diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index 0cb09d530b..6011cbea15 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -657,7 +657,7 @@ Ellipse::Ellipse(Base::Vector3d c, double mnr, double mjr) Base::Console().Message("G:Ellipse - failed to make Ellipse\n"); } const Handle(Geom_Ellipse) gEllipse = me.Value(); - BRepBuilderAPI_MakeEdge mkEdge(gEllipse, 0.0, 2 * M_PI); + BRepBuilderAPI_MakeEdge mkEdge(gEllipse, 0.0, 2 * std::numbers::pi); if (mkEdge.IsDone()) { occEdge = mkEdge.Edge(); } @@ -686,10 +686,10 @@ AOE::AOE(const TopoDS_Edge &e) : Ellipse(e) e.GetMessageString()); } - startAngle = fmod(f, 2.0*M_PI); - endAngle = fmod(l, 2.0*M_PI); + startAngle = fmod(f, 2.0*std::numbers::pi); + endAngle = fmod(l, 2.0*std::numbers::pi); cw = (a < 0) ? true: false; - largeArc = (l-f > M_PI) ? true : false; + largeArc = (l-f > std::numbers::pi) ? true : false; startPnt = Base::Vector3d(s.X(), s.Y(), s.Z()); endPnt = Base::Vector3d(ePt.X(), ePt.Y(), ePt.Z()); @@ -709,6 +709,8 @@ Circle::Circle() Circle::Circle(Base::Vector3d c, double r) { + using std::numbers::pi; + geomType = GeomType::CIRCLE; radius = r; center = c; @@ -722,7 +724,7 @@ Circle::Circle(Base::Vector3d c, double r) double angle2 = 360.0; Handle(Geom_Circle) hCircle = new Geom_Circle (circle); - BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(M_PI/180), angle2*(M_PI/180)); + BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(pi/180), angle2*(pi/180)); TopoDS_Edge edge = aMakeEdge.Edge(); occEdge = edge; } @@ -794,12 +796,12 @@ AOC::AOC(const TopoDS_Edge &e) : Circle(e) // this is the wrong determination of cw/ccw. needs to be determined by edge. double a = v3.DotCross(v1, v2); //error if v1 = v2? - startAngle = fmod(f, 2.0*M_PI); - endAngle = fmod(l, 2.0*M_PI); + startAngle = fmod(f, 2.0*std::numbers::pi); + endAngle = fmod(l, 2.0*std::numbers::pi); cw = (a < 0) ? true: false; - largeArc = (fabs(l-f) > M_PI) ? true : false; + largeArc = (fabs(l-f) > std::numbers::pi) ? true : false; startPnt = Base::convertTo(s); endPnt = Base::convertTo(ePt); @@ -823,7 +825,7 @@ AOC::AOC(Base::Vector3d c, double r, double sAng, double eAng) : Circle() circle.SetRadius(r); Handle(Geom_Circle) hCircle = new Geom_Circle (circle); - BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, sAng*(M_PI/180), eAng*(M_PI/180)); + BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, sAng*(std::numbers::pi/180), eAng*(std::numbers::pi/180)); TopoDS_Edge edge = aMakeEdge.Edge(); occEdge = edge; @@ -844,10 +846,10 @@ AOC::AOC(Base::Vector3d c, double r, double sAng, double eAng) : Circle() // this cw flag is a problem. we should just declare that arcs are always ccw and flip the start and end angles. double a = v3.DotCross(v1, v2); //error if v1 = v2? - startAngle = fmod(f, 2.0*M_PI); - endAngle = fmod(l, 2.0*M_PI); + startAngle = fmod(f, 2.0*std::numbers::pi); + endAngle = fmod(l, 2.0*std::numbers::pi); cw = (a < 0) ? true: false; - largeArc = (fabs(l-f) > M_PI) ? true : false; + largeArc = (fabs(l-f) > std::numbers::pi) ? true : false; startPnt = Base::convertTo(s); endPnt = Base::convertTo(ePt); @@ -866,7 +868,7 @@ AOC::AOC() : Circle() endPnt = Base::Vector3d(0.0, 0.0, 0.0); midPnt = Base::Vector3d(0.0, 0.0, 0.0); startAngle = 0.0; - endAngle = 2.0 * M_PI; + endAngle = 2.0 * std::numbers::pi; cw = false; largeArc = false; @@ -1095,7 +1097,7 @@ double Generic::slope() { Base::Vector3d v = asVector(); if (v.x == 0.0) { - return DOUBLE_MAX; + return std::numeric_limits::max(); } else { return v.y/v.x; } @@ -1146,11 +1148,11 @@ BSpline::BSpline(const TopoDS_Edge &e) startAngle = atan2(startPnt.y, startPnt.x); if (startAngle < 0) { - startAngle += 2.0 * M_PI; + startAngle += 2.0 * std::numbers::pi; } endAngle = atan2(endPnt.y, endPnt.x); if (endAngle < 0) { - endAngle += 2.0 * M_PI; + endAngle += 2.0 * std::numbers::pi; } Standard_Real tol3D = 0.001; //1/1000 of a mm? screen can't resolve this @@ -1473,7 +1475,7 @@ TopoDS_Edge GeometryUtils::edgeFromCircle(TechDraw::CirclePtr c) circle.SetAxis(axis); circle.SetRadius(c->radius); Handle(Geom_Circle) hCircle = new Geom_Circle (circle); - BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, 0.0, 2.0 * M_PI); + BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, 0.0, 2.0 * std::numbers::pi); return aMakeEdge.Edge(); } diff --git a/src/Mod/TechDraw/App/GeometryObject.cpp b/src/Mod/TechDraw/App/GeometryObject.cpp index b56e54943f..021cb13534 100644 --- a/src/Mod/TechDraw/App/GeometryObject.cpp +++ b/src/Mod/TechDraw/App/GeometryObject.cpp @@ -759,24 +759,26 @@ TechDraw::DrawViewDetail* GeometryObject::isParentDetail() bool GeometryObject::isWithinArc(double theta, double first, double last, bool cw) const { - if (fabs(last - first) >= 2 * M_PI) { + using std::numbers::pi; + + if (fabs(last - first) >= 2 * pi) { return true; } // Put params within [0, 2*pi) - not totally sure this is necessary - theta = fmod(theta, 2 * M_PI); + theta = fmod(theta, 2 * pi); if (theta < 0) { - theta += 2 * M_PI; + theta += 2 * pi; } - first = fmod(first, 2 * M_PI); + first = fmod(first, 2 * pi); if (first < 0) { - first += 2 * M_PI; + first += 2 * pi; } - last = fmod(last, 2 * M_PI); + last = fmod(last, 2 * pi); if (last < 0) { - last += 2 * M_PI; + last += 2 * pi; } if (cw) { diff --git a/src/Mod/TechDraw/App/HatchLine.cpp b/src/Mod/TechDraw/App/HatchLine.cpp index 2c2814cac1..e37626a2d1 100644 --- a/src/Mod/TechDraw/App/HatchLine.cpp +++ b/src/Mod/TechDraw/App/HatchLine.cpp @@ -396,7 +396,7 @@ double PATLineSpec::getSlope() } else if (angle < -90.0) { angle = (180 + angle); } - return tan(angle * M_PI/180.0); + return tan(angle * std::numbers::pi/180.0); } bool PATLineSpec::isDashed() @@ -413,7 +413,7 @@ double PATLineSpec::getIntervalX() return getInterval(); } else { double perpAngle = fabs(getAngle() - 90.0); - return fabs(getInterval() / cos(perpAngle * M_PI/180.0)); + return fabs(getInterval() / cos(perpAngle * std::numbers::pi/180.0)); } } @@ -426,7 +426,7 @@ double PATLineSpec::getIntervalY() return 0.0; } else { double perpAngle = fabs(getAngle() - 90.0); - return fabs(getInterval() * tan(perpAngle * M_PI/180.0)); + return fabs(getInterval() * tan(perpAngle * std::numbers::pi/180.0)); } } diff --git a/src/Mod/TechDraw/App/ShapeUtils.cpp b/src/Mod/TechDraw/App/ShapeUtils.cpp index 88db95abc8..6e5c070fe5 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.cpp +++ b/src/Mod/TechDraw/App/ShapeUtils.cpp @@ -96,7 +96,7 @@ gp_Ax2 ShapeUtils::getViewAxis(const Base::Vector3d origin, const Base::Vector3d cross = cross.Cross(stdZ); } - if (cross.IsEqual(stdOrg, FLT_EPSILON)) { + if (cross.IsEqual(stdOrg, std::numeric_limits::epsilon())) { viewAxis = gp_Ax2(inputCenter, gp_Dir(direction.x, direction.y, direction.z)); return viewAxis; } @@ -142,7 +142,7 @@ gp_Ax2 ShapeUtils::legacyViewAxis1(const Base::Vector3d origin, const Base::Vect cross = cross.Cross(stdZ); } - if (cross.IsEqual(stdOrg, FLT_EPSILON)) { + if (cross.IsEqual(stdOrg, std::numeric_limits::epsilon())) { return gp_Ax2(inputCenter, gp_Dir(flipDirection.x, flipDirection.y, flipDirection.z)); } @@ -273,7 +273,7 @@ TopoDS_Shape ShapeUtils::rotateShape(const TopoDS_Shape& input, const gp_Ax2& vi } gp_Ax1 rotAxis = viewAxis.Axis(); - double rotation = rotAngle * M_PI / 180.0; + double rotation = rotAngle * std::numbers::pi / 180.0; try { gp_Trsf tempTransform; diff --git a/src/Mod/TechDraw/App/TechDrawExport.cpp b/src/Mod/TechDraw/App/TechDrawExport.cpp index dd7391eac6..eb97f04a0e 100644 --- a/src/Mod/TechDraw/App/TechDrawExport.cpp +++ b/src/Mod/TechDraw/App/TechDrawExport.cpp @@ -220,7 +220,7 @@ void SVGOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) else { // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths char xar = '0'; // x-axis-rotation - char las = (l-f > M_PI) ? '1' : '0'; // large-arc-flag + char las = (l-f > std::numbers::pi) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << " M_PI) ? '1' : '0'; // large-arc-flag + char las = (l-f > std::numbers::pi) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << " M_PI) ? '1' : '0'; // large-arc-flag + char las = (l-f > std::numbers::pi) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << " 0) { double temp = start_angle; @@ -583,7 +583,7 @@ void DXFOutput::printEllipse(const BRepAdaptor_Curve& c, int /*id*/, std::ostrea gp_Dir xaxis = ellp.XAxis().Direction(); Standard_Real angle = xaxis.Angle(gp_Dir(1, 0,0)); angle = Base::toDegrees(angle); - char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag + char las = (l-f > std::numbers::pi) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << "::max(); + double minY = std::numeric_limits::max(); + double maxX = -std::numeric_limits::max(); + double maxY = -std::numeric_limits::max(); for (auto dim : dims) { TechDraw::pointPair pp = dim->getLinearPoints(); Base::Vector3d pnt1 = Rez::guiX(pp.first()); diff --git a/src/Mod/TechDraw/Gui/CommandExtensionDims.cpp b/src/Mod/TechDraw/Gui/CommandExtensionDims.cpp index 64d16ae320..7da9433ff9 100644 --- a/src/Mod/TechDraw/Gui/CommandExtensionDims.cpp +++ b/src/Mod/TechDraw/Gui/CommandExtensionDims.cpp @@ -2050,7 +2050,7 @@ void execCreateHorizChamferDimension(Gui::Command* cmd) { std::vector allVertexes; allVertexes = _getVertexInfo(objFeat, subNames); if (!allVertexes.empty() && allVertexes.size() > 1) { - const auto Pi180 = 180.0 / M_PI; + const auto Pi180 = 180.0 / std::numbers::pi; TechDraw::DrawViewDimension* dim; dim = _createLinDimension(objFeat, allVertexes[0].name, allVertexes[1].name, "DistanceX"); float yMax = std::max(abs(allVertexes[0].point.y), abs(allVertexes[1].point.y)) + 7.0; @@ -2119,7 +2119,7 @@ void execCreateVertChamferDimension(Gui::Command* cmd) { std::vector allVertexes; allVertexes = _getVertexInfo(objFeat, subNames); if (!allVertexes.empty() && allVertexes.size() > 1) { - const auto Pi180 = 180.0 / M_PI; + const auto Pi180 = 180.0 / std::numbers::pi; TechDraw::DrawViewDimension* dim; dim = _createLinDimension(objFeat, allVertexes[0].name, allVertexes[1].name, "DistanceY"); float xMax = std::max(abs(allVertexes[0].point.x), abs(allVertexes[1].point.x)) + 7.0; diff --git a/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp b/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp index e37c3a7795..582bcfdd22 100644 --- a/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp +++ b/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp @@ -2099,7 +2099,7 @@ double _getAngle(Base::Vector3d center, Base::Vector3d point) { constexpr double DegreesHalfCircle{180.0}; Base::Vector3d vecCP = point - center; - double angle = DU::angleWithX(vecCP) * DegreesHalfCircle / M_PI; + double angle = DU::angleWithX(vecCP) * DegreesHalfCircle / std::numbers::pi; return angle; } diff --git a/src/Mod/TechDraw/Gui/DimensionValidators.cpp b/src/Mod/TechDraw/Gui/DimensionValidators.cpp index 2142161701..9f24fdf162 100644 --- a/src/Mod/TechDraw/Gui/DimensionValidators.cpp +++ b/src/Mod/TechDraw/Gui/DimensionValidators.cpp @@ -386,10 +386,10 @@ DimensionGeometry TechDraw::isValidSingleEdge(const ReferenceEntry& ref) return DimensionGeometry::isInvalid; } Base::Vector3d line = gen1->points.at(1) - gen1->points.at(0); - if (fabs(line.y) < FLT_EPSILON) { + if (fabs(line.y) < std::numeric_limits::epsilon()) { return DimensionGeometry::isVertical; } - if (fabs(line.x) < FLT_EPSILON) { + if (fabs(line.x) < std::numeric_limits::epsilon()) { return DimensionGeometry::isHorizontal; } return DimensionGeometry::isDiagonal; @@ -430,13 +430,13 @@ DimensionGeometry TechDraw::isValidSingleEdge3d(DrawViewPart* dvp, const Referen Base::Vector3d point1 = Base::convertTo(BRep_Tool::Pnt(TopExp::LastVertex(occEdge))); point1 = dvp->projectPoint(point1); Base::Vector3d line = point1 - point0; - if (fabs(line.y) < FLT_EPSILON) { + if (fabs(line.y) < std::numeric_limits::epsilon()) { return DimensionGeometry::isVertical; } - if (fabs(line.x) < FLT_EPSILON) { + if (fabs(line.x) < std::numeric_limits::epsilon()) { return DimensionGeometry::isHorizontal; } - // else if (fabs(line.z) < FLT_EPSILON) { + // else if (fabs(line.z) < std::numeric_limits::epsilon()) { // return TechDraw::isZLimited; // } else { @@ -632,9 +632,9 @@ DimensionGeometry TechDraw::isValidVertexes(const ReferenceVector& refs) TechDraw::VertexPtr v0 = dvp->getVertex(refs.at(0).getSubName()); TechDraw::VertexPtr v1 = dvp->getVertex(refs.at(1).getSubName()); Base::Vector3d line = v1->point() - v0->point(); - if (fabs(line.y) < FLT_EPSILON) { + if (fabs(line.y) < std::numeric_limits::epsilon()) { return DimensionGeometry::isHorizontal; - } else if (fabs(line.x) < FLT_EPSILON) { + } else if (fabs(line.x) < std::numeric_limits::epsilon()) { return DimensionGeometry::isHorizontal; } else { return DimensionGeometry::isDiagonal; @@ -670,12 +670,12 @@ DimensionGeometry TechDraw::isValidVertexes3d(DrawViewPart* dvp, const Reference Base::Vector3d point1 = Base::convertTo(BRep_Tool::Pnt(TopoDS::Vertex(geometry1))); point1 = dvp->projectPoint(point1); Base::Vector3d line = point1 - point0; - if (fabs(line.y) < FLT_EPSILON) { + if (fabs(line.y) < std::numeric_limits::epsilon()) { return DimensionGeometry::isVertical; } - if (fabs(line.x) < FLT_EPSILON) { + if (fabs(line.x) < std::numeric_limits::epsilon()) { return DimensionGeometry::isHorizontal; - // } else if(fabs(line.z) < FLT_EPSILON) { + // } else if(fabs(line.z) < std::numeric_limits::epsilon()) { // return isZLimited; } else { return DimensionGeometry::isDiagonal; diff --git a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp index 3954090e30..a6e9dce171 100644 --- a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp +++ b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp @@ -832,7 +832,7 @@ void DrawGuiUtil::rotateToAlign(DrawViewPart* view, const Base::Vector2d& oldDir double toRotate = newDirection.GetAngle(oldDirection); // Radians to degrees - toRotate = toRotate * 180 / M_PI; + toRotate = toRotate * 180 / std::numbers::pi; // Rotate least amount possible if(toRotate > 90) { diff --git a/src/Mod/TechDraw/Gui/PathBuilder.cpp b/src/Mod/TechDraw/Gui/PathBuilder.cpp index 2d5240baab..11e26758b3 100644 --- a/src/Mod/TechDraw/Gui/PathBuilder.cpp +++ b/src/Mod/TechDraw/Gui/PathBuilder.cpp @@ -327,11 +327,11 @@ void PathBuilder::pathArc(QPainterPath& path, double rx, double ry, double x_axi th_arc = th1 - th0; if (th_arc < 0 && sweep_flag) - th_arc += 2 * M_PI; + th_arc += 2 * std::numbers::pi; else if (th_arc > 0 && !sweep_flag) - th_arc -= 2 * M_PI; + th_arc -= 2 * std::numbers::pi; - n_segs = qCeil(qAbs(th_arc / (M_PI * 0.5 + 0.001))); + n_segs = qCeil(qAbs(th_arc / (std::numbers::pi * 0.5 + 0.001))); path.moveTo(curx, cury); diff --git a/src/Mod/TechDraw/Gui/QGIHighlight.cpp b/src/Mod/TechDraw/Gui/QGIHighlight.cpp index 165a9156e6..85d58d9ffc 100644 --- a/src/Mod/TechDraw/Gui/QGIHighlight.cpp +++ b/src/Mod/TechDraw/Gui/QGIHighlight.cpp @@ -125,7 +125,7 @@ void QGIHighlight::makeReference() QRectF r(m_start, m_end); double radius = r.width() / 2.0; QPointF center = r.center(); - double angleRad = m_referenceAngle * M_PI / 180.0; + double angleRad = m_referenceAngle * std::numbers::pi / 180.0; double posX = center.x() + cos(angleRad) * radius + horizOffset; double posY = center.y() - sin(angleRad) * radius - vertOffset; m_reference->setPos(posX, posY); diff --git a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp index 40c1e15ecd..b8e23aac6c 100644 --- a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp +++ b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp @@ -589,7 +589,7 @@ Base::Vector3d QGILeaderLine::getAttachPoint() double yPos = Rez::guiX(featLeader->Y.getValue()); Base::Vector3d vAttachPoint{xPos, yPos}; vAttachPoint = vAttachPoint * baseScale; - double rotationRad = parent->Rotation.getValue() * M_PI / DegreesHalfCircle; + double rotationRad = parent->Rotation.getValue() * std::numbers::pi / DegreesHalfCircle; if (rotationRad != 0.0) { vAttachPoint.RotateZ(rotationRad); } diff --git a/src/Mod/TechDraw/Gui/QGISectionLine.cpp b/src/Mod/TechDraw/Gui/QGISectionLine.cpp index 37415d4df5..c5546e85ec 100644 --- a/src/Mod/TechDraw/Gui/QGISectionLine.cpp +++ b/src/Mod/TechDraw/Gui/QGISectionLine.cpp @@ -402,9 +402,9 @@ double QGISectionLine::getArrowRotation(Base::Vector3d arrowDir) arrowDir.Normalize(); double angle = atan2f(arrowDir.y, arrowDir.x); if (angle < 0.0) { - angle = 2 * M_PI + angle; + angle = 2 * std::numbers::pi + angle; } - double arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees) + double arrowRotation = 360.0 - angle * (180.0/std::numbers::pi); //convert to Qt rotation (clockwise degrees) return arrowRotation; } diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp index c63e7c5cdc..b1d4258814 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp @@ -606,6 +606,8 @@ void QGIViewBalloon::draw() void QGIViewBalloon::drawBalloon(bool originDrag) { + using std::numbers::pi; + if ((!originDrag) && m_dragInProgress) { // TODO there are 2 drag status variables. m_draggingInProgress appears to be the one to use? // dragged shows false while drag is still in progress. @@ -696,14 +698,14 @@ void QGIViewBalloon::drawBalloon(bool originDrag) double radius = sqrt(pow((textHeight / 2.0), 2) + pow((textWidth / 2.0), 2)); radius = radius * scale; radius += Rez::guiX(3.0); - offsetLR = (tan(30 * M_PI / 180) * radius); + offsetLR = (tan(30 * pi / 180) * radius); QPolygonF triangle; - double startAngle = -M_PI / 2; + double startAngle = -pi / 2; double angle = startAngle; for (int i = 0; i < 4; i++) { triangle += QPointF(lblCenter.x + (radius * cos(angle)), lblCenter.y + (radius * sin(angle))); - angle += (2 * M_PI / 3); + angle += (2 * pi / 3); } balloonPath.moveTo(lblCenter.x + (radius * cos(startAngle)), lblCenter.y + (radius * sin(startAngle))); @@ -737,12 +739,12 @@ void QGIViewBalloon::drawBalloon(bool originDrag) radius += Rez::guiX(1.0); offsetLR = radius; QPolygonF triangle; - double startAngle = -2 * M_PI / 3; + double startAngle = -2 * pi / 3; double angle = startAngle; for (int i = 0; i < 7; i++) { triangle += QPointF(lblCenter.x + (radius * cos(angle)), lblCenter.y + (radius * sin(angle))); - angle += (2 * M_PI / 6); + angle += (2 * pi / 6); } balloonPath.moveTo(lblCenter.x + (radius * cos(startAngle)), lblCenter.y + (radius * sin(startAngle))); @@ -805,7 +807,7 @@ void QGIViewBalloon::drawBalloon(bool originDrag) dirballoonLinesLine = (arrowTipPosInParent - dLineStart).Normalize(); } - float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI; + float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / pi; if ((endType == ArrowType::FILLED_TRIANGLE) && (prefOrthoPyramid())) { if (arAngle < 0.0) { @@ -824,7 +826,7 @@ void QGIViewBalloon::drawBalloon(bool originDrag) else { arAngle = 0; } - double radAngle = arAngle * M_PI / 180.0; + double radAngle = arAngle * pi / 180.0; double sinAngle = sin(radAngle); double cosAngle = cos(radAngle); xAdj = Rez::guiX(arrowAdj * cosAngle); diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index 60040fbbba..27fdc744ed 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -22,10 +22,6 @@ #include "PreCompiled.h" -#ifdef FC_OS_WIN32 -# define _USE_MATH_DEFINES //resolves Windows & M_PI issues -#endif - #ifndef _PreComp_ # include @@ -440,25 +436,27 @@ void QGIViewDimension::draw() double QGIViewDimension::getAnglePlacementFactor(double testAngle, double endAngle, double startRotation) { + using std::numbers::pi; + if (startRotation > 0.0) { startRotation = -startRotation; endAngle -= startRotation; - if (endAngle > M_PI) { - endAngle -= M_2PI; + if (endAngle > pi) { + endAngle -= 2 * pi; } } if (testAngle > endAngle) { - testAngle -= M_2PI; + testAngle -= 2 * pi; } if (testAngle >= endAngle + startRotation) { return +1.0; } - testAngle += M_PI; + testAngle += pi; if (testAngle > endAngle) { - testAngle -= M_2PI; + testAngle -= 2 * pi; } if (testAngle >= endAngle + startRotation) { @@ -472,7 +470,7 @@ int QGIViewDimension::compareAngleStraightness(double straightAngle, double left double rightAngle, double leftStrikeFactor, double rightStrikeFactor) { - double leftDelta = DrawUtil::angleComposition(M_PI, straightAngle - leftAngle); + double leftDelta = DrawUtil::angleComposition(std::numbers::pi, straightAngle - leftAngle); double rightDelta = DrawUtil::angleComposition(rightAngle, -straightAngle); if (fabs(leftDelta - rightDelta) <= Precision::Confusion()) { @@ -492,7 +490,7 @@ int QGIViewDimension::compareAngleStraightness(double straightAngle, double left double QGIViewDimension::getIsoStandardLinePlacement(double labelAngle) { // According to ISO 129-1 Standard Figure 23, the bordering angle is 1/2 PI, resp. -1/2 PI - return labelAngle < -M_PI / 2.0 || labelAngle > +M_PI / 2.0 ? +1.0 : -1.0; + return labelAngle < -std::numbers::pi / 2.0 || labelAngle > +std::numbers::pi / 2.0 ? +1.0 : -1.0; } Base::Vector2d QGIViewDimension::getIsoRefOutsetPoint(const Base::BoundBox2d& labelRectangle, @@ -599,7 +597,7 @@ double QGIViewDimension::computeLineAndLabelAngles(const Base::Vector2d& rotatio double devAngle = getIsoStandardLinePlacement(rawAngle) * asin(lineLabelDistance / rawDistance); lineAngle = DrawUtil::angleComposition(lineAngle, devAngle); - labelAngle = devAngle < 0.0 ? lineAngle : DrawUtil::angleComposition(lineAngle, M_PI); + labelAngle = devAngle < 0.0 ? lineAngle : DrawUtil::angleComposition(lineAngle, std::numbers::pi); return devAngle; } @@ -669,7 +667,7 @@ QGIViewDimension::computeArcStrikeFactor(const Base::BoundBox2d& labelRectangle, double arcAngle = drawMarking[startIndex].first; double arcRotation = drawMarking[currentIndex].first - arcAngle; if (arcRotation < 0.0) { - arcRotation += M_2PI; + arcRotation += 2 * std::numbers::pi; } DrawUtil::findCircularArcRectangleIntersections(arcCenter, arcRadius, arcAngle, @@ -689,7 +687,7 @@ double QGIViewDimension::normalizeStartPosition(double& startPosition, double& l { if (startPosition > 0.0) { startPosition = -startPosition; - lineAngle += M_PI; + lineAngle += std::numbers::pi; return -1.0; } @@ -872,7 +870,7 @@ bool QGIViewDimension::constructDimensionArc( // Add the arrow tails - these are drawn always double tailDelta = - arcRadius >= Precision::Confusion() ? getDefaultArrowTailLength() / arcRadius : M_PI_4; + arcRadius >= Precision::Confusion() ? getDefaultArrowTailLength() / arcRadius : std::numbers::pi / 4.0; double placementFactor = flipArrows ? +1.0 : -1.0; DrawUtil::intervalMarkCircular(outputMarking, endAngle, @@ -993,7 +991,7 @@ void QGIViewDimension::drawSingleArc(QPainterPath& painterPath, const Base::Vect return; } if (endAngle < startAngle) { - endAngle += M_2PI; + endAngle += 2 * std::numbers::pi; } QRectF qtArcRectangle( @@ -1019,7 +1017,7 @@ void QGIViewDimension::drawMultiArc(QPainterPath& painterPath, const Base::Vecto } if (entryIndex >= drawMarking.size()) { - drawSingleArc(painterPath, arcCenter, arcRadius, 0, M_2PI); + drawSingleArc(painterPath, arcCenter, arcRadius, 0, 2 * std::numbers::pi); return; } @@ -1067,7 +1065,7 @@ void QGIViewDimension::drawDimensionLine(QPainterPath& painterPath, double arrowAngles[2]; arrowAngles[0] = lineAngle; - arrowAngles[1] = lineAngle + M_PI; + arrowAngles[1] = lineAngle + std::numbers::pi; drawArrows(arrowCount, arrowPositions, arrowAngles, flipArrows, forcePointStyle); } @@ -1077,13 +1075,15 @@ void QGIViewDimension::drawDimensionArc(QPainterPath& painterPath, const Base::V double jointAngle, const Base::BoundBox2d& labelRectangle, int arrowCount, int standardStyle, bool flipArrows) const { + using std::numbers::pi; + // Keep the convention start rotation <= 0 double handednessFactor = normalizeStartRotation(startRotation); // Split the rest of 2PI minus the angle and assign joint offset so > 0 is closer to end arc side double jointRotation = handednessFactor * (jointAngle - endAngle); - if (fabs(jointRotation - startRotation * 0.5) > M_PI) { - jointRotation += jointRotation < 0.0 ? +M_2PI : -M_2PI; + if (fabs(jointRotation - startRotation * 0.5) > pi) { + jointRotation += jointRotation < 0.0 ? +2*pi : -2*pi; } std::vector> drawMarks; @@ -1099,8 +1099,8 @@ void QGIViewDimension::drawDimensionArc(QPainterPath& painterPath, const Base::V + Base::Vector2d::FromPolar(arcRadius, endAngle + handednessFactor * startRotation); double arrowAngles[2]; - arrowAngles[0] = endAngle + handednessFactor * M_PI_2; - arrowAngles[1] = endAngle + handednessFactor * (startRotation - M_PI_2); + arrowAngles[0] = endAngle + handednessFactor * std::numbers::pi/2; + arrowAngles[1] = endAngle + handednessFactor * (startRotation - std::numbers::pi/2); drawArrows(arrowCount, arrowPositions, arrowAngles, flipArrows); } @@ -1119,6 +1119,8 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d& startPoint, int standardStyle, int renderExtent, bool flipArrows) const { + using std::numbers::pi; + QPainterPath distancePath; Base::Vector2d labelCenter(labelRectangle.GetCenter()); @@ -1170,9 +1172,9 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d& startPoint, // Orient the leader line angle correctly towards the target point double angles[2]; angles[0] = - jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngle, pi) : lineAngle; angles[1] = - jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngle, pi) : lineAngle; // Select the placement, where the label is not obscured by the leader line // or (if both behave the same) the one that bends the reference line less @@ -1226,7 +1228,7 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d& startPoint, // We may rotate the label so no leader and reference lines are needed double placementFactor = getIsoStandardLinePlacement(lineAngle); labelAngle = - placementFactor > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + placementFactor > 0.0 ? DrawUtil::angleComposition(lineAngle, pi) : lineAngle; // Find out the projection of label center on the line with given angle Base::Vector2d labelProjection( @@ -1234,7 +1236,7 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d& startPoint, + Base::Vector2d::FromPolar( placementFactor * (labelRectangle.Height() * 0.5 + getIsoDimensionLineSpacing()), - lineAngle + M_PI_2)); + lineAngle + pi/2)); // Compute the dimensional line start and end crossings with (virtual) extension lines //check for isometric direction and if iso compute non-perpendicular intersection of dim line and ext lines @@ -1288,14 +1290,14 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d& startPoint, Base::Vector2d extensionOrigin; Base::Vector2d extensionTarget(computeExtensionLinePoints( - endPoint, endCross, lineAngle + M_PI_2, getDefaultExtensionLineOverhang(), gapSize, + endPoint, endCross, lineAngle + std::numbers::pi/2, getDefaultExtensionLineOverhang(), gapSize, extensionOrigin)); //draw 1st extension line distancePath.moveTo(toQtGui(extensionOrigin)); distancePath.lineTo(toQtGui(extensionTarget)); if (arrowCount > 1) { - extensionTarget = computeExtensionLinePoints(startPoint, startCross, lineAngle + M_PI_2, + extensionTarget = computeExtensionLinePoints(startPoint, startCross, lineAngle + std::numbers::pi/2, getDefaultExtensionLineOverhang(), gapSize, extensionOrigin); //draw second extension line @@ -1320,6 +1322,8 @@ void QGIViewDimension::drawDistanceOverride(const Base::Vector2d& startPoint, int standardStyle, int renderExtent, bool flipArrows, double extensionAngle) const { + using std::numbers::pi; + QPainterPath distancePath; Base::Vector2d labelCenter(labelRectangle.GetCenter()); @@ -1377,9 +1381,9 @@ void QGIViewDimension::drawDistanceOverride(const Base::Vector2d& startPoint, // Orient the leader line angle correctly towards the target point double angles[2]; angles[0] = - jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngle, pi) : lineAngle; angles[1] = - jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngle, pi) : lineAngle; // Select the placement, where the label is not obscured by the leader line // or (if both behave the same) the one that bends the reference line less @@ -1436,7 +1440,7 @@ void QGIViewDimension::drawDistanceOverride(const Base::Vector2d& startPoint, // We may rotate the label so no leader and reference lines are needed double placementFactor = getIsoStandardLinePlacement(lineAngle); labelAngle = - placementFactor > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + placementFactor > 0.0 ? DrawUtil::angleComposition(lineAngle, pi) : lineAngle; // Find out the projection of label center on the line with given angle Base::Vector2d labelProjection( @@ -1444,7 +1448,7 @@ void QGIViewDimension::drawDistanceOverride(const Base::Vector2d& startPoint, + Base::Vector2d::FromPolar( placementFactor * (labelRectangle.Height() * 0.5 + getIsoDimensionLineSpacing()), - lineAngle + M_PI_2)); + lineAngle + std::numbers::pi/2)); // Compute the dimensional line start and end crossings with (virtual) extension lines startCross = @@ -1499,14 +1503,14 @@ void QGIViewDimension::drawDistanceOverride(const Base::Vector2d& startPoint, Base::Vector2d extensionOrigin; Base::Vector2d extensionTarget(computeExtensionLinePoints( - endPoint, endCross, lineAngle + M_PI_2, getDefaultExtensionLineOverhang(), gapSize, + endPoint, endCross, lineAngle + std::numbers::pi/2, getDefaultExtensionLineOverhang(), gapSize, extensionOrigin)); //draw 1st extension line distancePath.moveTo(toQtGui(extensionOrigin)); distancePath.lineTo(toQtGui(extensionTarget)); if (arrowCount > 1) { - extensionTarget = computeExtensionLinePoints(startPoint, startCross, lineAngle + M_PI_2, + extensionTarget = computeExtensionLinePoints(startPoint, startCross, lineAngle + std::numbers::pi/2, getDefaultExtensionLineOverhang(), gapSize, extensionOrigin); //draw second extension line @@ -1528,6 +1532,8 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d& centerPoint, double centerOverhang, int standardStyle, int renderExtent, bool flipArrow) const { + using std::numbers::pi; + QPainterPath radiusPath; Base::Vector2d labelCenter(labelRectangle.GetCenter()); @@ -1558,10 +1564,10 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d& centerPoint, // Orient the leader line angle correctly towards the point on arc if (angleFactors[0] < 0.0) { - lineAngles[0] = DrawUtil::angleComposition(lineAngles[0], M_PI); + lineAngles[0] = DrawUtil::angleComposition(lineAngles[0], pi); } if (angleFactors[1] < 0.0) { - lineAngles[1] = DrawUtil::angleComposition(lineAngles[1], M_PI); + lineAngles[1] = DrawUtil::angleComposition(lineAngles[1], pi); } // Find the positions where the reference line attaches to the dimension line @@ -1600,9 +1606,9 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d& centerPoint, if (compareAngleStraightness( 0.0, - jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngles[0], M_PI) + jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngles[0], pi) : lineAngles[0], - jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngles[1], M_PI) + jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngles[1], pi) : lineAngles[1], strikeFactors[0], strikeFactors[1]) > 0) { @@ -1653,7 +1659,7 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d& centerPoint, // Is there point on the arc, where line from center intersects it perpendicularly? double angleFactor = getAnglePlacementFactor(lineAngle, endAngle, startRotation); if (angleFactor < 0.0) { - lineAngle = DrawUtil::angleComposition(lineAngle, M_PI); + lineAngle = DrawUtil::angleComposition(lineAngle, pi); } Base::Vector2d arcPoint; @@ -1673,7 +1679,7 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d& centerPoint, labelRectangle.Height() * 0.5 + getIsoDimensionLineSpacing(), lineAngle, labelAngle); - lineAngle = DrawUtil::angleComposition(lineAngle, M_PI); + lineAngle = DrawUtil::angleComposition(lineAngle, pi); labelPosition = -cos(devAngle) * ((labelCenter - arcPoint).Length()); } @@ -1693,7 +1699,7 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d& centerPoint, // Is there point on the arc, where line from center intersects it perpendicularly? double angleFactor = getAnglePlacementFactor(lineAngle, endAngle, startRotation); if (angleFactor < 0) { - lineAngle = DrawUtil::angleComposition(lineAngle, M_PI); + lineAngle = DrawUtil::angleComposition(lineAngle, pi); } Base::Vector2d arcPoint; @@ -1779,7 +1785,7 @@ void QGIViewDimension::drawAreaExecutive(const Base::Vector2d& centerPoint, doub labelRectangle.Height() * 0.5 + getIsoDimensionLineSpacing(), lineAngle, labelAngle); - lineAngle = lineAngle - M_PI; + lineAngle = lineAngle - std::numbers::pi; double labelPosition = -cos(devAngle) * ((labelCenter - centerPoint).Length()); drawDimensionLine(areaPath, centerPoint, lineAngle, 0.0, labelPosition, labelRectangle, 1, standardStyle, flipArrow, forcePointStyle); @@ -1818,7 +1824,7 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension* dimension, lineAngle = 0.0; } else if (strcmp(dimensionType, "DistanceY") == 0) { - lineAngle = M_PI_2; + lineAngle = std::numbers::pi/2; } else { lineAngle = (fromQtApp(linePoints.second()) - fromQtApp(linePoints.first())).Angle(); @@ -1831,9 +1837,9 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension* dimension, if (dimension->AngleOverride.getValue()) { drawDistanceOverride(fromQtApp(linePoints.first()), fromQtApp(linePoints.second()), - dimension->LineAngle.getValue() * M_PI / 180.0, labelRectangle, + dimension->LineAngle.getValue() * std::numbers::pi / 180.0, labelRectangle, standardStyle, renderExtent, flipArrows, - dimension->ExtensionAngle.getValue() * M_PI / 180.0); + dimension->ExtensionAngle.getValue() * std::numbers::pi / 180.0); } else { drawDistanceExecutive(fromQtApp(linePoints.extensionLineFirst()), fromQtApp(linePoints.extensionLineSecond()), @@ -1844,6 +1850,8 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension* dimension, void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { + using std::numbers::pi; + Base::BoundBox2d labelRectangle( fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); arcPoints curvePoints = dimension->getArcPoints(); @@ -1858,12 +1866,12 @@ void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension* dimension, - endAngle; if (startRotation != 0.0 && ((startRotation > 0.0) != curvePoints.arcCW)) { - startRotation += curvePoints.arcCW ? +M_2PI : -M_2PI; + startRotation += curvePoints.arcCW ? +2*pi : -2*pi; } } else {// A circle arc covers the whole plane - endAngle = M_PI; - startRotation = -M_2PI; + endAngle = pi; + startRotation = -2*pi; } drawRadiusExecutive( @@ -1875,6 +1883,8 @@ void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension* dimension, void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { + using std::numbers::pi; + Base::BoundBox2d labelRectangle( fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); Base::Vector2d labelCenter(labelRectangle.GetCenter()); @@ -1941,9 +1951,9 @@ void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, int selected = 0; if (compareAngleStraightness( 0.0, - jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngles[0], M_PI) + jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngles[0], pi) : lineAngles[0], - jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngles[1], M_PI) + jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngles[1], pi) : lineAngles[1], strikeFactors[0], strikeFactors[1]) > 0) { @@ -2006,8 +2016,8 @@ void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, Base::Vector2d startPoint(curveCenter); Base::Vector2d endPoint(curveCenter); - if ((lineAngle >= M_PI_4 && lineAngle <= 3.0 * M_PI_4) - || (lineAngle <= -M_PI_4 && lineAngle >= -3.0 * M_PI_4)) { + if ((lineAngle >= pi/4 && lineAngle <= 3.0 * pi/4) + || (lineAngle <= -pi/4 && lineAngle >= -3.0 * pi/4)) { // Horizontal dimension line startPoint.x -= curveRadius; endPoint.x += curveRadius; @@ -2016,10 +2026,10 @@ void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, else {// Vertical dimension line startPoint.y -= curveRadius; endPoint.y += curveRadius; - lineAngle = M_PI_2; + lineAngle = pi/2; } - // lineAngle = DrawUtil::angleComposition((labelCenter - curveCenter).Angle(), +M_PI_2); + // lineAngle = DrawUtil::angleComposition((labelCenter - curveCenter).Angle(), +pi/2); // startPoint = curveCenter - Base::Vector2d::FromPolar(curveRadius, lineAngle); // endPoint = curveCenter + Base::Vector2d::FromPolar(curveRadius, lineAngle); @@ -2031,8 +2041,8 @@ void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, ? ViewProviderDimension::REND_EXTENT_REDUCED : ViewProviderDimension::REND_EXTENT_NORMAL; - drawRadiusExecutive(curveCenter, Rez::guiX(curvePoints.midArc, true), curveRadius, M_PI, - -M_2PI, labelRectangle, getDefaultExtensionLineOverhang(), + drawRadiusExecutive(curveCenter, Rez::guiX(curvePoints.midArc, true), curveRadius, pi, + -2*pi, labelRectangle, getDefaultExtensionLineOverhang(), standardStyle, renderExtent, flipArrows); } } @@ -2040,6 +2050,8 @@ void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, void QGIViewDimension::drawAngle(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { + using std::numbers::pi; + QPainterPath anglePath; Base::BoundBox2d labelRectangle( @@ -2105,11 +2117,11 @@ void QGIViewDimension::drawAngle(TechDraw::DrawViewDimension* dimension, jointRotations[1] = handednessFactor * (jointAngles[1] - endAngle); // Compare the offset with half of the rest of 2PI minus the angle and eventually fix the values - if (fabs(jointRotations[0] - startRotation * 0.5) > M_PI) { - jointRotations[0] += jointRotations[0] < 0.0 ? +M_2PI : -M_2PI; + if (fabs(jointRotations[0] - startRotation * 0.5) > pi) { + jointRotations[0] += jointRotations[0] < 0.0 ? +2*pi : -2*pi; } - if (fabs(jointRotations[1] - startRotation * 0.5) > M_PI) { - jointRotations[1] += jointRotations[1] < 0.0 ? +M_2PI : -M_2PI; + if (fabs(jointRotations[1] - startRotation * 0.5) > pi) { + jointRotations[1] += jointRotations[1] < 0.0 ? +2*pi : -2*pi; } // Compute the strike factors so we can choose the placement where value is not obscured by dimensional arc @@ -2133,9 +2145,9 @@ void QGIViewDimension::drawAngle(TechDraw::DrawViewDimension* dimension, if (compareAngleStraightness( 0.0, DrawUtil::angleComposition( - jointAngles[0], handednessFactor * jointRotations[0] > 0.0 ? -M_PI_2 : +M_PI_2), + jointAngles[0], handednessFactor * jointRotations[0] > 0.0 ? -pi/2 : +pi/2), DrawUtil::angleComposition( - jointAngles[1], handednessFactor * jointRotations[1] > 0.0 ? -M_PI_2 : +M_PI_2), + jointAngles[1], handednessFactor * jointRotations[1] > 0.0 ? -pi/2 : +pi/2), strikeFactors[0], strikeFactors[1]) > 0) { selected = 1; @@ -2160,10 +2172,10 @@ void QGIViewDimension::drawAngle(TechDraw::DrawViewDimension* dimension, Base::Vector2d labelDirection(labelCenter - angleVertex); double radiusAngle = labelDirection.Angle(); - labelAngle = DrawUtil::angleComposition(radiusAngle, M_PI_2); + labelAngle = DrawUtil::angleComposition(radiusAngle, pi/2); double placementFactor = getIsoStandardLinePlacement(labelAngle); labelAngle = - placementFactor > 0.0 ? DrawUtil::angleComposition(labelAngle, M_PI) : labelAngle; + placementFactor > 0.0 ? DrawUtil::angleComposition(labelAngle, pi) : labelAngle; arcRadius = labelDirection.Length() - placementFactor @@ -2290,22 +2302,23 @@ Base::Vector3d QGIViewDimension::findIsoExt(Base::Vector3d dir) const Base::Vector3d isoYr(0.866, -0.5, 0.0); //iso +Y? Base::Vector3d isoZ(0.0, 1.0, 0.0); //iso Z Base::Vector3d isoZr(0.0, -1.0, 0.0); //iso -Z - if (dir.IsEqual(isoX, FLT_EPSILON)) { + constexpr float floatEpsilon = std::numeric_limits::epsilon(); + if (dir.IsEqual(isoX, floatEpsilon)) { return isoY; } - else if (dir.IsEqual(-isoX, FLT_EPSILON)) { + else if (dir.IsEqual(-isoX, floatEpsilon)) { return -isoY; } - else if (dir.IsEqual(isoY, FLT_EPSILON)) { + else if (dir.IsEqual(isoY, floatEpsilon)) { return isoZ; } - else if (dir.IsEqual(-isoY, FLT_EPSILON)) { + else if (dir.IsEqual(-isoY, floatEpsilon)) { return -isoZ; } - else if (dir.IsEqual(isoZ, FLT_EPSILON)) { + else if (dir.IsEqual(isoZ, floatEpsilon)) { return isoX; } - else if (dir.IsEqual(-isoZ, FLT_EPSILON)) { + else if (dir.IsEqual(-isoZ, floatEpsilon)) { return -isoX; } @@ -2454,11 +2467,11 @@ void QGIViewDimension::setPens() aHead2->setWidth(m_lineWidth); } -double QGIViewDimension::toDeg(double angle) { return angle * 180 / M_PI; } +double QGIViewDimension::toDeg(double angle) { return angle * 180 / std::numbers::pi; } double QGIViewDimension::toQtRad(double angle) { return -angle; } -double QGIViewDimension::toQtDeg(double angle) { return -angle * 180.0 / M_PI; } +double QGIViewDimension::toQtDeg(double angle) { return -angle * 180.0 / std::numbers::pi; } void QGIViewDimension::makeMarkC(double xPos, double yPos, QColor color) const { diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index d0259a66bb..30d395be52 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -964,7 +964,7 @@ void QGIViewPart::drawHighlight(TechDraw::DrawViewDetail* viewDetail, bool b) highlight->setPos(0.0, 0.0);//sb setPos(center.x, center.y)? Base::Vector3d center = viewDetail->AnchorPoint.getValue() * viewPart->getScale(); - double rotationRad = viewPart->Rotation.getValue() * M_PI / 180.0; + double rotationRad = viewPart->Rotation.getValue() * std::numbers::pi / 180.0; center.RotateZ(rotationRad); double radius = viewDetail->Radius.getValue() * viewPart->getScale(); diff --git a/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp b/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp index 436fcfac3e..51e785053c 100644 --- a/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp +++ b/src/Mod/TechDraw/Gui/QGIWeldSymbol.cpp @@ -549,7 +549,7 @@ std::pair QGIWeldSymbol::getLocalAxes() { auto localX = getLeader()->lastSegmentDirection(); auto localY = DU::invertY(localX); - localY.RotateZ(M_PI_2); + localY.RotateZ(std::numbers::pi/2); localY.Normalize(); localY = DU::invertY(localY); return {localX, localY}; diff --git a/src/Mod/TechDraw/Gui/QGTracker.cpp b/src/Mod/TechDraw/Gui/QGTracker.cpp index 8f796a33c9..c1313ded2b 100644 --- a/src/Mod/TechDraw/Gui/QGTracker.cpp +++ b/src/Mod/TechDraw/Gui/QGTracker.cpp @@ -54,7 +54,8 @@ using namespace TechDrawGui; QGTracker::QGTracker(QGSPage* inScene, TrackerMode m): m_sleep(false), m_qgParent(nullptr), - m_lastClick(QPointF(FLT_MAX, FLT_MAX)) + m_lastClick(QPointF(std::numeric_limits::max(), + std::numeric_limits::max())) { setTrackerMode(m); if (inScene) { @@ -183,7 +184,7 @@ QPointF QGTracker::snapToAngle(QPointF dumbPt) return dumbPt; QPointF result(dumbPt); - double angleIncr = M_PI / 8.0; //15* + double angleIncr = std::numbers::pi / 8.0; //15* //mirror last clicked point and event point to get sensible coords QPointF last(m_points.back().x(), -m_points.back().y()); QPointF pt(dumbPt.x(), -dumbPt.y()); @@ -192,7 +193,7 @@ QPointF QGTracker::snapToAngle(QPointF dumbPt) QPointF qVec = last - pt; //vec from end of track to end of tail double actual = atan2(-qVec.y(), qVec.x()); if (actual < 0.0) { - actual = (2 * M_PI) + actual; //map to +ve angle + actual = (2 * std::numbers::pi) + actual; //map to +ve angle } double intPart; diff --git a/src/Mod/TechDraw/Gui/TaskComplexSection.cpp b/src/Mod/TechDraw/Gui/TaskComplexSection.cpp index 30eab5653a..c19a4a500d 100644 --- a/src/Mod/TechDraw/Gui/TaskComplexSection.cpp +++ b/src/Mod/TechDraw/Gui/TaskComplexSection.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #endif// #ifndef _PreComp_ #include @@ -193,7 +194,7 @@ void TaskComplexSection::setUiEdit() ui->leBaseView->setText(QString::fromStdString(m_baseView->getNameInDocument())); Base::Vector3d projectedViewDirection = m_baseView->projectPoint(sectionNormalVec, false); double viewAngle = atan2(-projectedViewDirection.y, -projectedViewDirection.x); - m_compass->setDialAngle(viewAngle * 180.0 / M_PI); + m_compass->setDialAngle(viewAngle * 180.0 / std::numbers::pi); m_viewDirectionWidget->setValueNoNotify(projectedViewDirection * -1.0); } else { @@ -308,7 +309,7 @@ void TaskComplexSection::slotViewDirectionChanged(Base::Vector3d newDirection) } projectedViewDirection.Normalize(); double viewAngle = atan2(projectedViewDirection.y, projectedViewDirection.x); - m_compass->setDialAngle(viewAngle * 180.0 / M_PI); + m_compass->setDialAngle(viewAngle * 180.0 / std::numbers::pi); checkAll(false); applyAligned(); } @@ -318,7 +319,7 @@ void TaskComplexSection::slotViewDirectionChanged(Base::Vector3d newDirection) void TaskComplexSection::slotChangeAngle(double newAngle) { // Base::Console().Message("TCS::slotAngleChanged(%.3f)\n", newAngle); - double angleRadians = newAngle * M_PI / 180.0; + double angleRadians = newAngle * std::numbers::pi / 180.0; double unitX = cos(angleRadians); double unitY = sin(angleRadians); Base::Vector3d localUnit(unitX, unitY, 0.0); diff --git a/src/Mod/TechDraw/Gui/TaskCosmeticLine.cpp b/src/Mod/TechDraw/Gui/TaskCosmeticLine.cpp index 5b83340515..11cea7d77a 100644 --- a/src/Mod/TechDraw/Gui/TaskCosmeticLine.cpp +++ b/src/Mod/TechDraw/Gui/TaskCosmeticLine.cpp @@ -113,7 +113,7 @@ void TaskCosmeticLine::setUiPrimary() setWindowTitle(QObject::tr("Create Cosmetic Line")); // double rotDeg = m_partFeat->Rotation.getValue(); - // double rotRad = rotDeg * M_PI / 180.0; + // double rotRad = rotDeg * std::numbers::pi / 180.0; Base::Vector3d centroid = m_partFeat->getCurrentCentroid(); Base::Vector3d p1, p2; if (m_is3d.front()) { diff --git a/src/Mod/TechDraw/Gui/TaskDimension.cpp b/src/Mod/TechDraw/Gui/TaskDimension.cpp index 4da35c5c67..f3794c9c9c 100644 --- a/src/Mod/TechDraw/Gui/TaskDimension.cpp +++ b/src/Mod/TechDraw/Gui/TaskDimension.cpp @@ -227,7 +227,7 @@ void TaskDimension::onEqualToleranceChanged() ui->leFormatSpecifierUnderTolerance->setDisabled(true); } else { - ui->qsbOvertolerance->setMinimum(-DBL_MAX); + ui->qsbOvertolerance->setMinimum(-std::numeric_limits::max()); if (!ui->cbTheoreticallyExact->isChecked()) { ui->qsbUndertolerance->setDisabled(false); ui->leFormatSpecifierUnderTolerance->setDisabled(false); @@ -372,14 +372,14 @@ void TaskDimension::onDimUseDefaultClicked() Base::Vector2d first2(points.first().x, -points.first().y); Base::Vector2d second2(points.second().x, -points.second().y); double lineAngle = (second2 - first2).Angle(); - ui->dsbDimAngle->setValue(lineAngle * 180.0 / M_PI); + ui->dsbDimAngle->setValue(lineAngle * 180.0 / std::numbers::pi); } void TaskDimension::onDimUseSelectionClicked() { std::pair result = getAngleFromSelection(); if (result.second) { - ui->dsbDimAngle->setValue(result.first * 180.0 / M_PI); + ui->dsbDimAngle->setValue(result.first * 180.0 / std::numbers::pi); } } @@ -392,13 +392,13 @@ void TaskDimension::onExtUseDefaultClicked() Base::Vector2d lineDirection = second2 - first2; Base::Vector2d extensionDirection(-lineDirection.y, lineDirection.x); double extensionAngle = extensionDirection.Angle(); - ui->dsbExtAngle->setValue(extensionAngle * 180.0 / M_PI); + ui->dsbExtAngle->setValue(extensionAngle * 180.0 / std::numbers::pi); } void TaskDimension::onExtUseSelectionClicked() { std::pair result = getAngleFromSelection(); if (result.second) { - ui->dsbExtAngle->setValue(result.first * 180.0 / M_PI); + ui->dsbExtAngle->setValue(result.first * 180.0 / std::numbers::pi); } } diff --git a/src/Mod/TechDraw/Gui/TaskSectionView.cpp b/src/Mod/TechDraw/Gui/TaskSectionView.cpp index 8cceb4eea7..3169ff543e 100644 --- a/src/Mod/TechDraw/Gui/TaskSectionView.cpp +++ b/src/Mod/TechDraw/Gui/TaskSectionView.cpp @@ -180,7 +180,7 @@ void TaskSectionView::setUiEdit() Base::Vector3d projectedViewDirection = m_base->projectPoint(sectionNormalVec, false); projectedViewDirection.Normalize(); double viewAngle = atan2(-projectedViewDirection.y, -projectedViewDirection.x); - m_compass->setDialAngle(viewAngle * 180.0 / M_PI); + m_compass->setDialAngle(viewAngle * 180.0 / std::numbers::pi); m_viewDirectionWidget->setValueNoNotify(sectionNormalVec * -1.0); } @@ -272,7 +272,7 @@ void TaskSectionView::slotViewDirectionChanged(Base::Vector3d newDirection) Base::Vector3d projectedViewDirection = m_base->projectPoint(newDirection, false); projectedViewDirection.Normalize(); double viewAngle = atan2(projectedViewDirection.y, projectedViewDirection.x); - m_compass->setDialAngle(viewAngle * 180.0 / M_PI); + m_compass->setDialAngle(viewAngle * 180.0 / std::numbers::pi); checkAll(false); directionChanged(true); applyAligned(); @@ -281,7 +281,7 @@ void TaskSectionView::slotViewDirectionChanged(Base::Vector3d newDirection) //the CompassWidget reports that the view direction angle has changed void TaskSectionView::slotChangeAngle(double newAngle) { - double angleRadians = newAngle * M_PI / 180.0; + double angleRadians = newAngle * std::numbers::pi / 180.0; double unitX = cos(angleRadians); double unitY = sin(angleRadians); Base::Vector3d localUnit(unitX, unitY, 0.0); diff --git a/src/Mod/TechDraw/Gui/ViewProviderCosmeticExtension.cpp b/src/Mod/TechDraw/Gui/ViewProviderCosmeticExtension.cpp index 8359f8a490..6a18181eb5 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderCosmeticExtension.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderCosmeticExtension.cpp @@ -24,10 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# ifdef _MSC_VER -# define _USE_MATH_DEFINES -# include -# endif //_MSC_VER +# include #endif #include diff --git a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp index c186079a6c..311e885f5d 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp @@ -28,7 +28,6 @@ #include #endif -#include #include #include @@ -404,7 +403,7 @@ void ViewProviderDrawingView::stackTop() //no view, nothing to stack return; } - int maxZ = INT_MIN; + int maxZ = std::numeric_limits::min(); auto parent = qView->parentItem(); if (parent) { //if we have a parentItem, we have to stack within the parentItem, not within the page @@ -439,7 +438,7 @@ void ViewProviderDrawingView::stackBottom() //no view, nothing to stack return; } - int minZ = INT_MAX; + int minZ = std::numeric_limits::max(); auto parent = qView->parentItem(); if (parent) { //if we have a parentItem, we have to stack within the parentItem, not within the page From f773550a47f3214afe31e03f8126f9ca813ce949 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:03:03 +0100 Subject: [PATCH 058/316] Tools: Use std::numeric_limits and std::numbers instead of defines --- src/Tools/plugins/widget/customwidgets.cpp | 41 +++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Tools/plugins/widget/customwidgets.cpp b/src/Tools/plugins/widget/customwidgets.cpp index 0f9107619a..b5e5dec404 100644 --- a/src/Tools/plugins/widget/customwidgets.cpp +++ b/src/Tools/plugins/widget/customwidgets.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include "customwidgets.h" @@ -449,8 +448,8 @@ ActionSelector::~ActionSelector() InputField::InputField(QWidget* parent) : QLineEdit(parent) , Value(0) - , Maximum(INT_MAX) - , Minimum(-INT_MAX) + , Maximum(std::numeric_limits::max()) + , Minimum(-std::numeric_limits::max()) , StepSize(1.0) , HistorySize(5) {} @@ -671,8 +670,8 @@ public: : validInput(true) , pendingEmit(false) , unitValue(0) - , maximum(INT_MAX) - , minimum(-INT_MAX) + , maximum(std::numeric_limits::max()) + , minimum(-std::numeric_limits::max()) , singleStep(1.0) {} ~QuantitySpinBoxPrivate() @@ -1459,7 +1458,7 @@ UnsignedValidator::UnsignedValidator(QObject* parent) : QValidator(parent) { b = 0; - t = UINT_MAX; + t = std::numeric_limits::max(); } UnsignedValidator::UnsignedValidator(uint minimum, uint maximum, QObject* parent) @@ -1522,39 +1521,41 @@ public: {} uint mapToUInt(int v) const { + using limits = std::numeric_limits; uint ui; - if (v == INT_MIN) { + if (v == limits::min()) { ui = 0; } - else if (v == INT_MAX) { - ui = UINT_MAX; + else if (v == limits::max()) { + ui = limits::max(); } else if (v < 0) { - v -= INT_MIN; - ui = (uint)v; + v -= limits::min(); + ui = static_cast(v); } else { - ui = (uint)v; - ui -= INT_MIN; + ui = static_cast(v); + ui -= limits::min(); } return ui; } int mapToInt(uint v) const { + using limits = std::numeric_limits; int in; - if (v == UINT_MAX) { - in = INT_MAX; + if (v == limits::max()) { + in = limits::max(); } else if (v == 0) { - in = INT_MIN; + in = limits::min(); } - else if (v > INT_MAX) { - v += INT_MIN; - in = (int)v; + else if (v > limits::max()) { + v += limits::min(); + in = static_cast(v); } else { in = v; - in += INT_MIN; + in += limits::min(); } return in; } From 8d228090de252f4b69df69ce86b4f7e7a4b6cd21 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 27 Mar 2025 19:50:28 +0100 Subject: [PATCH 059/316] Web: Use std::numeric_limits and std::numbers instead of defines --- src/Mod/Web/App/AppWeb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Web/App/AppWeb.cpp b/src/Mod/Web/App/AppWeb.cpp index d89e3ef568..54b2a9ebbc 100644 --- a/src/Mod/Web/App/AppWeb.cpp +++ b/src/Mod/Web/App/AppWeb.cpp @@ -89,7 +89,7 @@ private: if (!PyArg_ParseTuple(args.ptr(), "|si", &addr, &port)) { throw Py::Exception(); } - if (port > USHRT_MAX) { + if (port > std::numeric_limits::max()) { throw Py::OverflowError("port number is greater than maximum"); } else if (port < 0) { @@ -121,7 +121,7 @@ private: if (!PyArg_ParseTuple(args.ptr(), "|sii", &addr, &port, &timeout)) { throw Py::Exception(); } - if (port > USHRT_MAX) { + if (port > std::numeric_limits::max()) { throw Py::OverflowError("port number is greater than maximum"); } else if (port < 0) { From b263b407ed9ed703c0f39332611a6ceeb8842caf Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Thu, 27 Mar 2025 16:37:18 +0100 Subject: [PATCH 060/316] [Doc] Improve the main page for WebDoc For the web version, the main page has improved with more information about the organization with respect to the topics. The most important topics are listed prominently on the main page as well. --- src/Doc/mainpage.dox.in | 126 +++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 39 deletions(-) diff --git a/src/Doc/mainpage.dox.in b/src/Doc/mainpage.dox.in index 5ab0e6c5dc..d3803f155f 100644 --- a/src/Doc/mainpage.dox.in +++ b/src/Doc/mainpage.dox.in @@ -22,64 +22,112 @@ /** - \mainpage FreeCAD source documentation + @mainpage FreeCAD Source Documentation - This is the source documentation of FreeCAD. - It is automatically generated from the source code, and describes the different - components of the FreeCAD source code, for both the parts written in C++ and Python. - - For general help and documentation about the FreeCAD application and how to use it, head - first to the Wiki Documentation. - - Refer to the - general - introduction to the FreeCAD source code page for a broad view of how the source - code is organized, and browse the modules, classes and namespaces from the menu above. - - The Developers section - of the wiki also contains additional information for developers, and the - Powerusers / python scripting - section contains coding documentation that is specifically aimed at python scripting, but - that will also be useful to C++ coders, as most of the APIs are identical or very similar. - - For space reasons, this on-line version doesn't include the source code headers nor the full - inheritance graphics. But you can build a full version yourself with everything included, - as explained in building - the source code documentation. You can also browse through the source - code on github. + @section toc Table of Contents + - @ref intro_main "Introduction" + - @ref organization "Organization of the API Documentation" + - @ref other_doc "Other Documentation" - \if DEV_DOCUMENTATION + @section intro_main Introduction - \mainpage FreeCAD source documentation + This is the source documentation of [FreeCAD](https://www.freecad.org). It + is automatically generated from the source code and describes the different + components of the FreeCAD source code, for both the parts written in C++ + and Python. The next section discusses the organization of this API + documentation and the last section describes other forms of documentation + that FreeCAD has. + + @section organization Organization of the API Documentation + + This documentation is divided into several topics of which the most important are: + - @ref CORE "Core" + - @ref BASE "Base" + - @ref APP "App" + - @ref GUI "Gui" + - @ref WORKBENCHES "Workbenches" + - @ref EMBEDDED "Embedded 3rd party packages" + + Firstly, topic @ref CORE "Core" contains the core namespaces and classes + that all of FreeCAD relies on. This consists of namespace %Base (see topic + @ref BASE "Base") that contains fundamental base classes, the namespace + %App (see topic @ref APP "App") that contains classes for FreeCAD in + command-line mode, and namespace %Gui (see topic @ref GUI "Gui") that + contains the classes for FreeCAD's GUI. + + FreeCAD is highly modular and most of its functionality is within modules + that are called @ref WORKBENCHES "Workbenches". Workbenches can be written + in C++ or Python or in a combination of the two. FreeCAD also has external + workbenches that can be loaded from the Addon Manager. These external + workbenches need to be written in Python. + + Finally, there is the topic @ref EMBEDDED "Embedded 3rd party packages" + that contains 3rd-party software of which the source is embedded in + FreeCAD. This means that during compilation, these packages will be + compiled and linked to FreeCAD as opposed to non-embedded 3rd-party + packages that are only linked to FreeCAD. An example of an important + non-embedded 3rd party software package is [Open CASCADE + Technology](https://dev.opencascade.org/doc/overview/html/). Its API + documentation can be found + [here](https://dev.opencascade.org/doc/refman/html/index.html). + + @section other_doc Other Documentation + + For general help and documentation about the FreeCAD application and how to + use it, head first to the [Wiki Documentation](https://www.freecad.org/wiki). + + Refer to the [Wiki page "The FreeCAD source + code"](https://www.freecad.org/wiki/The_FreeCAD_source_code) for a broad + view of how the source code is organized, and browse the modules, classes + and namespaces from the menu above. + + The [Developer hub](https://www.freecad.org/wiki/Developer_hub) of the wiki + contains additional information for developers and the [Power users / + Python scripting section](https://www.freecad.org/wiki/Power_users_hub) + contains coding documentation that is specifically aimed at Python + scripting, but that will also be useful to C++ coders, as most of the APIs + are identical or very similar. + + For space reasons, this on-line version doesn't include the source code + headers nor the full inheritance graphics. But you can build a full version + yourself with everything included, as explained in Wiki page [Source + documentation](https://wiki.freecad.org/Source_documentation#Complete_documentation). You + can also browse through the [source code on + GitHub](https://github.com/FreeCAD/FreeCAD). + + @if DEV_DOCUMENTATION + + @mainpage FreeCAD source documentation + + @image html freecadsplash.png - \image html freecadsplash.png - Welcome to FreeCAD source documentation! - + We hope you'll find it a convenient tool to explore, understand and experiment with the internals of the program. - + Being generated from the actual state of the code, this documentation is by no means a well structured corpus or a textbook, but more an utility to browse through the sources. - + If you seek information on FreeCAD at large, please consult our Wiki - + FreeCAD being a fast moving target, don't hesitate to rebuild an up to date doc from source as often as needed (\ref makingdocs "more info"). CPU cycles are cheap - nowadays! - + nowadays! + The homepage of FreeCAD is here. - - \endif + + @endif @GIT_REVISION_INFO@ */ -/** \namespace std - \brief The Standard namespace for the C++ library -*/ +/** + * @namespace std + * @brief The Standard namespace for the C++ library + */ From caab5fba78a71afa918046ff276690f936cb1a37 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 29 Mar 2025 17:44:03 +0100 Subject: [PATCH 061/316] Gui: Fix saving light sources --- .../PreferencePages/DlgSettingsLightSources.ui | 16 ++++++++-------- src/Gui/View3DSettings.cpp | 5 +++++ src/Gui/View3DSettings.h | 2 ++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Gui/PreferencePages/DlgSettingsLightSources.ui b/src/Gui/PreferencePages/DlgSettingsLightSources.ui index 6c09e0ec81..59f516abd5 100644 --- a/src/Gui/PreferencePages/DlgSettingsLightSources.ui +++ b/src/Gui/PreferencePages/DlgSettingsLightSources.ui @@ -164,7 +164,7 @@ AmbientLightIntensity
- View + View/LightSources
@@ -181,7 +181,7 @@ BacklightColor
- View + View/LightSources
@@ -267,7 +267,7 @@ AmbientLightColor - View + View/LightSources @@ -293,7 +293,7 @@ HeadlightIntensity - View + View/LightSources @@ -332,7 +332,7 @@ BacklightIntensity - View + View/LightSources @@ -367,7 +367,7 @@ FillLightIntensity - View + View/LightSources @@ -404,7 +404,7 @@ FillLightColor - View + View/LightSources @@ -431,7 +431,7 @@ HeadlightColor - View + View/LightSources diff --git a/src/Gui/View3DSettings.cpp b/src/Gui/View3DSettings.cpp index b625158f0d..9bd0669627 100644 --- a/src/Gui/View3DSettings.cpp +++ b/src/Gui/View3DSettings.cpp @@ -45,22 +45,27 @@ using namespace Gui; View3DSettings::View3DSettings(ParameterGrp::handle hGrp, View3DInventorViewer* view) : hGrp(hGrp) + , hLightSourcesGrp(hGrp->GetGroup("LightSources")) , _viewers{view} { hGrp->Attach(this); + hLightSourcesGrp->Attach(this); } View3DSettings::View3DSettings(ParameterGrp::handle hGrp, const std::vector& view) : hGrp(hGrp) + , hLightSourcesGrp(hGrp->GetGroup("LightSources")) , _viewers(view) { hGrp->Attach(this); + hLightSourcesGrp->Attach(this); } View3DSettings::~View3DSettings() { hGrp->Detach(this); + hLightSourcesGrp->Detach(this); } int View3DSettings::stopAnimatingIfDeactivated() const diff --git a/src/Gui/View3DSettings.h b/src/Gui/View3DSettings.h index 0bc7f3af6d..ccef176218 100644 --- a/src/Gui/View3DSettings.h +++ b/src/Gui/View3DSettings.h @@ -54,6 +54,8 @@ public: private: ParameterGrp::handle hGrp; + ParameterGrp::handle hLightSourcesGrp; + std::vector _viewers; }; From 031720693018ee4884c32abdf2a6cce960e1b1d3 Mon Sep 17 00:00:00 2001 From: ashimabu <67717920+ashimabu@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:25:58 -0700 Subject: [PATCH 062/316] Sketcher: Explicitly check fullyConstrainedChanged on solve (#20236) --- src/Mod/Sketcher/App/SketchObject.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 64b717d48d..ced32138b6 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -600,8 +600,9 @@ int SketchObject::solve(bool updateGeoAfterSolving /*=true*/) Part::PropertyGeometryList tmp; tmp.setValues(std::move(geomlist)); // Only set values if there is actual changes - if (!Geometry.isSame(tmp)) + if (Constraints.isTouched() || !Geometry.isSame(tmp)) { Geometry.moveValues(std::move(tmp)); + } } } else if (err < 0) { From e33b427224047998064cf1b6c0322637420d7ba5 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 22 Mar 2025 18:23:23 -0500 Subject: [PATCH 063/316] Fem: Remove unused variables --- src/Mod/Fem/App/FemPostBranchFilter.h | 1 - src/Mod/Fem/App/FemPostPipeline.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Mod/Fem/App/FemPostBranchFilter.h b/src/Mod/Fem/App/FemPostBranchFilter.h index 7d483ff0a5..f07f0dd3f8 100644 --- a/src/Mod/Fem/App/FemPostBranchFilter.h +++ b/src/Mod/Fem/App/FemPostBranchFilter.h @@ -64,7 +64,6 @@ protected: private: static const char* OutputEnums[]; - bool m_transform_used = false; void setupPipeline(); vtkSmartPointer m_append; diff --git a/src/Mod/Fem/App/FemPostPipeline.h b/src/Mod/Fem/App/FemPostPipeline.h index 6c96b6dbae..c56d37ad01 100644 --- a/src/Mod/Fem/App/FemPostPipeline.h +++ b/src/Mod/Fem/App/FemPostPipeline.h @@ -133,7 +133,6 @@ private: bool m_block_property = false; bool m_data_updated = false; - bool m_use_transform = false; void updateData(); From 0f4f47e313c37b16287ab84750d54d0136f6726c Mon Sep 17 00:00:00 2001 From: Andrea Date: Mon, 24 Mar 2025 23:46:13 +0100 Subject: [PATCH 064/316] [Mod] assembly clean clean code --- src/Mod/Assembly/App/AssemblyLink.cpp | 23 ------ src/Mod/Assembly/App/AssemblyObject.cpp | 8 -- src/Mod/Assembly/App/AssemblyObject.h | 4 - src/Mod/Assembly/App/AssemblyUtils.cpp | 102 +----------------------- src/Mod/Assembly/App/AssemblyUtils.h | 1 - 5 files changed, 1 insertion(+), 137 deletions(-) diff --git a/src/Mod/Assembly/App/AssemblyLink.cpp b/src/Mod/Assembly/App/AssemblyLink.cpp index 52607d3180..7df49b12e7 100644 --- a/src/Mod/Assembly/App/AssemblyLink.cpp +++ b/src/Mod/Assembly/App/AssemblyLink.cpp @@ -159,7 +159,6 @@ void AssemblyLink::onChanged(const App::Property* prop) propPlc->setValue(movePlc); } } - return; } App::Part::onChanged(prop); @@ -175,7 +174,6 @@ void AssemblyLink::updateContents() else { synchronizeJoints(); } - purgeTouched(); } @@ -220,7 +218,6 @@ void AssemblyLink::synchronizeComponents() continue; } - if (linkedObj == obj) { found = true; link = obj2; @@ -272,24 +269,6 @@ void AssemblyLink::synchronizeComponents() if (objLinkMap.find(link) != objLinkMap.end()) { doc->removeObject(link->getNameInDocument()); } - - /*if (!link->isDerivedFrom() && !link->isDerivedFrom()) { - // AssemblyLink should contain only Links or assembly links. - continue; - } - - auto* linkedObj = link->getLinkedObject(false); // not recursive - - bool found = false; - for (auto* obj2 : assemblyGroup) { - if (obj2 == linkedObj) { - found = true; - break; - } - } - if (!found) { - doc->removeObject(link->getNameInDocument()); - }*/ } } @@ -567,7 +546,6 @@ bool AssemblyLink::isRigid() if (!prop) { return true; } - return prop->getValue(); } @@ -578,6 +556,5 @@ std::vector AssemblyLink::getJoints() if (!jointGroup) { return {}; } - return jointGroup->getJoints(); } diff --git a/src/Mod/Assembly/App/AssemblyObject.cpp b/src/Mod/Assembly/App/AssemblyObject.cpp index a7164bad36..910101a8bf 100644 --- a/src/Mod/Assembly/App/AssemblyObject.cpp +++ b/src/Mod/Assembly/App/AssemblyObject.cpp @@ -158,7 +158,6 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS) } try { - // mbdAssembly->runPreDrag(); // solve() is causing some issues with limits. mbdAssembly->runKINEMATIC(); } catch (const std::exception& e) { @@ -198,7 +197,6 @@ int AssemblyObject::generateSimulation(App::DocumentObject* sim) create_mbdSimulationParameters(sim); - try { mbdAssembly->runKINEMATIC(); } @@ -384,7 +382,6 @@ bool AssemblyObject::validateNewPlacements() // TODO: We could do further tests // For example check if the joints connectors are correctly aligned. - return true; } @@ -593,7 +590,6 @@ App::DocumentObject* AssemblyObject::getJointOfPartConnectingToGround(App::Docum return joint; } } - return nullptr; } @@ -753,7 +749,6 @@ std::vector AssemblyObject::getJointsOfPart(App::DocumentO jointsOf.push_back(joint); } } - return jointsOf; } @@ -1804,7 +1799,6 @@ AssemblyObject::MbDPartData AssemblyObject::getMbDData(App::DocumentObject* part addConnectedFixedParts(part, addConnectedFixedParts); } - return data; } @@ -1813,7 +1807,6 @@ std::shared_ptr AssemblyObject::getMbDPart(App::DocumentObject* part) if (!part) { return nullptr; } - return getMbDData(part).part; } @@ -1831,7 +1824,6 @@ AssemblyObject::makeMbdPart(std::string& name, Base::Placement plc, double mass) Base::Vector3d pos = plc.getPosition(); mbdPart->setPosition3D(pos.x, pos.y, pos.z); - // Base::Console().Warning("MbD Part placement : (%f, %f, %f)\n", pos.x, pos.y, pos.z); // TODO : replace with quaternion to simplify Base::Rotation rot = plc.getRotation(); diff --git a/src/Mod/Assembly/App/AssemblyObject.h b/src/Mod/Assembly/App/AssemblyObject.h index b8ea59049c..61ceaff796 100644 --- a/src/Mod/Assembly/App/AssemblyObject.h +++ b/src/Mod/Assembly/App/AssemblyObject.h @@ -200,12 +200,8 @@ private: std::vector> previousPositions; bool bundleFixed; - // void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property - // *prop) override; }; -// using AssemblyObjectPython = App::FeaturePythonT; - } // namespace Assembly diff --git a/src/Mod/Assembly/App/AssemblyUtils.cpp b/src/Mod/Assembly/App/AssemblyUtils.cpp index f48eb4dbd7..f665b25613 100644 --- a/src/Mod/Assembly/App/AssemblyUtils.cpp +++ b/src/Mod/Assembly/App/AssemblyUtils.cpp @@ -37,9 +37,8 @@ #include #include #include -// #include #include -// #include + #include #include #include @@ -695,7 +694,6 @@ App::DocumentObject* getMovingPartFromRef(const AssemblyObject* assemblyObject, return obj; } - return nullptr; } @@ -715,7 +713,6 @@ App::DocumentObject* getMovingPartFromRef(const AssemblyObject* assemblyObject, if (subs.empty()) { return nullptr; } - return getMovingPartFromRef(assemblyObject, obj, subs[0]); } @@ -731,102 +728,5 @@ App::DocumentObject* getMovingPartFromRef(const AssemblyObject* assemblyObject, return getMovingPartFromRef(assemblyObject, prop); } -/* -Base::Placement getPlacementFromProp(App::DocumentObject* obj, const char* propName) -{ - Base::Placement plc = Base::Placement(); - auto* propPlacement = dynamic_cast(obj->getPropertyByName(propName)); - if (propPlacement) { - plc = propPlacement->getValue(); - } - return plc; -} - -// Currently unused -Base::Placement* getTargetPlacementRelativeTo( - App::DocumentObject* targetObj, App::DocumentObject* part, App::DocumentObject* container, - bool inContainerBranch, bool ignorePlacement = false) -{ - inContainerBranch = inContainerBranch || (!ignorePlacement && part == container); - - Base::Console().Warning("sub --------------\n"); - if (targetObj == part && inContainerBranch && !ignorePlacement) { - Base::Console().Warning("found0\n"); - return &getPlacementFromProp(targetObj, "Placement"); - } - - if (auto group = dynamic_cast(part)) { - for (auto& obj : group->getOutList()) { - auto foundPlacement = getTargetPlacementRelativeTo( - targetObj, obj, container, inContainerBranch, ignorePlacement - ); - if (foundPlacement != nullptr) { - return foundPlacement; - } - } - } - else if (auto assembly = dynamic_cast(part)) { - Base::Console().Warning("h3\n"); - for (auto& obj : assembly->getOutList()) { - auto foundPlacement = getTargetPlacementRelativeTo( - targetObj, obj, container, inContainerBranch - ); - if (foundPlacement == nullptr) { - continue; - } - - if (!ignorePlacement) { - *foundPlacement = getPlacementFromProp(part, "Placement") * *foundPlacement; - } - - Base::Console().Warning("found\n"); - return foundPlacement; - } - } - else if (auto link = dynamic_cast(part)) { - Base::Console().Warning("h4\n"); - auto linked_obj = link->getLinkedObject(); - - if (dynamic_cast(linked_obj) || dynamic_cast(linked_obj)) { - for (auto& obj : linked_obj->getOutList()) { - auto foundPlacement = getTargetPlacementRelativeTo( - targetObj, obj, container, inContainerBranch - ); - if (foundPlacement == nullptr) { - continue; - } - - *foundPlacement = getPlacementFromProp(link, "Placement") * *foundPlacement; - return foundPlacement; - } - } - - auto foundPlacement = getTargetPlacementRelativeTo( - targetObj, linked_obj, container, inContainerBranch, true - ); - - if (foundPlacement != nullptr && !ignorePlacement) { - *foundPlacement = getPlacementFromProp(link, "Placement") * *foundPlacement; - } - - Base::Console().Warning("found2\n"); - return foundPlacement; - } - - return nullptr; -} - -Base::Placement getGlobalPlacement(App::DocumentObject* targetObj, App::DocumentObject* container = -nullptr) { bool inContainerBranch = container == nullptr; auto rootObjects = -App::GetApplication().getActiveDocument()->getRootObjects(); for (auto& part : rootObjects) { auto -foundPlacement = getTargetPlacementRelativeTo(targetObj, part, container, inContainerBranch); if -(foundPlacement != nullptr) { Base::Placement plc(foundPlacement->toMatrix()); return plc; - } - } - - return Base::Placement(); -} -*/ - } // namespace Assembly diff --git a/src/Mod/Assembly/App/AssemblyUtils.h b/src/Mod/Assembly/App/AssemblyUtils.h index b04145d26b..6fe1e22912 100644 --- a/src/Mod/Assembly/App/AssemblyUtils.h +++ b/src/Mod/Assembly/App/AssemblyUtils.h @@ -25,7 +25,6 @@ #ifndef ASSEMBLY_AssemblyUtils_H #define ASSEMBLY_AssemblyUtils_H - #include #include From 1dc34ffcd42d5ac008e3fa18d25b6ab49a5cb577 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Sat, 29 Mar 2025 20:56:30 +0100 Subject: [PATCH 065/316] Update src/App/ExpressionParser.l Fixes issue in expression parser Co-authored-by: Chris Hennes --- src/App/ExpressionParser.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index bed2fc5f33..937e8393e7 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -343,7 +343,7 @@ EXPO [eE][-+]?[0-9]+ yylval.ivalue = strtoll( yytext, NULL, 10 ); if (yylval.ivalue == std::numeric_limits::min) throw Base::UnderflowError("Integer underflow"); - else if (yylval.ivalue == std::numeric_limits::max) + else if (yylval.ivalue == std::numeric_limits::max()) throw Base::OverflowError("Integer overflow"); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; } From 8145be8c2be287005949837a52c1c3c8fbd0f571 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Sat, 29 Mar 2025 20:56:55 +0100 Subject: [PATCH 066/316] Update src/App/ExpressionParser.l Co-authored-by: Chris Hennes --- src/App/ExpressionParser.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index 937e8393e7..566dab95e0 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -341,7 +341,7 @@ EXPO [eE][-+]?[0-9]+ {DIGIT}+{EXPO} COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}+ { COUNTCHARS; yylval.ivalue = strtoll( yytext, NULL, 10 ); - if (yylval.ivalue == std::numeric_limits::min) + if (yylval.ivalue == std::numeric_limits::min()) throw Base::UnderflowError("Integer underflow"); else if (yylval.ivalue == std::numeric_limits::max()) throw Base::OverflowError("Integer overflow"); From 52317683f7cb048ae176888a77b58fd6bcb99d02 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Mon, 24 Mar 2025 17:23:28 +0100 Subject: [PATCH 067/316] [Doc] Show topics instead of modules --- src/Doc/FreecadDoxygenLayout.xml | 2 +- src/Doc/templates/header.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Doc/FreecadDoxygenLayout.xml b/src/Doc/FreecadDoxygenLayout.xml index 49194389a5..89698cb1d9 100644 --- a/src/Doc/FreecadDoxygenLayout.xml +++ b/src/Doc/FreecadDoxygenLayout.xml @@ -2,7 +2,7 @@ - + diff --git a/src/Doc/templates/header.html b/src/Doc/templates/header.html index 1cce457543..337cceeff0 100644 --- a/src/Doc/templates/header.html +++ b/src/Doc/templates/header.html @@ -34,7 +34,7 @@
  • Index
  • -
  • Modules
  • +
  • Topics
  • Classes
  • From ec4ea7f8d3539c7938701b4f9519b5f24d62c57f Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Mon, 24 Mar 2025 21:02:05 +0100 Subject: [PATCH 068/316] [Doc] Improve topics within App - The location of the documentation is improved (not in the cpp file anymore but in core-app.dox). This prevents cluttering source with high-level overviews typical of topic documentation. - The formatting has been made consistent. --- src/App/Document.cpp | 35 ---------- src/App/DocumentObject.cpp | 4 -- src/App/Expression.cpp | 5 -- src/App/PropertyContainer.cpp | 47 ------------- src/App/core-app.dox | 122 +++++++++++++++++++++++++++++++--- src/Doc/primary-groups.dox | 14 ++-- 6 files changed, 118 insertions(+), 109 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 3b7e3c2ea7..5b22ef1b8a 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -20,41 +20,6 @@ * * ***************************************************************************/ - -/*! -\defgroup Document Document -\ingroup APP -\brief The Base class of the FreeCAD Document - -This (besides the App::Application class) is the most important class in FreeCAD. -It contains all the data of the opened, saved, or newly created FreeCAD Document. -The App::Document manages the Undo and Redo mechanism and the linking of documents. - -\namespace App \class App::Document -This is besides the Application class the most important class in FreeCAD -It contains all the data of the opened, saved or newly created FreeCAD Document. -The Document manage the Undo and Redo mechanism and the linking of documents. - -Note: the documents are not free objects. They are completely handled by the -App::Application. Only the Application can Open or destroy a document. - -\section Exception Exception handling -As the document is the main data structure of FreeCAD we have to take a close -look at how Exceptions affect the integrity of the App::Document. - -\section UndoRedo Undo Redo an Transactions -Undo Redo handling is one of the major mechanism of a document in terms of -user friendliness and speed (no one will wait for Undo too long). - -\section Dependency Graph and dependency handling -The FreeCAD document handles the dependencies of its DocumentObjects with -an adjacence list. This gives the opportunity to calculate the shortest -recompute path. Also, it enables more complicated dependencies beyond trees. - -@see App::Application -@see App::DocumentObject -*/ - #include "PreCompiled.h" #ifndef _PreComp_ diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index bc5d291e7b..df544afd0b 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -55,10 +55,6 @@ FC_LOG_LEVEL_INIT("App", true, true) using namespace App; -/** \defgroup DocObject Document Object - \ingroup APP - \brief Base class of all objects handled in the Document -*/ PROPERTY_SOURCE(App::DocumentObject, App::TransactionalObject) diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index 115db3dd9b..9f16fdbf3a 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -52,11 +52,6 @@ #include "ExpressionParser.h" -/** \defgroup Expression Expressions framework - \ingroup APP - \brief The expression system allows users to write expressions and formulas that produce values -*/ - using namespace Base; using namespace App; diff --git a/src/App/PropertyContainer.cpp b/src/App/PropertyContainer.cpp index cbaac141f1..1b083e8552 100644 --- a/src/App/PropertyContainer.cpp +++ b/src/App/PropertyContainer.cpp @@ -640,50 +640,3 @@ void PropertyData::visitProperties(OffsetBase offsetBase, }; } -/** \defgroup PropFrame Property framework - \ingroup APP - \brief System to access object properties -\section propframe_intro Introduction -The property framework introduces the ability to access attributes (member variables) of a class by name without -knowing the class type. It's like the reflection mechanism of Java or C#. -This ability is introduced by the App::PropertyContainer class and can be used by all derived classes. - -This makes it possible in the first place to make an automatic mapping to python (e.g. in App::FeaturePy) and -abstract editing properties in Gui::PropertyEditor. - -\section Examples - -Here some little examples how to use it: - -\code -// search in PropertyList -Property *prop = _pcFeature->getPropertyByName(attr); -if(prop) -{ - return prop->getPyObject(); -} -\endcode - -or: - -\code -void PropertyContainer::Restore(Base::Reader &reader) -{ - reader.readElement("Properties"); - int Cnt = reader.getAttributeAsInteger("Count"); - - for(int i=0 ;iRestore(reader); - - reader.readEndElement("Property"); - } - reader.readEndElement("Properties"); -} -\endcode - -*/ diff --git a/src/App/core-app.dox b/src/App/core-app.dox index 1a5f38b0e9..a4fc82c12e 100644 --- a/src/App/core-app.dox +++ b/src/App/core-app.dox @@ -1,15 +1,115 @@ -/** \defgroup APP App - * \ingroup CORE - * \brief The part of FreeCAD that works without GUI (console or server mode) -*/ +/** + * @defgroup APP App + * @ingroup CORE + * @brief The part of FreeCAD that works without GUI (console or server mode) + * @details It contains the App namespace and defines core concepts such as + * @ref DocumentGroup "Document", @ref DocObject "Document Object", the @ref + * Expression "Expression Framework", and the @ref PropFrame + * "Property Framework". + */ -/** \namespace App - \ingroup APP - \brief The FreeCAD Application layer +/** + * @defgroup DocumentGroup Document + * @ingroup APP + * @brief The class that represents a FreeCAD document + * + * This (besides the App::Application class) is the most important class in FreeCAD. + * It contains all the data of the opened, saved, or newly created FreeCAD Document. + * The App::Document manages the Undo and Redo mechanism and the linking of documents. + * + * Note: the documents are not free objects. They are completely handled by the + * App::Application. Only the Application can Open or destroy a document. + * + * \section Exception Exception handling + * As the document is the main data structure of FreeCAD we have to take a close + * look at how Exceptions affect the integrity of the App::Document. + * + * \section UndoRedo Undo Redo an Transactions + * Undo Redo handling is one of the major mechanism of a document in terms of + * user friendliness and speed (no one will wait for Undo too long). + * + * \section Dependency Graph and dependency handling + * The FreeCAD document handles the dependencies of its DocumentObjects with + * an adjacency list. This gives the opportunity to calculate the shortest + * recompute path. Also, it enables more complicated dependencies beyond trees. + * + * @see App::Application + * @see App::DocumentObject + */ - This namespace includes Application services of FreeCAD like: - - The Application class - - The Document class +/** + * @defgroup DocObject Document Object + * @ingroup APP + * @brief %Base class of all objects handled in the Document. + */ + +/** + * @defgroup Expression Expressions framework + * @ingroup APP + * @brief The expression system allows users to write expressions and formulas that produce values + */ + +/** + * @defgroup PropFrame Property framework + * @ingroup APP + * @brief System to access object properties. + * + * @section propframe_intro Introduction + * + * The property framework introduces the ability to access attributes (member + * variables) of a class by name without knowing the class type. It's like the + * reflection mechanism of Java or C#. This ability is introduced by the + * App::PropertyContainer class and can be used by all derived classes. + * + * This makes it possible in the first place to make an automatic mapping to python (e.g. in App::FeaturePy) and + * abstract editing properties in Gui::PropertyEditor. + * + * @section Examples + * + * Here some little examples how to use it: + * + * @code + * // search in PropertyList + * Property *prop = _pcFeature->getPropertyByName(attr); + * if(prop) + * { + * return prop->getPyObject(); + * } + * @endcode + * + * or: + * + * @code + * void PropertyContainer::Restore(Base::Reader &reader) + * { + * reader.readElement("Properties"); + * int Cnt = reader.getAttributeAsInteger("Count"); + * + * for(int i=0 ;iRestore(reader); + * + * reader.readEndElement("Property"); + * } + * reader.readEndElement("Properties"); + * } + * @endcode + */ -*/ +/** + * @namespace App + * @ingroup APP + * @brief The namespace for the part of FreeCAD that works without GUI. + * @details This namespace includes %Application services of FreeCAD that such as: + * - The Application class + * - The Document class + * - The DocumentObject classes + * - The Expression classes + * - The Property classes + */ + diff --git a/src/Doc/primary-groups.dox b/src/Doc/primary-groups.dox index 7ec6329e65..d54bdc7504 100644 --- a/src/Doc/primary-groups.dox +++ b/src/Doc/primary-groups.dox @@ -1,15 +1,15 @@ -/** \defgroup CORE Core - These are the core components of FreeCAD. +/** @defgroup CORE Core + The core components of FreeCAD. - It groups the Base classes, and the main components of FreeCAD core, - spread over their App and Gui sides. Core components are programmed in - C++ but provide a broad Python API too. Most of FreeCAD functionality, + FreeCAD's core consists of Base classes, and the main components of FreeCAD + core, spread over their App and Gui sides. Core components are programmed + in C++ but provide a broad Python API too. Most of FreeCAD functionality, however, is defined in Workbenches. */ -/** \defgroup WORKBENCHES Workbenches +/** @defgroup WORKBENCHES Workbenches */ -/** \defgroup EMBEDDED Embedded 3rd party libraries +/** @defgroup EMBEDDED Embedded 3rd party libraries Important tools and libraries incorporated to FreeCAD. */ From 1ba6a40472829cc66ba5d52696f09db89d51078c Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Wed, 26 Mar 2025 17:08:57 +0100 Subject: [PATCH 069/316] [Doc] Add links between topics and relevant items The documentation has topics, for example topic App which contains namespace App or topic Document that contains class Document. This commit makes sure that the topic has a link to the relevant class or namespace, whereas the relevant class or namespace refers back to the topic for a more high-level overview. --- src/App/Document.h | 6 +++++- src/App/DocumentObject.h | 5 ++++- src/App/Expression.h | 11 +++++++---- src/App/Property.h | 17 +++++++++++------ src/App/core-app.dox | 2 ++ 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/App/Document.h b/src/App/Document.h index 369e29377c..dce5b1a553 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -57,7 +57,11 @@ class Transaction; class StringHasher; using StringHasherRef = Base::Reference; -/// The document class +/** + * @brief The document class + * @ingroup DocumentGroup + * @details For a more high-level discussion see the topic @ref DocumentGroup "Document". + */ class AppExport Document: public App::PropertyContainer { PROPERTY_HEADER_WITH_OVERRIDE(App::Document); diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index 860d3af357..bd62977774 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -101,7 +101,10 @@ public: }; -/** Base class of all Classes handled in the Document +/** + * @brief %Base class of all objects handled in the @ref App::Document "Document". + * @ingroup DocObject + * @details For a more high-level overview see topic @ref DocObject "Document Object". */ class AppExport DocumentObject: public App::TransactionalObject { diff --git a/src/App/Expression.h b/src/App/Expression.h index 7ff8352d0c..4455fb60f6 100644 --- a/src/App/Expression.h +++ b/src/App/Expression.h @@ -108,11 +108,14 @@ protected: int _changed{0}; }; -/** - * Base class for expressions. - * - */ +/** + * @brief %Base class for expressions. + * @ingroup Expression + * + * @details For a high-level overview of the %Expression framework see topic + * @ref Expression "Expression Framework". + */ class AppExport Expression : public Base::BaseClass { TYPESYSTEM_HEADER_WITH_OVERRIDE(); diff --git a/src/App/Property.h b/src/App/Property.h index 5448777649..86bc63f6f5 100644 --- a/src/App/Property.h +++ b/src/App/Property.h @@ -44,14 +44,19 @@ namespace App class PropertyContainer; class ObjectIdentifier; -/** Base class of all properties - * This is the father of all properties. Properties are objects which are used - * in the document tree to parametrize e.g. features and their graphical output. +/** + * @brief %Base class of all properties + * @ingroup PropFrame + * + * @details This is the father of all properties. Properties are objects which that used + * in the document tree to parameterize e.g. features and their graphical output. * They are also used to gain access from the scripting facility. - * /par + * @par * This abstract base class defines all methods shared by all - * possible properties. It is also possible to define user properties - * and use them in the framework... + * possible properties. It is also possible to define user properties + * and use them in the framework. + * + * For a more high-level overview see topic @ref PropFrame "Property Framework". */ class AppExport Property: public Base::Persistence { diff --git a/src/App/core-app.dox b/src/App/core-app.dox index a4fc82c12e..08df44bf6c 100644 --- a/src/App/core-app.dox +++ b/src/App/core-app.dox @@ -111,5 +111,7 @@ * - The DocumentObject classes * - The Expression classes * - The Property classes + * + * For a more high-level discussion see the topic @ref APP "App". */ From cf1a5c5c18feae8a68e90891a16a7bc7c8841993 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Thu, 27 Mar 2025 11:58:03 +0100 Subject: [PATCH 070/316] [Doc] Make naming groups consistent in App The identifier for groups/topics such as "Document" that have a class with the samen name are suffixed with "Group", so the identifier becomes "DocumentGroup". For groups/topics with no ambiguity the identifier matches the topic name closely, for example "ExpressionFramework" for topic "Expression Framework". --- src/App/Expression.h | 4 ++-- src/App/Property.h | 4 ++-- src/App/core-app.dox | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/App/Expression.h b/src/App/Expression.h index 4455fb60f6..a17a2267ba 100644 --- a/src/App/Expression.h +++ b/src/App/Expression.h @@ -111,10 +111,10 @@ protected: /** * @brief %Base class for expressions. - * @ingroup Expression + * @ingroup ExpressionFramework * * @details For a high-level overview of the %Expression framework see topic - * @ref Expression "Expression Framework". + * @ref ExpressionFramework "Expression Framework". */ class AppExport Expression : public Base::BaseClass { TYPESYSTEM_HEADER_WITH_OVERRIDE(); diff --git a/src/App/Property.h b/src/App/Property.h index 86bc63f6f5..38b95d8df3 100644 --- a/src/App/Property.h +++ b/src/App/Property.h @@ -46,7 +46,7 @@ class ObjectIdentifier; /** * @brief %Base class of all properties - * @ingroup PropFrame + * @ingroup PropertyFramework * * @details This is the father of all properties. Properties are objects which that used * in the document tree to parameterize e.g. features and their graphical output. @@ -56,7 +56,7 @@ class ObjectIdentifier; * possible properties. It is also possible to define user properties * and use them in the framework. * - * For a more high-level overview see topic @ref PropFrame "Property Framework". + * For a more high-level overview see topic @ref PropertyFramework "Property Framework". */ class AppExport Property: public Base::Persistence { diff --git a/src/App/core-app.dox b/src/App/core-app.dox index 08df44bf6c..01a52d80eb 100644 --- a/src/App/core-app.dox +++ b/src/App/core-app.dox @@ -3,9 +3,9 @@ * @ingroup CORE * @brief The part of FreeCAD that works without GUI (console or server mode) * @details It contains the App namespace and defines core concepts such as - * @ref DocumentGroup "Document", @ref DocObject "Document Object", the @ref - * Expression "Expression Framework", and the @ref PropFrame - * "Property Framework". + * @ref DocumentGroup "Document", @ref DocumentObjectGroup "Document Object", + * the @ref ExpressionFramework "Expression Framework", and the @ref + * PropertyFramework "Property Framework". */ /** @@ -38,19 +38,19 @@ */ /** - * @defgroup DocObject Document Object + * @defgroup DocumentObjectGroup Document Object * @ingroup APP * @brief %Base class of all objects handled in the Document. */ /** - * @defgroup Expression Expressions framework + * @defgroup ExpressionFramework Expressions framework * @ingroup APP * @brief The expression system allows users to write expressions and formulas that produce values */ /** - * @defgroup PropFrame Property framework + * @defgroup PropertyFramework Property framework * @ingroup APP * @brief System to access object properties. * From b05c02b6f1c3fe7fad7066de093ac1dcda347e19 Mon Sep 17 00:00:00 2001 From: Paul Lee Date: Sun, 30 Mar 2025 10:29:36 +0800 Subject: [PATCH 071/316] [Draft-Faces] Bind: Improve fuse and warning - Further Fix Github Discussion: - Fix problem Roy-043 pointed out https://github.com/FreeCAD/FreeCAD/pull/20395#pullrequestreview-2726624360 FC Forum: - https://forum.freecad.org/viewtopic.php?p=819121#p819121 --- src/Mod/Draft/draftgeoutils/faces.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftgeoutils/faces.py b/src/Mod/Draft/draftgeoutils/faces.py index 1c329f0fc8..06469daa11 100644 --- a/src/Mod/Draft/draftgeoutils/faces.py +++ b/src/Mod/Draft/draftgeoutils/faces.py @@ -132,8 +132,6 @@ def bind(w1, w2, per_segment=False): if w3.section(w4).Vertexes: print("DraftGeomUtils: Problem, a segment is self-intersecting, please check!") f = Part.Face(Part.Wire(w1.Edges + [w3] + w2.Edges + [w4])) - if f.normalAt(0,0).z == -1: - print("DraftGeomUtils: Problem, a segment direction is reversed, please check!") return f if not w1 or not w2: @@ -185,31 +183,53 @@ def bind(w1, w2, per_segment=False): # if w1.isClosed() and w2.isClosed() \ and len(faces_list) > 1 and faces_list[0]: - faces_list[0].extend(faces) + 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) + 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 : # Below not good if a face is self-intersecting or reversed #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 faces_fused_list.append(rf) - # faces might be empty list [], see above; skip if empty elif faces: faces_fused_list.append(faces[0]) # Only 1 face return Part.Compound(faces_fused_list) else: + dir = [] + countDir = None + for f in faces: + 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!") # Below not good if a face is self-intersecting or reversed #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 return rf elif w1.isClosed() and w2.isClosed(): From f5d98e6e5db01d77268b1537d8e44f52aa9162c3 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Sun, 30 Mar 2025 14:01:10 +0200 Subject: [PATCH 072/316] Draft: fix Dim Auto Flip Tex angle checks When checking angles Dim Auto Flip Text did not consider that angles can be almost -180 degrees and should then be treated the same as 180 degree angles. --- src/Mod/Draft/draftmake/make_dimension.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftmake/make_dimension.py b/src/Mod/Draft/draftmake/make_dimension.py index 923ffffab0..02d2c10fa1 100644 --- a/src/Mod/Draft/draftmake/make_dimension.py +++ b/src/Mod/Draft/draftmake/make_dimension.py @@ -64,7 +64,7 @@ def _get_flip_text_lin(p1, p2, wp, normal): tol = 1e-4 # high tolerance if math.isclose(ang, 0, abs_tol=tol): return False - if math.isclose(ang, math.pi, abs_tol=tol): + if math.isclose(abs(ang), math.pi, abs_tol=tol): return True if math.isclose(ang, math.pi/2, abs_tol=tol): return False @@ -92,7 +92,7 @@ def _get_flip_text_ang(cen, sta, end, normal): tol = 1e-4 # high tolerance if math.isclose(ang, 0, abs_tol=tol): return True - if math.isclose(ang, math.pi, abs_tol=tol): + if math.isclose(abs(ang), math.pi, abs_tol=tol): return False if ang > 0: return False From 025155fbe798c01481133e19e642511ad3b1d9e4 Mon Sep 17 00:00:00 2001 From: jonzirk76 Date: Thu, 20 Mar 2025 06:03:03 -0400 Subject: [PATCH 073/316] TechDraw: remove double type checking Fixes #20131 --- src/Mod/TechDraw/App/DrawView.cpp | 6 +++--- src/Mod/TechDraw/App/DrawViewClip.cpp | 24 +++++++----------------- src/Mod/TechDraw/App/DrawViewPart.cpp | 12 ++++++------ src/Mod/TechDraw/App/ShapeExtractor.cpp | 2 +- src/Mod/TechDraw/Gui/CommandHelpers.cpp | 4 ++-- src/Mod/TechDraw/Gui/QGSPage.cpp | 4 ++-- 6 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawView.cpp b/src/Mod/TechDraw/App/DrawView.cpp index 4b01917bf6..32ed36cec0 100644 --- a/src/Mod/TechDraw/App/DrawView.cpp +++ b/src/Mod/TechDraw/App/DrawView.cpp @@ -442,7 +442,7 @@ DrawViewClip* DrawView::getClipGroup() { for (auto* obj : getInList()) { if (obj->isDerivedFrom()) { - return dynamic_cast(obj); + return static_cast(obj); } } return nullptr; @@ -452,7 +452,7 @@ DrawViewCollection *DrawView::getCollection() const { for (auto* obj : getInList()) { if (obj->isDerivedFrom()) { - return dynamic_cast(obj); + return static_cast(obj); } } return nullptr; @@ -551,7 +551,7 @@ std::vector DrawView::getLeaders() const std::vector children = getInList(); for (std::vector::iterator it = children.begin(); it != children.end(); ++it) { if ((*it)->isDerivedFrom()) { - TechDraw::DrawLeaderLine* lead = dynamic_cast(*it); + TechDraw::DrawLeaderLine* lead = static_cast(*it); result.push_back(lead); } } diff --git a/src/Mod/TechDraw/App/DrawViewClip.cpp b/src/Mod/TechDraw/App/DrawViewClip.cpp index 027dcc6104..6464ba220c 100644 --- a/src/Mod/TechDraw/App/DrawViewClip.cpp +++ b/src/Mod/TechDraw/App/DrawViewClip.cpp @@ -69,25 +69,15 @@ void DrawViewClip::onChanged(const App::Property* prop) void DrawViewClip::addView(App::DocumentObject* docObj) { - if (!docObj->isDerivedFrom() && !docObj->isDerivedFrom()) { + if(docObj->isDerivedFrom()) { + auto* link = static_cast(docObj); + docObj = link->getLinkedObject(); + } + + if (!docObj->isDerivedFrom()) { return; } - - auto* view = dynamic_cast(docObj); - - if (!view) { - auto* link = dynamic_cast(docObj); - if (!link) { - return; - } - - if (link) { - view = dynamic_cast(link->getLinkedObject()); - if (!view) { - return; - } - } - } + auto* view = static_cast(docObj); std::vector newViews(Views.getValues()); newViews.push_back(docObj); diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index 117001a094..dcc6a31333 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -718,7 +718,7 @@ std::vector DrawViewPart::getHatches() const std::vector children = getInList(); for (auto& child : children) { if (child->isDerivedFrom() && !child->isRemoving()) { - TechDraw::DrawHatch* hatch = dynamic_cast(child); + TechDraw::DrawHatch* hatch = static_cast(child); result.push_back(hatch); } } @@ -733,7 +733,7 @@ std::vector DrawViewPart::getGeomHatches() const for (auto& child : children) { if (child->isDerivedFrom() && !child->isRemoving()) { - TechDraw::DrawGeomHatch* geom = dynamic_cast(child); + TechDraw::DrawGeomHatch* geom = static_cast(child); result.push_back(geom); } } @@ -752,7 +752,7 @@ std::vector DrawViewPart::getDimensions() const std::unique(children.begin(), children.end()); for (std::vector::iterator it = children.begin(); it != newEnd; ++it) { if ((*it)->isDerivedFrom()) { - TechDraw::DrawViewDimension* dim = dynamic_cast(*it); + TechDraw::DrawViewDimension* dim = static_cast(*it); result.push_back(dim); } } @@ -768,7 +768,7 @@ std::vector DrawViewPart::getBalloons() const std::unique(children.begin(), children.end()); for (std::vector::iterator it = children.begin(); it != newEnd; ++it) { if ((*it)->isDerivedFrom()) { - TechDraw::DrawViewBalloon* balloon = dynamic_cast(*it); + TechDraw::DrawViewBalloon* balloon = static_cast(*it); result.push_back(balloon); } } @@ -1142,7 +1142,7 @@ std::vector DrawViewPart::getSectionRefs() const if (o->isDerivedFrom()) { // expressions can add extra links to this DVP so we keep only // objects that are BaseViews - auto section = dynamic_cast(o); + auto section = static_cast(o); auto base = section->BaseView.getValue(); if (base == this) { result.push_back(section); @@ -1161,7 +1161,7 @@ std::vector DrawViewPart::getDetailRefs() const !o->isRemoving() ) { // expressions can add extra links to this DVP so we keep only // objects that are BaseViews - auto detail = dynamic_cast(o); + auto detail = static_cast(o); auto base = detail->BaseView.getValue(); if (base == this) { result.push_back(detail); diff --git a/src/Mod/TechDraw/App/ShapeExtractor.cpp b/src/Mod/TechDraw/App/ShapeExtractor.cpp index 46247e125d..74d811957e 100644 --- a/src/Mod/TechDraw/App/ShapeExtractor.cpp +++ b/src/Mod/TechDraw/App/ShapeExtractor.cpp @@ -127,7 +127,7 @@ TopoDS_Shape ShapeExtractor::getShapes(const std::vector l } if (obj->isDerivedFrom()) { - App::Link* xLink = dynamic_cast(obj); + App::Link* xLink = static_cast(obj); std::vector xShapes = getXShapes(xLink); if (!xShapes.empty()) { sourceShapes.insert(sourceShapes.end(), xShapes.begin(), xShapes.end()); diff --git a/src/Mod/TechDraw/Gui/CommandHelpers.cpp b/src/Mod/TechDraw/Gui/CommandHelpers.cpp index e1e2b059f6..45ab2af998 100644 --- a/src/Mod/TechDraw/Gui/CommandHelpers.cpp +++ b/src/Mod/TechDraw/Gui/CommandHelpers.cpp @@ -62,7 +62,7 @@ TechDraw::DrawView* CommandHelpers::firstViewInSelection(Gui::Command* cmd) for (auto& selobj : selection) { if (selobj.getObject()->isDerivedFrom()) { auto docobj = selobj.getObject(); - baseView = dynamic_cast(docobj); + baseView = static_cast(docobj); break; } } @@ -81,7 +81,7 @@ TechDraw::DrawView* CommandHelpers::firstNonSpreadsheetInSelection(Gui::Command* continue; } else { auto docobj = selobj.getObject(); - baseView = dynamic_cast(docobj); + baseView = static_cast(docobj); break; } } diff --git a/src/Mod/TechDraw/Gui/QGSPage.cpp b/src/Mod/TechDraw/Gui/QGSPage.cpp index cb7ac278e0..d5d612d93e 100644 --- a/src/Mod/TechDraw/Gui/QGSPage.cpp +++ b/src/Mod/TechDraw/Gui/QGSPage.cpp @@ -893,7 +893,7 @@ void QGSPage::findMissingViews(const std::vector& list, if (obj->isDerivedFrom()) { std::vector missingChildViews; - auto* collection = dynamic_cast(obj); + auto* collection = static_cast(obj); // Find Child Views recursively findMissingViews(collection->getViews(), missingChildViews); @@ -1000,7 +1000,7 @@ bool QGSPage::orphanExists(const char* viewName, const std::vectorisDerivedFrom()) { - auto* collection = dynamic_cast(obj); + auto* collection = static_cast(obj); if (orphanExists(viewName, collection->getViews())) return true; } From 3a7712bc68a94bab8ea65dfb8f5a2695749c980a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Br=C3=A6strup=20Sayoc?= Date: Sun, 30 Mar 2025 17:41:41 +0200 Subject: [PATCH 074/316] Tests: move Color.cpp to Base --- tests/src/App/CMakeLists.txt | 1 - tests/src/Base/CMakeLists.txt | 1 + tests/src/{App => Base}/Color.cpp | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename tests/src/{App => Base}/Color.cpp (100%) diff --git a/tests/src/App/CMakeLists.txt b/tests/src/App/CMakeLists.txt index a162d622e6..94afdcd0a9 100644 --- a/tests/src/App/CMakeLists.txt +++ b/tests/src/App/CMakeLists.txt @@ -3,7 +3,6 @@ target_compile_definitions(Tests_run PRIVATE DATADIR="${CMAKE_SOURCE_DIR}/data") target_sources(Tests_run PRIVATE Application.cpp Branding.cpp - Color.cpp ComplexGeoData.cpp Document.cpp DocumentObject.cpp diff --git a/tests/src/Base/CMakeLists.txt b/tests/src/Base/CMakeLists.txt index 531b5ac4c6..ac7c77c8fc 100644 --- a/tests/src/Base/CMakeLists.txt +++ b/tests/src/Base/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(Tests_run PRIVATE Bitmask.cpp BoundBox.cpp Builder3D.cpp + Color.cpp CoordinateSystem.cpp DualNumber.cpp DualQuaternion.cpp diff --git a/tests/src/App/Color.cpp b/tests/src/Base/Color.cpp similarity index 100% rename from tests/src/App/Color.cpp rename to tests/src/Base/Color.cpp From e581142ff63ebb9445c2cae79ae2897fff136179 Mon Sep 17 00:00:00 2001 From: Tomas Polak Date: Thu, 27 Mar 2025 18:02:02 +0100 Subject: [PATCH 075/316] BIM adjust BIM_Classification tooltip --- src/Mod/BIM/Resources/ui/dialogClassification.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/BIM/Resources/ui/dialogClassification.ui b/src/Mod/BIM/Resources/ui/dialogClassification.ui index 9b9a022ee0..de2ce45e70 100644 --- a/src/Mod/BIM/Resources/ui/dialogClassification.ui +++ b/src/Mod/BIM/Resources/ui/dialogClassification.ui @@ -173,7 +173,7 @@ - Apply the selected class to selected materials + Apply the selected class to selected objects << Apply to selected From 1c588e66145787e5cdf230f99fc06354d3b6502b Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Sun, 30 Mar 2025 21:20:26 +0200 Subject: [PATCH 076/316] Draft: fix alignment of dim arrows Forum post (issue 3): https://forum.freecad.org/viewtopic.php?t=95898#p819131 The `invert` value of dim arrows should always be `False` for the 1st and `True` for the 2nd. It should not depend on their X coords. --- src/Mod/Draft/draftviewproviders/view_dimension.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index 7b5e898bb9..ef417fef89 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -723,11 +723,6 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): if not hasattr(vobj, "ArrowType"): return - if self.p3.x < self.p2.x: - inv = False - else: - inv = True - # Set scale symbol = utils.ARROW_TYPES.index(vobj.ArrowType) s = vobj.ArrowSize.Value * vobj.ScaleMultiplier @@ -745,7 +740,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): else: s1.addChild(self.trans1) - s1.addChild(gui_utils.dim_symbol(symbol, invert=not inv)) + s1.addChild(gui_utils.dim_symbol(symbol, invert=False)) self.marks.addChild(s1) s2 = coin.SoSeparator() @@ -754,7 +749,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): else: s2.addChild(self.trans2) - s2.addChild(gui_utils.dim_symbol(symbol, invert=inv)) + s2.addChild(gui_utils.dim_symbol(symbol, invert=True)) self.marks.addChild(s2) self.node_wld.insertChild(self.marks, 2) From 487c62a663a567a08d87360ed6c74dcbc998081f Mon Sep 17 00:00:00 2001 From: Alfredo Monclus Date: Sun, 30 Mar 2025 19:14:19 -0300 Subject: [PATCH 077/316] Gui: fix Inputfield valid/invalid icon placement and size (#20466) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Gui: fix inputfield icon size placement * chore:Update inputfield comment to be more clear Co-authored-by: Benjamin Bræstrup Sayoc --------- Co-authored-by: Benjamin Bræstrup Sayoc --- src/Gui/InputField.cpp | 39 ++++++++++++++++++++++++--------------- src/Gui/InputField.h | 1 + 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index e53fc5d1c4..ee559b0bc6 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -86,22 +86,33 @@ InputField::InputField(QWidget * parent) } iconLabel = new ExpressionLabel(this); iconLabel->setCursor(Qt::ArrowCursor); - QPixmap pixmap = getValidationIcon(":/icons/button_valid.svg", QSize(sizeHint().height(),sizeHint().height())); + QFontMetrics fm(font()); + int iconSize = fm.height(); + QPixmap pixmap = getValidationIcon(":/icons/button_valid.svg", QSize(iconSize, iconSize)); iconLabel->setPixmap(pixmap); - iconLabel->setStyleSheet(QStringLiteral("QLabel { border: none; padding: 0px; }")); iconLabel->hide(); connect(this, &QLineEdit::textChanged, this, &InputField::updateIconLabel); - int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QStringLiteral("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); - QSize msz = minimumSizeHint(); - setMinimumSize(qMax(msz.width(), iconLabel->sizeHint().height() + frameWidth * 2 + 2), - qMax(msz.height(), iconLabel->sizeHint().height() + frameWidth * 2 + 2)); + + // Set Margins + // vertical margin, such that `,` won't be clipped to a `.` and similar font descents. Relevant on some OSX versions + // horizontal margin, such that text will not be behind `fx` icon + int margin = getMargin(); + setTextMargins(margin, margin, margin + iconSize, margin); this->setContextMenuPolicy(Qt::DefaultContextMenu); connect(this, &QLineEdit::textChanged, this, &InputField::newInput); } +int InputField::getMargin() +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0) + return style()->pixelMetric(QStyle::PM_LineEditIconMargin, nullptr, this) / 2; +#else + return style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, this); +#endif +} + InputField::~InputField() = default; void InputField::bind(const App::ObjectIdentifier &_path) @@ -175,12 +186,10 @@ void InputField::updateText(const Base::Quantity& quant) setText(QString::fromStdString(txt)); } -void InputField::resizeEvent(QResizeEvent *) +void InputField::resizeEvent(QResizeEvent * /*event*/) { - QSize sz = iconLabel->sizeHint(); - int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - iconLabel->move(rect().right() - frameWidth - sz.width(), - rect().center().y() - sz.height() / 2); + QSize iconSize = iconLabel->sizeHint(); + iconLabel->move(width() - (iconSize.width() + 2 * getMargin()), (height() - iconSize.height()) / 2); } void InputField::updateIconLabel(const QString& text) @@ -260,7 +269,7 @@ void InputField::newInput(const QString & text) } catch(Base::Exception &e){ QString errorText = QString::fromLatin1(e.what()); - QPixmap pixmap = getValidationIcon(":/icons/button_invalid.svg", QSize(sizeHint().height(),sizeHint().height())); + QPixmap pixmap = getValidationIcon(":/icons/button_invalid.svg", iconLabel->sizeHint()); iconLabel->setPixmap(pixmap); Q_EMIT parseError(errorText); validInput = false; @@ -272,7 +281,7 @@ void InputField::newInput(const QString & text) // check if unit fits! if(!actUnit.isEmpty() && !res.getUnit().isEmpty() && actUnit != res.getUnit()){ - QPixmap pixmap = getValidationIcon(":/icons/button_invalid.svg", QSize(sizeHint().height(),sizeHint().height())); + QPixmap pixmap = getValidationIcon(":/icons/button_invalid.svg", iconLabel->sizeHint()); iconLabel->setPixmap(pixmap); Q_EMIT parseError(QStringLiteral("Wrong unit")); validInput = false; @@ -280,7 +289,7 @@ void InputField::newInput(const QString & text) } - QPixmap pixmap = getValidationIcon(":/icons/button_valid.svg", QSize(sizeHint().height(),sizeHint().height())); + QPixmap pixmap = getValidationIcon(":/icons/button_valid.svg", iconLabel->sizeHint()); iconLabel->setPixmap(pixmap); validInput = true; diff --git a/src/Gui/InputField.h b/src/Gui/InputField.h index 1aa7fb1c98..fc4e356ee1 100644 --- a/src/Gui/InputField.h +++ b/src/Gui/InputField.h @@ -201,6 +201,7 @@ protected: void wheelEvent(QWheelEvent * event) override; void contextMenuEvent(QContextMenuEvent * event) override; void resizeEvent(QResizeEvent*) override; + int getMargin(); private: QPixmap getValidationIcon(const char* name, const QSize& size) const; From ee6f757c577b20b5bfe29ebee26a0651a7c7c921 Mon Sep 17 00:00:00 2001 From: Jonathan Zirkle <97168343+jonzirk76@users.noreply.github.com> Date: Mon, 31 Mar 2025 09:17:51 -0400 Subject: [PATCH 078/316] Mod: Convert from dynamic to static casts (#20452) --- src/Mod/Measure/Gui/Command.cpp | 2 +- src/Mod/Part/App/Geometry.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Mod/Measure/Gui/Command.cpp b/src/Mod/Measure/Gui/Command.cpp index 5a886fb2c9..2a138080fa 100644 --- a/src/Mod/Measure/Gui/Command.cpp +++ b/src/Mod/Measure/Gui/Command.cpp @@ -70,7 +70,7 @@ bool StdCmdMeasure::isActive() Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); if (view && view->isDerivedFrom()) { - Gui::View3DInventorViewer* viewer = dynamic_cast(view)->getViewer(); + Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); return !viewer->isEditing(); } return false; diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index 571b91cd18..bc545995af 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -765,8 +765,8 @@ GeomLineSegment* GeomCurve::toLineSegment(KeepTag clone) const Base::Vector3d start, end; if (isDerivedFrom()) { - start = dynamic_cast(this)->getStartPoint(); - end = dynamic_cast(this)->getEndPoint(); + start = static_cast(this)->getStartPoint(); + end = static_cast(this)->getEndPoint(); } else { start = pointAtParameter(getFirstParameter()); end = pointAtParameter(getLastParameter()); @@ -4527,7 +4527,7 @@ bool GeomLine::isSame(const Geometry &_other, double tol, double atol) const { if(_other.getTypeId() != getTypeId()) { if (_other.isDerivedFrom()) { - std::unique_ptr geo(dynamic_cast(_other).toLine()); + std::unique_ptr geo(static_cast(_other).toLine()); if (geo) return isSame(*geo, tol, atol); } @@ -4819,10 +4819,10 @@ GeomPlane* GeomSurface::toPlane(bool clone, double tol) const { if (isDerivedFrom()) { if (clone) { - return dynamic_cast(this->clone()); + return static_cast(this->clone()); } else { - return dynamic_cast(this->copy()); + return static_cast(this->copy()); } } From 7441ae36d3836211b737569b3b59c8e63fc6a111 Mon Sep 17 00:00:00 2001 From: Kevin Martin Date: Mon, 31 Mar 2025 11:45:58 -0400 Subject: [PATCH 079/316] Base: UniqueNameManager support for very long numbers in name (#19943) * Add unit tests for large digit count in unique names * Updated to use arbitrary-precision unsigneds Passes the new unit tests, all diagnostics, and resolves Issue 19881 * Place UnlimitedUnsigned at top level and add unit tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Base/CMakeLists.txt | 1 + src/Base/UniqueNameManager.cpp | 109 ++----------- src/Base/UniqueNameManager.h | 110 ++++++++++++- src/Base/UnlimitedUnsigned.h | 235 +++++++++++++++++++++++++++ tests/src/Base/CMakeLists.txt | 1 + tests/src/Base/UniqueNameManager.cpp | 16 ++ tests/src/Base/UnlimitedUnsigned.cpp | 55 +++++++ 7 files changed, 420 insertions(+), 107 deletions(-) create mode 100644 src/Base/UnlimitedUnsigned.h create mode 100644 tests/src/Base/UnlimitedUnsigned.cpp diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index 52f85bd30a..43ee4cc2bb 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -301,6 +301,7 @@ SET(FreeCADBase_HPP_SRCS Tools3D.h Translate.h Type.h + UnlimitedUnsigned.h UniqueNameManager.h Uuid.h Vector3D.h diff --git a/src/Base/UniqueNameManager.cpp b/src/Base/UniqueNameManager.cpp index 34a050606a..a7f580e0a7 100644 --- a/src/Base/UniqueNameManager.cpp +++ b/src/Base/UniqueNameManager.cpp @@ -30,99 +30,7 @@ #endif #include "UniqueNameManager.h" -void Base::UniqueNameManager::PiecewiseSparseIntegerSet::add(unsigned int value) -{ - SpanType newSpan(value, 1); - // Look for the smallest entry not less than newSpan. - // Bear in mind that overlapping spans are neither less than nor greater than ech other. - auto above = spans.lower_bound(newSpan); - if (above != spans.end() && above->first <= value) { - // A span was found that includes value so there is nothing to do as it is already in the - // set. - return; - } - - // Set below to the next span below 'after', if any, otherwise to spans.end(). - // Logically, we want spans.begin()-1 so 'below' is always the entry before 'after', - // but that is not an allowed reference so spans.end() is used - std::set::iterator below; - if (above == spans.begin()) { - // No spans are less than newSpan - // (possibly spans is empty, in which case above == spans.end() too) - below = spans.end(); - } - else { - // At least one span is less than newSpan, - // and 'above' is the next span above that - // (or above == spans.end() if all spans are below newSpan) - below = above; - --below; - } - - // Determine whether the span above (if any) and/or the span below (if any) - // are adjacent to newSpan and if so, merge them appropriately and remove the - // original span(s) that was/were merged, updating newSpan to be the new merged - // span. - if (above != spans.end() && below != spans.end() - && above->first - below->first + 1 == below->second) { - // below and above have a gap of exactly one between them, and this must be value - // so we coalesce the two spans (and the gap) into one. - newSpan = SpanType(below->first, below->second + above->second + 1); - spans.erase(above); - above = spans.erase(below); - } - else if (below != spans.end() && value - below->first == below->second) { - // value is adjacent to the end of below, so just expand below by one - newSpan = SpanType(below->first, below->second + 1); - above = spans.erase(below); - } - else if (above != spans.end() && above->first - value == 1) { - // value is adjacent to the start of above, so just expand above down by one - newSpan = SpanType(above->first - 1, above->second + 1); - above = spans.erase(above); - } - // else value is not adjacent to any existing span, so just make anew span for it - spans.insert(above, newSpan); -} -void Base::UniqueNameManager::PiecewiseSparseIntegerSet::remove(unsigned int value) -{ - SpanType newSpan(value, 1); - auto at = spans.lower_bound(newSpan); - if (at == spans.end() || at->first > value) { - // The found span does not include value so there is nothing to do, as it is already not in - // the set. - return; - } - if (at->second == 1) { - // value is the only in this span, just remove the span - spans.erase(at); - } - else if (at->first == value) { - // value is the first in this span, trim the lower end - SpanType replacement(at->first + 1, at->second - 1); - spans.insert(spans.erase(at), replacement); - } - else if (value - at->first == at->second - 1) { - // value is the last in this span, trim the upper end - SpanType replacement(at->first, at->second - 1); - spans.insert(spans.erase(at), replacement); - } - else { - // value is in the moddle of the span, so we must split it. - SpanType firstReplacement(at->first, value - at->first); - SpanType secondReplacement(value + 1, at->second - ((value + 1) - at->first)); - // Because erase returns the iterator after the erased element, and insert returns the - // iterator for the inserted item, we want to insert secondReplacement first. - spans.insert(spans.insert(spans.erase(at), secondReplacement), firstReplacement); - } -} -bool Base::UniqueNameManager::PiecewiseSparseIntegerSet::contains(unsigned int value) const -{ - auto at = spans.lower_bound(SpanType(value, 1)); - return at != spans.end() && at->first <= value; -} - -std::tuple +std::tuple Base::UniqueNameManager::decomposeName(const std::string& name) const { auto suffixStart = getNameSuffixStartPosition(name); @@ -130,11 +38,11 @@ Base::UniqueNameManager::decomposeName(const std::string& name) const return std::isdigit(c); }); unsigned int digitCount = digitsStart - suffixStart; - return std::tuple { + return std::tuple { name.substr(0, name.crend() - digitsStart), name.substr(name.crend() - suffixStart), digitCount, - digitCount == 0 ? 0U : std::stoul(name.substr(name.crend() - digitsStart, digitCount))}; + UnlimitedUnsigned::fromString(name.substr(name.crend() - digitsStart, digitCount))}; } bool Base::UniqueNameManager::haveSameBaseName(const std::string& first, const std::string& second) const @@ -162,13 +70,16 @@ void Base::UniqueNameManager::addExactName(const std::string& name) if (baseNameEntry == uniqueSeeds.end()) { // First use of baseName baseNameEntry = - uniqueSeeds.emplace(baseName, std::vector()).first; + uniqueSeeds + .emplace(baseName, std::vector>()) + .first; } if (digitCount >= baseNameEntry->second.size()) { // First use of this digitCount baseNameEntry->second.resize(digitCount + 1); } - PiecewiseSparseIntegerSet& baseNameAndDigitCountEntry = baseNameEntry->second[digitCount]; + PiecewiseSparseIntegerSet& baseNameAndDigitCountEntry = + baseNameEntry->second[digitCount]; if (baseNameAndDigitCountEntry.contains(digitsValue)) { // We already have at least one instance of the name. @@ -198,12 +109,12 @@ std::string Base::UniqueNameManager::makeUniqueName(const std::string& modelName // We start the longer digit string at 000...0001 even though we might have shorter strings // with larger numeric values. digitCount = minDigits; - digitsValue = 1; + digitsValue = UnlimitedUnsigned(1); } else { digitsValue = baseNameEntry->second[digitCount].next(); } - std::string digits = std::to_string(digitsValue); + std::string digits = digitsValue.toString(); if (digitCount > digits.size()) { namePrefix += std::string(digitCount - digits.size(), '0'); } diff --git a/src/Base/UniqueNameManager.h b/src/Base/UniqueNameManager.h index c91c9772f1..6797d57be8 100644 --- a/src/Base/UniqueNameManager.h +++ b/src/Base/UniqueNameManager.h @@ -31,6 +31,10 @@ #include #include #include // Forward declares std::tuple +#include +#include +#include +#include "UnlimitedUnsigned.h" // ---------------------------------------------------------------------------- @@ -58,6 +62,7 @@ protected: } private: + template class PiecewiseSparseIntegerSet { public: @@ -66,7 +71,7 @@ private: private: // Each pair being represents the span of integers from lowest to // (lowest+count-1) inclusive - using SpanType = std::pair; + using SpanType = std::pair; // This span Comparer class is analogous to std::less and treats overlapping spans as being // neither greater nor less than each other class Comparer @@ -81,11 +86,100 @@ private: // spans is the set of spans. Adjacent spans are coalesced so there are always gaps between // the entries. std::set spans; + using SpanSetIterator = typename std::set::iterator; public: - void add(unsigned int value); - void remove(unsigned int value); - bool contains(unsigned int value) const; + void add(IT value) + { + SpanType newSpan(value, 1); + // Look for the smallest entry not less than newSpan. + // Bear in mind that overlapping spans are neither less than nor greater than ech other. + auto above = spans.lower_bound(newSpan); + if (above != spans.end() && above->first <= value) { + // A span was found that includes value so there is nothing to do as it is already + // in the set. + return; + } + + // Set below to the next span below 'after', if any, otherwise to spans.end(). + // Logically, we want spans.begin()-1 so 'below' is always the entry before 'after', + // but that is not an allowed reference so spans.end() is used + SpanSetIterator below; + if (above == spans.begin()) { + // No spans are less than newSpan + // (possibly spans is empty, in which case above == spans.end() too) + below = spans.end(); + } + else { + // At least one span is less than newSpan, + // and 'above' is the next span above that + // (or above == spans.end() if all spans are below newSpan) + below = above; + --below; + } + + // Determine whether the span above (if any) and/or the span below (if any) + // are adjacent to newSpan and if so, merge them appropriately and remove the + // original span(s) that was/were merged, updating newSpan to be the new merged + // span. + if (above != spans.end() && below != spans.end() + && above->first - below->first + 1 == below->second) { + // below and above have a gap of exactly one between them, and this must be value + // so we coalesce the two spans (and the gap) into one. + newSpan = SpanType(below->first, below->second + above->second + 1); + spans.erase(above); + above = spans.erase(below); + } + else if (below != spans.end() && value - below->first == below->second) { + // value is adjacent to the end of below, so just expand below by one + newSpan = SpanType(below->first, below->second + 1); + above = spans.erase(below); + } + else if (above != spans.end() && above->first - value == 1) { + // value is adjacent to the start of above, so just expand above down by one + newSpan = SpanType(above->first - 1, above->second + 1); + above = spans.erase(above); + } + // else value is not adjacent to any existing span, so just make anew span for it + spans.insert(above, newSpan); + } + void remove(IT value) + { + SpanType newSpan(value, 1); + auto at = spans.lower_bound(newSpan); + if (at == spans.end() || at->first > value) { + // The found span does not include value so there is nothing to do, as it is already + // not in the set. + return; + } + if (at->second == 1) { + // value is the only in this span, just remove the span + spans.erase(at); + } + else if (at->first == value) { + // value is the first in this span, trim the lower end + SpanType replacement(at->first + 1, at->second - 1); + spans.insert(spans.erase(at), replacement); + } + else if (value - at->first == at->second - 1) { + // value is the last in this span, trim the upper end + SpanType replacement(at->first, at->second - 1); + spans.insert(spans.erase(at), replacement); + } + else { + // value is in the moddle of the span, so we must split it. + SpanType firstReplacement(at->first, value - at->first); + SpanType secondReplacement(value + 1, at->second - ((value + 1) - at->first)); + // Because erase returns the iterator after the erased element, and insert returns + // the iterator for the inserted item, we want to insert secondReplacement first. + spans.insert(spans.insert(spans.erase(at), secondReplacement), firstReplacement); + } + } + bool contains(IT value) const + { + auto at = spans.lower_bound(SpanType(value, IT(1))); + return at != spans.end() && at->first <= value; + } bool empty() const { return spans.empty(); @@ -94,10 +188,10 @@ private: { spans.clear(); } - unsigned int next() const + IT next() const { if (spans.empty()) { - return 0; + return IT(0); } auto last = spans.end(); --last; @@ -107,7 +201,7 @@ private: // Keyed as uniqueSeeds[baseName][digitCount][digitValue] iff that seed is taken. // We need the double-indexing so that Name01 and Name001 can both be indexed, although we only // ever allocate off the longest for each name i.e. uniqueSeeds[baseName].size()-1 digits. - std::map> uniqueSeeds; + std::map>> uniqueSeeds; // Counts of inserted strings that have duplicates, i.e. more than one instance in the // collection. This does not contain entries for singleton names. std::map duplicateCounts; @@ -116,7 +210,7 @@ private: /// @param name The name to break up /// @return a tuple(basePrefix, nameSuffix, uniqueDigitCount, uniqueDigitsValue); /// The two latter values will be (0,0) if name is a base name without uniquifying digits. - std::tuple + std::tuple decomposeName(const std::string& name) const; public: diff --git a/src/Base/UnlimitedUnsigned.h b/src/Base/UnlimitedUnsigned.h new file mode 100644 index 0000000000..36e6eaf1cf --- /dev/null +++ b/src/Base/UnlimitedUnsigned.h @@ -0,0 +1,235 @@ +/*************************************************************************** + * Copyright (c) 2025 Kevin Martin * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + + +#ifndef SRC_BASE_UNLIMITEDUNSIGNED_H_ +#define SRC_BASE_UNLIMITEDUNSIGNED_H_ + +#ifndef FC_GLOBAL_H +#include +#endif +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Base +{ +class UnlimitedUnsigned +{ +private: + // This should be a signed type so we can get transient negative values during calculations + // without resorting to a larger type + using PartType = int32_t; + // The following must be a type that limits the value to >= 0 and < maxPartPlusOne + using SmallDeltaType = unsigned char; + explicit UnlimitedUnsigned(std::vector&& partsVector) + : parts(std::move(partsVector)) + {} + // We take a really cheap floor(bitcount * log10(max PartType)). 3/10 is just a bit less + // than log10(2) The value should be sizeof(PartType) * CHAR_BIT * 3 / 10 but we can't + // calculate the corresponding maxPartPlusOne in a static const initializer, so we just wire + // in the values for 4-byte PartType. + static const size_t partDigitCount = 9; + static const PartType maxPartPlusOne = + 1000000000; // (PartType)pow(10, partDigitCount); but can't call pow in a const ctor. + +public: + explicit UnlimitedUnsigned(SmallDeltaType value) + : parts(std::vector(1, value)) + {} + // Parse a decimal digit string into an UnlimitedUnsigned. There should be no white space, + // only digits. a zero-length string parses as zero. + static UnlimitedUnsigned fromString(const std::string& text) + { + std::vector result((text.size() + partDigitCount - 1) / partDigitCount); + size_t minimumSize = 0; + size_t lastStartPosition = text.size(); + // Parse chunks of digits starting with the least significant + for (size_t i = 0; i < result.size(); i++) { + if (partDigitCount >= lastStartPosition) { + // partial chunk of leading digits + result[i] = static_cast(std::stoul(text.substr(0, lastStartPosition))); + } + else { + lastStartPosition -= partDigitCount; + result[i] = static_cast( + std::stoul(text.substr(lastStartPosition, partDigitCount))); + } + if (result[i] != 0) { + minimumSize = i + 1; + } + } + result.resize(minimumSize); + return UnlimitedUnsigned(std::move(result)); + } + std::string toString() + { + std::string result; + result.reserve(parts.size() * partDigitCount); + // Format the chunks from most- to least-significant + for (auto it = parts.rbegin(); it != parts.rend(); it++) { + std::string partDigits = std::to_string(*it); + if (!result.empty()) { + size_t padding = partDigitCount - partDigits.size(); + if (padding > 0) { + result += std::string(padding, '0'); + } + } + result += partDigits; + } + return result; + } + // TODO: Some allocation of vector contents could be avoided by defining methods like + // static UnlimitedUnsigned operator+(UnlimitedUnsigned&& left, const UnlimitedUnsigned& + // right); static UnlimitedUnsigned operator+(const UnlimitedUnsigned& left, + // UnlimitedUnsigned&& right); static UnlimitedUnsigned operator+(UnlimitedUnsigned&& left, + // UnlimitedUnsigned&& right); which would re-use left.parts or right.parts after possibly + // growing it. The last one would use the larger of the two buffers + UnlimitedUnsigned operator+(const UnlimitedUnsigned& right) const + { + size_t resultSize = std::max(parts.size(), right.parts.size()); + std::vector result(resultSize); + PartType carry = 0; + for (size_t i = 0; i < resultSize; i++) { + auto newPart = (i < parts.size() ? parts[i] : 0) + + (i < right.parts.size() ? right.parts[i] : 0) + carry; + if (newPart < maxPartPlusOne) { + carry = 0; + } + else { + carry = 1; + newPart -= maxPartPlusOne; + } + result[i] = newPart; + } + if (carry > 0) { + result.resize(resultSize + 1); + result[resultSize] = carry; + } + return UnlimitedUnsigned(std::move(result)); + } + UnlimitedUnsigned operator+(SmallDeltaType right) const + { + size_t resultSize = parts.size(); + std::vector result(resultSize); + PartType carry = right; + for (size_t i = 0; i < resultSize; i++) { + auto newPart = parts[i] + carry; + if (newPart < maxPartPlusOne) { + carry = 0; + } + else { + carry = 1; + newPart -= maxPartPlusOne; + } + result[i] = newPart; + } + if (carry > 0) { + result.resize(resultSize + 1); + result[resultSize] = carry; + } + return UnlimitedUnsigned(std::move(result)); + } + UnlimitedUnsigned operator-(const UnlimitedUnsigned& right) const + { + size_t resultSize = std::max(parts.size(), right.parts.size()); + std::vector result(resultSize); + PartType borrow = 0; + size_t lastNonZero = 0; + for (size_t i = 0; i < resultSize; i++) { + auto newPart = (i < parts.size() ? parts[i] : 0) + - (i < right.parts.size() ? right.parts[i] : 0) - borrow; + if (newPart >= 0) { + borrow = 0; + } + else { + borrow = 1; + newPart += maxPartPlusOne; + } + result[i] = newPart; + if (newPart != 0) { + lastNonZero = i + 1; + } + } + if (borrow > 0) { + throw std::overflow_error("UnlimitedUnsigned arithmetic produced a negative result"); + } + result.resize(lastNonZero); + return UnlimitedUnsigned(std::move(result)); + } + UnlimitedUnsigned operator-(SmallDeltaType right) const + { + size_t resultSize = parts.size(); + std::vector result(resultSize); + PartType borrow = right; + for (size_t i = 0; i < resultSize; i++) { + auto newPart = parts[i] - borrow; + if (newPart >= 0) { + borrow = 0; + } + else { + borrow = 1; + newPart += maxPartPlusOne; + } + result[i] = newPart; + } + if (borrow > 0) { + throw std::overflow_error("UnlimitedUnsigned arithmetic produced a negative result"); + } + // Note that by here resultSize > 0, otherwise the original this == 0 and we would have + // the above exception. + if (result[resultSize - 1] == 0) { + result.resize(resultSize - 1); + } + return UnlimitedUnsigned(std::move(result)); + } + bool operator<=(const UnlimitedUnsigned& right) const + { + // lexicographical_compare is logically a < operation, so we reverse the operands and + // invert the result to get <= and we compare the most significant chunks first. + return parts.size() < right.parts.size() + || (parts.size() == right.parts.size() + && !std::lexicographical_compare(right.parts.rbegin(), + right.parts.rend(), + parts.rbegin(), + parts.rend())); + } + bool operator>(const UnlimitedUnsigned& right) const + { + return !(*this <= right); + } + bool operator==(const UnlimitedUnsigned& right) const + { + return parts == right.parts; + } + bool operator==(SmallDeltaType right) const + { + return right == 0 ? parts.empty() : (parts.size() == 1 && parts[0] == right); + } + +private: + std::vector parts; +}; +} // namespace Base + +#endif // SRC_BASE_UNLIMITEDUNSIGNED_H_ diff --git a/tests/src/Base/CMakeLists.txt b/tests/src/Base/CMakeLists.txt index ac7c77c8fc..154831216f 100644 --- a/tests/src/Base/CMakeLists.txt +++ b/tests/src/Base/CMakeLists.txt @@ -21,6 +21,7 @@ target_sources(Tests_run PRIVATE Tools.cpp Tools2D.cpp Tools3D.cpp + UnlimitedUnsigned.cpp UniqueNameManager.cpp Unit.cpp Vector3D.cpp diff --git a/tests/src/Base/UniqueNameManager.cpp b/tests/src/Base/UniqueNameManager.cpp index a9ff22f3ff..ba502eafd2 100644 --- a/tests/src/Base/UniqueNameManager.cpp +++ b/tests/src/Base/UniqueNameManager.cpp @@ -106,4 +106,20 @@ TEST(UniqueNameManager, Issue18504) name = manager.makeUniqueName("Origin", 3); EXPECT_NE(name, "Origin010"); } + +TEST(UniqueNameManager, UniqueNameWithManyDigits) +{ + // Check that names with many digits (value larger than max unsigned long) work + Base::UniqueNameManager manager; + manager.addExactName("Compound006002002002002"); + EXPECT_EQ(manager.makeUniqueName("Compound", 3), "Compound006002002002003"); +} +TEST(UniqueNameManager, UniqueNameWith9NDigits) +{ + // Check that names with a multiple of 9 digits work. The manager chunks nine digits at a time + // so this boundary condition needs a test. + Base::UniqueNameManager manager; + manager.addExactName("Compound123456789"); + EXPECT_EQ(manager.makeUniqueName("Compound", 3), "Compound123456790"); +} // NOLINTEND(cppcoreguidelines-*,readability-*) diff --git a/tests/src/Base/UnlimitedUnsigned.cpp b/tests/src/Base/UnlimitedUnsigned.cpp new file mode 100644 index 0000000000..240c7ed141 --- /dev/null +++ b/tests/src/Base/UnlimitedUnsigned.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (c) 2025 Kevin Martin * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ +#include +#include +#include + +// NOLINTBEGIN(cppcoreguidelines-*,readability-*) +TEST(UnlimitedUnsigned, Basics) +{ + // Check simple addition with carry and conversion from string + Base::UnlimitedUnsigned one(1); + auto nines = Base::UnlimitedUnsigned::fromString("999999999"); + EXPECT_EQ(nines + one, Base::UnlimitedUnsigned::fromString("1000000000")); +} +TEST(UnlimitedUnsigned, ToString) +{ + // Check toString on simple addition result + Base::UnlimitedUnsigned one(1); + auto nines = Base::UnlimitedUnsigned::fromString("999999999"); + EXPECT_EQ((nines + one).toString(), "1000000000"); +} +TEST(UnlimitedUnsigned, TestSubtraction1) +{ + // Check subtraction and comparison with byte-sized number + EXPECT_EQ(Base::UnlimitedUnsigned::fromString("6842357951") + - Base::UnlimitedUnsigned::fromString("6842357948"), + 3); +} +TEST(UnlimitedUnsigned, TestSubtraction2) +{ + // Check subtraction and comparison + EXPECT_EQ(Base::UnlimitedUnsigned::fromString("6842357951") + - Base::UnlimitedUnsigned::fromString("6000000000"), + Base::UnlimitedUnsigned::fromString("842357951")); +} + +// NOLINTEND(cppcoreguidelines-*,readability-*) From 9c99e73d650b585ad77ba304605853ad4264f584 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 22 Mar 2025 17:48:53 -0500 Subject: [PATCH 080/316] Navlib: Eliminate compiler warnings A few unused variables, and a few cases where clang would prefer it be made clear that an initializer is initializing two separate sub-objects, rather than using a flat list. --- .../3Dconnexion/navlib/NavlibNavigation.cpp | 24 +++++++++---------- src/Gui/3Dconnexion/navlib/NavlibPivot.cpp | 14 +++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Gui/3Dconnexion/navlib/NavlibNavigation.cpp b/src/Gui/3Dconnexion/navlib/NavlibNavigation.cpp index a74c21fc1f..47a0219f9e 100644 --- a/src/Gui/3Dconnexion/navlib/NavlibNavigation.cpp +++ b/src/Gui/3Dconnexion/navlib/NavlibNavigation.cpp @@ -49,8 +49,8 @@ NavlibInterface::NavlibInterface() : CNavigation3D(false, navlib::nlOptions_t::no_ui), - patternInitialized(false), - activeTab({-1, ""}) + activeTab({-1, ""}), + patternInitialized(false) {} NavlibInterface::~NavlibInterface() @@ -304,7 +304,7 @@ long NavlibInterface::GetViewFrustum(navlib::frustum_t& frustum) const return 0; } -long NavlibInterface::SetViewFrustum(const navlib::frustum_t& frustum) +long NavlibInterface::SetViewFrustum(const navlib::frustum_t&) { return navlib::make_result_code(navlib::navlib_errc::no_data_available); } @@ -334,12 +334,12 @@ long NavlibInterface::GetViewExtents(navlib::box_t& extents) const const double halfWidth = static_cast(viewVolume.getWidth() / 2.0f); const double halfDepth = 1.0e8; - extents = {-halfWidth, - -halfHeight, - -halfDepth, - halfWidth, - halfHeight, - halfDepth}; + extents = {{-halfWidth, + -halfHeight, + -halfDepth}, + {halfWidth, + halfHeight, + halfDepth}}; return 0; } @@ -385,12 +385,12 @@ long NavlibInterface::SetViewExtents(const navlib::box_t& extents) return navlib::make_result_code(navlib::navlib_errc::no_data_available); } -long NavlibInterface::GetViewFOV(double& fov) const +long NavlibInterface::GetViewFOV(double&) const { return navlib::make_result_code(navlib::navlib_errc::no_data_available); } -long NavlibInterface::SetViewFOV(double fov) +long NavlibInterface::SetViewFOV(double) { return navlib::make_result_code(navlib::navlib_errc::no_data_available); } @@ -448,7 +448,7 @@ long NavlibInterface::GetModelExtents(navlib::box_t& extents) const return navlib::make_result_code(navlib::navlib_errc::no_data_available); } -long NavlibInterface::SetTransaction(long value) +long NavlibInterface::SetTransaction(long) { return navlib::make_result_code(navlib::navlib_errc::no_data_available); } diff --git a/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp b/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp index 9a08f21eaf..74a2848601 100644 --- a/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp +++ b/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp @@ -66,7 +66,7 @@ long NavlibInterface::SetSelectionTransform(const navlib::matrix_t&) return navlib::make_result_code(navlib::navlib_errc::no_data_available); } -long NavlibInterface::GetPivotPosition(navlib::point_t& position) const +long NavlibInterface::GetPivotPosition(navlib::point_t&) const { return navlib::make_result_code(navlib::navlib_errc::no_data_available); } @@ -223,12 +223,12 @@ long NavlibInterface::GetSelectionExtents(navlib::box_t& extents) const return 0l; }); - extents = {boundingBox.MinX, - boundingBox.MinY, - boundingBox.MinZ, - boundingBox.MaxX, - boundingBox.MaxY, - boundingBox.MaxZ}; + extents = {{boundingBox.MinX, + boundingBox.MinY, + boundingBox.MinZ}, + {boundingBox.MaxX, + boundingBox.MaxY, + boundingBox.MaxZ}}; return 0; } From a8cf308ea0477a3415165a658f7e03413f3fff80 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Mon, 24 Mar 2025 15:26:03 +0100 Subject: [PATCH 081/316] Update SetupLibFmt.cmake update fmt to last version --- cMake/FreeCAD_Helpers/SetupLibFmt.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cMake/FreeCAD_Helpers/SetupLibFmt.cmake b/cMake/FreeCAD_Helpers/SetupLibFmt.cmake index 53fce7836b..52b986fe46 100644 --- a/cMake/FreeCAD_Helpers/SetupLibFmt.cmake +++ b/cMake/FreeCAD_Helpers/SetupLibFmt.cmake @@ -34,8 +34,8 @@ macro(SetupLibFmt) cmake_policy(SET CMP0135 NEW) endif() FetchContent_Declare(fmt - URL https://github.com/fmtlib/fmt/archive/refs/tags/9.1.0.zip - URL_MD5 e6754011ff56bfc37631fcc90961e377 + URL https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.zip + URL_MD5 90667b07f34d91554cf8285ae234ff66 ) FetchContent_MakeAvailable(fmt) set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON) From 85179089b10a13691a7ce302152c2c29a095a749 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 25 Mar 2025 00:08:24 +0100 Subject: [PATCH 082/316] [mod] clean code clean --- src/Mod/CAM/PathSimulator/AppGL/MillMotion.h | 2 +- src/Mod/Cloud/App/AppCloud.cpp | 21 +------------------ src/Mod/Material/Gui/ArrayDelegate.cpp | 2 -- src/Mod/Material/Gui/ListDelegate.cpp | 1 - src/Mod/Part/App/ExtrusionHelper.cpp | 1 - src/Mod/TechDraw/App/DrawBrokenView.cpp | 1 - .../App/TopoShapeMakeShapeWithElementMap.cpp | 1 - 7 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h b/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h index 9b9f1d2afd..e6b854a3b7 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h +++ b/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h @@ -22,7 +22,7 @@ #ifndef __mill_operation_h__ #define __mill_operation_h__ -// #include + #include "EndMill.h" #include "linmath.h" namespace MillSim diff --git a/src/Mod/Cloud/App/AppCloud.cpp b/src/Mod/Cloud/App/AppCloud.cpp index 122c82a72f..6d26780d4e 100644 --- a/src/Mod/Cloud/App/AppCloud.cpp +++ b/src/Mod/Cloud/App/AppCloud.cpp @@ -348,23 +348,7 @@ void Cloud::CloudWriter::createBucket() curl_easy_cleanup(curl); } } -// -// #if defined(FC_OS_WIN32) -// -// #include -// #undef timezone -// -// -// int gettimeofday( time_t* tp, struct timezone* tzp) { -// namespace sc = std::chrono; -// sc::system_clock::duration d = sc::system_clock::now().time_since_epoch(); -// sc::seconds s = sc::duration_cast(d); -// tp->tv_sec = s.count(); -// tp->tv_usec = sc::duration_cast(d - s).count(); -// -// return 0; -//} -// #endif + struct Cloud::AmzDatav4* Cloud::ComputeDigestAmzS3v4(char* operation, const char* server, @@ -639,7 +623,6 @@ Cloud::BuildHeaderAmzS3v4(const char* URL, const char* PublicKey, struct Cloud:: struct curl_slist* chunk = nullptr; // Build the Host: entry - // sprintf(header_data,"Host: %s:%s", URL, TCPPort); sprintf(header_data, "Host: %s", URL); chunk = curl_slist_append(chunk, header_data); @@ -1314,7 +1297,6 @@ void Cloud::CloudWriter::pushCloud(const char* FileName, const char* data, long void Cloud::CloudWriter::writeFiles(void) { - // use a while loop because it is possible that while // processing the files, new ones can be added std::string tmp = ""; @@ -1505,7 +1487,6 @@ bool Cloud::Module::cloudRestore(const char* BucketName) doc->setStatus(Document::Restoring, true); try { - // Document::Restore(reader); doc->Restore(reader); } catch (const Base::Exception& e) { diff --git a/src/Mod/Material/Gui/ArrayDelegate.cpp b/src/Mod/Material/Gui/ArrayDelegate.cpp index 91ff581927..0ceebb9519 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.cpp +++ b/src/Mod/Material/Gui/ArrayDelegate.cpp @@ -42,7 +42,6 @@ #include #include #include -// #include #include #include @@ -67,7 +66,6 @@ void ArrayDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - if (_type == Materials::MaterialValue::Quantity) { auto* tableModel = dynamic_cast(index.model()); painter->save(); diff --git a/src/Mod/Material/Gui/ListDelegate.cpp b/src/Mod/Material/Gui/ListDelegate.cpp index bcef1f752a..b725216818 100644 --- a/src/Mod/Material/Gui/ListDelegate.cpp +++ b/src/Mod/Material/Gui/ListDelegate.cpp @@ -42,7 +42,6 @@ #include #include #include -// #include #include #include diff --git a/src/Mod/Part/App/ExtrusionHelper.cpp b/src/Mod/Part/App/ExtrusionHelper.cpp index 64af79e8b6..aabafa7141 100644 --- a/src/Mod/Part/App/ExtrusionHelper.cpp +++ b/src/Mod/Part/App/ExtrusionHelper.cpp @@ -43,7 +43,6 @@ #include #include #include -// #include #include "ExtrusionHelper.h" #include "TopoShape.h" diff --git a/src/Mod/TechDraw/App/DrawBrokenView.cpp b/src/Mod/TechDraw/App/DrawBrokenView.cpp index af7c91fc54..170b09cd3a 100644 --- a/src/Mod/TechDraw/App/DrawBrokenView.cpp +++ b/src/Mod/TechDraw/App/DrawBrokenView.cpp @@ -86,7 +86,6 @@ #include "GeometryObject.h" #include "ShapeExtractor.h" #include "ShapeUtils.h" -// #include "Preferences.h" #include "DrawBrokenView.h" #include "DrawBrokenViewPy.h" diff --git a/tests/src/Mod/Part/App/TopoShapeMakeShapeWithElementMap.cpp b/tests/src/Mod/Part/App/TopoShapeMakeShapeWithElementMap.cpp index 47e74f980b..a0f8bbabc6 100644 --- a/tests/src/Mod/Part/App/TopoShapeMakeShapeWithElementMap.cpp +++ b/tests/src/Mod/Part/App/TopoShapeMakeShapeWithElementMap.cpp @@ -8,7 +8,6 @@ #include "PartTestHelpers.h" #include #include -// #include #include #include From c1970323849800e9e827e9da1104cebaf8a46e65 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 13 Mar 2025 11:54:23 +0100 Subject: [PATCH 083/316] update libkdtree switch to version 0.7.4 fix for a compiler warning inkdtree++/region.hpp fixes of warnings, latest c++ standard compatibility. . --- src/3rdParty/libkdtree/CMakeLists.txt | 2 +- src/3rdParty/libkdtree/COPYING | 2 +- src/3rdParty/libkdtree/ChangeLog | 236 ---------- src/3rdParty/libkdtree/README.md | 10 +- .../libkdtree/examples/CMakeLists.txt | 3 - .../examples/test_find_within_range.cpp | 108 ----- .../libkdtree/examples/test_hayne.cpp | 116 ----- .../libkdtree/examples/test_kdtree.cpp | 424 ------------------ src/3rdParty/libkdtree/kdtree++/iterator.hpp | 4 +- src/3rdParty/libkdtree/kdtree++/kdtree.hpp | 5 +- src/3rdParty/libkdtree/kdtree++/region.hpp | 2 +- .../libkdtree/python-bindings/CMakeLists.txt | 2 +- 12 files changed, 13 insertions(+), 901 deletions(-) delete mode 100644 src/3rdParty/libkdtree/ChangeLog delete mode 100644 src/3rdParty/libkdtree/examples/CMakeLists.txt delete mode 100644 src/3rdParty/libkdtree/examples/test_find_within_range.cpp delete mode 100644 src/3rdParty/libkdtree/examples/test_hayne.cpp delete mode 100644 src/3rdParty/libkdtree/examples/test_kdtree.cpp diff --git a/src/3rdParty/libkdtree/CMakeLists.txt b/src/3rdParty/libkdtree/CMakeLists.txt index a84b167ccd..6fb99292d4 100644 --- a/src/3rdParty/libkdtree/CMakeLists.txt +++ b/src/3rdParty/libkdtree/CMakeLists.txt @@ -1,5 +1,5 @@ +cmake_minimum_required (VERSION 2.8.12) project (libkdtree CXX) -cmake_minimum_required (VERSION 2.6.0) option (BUILD_PYTHON_BINDINGS "Build Python bindings (requires SWIG)") diff --git a/src/3rdParty/libkdtree/COPYING b/src/3rdParty/libkdtree/COPYING index e74fc557b0..7bf5ef81a1 100644 --- a/src/3rdParty/libkdtree/COPYING +++ b/src/3rdParty/libkdtree/COPYING @@ -1,6 +1,6 @@ "The Artistic Licence 2.0" Copyright (c) 2000-2006, The Perl Foundation. -https://www.perlfoundation.org/artistic-license-20.html +http://www.perlfoundation.org/legal/licenses/artistic-2_0.html Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/src/3rdParty/libkdtree/ChangeLog b/src/3rdParty/libkdtree/ChangeLog deleted file mode 100644 index 30fc38e3ee..0000000000 --- a/src/3rdParty/libkdtree/ChangeLog +++ /dev/null @@ -1,236 +0,0 @@ -libkdtree++ ChangeLog -===================== - -2008-11-17 Sylvain Bougerel - - - Added #include in order to compile 'printf' statements in the - file 'examples/test_find_within_range.cpp'. - - Added patch from Max Fellermann in order to compile libkdtree++ with - clang++. - -2009-02-10 Paul Harris - - - Bug fix: was incorrectly casting a pointer when the search key type - was different to the stored type. - -2008-12-30 Paul Harris - - - New function: efficient_replace_and_optimise(). - Yes, its a long name. Sylvain doesn't like it. - The reason for the long name is that it is a dangerous function, - and it will resort whatever vector<> of data that you pass it. - So I wanted the user to really know what they were doing before - they called this function. - - Now calls sqrt() when required in order to search for items - in 'real' distance units... And so it will accept and return distance - in 'real' units (as opposed to squared units). - This is not an ideal solution, we have all sorts of ideas to improve - kdtree which will include less calls to sqrt() for more speed, and - the ability to change the standard euclidean distance measurements - for distance-on-a-sphere or whatever the user wants. - - Changed from using std::sort() to std::nth_element() when optimising - the tree. Performance boost. - - Added lots of tests to check that the find functions are working - correctly when fed edge-cases, including: - - Items that are exactly 'max' distance away from the target. - - When there are no value items to find. - - Templated the find functions so that the target/center point can be - anything that can be accessed via the Accessor. - - Fixes to make it compile. - - - And, a Python wrapper ! See README.Python - - - CMake support now can build the python wrapper and install the headers - and the python wrapper to a destination folder. Its simple, but neat. - Does not install python module into the python site packages or anything - like that. - -2008-11-17 Sylvain Bougerel - - - The version number of the library is now part of the headers. - - Fixed a bug with assignment operator. - - Fixed uninitialized memory problem with valgrind, when printing the - content of the tree. Due to the fact the _M_header was a _Link_type - instead of a _Node_base type and _M_root was a _Base_ptr type instead of - a _Link_type. - - Paul Harris fixed find() by ensuring that the correct node is being - matched during a find(). Thus, fixed a similar problem in erase. Paul - also added a new test courtesy of Hayne. - - Paul Harris augmented test_kdtree with various test on copy - construction, assignment, and formatting operator. - - Paul Harris added support for CMake, which should suit not only - MSVC users but others too. - - Paul Harris fixed bug with compiling with MSVC2005 with the 64bit - warnings turned on. - -2008-11-12 Sylvain Bougerel - - - Fix segfault on the regular iterator when _M_header->_M_right == - _M_root. Fix segfault on the reverse iterator when _M_header->_M_left == - _M_root. - - Besides, it also change the behavior when iterating past the end() or - rend(). Previously this would result in segfaults, now it makes the - iterator points to an undetermined location in the tree, similarly to - the current implementation of GNU libstdc++. - -2008-11-10 Sylvain Bougerel - - - kdtree++/iterator.hpp (KDTree): the decrement iterator was - ill-written. Its buggy behavior, and the use of non-standard - reverse_iterator initialiser needed to be fixed. These error were do to - a previous failed attempt by me at fixing the reverse_iterator. - - This time, I believe I got it right, however it needed the kdtree - structure to be modified. The reason is that without modification it is - not possible to distinguish the "header" from the "root" within the - iterator. This is required for the reverse_iterator to work properly. - - Now the kdtree has an additional pointer that points directly to the - root. The parent pointer of the header is permanently null. And - therefore the header can be distinguished from the root within the - iterator by checking the parent of the current node: if it is null, we - are at the header. - - -2008-11-10 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com) - - - patch from Martin Shreiber to make libkdtree to compile with newer - version of g++-4.2 and g++4.3. - - - patch from Paul Harris to make libkdtree more exception transparent. - -2007-12-08 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com) - - - fix bug where find_nearest() could return the wrong value if a - maximum distance greater than the root distance to the target value - was given in argument to the function. - - - find_nearest() still returns SQUARED value of the distance. You still - have to use sqrt() on the second member of the iterator. - - - find_nearest() behavior was slightly changed: if many nodes are at - the same distance from the target value, the node with the lowest - memory address will be returned. This is to catter for the - reimplementation of find_exact() coming soon. - -2007-12-02 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com) - - - find_nearest() now returned the SQUARED value of the distance for - euclidean space calculation (the default). You have to use sqrt() on - the returned distance (i.e. iterator->second) if you want to read the - absolute distance returned by find_nearest. My apologies for not - making highlighting this beforehand. - - - Increased the performance of find and find_nearest/find_nearest_if by - about 50x to 100x depending on your compilation flags. - - - KDTree are not defined as: - KDTree<__K, _Val, _Acc, _Cmp, _Alloc> - but as: - KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc> - So pay attention to the _Dist functor. The distance functor calculate - the squared difference between 2 elements returned by the accessor. You - might have to change your code to reflect the new definition, or it wont - compile if you have set custom accessor and comparison functors. - - - The following functors are now accessible in the tree: - - the comparison functor, accessible by copy only - - the accessor functor, accessible by copy only - - the distance functor, accessible read-write, this means that - you can modify the behavior of find, find_nearest, - find_nearest_if within the same KDTree object. - - - find_exact has not be modified and retained the code of the former, - slower algorithm. I have to write some more code to do this. Pls wait a - little more. - - - The file accessor.hpp was renamed as function.hpp for it now boast - more than just the KDTree accessor - -2007-11-25 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com) - - - fixed the reverse_iterator. Now it can be used. - -2007-10-24 Sylvain Bougerel (sylvain.bougerel.devel@gmail.com) - - - Removal of all the warnings that are yield by the compiler when - using the following flags: - -Wall -pedantic -ansi - Do not hesitate to suggest any flags for additional code checking. - - This release also feature numerous of enhancements by Paul Harris - (paulharris@computer.org): - - const kdtrees can be searched - - find_nearest_if() enforce validation of a predicate - - visit_within_range() walk the tree and calls - Visitor::operator() on template argument for - each node within the range - - find_exact() matches an kdtree::value_type by location and by - calling kdtree::value_type::operator==() (in case two different - items have the same location find_exact() will not return the - wrong item) - - erase_exact() is to erase() what find_exact() is to find() - - check_tree() and num_dist_calcs for debugging purpose plus - additional improvements on erase and region intersection - -2004-11-26 Paul Harris (paulharris@computer.org) - - - New feature: find_nearest() - - Accessors can now be initialised with the tree, so ptr_fun() - or functors can be used to access datapoints. - - Accessors now much more generic, so you can use the same - accessor to access multiple types. - - Range-constructors now optimise() automatically, simplifying - the construction of a filled tree. - - _Range is now more easy to construct. - -2004-11-15 Martin F. Krafft (libkdtree@pobox.madduck.net) - - - fixed numerous little bugs that led to compilation problems - - changed code to compile cleanly with GCC 3.4 and GCC 4.0 - -2004-11-06 Martin F. Krafft (libkdtree@pobox.madduck.net) - - - reverted to optimise() to prevent API change, and added an optimize() - passthrough method with an appropriate comment. - -2004-11-05 Paul Harris (paulharris@computer.org) - - - Renamed optimise() to optimize(). - - Added a full set of range constructors and insert(range) methods. - it now works with inserter(tree,tree.begin()) - - Target type no longer needs a default constructor. This also fixes - problems with empty trees (would crash if optimized). - - Some code cleanup (removed inlines, switched from const_iterator to - iterator, added this-> to ensure the methods are called). - - Added a new method: count_within_range(). - - Fixed bug in rend(). - -2004-11-04 Martin F. Krafft (libkdtree@pobox.madduck.net) - - - Integrated patch by Paul Harris to fix a logic error pertaining to - OutputIterators in find_within_range. find_within_range() now - returns the output iterator instead of a count. Thanks, Paul! - - Added another fix by Paul Harris to _M_get_j_max, which would cause - a dimensional overflow for trees with depths >= K. Thanks (again) Paul! - - Made some improvements to the autotools files. - -2004-05-11 Martin F. Krafft (libkdtree@pobox.madduck.net) - - - Fixed CFlags and Libs entries in pkgconfig file. - -2004-05-11 Martin F. Krafft (libkdtree@pobox.madduck.net) - - - Initial release. - - - COPYRIGHT -- - libkdtree++ is (c) 2004-2007 Martin F. Krafft and - Sylvain Bougerel and distributed under the - terms of the Artistic License 2.0. See the ./COPYING file in the source tree - root for more information. - - THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND - FITNESS FOR A PARTICULAR PURPOSE. diff --git a/src/3rdParty/libkdtree/README.md b/src/3rdParty/libkdtree/README.md index 1d3eed9c7a..b7364c581b 100644 --- a/src/3rdParty/libkdtree/README.md +++ b/src/3rdParty/libkdtree/README.md @@ -24,12 +24,12 @@ Please leave bugreports on Github Issues page . +This page seems to be gone now, available only via WebArchive. This is a mirror and a fork of that original repository, created in 2011 and maintained ever since. -Notes of the original author are preserved below. +Notes of the original author a preserved below. Installation ------------ @@ -114,8 +114,8 @@ without the help of a number of people. Foremost, I would like to thank the folks from the #c++ channel on Freenode, specifically (in no particular order) orbitz, quix, Erwin, pwned, wcstok, dasOp, Chaku, Adrinael, The_Vulture, and LIM2 (if I left anyone out, let me know). Finally, I thank the Artificial -Intelligence Laboratory of the University of Zurich, Dr. Peter Eggenberger, and -Gabriel Gómez for giving me the opportunity to write this stuff. +Intelligence Laboratory of the University of Zurich, Dr. Peter Eggenberger and +Gabriel Gómez for giving me the opportunity to write this stuff. Since libkdtree++ makes an effort to stay as close as possible to the feel of a STL container, concepts and inspiration was gained from the SGI C++ diff --git a/src/3rdParty/libkdtree/examples/CMakeLists.txt b/src/3rdParty/libkdtree/examples/CMakeLists.txt deleted file mode 100644 index 9b4cc4ff0c..0000000000 --- a/src/3rdParty/libkdtree/examples/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_executable (test_hayne test_hayne.cpp) -add_executable (test_kdtree test_kdtree.cpp) -add_executable (test_find_within_range test_find_within_range.cpp) diff --git a/src/3rdParty/libkdtree/examples/test_find_within_range.cpp b/src/3rdParty/libkdtree/examples/test_find_within_range.cpp deleted file mode 100644 index 62214f606b..0000000000 --- a/src/3rdParty/libkdtree/examples/test_find_within_range.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Thanks to James Remillard -// -#include -#include -#include -#include -#include - -using namespace std; - -struct kdtreeNode -{ - typedef double value_type; - - double xyz[3]; - size_t index; - - value_type operator[](size_t n) const - { - return xyz[n]; - } - - double distance( const kdtreeNode &node) - { - double x = xyz[0] - node.xyz[0]; - double y = xyz[1] - node.xyz[1]; - double z = xyz[2] - node.xyz[2]; - -// this is not correct return sqrt( x*x+y*y+z*z); - -// this is what kdtree checks with find_within_range() -// the "manhattan distance" from the search point. -// effectively, distance is the maximum distance in any one dimension. - return max(fabs(x),max(fabs(y),fabs(z))); - - } -}; - -int main(int argc,char *argv[]) -{ - vector pts; - - typedef KDTree::KDTree<3,kdtreeNode> treeType; - - treeType tree; - - // make random 3d points - for ( size_t n = 0; n < 10000; ++n) - { - kdtreeNode node; - node.xyz[0] = double(rand())/RAND_MAX; - node.xyz[1] = double(rand())/RAND_MAX; - node.xyz[2] = double(rand())/RAND_MAX; - node.index = n; - - tree.insert( node); - pts.push_back( node); - } - - for (size_t r = 0; r < 1000; ++r) - { - kdtreeNode refNode; - refNode.xyz[0] = double(rand())/RAND_MAX; - refNode.xyz[1] = double(rand())/RAND_MAX; - refNode.xyz[2] = double(rand())/RAND_MAX; - - double limit = double(rand())/RAND_MAX; - - // find the correct return list by checking every single point - set correctCloseList; - - for ( size_t i= 0; i < pts.size(); ++i) - { - double dist = refNode.distance( pts[i]); - if ( dist < limit) - correctCloseList.insert( i ); - } - - // now do the same with the kdtree. - vector howClose; - tree.find_within_range(refNode,limit,back_insert_iterator >(howClose)); - - // make sure no extra points are returned, and the return has no missing points. - for ( size_t i = 0; i < howClose.size(); ++i) - { - set::iterator hit = correctCloseList.find( howClose[i].index); - - if ( hit != correctCloseList.end()) - { - correctCloseList.erase(hit); - } - else - { - // point that is too far away - fail! - assert(false); - printf("fail, extra points.\n"); - } - } - - // fail, not all of the close enough points returned. - assert( correctCloseList.size() == 0); - if ( correctCloseList.size() > 0) - { - printf("fail, missing points.\n"); - } - } -} - diff --git a/src/3rdParty/libkdtree/examples/test_hayne.cpp b/src/3rdParty/libkdtree/examples/test_hayne.cpp deleted file mode 100644 index 6771727fdc..0000000000 --- a/src/3rdParty/libkdtree/examples/test_hayne.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#define KDTREE_SIZE_T unsigned int -#include - -#include -#include -#include -#include - -using namespace std; - -struct duplet -{ - typedef int value_type; - - inline value_type operator[](int const N) const { return d[N]; } - - inline bool operator==(duplet const& other) const - { - return this->d[0] == other.d[0] && this->d[1] == other.d[1]; - } - - inline bool operator!=(duplet const& other) const - { - return this->d[0] != other.d[0] || this->d[1] != other.d[1]; - } - - friend ostream & operator<<(ostream & o, duplet const& d) - { - return o << "(" << d[0] << "," << d[1] << ")"; - } - - value_type d[2]; -}; - -typedef KDTree::KDTree<2, duplet, std::pointer_to_binary_function > duplet_tree_type; - -inline double return_dup( duplet d, int k ) { return d[k]; } - - - -int main() -{ - duplet_tree_type dupl_tree_test(std::ptr_fun(return_dup)); - std::vector vDuplets; - - //srand(time(0)); - int randy1 = 0; - int randy2 = 0; - for (int i=0; i<700; i++) - { - //create coordinate for new duplet - randy1+=2; - randy1=randy1%255; - randy2+=3; - randy2=randy2%255; - //randy1 = rand() % 255; - //randy2 = rand() % 255; - - //new duplet - duplet super_dupre = { {randy1, randy2} }; - - //check if duplet with same coordinate already in vector/tree. If not: insert in vector and tree - duplet_tree_type::iterator pItr = dupl_tree_test.find_nearest(super_dupre,std::numeric_limits::max()).first; - if (*pItr!=super_dupre) - { - dupl_tree_test.insert(super_dupre); - vDuplets.push_back(super_dupre); - } - } - - dupl_tree_test.optimise(); - - size_t elements; - - while (vDuplets.size() > 0) //delete all duplets from tree which are in the vector - { - elements = vDuplets.size(); - - duplet element_to_erase = vDuplets.back(); - vDuplets.pop_back(); - - if (vDuplets.size() == 147) - cout << "THIS IS THE BUG TRIGGER" << endl; - - cout << vDuplets.size() << " : Deleting " << element_to_erase << endl; - - assert( find(dupl_tree_test.begin(),dupl_tree_test.end(), element_to_erase) != dupl_tree_test.end() ); - assert(dupl_tree_test.find(element_to_erase) != dupl_tree_test.end()); - - duplet_tree_type::iterator will = dupl_tree_test.find(element_to_erase); - duplet_tree_type::iterator should = dupl_tree_test.find_exact(element_to_erase); - - cout << " tree will delete: " << *will << endl; - cout << " tree should delete: " << *should << endl; - - assert(*will == *should); - - dupl_tree_test.erase(element_to_erase); //erase() : will probably erase wrong element sooner or later - //dupl_tree_test.erase_exact(element_to_erase); --> this works - - // now check that it cannot find the element UNLESS there is another one with the identical location in the list... - if (find(vDuplets.begin(),vDuplets.end(),element_to_erase) == vDuplets.end()) - { - duplet_tree_type::iterator not_there = dupl_tree_test.find(element_to_erase); - if (not_there != dupl_tree_test.end()) - { - cout << "SHOULD NOT HAVE FOUND THIS: " << *not_there << endl; - assert(0); - } - else - { - cout << " find() double-check passed." << endl; - } - } - } -} diff --git a/src/3rdParty/libkdtree/examples/test_kdtree.cpp b/src/3rdParty/libkdtree/examples/test_kdtree.cpp deleted file mode 100644 index 4bbd9a2e4e..0000000000 --- a/src/3rdParty/libkdtree/examples/test_kdtree.cpp +++ /dev/null @@ -1,424 +0,0 @@ -#define KDTREE_DEFINE_OSTREAM_OPERATORS - -// Make SURE all our asserts() are checked -#undef NDEBUG - -#include - -#include -#include -#include -#include -#include -#include - -// used to ensure all triplets that are accessed via the operator<< are initialised. -std::set registered; - -struct triplet -{ - typedef double value_type; - - triplet(value_type a, value_type b, value_type c) - { - d[0] = a; - d[1] = b; - d[2] = c; - bool reg_ok = (registered.find(this) == registered.end()); - assert(reg_ok); - bool reg_inserted_ok = registered.insert(this).second; - assert(reg_inserted_ok); - } - - triplet(const triplet & x) - { - d[0] = x.d[0]; - d[1] = x.d[1]; - d[2] = x.d[2]; - bool reg_ok = (registered.find(this) == registered.end()); - assert(reg_ok); - bool reg_inserted_ok = registered.insert(this).second; - assert(reg_inserted_ok); - } - - ~triplet() - { - bool unreg_ok = (registered.find(this) != registered.end()); - assert(unreg_ok); - registered.erase(this); - } - - double distance_to(triplet const& x) const - { - double dist = 0; - for (int i = 0; i != 3; ++i) - dist += (d[i]-x.d[i])*(d[i]-x.d[i]); - return std::sqrt(dist); - } - - inline value_type operator[](size_t const N) const { return d[N]; } - - value_type d[3]; -}; - - - -// same as triplet, except with the values reversed. -struct alternate_triplet -{ - typedef double value_type; - - alternate_triplet(const triplet & x) - { - d[0] = x.d[2]; - d[1] = x.d[1]; - d[2] = x.d[0]; - } - - inline value_type operator[](size_t const N) const { return d[2-N]; } - - value_type d[3]; -}; - -inline bool operator==(triplet const& A, triplet const& B) { - return A.d[0] == B.d[0] && A.d[1] == B.d[1] && A.d[2] == B.d[2]; -} - -std::ostream& operator<<(std::ostream& out, triplet const& T) -{ - assert(registered.find(&T) != registered.end()); - return out << '(' << T.d[0] << ',' << T.d[1] << ',' << T.d[2] << ')'; -} - -inline double tac( triplet t, size_t k ) { return t[k]; } - -// use tac as a class instead of a function, -// can access more than one type with just 1 definition. -struct alternate_tac -{ - typedef double result_type; - double operator()( triplet const& t, size_t k ) const { return t[k]; } - double operator()( alternate_triplet const& t, size_t k ) const { return t[k]; } -}; - - -typedef KDTree::KDTree<3, triplet, std::pointer_to_binary_function > tree_type; - -struct Predicate -{ - bool operator()( triplet const& t ) const - { - return t[0] > 3; // anything, we are currently testing that it compiles. - } -}; - -// never finds anything -struct FalsePredicate -{ - bool operator()( triplet const& t ) const { return false; } -}; - -int main() -{ - // check that it'll find nodes exactly MAX away - { - tree_type exact_dist(std::ptr_fun(tac)); - triplet c0(5, 4, 0); - exact_dist.insert(c0); - triplet target(7,4,0); - - std::pair found = exact_dist.find_nearest(target,2); - assert(found.first != exact_dist.end()); - assert(found.second == 2); - std::cout << "Test find_nearest(), found at exact distance away from " << target << ", found " << *found.first << std::endl; - } - - // do the same test, except use alternate_triplet as the search key - { - // NOTE: stores triplet, but we search with alternate_triplet - typedef KDTree::KDTree<3, triplet, alternate_tac> alt_tree; - - triplet actual_target(7,0,0); - - alt_tree tree; - tree.insert( triplet(0, 0, 7) ); - tree.insert( triplet(0, 0, 7) ); - tree.insert( triplet(0, 0, 7) ); - tree.insert( triplet(3, 0, 0) ); - tree.insert( actual_target ); - tree.optimise(); - - alternate_triplet target( actual_target ); - - std::pair found = tree.find_nearest(target); - assert(found.first != tree.end()); - std::cout << "Test with alternate search type, found: " << *found.first << ", wanted " << actual_target << std::endl; - assert(found.second == 0); - assert(*found.first == actual_target); - } - - - { - tree_type exact_dist(std::ptr_fun(tac)); - triplet c0(5, 2, 0); - exact_dist.insert(c0); - triplet target(7,4,0); - - // call find_nearest without a range value - it found a compile error earlier. - std::pair found = exact_dist.find_nearest(target); - assert(found.first != exact_dist.end()); - std::cout << "Test find_nearest(), found at exact distance away from " << target << ", found " << *found.first << " @ " << found.second << " should be " << std::sqrt(8) << std::endl; - assert(found.second == std::sqrt(8)); - } - - { - tree_type exact_dist(std::ptr_fun(tac)); - triplet c0(5, 2, 0); - exact_dist.insert(c0); - triplet target(7,4,0); - - std::pair found = exact_dist.find_nearest(target,std::sqrt(8)); - assert(found.first != exact_dist.end()); - std::cout << "Test find_nearest(), found at exact distance away from " << target << ", found " << *found.first << " @ " << found.second << " should be " << std::sqrt(8) << std::endl; - assert(found.second == std::sqrt(8)); - } - - tree_type src(std::ptr_fun(tac)); - - triplet c0(5, 4, 0); src.insert(c0); - triplet c1(4, 2, 1); src.insert(c1); - triplet c2(7, 6, 9); src.insert(c2); - triplet c3(2, 2, 1); src.insert(c3); - triplet c4(8, 0, 5); src.insert(c4); - triplet c5(5, 7, 0); src.insert(c5); - triplet c6(3, 3, 8); src.insert(c6); - triplet c7(9, 7, 3); src.insert(c7); - triplet c8(2, 2, 6); src.insert(c8); - triplet c9(2, 0, 6); src.insert(c9); - - std::cout << src << std::endl; - - src.erase(c0); - src.erase(c1); - src.erase(c3); - src.erase(c5); - - src.optimise(); - - - // test the efficient_replace_and_optimise() - tree_type eff_repl = src; - { - std::vector vec; - // erased above as part of test vec.push_back(triplet(5, 4, 0)); - // erased above as part of test vec.push_back(triplet(4, 2, 1)); - vec.push_back(triplet(7, 6, 9)); - // erased above as part of test vec.push_back(triplet(2, 2, 1)); - vec.push_back(triplet(8, 0, 5)); - // erased above as part of test vec.push_back(triplet(5, 7, 0)); - vec.push_back(triplet(3, 3, 8)); - vec.push_back(triplet(9, 7, 3)); - vec.push_back(triplet(2, 2, 6)); - vec.push_back(triplet(2, 0, 6)); - - eff_repl.clear(); - eff_repl.efficient_replace_and_optimise(vec); - } - - - std::cout << std::endl << src << std::endl; - - tree_type copied(src); - std::cout << copied << std::endl; - tree_type assigned = src; - std::cout << assigned << std::endl; - - for (int loop = 0; loop != 4; ++loop) - { - tree_type * target; - switch (loop) - { - case 0: std::cout << "Testing plain construction" << std::endl; - target = &src; - break; - - case 1: std::cout << "Testing copy-construction" << std::endl; - target = &copied; - break; - - case 2: std::cout << "Testing assign-construction" << std::endl; - target = &assigned; - break; - - default: - case 4: std::cout << "Testing efficient-replace-and-optimise" << std::endl; - target = &eff_repl; - break; - } - tree_type & t = *target; - - int i=0; - for (tree_type::const_iterator iter=t.begin(); iter!=t.end(); ++iter, ++i); - std::cout << "iterator walked through " << i << " nodes in total" << std::endl; - if (i!=6) - { - std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl; - return 1; - } - i=0; - for (tree_type::const_reverse_iterator iter=t.rbegin(); iter!=t.rend(); ++iter, ++i); - std::cout << "reverse_iterator walked through " << i << " nodes in total" << std::endl; - if (i!=6) - { - std::cerr << "Error: does not tally with the expected number of nodes (6)" << std::endl; - return 1; - } - - triplet s(5, 4, 3); - std::vector v; - unsigned int const RANGE = 3; - - size_t count = t.count_within_range(s, RANGE); - std::cout << "counted " << count - << " nodes within range " << RANGE << " of " << s << ".\n"; - t.find_within_range(s, RANGE, std::back_inserter(v)); - - std::cout << "found " << v.size() << " nodes within range " << RANGE - << " of " << s << ":\n"; - std::vector::const_iterator ci = v.begin(); - for (; ci != v.end(); ++ci) - std::cout << *ci << " "; - std::cout << "\n" << std::endl; - - std::cout << std::endl << t << std::endl; - - // search for all the nodes at exactly 0 dist away - for (tree_type::const_iterator target = t.begin(); target != t.end(); ++target) - { - std::pair found = t.find_nearest(*target,0); - assert(found.first != t.end()); - assert(*found.first == *target); - std::cout << "Test find_nearest(), found at exact distance away from " << *target << ", found " << *found.first << std::endl; - } - - { - const double small_dist = 0.0001; - std::pair notfound = t.find_nearest(s,small_dist); - std::cout << "Test find_nearest(), nearest to " << s << " within " << small_dist << " should not be found" << std::endl; - - if (notfound.first != t.end()) - { - std::cout << "ERROR found a node at dist " << notfound.second << " : " << *notfound.first << std::endl; - std::cout << "Actual distance = " << s.distance_to(*notfound.first) << std::endl; - } - - assert(notfound.first == t.end()); - } - - { - std::pair nif = t.find_nearest_if(s,std::numeric_limits::max(),Predicate()); - std::cout << "Test find_nearest_if(), nearest to " << s << " @ " << nif.second << ": " << *nif.first << std::endl; - - std::pair cantfind = t.find_nearest_if(s,std::numeric_limits::max(),FalsePredicate()); - std::cout << "Test find_nearest_if(), nearest to " << s << " should never be found (predicate too strong)" << std::endl; - assert(cantfind.first == t.end()); - } - - - - - { - std::pair found = t.find_nearest(s,std::numeric_limits::max()); - std::cout << "Nearest to " << s << " @ " << found.second << " " << *found.first << std::endl; - std::cout << "Should be " << found.first->distance_to(s) << std::endl; - // NOTE: the assert does not check for an exact match, as it is not exact when -O2 or -O3 is - // switched on. Some sort of optimisation makes the math inexact. - assert( fabs(found.second - found.first->distance_to(s)) < std::numeric_limits::epsilon() ); - } - - { - triplet s2(10, 10, 2); - std::pair found = t.find_nearest(s2,std::numeric_limits::max()); - std::cout << "Nearest to " << s2 << " @ " << found.second << " " << *found.first << std::endl; - std::cout << "Should be " << found.first->distance_to(s2) << std::endl; - // NOTE: the assert does not check for an exact match, as it is not exact when -O2 or -O3 is - // switched on. Some sort of optimisation makes the math inexact. - assert( fabs(found.second - found.first->distance_to(s2)) < std::numeric_limits::epsilon() ); - } - - std::cout << std::endl; - - std::cout << t << std::endl; - - // Testing iterators - { - std::cout << "Testing iterators" << std::endl; - - t.erase(c2); - t.erase(c4); - t.erase(c6); - t.erase(c7); - t.erase(c8); - // t.erase(c9); - - std::cout << std::endl << t << std::endl; - - std::cout << "Forward iterator test..." << std::endl; - std::vector forwards; - for (tree_type::iterator i = t.begin(); i != t.end(); ++i) - { std::cout << *i << " " << std::flush; forwards.push_back(*i); } - std::cout << std::endl; - std::cout << "Reverse iterator test..." << std::endl; - std::vector backwards; - for (tree_type::reverse_iterator i = t.rbegin(); i != t.rend(); ++i) - { std::cout << *i << " " << std::flush; backwards.push_back(*i); } - std::cout << std::endl; - std::reverse(backwards.begin(),backwards.end()); - assert(backwards == forwards); - } - } - - - // Walter reported that the find_within_range() wasn't giving results that were within - // the specified range... this is the test. - { - tree_type tree(std::ptr_fun(tac)); - tree.insert( triplet(28.771200,16.921600,-2.665970) ); - tree.insert( triplet(28.553101,18.649700,-2.155560) ); - tree.insert( triplet(28.107500,20.341400,-1.188940) ); - tree.optimise(); - - std::deque< triplet > vectors; - triplet sv(18.892500,20.341400,-1.188940); - tree.find_within_range(sv, 10.0f, std::back_inserter(vectors)); - - std::cout << std::endl << "Test find_with_range( " << sv << ", 10.0f) found " << vectors.size() << " candidates." << std::endl; - - // double-check the ranges - for (std::deque::iterator v = vectors.begin(); v != vectors.end(); ++v) - { - double dist = sv.distance_to(*v); - std::cout << " " << *v << " dist=" << dist << std::endl; - if (dist > 10.0f) - std::cout << " This point is too far! But that is by design, its within a 'box' with a 'radius' of 10, not a sphere with a radius of 10" << std::endl; - // Not a valid test, it can be greater than 10 if the point is in the corners of the box. - // assert(dist <= 10.0f); - } - } - - - return 0; -} - -/* COPYRIGHT -- - * - * This file is part of libkdtree++, a C++ template KD-Tree sorting container. - * libkdtree++ is (c) 2004-2007 Martin F. Krafft - * and Sylvain Bougerel distributed under the - * terms of the Artistic License 2.0. See the ./COPYING file in the source tree - * root for more information. - * - * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES - * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ diff --git a/src/3rdParty/libkdtree/kdtree++/iterator.hpp b/src/3rdParty/libkdtree/kdtree++/iterator.hpp index 05ea9db9e4..4b24ea1a95 100644 --- a/src/3rdParty/libkdtree/kdtree++/iterator.hpp +++ b/src/3rdParty/libkdtree/kdtree++/iterator.hpp @@ -54,8 +54,8 @@ namespace KDTree inline _Base_iterator(_Base_const_ptr const __N = NULL) : _M_node(__N) {} - //inline _Base_iterator(_Base_iterator const& __THAT) - // : _M_node(__THAT._M_node) {} + inline _Base_iterator(_Base_iterator const& __THAT) + : _M_node(__THAT._M_node) {} inline void _M_increment() diff --git a/src/3rdParty/libkdtree/kdtree++/kdtree.hpp b/src/3rdParty/libkdtree/kdtree++/kdtree.hpp index 27a41a28bf..6e49d77395 100644 --- a/src/3rdParty/libkdtree/kdtree++/kdtree.hpp +++ b/src/3rdParty/libkdtree/kdtree++/kdtree.hpp @@ -53,12 +53,12 @@ // KDTREE_VERSION % 100 is the patch level // KDTREE_VERSION / 100 % 1000 is the minor version // KDTREE_VERSION / 100000 is the major version -#define KDTREE_VERSION 702 +#define KDTREE_VERSION 704 // // KDTREE_LIB_VERSION must be defined to be the same as KDTREE_VERSION // but as a *string* in the form "x_y[_z]" where x is the major version // number, y is the minor version number, and z is the patch level if not 0. -#define KDTREE_LIB_VERSION "0_7_2" +#define KDTREE_LIB_VERSION "0_7_4" #include @@ -1214,7 +1214,6 @@ protected: o << "dimensions: " << __K << std::endl; typedef KDTree<__K, _Val, _Acc, _Dist, _Cmp, _Alloc> _Tree; - typedef typename _Tree::_Link_type _Link_type; std::stack<_Link_const_type> s; s.push(tree._M_get_root()); diff --git a/src/3rdParty/libkdtree/kdtree++/region.hpp b/src/3rdParty/libkdtree/kdtree++/region.hpp index 6e5a750502..cb0ec868fb 100644 --- a/src/3rdParty/libkdtree/kdtree++/region.hpp +++ b/src/3rdParty/libkdtree/kdtree++/region.hpp @@ -27,7 +27,7 @@ namespace KDTree typedef std::pair<_Region,_SubVal> _CenterPt; _Region(_Acc const& __acc=_Acc(), const _Cmp& __cmp=_Cmp()) - : _M_cmp(__cmp), _M_acc(__acc) {} + : _M_acc(__acc), _M_cmp(__cmp) {} template _Region(Val const& __V, diff --git a/src/3rdParty/libkdtree/python-bindings/CMakeLists.txt b/src/3rdParty/libkdtree/python-bindings/CMakeLists.txt index 09cfff97e4..4200cf4110 100644 --- a/src/3rdParty/libkdtree/python-bindings/CMakeLists.txt +++ b/src/3rdParty/libkdtree/python-bindings/CMakeLists.txt @@ -10,7 +10,7 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}/..) # Build the _kdtree python module set_source_files_properties (py-kdtree.i PROPERTIES CPLUSPLUS ON) swig_add_module (kdtree python py-kdtree.i) -swig_link_libraries (kdtree ${Python3_LIBRARIES}) +swig_link_libraries (kdtree ${PYTHON_LIBRARIES}) # Copy the test file into the build dir install (FILES py-kdtree_test.py DESTINATION ${CMAKE_INSTALL_PREFIX}/python) From 9153926cbff18ff35576450f3439dc1d7d80439b Mon Sep 17 00:00:00 2001 From: Tiago Almeida Date: Mon, 24 Mar 2025 14:52:15 +0000 Subject: [PATCH 084/316] fix #20005: material editor issue -Changed info.baseName() to info.fileName().remove(QStringLiteral(".FCMat"), Qt::CaseInsensitive) in MaterialLibrary.cpp to ensure that only the extension ".FCmat" is removed from the file name bacause the previous version was removing everything in front of the first dot --- src/Mod/Material/App/MaterialLibrary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Material/App/MaterialLibrary.cpp b/src/Mod/Material/App/MaterialLibrary.cpp index 14446afeb0..76f46a5e50 100644 --- a/src/Mod/Material/App/MaterialLibrary.cpp +++ b/src/Mod/Material/App/MaterialLibrary.cpp @@ -315,7 +315,7 @@ MaterialLibraryLocal::saveMaterial(const std::shared_ptr& material, stream.setGenerateByteOrderMark(true); // Write the contents - material->setName(info.baseName()); + material->setName(info.fileName().remove(QStringLiteral(".FCMat"), Qt::CaseInsensitive)); material->setLibrary(getptr()); material->setDirectory(getRelativePath(path)); material->save(stream, overwrite, saveAsCopy, saveInherited); From 0986dadb2fdd5341bcb78fa8b0e5df923c50f617 Mon Sep 17 00:00:00 2001 From: Kevin Martin Date: Mon, 31 Mar 2025 12:20:37 -0400 Subject: [PATCH 085/316] Correct non-gui DXF C++ importer to not generate pending python exceptions (#20328) * Add a test case for DXF import * Test gui flag rather than look for import error to make gui decision The new code is cleaner and faster and avoids any exception stuff * Properly avoid trying to use Layer's View object in non-GUI The code was trying to avoid this but had a Python None object rather than a null C++ pointer and so tried setting a property on None. This left an unhandled exception state which acted as a booby trap that caused the later failure of some unrelated code. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * De-lint, remove wong "unsupported" message Hidden layers have been supported for a while but still generated an import note about this being unsupported. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Mod/Draft/importDXF.py | 14 +- src/Mod/Import/App/dxf/ImpExpDxf.cpp | 21 +- src/Mod/Import/App/dxf/ImpExpDxf.h | 3 +- src/Mod/Import/App/dxf/dxf.cpp | 3 - src/Mod/Test/CMakeLists.txt | 1 + src/Mod/Test/Document.py | 44 + src/Mod/Test/TestData/DXFSample.dxf | 2310 ++++++++++++++++++++++++++ 7 files changed, 2373 insertions(+), 23 deletions(-) create mode 100644 src/Mod/Test/TestData/DXFSample.dxf diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 4be863fc73..e670dfeb22 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -2828,13 +2828,12 @@ def open(filename): doc = FreeCAD.newDocument(docname) doc.Label = docname FreeCAD.setActiveDocument(doc.Name) - try: + if gui: import ImportGui - except Exception: + ImportGui.readDXF(filename) + else: import Import Import.readDXF(filename) - else: - ImportGui.readDXF(filename) Draft.convert_draft_texts() # convert annotations to Draft texts doc.recompute() @@ -2871,13 +2870,12 @@ def insert(filename, docname): else: errorDXFLib(gui) else: - try: + if gui: import ImportGui - except Exception: + ImportGui.readDXF(filename) + else: import Import Import.readDXF(filename) - else: - ImportGui.readDXF(filename) Draft.convert_draft_texts() # convert annotations to Draft texts doc.recompute() diff --git a/src/Mod/Import/App/dxf/ImpExpDxf.cpp b/src/Mod/Import/App/dxf/ImpExpDxf.cpp index 913d53aae6..ab9f87c2e9 100644 --- a/src/Mod/Import/App/dxf/ImpExpDxf.cpp +++ b/src/Mod/Import/App/dxf/ImpExpDxf.cpp @@ -462,7 +462,7 @@ void ImpExpDxfRead::ExpandInsert(const std::string& name, double rotation, const Base::Vector3d& scale) { - if (Blocks.count(name) == 0) { + if (!Blocks.contains(name)) { ImportError("Reference to undefined or external block '%s'\n", name); return; } @@ -607,15 +607,14 @@ ImpExpDxfRead::Layer::Layer(const std::string& name, std::string&& lineType, PyObject* drawingLayer) : CDxfRead::Layer(name, color, std::move(lineType)) - , DraftLayerView(drawingLayer == nullptr ? nullptr + , DraftLayerView(drawingLayer == nullptr ? Py_None : PyObject_GetAttrString(drawingLayer, "ViewObject")) - , GroupContents( - drawingLayer == nullptr - ? nullptr - : (App::PropertyLinkListHidden*)(((App::FeaturePythonPyT*) - drawingLayer) - ->getPropertyContainerPtr()) - ->getDynamicPropertyByName("Group")) + , GroupContents(drawingLayer == nullptr + ? nullptr + : dynamic_cast( + (((App::FeaturePythonPyT*)drawingLayer) + ->getPropertyContainerPtr()) + ->getDynamicPropertyByName("Group"))) {} ImpExpDxfRead::Layer::~Layer() { @@ -631,7 +630,7 @@ void ImpExpDxfRead::Layer::FinishLayer() const // App::FeaturePython, and its Proxy is a draftobjects.layer.Layer GroupContents->setValue(Contents); } - if (DraftLayerView != nullptr && Hidden) { + if (DraftLayerView != Py_None && Hidden) { // Hide the Hidden layers if possible (if GUI exists) // We do this now rather than when the layer is created so all objects // within the layers also become hidden. @@ -672,7 +671,7 @@ ImpExpDxfRead::MakeLayer(const std::string& name, ColorIndex_t color, std::strin "Solid"); } auto result = new Layer(name, color, std::move(lineType), layer); - if (result->DraftLayerView != nullptr) { + if (result->DraftLayerView != Py_None) { PyObject_SetAttrString(result->DraftLayerView, "OverrideLineColorChildren", Py_False); PyObject_SetAttrString(result->DraftLayerView, "OverrideShapeAppearanceChildren", diff --git a/src/Mod/Import/App/dxf/ImpExpDxf.h b/src/Mod/Import/App/dxf/ImpExpDxf.h index 3c71aa1f29..c7f86715d5 100644 --- a/src/Mod/Import/App/dxf/ImpExpDxf.h +++ b/src/Mod/Import/App/dxf/ImpExpDxf.h @@ -147,6 +147,7 @@ protected: void operator=(const Layer&) = delete; void operator=(Layer&&) = delete; ~Layer() override; + // The View object for the layer or Py_None (e.g. if no gui) PyObject* const DraftLayerView; std::vector Contents; void FinishLayer() const; @@ -334,7 +335,7 @@ protected: const std::string& name, double rotation) override { - InsertsList[Reader.m_entityAttributes].push_back( + InsertsList[Reader.m_entityAttributes].emplace_back( Block::Insert(name, point, rotation, scale)); } diff --git a/src/Mod/Import/App/dxf/dxf.cpp b/src/Mod/Import/App/dxf/dxf.cpp index 0799e021ba..2672b264b2 100644 --- a/src/Mod/Import/App/dxf/dxf.cpp +++ b/src/Mod/Import/App/dxf/dxf.cpp @@ -2950,9 +2950,6 @@ bool CDxfRead::ReadLayer() // TODO: Should have an import option to omit frozen layers. UnsupportedFeature("Frozen layers"); } - if (layerColor < 0) { - UnsupportedFeature("Hidden layers"); - } Layers[layername] = MakeLayer(layername, layerColor, std::move(lineTypeName)); return true; } diff --git a/src/Mod/Test/CMakeLists.txt b/src/Mod/Test/CMakeLists.txt index acc7140276..32dad5493e 100644 --- a/src/Mod/Test/CMakeLists.txt +++ b/src/Mod/Test/CMakeLists.txt @@ -25,6 +25,7 @@ SET(TestData_SRCS TestData/bad_xml.xml TestData/bad_version.xml TestData/content_items.xml + TestData/DXFSample.dxf ) SOURCE_GROUP("" FILES ${Test_SRCS} ${TestData_SRCS}) diff --git a/src/Mod/Test/Document.py b/src/Mod/Test/Document.py index 9ad30c9f28..bf48b4811d 100644 --- a/src/Mod/Test/Document.py +++ b/src/Mod/Test/Document.py @@ -21,6 +21,7 @@ # * * # ***************************************************************************/ +from plistlib import UID import FreeCAD, os, unittest, tempfile from FreeCAD import Base import math @@ -671,6 +672,49 @@ class DocumentBasicCases(unittest.TestCase): FreeCAD.closeDocument("CreateTest") +class DocumentImportCases(unittest.TestCase): + def testDXFImportCPPIssue20195(self): + import importDXF + from draftutils import params + + # Set options, doing our best to restore them: + wasShowDialog = params.get_param("dxfShowDialog") + wasUseLayers = params.get_param("dxfUseDraftVisGroups") + wasUseLegacyImporter = params.get_param("dxfUseLegacyImporter") + wasCreatePart = params.get_param("dxfCreatePart") + wasCreateDraft = params.get_param("dxfCreateDraft") + wasCreateSketch = params.get_param("dxfCreateSketch") + + try: + # disable Preferences dialog in gui mode (avoids popup prompt to user) + params.set_param("dxfShowDialog", False) + # Preserve the DXF layers (makes the checking of document contents easier) + params.set_param("dxfUseDraftVisGroups", True) + # Use the new C++ importer -- that's where the bug was + params.set_param("dxfUseLegacyImporter", False) + # create simple part shapes (3 params) + # This is required to display the bug because creation of Draft objects clears out the + # pending exception this test is looking for, whereas creation of the simple shape object + # actually throws on the pending exception so the entity is absent from the document. + params.set_param("dxfCreatePart", True) + params.set_param("dxfCreateDraft", False) + params.set_param("dxfCreateSketch", False) + importDXF.insert( + FreeCAD.getHomePath() + "Mod/Test/TestData/DXFSample.dxf", "ImportedDocName" + ) + finally: + params.set_param("dxfShowDialog", wasShowDialog) + params.set_param("dxfUseDraftVisGroups", wasUseLayers) + params.set_param("dxfUseLegacyImporter", wasUseLegacyImporter) + params.set_param("dxfCreatePart", wasCreatePart) + params.set_param("dxfCreateDraft", wasCreateDraft) + params.set_param("dxfCreateSketch", wasCreateSketch) + doc = FreeCAD.getDocument("ImportedDocName") + # This doc should ahve 3 objects: The Layers containter, the DXF layer called 0, and one Line + self.assertEqual(len(doc.Objects), 3) + FreeCAD.closeDocument("ImportedDocName") + + # class must be defined in global scope to allow it to be reloaded on document open class SaveRestoreSpecialGroup: def __init__(self, obj): diff --git a/src/Mod/Test/TestData/DXFSample.dxf b/src/Mod/Test/TestData/DXFSample.dxf new file mode 100644 index 0000000000..b889797b45 --- /dev/null +++ b/src/Mod/Test/TestData/DXFSample.dxf @@ -0,0 +1,2310 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1012 + 9 +$DWGCODEPAGE + 3 +ansi_1252 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMAX + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$DRAGMODE + 70 + 2 + 9 +$LTSCALE + 40 +1.0 + 9 +$OSMODE + 70 + 0 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DELOBJ + 70 + 1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 1 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 2 + 9 +$DIMALTF + 40 +0.0394 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +1.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 1 + 9 +$DIMTZIN + 70 + 0 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMFIT + 70 + 3 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMUNIT + 70 + 2 + 9 +$DIMDEC + 70 + 4 + 9 +$DIMTDEC + 70 + 4 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 2 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +0.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 0 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$BLIPMODE + 70 + 1 + 9 +$CHAMFERA + 40 +10.0 + 9 +$CHAMFERB + 40 +10.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2460755.400945150 + 9 +$TDUPDATE + 40 +2460755.402199340 + 9 +$TDINDWG + 40 +0.0012541898 + 9 +$TDUSRTIMER + 40 +0.0012541898 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$COORDS + 70 + 1 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$ATTDIA + 70 + 0 + 9 +$ATTREQ + 70 + 1 + 9 +$HANDLING + 70 + 1 + 9 +$HANDSEED + 5 +31 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 16 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.000000E+20 + 20 +1.000000E+20 + 30 +1.000000E+20 + 9 +$PEXTMAX + 10 +-1.000000E+20 + 20 +-1.000000E+20 + 30 +-1.000000E+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 0 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$PICKSTYLE + 70 + 1 + 9 +$CMLSTYLE + 2 +STANDARD + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +1.0 + 9 +$SAVEIMAGES + 70 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +100 +AcDbSymbolTable + 70 + 3 + 0 +VPORT + 5 +30 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +11.892094 + 22 +1.953472 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +19.534714 + 41 +2.318293 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +F +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +10 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 64 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +ISOCP + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +11 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +100 +AcDbSymbolTable + 70 + 8 + 0 +DIMSTYLE +105 +1D +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +STANDARD + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +0.18 + 42 +0.0625 + 43 +0.38 + 44 +0.18 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +0.18 +141 +0.09 +142 +0.0 +143 +25.4 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.09 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +24 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +1.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +25 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-35 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +3.5 + 42 +0.875 + 43 +5.25 + 44 +1.75 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +3.5 +141 +3.5 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +1.4 +146 +1.0 +147 +0.875 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +26 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-5 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +5.0 + 42 +1.25 + 43 +7.5 + 44 +2.5 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +5.0 +141 +5.0 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +2.0 +146 +1.0 +147 +1.25 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +27 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-7 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +7.0 + 42 +1.75 + 43 +10.5 + 44 +3.5 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +7.0 +141 +7.0 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +2.8 +146 +1.0 +147 +1.75 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +28 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO1 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +10.0 + 42 +2.5 + 43 +15.0 + 44 +5.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +10.0 +141 +10.0 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +4.0 +146 +1.0 +147 +2.5 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +29 +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO1-4 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +14.0 + 42 +3.5 + 43 +21.0 + 44 +7.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +14.0 +141 +14.0 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +5.6 +146 +1.0 +147 +3.5 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +2A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO2 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +20.0 + 42 +5.0 + 43 +30.0 + 44 +10.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +20.0 +141 +20.0 +142 +0.0 +143 +0.0394 +144 +1.0 +145 +8.0 +146 +1.0 +147 +5.0 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 2 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +10 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +100 +AcDbSymbolTable + 70 + 0 + 0 +BLOCK_RECORD + 5 +1A +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +17 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +1C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +18 +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +19 +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +2E +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 0 +VIEWPORT + 5 +22 +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbViewport + 10 +261.517699 + 20 +148.5 + 30 +0.0 + 40 +523.035398 + 41 +297.0 + 68 + -1 + 69 + 1 +1001 +ACAD +1000 +MVIEW +1002 +{ +1070 + 16 +1010 +0.0 +1020 +0.0 +1030 +0.0 +1010 +0.0 +1020 +0.0 +1030 +1.0 +1040 +0.0 +1040 +297.0 +1040 +261.517699 +1040 +148.5 +1040 +50.0 +1040 +0.0 +1040 +0.0 +1070 + 0 +1070 + 100 +1070 + 1 +1070 + 1 +1070 + 0 +1070 + 0 +1070 + 0 +1070 + 0 +1040 +0.0 +1040 +0.0 +1040 +0.0 +1040 +1.0 +1040 +1.0 +1040 +10.0 +1040 +10.0 +1070 + 0 +1002 +{ +1002 +} +1002 +} + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +E + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +100 +AcDbDictionary + 0 +DICTIONARY + 5 +E +102 +{ACAD_REACTORS +330 +C +102 +} +100 +AcDbDictionary + 3 +STANDARD +350 +13 + 0 +MLINESTYLE + 5 +13 +102 +{ACAD_REACTORS +330 +E +102 +} +100 +AcDbMlineStyle + 2 +STANDARD + 70 + 0 + 3 + + 62 + 0 + 51 +90.0 + 52 +90.0 + 71 + 2 + 49 +0.5 + 62 + 256 + 6 +BYLAYER + 49 +-0.5 + 62 + 256 + 6 +BYLAYER + 0 +ENDSEC + 0 +EOF From ba4ee26ebcbd1a6fbcb6cbe3533c3666112775d3 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Mon, 24 Mar 2025 17:18:02 +0100 Subject: [PATCH 086/316] [Doc] Add an up-to-date Doxygen configuration file This is currently only for the WebDoc target and not for teh DevDoc target. --- src/Doc/BuildWebDoc.cfg.in | 882 +++++++++++++++++++++++-------------- 1 file changed, 554 insertions(+), 328 deletions(-) diff --git a/src/Doc/BuildWebDoc.cfg.in b/src/Doc/BuildWebDoc.cfg.in index 50411a853d..cd2adc6aee 100644 --- a/src/Doc/BuildWebDoc.cfg.in +++ b/src/Doc/BuildWebDoc.cfg.in @@ -1,7 +1,7 @@ -# Doxyfile 1.9.4 +# Doxyfile 1.13.2 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. +# Doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. @@ -15,11 +15,12 @@ # # Note: # -# Use doxygen to compare the used configuration file with the template +# Use Doxygen to compare the used configuration file with the template # configuration file: # doxygen -x [configFile] -# Use doxygen to compare the used configuration file with the template -# configuration file without replacing the environment variables: +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: # doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- @@ -50,7 +51,7 @@ PROJECT_NAME = FreeCAD PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a +# for a project that appears at the top of each page and should give viewers a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = @@ -62,18 +63,24 @@ PROJECT_BRIEF = PROJECT_LOGO = +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If +# entered, it will be relative to the location where Doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = @DOXYGEN_OUTPUT_DIR@ -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format # and will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes +# option can be useful when feeding Doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise cause # performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to # control the number of sub-directories. # The default value is: NO. @@ -85,13 +92,13 @@ CREATE_SUBDIRS = YES # level increment doubles the number of directories, resulting in 4096 # directories at level 8 which is the default and also the maximum value. The # sub-directories are organized in 2 levels, the first level always has a fixed -# numer of 16 directories. +# number of 16 directories. # Minimum value: 0, maximum value: 8, default value: 8. # This tag requires that the tag CREATE_SUBDIRS is set to YES. CREATE_SUBDIRS_LEVEL = 8 -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. @@ -100,7 +107,7 @@ CREATE_SUBDIRS_LEVEL = 8 ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this +# documentation generated by Doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, # Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English @@ -114,14 +121,14 @@ ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# If the BRIEF_MEMBER_DESC tag is set to YES, Doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, Doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the @@ -142,13 +149,13 @@ REPEAT_BRIEF = YES ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief +# Doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# If the INLINE_INHERITED_MEMB tag is set to YES, Doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. @@ -156,7 +163,7 @@ ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, Doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. @@ -166,11 +173,11 @@ FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to +# If left blank the directory from which Doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. +# will be relative from the directory where Doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = ../.. @@ -184,41 +191,42 @@ STRIP_FROM_PATH = ../.. STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't +# If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but +# less readable) file names. This can be useful if your file system doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the +# first line (until the first dot, question mark or exclamation mark) of a +# Javadoc-style comment as the brief description. If set to NO, the Javadoc- +# style will behave just like regular Qt-style comments (thus requiring an +# explicit @brief command for a brief description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be -# interpreted by doxygen. +# interpreted by Doxygen. # The default value is: NO. JAVADOC_BANNER = NO -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first +# line (until the first dot, question mark or exclamation mark) of a Qt-style +# comment as the brief description. If set to NO, the Qt-style will behave just +# like regular Qt-style comments (thus requiring an explicit \brief command for +# a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this @@ -230,10 +238,10 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO -# By default Python docstrings are displayed as preformatted text and doxygen's +# By default Python docstrings are displayed as preformatted text and Doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the -# doxygen's special commands can be used and the contents of the docstring -# documentation blocks is shown as doxygen documentation. +# Doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as Doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES @@ -244,7 +252,7 @@ PYTHON_DOCSTRING = YES INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# If the SEPARATE_MEMBER_PAGES tag is set to YES then Doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. @@ -314,30 +322,30 @@ OPTIMIZE_OUTPUT_SLICE = NO # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, # VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files). For instance to make doxygen treat .inc files +# default for Fortran type files). For instance to make Doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. When specifying no_extension you should add +# the files are not read by Doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# The output of markdown processing is further processed by Doxygen, so you can +# mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. @@ -347,25 +355,45 @@ MARKDOWN_SUPPORT = YES # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 5. +# Minimum value: 0, maximum value: 99, default value: 6. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 -# When enabled doxygen tries to link words that correspond to documented +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled Doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. +# globally by setting AUTOLINK_SUPPORT to NO. Words listed in the +# AUTOLINK_IGNORE_WORDS tag are excluded from automatic linking. # The default value is: YES. AUTOLINK_SUPPORT = YES +# This tag specifies a list of words that, when matching the start of a word in +# the documentation, will suppress auto links generation, if it is enabled via +# AUTOLINK_SUPPORT. This list does not affect affect links explicitly created +# using \# or the \link or commands. +# This tag requires that the tag AUTOLINK_SUPPORT is set to YES. + +AUTOLINK_IGNORE_WORDS = + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and +# tag to YES in order to let Doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. +# versus func(std::string) {}). This also makes the inheritance and +# collaboration diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES @@ -377,16 +405,16 @@ BUILTIN_STL_SUPPORT = YES CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. +# https://www.riverbankcomputing.com/software) sources only. Doxygen will parse +# them like normal C++ but will assume all classes use public instead of private +# inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. +# Doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. @@ -395,7 +423,7 @@ SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first +# tag is set to YES then Doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. @@ -453,18 +481,18 @@ TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The +# code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# Doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest +# symbols. At the end of a run Doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 -# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use -# during processing. When set to 0 doxygen will based this on the number of +# The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use +# during processing. When set to 0 Doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple @@ -476,11 +504,19 @@ LOOKUP_CACHE_SIZE = 0 NUM_PROC_THREADS = 1 +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# If the EXTRACT_ALL tag is set to YES, Doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. @@ -546,7 +582,7 @@ EXTRACT_ANON_NSPACES = NO RESOLVE_UNNAMED_PARAMS = YES -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. @@ -554,22 +590,31 @@ RESOLVE_UNNAMED_PARAMS = YES HIDE_UNDOC_MEMBERS = YES -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. -HIDE_UNDOC_CLASSES = YES +HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all +# undocumented namespaces that are normally visible in the namespace hierarchy. +# If set to NO, these namespaces will be included in the various overviews. This +# option has no effect if EXTRACT_ALL is enabled. +# The default value is: YES. + +HIDE_UNDOC_NAMESPACES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -583,7 +628,7 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# With the correct setting of option CASE_SENSE_NAMES Doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly @@ -592,21 +637,22 @@ INTERNAL_DOCS = NO # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On -# Windows (including Cygwin) and MacOS, users should typically set this option +# Windows (including Cygwin) and macOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. -# The default value is: system dependent. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. @@ -619,7 +665,7 @@ HIDE_COMPOUND_REFERENCE= NO SHOW_HEADERFILE = YES -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -632,7 +678,7 @@ SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. @@ -644,14 +690,14 @@ FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# If the SORT_MEMBER_DOCS tag is set to YES then Doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. @@ -659,7 +705,7 @@ SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = YES -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then Doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. @@ -671,7 +717,7 @@ SORT_BRIEF_DOCS = YES SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# If the SORT_GROUP_NAMES tag is set to YES then Doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. @@ -688,11 +734,11 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = YES -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. @@ -762,25 +808,25 @@ SHOW_FILES = NO SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from +# Doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file +# by Doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated +# by Doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can +# that represents Doxygen's defaults, run Doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. See also section "Changing the # layout of pages" for information. # -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# Note that if you run Doxygen from a directory containing a file called +# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = @DOXYGEN_LAYOUT_FILE@ @@ -795,19 +841,35 @@ LAYOUT_FILE = @DOXYGEN_LAYOUT_FILE@ CITE_BIB_FILES = +# The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH +# environment variable) so that external tools such as latex and gs can be +# found. +# Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the +# path already specified by the PATH variable, and are added in the order +# specified. +# Note: This option is particularly useful for macOS version 14 (Sonoma) and +# higher, when running Doxygen from Doxywizard, because in this case any user- +# defined changes to the PATH are ignored. A typical example on macOS is to set +# EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin +# together with the standard path, the full search path used by doxygen when +# launching external tools will then become +# PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + +EXTERNAL_TOOL_PATH = + #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the +# standard output by Doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -815,14 +877,14 @@ QUIET = NO WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag is set to YES then Doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for # potential errors in the documentation, such as documenting some parameters in # a documented function twice, or documenting parameters that don't exist or # using markup commands wrongly. @@ -830,8 +892,8 @@ WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES -# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete -# function parameter documentation. If set to NO, doxygen will accept that some +# If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete +# function parameter documentation. If set to NO, Doxygen will accept that some # parameters have no documentation without warning. # The default value is: YES. @@ -839,7 +901,7 @@ WARN_IF_INCOMPLETE_DOC = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong parameter +# value. If set to NO, Doxygen will only warn about wrong parameter # documentation, but not about the absence of documentation. If EXTRACT_ALL is # set to YES then this flag will automatically be disabled. See also # WARN_IF_INCOMPLETE_DOC @@ -847,16 +909,31 @@ WARN_IF_INCOMPLETE_DOC = YES WARN_NO_PARAMDOC = NO -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about +# undocumented enumeration values. If set to NO, Doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS -# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but -# at the end of the doxygen process doxygen will return with a non-zero status. -# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the Doxygen process Doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = NO -# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# The WARN_FORMAT tag determines the format of the warning messages that Doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will @@ -869,7 +946,7 @@ WARN_FORMAT = "$file:$line: $text" # In the $text part of the WARN_FORMAT command it is possible that a reference # to a more specific place is given. To make it easier to jump to this place -# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# (outside of Doxygen) the user can define a custom "cut" / "paste" string. # Example: # WARN_LINE_FORMAT = "'vi $file +$line'" # See also: WARN_FORMAT @@ -899,31 +976,42 @@ WARN_LOGFILE = INPUT = @DOXYGEN_INPUT_LIST@ # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). +# See also: INPUT_ENCODING for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. +# read by Doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, -# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C -# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, -# *.vhdl, *.ucf, *.qsf and *.ice. +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.h \ *.hpp \ @@ -945,7 +1033,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # -# Note that relative paths are relative to the directory from which doxygen is +# Note that relative paths are relative to the directory from which Doxygen is # run. EXCLUDE = @DOXYGEN_EXCLUDE_LIST@ @@ -978,9 +1066,6 @@ EXCLUDE_PATTERNS =*.moc.* \ # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # ANamespace::AClass, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = __init__ \ None \ @@ -1021,7 +1106,7 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = @DOXYGEN_IMAGE_PATH@ -# The INPUT_FILTER tag can be used to specify a program that doxygen should +# The INPUT_FILTER tag can be used to specify a program that Doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # @@ -1036,9 +1121,14 @@ IMAGE_PATH = @DOXYGEN_IMAGE_PATH@ # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that Doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. +# properly processed by Doxygen. INPUT_FILTER = @@ -1051,7 +1141,7 @@ INPUT_FILTER = # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. +# properly processed by Doxygen. FILTER_PATTERNS = @@ -1073,10 +1163,28 @@ FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. +# and want to reuse the introduction page also for the Doxygen output. USE_MDFILE_AS_MAINPAGE = +# If the IMPLICIT_DIR_DOCS tag is set to YES, any README.md file found in sub- +# directories of the project's root, is used as the documentation for that sub- +# directory, except when the README.md starts with a \dir, \page or \mainpage +# command. If set to NO, the README.md file needs to start with an explicit \dir +# command in order to be used as directory documentation. +# The default value is: YES. + +IMPLICIT_DIR_DOCS = YES + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1091,12 +1199,13 @@ USE_MDFILE_AS_MAINPAGE = SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. +# multi-line macros, enums or list initialized variables directly into the +# documentation. # The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. @@ -1134,7 +1243,7 @@ REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = NO # If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# point to the HTML generated by the htags(1) tool instead of Doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. @@ -1148,14 +1257,14 @@ SOURCE_TOOLTIPS = NO # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # -# The result: instead of the source browser generated by doxygen, the links to +# The result: instead of the source browser generated by Doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# If the VERBATIM_HEADERS tag is set the YES then Doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. @@ -1163,19 +1272,19 @@ USE_HTAGS = NO VERBATIM_HEADERS = NO -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# If the CLANG_ASSISTED_PARSING tag is set to YES then Doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for -# which doxygen's built-in parser lacks the necessary type information. -# Note: The availability of this option depends on whether or not doxygen was +# which Doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not Doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS -# tag is set to YES then doxygen will add the directory of each input to the +# tag is set to YES then Doxygen will add the directory of each input to the # include path. # The default value is: YES. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. @@ -1184,7 +1293,7 @@ CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories +# the include paths will already be set by Doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. @@ -1198,7 +1307,7 @@ CLANG_OPTIONS = # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. -# Note: The availability of this option depends on whether or not doxygen was +# Note: The availability of this option depends on whether or not Doxygen was # generated with the -Duse_libclang=ON option for CMake. CLANG_DATABASE_PATH = @@ -1214,10 +1323,11 @@ CLANG_DATABASE_PATH = ALPHABETICAL_INDEX = NO -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1226,7 +1336,7 @@ IGNORE_PREFIX = # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1247,40 +1357,40 @@ HTML_OUTPUT = html HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a +# each generated HTML page. If the tag is left blank Doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. +# that Doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally +# for information on how to generate the default header that Doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description +# default header when upgrading to a newer version of Doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/templates/header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard +# generated HTML page. If the tag is left blank Doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. +# that Doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = @CMAKE_CURRENT_SOURCE_DIR@/templates/footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. +# the HTML output. If left blank Doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. +# sheet that Doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. @@ -1290,13 +1400,18 @@ HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. +# created by Doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/templates/customdoxygen.css @@ -1311,6 +1426,19 @@ HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/templates/customdoxygen.css HTML_EXTRA_FILES = @CMAKE_CURRENT_SOURCE_DIR@/templates/doxy-boot.js +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generates light mode output, DARK always +# generates dark mode output, AUTO_LIGHT automatically sets the mode according +# to the user preference, uses light mode if no preference is set (the default), +# AUTO_DARK automatically sets the mode according to the user preference, uses +# dark mode if no preference is set and TOGGLE allows a user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a color-wheel, see @@ -1341,15 +1469,6 @@ HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will @@ -1369,6 +1488,33 @@ HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1386,7 +1532,7 @@ HTML_INDEX_NUM_ENTRIES = 100 # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To -# create a documentation set, doxygen will generate a Makefile in the HTML +# create a documentation set, Doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at @@ -1434,18 +1580,18 @@ DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # on Windows. In the beginning of 2021 Microsoft took the original page, with -# a.o. the download links, offline the HTML help workshop was already many years -# in maintenance mode). You can download the HTML help workshop from the web -# archives at Installation executable (see: +# a.o. the download links, offline (the HTML help workshop was already many +# years in maintenance mode). You can download the HTML help workshop from the +# web archives at Installation executable (see: # http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo # ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for @@ -1465,7 +1611,7 @@ CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. +# Doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1499,6 +1645,16 @@ BINARY_TOC = NO TOC_EXPAND = NO +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help @@ -1522,7 +1678,7 @@ QCH_FILE = FreeCADSourceDocu # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_NAMESPACE = "FreeCADSourceDocu" +QHP_NAMESPACE = FreeCADSourceDocu # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual @@ -1557,7 +1713,7 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path -# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1589,7 +1745,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. +# The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO @@ -1602,11 +1758,11 @@ DISABLE_INDEX = NO # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine tune the look of the index (see "Fine-tuning the output"). As an -# example, the default style sheet generated by doxygen has an example that +# example, the default style sheet generated by Doxygen has an example that # shows how to put an image at the root of the tree instead of the PROJECT_NAME. # Since the tree basically has the same information as the tab index, you could # consider setting DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. +# The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO @@ -1624,7 +1780,7 @@ GENERATE_TREEVIEW = NO FULL_SIDEBAR = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. +# Doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. @@ -1633,6 +1789,12 @@ FULL_SIDEBAR = NO ENUM_VALUES_PER_LINE = 4 +# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified +# enumeration values besides the enumeration mnemonics. +# The default value is: NO. + +SHOW_ENUM_VALUES = NO + # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. @@ -1640,21 +1802,21 @@ ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email # addresses. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. OBFUSCATE_EMAILS = YES -# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. @@ -1667,24 +1829,13 @@ HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML +# Doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. @@ -1722,7 +1873,7 @@ MATHJAX_VERSION = MathJax_2 # Possible values are: HTML-CSS (which is slower, but has the best # compatibility. This is the name for Mathjax version 2, for MathJax version 3 # this will be translated into chtml), NativeMML (i.e. MathML. Only supported -# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This # is the name for Mathjax version 3, for MathJax version 2 this will be # translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. @@ -1746,8 +1897,8 @@ MATHJAX_RELPATH = # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example -# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7-latest/tex.html -# #tex-and-latex-extensions): +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # For example for MathJax version 3 (see # http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): @@ -1756,7 +1907,7 @@ MATHJAX_RELPATH = MATHJAX_EXTENSIONS = -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an @@ -1765,12 +1916,12 @@ MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and +# When the SEARCHENGINE tag is enabled Doxygen will generate a search box for +# the HTML output. The underlying search engine uses JavaScript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then +# For large projects the JavaScript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically @@ -1789,7 +1940,7 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH -# setting. When disabled, doxygen will generate a PHP script for searching and +# setting. When disabled, Doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing # and searching needs to be provided by external tools. See the section # "External Indexing and Searching" for details. @@ -1798,7 +1949,7 @@ SEARCHENGINE = YES SERVER_BASED_SEARCH = NO -# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# When EXTERNAL_SEARCH tag is enabled Doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain the @@ -1843,7 +1994,7 @@ SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = -# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through Doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of @@ -1857,7 +2008,7 @@ EXTRA_SEARCH_MAPPINGS = # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, Doxygen will generate LaTeX output. # The default value is: YES. GENERATE_LATEX = NO @@ -1902,7 +2053,7 @@ MAKEINDEX_CMD_NAME = makeindex LATEX_MAKEINDEX_CMD = makeindex -# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# If the COMPACT_LATEX tag is set to YES, Doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1917,7 +2068,7 @@ COMPACT_LATEX = NO # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just @@ -1933,15 +2084,15 @@ EXTRA_PACKAGES = amsmath # The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for # the generated LaTeX document. The header should contain everything until the -# first chapter. If it is left blank doxygen will generate a standard header. It +# first chapter. If it is left blank Doxygen will generate a standard header. It # is highly recommended to start with a default header using # doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty # and then modify the file new_header.tex. See also section "Doxygen usage" for -# information on how to generate the default header that doxygen normally uses. +# information on how to generate the default header that Doxygen normally uses. # # Note: Only use a user-defined header if you know what you are doing! # Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. The following +# default header when upgrading to a newer version of Doxygen. The following # commands have a special meaning inside the header (and footer): For a # description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1950,10 +2101,10 @@ LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for # the generated LaTeX document. The footer should contain everything after the -# last chapter. If it is left blank doxygen will generate a standard footer. See +# last chapter. If it is left blank Doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what # special commands can be used inside the footer. See also section "Doxygen -# usage" for information on how to generate the default footer that doxygen +# usage" for information on how to generate the default footer that Doxygen # normally uses. Note: Only use a user-defined footer if you know what you are # doing! # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1962,7 +2113,7 @@ LATEX_FOOTER = # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined # LaTeX style sheets that are included after the standard style sheets created -# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# by Doxygen. Using this option one can overrule certain style aspects. Doxygen # will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the @@ -1988,7 +2139,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# If the USE_PDFLATEX tag is set to YES, Doxygen will use the engine as # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX # files. Set this option to YES, to get a higher quality PDF documentation. # @@ -1998,15 +2149,22 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode -# command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BATCHMODE = NO -# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# If the LATEX_HIDE_INDICES tag is set to YES then Doxygen will not include the # index chapters (such as File Index, Compound Index, etc.) in the output. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -2016,18 +2174,10 @@ LATEX_HIDE_INDICES = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. -# The default value is: plain. +# The default value is: plainnat. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_BIB_STYLE = plain - -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO +LATEX_BIB_STYLE = plainnat # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # path from which the emoji images will be read. If a relative path is entered, @@ -2041,7 +2191,7 @@ LATEX_EMOJI_DIRECTORY = # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# If the GENERATE_RTF tag is set to YES, Doxygen will generate RTF output. The # RTF output is optimized for Word 97 and may not look too pretty with other RTF # readers/editors. # The default value is: NO. @@ -2056,7 +2206,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# If the COMPACT_RTF tag is set to YES, Doxygen generates more compact RTF # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -2076,28 +2226,36 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load stylesheet definitions from file. Syntax is similar to Doxygen's # configuration file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the -# default style sheet that doxygen normally uses. +# default style sheet that Doxygen normally uses. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's configuration file. A template extensions file can be +# similar to Doxygen's configuration file. A template extensions file can be # generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = +# The RTF_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the RTF_OUTPUT output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTRA_FILES = + #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, Doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -2128,7 +2286,7 @@ MAN_EXTENSION = .3 MAN_SUBDIR = -# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without # them the man command would be unable to find the correct page. @@ -2141,7 +2299,7 @@ MAN_LINKS = NO # Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# If the GENERATE_XML tag is set to YES, Doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. @@ -2155,7 +2313,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# If the XML_PROGRAMLISTING tag is set to YES, Doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size # of the XML output. @@ -2164,7 +2322,7 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES -# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, Doxygen will include # namespace members in file scope as well, matching the HTML output. # The default value is: NO. # This tag requires that the tag GENERATE_XML is set to YES. @@ -2175,7 +2333,7 @@ XML_NS_MEMB_FILE_SCOPE = NO # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, Doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -2193,19 +2351,45 @@ DOCBOOK_OUTPUT = docbook # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# If the GENERATE_AUTOGEN_DEF tag is set to YES, Doxygen will generate an +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + +# If the GENERATE_SQLITE3 tag is set to YES Doxygen will generate a Sqlite3 +# database with symbols found by Doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each Doxygen run. If set to NO, Doxygen +# will warn if a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# If the GENERATE_PERLMOD tag is set to YES, Doxygen will generate a Perl module # file that captures the structure of the code including all documentation. # # Note that this feature is still experimental and incomplete at the moment. @@ -2213,7 +2397,7 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# If the PERLMOD_LATEX tag is set to YES, Doxygen will generate the necessary # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # output from the Perl module output. # The default value is: NO. @@ -2243,13 +2427,13 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, Doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# If the MACRO_EXPANSION tag is set to YES, Doxygen will expand all macro names # in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. @@ -2264,7 +2448,7 @@ MACRO_EXPANSION = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_ONLY_PREDEF = YES +EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. @@ -2341,14 +2525,15 @@ PREDEFINED = HAVE_SWIG \ StartGuiExport= \ WebGuiExport= \ WM4_MEMORY_MANAGER \ - WM4_FOUNDATION_ITEM= \ + WM4_FOUNDATION_ITEM= \ IMETHOD=inline \ COIN_DLL_API= \ COIN_INTERNAL \ PYCXX_EXPORT= \ KDL_INLINE \ YY_NO_UNISTD_H \ - DOXYGEN_SHOULD_SKIP_THIS + DOXYGEN_SHOULD_SKIP_THIS \ + DEBUG_MACRO=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2394,7 +2579,7 @@ EXPAND_AS_DEFINED = Py_Header \ PRIVATE_EQUALITY_SOURCE \ USING_PART_OF_NAMESPACE_EIGEN -# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# If the SKIP_FUNCTION_MACROS tag is set to YES then Doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have # an all uppercase name, and do not end with a semicolon. Such function macros # are typically used for boiler-plate code, and will confuse the parser if not @@ -2418,26 +2603,26 @@ SKIP_FUNCTION_MACROS = YES # section "Linking to external documentation" for more information about the use # of tag files. # Note: Each tag file must have a unique name (where the name does NOT include -# the path). If a tag file is not located in the directory in which doxygen is +# the path). If a tag file is not located in the directory in which Doxygen is # run, you must also specify the path to the tagfile here. TAGFILES = @DOXYGEN_TAGFILES@ -# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# When a file name is specified after GENERATE_TAGFILE, Doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. # The default value is: NO. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will be +# in the topic index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2451,33 +2636,26 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to diagram generator tools #--------------------------------------------------------------------------- -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_PATH = - # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. HIDE_UNDOC_RELATIONS = NO -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# If you set the HAVE_DOT tag to YES then Doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO # The default value is: NO. HAVE_DOT = NO -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed -# to run in parallel. When set to 0 doxygen will base this on the number of +# The DOT_NUM_THREADS specifies the number of dot invocations Doxygen is allowed +# to run in parallel. When set to 0 Doxygen will base this on the number of # processors available in the system. You can set it explicitly to a value # larger than 0 to get control over the balance between CPU load and processing # speed. @@ -2486,59 +2664,83 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# Doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = FreeSans.ttf +DOT_COMMON_ATTR = "fontname=FreeSans.ttf,fontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_EDGE_ATTR = "labelfontname=FreeSans.ttf,labelfontsize=10" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" + +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a -# graph for each documented class showing the direct and indirect inheritance -# relations. In case HAVE_DOT is set as well dot will be used to draw the graph, -# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set -# to TEXT the direct and indirect inheritance relations will be shown as texts / -# links. -# Possible values are: NO, YES, TEXT and GRAPH. +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then Doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. Explicit enabling an inheritance +# graph or choosing a different representation for an inheritance graph of a +# specific class, can be accomplished by means of the command \inheritancegraph. +# Disabling an inheritance graph can be accomplished by means of the command +# \hideinheritancegraph. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. CLASS_GRAPH = NO -# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# If the COLLABORATION_GRAPH tag is set to YES then Doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = NO -# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. See also the chapter Grouping -# in the manual. +# If the GROUP_GRAPHS tag is set to YES then Doxygen will generate a graph for +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GROUP_GRAPHS = NO -# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# If the UML_LOOK tag is set to YES, Doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. # The default value is: NO. @@ -2559,10 +2761,10 @@ UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 -# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# If the DOT_UML_DETAILS tag is set to NO, Doxygen will show attributes and # methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS -# tag is set to YES, doxygen will add type and arguments for attributes and -# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# tag is set to YES, Doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, Doxygen # will not generate fields with class member information in the UML graphs. The # class diagrams will look similar to the default class diagrams but using UML # notation for the relationships. @@ -2574,8 +2776,8 @@ DOT_UML_DETAILS = NO # The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters # to display on a single line. If the actual line length exceeds this threshold -# significantly it will wrapped across multiple lines. Some heuristics are apply -# to avoid ugly line breaks. +# significantly it will be wrapped across multiple lines. Some heuristics are +# applied to avoid ugly line breaks. # Minimum value: 0, maximum value: 1000, default value: 17. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2590,24 +2792,29 @@ DOT_WRAP_THRESHOLD = 17 TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to -# YES then doxygen will generate a graph for each documented file showing the +# YES then Doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDE_GRAPH = NO # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are -# set to YES then doxygen will generate a graph for each documented file showing +# set to YES then Doxygen will generate a graph for each documented file showing # the direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDED_BY_GRAPH = NO -# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# If the CALL_GRAPH tag is set to YES then Doxygen will generate a call # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. @@ -2619,7 +2826,7 @@ INCLUDED_BY_GRAPH = NO CALL_GRAPH = NO -# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# If the CALLER_GRAPH tag is set to YES then Doxygen will generate a caller # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. @@ -2631,17 +2838,20 @@ CALL_GRAPH = NO CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# If the GRAPHICAL_HIERARCHY tag is set to YES then Doxygen will graphical # hierarchy of all classes instead of a textual one. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GRAPHICAL_HIERARCHY = NO -# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# If the DIRECTORY_GRAPH tag is set to YES then Doxygen will show the # dependencies a directory has on other directories in a graphical way. The # dependency relations are determined by the #include relations between the -# files in the directories. +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2657,25 +2867,30 @@ DIR_GRAPH_MAX_DEPTH = 1 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). -# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order -# to make the SVG files visible in IE 9+ (other browsers do not have this -# requirement). +# https://www.graphviz.org/)). +# +# Note the formats svg:cairo and svg:cairo:cairo cannot be used in combination +# with INTERACTIVE_SVG (the INTERACTIVE_SVG will be set to NO). # Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, -# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and -# png:gdiplus:gdiplus. +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus, +# png:gdiplus:gdiplus, svg:cairo, svg:cairo:cairo, svg:svg, svg:svg:core, +# gif:cairo, gif:cairo:gd, gif:cairo:gdiplus, gif:gdiplus, gif:gdiplus:gdiplus, +# gif:gd, gif:gd:gd, jpg:cairo, jpg:cairo:gd, jpg:cairo:gdiplus, jpg:gd, +# jpg:gd:gd, jpg:gdiplus and jpg:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. DOT_IMAGE_FORMAT = png -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. +# If DOT_IMAGE_FORMAT is set to svg or svg:svg or svg:svg:core, then this option +# can be set to YES to enable generation of interactive SVG images that allow +# zooming and panning. # # Note that this requires a modern browser other than Internet Explorer. Tested # and working are Firefox, Chrome, Safari, and Opera. -# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make -# the SVG files visible. Older versions of IE do not have SVG support. +# +# Note This option will be automatically disabled when DOT_IMAGE_FORMAT is set +# to svg:cairo or svg:cairo:cairo. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2694,11 +2909,12 @@ DOT_PATH = DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). +# You can include diagrams made with dia in Doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCFILE_DIRS = +DIA_PATH = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2706,7 +2922,7 @@ MSCFILE_DIRS = DIAFILE_DIRS = -# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# When using PlantUML, the PLANTUML_JAR_PATH tag should be used to specify the # path where java can find the plantuml.jar file or to the filename of jar file # to be used. If left blank, it is assumed PlantUML is not used or called during # a preprocessing step. Doxygen will generate a warning when it encounters a @@ -2714,20 +2930,26 @@ DIAFILE_DIRS = PLANTUML_JAR_PATH = -# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a -# configuration file for plantuml. +# When using PlantUML, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for PlantUML. PLANTUML_CFG_FILE = -# When using plantuml, the specified paths are searched for files specified by -# the !include statement in a plantuml block. +# When using PlantUML, the specified paths are searched for files specified by +# the !include statement in a PlantUML block. PLANTUML_INCLUDE_PATH = +# The PLANTUMLFILE_DIRS tag can be used to specify one or more directories that +# contain PlantUml files that are included in the documentation (see the +# \plantumlfile command). + +PLANTUMLFILE_DIRS = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes -# larger than this value, doxygen will truncate the graph, which is visualized -# by representing a node as a red box. Note that doxygen if the number of direct +# larger than this value, Doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that if the number of direct # children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. @@ -2748,18 +2970,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2769,17 +2979,17 @@ DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO -# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# If the GENERATE_LEGEND tag is set to YES Doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. -# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# Note: This tag requires that UML_LOOK isn't set, i.e. the Doxygen internal # graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = NO -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate +# If the DOT_CLEANUP tag is set to YES, Doxygen will remove the intermediate # files that are used to generate the various graphs. # # Note: This setting is not only used for dot files but also for msc temporary @@ -2787,3 +2997,19 @@ GENERATE_LEGEND = NO # The default value is: YES. DOT_CLEANUP = YES + +# You can define message sequence charts within Doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then Doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, Doxygen will call the tool as prog -T +# -o . The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = From b655de3ea6a0ec0335e80d377fa9e7dc17cff30f Mon Sep 17 00:00:00 2001 From: marioalexis Date: Fri, 28 Mar 2025 11:38:42 -0300 Subject: [PATCH 087/316] Fem: Simplify label in material task panel --- src/Mod/Fem/Gui/Resources/ui/Material.ui | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/Gui/Resources/ui/Material.ui b/src/Mod/Fem/Gui/Resources/ui/Material.ui index 60913293b5..45315aa9dd 100755 --- a/src/Mod/Fem/Gui/Resources/ui/Material.ui +++ b/src/Mod/Fem/Gui/Resources/ui/Material.ui @@ -340,7 +340,10 @@ - Expansion Reference Temperature: + Reference Temperature: + + + Reference temperature for thermal expansion From 1d4a09366c98576390eb17ce2066c6b0abd770e5 Mon Sep 17 00:00:00 2001 From: Rafael Pronto Date: Mon, 31 Mar 2025 18:45:33 +0100 Subject: [PATCH 088/316] Sketcher: Prevent renaming interruption when hovering task elements. (#20458) * Sketcher: Prevent renaming interruption when hovering task elements. Fixes #11842. * Sketcher: Refactored input focus check based on PR feedback (PR #20458) * Update src/Mod/Sketcher/Gui/TaskSketcherElements.cpp --------- Co-authored-by: Benjamin Nauck --- src/Mod/Sketcher/Gui/TaskSketcherElements.cpp | 14 ++++++++++++++ src/Mod/Sketcher/Gui/TaskSketcherElements.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp index 551b9fa90f..e2412dc51a 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #include #include #include @@ -1694,8 +1695,17 @@ void TaskSketcherElements::onListWidgetElementsItemPressed(QListWidgetItem* it) ui->listWidgetElements->repaint(); } +bool TaskSketcherElements::hasInputWidgetFocused() +{ + QWidget* focusedWidget = QApplication::focusWidget(); + return qobject_cast(focusedWidget) != nullptr; +} + void TaskSketcherElements::onListWidgetElementsItemEntered(QListWidgetItem* item) { + if (hasInputWidgetFocused()) { + return; + } ui->listWidgetElements->setFocus(); focusItemIndex = ui->listWidgetElements->row(item); @@ -1703,6 +1713,10 @@ void TaskSketcherElements::onListWidgetElementsItemEntered(QListWidgetItem* item void TaskSketcherElements::onListWidgetElementsMouseMoveOnItem(QListWidgetItem* it) { + if (hasInputWidgetFocused()) { + return; + } + ElementItem* item = static_cast(it); if (!item diff --git a/src/Mod/Sketcher/Gui/TaskSketcherElements.h b/src/Mod/Sketcher/Gui/TaskSketcherElements.h index 05d528b7ac..aa91e1b643 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherElements.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherElements.h @@ -125,6 +125,8 @@ public: /// Observer message from the Selection void onSelectionChanged(const Gui::SelectionChanges& msg) override; + bool hasInputWidgetFocused(); + private: void slotElementsChanged(); void updateVisibility(); From 31e43a8381259d8fe9311eb39c30a0a855e9f2cb Mon Sep 17 00:00:00 2001 From: David Carter Date: Mon, 31 Mar 2025 14:16:33 -0400 Subject: [PATCH 089/316] Materials: Build external materials support conditionally Adds a new build option BUILD_MATERIAL_EXTERNAL which is off by default. When disabled, the external interface is not built. This allows the code to be tested thoroughly before reaching the end user. --- cMake/FreeCAD_Helpers/CheckInterModuleDependencies.cmake | 1 + cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake | 1 + cMake/FreeCAD_Helpers/PrintFinalReport.cmake | 1 + 3 files changed, 3 insertions(+) diff --git a/cMake/FreeCAD_Helpers/CheckInterModuleDependencies.cmake b/cMake/FreeCAD_Helpers/CheckInterModuleDependencies.cmake index fae2b80f4f..a684a3d3e4 100644 --- a/cMake/FreeCAD_Helpers/CheckInterModuleDependencies.cmake +++ b/cMake/FreeCAD_Helpers/CheckInterModuleDependencies.cmake @@ -28,6 +28,7 @@ macro(CheckInterModuleDependencies) REQUIRES_MODS(BUILD_MESH_PART BUILD_PART BUILD_MESH) REQUIRES_MODS(BUILD_FLAT_MESH BUILD_MESH_PART) REQUIRES_MODS(BUILD_OPENSCAD BUILD_MESH_PART BUILD_DRAFT) + REQUIRES_MODS(BUILD_MATERIAL_EXTERNAL BUILD_MATERIAL) REQUIRES_MODS(BUILD_PART BUILD_MATERIAL) REQUIRES_MODS(BUILD_PART_DESIGN BUILD_SKETCHER) # REQUIRES_MODS(BUILD_CAM BUILD_PART BUILD_MESH BUILD_ROBOT) diff --git a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake index ebe6938865..f329745050 100644 --- a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake +++ b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake @@ -120,6 +120,7 @@ macro(InitializeFreeCADBuildOptions) option(BUILD_INSPECTION "Build the FreeCAD inspection module" ON) option(BUILD_JTREADER "Build the FreeCAD jt reader module" OFF) option(BUILD_MATERIAL "Build the FreeCAD material module" ON) + option(BUILD_MATERIAL_EXTERNAL "Build the FreeCAD material external interface module" OFF) option(BUILD_MESH "Build the FreeCAD mesh module" ON) option(BUILD_MESH_PART "Build the FreeCAD mesh part module" ON) option(BUILD_FLAT_MESH "Build the FreeCAD flat mesh module" ON) diff --git a/cMake/FreeCAD_Helpers/PrintFinalReport.cmake b/cMake/FreeCAD_Helpers/PrintFinalReport.cmake index 25bb8e7b3a..be1078cc4c 100644 --- a/cMake/FreeCAD_Helpers/PrintFinalReport.cmake +++ b/cMake/FreeCAD_Helpers/PrintFinalReport.cmake @@ -104,6 +104,7 @@ macro(PrintFinalReport) value(BUILD_INSPECTION) value(BUILD_JTREADER) value(BUILD_MATERIAL) + value(BUILD_MATERIAL_EXTERNAL) value(BUILD_MESH) value(BUILD_MESH_PART) value(BUILD_OPENSCAD) From f809e34ea05c8ce83169ec96d232414290919641 Mon Sep 17 00:00:00 2001 From: Luz Paz Date: Mon, 31 Mar 2025 15:48:29 -0400 Subject: [PATCH 090/316] Fix typos Found via `codespell -q 3 -L aci,addmin,ake,aline,alle,alledges,alocation,als,ang,anid,anormal,aply,apoints,ba,beginn,behaviour,bloaded,bottome,brushin,bu,byteorder,calculater,cancelled,cancelling,cas,cascade,centimetre,childrens,childs,colour,colours,commen,connexion,currenty,documentin,dof,doubleclick,dum,eiter,elemente,ende,feld,finde,findf,findn,fle,freez,graphin,hist,iff,incrementin,indexin,indicies,initialisation,initialise,initialised,initialises,initialisiert,inout,ist,itsel,kilometre,leadin,localy,lod,mantatory,methode,metres,millimetre,modell,nd,noe,normale,normaly,nto,numer,oce,oder,ontop,orgin,orginx,orginy,ot,pard,parm,parms,pres,programm,que,rady,recurrance,renderin,rin,ro,rougly,sectionin,seperator,serie,shs,sinc,siz,som,strack,substraction,te,technic,thist,thru,tread,tru,ue,uint,unter,uptodate,vas,vertexes,vew,wallthickness,whitespaces -S "./.git,*.po,*.ts,*.pdf,./ChangeLog.txt,./src/3rdParty,./src/Mod/Assembly/App/opendcm,./src/CXX,./src/zipios++,./src/Base/swig*,./src/Mod/Robot/App/kdl_cp,./src/Mod/Import/App/SCL,./src/WindowsInstaller,./src/Doc/FreeCAD.uml,./src/Base/StackWalker.cpp,./build/doc/SourceDoc,./tools/build/WindowsInstaller/lang,./src/Mod/TechDraw/Templates/locale"` --- src/Mod/BIM/ArchSpace.py | 2 +- src/Mod/BIM/importers/importSH3DHelper.py | 4 ++-- src/Mod/Fem/App/FemPostBranchFilter.cpp | 8 ++++---- src/Mod/Fem/App/FemPostPipeline.cpp | 10 +++++----- src/Mod/Fem/App/FemPostPipelinePyImp.cpp | 2 +- src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h | 2 +- src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h | 2 +- src/Mod/Fem/femresult/resulttools.py | 2 +- src/Mod/Material/App/Exceptions.h | 4 ++-- src/Mod/TechDraw/App/AppTechDrawPy.cpp | 2 +- src/Mod/TechDraw/Gui/ViewProviderAnnotation.cpp | 2 +- src/Mod/Test/Document.py | 2 +- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Mod/BIM/ArchSpace.py b/src/Mod/BIM/ArchSpace.py index 7c6f74a608..0d4233cc6e 100644 --- a/src/Mod/BIM/ArchSpace.py +++ b/src/Mod/BIM/ArchSpace.py @@ -442,7 +442,7 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent): pl = vobj.PropertiesList if not "Text" in pl: - vobj.addProperty("App::PropertyStringList", "Text", "Space",QT_TRANSLATE_NOOP("App::Property","The text to show. Use $area, $label, $longname, $description or any other propery name preceded with $ (case insensitive), or $floor, $walls, $ceiling for finishes, to insert the respective data")) + vobj.addProperty("App::PropertyStringList", "Text", "Space",QT_TRANSLATE_NOOP("App::Property","The text to show. Use $area, $label, $longname, $description or any other property name preceded with $ (case insensitive), or $floor, $walls, $ceiling for finishes, to insert the respective data")) vobj.Text = ["$label","$area"] if not "FontName" in pl: vobj.addProperty("App::PropertyFont", "FontName", "Space",QT_TRANSLATE_NOOP("App::Property","The name of the font")) diff --git a/src/Mod/BIM/importers/importSH3DHelper.py b/src/Mod/BIM/importers/importSH3DHelper.py index 4198f563db..22d4f079c7 100644 --- a/src/Mod/BIM/importers/importSH3DHelper.py +++ b/src/Mod/BIM/importers/importSH3DHelper.py @@ -1511,9 +1511,9 @@ class WallHandler(BaseHandler): def _set_baseboard_properties(self, obj, elm): # Baseboard are a little bit special: - # Since their placement and other characteristics are dependant of + # Since their placement and other characteristics are dependent on # the wall elements to be created (such as doorOrWndows), their - # creation is delayed until the + # creation is delayed until then for baseboard in elm.findall('baseboard'): side = baseboard.get('attribute') self.setp(obj, "App::PropertyQuantity", f"{side}Thickness", f"The thickness of the {side} baseboard", dim_sh2fc(float(baseboard.get("thickness")))) diff --git a/src/Mod/Fem/App/FemPostBranchFilter.cpp b/src/Mod/Fem/App/FemPostBranchFilter.cpp index 9f13340519..9f0cccc3ac 100644 --- a/src/Mod/Fem/App/FemPostBranchFilter.cpp +++ b/src/Mod/Fem/App/FemPostBranchFilter.cpp @@ -44,14 +44,14 @@ FemPostBranchFilter::FemPostBranchFilter() (long(0)), "Pipeline", App::Prop_None, - "Selects what the output of the branch itself is\n" - "In passthrough the branchs output is equal its imput.\n" - "In append, all child filter outputs gets appended as the branches output"); + "Selects what the output of the branch itself is.\n" + "In passthrough, the branch's output is equal to its input.\n" + "In append, all child filter outputs get appended as the branch's output"); Output.setEnums(OutputEnums); /* We always have a passthrough filter. This allows to connect our children - * dependend on the Mode setting, without worrying about the connection to our input + * dependent on the Mode setting, without worrying about the connection to our input * filter. We do not care if the input filter changes, as this is affecting only the passthrough * input and does not affect our child connections. * Dependent on our output mode, the passthrough is also used as output, but potentially diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index 8767097951..4501fca2ca 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -185,8 +185,8 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation*, auto time = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()); auto frames = getFrameValues(); - // we have float values, so be aware of roundign erros. lets subtract the searched time and - // then use the smalles value + // we have float values, so be aware of rounding errors. lets subtract the searched time and + // then use the smallest value for (auto& frame : frames) { frame = std::abs(frame - time); } @@ -257,7 +257,7 @@ bool FemPostPipeline::allowObject(App::DocumentObject* obj) return true; } - // and all standart Post objects the group can handle + // and all standard Post objects the group can handle return FemPostGroupExtension::allowObject(obj); } @@ -360,7 +360,7 @@ void FemPostPipeline::scale(double s) App::DocumentObjectExecReturn* FemPostPipeline::execute() { - // we fake a recalculated data oject, so that the viewprovider updates + // we fake a recalculated data object, so that the viewprovider updates // the visualization. We do not want to do this in onChange, as it // could theoretically be long running if (m_data_updated) { @@ -487,7 +487,7 @@ void FemPostPipeline::onChanged(const Property* prop) FemPostFilter* nextFilter = obj; nextFilter->getFilterInput()->RemoveAllInputConnections(0); - // handle input modes (Parallel is seperated, alll other settings are serial, just in + // handle input modes (Parallel is separated, all other settings are serial, just in // case an old document is loaded with "custom" mode, idx 2) if (Mode.getValue() == Fem::PostGroupMode::Parallel) { // parallel: all filters get out input diff --git a/src/Mod/Fem/App/FemPostPipelinePyImp.cpp b/src/Mod/Fem/App/FemPostPipelinePyImp.cpp index 83c282fc56..f2f7d14bfb 100644 --- a/src/Mod/Fem/App/FemPostPipelinePyImp.cpp +++ b/src/Mod/Fem/App/FemPostPipelinePyImp.cpp @@ -222,7 +222,7 @@ PyObject* FemPostPipelinePy::load(PyObject* args) } else { std::string error = std::string( - "Multistep load requries 4 arguments: ResultList, ValueList, unit, type"); + "Multistep load requires 4 arguments: ResultList, ValueList, unit, type"); throw Base::TypeError(error); } } diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h b/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h index 6c96e954e9..9f97b8e1b9 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h @@ -50,7 +50,7 @@ public: protected: virtual void setupTaskDialog(TaskDlgPost* dlg) override; - // change default group drag/drop behaviour sligthly + // change default group drag/drop behaviour slightly bool acceptReorderingObjects() const override; bool canDragObjectToTarget(App::DocumentObject* obj, App::DocumentObject* target) const override; diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h index 5096df9d6a..ae252125a8 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h @@ -56,7 +56,7 @@ protected: void updateFunctionSize(); virtual void setupTaskDialog(TaskDlgPost* dlg) override; - // change default group drag/drop behaviour sligthly + // change default group drag/drop behaviour slightly bool acceptReorderingObjects() const override; bool canDragObjectToTarget(App::DocumentObject* obj, App::DocumentObject* target) const override; diff --git a/src/Mod/Fem/femresult/resulttools.py b/src/Mod/Fem/femresult/resulttools.py index 4a2df17f2c..4b4bb2d39e 100644 --- a/src/Mod/Fem/femresult/resulttools.py +++ b/src/Mod/Fem/femresult/resulttools.py @@ -71,7 +71,7 @@ def purge_results(analysis): # result pipeline and filter for m in analysis.Group: if is_of_type(m, "Fem::FemPostPipeline"): - # delete the pipeline itself (it removes all fiters itself) + # delete the pipeline itself (it removes all filters itself) analysis.Document.removeObject(m.Name) analysis.Document.recompute() diff --git a/src/Mod/Material/App/Exceptions.h b/src/Mod/Material/App/Exceptions.h index d21053b40c..69ce4bce15 100644 --- a/src/Mod/Material/App/Exceptions.h +++ b/src/Mod/Material/App/Exceptions.h @@ -34,7 +34,7 @@ class Uninitialized: public Base::Exception { public: Uninitialized() - : Base::Exception("Uninitalized") + : Base::Exception("Uninitialized") {} explicit Uninitialized(const char* msg) : Base::Exception(msg) @@ -244,7 +244,7 @@ class UnknownValueType: public Base::Exception { public: UnknownValueType() - : Base::Exception("Unkown value type") + : Base::Exception("Unknown value type") {} explicit UnknownValueType(const char* msg) : Base::Exception(msg) diff --git a/src/Mod/TechDraw/App/AppTechDrawPy.cpp b/src/Mod/TechDraw/App/AppTechDrawPy.cpp index 15529bba1d..a9d3a2c0b1 100644 --- a/src/Mod/TechDraw/App/AppTechDrawPy.cpp +++ b/src/Mod/TechDraw/App/AppTechDrawPy.cpp @@ -567,7 +567,7 @@ private: TechDraw::GeometryObjectPtr gObj = dvp->getGeometryObject(); if (!gObj) { - // this test might be redundent here since we already checked hasGeometry. + // this test might be redundant here since we already checked hasGeometry. Base::Console().Message("TechDraw: %s has no geometry object!\n", dvp->Label.getValue()); return; } diff --git a/src/Mod/TechDraw/Gui/ViewProviderAnnotation.cpp b/src/Mod/TechDraw/Gui/ViewProviderAnnotation.cpp index 54b0db7975..30ec57c234 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderAnnotation.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderAnnotation.cpp @@ -135,7 +135,7 @@ bool ViewProviderAnnotation::setEdit(int ModNum) // setting the current item also opens the editor dataPropView->setCurrentIndex(index); dataPropView->activated(index); - // there is a button in the editor wigdet that opens a plain text dialog + // there is a button in the editor widget that opens a plain text dialog auto button = dataPropView->findChild(); if (button) { button->click(); diff --git a/src/Mod/Test/Document.py b/src/Mod/Test/Document.py index bf48b4811d..baf9621aa6 100644 --- a/src/Mod/Test/Document.py +++ b/src/Mod/Test/Document.py @@ -710,7 +710,7 @@ class DocumentImportCases(unittest.TestCase): params.set_param("dxfCreateDraft", wasCreateDraft) params.set_param("dxfCreateSketch", wasCreateSketch) doc = FreeCAD.getDocument("ImportedDocName") - # This doc should ahve 3 objects: The Layers containter, the DXF layer called 0, and one Line + # This doc should have 3 objects: The Layers container, the DXF layer called 0, and one Line self.assertEqual(len(doc.Objects), 3) FreeCAD.closeDocument("ImportedDocName") From b601629b2a9ef56d1167bf73b6df5938c3f37b19 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Mon, 31 Mar 2025 16:38:30 -0300 Subject: [PATCH 091/316] Fem: Capitalize label in material task panel --- src/Mod/Fem/Gui/Resources/ui/Material.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/Gui/Resources/ui/Material.ui b/src/Mod/Fem/Gui/Resources/ui/Material.ui index 45315aa9dd..dea6f96b2b 100755 --- a/src/Mod/Fem/Gui/Resources/ui/Material.ui +++ b/src/Mod/Fem/Gui/Resources/ui/Material.ui @@ -198,7 +198,7 @@ - Kinematic viscosity: + Kinematic Viscosity: From 27f56995880e58b4287edefcf0434b26530691ef Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:50:19 +0200 Subject: [PATCH 092/316] App: Add `#include ` where used --- src/App/ComplexGeoData.cpp | 1 + src/App/Link.cpp | 9 +++++++-- src/App/ObjectIdentifier.cpp | 1 + src/App/PropertyUnits.cpp | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index 4cb6994d6f..02c02d1bb6 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -28,6 +28,7 @@ #ifndef _PreComp_ #include +#include #endif #include diff --git a/src/App/Link.cpp b/src/App/Link.cpp index 9312aa13d2..1645c495e2 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -21,10 +21,15 @@ ****************************************************************************/ #include "PreCompiled.h" + +#ifndef _PreComp_ +#include +#endif + +#include +#include #include -#include -#include #include #include diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index 0c80b13672..fde8bff2ff 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include +#include #endif #include diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index 153b64bfa2..300c3ca786 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #endif #include From d9af8626273eb20436c54b43242883fcc7e2bc9e Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:50:30 +0200 Subject: [PATCH 093/316] Base: Add `#include ` where used --- src/Base/MatrixPyImp.cpp | 4 ++++ src/Base/PreCompiled.h | 23 ++++++++++++----------- src/Base/Quantity.cpp | 3 ++- src/Base/QuantityPyImp.cpp | 4 ++++ src/Base/Rotation.cpp | 4 ++++ src/Base/Tools2D.cpp | 1 + src/Base/Tools2D.h | 1 + src/Base/Vector3D.cpp | 5 ++++- 8 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index 9aaa9e8d63..5e93e20e2c 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -23,6 +23,10 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + // inclusion of the generated files (generated out of MatrixPy.xml) #include "RotationPy.h" #include "VectorPy.h" diff --git a/src/Base/PreCompiled.h b/src/Base/PreCompiled.h index 5a26c2e4f6..33b7e46f87 100644 --- a/src/Base/PreCompiled.h +++ b/src/Base/PreCompiled.h @@ -59,21 +59,22 @@ #endif // STL -#include -#include +#include +#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include // streams #include diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index e566227b17..1b25793824 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -22,8 +22,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include +#include +#include #include #endif diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp index 5b999d6aaa..36f435adef 100644 --- a/src/Base/QuantityPyImp.cpp +++ b/src/Base/QuantityPyImp.cpp @@ -22,6 +22,10 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + // inclusion of the generated files (generated out of QuantityPy.xml) #include "QuantityPy.h" #include "UnitPy.h" diff --git a/src/Base/Rotation.cpp b/src/Base/Rotation.cpp index e9e1776e80..d35fa1e672 100644 --- a/src/Base/Rotation.cpp +++ b/src/Base/Rotation.cpp @@ -23,6 +23,10 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + #include #include "Base/Exception.h" diff --git a/src/Base/Tools2D.cpp b/src/Base/Tools2D.cpp index 59bc296830..9a70b0bc36 100644 --- a/src/Base/Tools2D.cpp +++ b/src/Base/Tools2D.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include +#include #include #endif diff --git a/src/Base/Tools2D.h b/src/Base/Tools2D.h index a76fd88bb2..b97b61c73a 100644 --- a/src/Base/Tools2D.h +++ b/src/Base/Tools2D.h @@ -25,6 +25,7 @@ #include #include +#include #include #include diff --git a/src/Base/Vector3D.cpp b/src/Base/Vector3D.cpp index 4d6b049634..7f9403977d 100644 --- a/src/Base/Vector3D.cpp +++ b/src/Base/Vector3D.cpp @@ -23,8 +23,11 @@ #include "PreCompiled.h" -#include +#ifndef _PreComp_ #include +#endif + +#include #include #include "Vector3D.h" From 17dc7fce0628ffbf113feedbc9c2b249788cd20a Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:50:37 +0200 Subject: [PATCH 094/316] Gui: Add `#include ` where used --- src/Gui/3Dconnexion/navlib/NavlibPivot.cpp | 10 ++++++---- src/Gui/CallTips.cpp | 1 + src/Gui/Clipping.cpp | 1 + src/Gui/DemoMode.cpp | 1 + src/Gui/Dialogs/DlgParameterImp.cpp | 1 + src/Gui/EditableDatumLabel.cpp | 1 + src/Gui/InputField.cpp | 1 + src/Gui/OverlayManager.cpp | 1 + src/Gui/PreCompiled.h | 1 + src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp | 5 +++-- src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp | 4 ++++ src/Gui/QuantitySpinBox.cpp | 1 + src/Gui/Selection/SelectionFilter.h | 1 + src/Gui/Selection/SoFCSelectionContext.h | 1 + src/Gui/ShortcutManager.cpp | 1 + src/Gui/SoDatumLabel.cpp | 1 + src/Gui/SpinBox.cpp | 2 +- src/Gui/VectorListEditor.cpp | 4 ++++ src/Gui/propertyeditor/PropertyItem.cpp | 1 + src/Gui/propertyeditor/PropertyModel.cpp | 1 + 20 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp b/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp index 74a2848601..c021d21e3a 100644 --- a/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp +++ b/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp @@ -22,6 +22,10 @@ #include +#ifndef _PreComp_ +#include +#endif + #include #include #include @@ -48,8 +52,6 @@ #include #include -constexpr float MAX_FLOAT = std::numeric_limits::max(); - long NavlibInterface::GetSelectionTransform(navlib::matrix_t&) const { return navlib::make_result_code(navlib::navlib_errc::no_data_available); @@ -128,7 +130,7 @@ long NavlibInterface::GetHitLookAt(navlib::point_t& position) const SoRayPickAction rayPickAction(inventorViewer->getSoRenderManager()->getViewportRegion()); SbMatrix cameraMatrix; SbVec3f closestHitPoint; - float minLength = MAX_FLOAT; + float minLength = std::numeric_limits::max(); // Get the camera rotation SoCamera* pCamera = getCamera(); @@ -196,7 +198,7 @@ long NavlibInterface::GetHitLookAt(navlib::point_t& position) const } } - if (minLength < MAX_FLOAT) { + if (minLength < std::numeric_limits::max()) { std::copy(closestHitPoint.getValue(), closestHitPoint.getValue() + 3, &position.x); return 0; } diff --git a/src/Gui/CallTips.cpp b/src/Gui/CallTips.cpp index e3712f9c22..44e2599489 100644 --- a/src/Gui/CallTips.cpp +++ b/src/Gui/CallTips.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Gui/Clipping.cpp b/src/Gui/Clipping.cpp index d2495c3720..aebf86e8bd 100644 --- a/src/Gui/Clipping.cpp +++ b/src/Gui/Clipping.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Gui/DemoMode.cpp b/src/Gui/DemoMode.cpp index d69224d891..a4eef9d65c 100644 --- a/src/Gui/DemoMode.cpp +++ b/src/Gui/DemoMode.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Gui/Dialogs/DlgParameterImp.cpp b/src/Gui/Dialogs/DlgParameterImp.cpp index 8139e994ba..957d7992ef 100644 --- a/src/Gui/Dialogs/DlgParameterImp.cpp +++ b/src/Gui/Dialogs/DlgParameterImp.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Gui/EditableDatumLabel.cpp b/src/Gui/EditableDatumLabel.cpp index 0604bc0a2d..17068a5db7 100644 --- a/src/Gui/EditableDatumLabel.cpp +++ b/src/Gui/EditableDatumLabel.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index ee559b0bc6..6ebeb16844 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Gui/OverlayManager.cpp b/src/Gui/OverlayManager.cpp index 41cb897bc8..5515060f81 100644 --- a/src/Gui/OverlayManager.cpp +++ b/src/Gui/OverlayManager.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Gui/PreCompiled.h b/src/Gui/PreCompiled.h index c665016cf7..718190076b 100644 --- a/src/Gui/PreCompiled.h +++ b/src/Gui/PreCompiled.h @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp b/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp index 9e5bd6b5ba..1afea2d6c1 100644 --- a/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp +++ b/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp @@ -23,6 +23,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +# include +# include # include # include # include @@ -31,8 +34,6 @@ # include # include # include -# include -# include #endif #include diff --git a/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp b/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp index cb352c303f..42b76b5d4b 100644 --- a/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp +++ b/src/Gui/PreferencePages/DlgSettingsDocumentImp.cpp @@ -22,6 +22,10 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + #include #include #include diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index cc18e8be11..18657e6ed5 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Gui/Selection/SelectionFilter.h b/src/Gui/Selection/SelectionFilter.h index 563acd90af..13981dabbc 100644 --- a/src/Gui/Selection/SelectionFilter.h +++ b/src/Gui/Selection/SelectionFilter.h @@ -24,6 +24,7 @@ #ifndef GUI_SelectionFilter_H #define GUI_SelectionFilter_H +#include #include #include #include diff --git a/src/Gui/Selection/SoFCSelectionContext.h b/src/Gui/Selection/SoFCSelectionContext.h index d9cb345bbf..7eabce062d 100644 --- a/src/Gui/Selection/SoFCSelectionContext.h +++ b/src/Gui/Selection/SoFCSelectionContext.h @@ -23,6 +23,7 @@ #ifndef GUI_SOFCSELECTIONCONTEXT_H #define GUI_SOFCSELECTIONCONTEXT_H +#include #include #include #include diff --git a/src/Gui/ShortcutManager.cpp b/src/Gui/ShortcutManager.cpp index 2f49e8fd7d..0fbf60d3fe 100644 --- a/src/Gui/ShortcutManager.cpp +++ b/src/Gui/ShortcutManager.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include #endif diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index 978a7721a1..928284e67f 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -35,6 +35,7 @@ # include # include +# include # include # include # include diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index a4fdb99add..d25b0a201c 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +# include # include # include # include diff --git a/src/Gui/VectorListEditor.cpp b/src/Gui/VectorListEditor.cpp index 0e432920d1..85e69ec673 100644 --- a/src/Gui/VectorListEditor.cpp +++ b/src/Gui/VectorListEditor.cpp @@ -22,6 +22,10 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + #include "VectorListEditor.h" #include "ui_VectorListEditor.h" #include "QuantitySpinBox.h" diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 94bbd659f7..48733f4826 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -26,6 +26,7 @@ #ifndef _PreComp_ #include #include +#include #include #include #include diff --git a/src/Gui/propertyeditor/PropertyModel.cpp b/src/Gui/propertyeditor/PropertyModel.cpp index aa93d2563a..3babbd74f4 100644 --- a/src/Gui/propertyeditor/PropertyModel.cpp +++ b/src/Gui/propertyeditor/PropertyModel.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif From df6a76ba84059e28ac8238a6b9ab1e33ded0567d Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:50:49 +0200 Subject: [PATCH 095/316] CAM: Add `#include ` where used --- src/Mod/CAM/App/Area.cpp | 1 + src/Mod/CAM/App/PreCompiled.h | 1 + src/Mod/CAM/App/Voronoi.h | 1 + src/Mod/CAM/App/VoronoiEdgePyImp.cpp | 1 + src/Mod/CAM/Gui/ViewProviderPath.cpp | 1 + src/Mod/CAM/libarea/Area.cpp | 1 + 6 files changed, 6 insertions(+) diff --git a/src/Mod/CAM/App/Area.cpp b/src/Mod/CAM/App/Area.cpp index 82892eef4d..0e593cd448 100644 --- a/src/Mod/CAM/App/Area.cpp +++ b/src/Mod/CAM/App/Area.cpp @@ -26,6 +26,7 @@ #define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNING #ifndef _PreComp_ +#include #include #include diff --git a/src/Mod/CAM/App/PreCompiled.h b/src/Mod/CAM/App/PreCompiled.h index 470c653327..476d3f979d 100644 --- a/src/Mod/CAM/App/PreCompiled.h +++ b/src/Mod/CAM/App/PreCompiled.h @@ -45,6 +45,7 @@ // standard #include #include +#include #include #include #include diff --git a/src/Mod/CAM/App/Voronoi.h b/src/Mod/CAM/App/Voronoi.h index ff77698bfb..b00690850d 100644 --- a/src/Mod/CAM/App/Voronoi.h +++ b/src/Mod/CAM/App/Voronoi.h @@ -22,6 +22,7 @@ #ifndef PATH_VORONOI_H #define PATH_VORONOI_H +#include #include #include #include diff --git a/src/Mod/CAM/App/VoronoiEdgePyImp.cpp b/src/Mod/CAM/App/VoronoiEdgePyImp.cpp index bf47258083..0a26f6fe5e 100644 --- a/src/Mod/CAM/App/VoronoiEdgePyImp.cpp +++ b/src/Mod/CAM/App/VoronoiEdgePyImp.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif diff --git a/src/Mod/CAM/Gui/ViewProviderPath.cpp b/src/Mod/CAM/Gui/ViewProviderPath.cpp index 44698df05a..ce48d19271 100644 --- a/src/Mod/CAM/Gui/ViewProviderPath.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPath.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include diff --git a/src/Mod/CAM/libarea/Area.cpp b/src/Mod/CAM/libarea/Area.cpp index 770c150479..fa76059216 100644 --- a/src/Mod/CAM/libarea/Area.cpp +++ b/src/Mod/CAM/libarea/Area.cpp @@ -6,6 +6,7 @@ #include "Area.h" #include "AreaOrderer.h" +#include #include double CArea::m_accuracy = 0.01; From 1dc1cc8d1b550b8584460f7b09c3dfe8ee0d3ad0 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:50:57 +0200 Subject: [PATCH 096/316] Cloud: Add `#include ` where used --- src/Mod/Cloud/App/AppCloud.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Mod/Cloud/App/AppCloud.cpp b/src/Mod/Cloud/App/AppCloud.cpp index 6d26780d4e..3ec811dc04 100644 --- a/src/Mod/Cloud/App/AppCloud.cpp +++ b/src/Mod/Cloud/App/AppCloud.cpp @@ -22,6 +22,11 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + + #if defined(FC_OS_WIN32) #include #include From a6e1b894febdc347257dead527d20bc309461443 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:51:06 +0200 Subject: [PATCH 097/316] Fem: Add `#include ` where used --- src/Mod/Fem/App/FemConstraint.cpp | 1 + src/Mod/Fem/Gui/PreCompiled.h | 1 + src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintContact.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintForce.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintGear.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp | 1 + src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp | 1 + src/Mod/Fem/Gui/TaskPostBoxes.cpp | 2 +- src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp | 2 ++ 17 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/App/FemConstraint.cpp b/src/Mod/Fem/App/FemConstraint.cpp index 322e824335..87237513f5 100644 --- a/src/Mod/Fem/App/FemConstraint.cpp +++ b/src/Mod/Fem/App/FemConstraint.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Mod/Fem/Gui/PreCompiled.h b/src/Mod/Fem/Gui/PreCompiled.h index 41128a9151..cee7332325 100644 --- a/src/Mod/Fem/Gui/PreCompiled.h +++ b/src/Mod/Fem/Gui/PreCompiled.h @@ -40,6 +40,7 @@ // STL #include #include +#include #include #include #include diff --git a/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp b/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp index d054494ca6..ab6a5811ca 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintBearing.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp b/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp index 65c1744127..65019b1533 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintContact.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #endif #include "Mod/Fem/App/FemConstraintContact.h" diff --git a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp index b760434e77..86adc128d3 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp @@ -28,6 +28,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp b/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp index fb9a3fe912..2db9ff25ee 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintFluidBoundary.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp index fb8f7f9855..ef6e5a3119 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp b/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp index 9e139f899c..6b9e1637a7 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintGear.cpp @@ -26,6 +26,7 @@ #ifndef _PreComp_ #include #include +#include #endif #include diff --git a/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp b/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp index 0241563cbb..e9cc6090a9 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintHeatflux.cpp @@ -28,6 +28,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp b/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp index 41406cc1a2..a253f239b4 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintPressure.cpp @@ -26,6 +26,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp b/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp index ebc8ac670e..143118f68f 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintPulley.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include +#include #endif #include diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp index c1f5e17ee9..d3e8a43cf9 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp b/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp index e21fb5b299..413fe39bf9 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintSpring.cpp @@ -26,6 +26,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp b/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp index ff648c41e7..5dfe77200b 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintTemperature.cpp @@ -28,6 +28,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp b/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp index 894b27b62e..5d32f8fa7d 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintTransform.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.cpp b/src/Mod/Fem/Gui/TaskPostBoxes.cpp index dbd9dacbc4..3989857ce5 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.cpp +++ b/src/Mod/Fem/Gui/TaskPostBoxes.cpp @@ -29,7 +29,7 @@ #include #include - +#include #include #include #include diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 234f68dc9f..86b13b39c1 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -38,6 +38,8 @@ #include #include #include +#include + #include #include From 1669427449914d08ff0db83eb77b22413adc3ef8 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:51:31 +0200 Subject: [PATCH 098/316] Import: Add `#include ` where used --- src/Mod/Import/App/Tools.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mod/Import/App/Tools.h b/src/Mod/Import/App/Tools.h index 56b704e010..c2620e31fd 100644 --- a/src/Mod/Import/App/Tools.h +++ b/src/Mod/Import/App/Tools.h @@ -23,6 +23,8 @@ #ifndef IMPORT_TOOLS_H #define IMPORT_TOOLS_H +#include + #include #include #include From 1aeb594c80aff3d7b541c8c285031bf29650b79e Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:51:38 +0200 Subject: [PATCH 099/316] Inspection: Add `#include ` where used --- src/Mod/Inspection/Gui/ViewProviderInspection.h | 2 ++ src/Mod/Inspection/Gui/VisualInspection.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.h b/src/Mod/Inspection/Gui/ViewProviderInspection.h index ca3a575502..e7adedaf8f 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.h +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.h @@ -23,6 +23,8 @@ #ifndef INSPECTIOGUI_VIEWPROVIDERINSPECTION_H #define INSPECTIOGUI_VIEWPROVIDERINSPECTION_H +#include + #include #include #include diff --git a/src/Mod/Inspection/Gui/VisualInspection.cpp b/src/Mod/Inspection/Gui/VisualInspection.cpp index 4170624344..5be5012921 100644 --- a/src/Mod/Inspection/Gui/VisualInspection.cpp +++ b/src/Mod/Inspection/Gui/VisualInspection.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #endif #include From 368f1fc29636d1853d5fc52322c1a912c1ad9836 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:51:52 +0200 Subject: [PATCH 100/316] Mesh: Add `#include ` where used --- src/Mod/Mesh/App/Core/Algorithm.cpp | 1 + src/Mod/Mesh/App/Core/Approximation.cpp | 1 + src/Mod/Mesh/App/Core/Approximation.h | 1 + src/Mod/Mesh/App/Core/Curvature.cpp | 1 + src/Mod/Mesh/App/Core/CylinderFit.cpp | 1 + src/Mod/Mesh/App/Core/Decimation.cpp | 3 +++ src/Mod/Mesh/App/Core/Elements.cpp | 3 +++ src/Mod/Mesh/App/Core/Elements.h | 1 + src/Mod/Mesh/App/Core/Grid.cpp | 1 + src/Mod/Mesh/App/Core/Grid.h | 1 + src/Mod/Mesh/App/Core/MeshKernel.cpp | 1 + src/Mod/Mesh/App/Core/Projection.cpp | 1 + src/Mod/Mesh/App/Core/Segmentation.cpp | 1 + src/Mod/Mesh/App/Core/Smoothing.h | 1 + src/Mod/Mesh/App/Core/SphereFit.cpp | 1 + src/Mod/Mesh/App/Core/Tools.h | 1 + src/Mod/Mesh/App/Core/TopoAlgorithm.cpp | 1 + src/Mod/Mesh/App/Core/Triangulation.cpp | 1 + src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp | 3 +++ src/Mod/Mesh/App/FeatureMeshSolid.cpp | 3 +++ src/Mod/Mesh/App/MeshFeaturePyImp.cpp | 3 +++ src/Mod/Mesh/App/MeshPoint.h | 1 + src/Mod/Mesh/App/MeshPointPyImp.cpp | 1 + src/Mod/Mesh/App/PreCompiled.h | 1 + src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp | 1 + src/Mod/Mesh/Gui/Command.cpp | 1 + src/Mod/Mesh/Gui/MeshEditor.cpp | 1 + src/Mod/Mesh/Gui/RemoveComponents.cpp | 1 + src/Mod/Mesh/Gui/Segmentation.cpp | 1 + src/Mod/Mesh/Gui/SegmentationBestFit.cpp | 1 + src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp | 1 + src/Mod/Mesh/Gui/SoFCMeshObject.cpp | 1 + src/Mod/Mesh/Gui/SoPolygon.cpp | 1 + 33 files changed, 43 insertions(+) diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index 3f513925f8..5ceb1d3e8b 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include +#include #endif #include diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index cf7123a9ed..f0b8d2c25c 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #endif #include diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 32e7211390..b7d6688597 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -28,6 +28,7 @@ #include #endif #include +#include #include #include #include diff --git a/src/Mod/Mesh/App/Core/Curvature.cpp b/src/Mod/Mesh/App/Core/Curvature.cpp index 15b2c8733b..0cc38a7f12 100644 --- a/src/Mod/Mesh/App/Core/Curvature.cpp +++ b/src/Mod/Mesh/App/Core/Curvature.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #endif #include diff --git a/src/Mod/Mesh/App/Core/CylinderFit.cpp b/src/Mod/Mesh/App/Core/CylinderFit.cpp index cc44aa2d74..3cec8a71f5 100644 --- a/src/Mod/Mesh/App/Core/CylinderFit.cpp +++ b/src/Mod/Mesh/App/Core/CylinderFit.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #endif #include diff --git a/src/Mod/Mesh/App/Core/Decimation.cpp b/src/Mod/Mesh/App/Core/Decimation.cpp index da40713799..4f02f5ac43 100644 --- a/src/Mod/Mesh/App/Core/Decimation.cpp +++ b/src/Mod/Mesh/App/Core/Decimation.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include "Decimation.h" #include "MeshKernel.h" diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index 428358f9ca..7fd1d86a96 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include #include diff --git a/src/Mod/Mesh/App/Core/Elements.h b/src/Mod/Mesh/App/Core/Elements.h index 1c2521576f..486542ce2a 100644 --- a/src/Mod/Mesh/App/Core/Elements.h +++ b/src/Mod/Mesh/App/Core/Elements.h @@ -25,6 +25,7 @@ #include #include +#include #include #include diff --git a/src/Mod/Mesh/App/Core/Grid.cpp b/src/Mod/Mesh/App/Core/Grid.cpp index 083d834f10..17ef47eb53 100644 --- a/src/Mod/Mesh/App/Core/Grid.cpp +++ b/src/Mod/Mesh/App/Core/Grid.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include #include +#include #endif #include "Algorithm.h" diff --git a/src/Mod/Mesh/App/Core/Grid.h b/src/Mod/Mesh/App/Core/Grid.h index e5f9c46360..63881d0796 100644 --- a/src/Mod/Mesh/App/Core/Grid.h +++ b/src/Mod/Mesh/App/Core/Grid.h @@ -23,6 +23,7 @@ #ifndef MESH_GRID_H #define MESH_GRID_H +#include #include #include diff --git a/src/Mod/Mesh/App/Core/MeshKernel.cpp b/src/Mod/Mesh/App/Core/MeshKernel.cpp index b2def70220..9191516af3 100644 --- a/src/Mod/Mesh/App/Core/MeshKernel.cpp +++ b/src/Mod/Mesh/App/Core/MeshKernel.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include #include +#include #include #include #include diff --git a/src/Mod/Mesh/App/Core/Projection.cpp b/src/Mod/Mesh/App/Core/Projection.cpp index 06c676b234..030f2b83da 100644 --- a/src/Mod/Mesh/App/Core/Projection.cpp +++ b/src/Mod/Mesh/App/Core/Projection.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #include #endif diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 5fd0dd410f..9061f17e85 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #endif #include "Algorithm.h" diff --git a/src/Mod/Mesh/App/Core/Smoothing.h b/src/Mod/Mesh/App/Core/Smoothing.h index 4579f01959..38518480ed 100644 --- a/src/Mod/Mesh/App/Core/Smoothing.h +++ b/src/Mod/Mesh/App/Core/Smoothing.h @@ -23,6 +23,7 @@ #ifndef MESH_SMOOTHING_H #define MESH_SMOOTHING_H +#include #include #include "Definitions.h" diff --git a/src/Mod/Mesh/App/Core/SphereFit.cpp b/src/Mod/Mesh/App/Core/SphereFit.cpp index c53812a1b1..91ae259706 100644 --- a/src/Mod/Mesh/App/Core/SphereFit.cpp +++ b/src/Mod/Mesh/App/Core/SphereFit.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #endif #include "SphereFit.h" diff --git a/src/Mod/Mesh/App/Core/Tools.h b/src/Mod/Mesh/App/Core/Tools.h index 4c61987538..8e08609c0c 100644 --- a/src/Mod/Mesh/App/Core/Tools.h +++ b/src/Mod/Mesh/App/Core/Tools.h @@ -24,6 +24,7 @@ #define MESH_TOOLS_H #include +#include #include #include diff --git a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp index 48d92741de..9d7960f847 100644 --- a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp +++ b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #endif diff --git a/src/Mod/Mesh/App/Core/Triangulation.cpp b/src/Mod/Mesh/App/Core/Triangulation.cpp index 7d6855b573..710f64df8f 100644 --- a/src/Mod/Mesh/App/Core/Triangulation.cpp +++ b/src/Mod/Mesh/App/Core/Triangulation.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #include #endif diff --git a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp index 7cdb9060fe..ee8975d2db 100644 --- a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include diff --git a/src/Mod/Mesh/App/FeatureMeshSolid.cpp b/src/Mod/Mesh/App/FeatureMeshSolid.cpp index e2d1a53e76..41262f3669 100644 --- a/src/Mod/Mesh/App/FeatureMeshSolid.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSolid.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include diff --git a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp index f3770dac7b..74eca9fd43 100644 --- a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp +++ b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include "MeshFeature.h" // inclusion of the generated files (generated out of MeshFeaturePy.xml) diff --git a/src/Mod/Mesh/App/MeshPoint.h b/src/Mod/Mesh/App/MeshPoint.h index a29270108e..b0096d082f 100644 --- a/src/Mod/Mesh/App/MeshPoint.h +++ b/src/Mod/Mesh/App/MeshPoint.h @@ -23,6 +23,7 @@ #ifndef MESH_MESHPOINT_H #define MESH_MESHPOINT_H +#include #include #include diff --git a/src/Mod/Mesh/App/MeshPointPyImp.cpp b/src/Mod/Mesh/App/MeshPointPyImp.cpp index a4b62e1569..1cba0da0d7 100644 --- a/src/Mod/Mesh/App/MeshPointPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPointPyImp.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif diff --git a/src/Mod/Mesh/App/PreCompiled.h b/src/Mod/Mesh/App/PreCompiled.h index 7484b92f22..5580e172a8 100644 --- a/src/Mod/Mesh/App/PreCompiled.h +++ b/src/Mod/Mesh/App/PreCompiled.h @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp b/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp index f497f0851e..48f0e4b2f0 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp +++ b/src/Mod/Mesh/App/WildMagic4/Wm4Math.cpp @@ -16,6 +16,7 @@ #include "Wm4FoundationPCH.h" #include "Wm4Math.h" +#include namespace Wm4 { diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 6bfe41ea90..cfbc9d9842 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -26,6 +26,7 @@ #include #endif #include +#include #include #include diff --git a/src/Mod/Mesh/Gui/MeshEditor.cpp b/src/Mod/Mesh/Gui/MeshEditor.cpp index 9ffa3ce5a3..ef46e4d378 100644 --- a/src/Mod/Mesh/Gui/MeshEditor.cpp +++ b/src/Mod/Mesh/Gui/MeshEditor.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/src/Mod/Mesh/Gui/RemoveComponents.cpp b/src/Mod/Mesh/Gui/RemoveComponents.cpp index 5e54c225b7..9df41394af 100644 --- a/src/Mod/Mesh/Gui/RemoveComponents.cpp +++ b/src/Mod/Mesh/Gui/RemoveComponents.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp index 050e9f5327..ff648a83aa 100644 --- a/src/Mod/Mesh/Gui/Segmentation.cpp +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif diff --git a/src/Mod/Mesh/Gui/SegmentationBestFit.cpp b/src/Mod/Mesh/Gui/SegmentationBestFit.cpp index 2a147ac04b..3b413e0228 100644 --- a/src/Mod/Mesh/Gui/SegmentationBestFit.cpp +++ b/src/Mod/Mesh/Gui/SegmentationBestFit.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include diff --git a/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp b/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp index be7c40a5ea..997b8f8148 100644 --- a/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp +++ b/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp @@ -30,6 +30,7 @@ #ifndef _PreComp_ #include +#include #ifdef FC_OS_MACOSX #include #include diff --git a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp index 904f6fdf48..2304b30633 100644 --- a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp +++ b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #ifdef FC_OS_WIN32 #include #endif diff --git a/src/Mod/Mesh/Gui/SoPolygon.cpp b/src/Mod/Mesh/Gui/SoPolygon.cpp index a5b242c82b..bd8f626136 100644 --- a/src/Mod/Mesh/Gui/SoPolygon.cpp +++ b/src/Mod/Mesh/Gui/SoPolygon.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #ifdef FC_OS_WIN32 #include #endif From 0ac87c8a270943ce99a3212ab274d8f0f4c1e49f Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:00 +0200 Subject: [PATCH 101/316] MeshPart: Add `#include ` where used --- src/Mod/MeshPart/App/CurveProjector.cpp | 1 + src/Mod/MeshPart/App/CurveProjector.h | 2 ++ src/Mod/MeshPart/Gui/CrossSections.cpp | 1 + 3 files changed, 4 insertions(+) diff --git a/src/Mod/MeshPart/App/CurveProjector.cpp b/src/Mod/MeshPart/App/CurveProjector.cpp index db9926b50d..866d239a10 100644 --- a/src/Mod/MeshPart/App/CurveProjector.cpp +++ b/src/Mod/MeshPart/App/CurveProjector.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #ifdef FC_OS_LINUX #include #endif diff --git a/src/Mod/MeshPart/App/CurveProjector.h b/src/Mod/MeshPart/App/CurveProjector.h index d8fd6386d1..0d0a3262e9 100644 --- a/src/Mod/MeshPart/App/CurveProjector.h +++ b/src/Mod/MeshPart/App/CurveProjector.h @@ -23,6 +23,8 @@ #ifndef _CurveProjector_h_ #define _CurveProjector_h_ +#include + #include #include diff --git a/src/Mod/MeshPart/Gui/CrossSections.cpp b/src/Mod/MeshPart/Gui/CrossSections.cpp index 2ba73eeeac..00df2c45a1 100644 --- a/src/Mod/MeshPart/Gui/CrossSections.cpp +++ b/src/Mod/MeshPart/Gui/CrossSections.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include From d5447df72d30b82d7dc5692fdee8cad7f43fdef7 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:08 +0200 Subject: [PATCH 102/316] Part: Add `#include ` where used --- src/Mod/Part/App/Geometry.cpp | 1 + src/Mod/Part/App/ShapeMapHasher.h | 2 ++ src/Mod/Part/App/TopoShapeEdgePyImp.cpp | 1 + src/Mod/Part/App/TopoShapeExpansion.cpp | 1 + src/Mod/Part/App/TopoShapeMapper.h | 1 + src/Mod/Part/App/TopoShapePyImp.cpp | 1 + src/Mod/Part/App/WireJoiner.cpp | 1 + src/Mod/Part/Gui/CrossSections.cpp | 1 + src/Mod/Part/Gui/DlgPrimitives.cpp | 1 + src/Mod/Part/Gui/DlgProjectionOnSurface.cpp | 1 + src/Mod/Part/Gui/DlgRevolution.cpp | 1 + src/Mod/Part/Gui/Mirroring.cpp | 1 + src/Mod/Part/Gui/PreCompiled.h | 1 + src/Mod/Part/Gui/SectionCutting.cpp | 1 + src/Mod/Part/Gui/SoBrepEdgeSet.cpp | 1 + src/Mod/Part/Gui/SoBrepFaceSet.cpp | 1 + src/Mod/Part/Gui/SoBrepPointSet.cpp | 1 + src/Mod/Part/Gui/SoFCShapeObject.cpp | 1 + src/Mod/Part/Gui/TaskOffset.cpp | 1 + src/Mod/Part/Gui/TaskThickness.cpp | 1 + src/Mod/Part/Gui/ViewProvider2DObject.cpp | 1 + src/Mod/Part/Gui/ViewProviderGridExtension.cpp | 2 ++ 22 files changed, 24 insertions(+) diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index bc545995af..4245c39884 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -105,6 +105,7 @@ # include # include # include +# include #endif //_PreComp_ #include diff --git a/src/Mod/Part/App/ShapeMapHasher.h b/src/Mod/Part/App/ShapeMapHasher.h index 24ab2a5b30..fdd8d07f6f 100644 --- a/src/Mod/Part/App/ShapeMapHasher.h +++ b/src/Mod/Part/App/ShapeMapHasher.h @@ -24,6 +24,8 @@ #ifndef PART_SHAPEMAPHASHER_H #define PART_SHAPEMAPHASHER_H +#include + #include #include #if OCC_VERSION_HEX >= 0x070800 diff --git a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp index b3257c90fd..f34dc29e38 100644 --- a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 39fd232357..11cdc6e3c7 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -26,6 +26,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #include #include diff --git a/src/Mod/Part/App/TopoShapeMapper.h b/src/Mod/Part/App/TopoShapeMapper.h index 0febe93d47..4fb67c2865 100644 --- a/src/Mod/Part/App/TopoShapeMapper.h +++ b/src/Mod/Part/App/TopoShapeMapper.h @@ -21,6 +21,7 @@ * * ***************************************************************************/ +#include #include #include #include diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index c0b2ca1d2e..52e9bf3147 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include diff --git a/src/Mod/Part/App/WireJoiner.cpp b/src/Mod/Part/App/WireJoiner.cpp index abe3cf1326..f3688caf0f 100644 --- a/src/Mod/Part/App/WireJoiner.cpp +++ b/src/Mod/Part/App/WireJoiner.cpp @@ -26,6 +26,7 @@ #include #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/Part/Gui/CrossSections.cpp b/src/Mod/Part/Gui/CrossSections.cpp index ed2f1f8dad..7f6dfa06eb 100644 --- a/src/Mod/Part/Gui/CrossSections.cpp +++ b/src/Mod/Part/Gui/CrossSections.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include diff --git a/src/Mod/Part/Gui/DlgPrimitives.cpp b/src/Mod/Part/Gui/DlgPrimitives.cpp index ef411ecb96..f279f81573 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.cpp +++ b/src/Mod/Part/Gui/DlgPrimitives.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp b/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp index 01fe09b9d0..7267f49703 100644 --- a/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp +++ b/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Mod/Part/Gui/DlgRevolution.cpp b/src/Mod/Part/Gui/DlgRevolution.cpp index 04672dd218..5002410851 100644 --- a/src/Mod/Part/Gui/DlgRevolution.cpp +++ b/src/Mod/Part/Gui/DlgRevolution.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/Part/Gui/Mirroring.cpp b/src/Mod/Part/Gui/Mirroring.cpp index 09881413da..86880d8692 100644 --- a/src/Mod/Part/Gui/Mirroring.cpp +++ b/src/Mod/Part/Gui/Mirroring.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ # include +# include # include # include diff --git a/src/Mod/Part/Gui/PreCompiled.h b/src/Mod/Part/Gui/PreCompiled.h index 2eabeb2acf..9663515d0b 100644 --- a/src/Mod/Part/Gui/PreCompiled.h +++ b/src/Mod/Part/Gui/PreCompiled.h @@ -49,6 +49,7 @@ // STL #include +#include #include #include #include diff --git a/src/Mod/Part/Gui/SectionCutting.cpp b/src/Mod/Part/Gui/SectionCutting.cpp index 0885ffa9ed..b5febc76eb 100644 --- a/src/Mod/Part/Gui/SectionCutting.cpp +++ b/src/Mod/Part/Gui/SectionCutting.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include # include diff --git a/src/Mod/Part/Gui/SoBrepEdgeSet.cpp b/src/Mod/Part/Gui/SoBrepEdgeSet.cpp index 6d8c5d2bba..934ae99343 100644 --- a/src/Mod/Part/Gui/SoBrepEdgeSet.cpp +++ b/src/Mod/Part/Gui/SoBrepEdgeSet.cpp @@ -32,6 +32,7 @@ # include # endif # include +# include # include # include # include diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.cpp b/src/Mod/Part/Gui/SoBrepFaceSet.cpp index 1f0c9be301..e8ada70029 100644 --- a/src/Mod/Part/Gui/SoBrepFaceSet.cpp +++ b/src/Mod/Part/Gui/SoBrepFaceSet.cpp @@ -30,6 +30,7 @@ #ifndef _PreComp_ # include +# include # include # include # include diff --git a/src/Mod/Part/Gui/SoBrepPointSet.cpp b/src/Mod/Part/Gui/SoBrepPointSet.cpp index e8cef49446..d674011d3f 100644 --- a/src/Mod/Part/Gui/SoBrepPointSet.cpp +++ b/src/Mod/Part/Gui/SoBrepPointSet.cpp @@ -32,6 +32,7 @@ # include # endif # include +# include # include # include # include diff --git a/src/Mod/Part/Gui/SoFCShapeObject.cpp b/src/Mod/Part/Gui/SoFCShapeObject.cpp index 1ee21830ce..c6b1f31955 100644 --- a/src/Mod/Part/Gui/SoFCShapeObject.cpp +++ b/src/Mod/Part/Gui/SoFCShapeObject.cpp @@ -32,6 +32,7 @@ # include # endif # include +# include # include # include # include diff --git a/src/Mod/Part/Gui/TaskOffset.cpp b/src/Mod/Part/Gui/TaskOffset.cpp index c8bd77aaf3..13548e85b7 100644 --- a/src/Mod/Part/Gui/TaskOffset.cpp +++ b/src/Mod/Part/Gui/TaskOffset.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include #endif diff --git a/src/Mod/Part/Gui/TaskThickness.cpp b/src/Mod/Part/Gui/TaskThickness.cpp index cc5e27dafc..618fe3b923 100644 --- a/src/Mod/Part/Gui/TaskThickness.cpp +++ b/src/Mod/Part/Gui/TaskThickness.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include #endif diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.cpp b/src/Mod/Part/Gui/ViewProvider2DObject.cpp index b54dab267f..c555600f69 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.cpp +++ b/src/Mod/Part/Gui/ViewProvider2DObject.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ +# include # include # include diff --git a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp index f624823a22..986de17151 100644 --- a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp +++ b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp @@ -24,6 +24,8 @@ #ifndef _PreComp_ +# include + # include # include # include From 65a0fb0ed4c4d519e8b38e2caaa53a51e2896bc6 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:18 +0200 Subject: [PATCH 103/316] PartDesign: Add `#include ` where used --- src/Mod/PartDesign/App/FeatureChamfer.cpp | 4 ++-- src/Mod/PartDesign/App/FeatureExtrude.cpp | 1 + src/Mod/PartDesign/App/FeatureFillet.cpp | 1 + src/Mod/PartDesign/App/FeatureHelix.cpp | 1 + src/Mod/PartDesign/App/FeatureHole.cpp | 1 + src/Mod/PartDesign/App/FeatureLinearPattern.cpp | 1 + src/Mod/PartDesign/App/FeaturePolarPattern.cpp | 1 + src/Mod/PartDesign/App/FeaturePrimitive.cpp | 1 + src/Mod/PartDesign/App/PreCompiled.h | 3 +++ src/Mod/PartDesign/Gui/PreCompiled.h | 3 +++ src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp | 1 + src/Mod/PartDesign/Gui/TaskScaledParameters.cpp | 1 + src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp | 1 + 13 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp b/src/Mod/PartDesign/App/FeatureChamfer.cpp index c09aa683d2..e154eb2411 100644 --- a/src/Mod/PartDesign/App/FeatureChamfer.cpp +++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp @@ -23,6 +23,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include + # include # include # include @@ -35,8 +37,6 @@ # include #endif -#include - #include #include #include diff --git a/src/Mod/PartDesign/App/FeatureExtrude.cpp b/src/Mod/PartDesign/App/FeatureExtrude.cpp index fbe4560184..f1a6f43d7c 100644 --- a/src/Mod/PartDesign/App/FeatureExtrude.cpp +++ b/src/Mod/PartDesign/App/FeatureExtrude.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/FeatureFillet.cpp b/src/Mod/PartDesign/App/FeatureFillet.cpp index c44653a76f..35e7250330 100644 --- a/src/Mod/PartDesign/App/FeatureFillet.cpp +++ b/src/Mod/PartDesign/App/FeatureFillet.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/FeatureHelix.cpp b/src/Mod/PartDesign/App/FeatureHelix.cpp index 7acc3f267b..4afb42f670 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.cpp +++ b/src/Mod/PartDesign/App/FeatureHelix.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index d3fc78e2f9..448db0bad9 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp index 9d01fc33ab..d03dba8209 100644 --- a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp +++ b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp index 7272147711..9a5aa64c91 100644 --- a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp +++ b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/FeaturePrimitive.cpp b/src/Mod/PartDesign/App/FeaturePrimitive.cpp index 72e772765a..bf8e664029 100644 --- a/src/Mod/PartDesign/App/FeaturePrimitive.cpp +++ b/src/Mod/PartDesign/App/FeaturePrimitive.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include diff --git a/src/Mod/PartDesign/App/PreCompiled.h b/src/Mod/PartDesign/App/PreCompiled.h index e9594d34c6..8fac6ad1b1 100644 --- a/src/Mod/PartDesign/App/PreCompiled.h +++ b/src/Mod/PartDesign/App/PreCompiled.h @@ -34,6 +34,9 @@ #ifdef _PreComp_ +// stl +#include + // OpenCasCade #include diff --git a/src/Mod/PartDesign/Gui/PreCompiled.h b/src/Mod/PartDesign/Gui/PreCompiled.h index 20cba24151..2c3a580028 100644 --- a/src/Mod/PartDesign/Gui/PreCompiled.h +++ b/src/Mod/PartDesign/Gui/PreCompiled.h @@ -55,6 +55,9 @@ #include #include +// stl +#include + // Qt # include diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp index a6d37a9362..d7546695f3 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif diff --git a/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp b/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp index ffb399a6ed..0dfc4d4a5e 100644 --- a/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #endif #include diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp index 6c7f7f77c3..7e7d3ba87e 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include From 30ff61f7c0699b50489191bfbb10a7a37db563d4 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:24 +0200 Subject: [PATCH 104/316] Point: Add `#include ` where used --- src/Mod/Points/App/PointsGrid.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Points/App/PointsGrid.h b/src/Mod/Points/App/PointsGrid.h index 52a6fc248a..948bd045fa 100644 --- a/src/Mod/Points/App/PointsGrid.h +++ b/src/Mod/Points/App/PointsGrid.h @@ -23,6 +23,7 @@ #ifndef POINTS_GRID_H #define POINTS_GRID_H +#include #include #include From 5b436f2a83d2a5cfaf30b78dddf9f298215d87b0 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:33 +0200 Subject: [PATCH 105/316] ReverseEngineering: Add `#include ` where used --- src/Mod/ReverseEngineering/Gui/Command.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/ReverseEngineering/Gui/Command.cpp b/src/Mod/ReverseEngineering/Gui/Command.cpp index 2b184c39fa..8ac65d98d6 100644 --- a/src/Mod/ReverseEngineering/Gui/Command.cpp +++ b/src/Mod/ReverseEngineering/Gui/Command.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #include #include From 4b589088f6f8f3a143abd56b7766e0faef04ad58 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:38 +0200 Subject: [PATCH 106/316] Sketcher: Add `#include ` where used --- src/Mod/Sketcher/App/PreCompiled.h | 1 + src/Mod/Sketcher/App/PropertyConstraintList.cpp | 1 + src/Mod/Sketcher/App/SketchObject.cpp | 1 + src/Mod/Sketcher/Gui/CommandConstraints.cpp | 1 + src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h | 2 ++ src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp | 1 + src/Mod/Sketcher/Gui/PreCompiled.h | 1 + src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp | 1 + src/Mod/Sketcher/Gui/TaskSketcherElements.cpp | 1 + src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 2 ++ 10 files changed, 12 insertions(+) diff --git a/src/Mod/Sketcher/App/PreCompiled.h b/src/Mod/Sketcher/App/PreCompiled.h index b9d6e3ac32..5bdacf3b44 100644 --- a/src/Mod/Sketcher/App/PreCompiled.h +++ b/src/Mod/Sketcher/App/PreCompiled.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Sketcher/App/PropertyConstraintList.cpp b/src/Mod/Sketcher/App/PropertyConstraintList.cpp index 0cc4fca622..8e00ab0940 100644 --- a/src/Mod/Sketcher/App/PropertyConstraintList.cpp +++ b/src/Mod/Sketcher/App/PropertyConstraintList.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #endif #include diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index c456d45f16..77fadd32bd 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #include #include diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 8ed676bb93..4ad4981384 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h index 509d347027..c60285d2db 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h @@ -24,6 +24,8 @@ #ifndef SKETCHERGUI_DrawSketchHandlerOffset_H #define SKETCHERGUI_DrawSketchHandlerOffset_H +#include + #include #include diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index f69d71d71e..398c2534ab 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include #include +#include #include #include diff --git a/src/Mod/Sketcher/Gui/PreCompiled.h b/src/Mod/Sketcher/Gui/PreCompiled.h index d4a2ac5e7c..0afecab80c 100644 --- a/src/Mod/Sketcher/Gui/PreCompiled.h +++ b/src/Mod/Sketcher/Gui/PreCompiled.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp index 397d501703..49ac068091 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include diff --git a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp index 551b9fa90f..8518263495 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 3c27a517df..3107c34e11 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -38,6 +38,8 @@ #include #include #include + +#include #endif #include From 8073075301f59a0b646ea3147ef0fdde4d0d0277 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:48 +0200 Subject: [PATCH 107/316] Spreadsheet: Add `#include ` where used --- src/Mod/Spreadsheet/Gui/PreCompiled.h | 1 + src/Mod/Spreadsheet/Gui/SheetTableView.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Mod/Spreadsheet/Gui/PreCompiled.h b/src/Mod/Spreadsheet/Gui/PreCompiled.h index 2166289b3f..0828f48db3 100644 --- a/src/Mod/Spreadsheet/Gui/PreCompiled.h +++ b/src/Mod/Spreadsheet/Gui/PreCompiled.h @@ -40,6 +40,7 @@ #include // STL +#include #include #ifdef FC_OS_WIN32 diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp index 10013b96b5..dc8b7623c1 100644 --- a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include From 3462c165d83deb2db382302e7edfbda83d00ca63 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:52:55 +0200 Subject: [PATCH 108/316] Surface: Add `#include ` where used --- src/Mod/Surface/App/FeatureExtend.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Surface/App/FeatureExtend.cpp b/src/Mod/Surface/App/FeatureExtend.cpp index 518a300d18..24c83fcc34 100644 --- a/src/Mod/Surface/App/FeatureExtend.cpp +++ b/src/Mod/Surface/App/FeatureExtend.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include From d0320b494da3269ad8c7de36dd1da57ccf48b323 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:53:03 +0200 Subject: [PATCH 109/316] TechDraw: Add `#include ` where used --- src/Mod/TechDraw/App/DrawDimHelper.cpp | 1 + src/Mod/TechDraw/App/DrawGeomHatch.cpp | 1 + src/Mod/TechDraw/App/DrawProjGroup.cpp | 1 + src/Mod/TechDraw/App/DrawUtil.cpp | 1 + src/Mod/TechDraw/App/DrawUtil.h | 1 + src/Mod/TechDraw/App/DrawView.cpp | 1 + src/Mod/TechDraw/App/DrawViewBalloon.cpp | 1 + src/Mod/TechDraw/App/DrawViewDimension.cpp | 1 + src/Mod/TechDraw/App/DrawViewSection.cpp | 1 + src/Mod/TechDraw/App/EdgeWalker.cpp | 1 + src/Mod/TechDraw/App/Geometry.cpp | 9 +++++---- src/Mod/TechDraw/App/ShapeUtils.cpp | 1 + src/Mod/TechDraw/Gui/CommandCreateDims.cpp | 1 + src/Mod/TechDraw/Gui/DimensionValidators.cpp | 1 + src/Mod/TechDraw/Gui/PreCompiled.h | 1 + src/Mod/TechDraw/Gui/QGIViewDimension.cpp | 1 + src/Mod/TechDraw/Gui/TaskDimension.cpp | 1 + src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp | 1 + src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp | 3 +-- 19 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawDimHelper.cpp b/src/Mod/TechDraw/App/DrawDimHelper.cpp index cb445b9811..e691a539fe 100644 --- a/src/Mod/TechDraw/App/DrawDimHelper.cpp +++ b/src/Mod/TechDraw/App/DrawDimHelper.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include # include diff --git a/src/Mod/TechDraw/App/DrawGeomHatch.cpp b/src/Mod/TechDraw/App/DrawGeomHatch.cpp index 72412cf557..7529cb38ee 100644 --- a/src/Mod/TechDraw/App/DrawGeomHatch.cpp +++ b/src/Mod/TechDraw/App/DrawGeomHatch.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include #include diff --git a/src/Mod/TechDraw/App/DrawProjGroup.cpp b/src/Mod/TechDraw/App/DrawProjGroup.cpp index 2b05d8ab60..ebf21b07fd 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroup.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index 5e0dfc7a1c..b3ca7edba7 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 7490e58622..95e61017e4 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -23,6 +23,7 @@ #ifndef DrawUtil_h_ #define DrawUtil_h_ +#include #include #include diff --git a/src/Mod/TechDraw/App/DrawView.cpp b/src/Mod/TechDraw/App/DrawView.cpp index 32ed36cec0..708fd2ad65 100644 --- a/src/Mod/TechDraw/App/DrawView.cpp +++ b/src/Mod/TechDraw/App/DrawView.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include # include # include diff --git a/src/Mod/TechDraw/App/DrawViewBalloon.cpp b/src/Mod/TechDraw/App/DrawViewBalloon.cpp index 8ebb50cafa..e2dda3491b 100644 --- a/src/Mod/TechDraw/App/DrawViewBalloon.cpp +++ b/src/Mod/TechDraw/App/DrawViewBalloon.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index a16883c267..6d6faa663b 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 0df11b27a5..b629690c5f 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -71,6 +71,7 @@ #include #include #include +#include #include #endif diff --git a/src/Mod/TechDraw/App/EdgeWalker.cpp b/src/Mod/TechDraw/App/EdgeWalker.cpp index d30f1d9607..3d3f1f4891 100644 --- a/src/Mod/TechDraw/App/EdgeWalker.cpp +++ b/src/Mod/TechDraw/App/EdgeWalker.cpp @@ -29,6 +29,7 @@ #ifndef _PreComp_ # include +# include # include # include # include diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index 6011cbea15..3321e88f47 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include @@ -36,12 +37,12 @@ # include # include # include -#include +# include # include # include -#include -#include -#include +# include +# include +# include # include # include diff --git a/src/Mod/TechDraw/App/ShapeUtils.cpp b/src/Mod/TechDraw/App/ShapeUtils.cpp index 6e5c070fe5..1a02b267da 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.cpp +++ b/src/Mod/TechDraw/App/ShapeUtils.cpp @@ -27,6 +27,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Mod/TechDraw/Gui/CommandCreateDims.cpp b/src/Mod/TechDraw/Gui/CommandCreateDims.cpp index 5c02639b3b..983de413a2 100644 --- a/src/Mod/TechDraw/Gui/CommandCreateDims.cpp +++ b/src/Mod/TechDraw/Gui/CommandCreateDims.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include diff --git a/src/Mod/TechDraw/Gui/DimensionValidators.cpp b/src/Mod/TechDraw/Gui/DimensionValidators.cpp index 9f24fdf162..ab3f776c7b 100644 --- a/src/Mod/TechDraw/Gui/DimensionValidators.cpp +++ b/src/Mod/TechDraw/Gui/DimensionValidators.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include diff --git a/src/Mod/TechDraw/Gui/PreCompiled.h b/src/Mod/TechDraw/Gui/PreCompiled.h index 5f034dad6c..544f0447ff 100644 --- a/src/Mod/TechDraw/Gui/PreCompiled.h +++ b/src/Mod/TechDraw/Gui/PreCompiled.h @@ -41,6 +41,7 @@ #include #include #include +#include #include // STL diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index 27fdc744ed..baa1c20c0b 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include # include diff --git a/src/Mod/TechDraw/Gui/TaskDimension.cpp b/src/Mod/TechDraw/Gui/TaskDimension.cpp index f3794c9c9c..6428a9e045 100644 --- a/src/Mod/TechDraw/Gui/TaskDimension.cpp +++ b/src/Mod/TechDraw/Gui/TaskDimension.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include # include #endif // #ifndef _PreComp_ diff --git a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp index 311e885f5d..f90ee88df0 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif diff --git a/src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp b/src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp index 7b30cf89de..3f1086883d 100644 --- a/src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp +++ b/src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #include @@ -40,8 +41,6 @@ #include -#include - #include #include From d61dcb2e6d34818186092f6467c5c365e84ce3f3 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:53:10 +0200 Subject: [PATCH 110/316] Web: Add `#include ` where used --- src/Mod/Web/App/AppWeb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Web/App/AppWeb.cpp b/src/Mod/Web/App/AppWeb.cpp index 54b2a9ebbc..b5a298ff75 100644 --- a/src/Mod/Web/App/AppWeb.cpp +++ b/src/Mod/Web/App/AppWeb.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif From c97ce5b5e9c42455f10de31f865f5cad78fee09c Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 31 Mar 2025 23:53:16 +0200 Subject: [PATCH 111/316] Tools: Add `#include ` where used --- src/Tools/plugins/widget/customwidgets.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tools/plugins/widget/customwidgets.cpp b/src/Tools/plugins/widget/customwidgets.cpp index b5e5dec404..9444ae48b4 100644 --- a/src/Tools/plugins/widget/customwidgets.cpp +++ b/src/Tools/plugins/widget/customwidgets.cpp @@ -20,6 +20,7 @@ * * ***************************************************************************/ +#include #include #include From 81b7b0c4571ad8c25aa5583d2cd576532d5f4399 Mon Sep 17 00:00:00 2001 From: David Carter Date: Mon, 31 Mar 2025 22:46:12 -0400 Subject: [PATCH 112/316] Material: Interface with an external module The ExternalManager class calls python functions in an external module to create, read, update, and delete material definitions. The API provided by the modules must conform to that defined in the MaterialManagerExternal.py file. All communications with the external module is routed through this class. --- src/Mod/Material/App/CMakeLists.txt | 26 + src/Mod/Material/App/ExternalManager.cpp | 788 ++++++++++++++++++ src/Mod/Material/App/ExternalManager.h | 108 +++ src/Mod/Material/App/Library.cpp | 10 + src/Mod/Material/App/Library.h | 15 +- .../MaterialAPI/MaterialManagerExternal.py | 246 ++++++ src/Mod/Material/App/MaterialAPI/__init__.py | 0 src/Mod/Material/App/MaterialManagerLocal.cpp | 12 +- 8 files changed, 1198 insertions(+), 7 deletions(-) create mode 100644 src/Mod/Material/App/ExternalManager.cpp create mode 100644 src/Mod/Material/App/ExternalManager.h create mode 100644 src/Mod/Material/App/MaterialAPI/MaterialManagerExternal.py create mode 100644 src/Mod/Material/App/MaterialAPI/__init__.py diff --git a/src/Mod/Material/App/CMakeLists.txt b/src/Mod/Material/App/CMakeLists.txt index 825242fce7..bc976d7293 100644 --- a/src/Mod/Material/App/CMakeLists.txt +++ b/src/Mod/Material/App/CMakeLists.txt @@ -6,6 +6,10 @@ endif(MSVC) add_definitions(-DYAML_CPP_STATIC_DEFINE) +if(BUILD_MATERIAL_EXTERNAL) + add_definitions(-DBUILD_MATERIAL_EXTERNAL) +endif(BUILD_MATERIAL_EXTERNAL) + include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/src @@ -55,6 +59,11 @@ generate_from_py(MaterialProperty) generate_from_py(Model) generate_from_py(UUIDs) +SET(MaterialsAPI_Files + MaterialAPI/__init__.py + MaterialAPI/MaterialManagerExternal.py +) + SET(Python_SRCS Exceptions.h Array2D.pyi @@ -126,6 +135,12 @@ SET(Materials_SRCS PyVariants.h trim.h ) +if(BUILD_MATERIAL_EXTERNAL) + list(APPEND Materials_SRCS + ExternalManager.cpp + ExternalManager.h + ) +endif(BUILD_MATERIAL_EXTERNAL) if(FREECAD_USE_PCH) add_definitions(-D_PreComp_) @@ -143,3 +158,14 @@ SET_BIN_DIR(Materials Materials /Mod/Material) SET_PYTHON_PREFIX_SUFFIX(Materials) INSTALL(TARGETS Materials DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +ADD_CUSTOM_TARGET(MaterialsAPILib ALL + SOURCES ${MaterialsAPI_Files} ${Material_QRC_SRCS} +) + +fc_target_copy_resource(MaterialsAPILib + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR}/Mod/Material + ${MaterialsAPI_Files}) + +INSTALL(FILES ${MaterialsAPI_Files} DESTINATION Mod/Material/MaterialAPI) diff --git a/src/Mod/Material/App/ExternalManager.cpp b/src/Mod/Material/App/ExternalManager.cpp new file mode 100644 index 0000000000..249e049234 --- /dev/null +++ b/src/Mod/Material/App/ExternalManager.cpp @@ -0,0 +1,788 @@ +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include "Exceptions.h" +#include "ExternalManager.h" +#include "MaterialLibrary.h" +#include "MaterialLibraryPy.h" +#include "MaterialPy.h" +#include "ModelLibrary.h" +#include "ModelPy.h" +#include "MaterialFilterPy.h" +#include "MaterialFilterOptionsPy.h" + + +using namespace Materials; + +/* TRANSLATOR Material::Materials */ + +ExternalManager* ExternalManager::_manager = nullptr; +QMutex ExternalManager::_mutex; + +ExternalManager::ExternalManager() + : _instantiated(false) +{ + _hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface"); + _hGrp->Attach(this); + + getConfiguration(); +} + +ExternalManager::~ExternalManager() +{ + _hGrp->Detach(this); +} + +void ExternalManager::OnChange(ParameterGrp::SubjectType& rCaller, ParameterGrp::MessageType Reason) +{ + const ParameterGrp& rGrp = static_cast(rCaller); + if (std::strncmp(Reason, "Current", 7) == 0) { + if (_instantiated) { + // The old manager object will be deleted when reconnecting + _instantiated = false; + } + getConfiguration(); + } +} + +void ExternalManager::getConfiguration() +{ + // _hGrp = App::GetApplication().GetParameterGroupByPath( + // "User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface"); + auto current = _hGrp->GetASCII("Current", "None"); + if (current == "None") { + _moduleName = ""; + _className = ""; + } + else { + auto groupName = + "User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface/Interfaces/" + + current; + auto hGrp = App::GetApplication().GetParameterGroupByPath(groupName.c_str()); + _moduleName = hGrp->GetASCII("Module", ""); + _className = hGrp->GetASCII("Class", ""); + } +} + +void ExternalManager::instantiate() +{ + _instantiated = false; + Base::Console().Log("Loading external manager...\n"); + + if (_moduleName.empty() || _className.empty()) { + Base::Console().Log("External module not defined\n"); + return; + } + + try { + Base::PyGILStateLocker lock; + Py::Module mod(PyImport_ImportModule(_moduleName.c_str()), true); + + if (mod.isNull()) { + Base::Console().Log(" failed\n"); + return; + } + + Py::Callable managerClass(mod.getAttr(_className)); + _managerObject = managerClass.apply(); + if (_managerObject.hasAttr("APIVersion")) { + _instantiated = true; + } + + if (_instantiated) { + Base::Console().Log("done\n"); + } + else { + Base::Console().Log("failed\n"); + } + } + catch (Py::Exception& e) { + Base::Console().Log("failed\n"); + e.clear(); + } +} + +void ExternalManager::connect() +{ + if (!_instantiated) { + instantiate(); + + if (!_instantiated) { + throw ConnectionError(); + } + } +} + +void ExternalManager::initManager() +{ + QMutexLocker locker(&_mutex); + + if (!_manager) { + _manager = new ExternalManager(); + } +} + +ExternalManager* ExternalManager::getManager() +{ + initManager(); + + return _manager; +} + +//===== +// +// Library management +// +//===== + +std::shared_ptr +ExternalManager::libraryFromTuple(const Py::Tuple& entry) +{ + auto pyName = entry.getItem(0); + QString libraryName; + if (!pyName.isNone()) { + libraryName = QString::fromStdString(pyName.as_string()); + } + auto pyIcon = entry.getItem(1); + QString icon; + if (!pyIcon.isNone()) { + icon = QString::fromStdString(pyIcon.as_string()); + } + auto pyReadOnly = entry.getItem(2); + bool readOnly = pyReadOnly.as_bool(); + auto pyTimestamp = entry.getItem(3); + QString timestamp; + if (!pyTimestamp.isNone()) { + timestamp = QString::fromStdString(pyTimestamp.as_string()); + } + + Base::Console().Log("Library name '%s', Icon '%s', readOnly %s, timestamp '%s'\n", + libraryName.toStdString().c_str(), + icon.toStdString().c_str(), + readOnly ? "true" : "false", + timestamp.toStdString().c_str()); + auto library = std::make_shared(libraryName, icon, readOnly, timestamp); + return library; +} + +std::shared_ptr>> +ExternalManager::libraries() +{ + auto libList = std::make_shared>>(); + + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("libraries")) { + Py::Callable libraries(_managerObject.getAttr("libraries")); + Py::List list(libraries.apply()); + for (auto lib : list) { + auto library = libraryFromTuple(Py::Tuple(lib)); + libList->push_back(library); + } + } + else { + Base::Console().Log("\tlibraries() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw LibraryNotFound(e1.what()); + } + + return libList; +} + +std::shared_ptr>> ExternalManager::modelLibraries() +{ + auto libList = std::make_shared>>(); + + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("modelLibraries")) { + Py::Callable libraries(_managerObject.getAttr("modelLibraries")); + Py::List list(libraries.apply()); + for (auto lib : list) { + auto library = libraryFromTuple(Py::Tuple(lib)); + libList->push_back(library); + } + } + else { + Base::Console().Log("\tmodelLibraries() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw LibraryNotFound(e1.what()); + } + + return libList; +} + +std::shared_ptr>> ExternalManager::materialLibraries() +{ + auto libList = std::make_shared>>(); + + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("materialLibraries")) { + Py::Callable libraries(_managerObject.getAttr("materialLibraries")); + Py::List list(libraries.apply()); + for (auto lib : list) { + auto library = libraryFromTuple(Py::Tuple(lib)); + libList->push_back(library); + } + } + else { + Base::Console().Log("\tmaterialLibraries() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw LibraryNotFound(e1.what()); + } + + return libList; +} + +std::shared_ptr ExternalManager::getLibrary(const QString& name) +{ + // throw LibraryNotFound("Not yet implemented"); + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("getLibrary")) { + Py::Callable libraries(_managerObject.getAttr("getLibrary")); + Py::Tuple args(1); + args.setItem(0, Py::String(name.toStdString())); + Py::Tuple result(libraries.apply(args)); + + Py::Object libObject = result.getItem(0); + auto lib = libraryFromTuple(Py::Tuple(libObject)); + return std::make_shared(*lib); + } + else { + Base::Console().Log("\tgetLibrary() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw CreationError(e1.what()); + } +} + +void ExternalManager::createLibrary(const QString& libraryName, const QString& icon, bool readOnly) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("createLibrary")) { + Py::Callable libraries(_managerObject.getAttr("createLibrary")); + Py::Tuple args(3); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(icon.toStdString())); + args.setItem(2, Py::Boolean(readOnly)); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\tcreateLibrary() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw CreationError(e1.what()); + } +} + +void ExternalManager::renameLibrary(const QString& libraryName, const QString& newName) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("renameLibrary")) { + Py::Callable libraries(_managerObject.getAttr("renameLibrary")); + Py::Tuple args(2); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(newName.toStdString())); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\trenameLibrary() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw RenameError(e1.what()); + } +} + +void ExternalManager::changeIcon(const QString& libraryName, const QString& icon) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("changeIcon")) { + Py::Callable libraries(_managerObject.getAttr("changeIcon")); + Py::Tuple args(2); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(icon.toStdString())); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\tchangeIcon() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw ReplacementError(e1.what()); + } +} + +void ExternalManager::removeLibrary(const QString& libraryName) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("removeLibrary")) { + Py::Callable libraries(_managerObject.getAttr("removeLibrary")); + Py::Tuple args(1); + args.setItem(0, Py::String(libraryName.toStdString())); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\tremoveLibrary() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw DeleteError(e1.what()); + } +} + +std::shared_ptr>> +ExternalManager::libraryModels(const QString& libraryName) +{ + auto modelList = std::make_shared>>(); + + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("libraryModels")) { + Py::Callable libraries(_managerObject.getAttr("libraryModels")); + Py::Tuple args(1); + args.setItem(0, Py::String(libraryName.toStdString())); + Py::List list(libraries.apply(args)); + for (auto library : list) { + auto entry = Py::Tuple(library); + + auto pyUUID = entry.getItem(0); + QString uuid; + if (!pyUUID.isNone()) { + uuid = QString::fromStdString(pyUUID.as_string()); + } + auto pyPath = entry.getItem(1); + QString path; + if (!pyPath.isNone()) { + path = QString::fromStdString(pyPath.as_string()); + } + auto pyName = entry.getItem(2); + QString name; + if (!pyName.isNone()) { + name = QString::fromStdString(pyName.as_string()); + } + + modelList->push_back(std::tuple(uuid, path, name)); + } + } + else { + Base::Console().Log("\tlibraryModels() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw LibraryNotFound(e1.what()); + } + + return modelList; +} + +std::shared_ptr>> +ExternalManager::libraryMaterials(const QString& libraryName) +{ + auto materialList = std::make_shared>>(); + + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("libraryMaterials")) { + Py::Callable libraries(_managerObject.getAttr("libraryMaterials")); + Py::Tuple args(1); + args.setItem(0, Py::String(libraryName.toStdString())); + Py::List list(libraries.apply(args)); + for (auto library : list) { + auto entry = Py::Tuple(library); + + auto pyUUID = entry.getItem(0); + QString uuid; + if (!pyUUID.isNone()) { + uuid = QString::fromStdString(pyUUID.as_string()); + } + auto pyPath = entry.getItem(1); + QString path; + if (!pyPath.isNone()) { + path = QString::fromStdString(pyPath.as_string()); + } + auto pyName = entry.getItem(2); + QString name; + if (!pyName.isNone()) { + name = QString::fromStdString(pyName.as_string()); + } + + materialList->push_back(std::tuple(uuid, path, name)); + } + } + else { + Base::Console().Log("\tlibraryMaterials() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw LibraryNotFound(e1.what()); + } + + return materialList; +} + +std::shared_ptr>> +ExternalManager::libraryMaterials(const QString& libraryName, + const std::shared_ptr& filter, + const MaterialFilterOptions& options) +{ + auto materialList = std::make_shared>>(); + + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("libraryMaterials")) { + Py::Callable libraries(_managerObject.getAttr("libraryMaterials")); + Py::Tuple args(3); + args.setItem(0, Py::String(libraryName.toStdString())); + if (filter) { + args.setItem(1, + Py::Object(new MaterialFilterPy(new MaterialFilter(*filter)), true)); + } + else { + args.setItem(1, Py::None()); + } + args.setItem( + 2, + Py::Object(new MaterialFilterOptionsPy(new MaterialFilterOptions(options)), true)); + Py::List list(libraries.apply(args)); + for (auto library : list) { + auto entry = Py::Tuple(library); + + auto pyUUID = entry.getItem(0); + QString uuid; + if (!pyUUID.isNone()) { + uuid = QString::fromStdString(pyUUID.as_string()); + } + auto pyPath = entry.getItem(1); + QString path; + if (!pyPath.isNone()) { + path = QString::fromStdString(pyPath.as_string()); + } + auto pyName = entry.getItem(2); + QString name; + if (!pyName.isNone()) { + name = QString::fromStdString(pyName.as_string()); + } + + materialList->push_back(std::tuple(uuid, path, name)); + } + } + else { + Base::Console().Log("\tlibraryMaterials() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw LibraryNotFound(e1.what()); + } + + return materialList; +} + +//===== +// +// Model management +// +//===== + +std::shared_ptr ExternalManager::getModel(const QString& uuid) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("getModel")) { + Py::Callable libraries(_managerObject.getAttr("getModel")); + Py::Tuple args(1); + args.setItem(0, Py::String(uuid.toStdString())); + Py::Tuple result(libraries.apply(args)); // ignore return for now + + Py::Object uuidObject = result.getItem(0); + Py::Tuple libraryObject(result.getItem(1)); + Py::Object modelObject = result.getItem(2); + + Py::Object pyName = libraryObject.getItem(0); + Py::Object pyIcon = libraryObject.getItem(1); + Py::Object readOnly = libraryObject.getItem(2); + + QString name; + if (!pyName.isNone()) { + name = QString::fromStdString(pyName.as_string()); + } + QString icon; + if (!pyIcon.isNone()) { + icon = QString::fromStdString(pyIcon.as_string()); + } + auto library = + std::make_shared(name, QString(), icon, readOnly.as_bool()); + + Model* model = static_cast(*modelObject)->getModelPtr(); + model->setUUID(uuid); + model->setLibrary(library); + auto shared = std::make_shared(*model); + + return shared; + } + else { + Base::Console().Log("\tgetModel() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw ModelNotFound(e1.what()); + } +} + +void ExternalManager::addModel(const QString& libraryName, + const QString& path, + const std::shared_ptr& model) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("addModel")) { + Py::Callable libraries(_managerObject.getAttr("addModel")); + Py::Tuple args(3); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(path.toStdString())); + args.setItem(2, Py::Object(new ModelPy(new Model(*model)), true)); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\taddModel() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw CreationError(e1.what()); + } +} + +void ExternalManager::migrateModel(const QString& libraryName, + const QString& path, + const std::shared_ptr& model) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("migrateModel")) { + Py::Callable libraries(_managerObject.getAttr("migrateModel")); + Py::Tuple args(3); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(path.toStdString())); + args.setItem(2, Py::Object(new ModelPy(new Model(*model)), true)); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\tmigrateModel() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw CreationError(e1.what()); + } +} + +//===== +// +// Material management +// +//===== + +std::shared_ptr ExternalManager::getMaterial(const QString& uuid) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("getMaterial")) { + Py::Callable libraries(_managerObject.getAttr("getMaterial")); + Py::Tuple args(1); + args.setItem(0, Py::String(uuid.toStdString())); + Py::Tuple result(libraries.apply(args)); + + Py::Object uuidObject = result.getItem(0); + Py::Tuple libraryObject(result.getItem(1)); + Py::Object materialObject = result.getItem(2); + + Py::Object pyName = libraryObject.getItem(0); + Py::Object pyIcon = libraryObject.getItem(1); + Py::Object readOnly = libraryObject.getItem(2); + + QString name; + if (!pyName.isNone()) { + name = QString::fromStdString(pyName.as_string()); + } + QString icon; + if (!pyIcon.isNone()) { + icon = QString::fromStdString(pyIcon.as_string()); + } + auto library = + std::make_shared(name, QString(), icon, readOnly.as_bool()); + + Material* material = static_cast(*materialObject)->getMaterialPtr(); + material->setUUID(uuid); + material->setLibrary(library); + auto shared = std::make_shared(*material); + + return shared; + } + else { + Base::Console().Log("\tgetMaterial() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw MaterialNotFound(e1.what()); + } +} + +void ExternalManager::addMaterial(const QString& libraryName, + const QString& path, + const std::shared_ptr& material) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("addMaterial")) { + Py::Callable libraries(_managerObject.getAttr("addMaterial")); + Py::Tuple args(3); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(path.toStdString())); + args.setItem(2, Py::Object(new MaterialPy(new Material(*material)), true)); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\taddMaterial() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw CreationError(e1.what()); + } +} + +void ExternalManager::migrateMaterial(const QString& libraryName, + const QString& path, + const std::shared_ptr& material) +{ + connect(); + + Base::PyGILStateLocker lock; + try { + if (_managerObject.hasAttr("migrateMaterial")) { + Py::Callable libraries(_managerObject.getAttr("migrateMaterial")); + Py::Tuple args(3); + args.setItem(0, Py::String(libraryName.toStdString())); + args.setItem(1, Py::String(path.toStdString())); + auto mat = new Material(*material); + args.setItem(2, Py::Object(new MaterialPy(mat), true)); + libraries.apply(args); // No return expected + } + else { + Base::Console().Log("\tmigrateMaterial() not found\n"); + throw ConnectionError(); + } + } + catch (Py::Exception& e) { + Base::PyException e1; // extract the Python error text + throw CreationError(e1.what()); + } +} diff --git a/src/Mod/Material/App/ExternalManager.h b/src/Mod/Material/App/ExternalManager.h new file mode 100644 index 0000000000..56c4ae2a62 --- /dev/null +++ b/src/Mod/Material/App/ExternalManager.h @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef MATERIAL_EXTERNALMANAGER_H +#define MATERIAL_EXTERNALMANAGER_H + +#include +#include + +#include + +class QMutex; + +namespace Materials +{ + +class Library; +class Material; +class Model; +class MaterialFilter; +class MaterialFilterOptions; + +class MaterialsExport ExternalManager: public ParameterGrp::ObserverType +{ +public: + + static ExternalManager* getManager(); + + /// Observer message from the ParameterGrp + void OnChange(ParameterGrp::SubjectType& rCaller, ParameterGrp::MessageType Reason) override; + + // Library management + std::shared_ptr>> libraries(); + std::shared_ptr>> modelLibraries(); + std::shared_ptr>> materialLibraries(); + std::shared_ptr getLibrary(const QString& name); + void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true); + void renameLibrary(const QString& libraryName, const QString& newName); + void changeIcon(const QString& libraryName, const QString& icon); + void removeLibrary(const QString& libraryName); + std::shared_ptr>> + libraryModels(const QString& libraryName); + std::shared_ptr>> + libraryMaterials(const QString& libraryName); + std::shared_ptr>> + libraryMaterials(const QString& libraryName, + const std::shared_ptr& filter, + const MaterialFilterOptions& options); + + // Model management + std::shared_ptr getModel(const QString& uuid); + void + addModel(const QString& libraryName, const QString& path, const std::shared_ptr& model); + void + migrateModel(const QString& libraryName, const QString& path, const std::shared_ptr& model); + + // Material management + std::shared_ptr getMaterial(const QString& uuid); + void addMaterial(const QString& libraryName, + const QString& path, + const std::shared_ptr& material); + void migrateMaterial(const QString& libraryName, + const QString& path, + const std::shared_ptr& material); + +private: + ExternalManager(); + ~ExternalManager(); + + static void initManager(); + void getConfiguration(); + void instantiate(); + void connect(); + std::shared_ptr libraryFromTuple(const Py::Tuple& entry); + + static ExternalManager* _manager; + static QMutex _mutex; + + // COnfiguration + ParameterGrp::handle _hGrp; + std::string _moduleName; + std::string _className; + bool _instantiated; + + Py::Object _managerObject; +}; + +} // namespace Materials + +#endif // MATERIAL_EXTERNALMANAGER_H \ No newline at end of file diff --git a/src/Mod/Material/App/Library.cpp b/src/Mod/Material/App/Library.cpp index 57bbd50480..7e87310375 100644 --- a/src/Mod/Material/App/Library.cpp +++ b/src/Mod/Material/App/Library.cpp @@ -40,6 +40,16 @@ Library::Library(const QString& libraryName, const QString& icon, bool readOnly) , _readOnly(readOnly) {} +Library::Library(const QString& libraryName, + const QString& icon, + bool readOnly, + const QString& timestamp) + : _name(libraryName) + , _iconPath(icon) + , _readOnly(readOnly) + , _timestamp(timestamp) +{} + Library::Library(const QString& libraryName, const QString& dir, const QString& icon, bool readOnly) : _name(libraryName) , _directory(QDir::cleanPath(dir)) diff --git a/src/Mod/Material/App/Library.h b/src/Mod/Material/App/Library.h index b2249a91a8..5d773218d5 100644 --- a/src/Mod/Material/App/Library.h +++ b/src/Mod/Material/App/Library.h @@ -39,6 +39,10 @@ class MaterialsExport Library: public Base::BaseClass public: Library() = default; Library(const QString& libraryName, const QString& icon, bool readOnly = true); + Library(const QString& libraryName, + const QString& icon, + bool readOnly, + const QString& timestamp); Library(const QString& libraryName, const QString& dir, const QString& icon, @@ -53,7 +57,7 @@ public: { _name = newName; } - bool sameName(const QString& name) + bool isName(const QString& name) { return (_name == name); } @@ -87,6 +91,14 @@ public: { return QDir(_directory).absolutePath(); } + QString getTimestamp() const + { + return _timestamp; + } + void setTimestamp(const QString& timestamp) + { + _timestamp = timestamp; + } bool operator==(const Library& library) const; bool operator!=(const Library& library) const @@ -107,6 +119,7 @@ private: QString _directory; QString _iconPath; bool _readOnly; + QString _timestamp; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialAPI/MaterialManagerExternal.py b/src/Mod/Material/App/MaterialAPI/MaterialManagerExternal.py new file mode 100644 index 0000000000..2f9db88722 --- /dev/null +++ b/src/Mod/Material/App/MaterialAPI/MaterialManagerExternal.py @@ -0,0 +1,246 @@ +# *************************************************************************** +# * Copyright (c) 2024 David Carter * +# * * +# * 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 * +# * * +# *************************************************************************** + +__author__ = "David Carter" +__url__ = "https://www.davesrocketshop.com" + +from abc import ABC, abstractmethod +# from typing import Tuple + +import Materials + +# This requires Python 3.12 or later. This isn't available on all platforms yet +# type MaterialName = str +# type MaterialIcon = str +# type MaterialReadOnly = bool +# type MaterialTimestamp = str +# type MaterialUUID = str +# type MaterialPath = str +# type MaterialLibraryType = Tuple[MaterialName, MaterialIcon, MaterialReadOnly, MaterialTimestamp] +# type MaterialLibraryObjectType = Tuple[MaterialUUID, MaterialPath, MaterialName] + +class MaterialManagerExternal(ABC): + """Abstract base class for all external material managers + + Any external interface should be derivedfrom this base class.""" + + @classmethod + def APIVersion(cls) -> tuple: + """Returns a tuple of 3 integers describing the API version + + The version returned should be the latest supported version. This method + allows the interface to use older modules.""" + return (1, 0, 0) + + # + # Library methods + # + + @abstractmethod + def libraries(self) -> list: #[MaterialLibraryType]: + """Returns a list of libraries managed by this interface + + The list contains a series of tuples describing all libraries managed by + this module. Each tuple containes the library name, icon, a boolean to indicate + if it is a read only library, and a timestamp that indicates when it was last + modified.""" + pass + + @abstractmethod + def modelLibraries(self) -> list: #[MaterialLibraryType]: + """Returns a list of libraries managed by this interface + + The list contains a series of tuples describing all libraries managed by + this module. Each tuple containes the library name, icon, and a boolean to indicate + if it is a read only library, and a timestamp that indicates when it was last + modified. + + This differs from the libraries() function in that it only returns libraries + containing model objects.""" + pass + + @abstractmethod + def materialLibraries(self) -> list: #[MaterialLibraryType]: + """Returns a list of libraries managed by this interface + + The list contains a series of tuples describing all libraries managed by + this module. Each tuple containes the library name, icon, and a boolean to indicate + if it is a read only library, and a timestamp that indicates when it was last + modified. + + This differs from the libraries() function in that it only returns libraries + containing material objects.""" + pass + + @abstractmethod + def getLibrary(self, name: str) -> tuple: + """Get the library + + Retrieve the library with the given name""" + pass + + @abstractmethod + def createLibrary(self, name: str, icon: str, readOnly: bool) -> None: + """Create a new library + + Create a new library with the given name""" + pass + + @abstractmethod + def renameLibrary(self, oldName: str, newName: str) -> None: + """Rename an existing library + + Change the name of an existing library""" + pass + + @abstractmethod + def changeIcon(self, name: str, icon: str) -> None: + """Change the library icon + + Change the library icon""" + pass + + @abstractmethod + def removeLibrary(self, library: str) -> None: + """Delete a library and its contents + + Deletes the library and any models or materials it contains""" + pass + + @abstractmethod + def libraryModels(self, library: str) -> list: #[MaterialLibraryObjectType]: + """Returns a list of models managed by this library + + Each list entry is a tuple containing the UUID, path, and name of the model""" + pass + + @abstractmethod + def libraryMaterials(self, library: str, + filter: Materials.MaterialFilter = None, + options: Materials.MaterialFilterOptions = None) -> list: #[MaterialLibraryObjectType]: + """Returns a list of materials managed by this library + + Each list entry is a tuple containing the UUID, path, and name of the material""" + pass + + # + # Model methods + # + + @abstractmethod + def getModel(self, uuid: str) -> Materials.Model: + """Retrieve a model given its UUID""" + pass + + @abstractmethod + def addModel(self, library: str, path: str, model: Materials.Model) -> None: + """Add a model to a library in the given folder. + + This will throw a DatabaseModelExistsError exception if the model already exists.""" + pass + + @abstractmethod + def migrateModel(self, library: str, path: str, model: Materials.Model) -> None: + """Add the model to the library. + + If the model already exists, then no action is performed.""" + pass + + @abstractmethod + def updateModel(self, library: str, path: str, model: Materials.Model) -> None: + """Update the given model""" + pass + + @abstractmethod + def setModelPath(self, library: str, path: str, model: Materials.Model) -> None: + """Change the model path within the library""" + pass + + @abstractmethod + def renameModel(self, library: str, name: str, model: Materials.Model) -> None: + """Change the model name""" + pass + + @abstractmethod + def moveModel(self, library: str, path: str, model: Materials.Model) -> None: + """Move a model across libraries + + Move the model to the desired path in a different library. This should also + remove the model from the old library if that library is managed by this + interface""" + pass + + @abstractmethod + def removeModel(self, model: Materials.Model) -> None: + """Remove the model from the library""" + pass + + # + # Material methods + # + + @abstractmethod + def getMaterial(self, uuid: str) -> Materials.Material: + """ Retrieve a material given its UUID """ + pass + + @abstractmethod + def addMaterial(self, library: str, path: str, material: Materials.Material) -> None: + """Add a material to a library in the given folder. + + This will throw a DatabaseMaterialExistsError exception if the model already exists.""" + pass + + @abstractmethod + def migrateMaterial(self, library: str, path: str, material: Materials.Material) -> None: + """Add the material to the library in the given folder. + + If the material already exists, then no action is performed.""" + pass + + @abstractmethod + def updateMaterial(self, library: str, path: str, material: Materials.Material) -> None: + """Update the given material""" + pass + + @abstractmethod + def setMaterialPath(self, library: str, path: str, material: Materials.Material) -> None: + """Change the material path within the library""" + pass + + @abstractmethod + def renameMaterial(self, library: str, name: str, material: Materials.Material) -> None: + """Change the material name""" + pass + + @abstractmethod + def moveMaterial(self, library: str, path: str, material: Materials.Material) -> None: + """Move a material across libraries + + Move the material to the desired path in a different library. This should also + remove the material from the old library if that library is managed by this + interface""" + pass + + @abstractmethod + def removeMaterial(self, material: Materials.Material) -> None: + """Remove the material from the library""" + pass diff --git a/src/Mod/Material/App/MaterialAPI/__init__.py b/src/Mod/Material/App/MaterialAPI/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Material/App/MaterialManagerLocal.cpp b/src/Mod/Material/App/MaterialManagerLocal.cpp index 42b3daabe1..7db46b2bad 100644 --- a/src/Mod/Material/App/MaterialManagerLocal.cpp +++ b/src/Mod/Material/App/MaterialManagerLocal.cpp @@ -130,7 +130,7 @@ MaterialManagerLocal::getMaterialLibraries() std::shared_ptr MaterialManagerLocal::getLibrary(const QString& name) const { for (auto& library : *_libraryList) { - if (library->isLocal() && library->sameName(name)) { + if (library->isLocal() && library->isName(name)) { return library; } } @@ -160,7 +160,7 @@ void MaterialManagerLocal::createLibrary(const QString& libraryName, void MaterialManagerLocal::renameLibrary(const QString& libraryName, const QString& newName) { for (auto& library : *_libraryList) { - if (library->isLocal() && library->sameName(libraryName)) { + if (library->isLocal() && library->isName(libraryName)) { auto materialLibrary = reinterpret_cast&>(library); materialLibrary->setName(newName); @@ -174,7 +174,7 @@ void MaterialManagerLocal::renameLibrary(const QString& libraryName, const QStri void MaterialManagerLocal::changeIcon(const QString& libraryName, const QString& icon) { for (auto& library : *_libraryList) { - if (library->isLocal() && library->sameName(libraryName)) { + if (library->isLocal() && library->isName(libraryName)) { auto materialLibrary = reinterpret_cast&>(library); materialLibrary->setIconPath(icon); @@ -188,7 +188,7 @@ void MaterialManagerLocal::changeIcon(const QString& libraryName, const QString& void MaterialManagerLocal::removeLibrary(const QString& libraryName) { for (auto& library : *_libraryList) { - if (library->isLocal() && library->sameName(libraryName)) { + if (library->isLocal() && library->isName(libraryName)) { _libraryList->remove(library); // At this point we should rebuild the material map @@ -207,7 +207,7 @@ MaterialManagerLocal::libraryMaterials(const QString& libraryName) for (auto& it : *_materialMap) { // This is needed to resolve cyclic dependencies auto library = it.second->getLibrary(); - if (library->sameName(libraryName)) { + if (library->isName(libraryName)) { materials->push_back(std::tuple(it.first, it.second->getDirectory(), it.second->getName())); @@ -245,7 +245,7 @@ MaterialManagerLocal::libraryMaterials(const QString& libraryName, for (auto& it : *_materialMap) { // This is needed to resolve cyclic dependencies auto library = it.second->getLibrary(); - if (library->sameName(libraryName)) { + if (library->isName(libraryName)) { if (passFilter(it.second, filter, options)) { materials->push_back(std::tuple(it.first, it.second->getDirectory(), From 6d376dc77aa0c3d4a678cec7d2e19c0ce3dec145 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Mon, 24 Mar 2025 01:23:15 -0300 Subject: [PATCH 113/316] Fem: Add method to rename pipeline VTK data arrays --- src/Mod/Fem/App/FemPostPipeline.cpp | 35 ++++++++++++++++++++++-- src/Mod/Fem/App/FemPostPipeline.h | 1 + src/Mod/Fem/App/FemPostPipelinePy.xml | 5 ++++ src/Mod/Fem/App/FemPostPipelinePyImp.cpp | 22 +++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index 4501fca2ca..3af7c03132 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -46,8 +47,6 @@ #endif #include -#include -#include #include "FemMesh.h" #include "FemMeshObject.h" @@ -737,6 +736,38 @@ void FemPostPipeline::onDocumentRestored() } } +void FemPostPipeline::renameArrays(const std::map& names) +{ + std::vector> fields; + auto data = Data.getValue(); + if (!data) { + return; + } + + if (auto dataSet = vtkDataSet::SafeDownCast(data)) { + fields.emplace_back(dataSet); + } + else if (auto blocks = vtkMultiBlockDataSet::SafeDownCast(data)) { + for (unsigned int i = 0; i < blocks->GetNumberOfBlocks(); ++i) { + if (auto dataSet = vtkDataSet::SafeDownCast(blocks->GetBlock(i))) { + fields.emplace_back(dataSet); + } + } + } + + for (auto f : fields) { + auto pointData = f->GetPointData(); + for (const auto& name : names) { + auto array = pointData->GetAbstractArray(name.first.c_str()); + if (array) { + array->SetName(name.second.c_str()); + } + } + } + + Data.touch(); +} + PyObject* FemPostPipeline::getPyObject() { if (PythonObject.is(Py::_None())) { diff --git a/src/Mod/Fem/App/FemPostPipeline.h b/src/Mod/Fem/App/FemPostPipeline.h index c56d37ad01..15d9149705 100644 --- a/src/Mod/Fem/App/FemPostPipeline.h +++ b/src/Mod/Fem/App/FemPostPipeline.h @@ -98,6 +98,7 @@ public: Base::Unit unit, std::string& frame_type); void scale(double s); + void renameArrays(const std::map& names); // load from results void load(FemResultObject* res); diff --git a/src/Mod/Fem/App/FemPostPipelinePy.xml b/src/Mod/Fem/App/FemPostPipelinePy.xml index 9385b805c3..c71981393b 100644 --- a/src/Mod/Fem/App/FemPostPipelinePy.xml +++ b/src/Mod/Fem/App/FemPostPipelinePy.xml @@ -66,5 +66,10 @@ Load a single result object or create a multiframe result by loading multiple re Check if this pipeline holds a given post-processing object + + + Change name of data arrays + + diff --git a/src/Mod/Fem/App/FemPostPipelinePyImp.cpp b/src/Mod/Fem/App/FemPostPipelinePyImp.cpp index f2f7d14bfb..9de89e34cb 100644 --- a/src/Mod/Fem/App/FemPostPipelinePyImp.cpp +++ b/src/Mod/Fem/App/FemPostPipelinePyImp.cpp @@ -285,6 +285,28 @@ PyObject* FemPostPipelinePy::holdsPostObject(PyObject* args) return Py_BuildValue("O", (ok ? Py_True : Py_False)); } +PyObject* FemPostPipelinePy::renameArrays(PyObject* args) +{ + PyObject* pyObj; + if (!PyArg_ParseTuple(args, "O!", &(PyDict_Type), &pyObj)) { + return nullptr; + } + + Py::Dict pyNames {pyObj}; + std::map names {}; + for (auto&& [key, value] : pyNames) { + if (!key.isString() || !value.isString()) { + PyErr_SetString(PyExc_TypeError, "Names must be string objects"); + return nullptr; + } + names.emplace(key.as_string(), static_cast(value).as_string()); + } + + getFemPostPipelinePtr()->renameArrays(names); + + Py_Return; +} + PyObject* FemPostPipelinePy::getCustomAttributes(const char* /*attr*/) const { return nullptr; From 03dd780ef32eb59f01910323e8070cefa7aae99d Mon Sep 17 00:00:00 2001 From: tringenbach Date: Tue, 1 Apr 2025 00:53:22 -0500 Subject: [PATCH 114/316] Gui: Task overlay HiDPI vertical alignment --- src/Gui/OverlayManager.cpp | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/Gui/OverlayManager.cpp b/src/Gui/OverlayManager.cpp index 41cb897bc8..d2070faf4f 100644 --- a/src/Gui/OverlayManager.cpp +++ b/src/Gui/OverlayManager.cpp @@ -615,22 +615,12 @@ public: int delta = _bottom.tabWidget->getSizeDelta(); h -= ofs.height(); - auto getCubeSize = [naviCubeSize](OverlayInfo &info) -> int { - float scale = info.tabWidget->_imageScale; - if (scale == 0.0) { - scale = info.tabWidget->titleBar->grab().devicePixelRatio(); - if (scale == 0.0) - scale = 1.0; - } - return naviCubeSize/scale + 10; - }; - - int cubeSize = getCubeSize(_bottom); + const int paddedCubeSize = naviCubeSize + 10; if(naviCorner == 2) - ofs.setWidth(ofs.width()+cubeSize); + ofs.setWidth(ofs.width()+paddedCubeSize); int bw = w-10-ofs.width()-delta; if(naviCorner == 3) - bw -= cubeSize; + bw -= paddedCubeSize; if(bw < 10) bw = 10; @@ -648,12 +638,11 @@ public: rect = _left.tabWidget->getRect(); ofs = _left.tabWidget->getOffset(); - cubeSize = getCubeSize(_left); if(naviCorner == 0) - ofs.setWidth(ofs.width()+cubeSize); + ofs.setWidth(ofs.width()+paddedCubeSize); delta = _left.tabWidget->getSizeDelta()+rectBottom.height(); - if(naviCorner == 2 && cubeSize > rectBottom.height()) - delta += cubeSize - rectBottom.height(); + if(naviCorner == 2 && paddedCubeSize > rectBottom.height()) + delta += paddedCubeSize - rectBottom.height(); int lh = std::max(h-ofs.width()-delta, 10); _left.tabWidget->setRect(QRect(ofs.height(),ofs.width(),rect.width(),lh)); @@ -667,12 +656,11 @@ public: rect = _right.tabWidget->getRect(); ofs = _right.tabWidget->getOffset(); - cubeSize = getCubeSize(_right); if(naviCorner == 1) - ofs.setWidth(ofs.width()+cubeSize); + ofs.setWidth(ofs.width()+paddedCubeSize); delta = _right.tabWidget->getSizeDelta()+rectBottom.height(); - if(naviCorner == 3 && cubeSize > rectBottom.height()) - delta += cubeSize - rectBottom.height(); + if(naviCorner == 3 && paddedCubeSize > rectBottom.height()) + delta += paddedCubeSize - rectBottom.height(); int rh = std::max(h-ofs.width()-delta, 10); w -= ofs.height(); @@ -686,12 +674,11 @@ public: rect = _top.tabWidget->getRect(); ofs = _top.tabWidget->getOffset(); - cubeSize = getCubeSize(_top); delta = _top.tabWidget->getSizeDelta(); if(naviCorner == 0) - rectLeft.setWidth(std::max(rectLeft.width(), cubeSize)); + rectLeft.setWidth(std::max(rectLeft.width(), paddedCubeSize)); else if(naviCorner == 1) - rectRight.setWidth(std::max(rectRight.width(), cubeSize)); + rectRight.setWidth(std::max(rectRight.width(), paddedCubeSize)); int tw = w-rectLeft.width()-rectRight.width()-ofs.width()-delta; _top.tabWidget->setRect(QRect(rectLeft.width()-ofs.width(),ofs.height(),tw,rect.height())); From b3d8020e7777b1f6c9dcd5ebfc10c967b3d02485 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Mon, 31 Mar 2025 23:38:11 -0500 Subject: [PATCH 115/316] CMake: Allow external libE57Format --- .../InitializeFreeCADBuildOptions.cmake | 1 + cMake/UseLibPack3.cmake | 6 ++++++ src/3rdParty/CMakeLists.txt | 5 ++++- src/Mod/Points/App/CMakeLists.txt | 17 ++++++++++++++--- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake index f329745050..dfb29f1e56 100644 --- a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake +++ b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake @@ -10,6 +10,7 @@ macro(InitializeFreeCADBuildOptions) option(FREECAD_USE_EXTERNAL_KDL "Use system installed orocos-kdl instead of the bundled." OFF) option(FREECAD_USE_EXTERNAL_FMT "Use system installed fmt library if available instead of fetching the source." ON) option(FREECAD_USE_EXTERNAL_ONDSELSOLVER "Use system installed OndselSolver instead of git submodule." OFF) + option(FREECAD_USE_EXTERNAL_E57FORMAT "Use system installed libE57Format instead of the bundled." OFF) option(FREECAD_USE_FREETYPE "Builds the features using FreeType libs" ON) option(FREECAD_BUILD_DEBIAN "Prepare for a build of a Debian package" OFF) option(FREECAD_CHECK_PIVY "Check for pivy version using Python at build time" ON) diff --git a/cMake/UseLibPack3.cmake b/cMake/UseLibPack3.cmake index e1da9548dc..f8871df5bb 100644 --- a/cMake/UseLibPack3.cmake +++ b/cMake/UseLibPack3.cmake @@ -27,6 +27,12 @@ endif() find_package(XercesC REQUIRED PATHS ${FREECAD_LIBPACK_DIR}/cmake NO_DEFAULT_PATH) message(STATUS "Found LibPack 3 XercesC ${XercesC_VERSION}") +if(FREECAD_LIBPACK_VERSION VERSION_GREATER_EQUAL "3.1.1") + set(FREECAD_USE_EXTERNAL_E57FORMAT ON) + find_package(E57Format REQUIRED PATHS ${FREECAD_LIBPACK_DIR}/lib/cmake/e57format NO_DEFAULT_PATH) + message(STATUS "Found LibPack 3 e57format ${e57format_VERSION}") +endif() + find_package(yaml-cpp REQUIRED PATHS ${FREECAD_LIBPACK_DIR}/lib/cmake NO_DEFAULT_PATH) message(STATUS "Found LibPack 3 yaml-cpp ${yaml-cpp_VERSION}") diff --git a/src/3rdParty/CMakeLists.txt b/src/3rdParty/CMakeLists.txt index 71b368b902..86619e8d81 100644 --- a/src/3rdParty/CMakeLists.txt +++ b/src/3rdParty/CMakeLists.txt @@ -4,7 +4,10 @@ if (BUILD_SMESH) endif() add_subdirectory(lazy_loader) -add_subdirectory(libE57Format) + +if(NOT FREECAD_USE_EXTERNAL_E57FORMAT) + add_subdirectory(libE57Format) +endif() if (BUILD_ASSEMBLY AND NOT FREECAD_USE_EXTERNAL_ONDSELSOLVER) if( NOT EXISTS "${CMAKE_SOURCE_DIR}/src/3rdParty/OndselSolver/CMakeLists.txt" ) diff --git a/src/Mod/Points/App/CMakeLists.txt b/src/Mod/Points/App/CMakeLists.txt index fee35a31fa..740b4b3f93 100644 --- a/src/Mod/Points/App/CMakeLists.txt +++ b/src/Mod/Points/App/CMakeLists.txt @@ -14,10 +14,18 @@ target_include_directories( SYSTEM PUBLIC ${EIGEN3_INCLUDE_DIR} - ${CMAKE_BINARY_DIR}/src/3rdParty/libE57Format - ${CMAKE_SOURCE_DIR}/src/3rdParty/libE57Format/include ) +if (NOT FREECAD_USE_EXTERNAL_E57FORMAT) + target_include_directories( + Points + SYSTEM + PUBLIC + ${CMAKE_BINARY_DIR}/src/3rdParty/libE57Format + ${CMAKE_SOURCE_DIR}/src/3rdParty/libE57Format/include + ) +endif() + set(Points_LIBS FreeCADApp ) @@ -67,7 +75,10 @@ if(FREECAD_USE_PCH) endif(FREECAD_USE_PCH) target_sources(Points PRIVATE ${Points_SRCS} ${Points_Scripts}) -link_directories(${CMAKE_BINARY_DIR}/src/3rdParty/libE57Format) + +if (NOT FREECAD_USE_EXTERNAL_E57FORMAT) + link_directories(${CMAKE_BINARY_DIR}/src/3rdParty/libE57Format) +endif() target_link_libraries(Points E57Format ${Points_LIBS}) if (FREECAD_WARN_ERROR) From bad0daf9dc346e9d59c0cf715afc1b67cd9d86d4 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Tue, 1 Apr 2025 08:02:42 +0200 Subject: [PATCH 116/316] Refactor mapToInt/mapToUint --- src/Gui/SpinBox.cpp | 38 +++++++++++--------- src/Tools/plugins/widget/customwidgets.cpp | 40 ++++++++++++---------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index d25b0a201c..bc26dc7658 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -292,34 +292,40 @@ public: UnsignedValidator * mValidator{nullptr}; UIntSpinBoxPrivate() = default; - uint mapToUInt( int v ) const + unsigned mapToUInt( int v ) const { - uint ui; - if ( v == std::numeric_limits::min() ) { + using int_limits = std::numeric_limits; + using uint_limits = std::numeric_limits; + + unsigned ui; + if ( v == int_limits::min() ) { ui = 0; - } else if ( v == std::numeric_limits::max() ) { - ui = std::numeric_limits::max(); + } else if ( v == int_limits::max() ) { + ui = uint_limits::max(); } else if ( v < 0 ) { - v -= std::numeric_limits::min(); - ui = static_cast(v); + v -= int_limits::min(); + ui = static_cast(v); } else { - ui = static_cast(v); - ui -= std::numeric_limits::min(); + ui = static_cast(v); + ui -= int_limits::min(); } return ui; } - int mapToInt( uint v ) const + int mapToInt( unsigned v ) const { + using int_limits = std::numeric_limits; + using uint_limits = std::numeric_limits; + int in; - if ( v == std::numeric_limits::max() ) { - in = std::numeric_limits::max(); + if ( v == uint_limits::max() ) { + in = int_limits::max(); } else if ( v == 0 ) { - in = std::numeric_limits::min(); - } else if ( v > std::numeric_limits::max() ) { - v += std::numeric_limits::min(); + in = int_limits::min(); + } else if ( v > int_limits::max() ) { + v += int_limits::min(); in = static_cast(v); } else { in = v; - in += std::numeric_limits::min(); + in += int_limits::min(); } return in; } }; diff --git a/src/Tools/plugins/widget/customwidgets.cpp b/src/Tools/plugins/widget/customwidgets.cpp index 9444ae48b4..79836644b2 100644 --- a/src/Tools/plugins/widget/customwidgets.cpp +++ b/src/Tools/plugins/widget/customwidgets.cpp @@ -1520,43 +1520,47 @@ public: UIntSpinBoxPrivate() : mValidator(0) {} - uint mapToUInt(int v) const + unsigned mapToUInt(int v) const { - using limits = std::numeric_limits; - uint ui; - if (v == limits::min()) { + using int_limits = std::numeric_limits; + using uint_limits = std::numeric_limits; + + unsigned ui; + if (v == int_limits::min()) { ui = 0; } - else if (v == limits::max()) { - ui = limits::max(); + else if (v == int_limits::max()) { + ui = uint_limits::max(); } else if (v < 0) { - v -= limits::min(); - ui = static_cast(v); + v -= int_limits::min(); + ui = static_cast(v); } else { - ui = static_cast(v); - ui -= limits::min(); + ui = static_cast(v); + ui -= int_limits::min(); } return ui; } - int mapToInt(uint v) const + int mapToInt(unsigned v) const { - using limits = std::numeric_limits; + using int_limits = std::numeric_limits; + using uint_limits = std::numeric_limits; + int in; - if (v == limits::max()) { - in = limits::max(); + if (v == uint_limits::max()) { + in = int_limits::max(); } else if (v == 0) { - in = limits::min(); + in = int_limits::min(); } - else if (v > limits::max()) { - v += limits::min(); + else if (v > int_limits::max()) { + v += int_limits::min(); in = static_cast(v); } else { in = v; - in += limits::min(); + in += int_limits::min(); } return in; } From 4bbc59d3094a109b7fa8945375f98725675e841f Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Tue, 1 Apr 2025 10:32:18 +0200 Subject: [PATCH 117/316] [Core] Make PropertyItem column usage more clear - Renamed dataProperty -> dataPropertyName because the function returns variants for the property name. - Add an enum for the column to remove magic numbers --- src/Gui/propertyeditor/PropertyItem.cpp | 9 ++++----- src/Gui/propertyeditor/PropertyItem.h | 8 +++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 94bbd659f7..e7852c02a2 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -295,7 +295,7 @@ int PropertyItem::childCount() const int PropertyItem::columnCount() const { - return 2; + return PropertyItem::ColumnCount; } void PropertyItem::setReadOnly(bool ro) @@ -649,7 +649,7 @@ void PropertyItem::setPropertyValue(const QString& value) setPropertyValue(value.toStdString()); } -QVariant PropertyItem::dataProperty(int role) const +QVariant PropertyItem::dataPropertyName(int role) const { if (role == Qt::ForegroundRole && linked) { return QVariant::fromValue(QColor(0x20, 0xaa, 0x20)); // NOLINT @@ -742,9 +742,8 @@ QVariant PropertyItem::dataValue(int role) const QVariant PropertyItem::data(int column, int role) const { - // property name - if (column == 0) { - return dataProperty(role); + if (column == PropertyItem::NameColumn) { + return dataPropertyName(role); } return dataValue(role); diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index b8182c4fd8..cfdcc21a1b 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -130,6 +130,12 @@ class GuiExport PropertyItem: public QObject, public ExpressionBinding PROPERTYITEM_HEADER public: + enum Column { + NameColumn = 0, + ValueColumn = 1, + ColumnCount + }; + ~PropertyItem() override; /** Sets the current property objects. */ @@ -216,7 +222,7 @@ protected: void onChange() override; private: - QVariant dataProperty(int role) const; + QVariant dataPropertyName(int role) const; QVariant dataValue(int role) const; QString toString(const Py::Object&) const; QString asNone(const Py::Object&) const; From 84468fbc25bdf1272fb68d98f7e2b28b1dffa4a8 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Tue, 1 Apr 2025 10:34:19 +0200 Subject: [PATCH 118/316] [Core] Show units in value editor VarSet dialog Before this change, the units were not shown in the editor for values. With this change the units (if applicable) are shown in the editor. --- src/Gui/Dialogs/DlgAddPropertyVarSet.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp b/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp index 1b505e7365..a974ac4fdf 100644 --- a/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp +++ b/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp @@ -251,7 +251,9 @@ void DlgAddPropertyVarSet::addEditor(PropertyEditor::PropertyItem* propertyItem, editor.reset(propertyItem->createEditor(this, [this]() { this->valueChanged(); })); - propertyItem->setEditorData(editor.get(), QVariant()); + propertyItem->setEditorData( + editor.get(), + propertyItem->data(PropertyEditor::PropertyItem::ValueColumn, Qt::EditRole)); editor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); editor->setObjectName(QStringLiteral("editor")); auto formLayout = qobject_cast(layout()); From efcd78777759eb63224dae7a51352026fe5652df Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Tue, 1 Apr 2025 12:25:44 +0200 Subject: [PATCH 119/316] [Core] Fix value field unit selection Qt automatically selects the text in the value field on creation. This interferes with the selection when the field has focus. This commit ensures that the automatic selection is undone. --- src/Gui/Dialogs/DlgAddPropertyVarSet.cpp | 17 ++++++++++++++++- src/Gui/Dialogs/DlgAddPropertyVarSet.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp b/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp index a974ac4fdf..6a654898bf 100644 --- a/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp +++ b/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp @@ -153,7 +153,7 @@ static void printFocusChain(QWidget *widget) { QWidget* start = widget; int i = 0; do { - FC_ERR(" " << widget->objectName().toStdString(); + FC_ERR(" " << widget->objectName().toStdString()); widget = widget->nextInFocusChain(); i++; } while (widget != nullptr && i < 30 && start != widget); @@ -245,12 +245,24 @@ static PropertyEditor::PropertyItem *createPropertyItem(App::Property *prop) return item; } +void DlgAddPropertyVarSet::removeSelectionEditor() +{ + // If the editor has a lineedit, then Qt selects the string inside it when + // the editor is created. This interferes with the editor getting focus. + // For example, units will then be selected as well, whereas this is not + // the behavior we want. We therefore deselect the text in the lineedit. + if (auto lineEdit = editor->findChild()) { + lineEdit->deselect(); + } +} + void DlgAddPropertyVarSet::addEditor(PropertyEditor::PropertyItem* propertyItem, [[maybe_unused]]std::string& type) { editor.reset(propertyItem->createEditor(this, [this]() { this->valueChanged(); })); + editor->blockSignals(true); propertyItem->setEditorData( editor.get(), propertyItem->data(PropertyEditor::PropertyItem::ValueColumn, Qt::EditRole)); @@ -262,6 +274,9 @@ void DlgAddPropertyVarSet::addEditor(PropertyEditor::PropertyItem* propertyItem, QWidget::setTabOrder(ui->comboBoxType, editor.get()); QWidget::setTabOrder(editor.get(), ui->checkBoxAdd); + removeSelectionEditor(); + editor->blockSignals(false); + // FC_ERR("add editor"); // printFocusChain(editor.get()); } diff --git a/src/Gui/Dialogs/DlgAddPropertyVarSet.h b/src/Gui/Dialogs/DlgAddPropertyVarSet.h index d59a684cf6..3c797db686 100644 --- a/src/Gui/Dialogs/DlgAddPropertyVarSet.h +++ b/src/Gui/Dialogs/DlgAddPropertyVarSet.h @@ -92,6 +92,7 @@ private: void clearCurrentProperty(); void removeEditor(); + void removeSelectionEditor(); void addEditor(PropertyEditor::PropertyItem* propertyItem, std::string& type); bool isTypeWithEditor(const std::string& type); From b9d03abc7b894ea4e288b6c627c2b1e942595272 Mon Sep 17 00:00:00 2001 From: Luz Paz Date: Tue, 1 Apr 2025 10:05:08 -0400 Subject: [PATCH 120/316] Draft: fix source typo in draftobjects/patharray.py --- src/Mod/Draft/draftobjects/patharray.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftobjects/patharray.py b/src/Mod/Draft/draftobjects/patharray.py index 146319f730..7871eb8fd1 100644 --- a/src/Mod/Draft/draftobjects/patharray.py +++ b/src/Mod/Draft/draftobjects/patharray.py @@ -683,7 +683,7 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align, fullSpacingPattern = [spacingPattern[i % len(spacingPattern)] for i in range(segCount)] sumWeights = sum(fullSpacingPattern) distPerWeightUnit = totalDist / sumWeights - steps = [distPerWeightUnit * weigth for weigth in fullSpacingPattern] + steps = [distPerWeightUnit * weight for weight in fullSpacingPattern] else: # Available length will be evenly divided (the original spacing method): From 644b902615bb0f833c597287a39a98ad378355c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Br=C3=A6strup=20Sayoc?= Date: Tue, 1 Apr 2025 21:29:52 +0200 Subject: [PATCH 121/316] Build: force CMake to 3.31.6 version in CI (#20581) * Update sub_buildUbuntu.yml * Update sub_buildWindows.yml --- .github/workflows/sub_buildUbuntu.yml | 4 ++++ .github/workflows/sub_buildWindows.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/sub_buildUbuntu.yml b/.github/workflows/sub_buildUbuntu.yml index 4d704ac2bd..5c652b1cf2 100644 --- a/.github/workflows/sub_buildUbuntu.yml +++ b/.github/workflows/sub_buildUbuntu.yml @@ -107,6 +107,10 @@ jobs: ccache -s ccache -z ccache -p + - name: Install cmake + uses: jwlawson/actions-setup-cmake@v2 + with: + cmake-version: '3.31.6' - name: CMake Configure uses: ./.github/workflows/actions/linux/configure with: diff --git a/.github/workflows/sub_buildWindows.yml b/.github/workflows/sub_buildWindows.yml index 2ccbd44fba..11dbe16904 100644 --- a/.github/workflows/sub_buildWindows.yml +++ b/.github/workflows/sub_buildWindows.yml @@ -98,6 +98,10 @@ jobs: . $env:ccachebindir\ccache -s . $env:ccachebindir\ccache -z . $env:ccachebindir\ccache -p + - name: Install cmake + uses: jwlawson/actions-setup-cmake@v2 + with: + cmake-version: '3.31.6' - name: Configuring CMake run: > cmake -B"${{ env.builddir }}" . From 837f6fa788d7efd67140279acea6d9bfd5154638 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sun, 30 Mar 2025 10:50:04 -0500 Subject: [PATCH 122/316] App: Change element name warning to log --- src/App/PropertyLinks.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 356f1677d3..483b51bccf 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -469,9 +469,9 @@ bool PropertyLinkBase::_updateElementReference(DocumentObject* feature, const auto& newName = elementName.newName.size() ? elementName.newName : elementName.oldName; if (oldName != newName) { - FC_WARN(propertyName(this) - << " auto change element reference " << ret->getFullName() << " " - << oldName << " -> " << newName); + FC_LOG(propertyName(this) + << " auto change element reference " << ret->getFullName() << " " + << oldName << " -> " << newName); } } } From f4adf2e0e937989bbea2bf64659b2fd622dfd3d7 Mon Sep 17 00:00:00 2001 From: marioalexis84 <53127171+marioalexis84@users.noreply.github.com> Date: Wed, 2 Apr 2025 01:19:53 -0300 Subject: [PATCH 123/316] Fem: Update modification time for FemFrameSourceAlgorithm - fixes #20543 (#20548) --- src/Mod/Fem/App/FemPostPipeline.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index 3af7c03132..1136682c52 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -76,6 +76,7 @@ FemFrameSourceAlgorithm::FemFrameSourceAlgorithm::~FemFrameSourceAlgorithm() void FemFrameSourceAlgorithm::setDataObject(vtkSmartPointer data) { m_data = data; + Modified(); Update(); } @@ -157,7 +158,6 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outVector) { - vtkInformation* outInfo = outVector->GetInformationObject(0); vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); @@ -220,7 +220,6 @@ FemPostPipeline::FemPostPipeline() vtkDataSet* FemPostPipeline::getDataSet() { - if (!m_source_algorithm->isValid()) { return nullptr; } @@ -447,6 +446,7 @@ void FemPostPipeline::onChanged(const Property* prop) Frame.setValue(long(0)); } + updateData(); recomputeChildren(); } From 8f35742f1f552bf4497920c8629392ab33336b49 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Wed, 2 Apr 2025 20:08:41 +0200 Subject: [PATCH 124/316] Addon Manager: Fix call to get home_dir for pip --- src/Mod/AddonManager/addonmanager_utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/AddonManager/addonmanager_utilities.py b/src/Mod/AddonManager/addonmanager_utilities.py index 0323132006..48cc6f0832 100644 --- a/src/Mod/AddonManager/addonmanager_utilities.py +++ b/src/Mod/AddonManager/addonmanager_utilities.py @@ -587,7 +587,7 @@ def create_pip_call(args: List[str]) -> List[str]: call_args = ["pip", "--disable-pip-version-check"] call_args.extend(args) elif appimage: - python_exe = fci.DataPaths.home_dir + "bin/python" + python_exe = fci.DataPaths().home_dir + "bin/python" call_args = [python_exe, "-m", "pip", "--disable-pip-version-check"] call_args.extend(args) else: From eece614172415cd61310bd35416cb9cc5c2346b7 Mon Sep 17 00:00:00 2001 From: Dan Taylor Date: Sat, 22 Feb 2025 10:43:30 -0600 Subject: [PATCH 125/316] CAM: Adaptive: Make machined regions respect stock and model in 3D, not just the 2D projections of the stock and selected machining bounding box --- src/Mod/CAM/CAMTests/TestPathAdaptive.py | 149 +++-- src/Mod/CAM/Path/Op/Adaptive.py | 693 ++++++++++++++++------- 2 files changed, 613 insertions(+), 229 deletions(-) diff --git a/src/Mod/CAM/CAMTests/TestPathAdaptive.py b/src/Mod/CAM/CAMTests/TestPathAdaptive.py index 9325d4b836..70d72ac086 100644 --- a/src/Mod/CAM/CAMTests/TestPathAdaptive.py +++ b/src/Mod/CAM/CAMTests/TestPathAdaptive.py @@ -396,10 +396,109 @@ class TestPathAdaptive(PathTestBase): break self.assertTrue(isInBox, "No paths originating within the inner hole.") + def test08(self): + """test08() Tests stock awareness- avoids cutting into the model regardless + of bounding box selected.""" + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create("Adaptive") + adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) + adaptive.Label = "test08+" + adaptive.Comment = "test08() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different. Result should be the combination at Z=10 (faces from (0,0) to (40,25), minus tool radius), and only the lower face at Z=5: (15,0) to (40,25)." + + # Set additional operation properties + setDepthsAndHeights(adaptive, 15, 0) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression("StepDown", None) + adaptive.StepDown.Value = ( + 5.0 # Have to set expression to None before numerical value assignment + ) + + _addViewProvider(adaptive) + self.doc.recompute() + + # Check: + # - Bounding box at Z=10 stays within Face3 and Face10- so -X for Face3, + # +X and +/-Y for Face10 + # - bounding box at Z=5 stays within Face10 + # - No toolpaths at Z=0 + + paths = [c for c in adaptive.Path.Commands if c.Name in ["G0", "G00", "G1", "G01"]] + toolr = adaptive.OpToolDiameter.Value / 2 + tol = adaptive.Tolerance + + # Make clean up math below- combine tool radius and tolerance into a + # single field that can be added/subtracted to/from bounding boxes + moffset = toolr - tol + + zDict = {10: None, 5: None, 0: None} + + getPathBoundaries(paths, zDict) + + # NOTE: Face3 is at Z=10, Face10 is at Z=5 + bbf3 = self.doc.Fusion.Shape.getElement("Face3").BoundBox + bbf10 = self.doc.Fusion.Shape.getElement("Face10").BoundBox + + okAt10 = ( + zDict[10] is not None + and zDict[10]["min"][0] >= bbf3.XMin + moffset + and zDict[10]["min"][1] >= bbf10.YMin + moffset + and zDict[10]["max"][0] <= bbf10.XMax - moffset + and zDict[10]["max"][1] <= bbf10.YMax - moffset + ) + + okAt5 = ( + zDict[5] is not None + and zDict[5]["min"][0] >= bbf10.XMin + moffset + and zDict[5]["min"][1] >= bbf10.YMin + moffset + and zDict[5]["max"][0] < bbf10.XMax - moffset + and zDict[5]["max"][1] < bbf10.YMax - moffset + ) + + okAt0 = not zDict[0] + + self.assertTrue(okAt10 and okAt5 and okAt0, "Path boundaries outside of expected regions") + # Eclass +def getPathBoundaries(paths, zDict): + """getPathBoundaries(paths, zDict): Takes the list of paths and dictionary + of Z depths of interest, and finds the bounding box of the paths at each + depth. + + NOTE: You'd think that using Path.BoundBox would give us what we want, + but... no, for whatever reason it appears to always extend to (0,0,0) + """ + last = FreeCAD.Vector(0.0, 0.0, 0.0) + # First make sure each element has X, Y, and Z coordinates + for p in paths: + params = p.Parameters + last.x = p.X if "X" in params else last.x + last.y = p.Y if "Y" in params else last.y + last.z = p.Z if "Z" in params else last.z + + p.X = last.x + p.Y = last.y + p.Z = last.z + + for z in zDict: + zpaths = [k for k in paths if k.Z == z] + if not zpaths: + zDict[z] = None + continue + xmin = min([k.X for k in zpaths]) + xmax = max([k.X for k in zpaths]) + ymin = min([k.Y for k in zpaths]) + ymax = max([k.Y for k in zpaths]) + zDict[z] = {"min": (xmin, ymin), "max": (xmax, ymax)} + + def setDepthsAndHeights(op, strDep=20.0, finDep=0.0): """setDepthsAndHeights(op, strDep=20.0, finDep=0.0)... Sets default depths and heights for `op` passed to it""" @@ -421,43 +520,29 @@ def getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=Tr """getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=True)... Accepts command dict and returns point string coordinate. """ + + # NOTE: Can NOT just check "if p.get("X")" or similar- that chokes when X is + # zero. That becomes especially obvious when Z=0, and moves end up on the + # wrong depth gcode_list = list() last = FreeCAD.Vector(0.0, 0.0, 0.0) for c in cmdList: p = c.Parameters name = c.Name - if includeRapids and name in ["G0", "G00"]: + if (includeRapids and name in ["G0", "G00"]) or (includeLines and name in ["G1", "G01"]): gcode = name x = last.x y = last.y z = last.z - if p.get("X"): + if "X" in p: x = round(p["X"], 2) - gcode += " X" + str(x) - if p.get("Y"): + gcode += " X" + str(x) + if "Y" in p: y = round(p["Y"], 2) - gcode += " Y" + str(y) - if p.get("Z"): + gcode += " Y" + str(y) + if "Z" in p: z = round(p["Z"], 2) - gcode += " Z" + str(z) - last.x = x - last.y = y - last.z = z - gcode_list.append(gcode) - elif includeLines and name in ["G1", "G01"]: - gcode = name - x = last.x - y = last.y - z = last.z - if p.get("X"): - x = round(p["X"], 2) - gcode += " X" + str(x) - if p.get("Y"): - y = round(p["Y"], 2) - gcode += " Y" + str(y) - if p.get("Z"): - z = round(p["Z"], 2) - gcode += " Z" + str(z) + gcode += " Z" + str(z) last.x = x last.y = y last.z = z @@ -470,23 +555,23 @@ def getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=Tr i = 0.0 j = 0.0 k = 0.0 - if p.get("I"): + if "I" in p: i = round(p["I"], 2) gcode += " I" + str(i) - if p.get("J"): + if "J" in p: j = round(p["J"], 2) gcode += " J" + str(j) - if p.get("K"): + if "K" in p: k = round(p["K"], 2) gcode += " K" + str(k) - if p.get("X"): + if "X" in p: x = round(p["X"], 2) gcode += " X" + str(x) - if p.get("Y"): + if "Y" in p: y = round(p["Y"], 2) gcode += " Y" + str(y) - if p.get("Z"): + if "Z" in p: z = round(p["Z"], 2) gcode += " Z" + str(z) @@ -501,7 +586,7 @@ def pathOriginatesInBox(cmd, minPoint, maxPoint): p = cmd.Parameters name = cmd.Name if name in ["G0", "G00", "G1", "G01"]: - if p.get("X") and p.get("Y"): + if "X" in p and "Y" in p: x = p.get("X") y = p.get("Y") if x > minPoint.x and y > minPoint.y and x < maxPoint.x and y < maxPoint.y: diff --git a/src/Mod/CAM/Path/Op/Adaptive.py b/src/Mod/CAM/Path/Op/Adaptive.py index dc40299eda..75d3b62aa5 100644 --- a/src/Mod/CAM/Path/Op/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Adaptive.py @@ -72,6 +72,9 @@ sceneGraph = None scenePathNodes = [] # for scene cleanup afterwards topZ = 10 +# Constants to avoid magic numbers in the code +_ADAPTIVE_MIN_STEPDOWN = 0.1 + def sceneDrawPath(path, color=(0, 0, 1)): coPoint = coin.SoCoordinate3() @@ -117,7 +120,7 @@ def CalcHelixConePoint(height, cur_z, radius, angle): def GenerateGCode(op, obj, adaptiveResults, helixDiameter): - if len(adaptiveResults) == 0 or len(adaptiveResults[0]["AdaptivePaths"]) == 0: + if not adaptiveResults or not adaptiveResults[0]["AdaptivePaths"]: return # minLiftDistance = op.tool.Diameter @@ -125,74 +128,55 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): for region in adaptiveResults: p1 = region["HelixCenterPoint"] p2 = region["StartPoint"] - r = math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])) - if r > helixRadius: - helixRadius = r + helixRadius = max(math.dist(p1[:2], p2[:2]), helixRadius) - stepDown = obj.StepDown.Value - passStartDepth = obj.StartDepth.Value - - if stepDown < 0.1: - stepDown = 0.1 + stepDown = max(obj.StepDown.Value, _ADAPTIVE_MIN_STEPDOWN) length = 2 * math.pi * helixRadius - if float(obj.HelixAngle) < 1: - obj.HelixAngle = 1 - if float(obj.HelixAngle) > 89: - obj.HelixAngle = 89 + obj.HelixAngle = min(89, max(obj.HelixAngle.Value, 1)) + obj.HelixConeAngle = max(obj.HelixConeAngle, 0) - if float(obj.HelixConeAngle) < 0: - obj.HelixConeAngle = 0 - - helixAngleRad = math.pi * float(obj.HelixAngle) / 180.0 + helixAngleRad = math.radians(obj.HelixAngle) depthPerOneCircle = length * math.tan(helixAngleRad) - # print("Helix circle depth: {}".format(depthPerOneCircle)) - stepUp = obj.LiftDistance.Value - if stepUp < 0: - stepUp = 0 + stepUp = max(obj.LiftDistance.Value, 0) - finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0 - if finish_step > stepDown: - finish_step = stepDown + # TODO: finishStep is of limited utility with how regions are now broken + # up based on the model geometry- the "finish" step gets applied to each + # region separately, which results in excessive "finish" steps being taken + # where they really need not be. Leaving stock in Z generally makes more + # sense, but both technically have their uses, so leaving this here as + # option. Implementing flat area detection would make better use of both. + finishStep = min(obj.FinishDepth.Value, stepDown) if hasattr(obj, "FinishDepth") else 0.0 - depth_params = PathUtils.depth_params( - clearance_height=obj.ClearanceHeight.Value, - safe_height=obj.SafeHeight.Value, - start_depth=obj.StartDepth.Value, - step_down=stepDown, - z_finish_step=finish_step, - final_depth=obj.FinalDepth.Value, - user_depths=None, - ) + # Track Z position to determine when changing height is necessary prior to a move + lz = obj.StartDepth.Value - # ml: this is dangerous because it'll hide all unused variables hence forward - # however, I don't know what lx and ly signify so I'll leave them for now - # lx = adaptiveResults[0]["HelixCenterPoint"][0] - # ly = adaptiveResults[0]["HelixCenterPoint"][1] - lz = passStartDepth - step = 0 + for region in adaptiveResults: + passStartDepth = region["TopDepth"] - for passEndDepth in depth_params.data: - step = step + 1 + depthParams = PathUtils.depth_params( + clearance_height=obj.ClearanceHeight.Value, + safe_height=obj.SafeHeight.Value, + start_depth=region["TopDepth"], + step_down=stepDown, + z_finish_step=finishStep, + final_depth=region["BottomDepth"], + user_depths=None, + ) - for region in adaptiveResults: + for passEndDepth in depthParams.data: startAngle = math.atan2( region["StartPoint"][1] - region["HelixCenterPoint"][1], region["StartPoint"][0] - region["HelixCenterPoint"][0], ) - # lx = region["HelixCenterPoint"][0] - # ly = region["HelixCenterPoint"][1] - passDepth = passStartDepth - passEndDepth p1 = region["HelixCenterPoint"] p2 = region["StartPoint"] - helixRadius = math.sqrt( - (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]) - ) + helixRadius = math.dist(p1[:2], p2[:2]) # Helix ramp if helixRadius > 0.01: @@ -256,8 +240,6 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): op.commandlist.append( Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.vertFeed}) ) - # lx = x - # ly = y fi = fi + math.pi / 16 # one more circle at target depth to make sure center is cleared @@ -269,13 +251,11 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): op.commandlist.append( Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.horizFeed}) ) - # lx = x - # ly = y fi = fi + math.pi / 16 else: # Cone - _HelixAngle = 360 - (float(obj.HelixAngle) * 4) + _HelixAngle = 360 - (obj.HelixAngle.Value * 4) if obj.HelixConeAngle > 6: obj.HelixConeAngle = 6 @@ -510,8 +490,6 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): }, ) ) - # lx = x - # ly = y else: # no helix entry # rapid move to clearance height @@ -551,8 +529,6 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): x = pt[0] y = pt[1] - # dist = math.sqrt((x-lx)*(x-lx) + (y-ly)*(y-ly)) - if motionType == area.AdaptiveMotionType.Cutting: z = passEndDepth if z != lz: @@ -576,13 +552,6 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): op.commandlist.append(Path.Command("G0", {"X": x, "Y": y})) - # elif motionType == area.AdaptiveMotionType.LinkClearAtPrevPass: - # if lx!=x or ly!=y: - # op.commandlist.append(Path.Command("G0", { "X": lx, "Y":ly, "Z":passStartDepth+stepUp})) - # op.commandlist.append(Path.Command("G0", { "X": x, "Y":y, "Z":passStartDepth+stepUp})) - - # lx = x - # ly = y lz = z # return to safe height in this Z pass @@ -592,14 +561,14 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): lz = z - passStartDepth = passEndDepth + passStartDepth = passEndDepth - # return to safe height in this Z pass - z = obj.ClearanceHeight.Value - if z != lz: - op.commandlist.append(Path.Command("G0", {"Z": z})) + # return to safe height in this Z pass + z = obj.ClearanceHeight.Value + if z != lz: + op.commandlist.append(Path.Command("G0", {"Z": z})) - lz = z + lz = z z = obj.ClearanceHeight.Value if z != lz: @@ -634,70 +603,100 @@ def Execute(op, obj): topZ = op.stock.Shape.BoundBox.ZMax obj.Stopped = False obj.StopProcessing = False - if obj.Tolerance < 0.001: - obj.Tolerance = 0.001 + obj.Tolerance = max(0.001, obj.Tolerance) - # Get list of working edges for adaptive algorithm - pathArray = op.pathArray - if not pathArray: - msg = translate( - "CAM", - "Adaptive operation couldn't determine the boundary wire. Did you select base geometry?", + # NOTE: Reminder that stock is formatted differently than inside/outside! + stockPaths = {d: convertTo2d(op.stockPathArray[d]) for d in op.stockPathArray} + + outsideOpType = area.AdaptiveOperationType.ClearingOutside + insideOpType = area.AdaptiveOperationType.ClearingInside + + # List every REGION separately- we can then calculate a toolpath based + # on the region. One or more stepdowns may use that same toolpath by + # keeping a reference to the region without requiring we calculate the + # toolpath once per step down OR forcing all stepdowns of a region into + # a single list. + regionOps = list() + outsidePathArray2dDepthTuples = list() + insidePathArray2dDepthTuples = list() + # NOTE: Make sure the depth lists are sorted for use in order-by-depth + # and order-by-region algorithms below + # NOTE: Pretty sure sorting is already guaranteed by how these are + # created, but best to not assume that + for rdict in op.outsidePathArray: + regionOps.append( + { + "opType": outsideOpType, + "path2d": convertTo2d(rdict["edges"]), + # FIXME: Kinda gross- just use this to match up with the + # appropriate stockpaths entry... + "startdepth": rdict["depths"][0], + } + ) + outsidePathArray2dDepthTuples.append( + (sorted(rdict["depths"], reverse=True), regionOps[-1]) + ) + for rdict in op.insidePathArray: + regionOps.append( + { + "opType": insideOpType, + "path2d": convertTo2d(rdict["edges"]), + # FIXME: Kinda gross- just use this to match up with the + # appropriate stockpaths entry... + "startdepth": rdict["depths"][0], + } + ) + insidePathArray2dDepthTuples.append( + (sorted(rdict["depths"], reverse=True), regionOps[-1]) ) - FreeCAD.Console.PrintUserWarning(msg) - return - - path2d = convertTo2d(pathArray) - - # Use the 2D outline of the stock as the stock - # FIXME: This does not account for holes in the middle of stock! - outer_wire = TechDraw.findShapeOutline(op.stock.Shape, 1, FreeCAD.Vector(0, 0, 1)) - stockPaths = [[discretize(outer_wire)]] - - stockPath2d = convertTo2d(stockPaths) - - # opType = area.AdaptiveOperationType.ClearingInside # Commented out per LGTM suggestion - if obj.OperationType == "Clearing": - if obj.Side == "Outside": - opType = area.AdaptiveOperationType.ClearingOutside - - else: - opType = area.AdaptiveOperationType.ClearingInside - - else: # profiling - if obj.Side == "Outside": - opType = area.AdaptiveOperationType.ProfilingOutside - - else: - opType = area.AdaptiveOperationType.ProfilingInside keepToolDownRatio = 3.0 if hasattr(obj, "KeepToolDownRatio"): - keepToolDownRatio = float(obj.KeepToolDownRatio) + keepToolDownRatio = obj.KeepToolDownRatio.Value - # put here all properties that influence calculation of adaptive base paths, - - inputStateObject = { - "tool": float(op.tool.Diameter), - "tolerance": float(obj.Tolerance), - "geometry": path2d, - "stockGeometry": stockPath2d, - "stepover": float(obj.StepOver), - "effectiveHelixDiameter": float(helixDiameter), - "operationType": obj.OperationType, - "side": obj.Side, + # These fields are used to determine if toolpaths should be recalculated + outsideInputStateObject = { + "tool": op.tool.Diameter.Value, + "tolerance": obj.Tolerance, + "geometry": [k["path2d"] for k in regionOps if k["opType"] == outsideOpType], + "stockGeometry": stockPaths, + "stepover": obj.StepOver, + "effectiveHelixDiameter": helixDiameter, + "operationType": "Clearing", + "side": "Outside", "forceInsideOut": obj.ForceInsideOut, "finishingProfile": obj.FinishingProfile, "keepToolDownRatio": keepToolDownRatio, - "stockToLeave": float(obj.StockToLeave), + "stockToLeave": obj.StockToLeave.Value, } + insideInputStateObject = { + "tool": op.tool.Diameter.Value, + "tolerance": obj.Tolerance, + "geometry": [k["path2d"] for k in regionOps if k["opType"] == insideOpType], + "stockGeometry": stockPaths, + "stepover": obj.StepOver, + "effectiveHelixDiameter": helixDiameter, + "operationType": "Clearing", + "side": "Inside", + "forceInsideOut": obj.ForceInsideOut, + "finishingProfile": obj.FinishingProfile, + "keepToolDownRatio": keepToolDownRatio, + "stockToLeave": obj.StockToLeave.Value, + } + + inputStateObject = [outsideInputStateObject, insideInputStateObject] + inputStateChanged = False adaptiveResults = None - if obj.AdaptiveOutputState is not None and obj.AdaptiveOutputState != "": + # If we have a valid... path? Something. Generated, make that + # tentatively the output + if obj.AdaptiveOutputState: adaptiveResults = obj.AdaptiveOutputState + # If ANYTHING in our input-cutting parameters, cutting regions, + # etc.- changes, force recalculating if json.dumps(obj.AdaptiveInputState) != json.dumps(inputStateObject): inputStateChanged = True adaptiveResults = None @@ -721,31 +720,67 @@ def Execute(op, obj): start = time.time() if inputStateChanged or adaptiveResults is None: - a2d = area.Adaptive2d() - a2d.stepOverFactor = 0.01 * obj.StepOver - a2d.toolDiameter = float(op.tool.Diameter) - a2d.helixRampDiameter = helixDiameter - a2d.keepToolDownDistRatio = keepToolDownRatio - a2d.stockToLeave = float(obj.StockToLeave) - a2d.tolerance = float(obj.Tolerance) - a2d.forceInsideOut = obj.ForceInsideOut - a2d.finishingProfile = obj.FinishingProfile - a2d.opType = opType + # NOTE: Seem to need to create a new a2d for each area when we're + # stepping down depths like this. If we don't, it will keep history + # from the last region we did. - # EXECUTE - results = a2d.Execute(stockPath2d, path2d, progressFn) + # TODO: QThread/QRunnable trigger Python's global interpretor lock + # (GIL). To calculate toolpaths in parallel, making a C++ shim that + # takes in the array of regions/stock paths and parallelizes in + # C++-land is probably the way to do it. + + # Create a toolpath for each region to avoid re-calculating for + # identical stepdowns + for rdict in regionOps: + path2d = rdict["path2d"] + opType = rdict["opType"] + + a2d = area.Adaptive2d() + a2d.stepOverFactor = 0.01 * obj.StepOver + a2d.toolDiameter = op.tool.Diameter.Value + a2d.helixRampDiameter = helixDiameter + a2d.keepToolDownDistRatio = keepToolDownRatio + a2d.stockToLeave = obj.StockToLeave.Value + a2d.tolerance = obj.Tolerance + a2d.forceInsideOut = obj.ForceInsideOut + a2d.finishingProfile = obj.FinishingProfile + a2d.opType = opType + + rdict["toolpaths"] = a2d.Execute( + stockPaths[rdict["startdepth"]], path2d, progressFn + ) + + # Create list of regions to cut, in an order they can be cut in + cutlist = list() + # Region IDs that have been cut already + cutids = list() + # Create sorted list of unique depths + # NOTE: reverse because we cut top-down! + depths = list() + # NOTE: alltuples is sorted by depth already + alltuples = outsidePathArray2dDepthTuples + insidePathArray2dDepthTuples + for t in alltuples: + depths += [d for d in t[0]] + depths = sorted(list(set(depths)), reverse=True) + for d in depths: + cutlist += [([d], o[1]) for o in outsidePathArray2dDepthTuples if d in o[0]] + cutlist += [([d], i[1]) for i in insidePathArray2dDepthTuples if d in i[0]] # need to convert results to python object to be JSON serializable - adaptiveResults = [] - for result in results: - adaptiveResults.append( - { - "HelixCenterPoint": result.HelixCenterPoint, - "StartPoint": result.StartPoint, - "AdaptivePaths": result.AdaptivePaths, - "ReturnMotionType": result.ReturnMotionType, - } - ) + stepdown = max(obj.StepDown.Value, _ADAPTIVE_MIN_STEPDOWN) + adaptiveResults = list() + for depths, region in cutlist: + for result in region["toolpaths"]: + adaptiveResults.append( + { + "HelixCenterPoint": result.HelixCenterPoint, + "StartPoint": result.StartPoint, + "AdaptivePaths": result.AdaptivePaths, + "ReturnMotionType": result.ReturnMotionType, + "TopDepth": depths[0] + stepdown, + "BottomDepth": depths[-1], + } + ) # GENERATE GenerateGCode(op, obj, adaptiveResults, helixDiameter) @@ -765,71 +800,328 @@ def Execute(op, obj): sceneClean() -def _get_working_edges(op, obj): - """_get_working_edges(op, obj)... - Compile all working edges from the Base Geometry selection (obj.Base) - for the current operation. - Additional modifications to selected region(face), such as extensions, - should be placed within this function. +def projectFacesToXY(faces, minEdgeLength=1e-10): + """projectFacesToXY(faces, minEdgeLength) + Calculates the projection of the provided list of faces onto the XY plane. + The returned value is a single shape that may contain multiple faces if + there were disjoint projections. Each individual face will be clean, without + triangulated geometry, etc., and will be at Z=0 on the XY plane + + minEdgeLength is provided to (eg) filter out the tips of cones that are + internally represented as arbitrarily-small circular faces- using those for + additional operations causes problems. """ - all_regions = list() - edge_list = list() - avoidFeatures = list() - rawEdges = list() + projdir = FreeCAD.Vector(0, 0, 1) + outfaces = [] + for f in faces: + # Vertical cones and spheres will still have a projection on the XY + # plane. Cylinders and flat faces will not. + if Path.Geom.isVertical(f) and type(f.Surface) not in [Part.Cone, Part.Sphere]: + continue + + # NOTE: Wires/edges get clipped if we have an "exact fit" bounding box + projface = Path.Geom.makeBoundBoxFace(f.BoundBox, offset=1, zHeight=0) + + # NOTE: Cylinders, cones, and spheres are messy: + # - Internal representation of non-truncted cones and spheres includes + # the "tip" with a ~0-area closed edge. This is different than the + # "isNull() note" at the top in magnitude + # - Projecting edges doesn't naively work due to the way seams are handled + # - There may be holes at either end that may or may not line up- any + # overlap is a hole in the projection + if type(f.Surface) in [Part.Cone, Part.Cylinder, Part.Sphere]: + # This gets most of the face outline, but since cylinder/cone faces + # are hollow, if the ends overlap in the projection there may be a + # hole we need to remove from the solid projection + oface = Part.makeFace(TechDraw.findShapeOutline(f, 1, projdir)) + + # "endfacewires" is JUST the end faces of a cylinder/cone, used to + # determine if there's a hole we can see through the shape that + # should NOT be solid in the projection + endfacewires = DraftGeomUtils.findWires( + [e for e in f.Edges if not e.isSeam(f) and e.Length > minEdgeLength] + ) + + # Need to verify that there actually is a projection before taking + # a wire from the list, else this could nicely be one line. + projwires = [] + for w in endfacewires: + pp = projface.makeParallelProjection(w, projdir).Wires + if pp: + projwires.append(pp[0]) + + if len(projwires) > 1: + faces = [Part.makeFace(x) for x in projwires] + overlap = faces[0].common(faces[1:]) + outfaces.append(oface.cut(overlap)) + else: + outfaces.append(oface) + # For other cases, projecting the wires to a plane should suffice + else: + facewires = list() + for w in f.Wires: + if w.isClosed(): + projwire = projface.makeParallelProjection(w, projdir).Wires[0] + if projwire.isClosed(): + facewires.append(projwire) + if facewires: + outfaces.append(Part.makeFace(facewires)) + if outfaces: + fusion = outfaces[0].fuse(outfaces[1:]) + # removeSplitter fixes occasional concatenate issues for some face orders + return DraftGeomUtils.concatenate(fusion.removeSplitter()) + else: + return Part.Shape() + + +def _getSolidProjection(shp, z): + """_getSolidProjection(shp, z) + Calculates a shape obtained by slicing shp at the height z, then projecting + the solids above that height onto a region of proj_face, and creating a + simplified face + """ + bb = shp.BoundBox + + # Find all faces above the machining depth. This is used to mask future + # interior cuts, and the outer wire is used as the external wire + bbCutTop = Part.makeBox( + bb.XLength, + bb.YLength, + max(bb.ZLength, bb.ZLength - z), + FreeCAD.Vector(bb.XMin, bb.YMin, z), + ) + aboveSolids = shp.common(bbCutTop).Solids + + faces = list() + for s in aboveSolids: + faces += s.Faces + + return projectFacesToXY(faces) + + +def _workingEdgeHelperManual(op, obj, depths): + # Final calculated regions- list of dicts with entries: + # "region" - actual shape + # "depths" - list of depths this region applies to + insideRegions = list() + outsideRegions = list() + + # User selections, with extensions + selectedRegions = list() + selectedEdges = list() # Get extensions and identify faces to avoid extensions = FeatureExtensions.getExtensions(obj) - for e in extensions: - if e.avoid: - avoidFeatures.append(e.feature) + avoidFeatures = [e for e in extensions if e.avoid] - # Get faces selected by user - for base, subs in obj.Base: - for sub in subs: - if sub.startswith("Face"): - if sub not in avoidFeatures: - if obj.UseOutline: - face = base.Shape.getElement(sub) - # get outline with wire_A method used in PocketShape, but it does not play nicely later - # wire_A = TechDraw.findShapeOutline(face, 1, FreeCAD.Vector(0.0, 0.0, 1.0)) - wire_B = face.OuterWire - shape = Part.Face(wire_B) - else: - shape = base.Shape.getElement(sub) - all_regions.append(shape) - elif sub.startswith("Edge"): - # Save edges for later processing - rawEdges.append(base.Shape.getElement(sub)) - # Efor - - # Process selected edges - if rawEdges: - edgeWires = DraftGeomUtils.findWires(rawEdges) - if edgeWires: - for w in edgeWires: - for e in w.Edges: - edge_list.append([discretize(e)]) - - # Apply regular Extensions - op.exts = [] + # Similarly, expand selected regions with extensions for ext in extensions: if not ext.avoid: - wire = ext.getWire() - if wire: - for f in ext.getExtensionFaces(wire): - op.exts.append(f) - all_regions.append(f) + if wire := ext.getWire(): + selectedRegions += [f for f in ext.getExtensionFaces(wire)] - # Second face-combining method attempted - horizontal = Path.Geom.combineHorizontalFaces(all_regions) - if horizontal: - obj.removalshape = Part.makeCompound(horizontal) - for f in horizontal: - for w in f.Wires: - for e in w.Edges: - edge_list.append([discretize(e)]) + for base, subs in obj.Base: + for sub in subs: + element = base.Shape.getElement(sub) + if sub.startswith("Face") and sub not in avoidFeatures: + shape = Part.Face(element.OuterWire) if obj.UseOutline else element + selectedRegions.append(shape) + # Omit vertical edges, since they project to nothing in the XY plane + # and cause processing failures later if included + elif sub.startswith("Edge") and not Path.Geom.isVertical(element): + selectedEdges.append(element) - return edge_list + # Multiple input solids can be selected- make a single part out of them, + # will process each solid separately as appropriate + shps = op.model[0].Shape.fuse([k.Shape for k in op.model[1:]]) + + # Make a face to project onto + # NOTE: Use 0 as the height, since that's what TechDraw.findShapeOutline + # uses, which we use to find the machining boundary, and the actual depth + # is tracked separately. + # NOTE: Project to the PART bounding box- with some padding- not the stock, + # since the stock may be smaller than the part + projface = Path.Geom.makeBoundBoxFace(shps.BoundBox, offset=1, zHeight=0) + projdir = FreeCAD.Vector(0, 0, 1) + + # When looking for selected edges, project to a single plane first, THEN try + # to find wires. Take all the resulting wires and make faces in one shot to + # make bullseye-style cutouts where selected wires nest. + edgefaces = list() + if selectedEdges: + pp = [projface.makeParallelProjection(e, projdir).Wires[0] for e in selectedEdges] + ppe = list() + for w in pp: + ppe += w.Edges + edgeWires = DraftGeomUtils.findWires(ppe) + edgefaces = Part.makeFace(edgeWires).Faces + + selectedRefined = projectFacesToXY(selectedRegions + edgefaces) + + # If the user selected only faces that don't have an XY projection AND no + # edges, give a useful error + if not selectedRefined.Wires: + Path.Log.warning("Selected faces/wires have no projection on the XY plane") + return insideRegions, outsideRegions + + lastdepth = obj.StartDepth.Value + + for depth in depths: + # If our depth is above the top of the stock, there's nothing to machine + if depth >= op.stock.Shape.BoundBox.ZMax: + lastdepth = depth + continue + + aboveRefined = _getSolidProjection(shps, depth) + + # Create appropriate tuples and add to list, processing inside/outside + # as requested by operation + if obj.Side == "Outside": + # Outside is based on the outer wire of the faces of aboveRefined + # Insides are based on the remaining "below" regions, masked by the + # "above"- if something is above an area, we can't machine it in 2.5D + + # Outside: Take the outer wire of the above faces, added to selected + # edges and regions + # NOTE: Exactly one entry per depth (not necessarily one depth entry per + # stepdown, however), which is a LIST of the wires we're staying outside + # NOTE: Do this FIRST- if any inside regions share enough of an edge + # with an outside region for a tool to get through, we want to skip them + # for the current stepdown + # NOTE: This check naively seems unnecessary, but it's possible the + # user selected a vertical face as the only face to stay outside of, + # and we're above the model, causing keepOutFaces to be empty + if keepOutFaces := [ + Part.makeFace(TechDraw.findShapeOutline(f, 1, projdir)) + for f in aboveRefined.Faces + selectedRefined.Faces + ]: + finalMerge = keepOutFaces[0].fuse(keepOutFaces[1:]) + else: + finalMerge = selectedRefined + # Without removeSplitter(), concatenate will sometimes fail when + # trying to merge faces that are (eg) connected A-B and B-C, + # seemingly when trying to merge A-C + regions = DraftGeomUtils.concatenate(finalMerge.removeSplitter()) + + # If this region exists in our list, it has to be the last entry, due to + # proceeding in order and having only one per depth. If it's already + # there, replace with the new, deeper depth, else add new + # NOTE: Do NOT need a check for whether outsideRegions[-1]["region"] + # is valid since we have a user-specified region regardless of depth + # NOTE: See "isNull() note" at top of file + if ( + outsideRegions + and regions.Wires + and not regions.cut(outsideRegions[-1]["region"]).Wires + ): + outsideRegions[-1]["depths"].append(depth) + else: + outsideRegions.append({"region": regions, "depths": [depth]}) + + # Inside + # For every area selected by the user, project to a plane + # NOTE: See "isNull() note" at top of file + else: + if aboveRefined.Wires: + finalCut = selectedRefined.cut(aboveRefined) + else: + finalCut = selectedRefined + + # Split up into individual faces if any are disjoint, then update + # insideRegions- either by adding a new entry OR by updating the depth + # of an existing entry + for f in finalCut.Faces: + addNew = True + # Brute-force search all existing regions to see if any are the same + newtop = lastdepth + for rdict in insideRegions: + # FIXME: Smarter way to do this than a full cut operation? + if not rdict["region"].cut(f).Wires: + rdict["depths"].append(depth) + addNew = False + break + if addNew: + insideRegions.append({"region": f, "depths": [depth]}) + + # Update the last depth step + lastdepth = depth + # end for depth + + return insideRegions, outsideRegions + + +def _getWorkingEdges(op, obj): + """_getWorkingEdges(op, obj)... + Compile all working edges from the Base Geometry selection (obj.Base) + for the current operation (or the entire model if no selections). + Additional modifications to selected region(face), such as extensions, + should be placed within this function. + This version will return two lists- one for outside (keepout) edges and one + for inside ("machine inside") edges. Each list will be a dict with "region" + and "depths" entries- the former being discretized geometry of the region, + the latter being a list of every depth the geometry is machined on + """ + + # Find depth steps, throwing out all depths above anywhere we might cut + # NOTE: Finish stepdown = 0 here- it's actually applied when gcode is + # generated; doing so here would cause it to be applied twice. + depthParams = PathUtils.depth_params( + clearance_height=obj.ClearanceHeight.Value, + safe_height=obj.SafeHeight.Value, + start_depth=obj.StartDepth.Value, + step_down=max(obj.StepDown.Value, _ADAPTIVE_MIN_STEPDOWN), + z_finish_step=0.0, + final_depth=obj.FinalDepth.Value, + user_depths=None, + ) + + depths = [d for d in depthParams.data if d < op.stock.Shape.BoundBox.ZMax] + + # Get the stock outline at each stepdown. Used to calculate toolpaths and + # for calcuating cut regions in some instances + # NOTE: Stock is handled DIFFERENTLY than inside and outside regions! + # Combining different depths just adds code to look up the correct outline + # when computing inside/outside regions, for no real benefit. + stockProjectionDict = {d: _getSolidProjection(op.stock.Shape, d) for d in depths} + + # If user specified edges, calculate the machining regions based on that + # input. Otherwise, process entire model + # Output are lists of dicts with "region" and "depths" entries. Depths are + # a list of Z depths that the region applies to + # Inside regions are a single face; outside regions consist of ALL geometry + # to be avoided at those depths. + insideRegions, outsideRegions = _workingEdgeHelperManual(op, obj, depths) + + # Create discretized regions + def _createDiscretizedRegions(regionDicts): + discretizedRegions = list() + for rdict in regionDicts: + discretizedRegions.append( + { + "edges": [[discretize(w)] for w in rdict["region"].Wires], + "depths": rdict["depths"], + } + ) + return discretizedRegions + + insideDiscretized = _createDiscretizedRegions(insideRegions) + outsideDiscretized = _createDiscretizedRegions(outsideRegions) + + # NOTE: REMINDER: This is notably different from machining regions- just + # a dict with depth: region entries, single depth for easy lookup + stockDiscretized = {} + for d in stockProjectionDict: + discretizedEdges = list() + for a in stockProjectionDict[d].Faces: + for w in a.Wires: + discretizedEdges.append([discretize(w)]) + stockDiscretized[d] = discretizedEdges + + # Return found inside and outside regions/depths. Up to the caller to decide + # which ones it cares about. + # NOTE: REMINDER: Stock is notably different from machining regions- just + # a dict with depth: region entries, single depth for easy lookup + return insideDiscretized, outsideDiscretized, stockDiscretized class PathAdaptive(PathOp.ObjectOp): @@ -1108,7 +1400,14 @@ class PathAdaptive(PathOp.ObjectOp): See documentation of execute() for a list of base functionality provided. Should be overwritten by subclasses.""" - self.pathArray = _get_working_edges(self, obj) + # Contains both geometry to machine and the applicable depths + # NOTE: Reminder that stock is formatted differently than inside/outside! + inside, outside, stock = _getWorkingEdges(self, obj) + + self.insidePathArray = inside + self.outsidePathArray = outside + self.stockPathArray = stock + Execute(self, obj) def opOnDocumentRestored(self, obj): From 31ca3e742f2d32c0ca31b2a15e3f0482ebea3dca Mon Sep 17 00:00:00 2001 From: Dan Taylor Date: Wed, 2 Apr 2025 20:47:44 -0500 Subject: [PATCH 126/316] CAM: Adaptive: Add Z stock to leave (separate from XY stock to leave) and order-by-region/order-by-depth cut ordering options --- src/Mod/CAM/CAMTests/TestPathAdaptive.py | 61 ++++ .../Resources/panels/PageOpAdaptiveEdit.ui | 294 ++++++++++-------- src/Mod/CAM/Path/Op/Adaptive.py | 199 ++++++++++-- src/Mod/CAM/Path/Op/Gui/Adaptive.py | 11 + 4 files changed, 411 insertions(+), 154 deletions(-) diff --git a/src/Mod/CAM/CAMTests/TestPathAdaptive.py b/src/Mod/CAM/CAMTests/TestPathAdaptive.py index 70d72ac086..a544de3553 100644 --- a/src/Mod/CAM/CAMTests/TestPathAdaptive.py +++ b/src/Mod/CAM/CAMTests/TestPathAdaptive.py @@ -463,6 +463,67 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(okAt10 and okAt5 and okAt0, "Path boundaries outside of expected regions") + def test09(self): + """test09() Tests Z stock to leave- with 1mm Z stock to leave, machining + at the top of the model should not touch the top model face""" + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create("Adaptive") + adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) + adaptive.Label = "test09+" + adaptive.Comment = "test09() Verify Z stock is left as requested" + + # Set additional operation properties + setDepthsAndHeights(adaptive, 15, 10) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression("StepDown", None) + adaptive.StepDown.Value = ( + 5.0 # Have to set expression to None before numerical value assignment + ) + # Add some Z stock to leave so we avoid Face3 in this stepdown at Z=10 + adaptive.setExpression("ZStockToLeave", None) + adaptive.ZStockToLeave.Value = 1 + + _addViewProvider(adaptive) + self.doc.recompute() + + # Check: + # - No feed path at depth Z=10 touchs Face3 + toolr = adaptive.OpToolDiameter.Value / 2 + tol = adaptive.Tolerance + + # Make clean up math below- combine tool radius and tolerance into a + # single field that can be added/subtracted to/from bounding boxes + moffset = toolr - tol + + # Offset the face we don't expect to touch, verify no move is within + # that boundary + # NOTE: This isn't a perfect test (won't catch moves that start and end + # outside of our face, but cut through/across it), but combined with + # other tests should be sufficient. + noPathTouchesFace3 = True + foffset = self.doc.Fusion.Shape.getElement("Face3").makeOffset2D(moffset) + # NOTE: Face3 is at Z=10, and the only feed moves will be at Z=10 + lastpt = FreeCAD.Vector(0, 0, 10) + for p in [c.Parameters for c in adaptive.Path.Commands if c.Name in ["G1", "G01"]]: + pt = FreeCAD.Vector(lastpt) + if "X" in p: + pt.x = p.get("X") + if "Y" in p: + pt.x = p.get("Y") + + if foffset.isInside(pt, 0.001, True): + noPathTouchesFace3 = False + break + + lastpt = pt + + self.assertTrue(noPathTouchesFace3, "No feed moves within the top face.") + # Eclass diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui index 08db3a609f..91ae04896c 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui @@ -43,103 +43,19 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised - - - - Use Outline - - - - - - - Keep Tool Down Ratio - - - - - - - Helix Max Diameter - - - - - - - Type of adaptive operation - - - - - - - Cut Region - - - - - - - Step Over Percent - - - - - - - Force Clearing Inside-out - - - - - - - Lift Distance - - - - - - - Stock to Leave - - - - - - - Operation Type - - - - - - - Helix Ramp Angle - - - - - - - Finishing Profile - - - - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -152,7 +68,9 @@ - Influences calculation performance vs stability and accuracy + Influences calculation performance vs stability and accuracy. + +Larger values (further to the right) will calculate faster; smaller values (further to the left) will result in more accurate toolpaths. 5 @@ -167,7 +85,7 @@ 10 - Qt::Horizontal + Qt::Orientation::Horizontal 1 @@ -177,6 +95,13 @@ + + + + Force Clearing Inside-out + + + @@ -184,53 +109,37 @@ - - + + + + Type of adaptive operation + + + + + - Helix Cone Angle - - - - - - - If greater than zero it limits the helix ramp diameter, otherwise 75 percent of tool diameter is used - - - - - - - - - - How much to lift the tool up during the rapid linking moves over cleared regions. If linking path is not clear tool is raised to clearance height. - - - - - - - - - - Max length of keep-tool-down linking path compared to direct distance between points. If exceeded link will be done by raising the tool to clearance height. - - - + Finishing Profile - + - How much material to leave (i.e. for finishing operation) + How much material to leave in the XY plane (i.e. for finishing operation) + + + + XY Stock to Leave + + + @@ -250,13 +159,10 @@ - - - - Angle of the helix ramp entry - - - + + + + Step Over Percent @@ -270,6 +176,128 @@ + + + + Helix Ramp Angle + + + + + + + Use Outline + + + + + + + Operation Type + + + + + + + How much to lift the tool up during the rapid linking moves over cleared regions. If linking path is not clear tool is raised to clearance height. + + + + + + + + + + Keep Tool Down Ratio + + + + + + + If greater than zero it limits the helix ramp diameter, otherwise 75 percent of tool diameter is used + + + + + + + + + + Helix Cone Angle + + + + + + + Angle of the helix ramp entry + + + + + + + + + + Lift Distance + + + + + + + Cut Region + + + + + + + Max length of keep-tool-down linking path compared to direct distance between points. If exceeded link will be done by raising the tool to clearance height. + + + + + + + + + + Helix Max Diameter + + + + + + + After calculating toolpaths, the default cut order is by depth- all regions at a given stepdown are cleared before moving to the next stepdown. + +This option changes that behavior to cut each discrete area to its full depth before moving on to the next. + + + Order cuts by region + + + + + + + Z Stock to Leave + + + + + + + How much material to leave along the Z axis (i.e. for finishing operation) + + + @@ -283,7 +311,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/src/Mod/CAM/Path/Op/Adaptive.py b/src/Mod/CAM/Path/Op/Adaptive.py index 75d3b62aa5..51c7d8b656 100644 --- a/src/Mod/CAM/Path/Op/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Adaptive.py @@ -628,6 +628,8 @@ def Execute(op, obj): { "opType": outsideOpType, "path2d": convertTo2d(rdict["edges"]), + "id": rdict["id"], + "children": rdict["children"], # FIXME: Kinda gross- just use this to match up with the # appropriate stockpaths entry... "startdepth": rdict["depths"][0], @@ -641,6 +643,8 @@ def Execute(op, obj): { "opType": insideOpType, "path2d": convertTo2d(rdict["edges"]), + "id": rdict["id"], + "children": rdict["children"], # FIXME: Kinda gross- just use this to match up with the # appropriate stockpaths entry... "startdepth": rdict["depths"][0], @@ -668,6 +672,8 @@ def Execute(op, obj): "finishingProfile": obj.FinishingProfile, "keepToolDownRatio": keepToolDownRatio, "stockToLeave": obj.StockToLeave.Value, + "zStockToLeave": obj.ZStockToLeave.Value, + "orderCutsByRegion": obj.OrderCutsByRegion, } insideInputStateObject = { @@ -683,6 +689,8 @@ def Execute(op, obj): "finishingProfile": obj.FinishingProfile, "keepToolDownRatio": keepToolDownRatio, "stockToLeave": obj.StockToLeave.Value, + "zStockToLeave": obj.ZStockToLeave.Value, + "orderCutsByRegion": obj.OrderCutsByRegion, } inputStateObject = [outsideInputStateObject, insideInputStateObject] @@ -740,6 +748,7 @@ def Execute(op, obj): a2d.toolDiameter = op.tool.Diameter.Value a2d.helixRampDiameter = helixDiameter a2d.keepToolDownDistRatio = keepToolDownRatio + # NOTE: Z stock is handled in our stepdowns a2d.stockToLeave = obj.StockToLeave.Value a2d.tolerance = obj.Tolerance a2d.forceInsideOut = obj.ForceInsideOut @@ -762,9 +771,25 @@ def Execute(op, obj): for t in alltuples: depths += [d for d in t[0]] depths = sorted(list(set(depths)), reverse=True) - for d in depths: - cutlist += [([d], o[1]) for o in outsidePathArray2dDepthTuples if d in o[0]] - cutlist += [([d], i[1]) for i in insidePathArray2dDepthTuples if d in i[0]] + if obj.OrderCutsByRegion: + # Translate child ID numbers to an actual reference to the + # associated tuple + for rdict in regionOps: + rdict["childTuples"] = [t for t in alltuples if t[1]["id"] in rdict["children"]] + + # Helper function to recurse down children + def addToCutList(tuples): + for k in tuples: + if k in cutlist: + continue + cutlist.append(k) + addToCutList(k[1]["childTuples"]) + + addToCutList(alltuples) + else: + for d in depths: + cutlist += [([d], o[1]) for o in outsidePathArray2dDepthTuples if d in o[0]] + cutlist += [([d], i[1]) for i in insidePathArray2dDepthTuples if d in i[0]] # need to convert results to python object to be JSON serializable stepdown = max(obj.StepDown.Value, _ADAPTIVE_MIN_STEPDOWN) @@ -972,7 +997,9 @@ def _workingEdgeHelperManual(op, obj, depths): lastdepth = depth continue - aboveRefined = _getSolidProjection(shps, depth) + # NOTE: Slice stock lower than cut depth to effectively leave (at least) + # obj.ZStockToLeave + aboveRefined = _getSolidProjection(shps, depth - obj.ZStockToLeave.Value) # Create appropriate tuples and add to list, processing inside/outside # as requested by operation @@ -1079,10 +1106,14 @@ def _getWorkingEdges(op, obj): # Get the stock outline at each stepdown. Used to calculate toolpaths and # for calcuating cut regions in some instances + # NOTE: Slice stock lower than cut depth to effectively leave (at least) + # obj.ZStockToLeave # NOTE: Stock is handled DIFFERENTLY than inside and outside regions! # Combining different depths just adds code to look up the correct outline # when computing inside/outside regions, for no real benefit. - stockProjectionDict = {d: _getSolidProjection(op.stock.Shape, d) for d in depths} + stockProjectionDict = { + d: _getSolidProjection(op.stock.Shape, d - obj.ZStockToLeave.Value) for d in depths + } # If user specified edges, calculate the machining regions based on that # input. Otherwise, process entire model @@ -1092,6 +1123,101 @@ def _getWorkingEdges(op, obj): # to be avoided at those depths. insideRegions, outsideRegions = _workingEdgeHelperManual(op, obj, depths) + # Find all children of each region. A child of region X is any region Y such + # that Y is a subset of X AND Y starts within one stepdown of X (ie, direct + # children only). + # NOTE: Inside and outside regions are inverses of each other, so above + # refers to the area to be machined! + + # Assign an ID number to track each region + idnumber = 0 + for r in insideRegions + outsideRegions: + r["id"] = idnumber + r["children"] = list() + idnumber += 1 + + # NOTE: Inside and outside regions are inverses of each other + # NOTE: Outside regions can't have parents + for rx in insideRegions: + for ry in [k for k in insideRegions if k != rx]: + dist = min(rx["depths"]) - max(ry["depths"]) + # Ignore regions at our level or above, or more than one step down + if dist <= 0 or dist > depthParams.step_down: + continue + if not ry["region"].cut(rx["region"]).Wires: + rx["children"].append(ry["id"]) + # See which outside region this is a child of- basically inverse of above + for ry in [k for k in outsideRegions]: + dist = min(ry["depths"]) - max(rx["depths"]) + # Ignore regions at our level or above, or more than one step down + if dist <= 0 or dist > depthParams.step_down: + continue + # child if there is NO overlap between the stay-outside and stay- + # inside regions + # Also a child if the outer region is NULL (includes everything) + # NOTE: See "isNull() note" at top of file + if not ry["region"].Wires or not rx["region"].common(ry["region"]).Wires: + ry["children"].append(rx["id"]) + + # Further split regions as necessary for when the stock changes- a region as + # reported here is where a toolpath will be generated, and can be projected + # along all of the depths associated with it. By doing this, we can minimize + # the number of toolpaths that need to be generated AND avoid more complex + # logic in depth-first vs region-first sorting of regions. + # NOTE: For internal regions, stock is "the same" if the region cut with + # the stock results in the same region. + # NOTE: For external regions, stock is "the same" if the stock cut by the + # region results in the same region + def _regionChildSplitterHelper(regions, areInsideRegions): + nonlocal stockProjectionDict + nonlocal idnumber + for r in regions: + depths = sorted(r["depths"], reverse=True) + if areInsideRegions: + rcut = r["region"].cut(stockProjectionDict[depths[0]]) + else: + # NOTE: We may end up with empty "outside" regions in the space + # between the top of the stock and the top of the model- want + # to machine the entire stock in that case + # NOTE: See "isNull() note" at top of file + if not r["region"].Wires: + rcut = stockProjectionDict[depths[0]] + else: + rcut = stockProjectionDict[depths[0]].cut(r["region"]) + parentdepths = depths[0:1] + # If the region cut with the stock at a new depth is different than + # the original cut, we need to split this region + # The new region gets all of the children, and becomes a child of + # the existing region. + for d in depths[1:]: + if ( + areInsideRegions and r["region"].cut(stockProjectionDict[d]).cut(rcut).Wires + ) or stockProjectionDict[d].cut(r["region"]).cut(rcut).Wires: + newregion = { + "id": idnumber, + "depths": [k for k in depths if k not in parentdepths], + "region": r["region"], + "children": r["children"], + } + # Update parent with the new region as a child, along with all + # the depths it was unchanged on + r["children"] = [idnumber] + r["depths"] = parentdepths + + # Add the new region to the end of the list and stop processing + # this region + # When the new region is processed at the end, we'll effectively + # recurse and handle splitting that new region if required + regions.append(newregion) + idnumber += 1 + continue + # If we didn't split at this depth, the parent will keep "control" + # of this depth + parentdepths.append(d) + + _regionChildSplitterHelper(insideRegions, True) + _regionChildSplitterHelper(outsideRegions, False) + # Create discretized regions def _createDiscretizedRegions(regionDicts): discretizedRegions = list() @@ -1100,6 +1226,8 @@ def _getWorkingEdges(op, obj): { "edges": [[discretize(w)] for w in rdict["region"].Wires], "depths": rdict["depths"], + "id": rdict["id"], + "children": rdict["children"], } ) return discretizedRegions @@ -1190,11 +1318,6 @@ class PathAdaptive(PathOp.ObjectOp): "Side of selected faces that tool should cut", ), ) - # obj.Side = [ - # "Outside", - # "Inside", - # ] # side of profile that cutter is on in relation to direction of profile - obj.addProperty( "App::PropertyEnumeration", "OperationType", @@ -1204,11 +1327,6 @@ class PathAdaptive(PathOp.ObjectOp): "Type of adaptive operation", ), ) - # obj.OperationType = [ - # "Clearing", - # "Profiling", - # ] # side of profile that cutter is on in relation to direction of profile - obj.addProperty( "App::PropertyFloat", "Tolerance", @@ -1251,7 +1369,16 @@ class PathAdaptive(PathOp.ObjectOp): "Adaptive", QT_TRANSLATE_NOOP( "App::Property", - "How much stock to leave (i.e. for finishing operation)", + "How much stock to leave in the XY plane (eg for finishing operation)", + ), + ) + obj.addProperty( + "App::PropertyDistance", + "ZStockToLeave", + "Adaptive", + QT_TRANSLATE_NOOP( + "App::Property", + "How much stock to leave along the Z axis (eg for finishing operation)", ), ) obj.addProperty( @@ -1279,7 +1406,6 @@ class PathAdaptive(PathOp.ObjectOp): QT_TRANSLATE_NOOP("App::Property", "Stop processing"), ) obj.setEditorMode("Stopped", 2) # hide this property - obj.addProperty( "App::PropertyBool", "StopProcessing", @@ -1290,7 +1416,6 @@ class PathAdaptive(PathOp.ObjectOp): ), ) obj.setEditorMode("StopProcessing", 2) # hide this property - obj.addProperty( "App::PropertyBool", "UseHelixArcs", @@ -1300,7 +1425,6 @@ class PathAdaptive(PathOp.ObjectOp): "Use Arcs (G2) for helix ramp", ), ) - obj.addProperty( "App::PropertyPythonObject", "AdaptiveInputState", @@ -1348,7 +1472,6 @@ class PathAdaptive(PathOp.ObjectOp): "Limit helix entry diameter, if limit larger than tool diameter or 0, tool diameter is used", ), ) - obj.addProperty( "App::PropertyBool", "UseOutline", @@ -1358,7 +1481,15 @@ class PathAdaptive(PathOp.ObjectOp): "Uses the outline of the base geometry.", ), ) - + obj.addProperty( + "App::PropertyBool", + "OrderCutsByRegion", + "Adaptive", + QT_TRANSLATE_NOOP( + "App::Property", + "Orders cuts by region instead of depth.", + ), + ) obj.addProperty( "Part::PropertyPartShape", "removalshape", @@ -1390,9 +1521,11 @@ class PathAdaptive(PathOp.ObjectOp): obj.AdaptiveInputState = "" obj.AdaptiveOutputState = "" obj.StockToLeave = 0 + obj.ZStockToLeave = 0 obj.KeepToolDownRatio = 3.0 obj.UseHelixArcs = False obj.UseOutline = False + obj.OrderCutsByRegion = False FeatureExtensions.set_default_property_values(obj, job) def opExecute(self, obj): @@ -1427,6 +1560,28 @@ class PathAdaptive(PathOp.ObjectOp): "Uses the outline of the base geometry.", ) + if not hasattr(obj, "OrderCutsByRegion"): + obj.addProperty( + "App::PropertyBool", + "OrderCutsByRegion", + "Adaptive", + QT_TRANSLATE_NOOP( + "App::Property", + "Orders cuts by region instead of depth.", + ), + ) + + if not hasattr(obj, "ZStockToLeave"): + obj.addProperty( + "App::PropertyDistance", + "ZStockToLeave", + "Adaptive", + QT_TRANSLATE_NOOP( + "App::Property", + "How much stock to leave along the Z axis (eg for finishing operation)", + ), + ) + if not hasattr(obj, "removalshape"): obj.addProperty("Part::PropertyPartShape", "removalshape", "Path", "") obj.setEditorMode("removalshape", 2) # hide @@ -1446,6 +1601,7 @@ def SetupProperties(): "LiftDistance", "KeepToolDownRatio", "StockToLeave", + "ZStockToLeave", "ForceInsideOut", "FinishingProfile", "Stopped", @@ -1457,6 +1613,7 @@ def SetupProperties(): "HelixConeAngle", "HelixDiameterLimit", "UseOutline", + "OrderCutsByRegion", ] return setup diff --git a/src/Mod/CAM/Path/Op/Gui/Adaptive.py b/src/Mod/CAM/Path/Op/Gui/Adaptive.py index a9ae651faa..c2438dd21c 100644 --- a/src/Mod/CAM/Path/Op/Gui/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Gui/Adaptive.py @@ -50,6 +50,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): ) self.form.KeepToolDownRatio.setProperty("unit", obj.KeepToolDownRatio.getUserPreferred()[2]) self.form.StockToLeave.setProperty("unit", obj.StockToLeave.getUserPreferred()[2]) + self.form.ZStockToLeave.setProperty("unit", obj.ZStockToLeave.getUserPreferred()[2]) def getSignalsForUpdate(self, obj): """getSignalsForUpdate(obj) ... return list of signals for updating obj""" @@ -65,10 +66,12 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): signals.append(self.form.LiftDistance.valueChanged) signals.append(self.form.KeepToolDownRatio.valueChanged) signals.append(self.form.StockToLeave.valueChanged) + signals.append(self.form.ZStockToLeave.valueChanged) signals.append(self.form.coolantController.currentIndexChanged) signals.append(self.form.ForceInsideOut.stateChanged) signals.append(self.form.FinishingProfile.stateChanged) signals.append(self.form.useOutline.stateChanged) + signals.append(self.form.orderCutsByRegion.stateChanged) signals.append(self.form.StopButton.toggled) return signals @@ -97,9 +100,13 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if hasattr(obj, "StockToLeave"): self.form.StockToLeave.setProperty("rawValue", obj.StockToLeave.Value) + if hasattr(obj, "ZStockToLeave"): + self.form.ZStockToLeave.setProperty("rawValue", obj.ZStockToLeave.Value) + self.form.ForceInsideOut.setChecked(obj.ForceInsideOut) self.form.FinishingProfile.setChecked(obj.FinishingProfile) self.form.useOutline.setChecked(obj.UseOutline) + self.form.orderCutsByRegion.setChecked(obj.OrderCutsByRegion) self.setupToolController(obj, self.form.ToolController) self.setupCoolant(obj, self.form.coolantController) self.form.StopButton.setChecked(obj.Stopped) @@ -130,9 +137,13 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if hasattr(obj, "StockToLeave"): PathGuiUtil.updateInputField(obj, "StockToLeave", self.form.StockToLeave) + if hasattr(obj, "ZStockToLeave"): + PathGuiUtil.updateInputField(obj, "ZStockToLeave", self.form.ZStockToLeave) + obj.ForceInsideOut = self.form.ForceInsideOut.isChecked() obj.FinishingProfile = self.form.FinishingProfile.isChecked() obj.UseOutline = self.form.useOutline.isChecked() + obj.OrderCutsByRegion = self.form.orderCutsByRegion.isChecked() obj.Stopped = self.form.StopButton.isChecked() if obj.Stopped: self.form.StopButton.setChecked(False) # reset the button From 1c27258e086a8d4e95f109f7c3f88ff953231cc0 Mon Sep 17 00:00:00 2001 From: Dan Taylor Date: Wed, 2 Apr 2025 20:55:21 -0500 Subject: [PATCH 127/316] CAM: Adaptive: Machine entire model if no faces/edges are selected ("adaptive roughing") --- src/Mod/CAM/CAMTests/TestPathAdaptive.py | 157 +++++++++++++++++++++++ src/Mod/CAM/Path/Op/Adaptive.py | 154 ++++++++++++++++++++-- 2 files changed, 300 insertions(+), 11 deletions(-) diff --git a/src/Mod/CAM/CAMTests/TestPathAdaptive.py b/src/Mod/CAM/CAMTests/TestPathAdaptive.py index a544de3553..c328296980 100644 --- a/src/Mod/CAM/CAMTests/TestPathAdaptive.py +++ b/src/Mod/CAM/CAMTests/TestPathAdaptive.py @@ -524,6 +524,163 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(noPathTouchesFace3, "No feed moves within the top face.") + def test10(self): + """test10() Tests full roughing- should machine entire model with no inputs""" + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create("Adaptive") + adaptive.Base = [(self.doc.Fusion, [])] # (base, subs_list) + adaptive.Label = "test10+" + adaptive.Comment = "test10() Verify path generated with no subs roughs entire model" + + # Set additional operation properties + setDepthsAndHeights(adaptive, 15, 0) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression("StepDown", None) + adaptive.StepDown.Value = ( + 5.0 # Have to set expression to None before numerical value assignment + ) + + _addViewProvider(adaptive) + self.doc.recompute() + + # Check: + # - Bounding box at Z=0 goes outside the model box + tool diameter + # (has to profile the model) + # - Bounding box at Z=5 should go past the model in -X, but only up to the + # stock edges in +X and Y + # - Bounding box at Z=10 goes to at least stock bounding box edges, + # minus tool diameter (has to machine the entire top of the stock off) + # - [Should maybe check] At least one move Z = [10,5] is within the model + # - [Should maybe check] No moves at Z = 0 are within the model + + paths = [c for c in adaptive.Path.Commands if c.Name in ["G0", "G00", "G1", "G01"]] + toolr = adaptive.OpToolDiameter.Value / 2 + tol = adaptive.Tolerance + + # Make clean up math below- combine tool radius and tolerance into a + # single field that can be added/subtracted to/from bounding boxes + moffset = toolr - tol + + zDict = {10: None, 5: None, 0: None} + + getPathBoundaries(paths, zDict) + mbb = self.doc.Fusion.Shape.BoundBox + sbb = adaptive.Document.Stock.Shape.BoundBox + + okAt10 = ( + zDict[10] is not None + and zDict[10]["min"][0] <= sbb.XMin + moffset + and zDict[10]["min"][1] <= sbb.YMin + moffset + and zDict[10]["max"][0] >= sbb.XMax - moffset + and zDict[10]["max"][1] >= sbb.YMax - moffset + ) + + okAt5 = ( + zDict[5] is not None + and zDict[5]["min"][0] <= mbb.XMin - moffset + and zDict[5]["min"][1] <= sbb.YMin + moffset + and zDict[5]["max"][0] >= sbb.XMax - moffset + and zDict[5]["max"][1] >= sbb.YMax - moffset + ) + + okAt0 = ( + zDict[0] is not None + and zDict[0]["min"][0] <= mbb.XMin - moffset + and zDict[0]["min"][1] <= mbb.YMin - moffset + and zDict[0]["max"][0] >= mbb.XMax + moffset + and zDict[0]["max"][1] >= mbb.YMax + moffset + ) + + self.assertTrue( + okAt10 and okAt5 and okAt0, "Path boundaries don't include expected regions" + ) + + def test11(self): + """test11() Tests stock handling- should rough full model, but not cut + air excessively where there's not stock""" + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create("Adaptive") + adaptive.Base = [(self.doc.Fusion, [])] # (base, subs_list) + adaptive.Label = "test11+" + adaptive.Comment = "test11() Verify machining region is limited to the stock" + + # Set additional operation properties + setDepthsAndHeights(adaptive, 15, 5) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression("StepDown", None) + adaptive.StepDown.Value = ( + 5.0 # Have to set expression to None before numerical value assignment + ) + + # Create and assign new stock that will create different bounds at + # different stepdowns + btall = Part.makeBox(17, 27, 11, FreeCAD.Vector(-1, -1, 0)) + bshort = Part.makeBox(42, 27, 6, FreeCAD.Vector(-1, -1, 0)) + adaptive.Document.Job.Stock.Shape = btall.fuse(bshort) + + _addViewProvider(adaptive) + # NOTE: Do NOT recompute entire doc, which will undo our stock change! + adaptive.recompute() + + # Check: + # - Bounding box at Z=10 stays basically above "btall" + # - Bounding box at Z=5 and Z=0 are outside of stock + + paths = [c for c in adaptive.Path.Commands if c.Name in ["G1", "G01"]] + toolr = adaptive.OpToolDiameter.Value / 2 + tol = adaptive.Tolerance + + # Make clean up math below- combine tool radius and tolerance into a + # single field that can be added/subtracted to/from bounding boxes + # NOTE: ADD tol here, since we're effectively flipping our normal + # comparison and want tolerance to make our check looser + moffset = toolr + tol + + zDict = {10: None, 5: None} + + getPathBoundaries(paths, zDict) + sbb = adaptive.Document.Stock.Shape.BoundBox + sbb10 = btall.BoundBox + + # These should be no more than a tool radius outside of the "btall" + # XY section of the stock + okAt10 = ( + zDict[10] is not None + and zDict[10]["min"][0] >= sbb10.XMin - moffset + and zDict[10]["min"][1] >= sbb10.YMin - moffset + and zDict[10]["max"][0] <= sbb10.XMax + moffset + and zDict[10]["max"][1] <= sbb10.YMax + moffset + ) + + # These should be no more than a tool radius outside of the overall + # stock bounding box + okAt5 = ( + zDict[5] is not None + and zDict[5]["min"][0] >= sbb.XMin - moffset + and zDict[5]["min"][1] >= sbb.YMin - moffset + and zDict[5]["max"][0] <= sbb.XMax + moffset + and zDict[5]["max"][1] <= sbb.YMax + moffset + ) + + self.assertTrue(okAt10 and okAt5, "Path feeds extend excessively in +X") + + # POSSIBLY MISSING TESTS: + # - Something for region ordering + # - Known-edge cases: cones/spheres/cylinders (especially partials on edges + # of model + strange angles- especially for cylinders) + # - Multiple models/stock + # - XY stock to leave + # Eclass diff --git a/src/Mod/CAM/Path/Op/Adaptive.py b/src/Mod/CAM/Path/Op/Adaptive.py index 51c7d8b656..6aa2118d31 100644 --- a/src/Mod/CAM/Path/Op/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Adaptive.py @@ -22,6 +22,12 @@ # * * # *************************************************************************** +# NOTE: "isNull() note" +# After performing cut operations, checking the resulting shape.isNull() will +# sometimes return False even when the resulting shape is infinitesimal and +# further operations with it will raise exceptions. Instead checking if the +# shape.Wires list is non-empty bypasses this issue. + import Path import Path.Op.Base as PathOp import PathScripts.PathUtils as PathUtils @@ -759,7 +765,8 @@ def Execute(op, obj): stockPaths[rdict["startdepth"]], path2d, progressFn ) - # Create list of regions to cut, in an order they can be cut in + # Sort regions to cut by either depth or area. + # TODO: Bonus points for ordering to minimize rapids cutlist = list() # Region IDs that have been cut already cutids = list() @@ -924,6 +931,131 @@ def _getSolidProjection(shp, z): return projectFacesToXY(faces) +def _workingEdgeHelperRoughing(op, obj, depths): + # Final calculated regions- list of dicts with entries: + # "region" - actual shape + # "depths" - list of depths this region applies to + insideRegions = list() + outsideRegions = list() + + # Multiple input solids can be selected- make a single part out of them, + # will process each solid separately as appropriate + shps = op.model[0].Shape.fuse([k.Shape for k in op.model[1:]]) + + projdir = FreeCAD.Vector(0, 0, 1) + + # Take outline of entire model as our baseline machining region. No need to + # do this repeatedly inside the loop. + modelOutlineFaces = [ + Part.makeFace(TechDraw.findShapeOutline(s, 1, projdir)) for s in shps.Solids + ] + + lastdepth = obj.StartDepth.Value + + for depth in depths: + # If we have no stock to machine, just skip all the rest of the math + if depth >= op.stock.Shape.BoundBox.ZMax: + lastdepth = depth + continue + + # NOTE: To "leave" stock along Z without actually checking any face + # depths, we simply slice the model "lower" than our actual cut depth by + # the Z stock to leave, which ensures we stay at least that far from the + # actual faces + stockface = _getSolidProjection(op.stock.Shape, depth - obj.ZStockToLeave.Value) + aboveRefined = _getSolidProjection(shps, depth - obj.ZStockToLeave.Value) + + # Outside is based on the outer wire of the above_faces + # Insides are based on the remaining "below" regions, masked by the + # "above"- if something is above an area, we can't machine it in 2.5D + + # OUTSIDE REGIONS + # Outside: Take the outer wire of the above faces + # NOTE: Exactly one entry per depth (not necessarily one depth entry per + # stepdown, however), which is a LIST of the wires we're staying outside + # NOTE: Do this FIRST- if any inside regions share enough of an edge + # with an outside region for a tool to get through, we want to skip them + # for the current stepdown + if aboveModelFaces := [ + Part.makeFace(TechDraw.findShapeOutline(f, 1, projdir)) for f in aboveRefined.Faces + ]: + aboveModelFaces = aboveModelFaces[0].fuse(aboveModelFaces[1:]) + else: + aboveModelFaces = Part.Shape() + # If this region exists in our list, it has to be the last entry, due to + # proceeding in order and having only one per depth. If it's already + # there, replace with the new, deeper depth, else add new + # NOTE: Check for NULL regions to not barf on regions between the top of + # the model and the top of the stock, which are "outside" of nothing + # NOTE: See "isNull() note" at top of file + if ( + outsideRegions + and outsideRegions[-1]["region"].Wires + and aboveModelFaces.Wires + and not aboveModelFaces.cut(outsideRegions[-1]["region"]).Wires + ): + outsideRegions[-1]["depths"].append(depth) + else: + outsideRegions.append({"region": aboveModelFaces, "depths": [depth]}) + + # NOTE: If you don't care about controlling depth vs region ordering, + # you can actually just do everything with "outside" processing, if you + # don't remove internal holes from the regions above + + # INSIDE REGIONS + # NOTE: Nothing inside if there's no model above us + # NOTE: See "isNull() note" at top of file + if aboveModelFaces.Wires: + # Remove any overlapping areas already machined from the outside. + outsideface = stockface.cut(outsideRegions[-1]["region"].Faces) + # NOTE: See "isNull() note" at top of file + if outsideface.Wires: + belowFaces = [f.cut(outsideface) for f in modelOutlineFaces] + else: + # NOTE: Doesn't matter here, but ensure we're making a new list so + # we don't clobber modelOutlineFaces + belowFaces = [f for f in modelOutlineFaces] + + # This isn't really necessary unless the user inputs bad data- eg, a + # min depth above the top of the model. In which case we still want to + # clear the stock + if belowFaces: + # Remove the overhangs from the desired region to cut + belowCut = belowFaces[0].fuse(belowFaces[1:]).cut(aboveRefined) + # NOTE: See "isNull() note" at top of file + if belowCut.Wires: + # removeSplitter fixes occasional concatenate issues for + # some face orders + finalCut = DraftGeomUtils.concatenate(belowCut.removeSplitter()) + else: + finalCut = Part.Shape() + else: + # Make a dummy shape if we don't have anything actually below + finalCut = Part.Shape() + + # Split up into individual faces if any are disjoint, then update + # insideRegions- either by adding a new entry OR by updating the depth + # of an existing entry + for f in finalCut.Faces: + addNew = True + # Brute-force search all existing regions to see if any are the same + newtop = lastdepth + for rdict in insideRegions: + # FIXME: Smarter way to do this than a full cut operation? + if not rdict["region"].cut(f).Wires: + rdict["depths"].append(depth) + addNew = False + break + if addNew: + insideRegions.append({"region": f, "depths": [depth]}) + + # Update the last depth step + lastdepth = depth + # end for depth + + return insideRegions, outsideRegions + + def _workingEdgeHelperManual(op, obj, depths): # Final calculated regions- list of dicts with entries: # "region" - actual shape @@ -984,7 +1116,7 @@ def _workingEdgeHelperManual(op, obj, depths): selectedRefined = projectFacesToXY(selectedRegions + edgefaces) # If the user selected only faces that don't have an XY projection AND no - # edges, give a useful error + # edges, give a useful message if not selectedRefined.Wires: Path.Log.warning("Selected faces/wires have no projection on the XY plane") return insideRegions, outsideRegions @@ -997,8 +1129,8 @@ def _workingEdgeHelperManual(op, obj, depths): lastdepth = depth continue - # NOTE: Slice stock lower than cut depth to effectively leave (at least) - # obj.ZStockToLeave + # NOTE: See note in _workingEdgeHelperRoughing- tl;dr slice stock + # lower than cut depth to effectively leave (at least) obj.ZStockToLeave aboveRefined = _getSolidProjection(shps, depth - obj.ZStockToLeave.Value) # Create appropriate tuples and add to list, processing inside/outside @@ -1106,8 +1238,8 @@ def _getWorkingEdges(op, obj): # Get the stock outline at each stepdown. Used to calculate toolpaths and # for calcuating cut regions in some instances - # NOTE: Slice stock lower than cut depth to effectively leave (at least) - # obj.ZStockToLeave + # NOTE: See note in _workingEdgeHelperRoughing- tl;dr slice stock lower + # than cut depth to effectively leave (at least) obj.ZStockToLeave # NOTE: Stock is handled DIFFERENTLY than inside and outside regions! # Combining different depths just adds code to look up the correct outline # when computing inside/outside regions, for no real benefit. @@ -1121,7 +1253,10 @@ def _getWorkingEdges(op, obj): # a list of Z depths that the region applies to # Inside regions are a single face; outside regions consist of ALL geometry # to be avoided at those depths. - insideRegions, outsideRegions = _workingEdgeHelperManual(op, obj, depths) + if obj.Base: + insideRegions, outsideRegions = _workingEdgeHelperManual(op, obj, depths) + else: + insideRegions, outsideRegions = _workingEdgeHelperRoughing(op, obj, depths) # Find all children of each region. A child of region X is any region Y such # that Y is a subset of X AND Y starts within one stepdown of X (ie, direct @@ -1333,7 +1468,7 @@ class PathAdaptive(PathOp.ObjectOp): "Adaptive", QT_TRANSLATE_NOOP( "App::Property", - "Influences accuracy and performance", + "Influences calculation performance vs stability and accuracy.\n\nLarger values (further to the right) will calculate faster; smaller values (further to the left) will result in more accurate toolpaths.", ), ) obj.addProperty( @@ -1589,9 +1724,6 @@ class PathAdaptive(PathOp.ObjectOp): FeatureExtensions.initialize_properties(obj) -# Eclass - - def SetupProperties(): setup = [ "Side", From 5ed1435dd0bb76839c510fd618e4f9f4efa9e891 Mon Sep 17 00:00:00 2001 From: Dan Taylor Date: Wed, 2 Apr 2025 20:55:51 -0500 Subject: [PATCH 128/316] CAM: Adaptive: Rename tests with descriptive names; remove empty dummy test; minor test cleanups/comments/clarifications --- src/Mod/CAM/CAMTests/TestPathAdaptive.py | 133 ++++++++++++----------- 1 file changed, 72 insertions(+), 61 deletions(-) diff --git a/src/Mod/CAM/CAMTests/TestPathAdaptive.py b/src/Mod/CAM/CAMTests/TestPathAdaptive.py index c328296980..62c8fef05b 100644 --- a/src/Mod/CAM/CAMTests/TestPathAdaptive.py +++ b/src/Mod/CAM/CAMTests/TestPathAdaptive.py @@ -101,18 +101,14 @@ class TestPathAdaptive(PathTestBase): pass # Unit tests - def test00(self): - """test00() Empty test.""" - return - - def test01(self): - """test01() Verify path generated on Face3.""" + def testFaceSingleSimple(self): + """testFaceSingleSimple() Verify path generated on Face3.""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, ["Face3"])] # (base, subs_list) - adaptive.Label = "test01+" - adaptive.Comment = "test01() Verify path generated on Face3." + adaptive.Label = "testFaceSingleSimple+" + adaptive.Comment = "testFaceSingleSimple() Verify path generated on Face3." # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -138,14 +134,15 @@ class TestPathAdaptive(PathTestBase): # "expected_moves_test01: {}\noperationMoves: {}".format(expected_moves_test01, operationMoves)) self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") - def test02(self): - """test02() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different.""" + def testFacesMergedDifferentZ(self): + """testFacesMergedDifferentZ() Verify path generated on adjacent, combined + Face3 and Face10. The Z heights are different.""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) - adaptive.Label = "test02+" - adaptive.Comment = "test02() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different." + adaptive.Label = "testFacesMergedDifferentZ+" + adaptive.Comment = "testFacesMergedDifferentZ() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different. UseOutline = False" # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -165,14 +162,15 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") - def test03(self): - """test03() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different.""" + def testFacesMergedDifferentZUseOutline(self): + """testFacesMergedDifferentZUseOutline() Verify path generated on adjacent, combined Face3 and Face10. + The Z heights are different.""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) - adaptive.Label = "test03+" - adaptive.Comment = "test03() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different." + adaptive.Label = "testFacesMergedDifferentZUseOutline+" + adaptive.Comment = "testFacesMergedDifferentZUseOutline() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different. UseOutline = True." # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -192,8 +190,8 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") - def test04(self): - """test04() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".""" + def testOutlineDifferentZDiscontinuousEdges(self): + """testOutlineDifferentZDiscontinuous() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") @@ -212,8 +210,8 @@ class TestPathAdaptive(PathTestBase): ], ) ] # (base, subs_list) - adaptive.Label = "test04+" - adaptive.Comment = 'test04() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".' + adaptive.Label = "testOutlineDifferentZDiscontinuous+" + adaptive.Comment = 'testOutlineDifferentZDiscontinuous() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".' # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -233,7 +231,7 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") - def test05(self): + def testOutlineDifferentZContinuousEdges(self): """test05() Verify path generated closed wire with differing Z-heights: "Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".""" # Instantiate a Adaptive operation and set Base Geometry @@ -255,8 +253,8 @@ class TestPathAdaptive(PathTestBase): ], ) ] # (base, subs_list) - adaptive.Label = "test05+" - adaptive.Comment = 'test05() Verify path generated closed wire with differing Z-heights: "Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".' + adaptive.Label = "testOutlineDifferentZContinuous+" + adaptive.Comment = 'testOutlineDifferentZContinuous() Verify path generated closed wire with differing Z-heights: "Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".' # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -276,8 +274,8 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") - def test06(self): - """test06() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".""" + def testOutlineWithCutout(self): + """testOutlineWithCutout() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") @@ -298,8 +296,8 @@ class TestPathAdaptive(PathTestBase): ], ) ] # (base, subs_list) - adaptive.Label = "test06+" - adaptive.Comment = 'test06() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".' + adaptive.Label = "testOutlineWithCutout+" + adaptive.Comment = 'testOutlineWithCutout() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".' # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -335,14 +333,14 @@ class TestPathAdaptive(PathTestBase): break self.assertFalse(isInBox, "Paths originating within the inner hole.") - def test07(self): - """test07() Verify path generated on donut-shaped Face10.""" + def testFaceWithCutout(self): + """testFaceWithCutout() Verify path generated on donut-shaped Face10.""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, ["Face10"])] # (base, subs_list) - adaptive.Label = "test07+" - adaptive.Comment = "test07() Verify path generated on donut-shaped Face10." + adaptive.Label = "testFaceWithCutout+" + adaptive.Comment = "testFaceWithCutout() Verify path generated on donut-shaped Face10." # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -396,14 +394,14 @@ class TestPathAdaptive(PathTestBase): break self.assertTrue(isInBox, "No paths originating within the inner hole.") - def test08(self): - """test08() Tests stock awareness- avoids cutting into the model regardless + def testModelStockAwareness(self): + """testModelStockAwareness() Tests stock awareness- avoids cutting into the model regardless of bounding box selected.""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) - adaptive.Label = "test08+" - adaptive.Comment = "test08() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different. Result should be the combination at Z=10 (faces from (0,0) to (40,25), minus tool radius), and only the lower face at Z=5: (15,0) to (40,25)." + adaptive.Label = "testModelStockAwareness+" + adaptive.Comment = "testModelStockAwareness() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different. Result should be the combination at Z=10 (faces from (0,0) to (40,25), minus tool radius), and only the lower face at Z=5: (15,0) to (40,25)." # Set additional operation properties setDepthsAndHeights(adaptive, 15, 0) @@ -417,6 +415,10 @@ class TestPathAdaptive(PathTestBase): adaptive.StepDown.Value = ( 5.0 # Have to set expression to None before numerical value assignment ) + # Don't use helix entry- ensures helix moves are counted in the path + # boundary calculation. This should be unnecessary, as the helices are + # grown out of the cut area, and thus must be inside of it. + adaptive.UseHelixArcs = False _addViewProvider(adaptive) self.doc.recompute() @@ -435,9 +437,7 @@ class TestPathAdaptive(PathTestBase): # single field that can be added/subtracted to/from bounding boxes moffset = toolr - tol - zDict = {10: None, 5: None, 0: None} - - getPathBoundaries(paths, zDict) + zDict = getPathBoundaries(paths, [10, 5, 0]) # NOTE: Face3 is at Z=10, Face10 is at Z=5 bbf3 = self.doc.Fusion.Shape.getElement("Face3").BoundBox @@ -463,14 +463,14 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(okAt10 and okAt5 and okAt0, "Path boundaries outside of expected regions") - def test09(self): - """test09() Tests Z stock to leave- with 1mm Z stock to leave, machining + def testZStockToLeave(self): + """testZStockToLeave() Tests Z stock to leave- with 1mm Z stock to leave, machining at the top of the model should not touch the top model face""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) - adaptive.Label = "test09+" - adaptive.Comment = "test09() Verify Z stock is left as requested" + adaptive.Label = "testZStockToLeave+" + adaptive.Comment = "testZStockToLeave() Verify Z stock is left as requested" # Set additional operation properties setDepthsAndHeights(adaptive, 15, 10) @@ -524,13 +524,15 @@ class TestPathAdaptive(PathTestBase): self.assertTrue(noPathTouchesFace3, "No feed moves within the top face.") - def test10(self): - """test10() Tests full roughing- should machine entire model with no inputs""" + def testFullModelAdaptiveRoughing(self): + """testFullModelAdaptiveRoughing() Tests full roughing- should machine entire model with no inputs""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, [])] # (base, subs_list) - adaptive.Label = "test10+" - adaptive.Comment = "test10() Verify path generated with no subs roughs entire model" + adaptive.Label = "testFullModelAdaptiveRoughing+" + adaptive.Comment = ( + "testFullModelAdaptiveRoughing() Verify path generated with no subs roughs entire model" + ) # Set additional operation properties setDepthsAndHeights(adaptive, 15, 0) @@ -544,6 +546,10 @@ class TestPathAdaptive(PathTestBase): adaptive.StepDown.Value = ( 5.0 # Have to set expression to None before numerical value assignment ) + # Don't use helix entry- ensures helix moves are counted in the path + # boundary calculation. This should be unnecessary, as the helices are + # grown out of the cut area, and thus must be inside of it. + adaptive.UseHelixArcs = False _addViewProvider(adaptive) self.doc.recompute() @@ -566,9 +572,7 @@ class TestPathAdaptive(PathTestBase): # single field that can be added/subtracted to/from bounding boxes moffset = toolr - tol - zDict = {10: None, 5: None, 0: None} - - getPathBoundaries(paths, zDict) + zDict = getPathBoundaries(paths, [10, 5, 0]) mbb = self.doc.Fusion.Shape.BoundBox sbb = adaptive.Document.Stock.Shape.BoundBox @@ -600,14 +604,16 @@ class TestPathAdaptive(PathTestBase): okAt10 and okAt5 and okAt0, "Path boundaries don't include expected regions" ) - def test11(self): - """test11() Tests stock handling- should rough full model, but not cut + def testStockLimitsAwareness(self): + """testStockLimitsAwareness() Tests stock handling- should rough full model, but not cut air excessively where there's not stock""" # Instantiate a Adaptive operation and set Base Geometry adaptive = PathAdaptive.Create("Adaptive") adaptive.Base = [(self.doc.Fusion, [])] # (base, subs_list) - adaptive.Label = "test11+" - adaptive.Comment = "test11() Verify machining region is limited to the stock" + adaptive.Label = "testStockLimitsAwareness+" + adaptive.Comment = ( + "testStockLimitsAwareness() Verify machining region is limited to the stock" + ) # Set additional operation properties setDepthsAndHeights(adaptive, 15, 5) @@ -621,6 +627,10 @@ class TestPathAdaptive(PathTestBase): adaptive.StepDown.Value = ( 5.0 # Have to set expression to None before numerical value assignment ) + # Don't use helix entry- ensures helix moves are counted in the path + # boundary calculation. This should be unnecessary, as the helices are + # grown out of the cut area, and thus must be inside of it. + adaptive.UseHelixArcs = False # Create and assign new stock that will create different bounds at # different stepdowns @@ -646,9 +656,7 @@ class TestPathAdaptive(PathTestBase): # comparison and want tolerance to make our check looser moffset = toolr + tol - zDict = {10: None, 5: None} - - getPathBoundaries(paths, zDict) + zDict = getPathBoundaries(paths, [10, 5]) sbb = adaptive.Document.Stock.Shape.BoundBox sbb10 = btall.BoundBox @@ -685,10 +693,10 @@ class TestPathAdaptive(PathTestBase): # Eclass -def getPathBoundaries(paths, zDict): - """getPathBoundaries(paths, zDict): Takes the list of paths and dictionary - of Z depths of interest, and finds the bounding box of the paths at each - depth. +def getPathBoundaries(paths, zLevels): + """getPathBoundaries(paths, zLevels): Takes the list of paths and list of Z + depths of interest, and finds the bounding box of the paths at each depth. + A dictionary of depth: {"min": (x,y), "max": (x,y)} entries is returned. NOTE: You'd think that using Path.BoundBox would give us what we want, but... no, for whatever reason it appears to always extend to (0,0,0) @@ -705,7 +713,8 @@ def getPathBoundaries(paths, zDict): p.Y = last.y p.Z = last.z - for z in zDict: + zDict = {} + for z in zLevels: zpaths = [k for k in paths if k.Z == z] if not zpaths: zDict[z] = None @@ -716,6 +725,8 @@ def getPathBoundaries(paths, zDict): ymax = max([k.Y for k in zpaths]) zDict[z] = {"min": (xmin, ymin), "max": (xmax, ymax)} + return zDict + def setDepthsAndHeights(op, strDep=20.0, finDep=0.0): """setDepthsAndHeights(op, strDep=20.0, finDep=0.0)... Sets default depths and heights for `op` passed to it""" From c78e8ae4ceccd78cdcfc21a3a78e041bd4839a86 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Thu, 3 Apr 2025 05:07:52 +0200 Subject: [PATCH 129/316] MOD: OPENSCAD clean (#20558) clean code --- src/Mod/OpenSCAD/InitGui.py | 3 +-- src/Mod/OpenSCAD/OpenSCADCommands.py | 3 +-- src/Mod/OpenSCAD/OpenSCADUtils.py | 3 +-- src/Mod/OpenSCAD/colorcodeshapes.py | 6 ++---- src/Mod/OpenSCAD/expandplacements.py | 3 --- src/Mod/OpenSCAD/exportCSG.py | 1 - src/Mod/OpenSCAD/importCSG.py | 2 -- src/Mod/OpenSCAD/prototype.py | 20 +------------------- 8 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/Mod/OpenSCAD/InitGui.py b/src/Mod/OpenSCAD/InitGui.py index 396227c1e8..28f701dece 100644 --- a/src/Mod/OpenSCAD/InitGui.py +++ b/src/Mod/OpenSCAD/InitGui.py @@ -155,8 +155,7 @@ class OpenSCADWorkbench(Workbench): self.appendToolbar( QT_TRANSLATE_NOOP("Workbench", "Frequently-used Part WB tools"), parttoolbarcommands ) - # self.appendMenu('OpenSCAD',["AddOpenSCADElement"]) - ###self.appendCommandbar("&Generic Tools",["ColorCodeShape"]) + FreeCADGui.addIconPath(":/icons") FreeCADGui.addLanguagePath(":/translations") FreeCADGui.addPreferencePage(":/ui/openscadprefs-base.ui", "OpenSCAD") diff --git a/src/Mod/OpenSCAD/OpenSCADCommands.py b/src/Mod/OpenSCAD/OpenSCADCommands.py index 10b45d5f04..6cc3513adc 100644 --- a/src/Mod/OpenSCAD/OpenSCADCommands.py +++ b/src/Mod/OpenSCAD/OpenSCADCommands.py @@ -323,8 +323,7 @@ class AddSCADWidget(QtGui.QWidget): # Main text area self.textEdit=QtGui.QTextEdit() self.textEdit.setAcceptRichText(False) - #print(self.textEdit.maximumHeight()) - #print(self.textEdit.maximumViewportSize()) + # Message Area self.textMsg=QtGui.QPlainTextEdit() self.textMsg.setReadOnly(True) diff --git a/src/Mod/OpenSCAD/OpenSCADUtils.py b/src/Mod/OpenSCAD/OpenSCADUtils.py index f2652f0b75..9f01c5a822 100644 --- a/src/Mod/OpenSCAD/OpenSCADUtils.py +++ b/src/Mod/OpenSCAD/OpenSCADUtils.py @@ -53,8 +53,7 @@ except (ImportError, AttributeError): class OpenSCADError(BaseError): def __init__(self, value): self.value = value - #def __repr__(self): - # return self.msg + def __str__(self): return repr(self.value) diff --git a/src/Mod/OpenSCAD/colorcodeshapes.py b/src/Mod/OpenSCAD/colorcodeshapes.py index c63bb251eb..6d1f1b802b 100644 --- a/src/Mod/OpenSCAD/colorcodeshapes.py +++ b/src/Mod/OpenSCAD/colorcodeshapes.py @@ -45,7 +45,7 @@ def mostbasiccompound(comp): wires = shapeset(comp.Wires) edges = shapeset(comp.Edges) vertexes = shapeset(comp.Vertexes) - #FreeCAD.Console.PrintMessage('%s\n' % (str((len(solids),len(shells),len(faces),len(wires),len(edges),len(vertexes))))) + for shape in comp.Solids: shells -= shapeset(shape.Shells) faces -= shapeset(shape.Faces) @@ -66,8 +66,7 @@ def mostbasiccompound(comp): vertexes -= shapeset(shape.Vertexes) for shape in comp.Edges: vertexes -= shapeset(shape.Vertexes) - #FreeCAD.Console.PrintMessage('%s\n' % (str((len(solids),len(shells),len(faces),len(wires),len(edges),len(vertexes))))) - #return len(solids),len(shells),len(faces),len(wires),len(edges),len(vertexes) + if vertexes: return "Vertex" elif edges: @@ -110,4 +109,3 @@ def colorcodeshapes(objs): except Exception: raise -#colorcodeshapes(App.ActiveDocument.Objects) diff --git a/src/Mod/OpenSCAD/expandplacements.py b/src/Mod/OpenSCAD/expandplacements.py index 891ae4e494..5c86610536 100644 --- a/src/Mod/OpenSCAD/expandplacements.py +++ b/src/Mod/OpenSCAD/expandplacements.py @@ -58,7 +58,6 @@ def expandplacementsmatrix(obj,matrix): replaceobj.replaceobj(parent, obj, obj.Base) out.Document.removeObject(obj.Name) elif likeprimitive(obj, True): - #if isspecialorthogonalpython(fcsubmatrix(ownmatrix)): if isspecialorthogonal(ownmatrix): obj.Placement = FreeCAD.Placement() #this should never happen unless matrices cancel out @@ -93,7 +92,6 @@ def expandplacementsmatrix(obj,matrix): def expandplacements(obj,placement): ownplacement = placement.multiply(obj.Placement) if obj.isDerivedFrom('Part::FeaturePython') and isinstance(obj.Proxy, MatrixTransform): - #expandplacementsmatrix(obj,ownplacement.toMatrix()) expandplacementsmatrix(obj,placement.toMatrix()) elif likeprimitive(obj, False): obj.Placement = ownplacement @@ -110,7 +108,6 @@ def expandplacements(obj,placement): obj.Dir = ownplacement.Rotation.multVec(obj.Dir) elif obj.isDerivedFrom('Part::Revolution'): obj.Axis = ownplacement.Rotation.multVec(obj.Axis) - #obj.Base=ownplacement.Rotation.multVec(obj.Base) expandplacements(outobj, ownplacement) obj.Placement = FreeCAD.Placement() diff --git a/src/Mod/OpenSCAD/exportCSG.py b/src/Mod/OpenSCAD/exportCSG.py index cc4ea2e455..8b538ece28 100644 --- a/src/Mod/OpenSCAD/exportCSG.py +++ b/src/Mod/OpenSCAD/exportCSG.py @@ -145,7 +145,6 @@ def process_object(csg,ob): elif ob.TypeId == "Part::Prism": import math f = str(ob.Polygon) -# r = str(ob.Length/2.0/math.sin(math.pi/ob.Polygon)) r = str(ob.Circumradius) # length seems to be the outer radius h = str(ob.Height.Value) mm = check_multmatrix(csg, ob, 0, 0, -float(h)/2) diff --git a/src/Mod/OpenSCAD/importCSG.py b/src/Mod/OpenSCAD/importCSG.py index 8ed53b1ea2..bdf89bd809 100644 --- a/src/Mod/OpenSCAD/importCSG.py +++ b/src/Mod/OpenSCAD/importCSG.py @@ -780,8 +780,6 @@ def process_linear_extrude_with_transform(base,height,twist,scale) : ViewProviderTree(newobj.ViewObject) else: newobj.ViewObject.Proxy = 0 - #import ViewProviderTree from OpenSCADFeatures - #ViewProviderTree(obj.ViewObject) return newobj def p_linear_extrude_with_transform(p): diff --git a/src/Mod/OpenSCAD/prototype.py b/src/Mod/OpenSCAD/prototype.py index 1d38949abe..4e23a804ef 100644 --- a/src/Mod/OpenSCAD/prototype.py +++ b/src/Mod/OpenSCAD/prototype.py @@ -24,7 +24,6 @@ def openscadmesh(doc, scadstr, objname): import OpenSCADUtils tmpfilename = OpenSCADUtils.callopenscadstring(scadstr,'stl') if tmpfilename: - #mesh1 = doc.getObject(objname) #reuse imported object Mesh.insert(tmpfilename) os.unlink(tmpfilename) mesh1 = doc.getObject(objname) #blog @@ -38,7 +37,7 @@ def openscadmesh(doc, scadstr, objname): solid = solid.removeSplitter() if solid.Volume < 0: solid.complement() - obj.Shape = solid#.removeSplitter() + obj.Shape = solid return obj else: print(scadstr) @@ -148,7 +147,6 @@ class Node: obj.Height = h if self.arguments['center']: center(obj,0,0,h) - #base.ViewObject.hide() elif False: #use Frustum Feature with makeRuledSurface obj = doc.addObject("Part::FeaturePython",'frustum') Frustum(obj,r1,r2,int(self.arguments['$fn']), h) @@ -361,7 +359,6 @@ class Node: sh.makeShapeFromMesh(mesh1.Mesh.Topology,0.1) solid = Part.Solid(sh) obj = doc.addObject("Part::FeaturePython",'import_%s_%s'%(extension,objname)) - #obj=doc.addObject('Part::Feature',) ImportObject(obj,mesh1) #This object is not mutable from the GUI ViewProviderTree(obj.ViewObject) solid = solid.removeSplitter() @@ -400,7 +397,6 @@ class Node: FreeCAD.Console.PrintError('processing of dxf import failed\nPlease rework \'%s\' manually\n' % layera) f = Part.Shape() #empty Shape obj = doc.addObject("Part::FeaturePython",'import_dxf_%s_%s'%(objname,layera)) - #obj=doc.addObject('Part::Feature',) ImportObject(obj,groupobj[0]) #This object is not mutable from the GUI ViewProviderTree(obj.ViewObject) obj.Shape=f @@ -484,12 +480,6 @@ class Node: if self.arguments['center']: center(obj,xoff,yoff,0.0) return obj - #import os - #scadstr = 'surface(file = "%s", center = %s );' % \ - # (self.arguments['file'], 'true' if self.arguments['center'] else 'false') - #docname=os.path.split(self.arguments['file'])[1] - #objname,extension = docname.split('.',1) - #obj = openscadmesh(doc,scadstr,objname) elif namel in ['glide','hull']: raise(NotImplementedError) @@ -566,7 +556,6 @@ class Node: - def parseexpression(e): e = e.strip() el = e.lower() @@ -590,8 +579,6 @@ def parseexpression(e): else: import FreeCAD FreeCAD.Console.PrintMessage('%s\n' % (el)) - #return eval(el) - #assert(False) #Malformed else: return e #Return the string @@ -611,9 +598,6 @@ def parseargs(argstring): tok.append(''.join(a).strip()) #print(tok) argdict = dict(zip(tok[0::2],[parseexpression(argstring) for argstring in tok[1::2]])) -# argdict = {} -# for key, value in re.findall(r"(\$?\w+)\s*=\s*(\[?\w+]?),?\s*",argstring): -# argdict[key] = parseexpression(value) return argdict else: return parseexpression(argstring) @@ -688,8 +672,6 @@ def insert(filename,docname): except NameError: doc = FreeCAD.newDocument(docname) readfile(filename).addtofreecad(doc) - #doc.recompute() - global dxfcache From 6d7336cc7ae726697897e93a07729902ab2f9d2d Mon Sep 17 00:00:00 2001 From: Andrea Date: Mon, 31 Mar 2025 22:23:19 +0200 Subject: [PATCH 130/316] MOD: SANDBOX clean clean code --- src/Mod/Sandbox/App/DocumentProtectorPy.cpp | 4 -- src/Mod/Sandbox/Gui/AppSandboxGui.cpp | 62 --------------------- src/Mod/Sandbox/Gui/TaskPanelView.cpp | 6 -- src/Mod/Sandbox/Gui/Workbench.h | 3 - src/Mod/Sandbox/exportDRAWEXE.py | 10 ---- 5 files changed, 85 deletions(-) diff --git a/src/Mod/Sandbox/App/DocumentProtectorPy.cpp b/src/Mod/Sandbox/App/DocumentProtectorPy.cpp index 5e5e1ca271..c74d0977e2 100644 --- a/src/Mod/Sandbox/App/DocumentProtectorPy.cpp +++ b/src/Mod/Sandbox/App/DocumentProtectorPy.cpp @@ -211,10 +211,6 @@ Py::Object DocumentObjectProtectorPy::getattr(const char * attr) App::Property* prop = obj->getPropertyByName(attr); if (!prop) { return Py::PythonExtension::getattr(attr); - //std::string s; - //std::ostringstream s_out; - //s_out << "No such attribute '" << attr << "'"; - //throw Py::AttributeError(s_out.str()); } return Py::asObject(prop->getPyObject()); diff --git a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp index 07ed012b1a..6bc88ea0c0 100644 --- a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp +++ b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp @@ -82,69 +82,9 @@ private: try { Base::Vector3d m1 = arc->getCenter(); - //Base::Vector3d a3 = arc->getStartPoint(); Base::Vector3d a3 = arc->getEndPoint(true); - //Base::Vector3d l1 = seg->getStartPoint(); Base::Vector3d l2 = seg->getEndPoint(); -#if 0 - Py::Module pd("FilletArc"); - Py::Callable method(pd.getAttr(std::string("makeFilletArc"))); - Py::Callable vector(pd.getAttr(std::string("Vector"))); - Py::Tuple xyz(3); - Py::Tuple args(6); - xyz.setItem(0, Py::Float(m1.x)); - xyz.setItem(1, Py::Float(m1.y)); - xyz.setItem(2, Py::Float(m1.z)); - args.setItem(0,vector.apply(xyz)); - - xyz.setItem(0, Py::Float(a3.x)); - xyz.setItem(1, Py::Float(a3.y)); - xyz.setItem(2, Py::Float(a3.z)); - args.setItem(1,vector.apply(xyz)); - - xyz.setItem(0, Py::Float(l2.x)); - xyz.setItem(1, Py::Float(l2.y)); - xyz.setItem(2, Py::Float(l2.z)); - args.setItem(2,vector.apply(xyz)); - - xyz.setItem(0, Py::Float((float)0)); - xyz.setItem(1, Py::Float((float)0)); - xyz.setItem(2, Py::Float((float)1)); - args.setItem(3,vector.apply(xyz)); - - args.setItem(4,Py::Float(radius)); - args.setItem(5,Py::Long((int)0)); - Py::Tuple ret(method.apply(args)); - Py::Object S1(ret.getItem(0)); - Py::Object S2(ret.getItem(1)); - Py::Object M2(ret.getItem(2)); - - Base::Vector3d s1, s2, m2; - s1.x = (double)Py::Float(S1.getAttr("x")); - s1.y = (double)Py::Float(S1.getAttr("y")); - s1.z = (double)Py::Float(S1.getAttr("z")); - - s2.x = (double)Py::Float(S2.getAttr("x")); - s2.y = (double)Py::Float(S2.getAttr("y")); - s2.z = (double)Py::Float(S2.getAttr("z")); - - m2.x = (double)Py::Float(M2.getAttr("x")); - m2.y = (double)Py::Float(M2.getAttr("y")); - m2.z = (double)Py::Float(M2.getAttr("z")); - - coords->point.set1Value(0, (float)s1.x,(float)s1.y,(float)s1.z); - coords->point.set1Value(1, (float)m2.x,(float)m2.y,(float)m2.z); - coords->point.set1Value(2, (float)s2.x,(float)s2.y,(float)s2.z); - - Base::Console().Message("M1=<%.4f,%.4f>\n", m1.x,m1.y); - Base::Console().Message("M2=<%.4f,%.4f>\n", m2.x,m2.y); - Base::Console().Message("S1=<%.4f,%.4f>\n", s1.x,s1.y); - Base::Console().Message("S2=<%.4f,%.4f>\n", s2.x,s2.y); - Base::Console().Message("P=<%.4f,%.4f>\n", a3.x,a3.y); - Base::Console().Message("Q=<%.4f,%.4f>\n", l2.x,l2.y); - Base::Console().Message("\n"); -#else Py::Module pd("PartDesign"); Py::Callable method(pd.getAttr(std::string("makeFilletArc"))); @@ -154,7 +94,6 @@ private: args.setItem(2,Py::Vector(l2)); args.setItem(3,Py::Vector(Base::Vector3d(0,0,1))); args.setItem(4,Py::Float(radius)); - //args.setItem(5,Py::Long((int)0)); args.setItem(5,Py::Long((long)1)); Py::Tuple ret(method.apply(args)); Py::Vector S1(ret.getItem(0)); @@ -175,7 +114,6 @@ private: Base::Console().Message("P=<%.4f,%.4f>\n", a3.x,a3.y); Base::Console().Message("Q=<%.4f,%.4f>\n", l2.x,l2.y); Base::Console().Message("\n"); -#endif } catch (Py::Exception&) { Base::PyException e; // extract the Python error text diff --git a/src/Mod/Sandbox/Gui/TaskPanelView.cpp b/src/Mod/Sandbox/Gui/TaskPanelView.cpp index c02c3bdc7f..659a89be77 100644 --- a/src/Mod/Sandbox/Gui/TaskPanelView.cpp +++ b/src/Mod/Sandbox/Gui/TaskPanelView.cpp @@ -158,14 +158,12 @@ public: verticalLayout->addWidget(rbAndroidScheme); - gridLayout->addWidget(ActionGroup1, 0, 1, 1, 1); verticalSpacer = new QSpacerItem(20, 57, QSizePolicy::Minimum, QSizePolicy::Expanding); gridLayout->addItem(verticalSpacer, 1, 1, 1, 1); - retranslateUi(MainWindow2); QMetaObject::connectSlotsByName(MainWindow2); @@ -246,7 +244,6 @@ public: verticalLayout_3->addWidget(line_2); - verticalLayout->addLayout(verticalLayout_3); gridLayout_2 = new QGridLayout(); @@ -308,7 +305,6 @@ public: verticalLayout_4->addWidget(line); - verticalLayout->addLayout(verticalLayout_4); verticalLayout_2 = new QVBoxLayout(); @@ -343,10 +339,8 @@ public: verticalLayout_2->addWidget(ActionLabel3); - verticalLayout->addLayout(verticalLayout_2); - retranslateUi(MainWindow); } // setupUi diff --git a/src/Mod/Sandbox/Gui/Workbench.h b/src/Mod/Sandbox/Gui/Workbench.h index 0e055cb7e6..572b1aab3e 100644 --- a/src/Mod/Sandbox/Gui/Workbench.h +++ b/src/Mod/Sandbox/Gui/Workbench.h @@ -57,11 +57,8 @@ public: void setWidget(QWidget* w); protected: - //virtual void doAction(SoAction * action); virtual void GLRender(SoGLRenderAction *action); virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er); - //virtual void getPrimitiveCount(SoGetPrimitiveCountAction * action); - //virtual void rayPick (SoRayPickAction *action); virtual void generatePrimitives(SoAction *action); void getQuad(SoState * state, SbVec3f & v0, SbVec3f & v1, SbVec3f & v2, SbVec3f & v3); diff --git a/src/Mod/Sandbox/exportDRAWEXE.py b/src/Mod/Sandbox/exportDRAWEXE.py index 313748d1be..3024de98ae 100644 --- a/src/Mod/Sandbox/exportDRAWEXE.py +++ b/src/Mod/Sandbox/exportDRAWEXE.py @@ -305,7 +305,6 @@ class Drawexporter(object): spinename = '%s-0-spine' % ob.Name saveShape(self.csg,self.filename, path,spinename,None,\ self.cleanshape) # placement with shape - #safePlacement(ob.Placement,ob.Name) self.csg.write('mksweep %s\n' % spinename) #setsweep setoptions=[] @@ -327,9 +326,6 @@ class Drawexporter(object): sections=ob.Sections sectionnames = [] for i,subobj in enumerate(ob.Sections): - #process_object(csg,subobj,filename) - #sectionsnames.append(subobj.Name) - #d1['basename']=subobj.Name sectionname = '%s-0-section-%02d-%s' % (ob.Name,i,subobj.Name) addoptions=[] explodeshape = self.alwaysexplode or \ @@ -782,9 +778,6 @@ class Drawexporter(object): self.csg.write('compound vl v1l vnl vol vil hl h1l hnl hol hil %s\n' % ob.Name) else: self.csg.write('compound vl v1l vnl vol vil %s\n' % ob.Name) - #elif ob.isDerivedFrom('Part::FeaturePython') and \ - # hasattr(ob.Proxy,'__module__'): - # pass elif ob.isDerivedFrom('Part::Feature') : if ob.Shape.isNull(): #would crash in exportBrep otherwise raise ValueError('Shape of %s is Null' % ob.Name) @@ -837,9 +830,6 @@ class Drawexporter(object): names = [name for name in toplevelobjs if name is not False] self.csg.write('donly %s\n'%(' '.join(names))) self.export_annotations(objlst) - #for ob in objlst: - # self.process_object(ob,toplevel=toplevel) - #self.write_displayonly(objlst) def __exit__(self,exc_type, exc_val, exc_tb ): self.csg.close() From f7882c99c4ac5004d4e3ea274f11e3de4ee6994f Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Thu, 3 Apr 2025 05:11:09 +0200 Subject: [PATCH 131/316] MOD: ReverseEngineering clean (#20555) * MOD: ReverseEngineering clean code . removed old code pcl lib is alwais >then 1.7 (ubuntu 20.04 use pcl 1.10) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../ReverseEngineering/App/BSplineFitting.cpp | 36 ------------------- .../App/SurfaceTriangulation.cpp | 18 ++-------- 2 files changed, 3 insertions(+), 51 deletions(-) diff --git a/src/Mod/ReverseEngineering/App/BSplineFitting.cpp b/src/Mod/ReverseEngineering/App/BSplineFitting.cpp index adc28a89fc..e9e46e7696 100644 --- a/src/Mod/ReverseEngineering/App/BSplineFitting.cpp +++ b/src/Mod/ReverseEngineering/App/BSplineFitting.cpp @@ -37,13 +37,11 @@ #include "BSplineFitting.h" #include -#if PCL_VERSION_COMPARE(>=, 1, 7, 0) #include #include #include #include #include -#endif using namespace Reen; @@ -96,7 +94,6 @@ void BSplineFitting::setBoundaryWeight(double value) Handle(Geom_BSplineSurface) BSplineFitting::perform() { -#if PCL_VERSION_COMPARE(>=, 1, 7, 0) pcl::on_nurbs::NurbsDataSurface data; for (std::vector::const_iterator it = myPoints.begin(); it != myPoints.end(); ++it) { @@ -118,7 +115,6 @@ Handle(Geom_BSplineSurface) BSplineFitting::perform() // initialize ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox(myOrder, &data); pcl::on_nurbs::FittingSurface fit(&data, nurbs); - // fit.setQuiet (false); // enable/disable debug output // surface refinement for (unsigned i = 0; i < myRefinement; i++) { @@ -134,35 +130,6 @@ Handle(Geom_BSplineSurface) BSplineFitting::perform() fit.solve(); } - // fit B-spline curve -#if 0 - // parameters - pcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params; - curve_params.addCPsAccuracy = 5e-2; - curve_params.addCPsIteration = 3; - curve_params.maxCPs = 200; - curve_params.accuracy = 1e-3; - curve_params.iterations = 100; - - curve_params.param.closest_point_resolution = 0; - curve_params.param.closest_point_weight = 1.0; - curve_params.param.closest_point_sigma2 = 0.1; - curve_params.param.interior_sigma2 = 0.00001; - curve_params.param.smooth_concavity = 1.0; - curve_params.param.smoothness = 1.0; - - // initialisation (circular) - pcl::on_nurbs::NurbsDataCurve2d curve_data; - curve_data.interior = data.interior_param; - curve_data.interior_weight_function.push_back(true); - ON_NurbsCurve curve_nurbs = pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D(order, curve_data.interior); - - // curve fitting - pcl::on_nurbs::FittingCurve2dASDM curve_fit (&curve_data, curve_nurbs); - // curve_fit.setQuiet (false); // enable/disable debug output - curve_fit.fitting (curve_params); -#endif - // u parameters int numUKnots = fit.m_nurbs.KnotCount(0); int numUPoles = fit.m_nurbs.CVCount(0); @@ -246,8 +213,5 @@ Handle(Geom_BSplineSurface) BSplineFitting::perform() uPeriodic, vPeriodic); return spline; -#else - return Handle(Geom_BSplineSurface)(); -#endif } #endif // HAVE_PCL_OPENNURBS diff --git a/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp index a718e20d6d..3a97fe2bfc 100644 --- a/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp +++ b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp @@ -182,10 +182,6 @@ void SurfaceTriangulation::perform(const std::vector& normals) gp3.reconstruct(mesh); MeshConversion::convert(mesh, myMesh); - - // Additional vertex information - // std::vector parts = gp3.getPartIDs(); - // std::vector states = gp3.getPointStates(); } // ---------------------------------------------------------------------------- @@ -645,7 +641,6 @@ void Reen::MarchingCubesHoppe::perform(int ksearch) NormalEstimation n; PointCloud::Ptr normals(new PointCloud()); n.setInputCloud(cloud); - // n.setIndices (indices[B); n.setSearchMethod(tree); n.setKSearch(ksearch); n.compute(*normals); @@ -747,16 +742,9 @@ void MeshConversion::convert(const pcl::PolygonMesh& pclMesh, Mesh::MeshObject& for (size_t d = 0; d < pclMesh.cloud.fields.size(); ++d) { int c = 0; // adding vertex - if ((pclMesh.cloud.fields[d].datatype == -#if PCL_VERSION_COMPARE(>, 1, 6, 0) - pcl::PCLPointField::FLOAT32) - && -#else - sensor_msgs::PointField::FLOAT32) - && -#endif - (pclMesh.cloud.fields[d].name == "x" || pclMesh.cloud.fields[d].name == "y" - || pclMesh.cloud.fields[d].name == "z")) { + if ((pclMesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) + && (pclMesh.cloud.fields[d].name == "x" || pclMesh.cloud.fields[d].name == "y" + || pclMesh.cloud.fields[d].name == "z")) { float value; memcpy(&value, &pclMesh.cloud.data[i * point_size + pclMesh.cloud.fields[d].offset From 72c1659e4dc91a9d09fa688b8173f5a3e0d57531 Mon Sep 17 00:00:00 2001 From: Leticia Vong Date: Mon, 24 Mar 2025 14:00:13 +0000 Subject: [PATCH 132/316] GUI: Fix #18806 Toggle freeze behavior Previously, StdCmdToggleFreeze only unfroze child objects using getInListRecursive(). This update ensures that dependent objects are properly unfrozen. Freezing behavior remains unchanged. --- src/Gui/CommandFeat.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Gui/CommandFeat.cpp b/src/Gui/CommandFeat.cpp index b2e5504b82..c4a14a4acb 100644 --- a/src/Gui/CommandFeat.cpp +++ b/src/Gui/CommandFeat.cpp @@ -185,6 +185,14 @@ void StdCmdToggleFreeze::activated(int iMsg) obj->unfreeze(); for (auto child : obj->getInListRecursive()) child->unfreeze(); + if (obj->isDerivedFrom(Base::Type::fromName("PartDesign::Body"))) { + for (auto child : obj->getOutListRecursive()) + child->unfreeze(); + } + else { + for (auto child : obj->getOutList()) + child->unfreeze(); + } } else { obj->freeze(); for (auto parent : obj->getOutListRecursive()) From 63dcbd548ef98961b1c4b331b387478919dbae58 Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Thu, 3 Apr 2025 10:32:25 +0200 Subject: [PATCH 133/316] Revert "fix issues" This reverts commit 5a6fd53b3a071a1932392c17c72af7769af42e73. --- src/Mod/CAM/Path/Tool/Bit.py | 46 ++++++++++-------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/src/Mod/CAM/Path/Tool/Bit.py b/src/Mod/CAM/Path/Tool/Bit.py index 20a21382e9..b2b2905128 100644 --- a/src/Mod/CAM/Path/Tool/Bit.py +++ b/src/Mod/CAM/Path/Tool/Bit.py @@ -118,14 +118,22 @@ def _findRelativePath(path, typ): return relative +# Unused due to bug fix related to relative paths +""" +def findRelativePathShape(path): + return _findRelativePath(path, 'Shape') + + +def findRelativePathTool(path): + return _findRelativePath(path, 'Bit') +""" + + def findRelativePathLibrary(path): return _findRelativePath(path, "Library") class ToolBit(object): - - TOOL_TYPES = [ "EndMill", "BallEndMill", "BullNoseMill", "Drill", "VBit", "Probe", "Laser", "Other"] - def __init__(self, obj, shapeFile, path=None): Path.Log.track(obj.Label, shapeFile, path) self.obj = obj @@ -147,14 +155,6 @@ class ToolBit(object): "Base", QT_TRANSLATE_NOOP("App::Property", "The file of the tool"), ) - - obj.addProperty( - "App::PropertyEnumeration", - "ToolType", - "Base", - QT_TRANSLATE_NOOP("App::Property", "The type of the tool"), - ) - obj.addProperty( "App::PropertyString", "ShapeName", @@ -168,13 +168,10 @@ class ToolBit(object): QT_TRANSLATE_NOOP("App::Property", "List of all properties inherited from the bit"), ) - # set enum types by assigning array - obj.ToolType = self.TOOL_TYPES if path: obj.File = path if shapeFile is None: obj.BitShape = "endmill.fcstd" - obj.ToolType = "EndMill" self._setupBitShape(obj) self.unloadBitBody(obj) else: @@ -199,16 +196,6 @@ class ToolBit(object): obj.setEditorMode("BitBody", 2) obj.setEditorMode("File", 1) obj.setEditorMode("Shape", 2) - - if not hasattr(obj, "ToolType"): - obj.addProperty( - "App::PropertyString", - "ToolType", - "Base", - QT_TRANSLATE_NOOP("App::Property", "The type of the tool"), - ) - obj.ToolType = self.TOOL_TYPES - if not hasattr(obj, "BitPropertyNames"): obj.addProperty( "App::PropertyStringList", @@ -451,10 +438,6 @@ class ToolBit(object): attrs = {} attrs["version"] = 2 attrs["name"] = obj.Label - - if obj.ToolType: - attrs["type"] = obj.ToolType - if Path.Preferences.toolsStoreAbsolutePaths(): attrs["shape"] = obj.BitShape else: @@ -468,7 +451,8 @@ class ToolBit(object): for name in obj.BitPropertyNames: params[name] = PathUtil.getPropertyValueString(obj, name) attrs["parameter"] = params - attrs["attribute"] = {} + params = {} + attrs["attribute"] = params return attrs @@ -483,10 +467,6 @@ class ToolBitFactory(object): Path.Log.track(attrs, path) obj = Factory.Create(name, attrs["shape"], path) obj.Label = attrs["name"] - - if "type" in attrs: - obj.ToolType = attrs["type"] - params = attrs["parameter"] for prop in params: PathUtil.setProperty(obj, prop, params[prop]) From d4de12061e2bc6e6b4c6791df62af742c0c47316 Mon Sep 17 00:00:00 2001 From: captain0xff Date: Wed, 2 Apr 2025 21:01:13 +0530 Subject: [PATCH 134/316] Gui: make BitmapFactory::pixmapFromSvg dpi aware added getMaximumDPR method and removed a overload of pixmapFromSvg with dpr parameter update --- src/Gui/BitmapFactory.cpp | 30 +++++++++++++++++++----------- src/Gui/BitmapFactory.h | 10 ++-------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/Gui/BitmapFactory.cpp b/src/Gui/BitmapFactory.cpp index 5c70844bb1..0bb4f6c5eb 100644 --- a/src/Gui/BitmapFactory.cpp +++ b/src/Gui/BitmapFactory.cpp @@ -32,6 +32,7 @@ # include # include # include +# include # include # include # include @@ -277,6 +278,8 @@ QPixmap BitmapFactoryInst::pixmap(const char* name) const QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSizeF& size, const ColorMap& colorMapping) const { + static qreal dpr = getMaximumDPR(); + // If an absolute path is given QPixmap icon; QString iconPath; @@ -304,21 +307,15 @@ QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSizeF& size, QFile file(iconPath); if (file.open(QFile::ReadOnly | QFile::Text)) { QByteArray content = file.readAll(); - icon = pixmapFromSvg(content, size, colorMapping); + icon = pixmapFromSvg(content, size * dpr, colorMapping); } } - return icon; -} + if (!icon.isNull()) { + icon.setDevicePixelRatio(dpr); + } -QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSizeF& size, qreal dpr, - const ColorMap& colorMapping) const -{ - qreal width = size.width() * dpr; - qreal height = size.height() * dpr; - QPixmap px(pixmapFromSvg(name, QSizeF(width, height), colorMapping)); - px.setDevicePixelRatio(dpr); - return px; + return icon; } QPixmap BitmapFactoryInst::pixmapFromSvg(const QByteArray& originalContents, const QSizeF& size, @@ -677,3 +674,14 @@ QIcon BitmapFactoryInst::mergePixmap (const QIcon &base, const QPixmap &px, Gui: return overlayedIcon; } + +qreal BitmapFactoryInst::getMaximumDPR() +{ + qreal dpr = 1.0F; + + for (QScreen* screen: QGuiApplication::screens()) { + dpr = std::max(screen->devicePixelRatio(), dpr); + } + + return dpr; +} diff --git a/src/Gui/BitmapFactory.h b/src/Gui/BitmapFactory.h index 23288589af..22c79251ae 100644 --- a/src/Gui/BitmapFactory.h +++ b/src/Gui/BitmapFactory.h @@ -87,14 +87,6 @@ public: */ QPixmap pixmapFromSvg(const char* name, const QSizeF& size, const ColorMap& colorMapping = ColorMap()) const; - /** Retrieves a pixmap by name and size created by an - * scalable vector graphics (SVG) and a device pixel ratio - * - * @param colorMapping - a dictionary of substitute colors. - * Can be used to customize icon color scheme, e.g. crosshair color - */ - QPixmap pixmapFromSvg(const char* name, const QSizeF& size, qreal dpr, - const ColorMap& colorMapping = ColorMap()) const; /** This method is provided for convenience and does the same * as the method above except that it creates the pixmap from * a byte array. @@ -149,6 +141,8 @@ public: /// Helper method to merge a pixmap into one corner of a QIcon static QIcon mergePixmap (const QIcon &base, const QPixmap &px, Gui::BitmapFactoryInst::Position position); + static qreal getMaximumDPR(); + private: bool loadPixmap(const QString& path, QPixmap&) const; void restoreCustomPaths(); From 08381b1d18985cc9737fde82c2fd5559fffed524 Mon Sep 17 00:00:00 2001 From: captain0xff Date: Thu, 3 Apr 2025 01:49:16 +0530 Subject: [PATCH 135/316] remove some code setting pixel density ratio for pixmaps update --- src/Gui/CommandView.cpp | 5 +---- src/Gui/ToolHandler.cpp | 6 ++---- src/Gui/Tree.cpp | 2 +- src/Gui/ViewProviderLink.cpp | 2 +- src/Mod/Sketcher/Gui/CommandConstraints.cpp | 14 ++++++-------- src/Mod/Sketcher/Gui/DrawSketchHandler.cpp | 7 +------ src/Mod/TechDraw/Gui/CommandCreateDims.cpp | 7 +------ src/Mod/TechDraw/Gui/QGVPage.cpp | 10 +++------- 8 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 2583de287d..4af26bb8cf 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -2697,10 +2697,7 @@ public: hotYF *= pRatio; } #endif - qreal cursorWidth = size.width() * pRatio; - qreal cursorHeight = size.height() * pRatio; - QPixmap px(Gui::BitmapFactory().pixmapFromSvg(svgFile, QSizeF(cursorWidth, cursorHeight))); - px.setDevicePixelRatio(pRatio); + QPixmap px(Gui::BitmapFactory().pixmapFromSvg(svgFile, size)); return QCursor(px, hotXF, hotYF); } }; diff --git a/src/Gui/ToolHandler.cpp b/src/Gui/ToolHandler.cpp index 606e2527be..182fa8c6d2 100644 --- a/src/Gui/ToolHandler.cpp +++ b/src/Gui/ToolHandler.cpp @@ -120,7 +120,7 @@ void ToolHandler::setSvgCursor(const QString& cursorName, // qreal pRatio = devicePixelRatio(); bool isRatioOne = (pRatio == 1.0); - qreal defaultCursorSize = isRatioOne ? 64 : 32; + qreal cursorSize = isRatioOne ? 64 : 32; qreal hotX = x; qreal hotY = y; #if !defined(Q_OS_WIN32) && !defined(Q_OS_MACOS) @@ -129,15 +129,13 @@ void ToolHandler::setSvgCursor(const QString& cursorName, hotY *= pRatio; } #endif - qreal cursorSize = defaultCursorSize * pRatio; QPixmap pointer = Gui::BitmapFactory().pixmapFromSvg(cursorName.toStdString().c_str(), - QSizeF(cursorSize, cursorSize), + QSizeF{cursorSize, cursorSize}, colorMapping); if (isRatioOne) { pointer = pointer.scaled(32, 32); } - pointer.setDevicePixelRatio(pRatio); setCursor(pointer, hotX, hotY, false); } diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 77adeb35ee..ccb23dc5be 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -5488,7 +5488,7 @@ void DocumentObjectItem::testStatus(bool resetStatus, QIcon& icon1, QIcon& icon2 if (currentStatus & Status::External) { static QPixmap pxExternal; - int px = 12 * getMainWindow()->devicePixelRatioF(); + constexpr int px = 12; if (pxExternal.isNull()) { pxExternal = Gui::BitmapFactory().pixmapFromSvg("LinkOverlay", QSize(px, px)); diff --git a/src/Gui/ViewProviderLink.cpp b/src/Gui/ViewProviderLink.cpp index 9338ff37ad..e278d5a2cf 100644 --- a/src/Gui/ViewProviderLink.cpp +++ b/src/Gui/ViewProviderLink.cpp @@ -1730,7 +1730,7 @@ QIcon ViewProviderLink::getIcon() const { QPixmap ViewProviderLink::getOverlayPixmap() const { auto ext = getLinkExtension(); - int px = 12 * getMainWindow()->devicePixelRatioF(); + constexpr int px = 12; if(ext && ext->getLinkedObjectProperty() && ext->_getElementCountValue()) return BitmapFactory().pixmapFromSvg("LinkArrayOverlay", QSizeF(px,px)); else if(hasSubElement) diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 4ad4981384..090ea98dc2 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -1129,8 +1129,8 @@ private: auto colorMapping = std::map(); colorMapping[defaultCrosshairColor] = color; - qreal fullIconWidth = 32 * pixelRatio; - qreal iconWidth = 16 * pixelRatio; + constexpr qreal fullIconWidth = 32; + constexpr qreal iconWidth = 16; QPixmap cursorPixmap = Gui::BitmapFactory().pixmapFromSvg("Sketcher_Crosshair", QSizeF(fullIconWidth, fullIconWidth), @@ -1143,7 +1143,6 @@ private: cursorPainter.end(); int hotX = 8; int hotY = 8; - cursorPixmap.setDevicePixelRatio(pixelRatio); // only X11 needs hot point coordinates to be scaled if (qGuiApp->platformName() == QLatin1String("xcb")) { hotX *= pixelRatio; @@ -1422,17 +1421,16 @@ public: auto colorMapping = std::map(); colorMapping[defaultCrosshairColor] = color; - qreal fullIconWidth = 32 * pixelRatio; - qreal iconWidth = 16 * pixelRatio; - QPixmap cursorPixmap = Gui::BitmapFactory().pixmapFromSvg("Sketcher_Crosshair", QSizeF(fullIconWidth, fullIconWidth), colorMapping), - icon = Gui::BitmapFactory().pixmapFromSvg("Constraint_Dimension", QSizeF(iconWidth, iconWidth)); + constexpr qreal fullIconWidth = 32; + constexpr qreal iconWidth = 16; + QPixmap cursorPixmap = Gui::BitmapFactory().pixmapFromSvg("Sketcher_Crosshair", QSizeF(fullIconWidth, fullIconWidth), colorMapping); + QPixmap icon = Gui::BitmapFactory().pixmapFromSvg("Constraint_Dimension", QSizeF(iconWidth, iconWidth)); QPainter cursorPainter; cursorPainter.begin(&cursorPixmap); cursorPainter.drawPixmap(16 * pixelRatio, 16 * pixelRatio, icon); cursorPainter.end(); int hotX = 8; int hotY = 8; - cursorPixmap.setDevicePixelRatio(pixelRatio); // only X11 needs hot point coordinates to be scaled if (qGuiApp->platformName() == QLatin1String("xcb")) { hotX *= pixelRatio; diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index b6ff76dfd8..efbfee9143 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -406,12 +406,7 @@ DrawSketchHandler::suggestedConstraintsPixmaps(std::vector& sugg break; } if (!iconType.isEmpty()) { - qreal pixelRatio = 1; - Gui::View3DInventorViewer* viewer = getViewer(); - if (viewer) { - pixelRatio = viewer->devicePixelRatio(); - } - int iconWidth = 16 * pixelRatio; + constexpr int iconWidth = 16; QPixmap icon = Gui::BitmapFactory().pixmapFromSvg(iconType.toStdString().c_str(), QSize(iconWidth, iconWidth)); pixmaps.push_back(icon); diff --git a/src/Mod/TechDraw/Gui/CommandCreateDims.cpp b/src/Mod/TechDraw/Gui/CommandCreateDims.cpp index 983de413a2..706fb80cd5 100644 --- a/src/Mod/TechDraw/Gui/CommandCreateDims.cpp +++ b/src/Mod/TechDraw/Gui/CommandCreateDims.cpp @@ -1364,12 +1364,7 @@ protected: QPixmap icon(std::string name) { - qreal pixelRatio = 1; - Gui::View3DInventorViewer* viewer = getViewer(); - if (viewer) { - pixelRatio = viewer->devicePixelRatio(); - } - int width = 16 * pixelRatio; + constexpr int width = 16; return Gui::BitmapFactory().pixmapFromSvg(name.c_str(), QSize(width, width)); } diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index 893d077767..fec0d9c9ba 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -572,14 +572,10 @@ QPixmap QGVPage::prepareCursorPixmap(const char* iconName, QPoint& hotspot) { QPointF floatHotspot(hotspot); - double pixelRatio = getDevicePixelRatio(); - // Due to impossibility to query cursor size via Qt API, we stick to (32x32)*device_pixel_ratio + // Due to impossibility to query cursor size via Qt API, we stick to (32x32) // as FreeCAD Wiki suggests - see https://wiki.freecad.org/HiDPI_support#Custom_cursor_size - double cursorSize = 32.0 * pixelRatio; - - QPixmap pixmap = Gui::BitmapFactory().pixmapFromSvg(iconName, QSizeF(cursorSize, cursorSize)); - pixmap.setDevicePixelRatio(pixelRatio); + QPixmap pixmap = Gui::BitmapFactory().pixmapFromSvg(iconName, QSizeF(32, 32)); // The default (and here expected) SVG cursor graphics size is 64x64 pixels, thus we must adjust // the 64x64 based hotspot position for our 32x32 based cursor pixmaps accordingly @@ -590,7 +586,7 @@ QPixmap QGVPage::prepareCursorPixmap(const char* iconName, QPoint& hotspot) // therefore we must take care of the transformation ourselves... // Refer to QTBUG-68571 - https://bugreports.qt.io/browse/QTBUG-68571 if (qGuiApp->platformName() == QLatin1String("xcb")) { - floatHotspot *= pixelRatio; + floatHotspot *= getDevicePixelRatio(); } #endif From 5e8d048524be0cc8dd03f3e447304c92615f92ec Mon Sep 17 00:00:00 2001 From: captain0xff Date: Thu, 3 Apr 2025 19:38:36 +0530 Subject: [PATCH 136/316] techdraw: remove QGVPage::getDevicePixelRatio() in favor of getMaximumDPR --- src/Mod/TechDraw/Gui/QGVPage.cpp | 13 +------------ src/Mod/TechDraw/Gui/QGVPage.h | 1 - 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index fec0d9c9ba..8bd105dfd3 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -557,17 +557,6 @@ QColor QGVPage::getBackgroundColor() return fcColor.asValue(); } -double QGVPage::getDevicePixelRatio() const -{ - for (Gui::MDIView* view : m_vpPage->getDocument()->getMDIViews()) { - if (view->isDerivedFrom()) { - return static_cast(view)->getViewer()->devicePixelRatio(); - } - } - - return 1.0; -} - QPixmap QGVPage::prepareCursorPixmap(const char* iconName, QPoint& hotspot) { @@ -586,7 +575,7 @@ QPixmap QGVPage::prepareCursorPixmap(const char* iconName, QPoint& hotspot) // therefore we must take care of the transformation ourselves... // Refer to QTBUG-68571 - https://bugreports.qt.io/browse/QTBUG-68571 if (qGuiApp->platformName() == QLatin1String("xcb")) { - floatHotspot *= getDevicePixelRatio(); + floatHotspot *= Gui::BitmapFactoryInst::getMaximumDPR(); } #endif diff --git a/src/Mod/TechDraw/Gui/QGVPage.h b/src/Mod/TechDraw/Gui/QGVPage.h index 7a5b524574..332576871a 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.h +++ b/src/Mod/TechDraw/Gui/QGVPage.h @@ -152,7 +152,6 @@ protected: QColor getBackgroundColor(); - double getDevicePixelRatio() const; QPixmap prepareCursorPixmap(const char* iconName, QPoint& hotspot); void drawForeground(QPainter* painter, const QRectF& rect) override; From 83db2c260ce151474f5b5868e8c6200589dbda00 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Fri, 4 Apr 2025 14:26:28 +0200 Subject: [PATCH 137/316] Draft: make Draft_SelectPlane recognize the new Part_DatumPlane object Forum topic: https://forum.freecad.org/viewtopic.php?t=96058 --- src/Mod/Draft/WorkingPlane.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 9c1820dc29..202e36b507 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -1269,7 +1269,7 @@ class PlaneGui(PlaneBase): place = FreeCAD.Placement(mtx) typ = utils.get_type(obj) - if typ in ["App::Part", "PartDesign::Plane", "Axis", "SectionPlane"]: + if typ in ["App::Part", "Part::DatumPlane", "PartDesign::Plane", "Axis", "SectionPlane"]: ret = self.align_to_obj_placement(obj, offset, place, _hist_add) elif typ == "WorkingPlaneProxy": ret = self.align_to_wp_proxy(obj, offset, place, _hist_add) From d57339ee198b3e40ba0c83727f7e29235eb25c7d Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Fri, 4 Apr 2025 17:46:58 +0200 Subject: [PATCH 138/316] BIM: cleanup license and add SPDX --- src/Mod/BIM/Arch.py | 43 ++++++++-------- src/Mod/BIM/ArchAxis.py | 44 ++++++++-------- src/Mod/BIM/ArchAxisSystem.py | 43 ++++++++-------- src/Mod/BIM/ArchBuilding.py | 44 ++++++++-------- src/Mod/BIM/ArchBuildingPart.py | 44 ++++++++-------- src/Mod/BIM/ArchCommands.py | 45 ++++++++-------- src/Mod/BIM/ArchComponent.py | 43 ++++++++-------- src/Mod/BIM/ArchCurtainWall.py | 45 ++++++++-------- src/Mod/BIM/ArchCutPlane.py | 47 +++++++++-------- src/Mod/BIM/ArchEquipment.py | 45 ++++++++-------- src/Mod/BIM/ArchFence.py | 43 ++++++++-------- src/Mod/BIM/ArchFloor.py | 44 ++++++++-------- src/Mod/BIM/ArchFrame.py | 44 ++++++++-------- src/Mod/BIM/ArchGrid.py | 43 ++++++++-------- src/Mod/BIM/ArchIFC.py | 47 +++++++++-------- src/Mod/BIM/ArchIFCSchema.py | 47 +++++++++-------- src/Mod/BIM/ArchIFCView.py | 43 ++++++++-------- src/Mod/BIM/ArchMaterial.py | 45 ++++++++-------- src/Mod/BIM/ArchNesting.py | 44 ++++++++-------- src/Mod/BIM/ArchPanel.py | 46 ++++++++--------- src/Mod/BIM/ArchPipe.py | 46 +++++++++-------- src/Mod/BIM/ArchPrecast.py | 43 ++++++++-------- src/Mod/BIM/ArchProfile.py | 45 ++++++++-------- src/Mod/BIM/ArchProject.py | 44 ++++++++-------- src/Mod/BIM/ArchRebar.py | 45 ++++++++-------- src/Mod/BIM/ArchReference.py | 46 ++++++++--------- src/Mod/BIM/ArchRoof.py | 44 ++++++++-------- src/Mod/BIM/ArchSchedule.py | 46 +++++++++-------- src/Mod/BIM/ArchSectionPlane.py | 44 ++++++++-------- src/Mod/BIM/ArchSite.py | 45 ++++++++-------- src/Mod/BIM/ArchSketchObject.py | 44 ++++++++-------- src/Mod/BIM/ArchSpace.py | 44 ++++++++-------- src/Mod/BIM/ArchStairs.py | 49 +++++++++--------- src/Mod/BIM/ArchStructure.py | 43 ++++++++-------- src/Mod/BIM/ArchTruss.py | 45 ++++++++-------- src/Mod/BIM/ArchVRM.py | 43 ++++++++-------- src/Mod/BIM/ArchWall.py | 45 ++++++++-------- src/Mod/BIM/ArchWindow.py | 46 ++++++++--------- src/Mod/BIM/ArchWindowPresets.py | 43 ++++++++-------- src/Mod/BIM/BimStatus.py | 2 + src/Mod/BIM/Init.py | 2 + src/Mod/BIM/InitGui.py | 2 + src/Mod/BIM/OfflineRenderingUtils.py | 44 ++++++++-------- src/Mod/BIM/TestArch.py | 47 +++++++++-------- src/Mod/BIM/TestArchGui.py | 47 +++++++++-------- src/Mod/BIM/bimcommands/BimArchUtils.py | 2 + src/Mod/BIM/bimcommands/BimAxis.py | 2 + src/Mod/BIM/bimcommands/BimBackground.py | 2 + src/Mod/BIM/bimcommands/BimBeam.py | 2 + src/Mod/BIM/bimcommands/BimBox.py | 2 + src/Mod/BIM/bimcommands/BimBuilder.py | 2 + src/Mod/BIM/bimcommands/BimBuildingPart.py | 4 +- src/Mod/BIM/bimcommands/BimClassification.py | 2 + src/Mod/BIM/bimcommands/BimClone.py | 2 + src/Mod/BIM/bimcommands/BimColumn.py | 2 + src/Mod/BIM/bimcommands/BimCommon.py | 2 + src/Mod/BIM/bimcommands/BimCompound.py | 2 + src/Mod/BIM/bimcommands/BimConvert.py | 2 + src/Mod/BIM/bimcommands/BimCopy.py | 2 + src/Mod/BIM/bimcommands/BimCurtainwall.py | 2 + src/Mod/BIM/bimcommands/BimCut.py | 2 + src/Mod/BIM/bimcommands/BimCutPlane.py | 47 +++++++++-------- src/Mod/BIM/bimcommands/BimDiff.py | 2 + src/Mod/BIM/bimcommands/BimDimensions.py | 2 + src/Mod/BIM/bimcommands/BimDoor.py | 2 + src/Mod/BIM/bimcommands/BimDrawingView.py | 2 + src/Mod/BIM/bimcommands/BimEmptyTrash.py | 2 + src/Mod/BIM/bimcommands/BimEquipment.py | 2 + src/Mod/BIM/bimcommands/BimExamples.py | 2 + src/Mod/BIM/bimcommands/BimExtrude.py | 2 + src/Mod/BIM/bimcommands/BimFence.py | 2 + src/Mod/BIM/bimcommands/BimFrame.py | 3 +- src/Mod/BIM/bimcommands/BimFuse.py | 2 + src/Mod/BIM/bimcommands/BimGlue.py | 2 + src/Mod/BIM/bimcommands/BimHelp.py | 2 + src/Mod/BIM/bimcommands/BimIfcElements.py | 2 + src/Mod/BIM/bimcommands/BimIfcExplorer.py | 2 + src/Mod/BIM/bimcommands/BimIfcProperties.py | 2 + src/Mod/BIM/bimcommands/BimIfcQuantities.py | 2 + src/Mod/BIM/bimcommands/BimImagePlane.py | 2 + src/Mod/BIM/bimcommands/BimLayers.py | 2 + src/Mod/BIM/bimcommands/BimLeader.py | 2 + src/Mod/BIM/bimcommands/BimLibrary.py | 3 ++ src/Mod/BIM/bimcommands/BimMaterial.py | 2 + src/Mod/BIM/bimcommands/BimMoveView.py | 2 + src/Mod/BIM/bimcommands/BimNudge.py | 2 + src/Mod/BIM/bimcommands/BimOffset.py | 2 + src/Mod/BIM/bimcommands/BimPanel.py | 2 + src/Mod/BIM/bimcommands/BimPipe.py | 2 + src/Mod/BIM/bimcommands/BimPreflight.py | 2 + src/Mod/BIM/bimcommands/BimProfile.py | 2 + src/Mod/BIM/bimcommands/BimProject.py | 2 + src/Mod/BIM/bimcommands/BimProjectManager.py | 2 + src/Mod/BIM/bimcommands/BimRebar.py | 2 + src/Mod/BIM/bimcommands/BimReextrude.py | 2 + src/Mod/BIM/bimcommands/BimReference.py | 2 + src/Mod/BIM/bimcommands/BimReorder.py | 2 + .../BIM/bimcommands/BimResetCloneColors.py | 2 + src/Mod/BIM/bimcommands/BimRewire.py | 2 + src/Mod/BIM/bimcommands/BimRoof.py | 3 +- src/Mod/BIM/bimcommands/BimSchedule.py | 2 + src/Mod/BIM/bimcommands/BimSectionPlane.py | 2 + src/Mod/BIM/bimcommands/BimSetup.py | 2 + src/Mod/BIM/bimcommands/BimShape2DView.py | 2 + src/Mod/BIM/bimcommands/BimSimpleCopy.py | 2 + src/Mod/BIM/bimcommands/BimSite.py | 2 + src/Mod/BIM/bimcommands/BimSketch.py | 2 + src/Mod/BIM/bimcommands/BimSlab.py | 2 + src/Mod/BIM/bimcommands/BimSpace.py | 2 + src/Mod/BIM/bimcommands/BimStairs.py | 2 + src/Mod/BIM/bimcommands/BimTDPage.py | 2 + src/Mod/BIM/bimcommands/BimTDView.py | 2 + src/Mod/BIM/bimcommands/BimText.py | 3 +- src/Mod/BIM/bimcommands/BimTogglePanels.py | 2 + src/Mod/BIM/bimcommands/BimTrash.py | 2 + src/Mod/BIM/bimcommands/BimTruss.py | 2 + src/Mod/BIM/bimcommands/BimTutorial.py | 2 + src/Mod/BIM/bimcommands/BimUnclone.py | 2 + src/Mod/BIM/bimcommands/BimUngroup.py | 2 + src/Mod/BIM/bimcommands/BimViews.py | 2 + src/Mod/BIM/bimcommands/BimWPCommands.py | 2 + src/Mod/BIM/bimcommands/BimWall.py | 2 + src/Mod/BIM/bimcommands/BimWelcome.py | 2 + src/Mod/BIM/bimcommands/BimWindow.py | 2 + src/Mod/BIM/bimcommands/BimWindows.py | 2 + src/Mod/BIM/bimtests/TestArchBase.py | 3 +- src/Mod/BIM/bimtests/TestArchRoof.py | 49 +++++++++--------- src/Mod/BIM/bimtests/TestArchSpace.py | 51 ++++++++++--------- src/Mod/BIM/bimtests/TestArchWall.py | 48 ++++++++--------- src/Mod/BIM/ifc_objects.py | 44 ++++++++-------- src/Mod/BIM/ifc_viewproviders.py | 44 ++++++++-------- src/Mod/BIM/importers/exportIFC.py | 3 ++ src/Mod/BIM/importers/exportIFCHelper.py | 3 ++ .../BIM/importers/exportIFCStructuralTools.py | 3 ++ src/Mod/BIM/importers/import3DS.py | 43 ++++++++-------- src/Mod/BIM/importers/importDAE.py | 43 ++++++++-------- src/Mod/BIM/importers/importGBXML.py | 43 ++++++++-------- src/Mod/BIM/importers/importIFC.py | 3 ++ src/Mod/BIM/importers/importIFCHelper.py | 3 ++ src/Mod/BIM/importers/importIFClegacy.py | 43 ++++++++-------- src/Mod/BIM/importers/importIFCmulticore.py | 3 ++ src/Mod/BIM/importers/importJSON.py | 43 ++++++++-------- src/Mod/BIM/importers/importOBJ.py | 43 ++++++++-------- src/Mod/BIM/importers/importSH3D.py | 43 ++++++++-------- src/Mod/BIM/importers/importSH3DHelper.py | 3 ++ src/Mod/BIM/importers/importSHP.py | 44 ++++++++-------- src/Mod/BIM/importers/importWebGL.py | 45 ++++++++-------- src/Mod/BIM/nativeifc/ifc_classification.py | 2 + src/Mod/BIM/nativeifc/ifc_commands.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_diff.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_export.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_generator.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_geometry.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_import.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_layers.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_materials.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_objects.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_observer.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_openshell.py | 12 +++-- src/Mod/BIM/nativeifc/ifc_performance_test.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_psets.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_selftest.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_status.py | 11 ++-- src/Mod/BIM/nativeifc/ifc_tools.py | 2 + src/Mod/BIM/nativeifc/ifc_tree.py | 10 ++-- src/Mod/BIM/nativeifc/ifc_types.py | 2 + src/Mod/BIM/nativeifc/ifc_viewproviders.py | 2 + src/Mod/BIM/utils/buildPsets.py | 2 + src/Mod/BIM/utils/ifctree.py | 3 ++ 169 files changed, 1651 insertions(+), 1269 deletions(-) diff --git a/src/Mod/BIM/Arch.py b/src/Mod/BIM/Arch.py index 0ccc7ab635..169b48df28 100644 --- a/src/Mod/BIM/Arch.py +++ b/src/Mod/BIM/Arch.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 Arch API" __author__ = "Yorik van Havre" diff --git a/src/Mod/BIM/ArchAxis.py b/src/Mod/BIM/ArchAxis.py index 71cbaaa16c..eba177b27d 100644 --- a/src/Mod/BIM/ArchAxis.py +++ b/src/Mod/BIM/ArchAxis.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import math @@ -789,4 +792,3 @@ class _AxisTaskPanel: QtGui.QApplication.translate("Arch", "Distance", None), QtGui.QApplication.translate("Arch", "Angle", None), QtGui.QApplication.translate("Arch", "Label", None)]) - diff --git a/src/Mod/BIM/ArchAxisSystem.py b/src/Mod/BIM/ArchAxisSystem.py index df12fbb93d..8ed775aeb3 100644 --- a/src/Mod/BIM/ArchAxisSystem.py +++ b/src/Mod/BIM/ArchAxisSystem.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import FreeCAD import DraftGeomUtils diff --git a/src/Mod/BIM/ArchBuilding.py b/src/Mod/BIM/ArchBuilding.py index 652f958594..f592a40263 100644 --- a/src/Mod/BIM/ArchBuilding.py +++ b/src/Mod/BIM/ArchBuilding.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import FreeCAD import ArchCommands diff --git a/src/Mod/BIM/ArchBuildingPart.py b/src/Mod/BIM/ArchBuildingPart.py index 14f340e1fa..9868f70501 100644 --- a/src/Mod/BIM/ArchBuildingPart.py +++ b/src/Mod/BIM/ArchBuildingPart.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2018 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2018 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 * +# * * +# *************************************************************************** import FreeCAD import Draft diff --git a/src/Mod/BIM/ArchCommands.py b/src/Mod/BIM/ArchCommands.py index 5878504fd8..084b6dfa89 100644 --- a/src/Mod/BIM/ArchCommands.py +++ b/src/Mod/BIM/ArchCommands.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import FreeCAD import ArchComponent @@ -1379,4 +1383,3 @@ def makeIfcSpreadsheet(archobj=None): FreeCAD.ActiveDocument.removeObject(ifc_spreadsheet) else : return ifc_spreadsheet - diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index 93a8d32d57..76063e4421 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 provides the base Arch component class, that is shared by all of the Arch BIM objects. diff --git a/src/Mod/BIM/ArchCurtainWall.py b/src/Mod/BIM/ArchCurtainWall.py index e72a460e35..94cb4329c8 100644 --- a/src/Mod/BIM/ArchCurtainWall.py +++ b/src/Mod/BIM/ArchCurtainWall.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2020 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2020 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 Arch Curtain Wall" __author__ = "Yorik van Havre" @@ -562,4 +566,3 @@ class ViewProviderCurtainWall(ArchComponent.ViewProviderComponent): colors.append(panelcolor) if self.areDifferentColors(colors,obj.ViewObject.DiffuseColor) or force: obj.ViewObject.DiffuseColor = colors - diff --git a/src/Mod/BIM/ArchCutPlane.py b/src/Mod/BIM/ArchCutPlane.py index 9e5e67ecfa..fb17f85659 100644 --- a/src/Mod/BIM/ArchCutPlane.py +++ b/src/Mod/BIM/ArchCutPlane.py @@ -1,25 +1,28 @@ -#***************************************************************************** -#* Copyright (c) 2014 Jonathan Wiedemann (cutplan) * -#* Copyright (c) 2019 Jerome Laverroux (cutline)* -#* Copyright (c) 2023 FreeCAD Project Association * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* 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 * -#* * -#***************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# ***************************************************************************** +# * * +# * Copyright (c) 2014 Jonathan Wiedemann (cutplan) * +# * Copyright (c) 2019 Jerome Laverroux (cutline)* +# * Copyright (c) 2023 FreeCAD Project Association * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# ***************************************************************************** import FreeCAD import Part diff --git a/src/Mod/BIM/ArchEquipment.py b/src/Mod/BIM/ArchEquipment.py index 401df591bc..b2e21e2ffb 100644 --- a/src/Mod/BIM/ArchEquipment.py +++ b/src/Mod/BIM/ArchEquipment.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2014 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2014 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 Equipment" __author__ = "Yorik van Havre" @@ -305,4 +309,3 @@ class _ViewProviderEquipment(ArchComponent.ViewProviderComponent): self.coords.point.setValues([[p.x,p.y,p.z] for p in obj.SnapPoints]) else: self.coords.point.deleteValues(0) - diff --git a/src/Mod/BIM/ArchFence.py b/src/Mod/BIM/ArchFence.py index 49901eeddb..5b7cad9282 100644 --- a/src/Mod/BIM/ArchFence.py +++ b/src/Mod/BIM/ArchFence.py @@ -1,23 +1,26 @@ -#***************************************************************************** -#* Copyright (c) 2019 furti * -#* * -#* 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 * -#* * -#***************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# ***************************************************************************** +# * * +# * Copyright (c) 2019 furti * +# * * +# * 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 * +# * * +# ***************************************************************************** # Fence functionality for the Arch Workbench diff --git a/src/Mod/BIM/ArchFloor.py b/src/Mod/BIM/ArchFloor.py index cbde18279c..ecb7f25029 100644 --- a/src/Mod/BIM/ArchFloor.py +++ b/src/Mod/BIM/ArchFloor.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 provides tools to build Floor objects. Floors are used to group different Arch objects situated at a same level. diff --git a/src/Mod/BIM/ArchFrame.py b/src/Mod/BIM/ArchFrame.py index c7e09460b9..3863010df1 100644 --- a/src/Mod/BIM/ArchFrame.py +++ b/src/Mod/BIM/ArchFrame.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2013 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 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 * +# * * +# *************************************************************************** import FreeCAD import ArchComponent @@ -228,4 +231,3 @@ class _ViewProviderFrame(ArchComponent.ViewProviderComponent): if self.Object.Profile: p = [self.Object.Profile] return ArchComponent.ViewProviderComponent.claimChildren(self)+p - diff --git a/src/Mod/BIM/ArchGrid.py b/src/Mod/BIM/ArchGrid.py index dd14d12c5f..a46a30eb06 100644 --- a/src/Mod/BIM/ArchGrid.py +++ b/src/Mod/BIM/ArchGrid.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import math diff --git a/src/Mod/BIM/ArchIFC.py b/src/Mod/BIM/ArchIFC.py index 2f96f4aff0..c45d96992c 100644 --- a/src/Mod/BIM/ArchIFC.py +++ b/src/Mod/BIM/ArchIFC.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2019 Dion Moult * -#* Copyright (c) 2019 Yorik van Havre * -#* Copyright (c) 2020 FreeCAD Developers * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2019 Dion Moult * +# * Copyright (c) 2019 Yorik van Havre * +# * Copyright (c) 2020 FreeCAD Developers * +# * * +# * 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 modules sets up and manages the IFC-related properties, types and attributes of Arch/BIM objects. diff --git a/src/Mod/BIM/ArchIFCSchema.py b/src/Mod/BIM/ArchIFCSchema.py index 48aade83ca..edbcb8a386 100644 --- a/src/Mod/BIM/ArchIFCSchema.py +++ b/src/Mod/BIM/ArchIFCSchema.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2019 Dion Moult * -#* Copyright (c) 2019 Yorik van Havre * -#* Copyright (c) 2019 FreeCAD Developers * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2019 Dion Moult * +# * Copyright (c) 2019 Yorik van Havre * +# * Copyright (c) 2019 FreeCAD Developers * +# * * +# * 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 IFC schema data as dicts, by loading the JSON schema files. diff --git a/src/Mod/BIM/ArchIFCView.py b/src/Mod/BIM/ArchIFCView.py index 47325a2cd5..6fae401fed 100644 --- a/src/Mod/BIM/ArchIFCView.py +++ b/src/Mod/BIM/ArchIFCView.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2020 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2020 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 * +# * * +# *************************************************************************** """View providers and UI elements for the Ifc classes.""" diff --git a/src/Mod/BIM/ArchMaterial.py b/src/Mod/BIM/ArchMaterial.py index 30b0be4c36..b38ef6d427 100644 --- a/src/Mod/BIM/ArchMaterial.py +++ b/src/Mod/BIM/ArchMaterial.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2015 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2015 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 * +# * * +# *************************************************************************** import FreeCAD from draftutils import params @@ -895,5 +898,3 @@ class _ArchMultiMaterialTaskPanel: def reject(self): FreeCADGui.ActiveDocument.resetEdit() return True - - diff --git a/src/Mod/BIM/ArchNesting.py b/src/Mod/BIM/ArchNesting.py index 167e71644c..c012f6ec29 100644 --- a/src/Mod/BIM/ArchNesting.py +++ b/src/Mod/BIM/ArchNesting.py @@ -1,24 +1,28 @@ # -*- coding: utf-8 -*- -#*************************************************************************** -#* Copyright (c) 2017 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2017 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 * +# * * +# *************************************************************************** import math from datetime import datetime diff --git a/src/Mod/BIM/ArchPanel.py b/src/Mod/BIM/ArchPanel.py index d2b7f60f42..56e4a80291 100644 --- a/src/Mod/BIM/ArchPanel.py +++ b/src/Mod/BIM/ArchPanel.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import math @@ -1075,6 +1078,3 @@ class SheetTaskPanel(ArchComponent.ComponentTaskPanel): FreeCADGui.Control.closeDialog() FreeCADGui.runCommand("Draft_Edit") - - - diff --git a/src/Mod/BIM/ArchPipe.py b/src/Mod/BIM/ArchPipe.py index 0d3f67d9a7..f404134691 100644 --- a/src/Mod/BIM/ArchPipe.py +++ b/src/Mod/BIM/ArchPipe.py @@ -1,24 +1,28 @@ # -*- coding: utf-8 -*- -#*************************************************************************** -#* Copyright (c) 2016 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2016 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 * +# * * +# *************************************************************************** import FreeCAD import ArchComponent @@ -451,5 +455,3 @@ class _ArchPipeConnector(ArchComponent.Component): if pipe.OffsetEnd != offset: pipe.OffsetEnd = offset pipe.Proxy.execute(pipe) - - diff --git a/src/Mod/BIM/ArchPrecast.py b/src/Mod/BIM/ArchPrecast.py index 138772679d..ad662359b9 100644 --- a/src/Mod/BIM/ArchPrecast.py +++ b/src/Mod/BIM/ArchPrecast.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2016 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2016 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 Precast concrete module" __author__ = "Yorik van Havre" diff --git a/src/Mod/BIM/ArchProfile.py b/src/Mod/BIM/ArchProfile.py index 7e34aa8bbd..191d8b8af0 100644 --- a/src/Mod/BIM/ArchProfile.py +++ b/src/Mod/BIM/ArchProfile.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 Profile" __author__ = "Yorik van Havre" @@ -465,5 +468,3 @@ class ProfileTaskPanel: def retranslateUi(self, TaskPanel): self.form.setWindowTitle(self.type+" "+QtGui.QApplication.translate("Arch", "Profile", None)) - - diff --git a/src/Mod/BIM/ArchProject.py b/src/Mod/BIM/ArchProject.py index feb2279e58..272c68affa 100644 --- a/src/Mod/BIM/ArchProject.py +++ b/src/Mod/BIM/ArchProject.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 provides tools to build Project objects. Project objects are objects specifically for better IFC compatibility, allowing the user to tweak diff --git a/src/Mod/BIM/ArchRebar.py b/src/Mod/BIM/ArchRebar.py index 83e6f235b0..ac33256454 100644 --- a/src/Mod/BIM/ArchRebar.py +++ b/src/Mod/BIM/ArchRebar.py @@ -1,23 +1,27 @@ -#*************************************************************************** -#* Copyright (c) 2013 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 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 * +# * * +# *************************************************************************** + # Modified Amritpal Singh on 07-07-2017 import FreeCAD @@ -570,4 +574,3 @@ def getLengthOfRebar(rebar): else: FreeCAD.Console.PrintError("Cannot calculate rebar length from its base object\n") return None - diff --git a/src/Mod/BIM/ArchReference.py b/src/Mod/BIM/ArchReference.py index 2a6fa18396..64d2bb41fd 100644 --- a/src/Mod/BIM/ArchReference.py +++ b/src/Mod/BIM/ArchReference.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2018 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2018 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 Arch External Reference" __author__ = "Yorik van Havre" @@ -973,6 +976,3 @@ class ArchReferenceTaskPanel: FreeCAD.loadFile(self.obj.File) FreeCADGui.Control.closeDialog() FreeCADGui.ActiveDocument.resetEdit() - - - diff --git a/src/Mod/BIM/ArchRoof.py b/src/Mod/BIM/ArchRoof.py index a5392ec381..5018b1f35c 100644 --- a/src/Mod/BIM/ArchRoof.py +++ b/src/Mod/BIM/ArchRoof.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2012 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2012 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 * +# * * +# *************************************************************************** import math @@ -955,4 +958,3 @@ class _RoofTaskPanel: QtGui.QApplication.translate("Arch", "Thickness (mm)", None), QtGui.QApplication.translate("Arch", "Overhang (mm)", None), QtGui.QApplication.translate("Arch", "Height (mm)", None)]) - diff --git a/src/Mod/BIM/ArchSchedule.py b/src/Mod/BIM/ArchSchedule.py index 6cf4e8384d..17539c610b 100644 --- a/src/Mod/BIM/ArchSchedule.py +++ b/src/Mod/BIM/ArchSchedule.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2015 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2015 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 * +# * * +# *************************************************************************** import FreeCAD from draftutils import params @@ -1000,5 +1004,3 @@ class ArchScheduleTaskPanel: self.obj.AutoUpdate = self.form.checkAutoUpdate.isChecked() FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() - - diff --git a/src/Mod/BIM/ArchSectionPlane.py b/src/Mod/BIM/ArchSectionPlane.py index 8a6bd08d73..fc058ec015 100644 --- a/src/Mod/BIM/ArchSectionPlane.py +++ b/src/Mod/BIM/ArchSectionPlane.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import FreeCAD import math @@ -1348,4 +1351,3 @@ class SectionPlaneTaskPanel: self.resizeButton.setToolTip(QtGui.QApplication.translate("Arch", "Resizes the plane to fit the objects in the list above", None)) self.recenterButton.setText(QtGui.QApplication.translate("Arch", "Center", None)) self.recenterButton.setToolTip(QtGui.QApplication.translate("Arch", "Centers the plane on the objects in the list above", None)) - diff --git a/src/Mod/BIM/ArchSite.py b/src/Mod/BIM/ArchSite.py index ee67ead19f..cc456ec6dd 100644 --- a/src/Mod/BIM/ArchSite.py +++ b/src/Mod/BIM/ArchSite.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 provides tools to build Site objects. Sites are containers for Arch objects, and also define a terrain surface. @@ -1180,4 +1184,3 @@ class _ViewProviderSite: def loads(self,state): return None - diff --git a/src/Mod/BIM/ArchSketchObject.py b/src/Mod/BIM/ArchSketchObject.py index 16239a22f0..9c7cdc0aa5 100644 --- a/src/Mod/BIM/ArchSketchObject.py +++ b/src/Mod/BIM/ArchSketchObject.py @@ -1,24 +1,26 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2018-25 Paul Lee * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2018-25 Paul Lee * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** import ArchWindow from PySide.QtCore import QT_TRANSLATE_NOOP diff --git a/src/Mod/BIM/ArchSpace.py b/src/Mod/BIM/ArchSpace.py index 0d4233cc6e..029a9928ef 100644 --- a/src/Mod/BIM/ArchSpace.py +++ b/src/Mod/BIM/ArchSpace.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2013 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 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 Arch Space" __author__ = "Yorik van Havre" diff --git a/src/Mod/BIM/ArchStairs.py b/src/Mod/BIM/ArchStairs.py index ec504b237f..8b6ada325e 100644 --- a/src/Mod/BIM/ArchStairs.py +++ b/src/Mod/BIM/ArchStairs.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2013 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 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 Arch Stairs" __author__ = "Yorik van Havre" @@ -373,7 +376,7 @@ class _Stairs(ArchComponent.Component): if baseProxy and obj.ArchSketchData and \ hasattr(baseProxy, 'getStairsBaseShapeEdgesInfo'): propSetUuid = self.ArchSkPropSetPickedUuid - info = baseProxy.getStairsBaseShapeEdgesInfo(obj.Base, + info = baseProxy.getStairsBaseShapeEdgesInfo(obj.Base, propSetUuid=propSetUuid) if info: flightAxis = info.get('flightAxis') @@ -443,7 +446,7 @@ class _Stairs(ArchComponent.Component): edgeL = [Part.sortEdges(obj.Base.Shape.Edges)[0]] else: # Should not happen? edgeL = [] - #lenAxis = len(flightAxis) + len(landingAxis) + #lenAxis = len(flightAxis) + len(landingAxis) # Build Stairs if there is no obj.Base or even obj.Base is not valid else: @@ -1570,5 +1573,3 @@ class _ViewProviderStairs(ArchComponent.ViewProviderComponent): lst.extend(obj.Subtractions) return lst return [] - - diff --git a/src/Mod/BIM/ArchStructure.py b/src/Mod/BIM/ArchStructure.py index dd67c0407c..1511d1829e 100644 --- a/src/Mod/BIM/ArchStructure.py +++ b/src/Mod/BIM/ArchStructure.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** #Modified 2016-01-03 JAndersM import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands diff --git a/src/Mod/BIM/ArchTruss.py b/src/Mod/BIM/ArchTruss.py index 51b189b723..a0e21a12ff 100644 --- a/src/Mod/BIM/ArchTruss.py +++ b/src/Mod/BIM/ArchTruss.py @@ -1,24 +1,28 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2020 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2020 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 Arch Truss" __author__ = "Yorik van Havre" @@ -328,4 +332,3 @@ class ViewProviderTruss(ArchComponent.ViewProviderComponent): import Arch_rc return ":/icons/Arch_Truss_Tree.svg" - diff --git a/src/Mod/BIM/ArchVRM.py b/src/Mod/BIM/ArchVRM.py index 4ce391b912..b8407f9757 100644 --- a/src/Mod/BIM/ArchVRM.py +++ b/src/Mod/BIM/ArchVRM.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2012 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2012 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 * +# * * +# *************************************************************************** "The FreeCAD Arch Vector Rendering Module" diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index c839b3e9ca..cb4691f690 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 provides tools to build Wall objects. Walls are simple objects, usually vertical, typically obtained by giving a thickness to a base @@ -905,7 +908,7 @@ class _Wall(ArchComponent.Component): elif hasattr(obj.Base, 'Proxy') and obj.ArchSketchData and \ hasattr(obj.Base.Proxy, 'getWallBaseShapeEdgesInfo'): - wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base, + wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base, propSetUuid=propSetUuid) #get wall edges (not wires); use original edges if getWallBaseShapeEdgesInfo() provided none if wallBaseShapeEdgesInfo: diff --git a/src/Mod/BIM/ArchWindow.py b/src/Mod/BIM/ArchWindow.py index 93eea82a52..680edd15b0 100644 --- a/src/Mod/BIM/ArchWindow.py +++ b/src/Mod/BIM/ArchWindow.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import os @@ -1417,6 +1420,3 @@ class _ArchWindowTaskPanel: if self.obj: self.obj.ViewObject.Proxy.invertHinge() - - - diff --git a/src/Mod/BIM/ArchWindowPresets.py b/src/Mod/BIM/ArchWindowPresets.py index 765c85f402..d415caf447 100644 --- a/src/Mod/BIM/ArchWindowPresets.py +++ b/src/Mod/BIM/ArchWindowPresets.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2020 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2020 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 * +# * * +# *************************************************************************** import FreeCAD diff --git a/src/Mod/BIM/BimStatus.py b/src/Mod/BIM/BimStatus.py index 9da009da0d..5832d846b1 100644 --- a/src/Mod/BIM/BimStatus.py +++ b/src/Mod/BIM/BimStatus.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/Init.py b/src/Mod/BIM/Init.py index b8ac919cf5..77ab6a6c1f 100644 --- a/src/Mod/BIM/Init.py +++ b/src/Mod/BIM/Init.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * diff --git a/src/Mod/BIM/InitGui.py b/src/Mod/BIM/InitGui.py index 5b66367b6f..b44fb2d8bd 100644 --- a/src/Mod/BIM/InitGui.py +++ b/src/Mod/BIM/InitGui.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/OfflineRenderingUtils.py b/src/Mod/BIM/OfflineRenderingUtils.py index 1f566bf5be..bc61d6870c 100755 --- a/src/Mod/BIM/OfflineRenderingUtils.py +++ b/src/Mod/BIM/OfflineRenderingUtils.py @@ -1,24 +1,28 @@ # -*- coding: utf-8 -*- -#*************************************************************************** -#* Copyright (c) 2019 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2019 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 * +# * * +# *************************************************************************** ## \defgroup OFFLINERENDERINGUTILS OfflineRenderingUtils # \ingroup UTILITIES diff --git a/src/Mod/BIM/TestArch.py b/src/Mod/BIM/TestArch.py index f6829ef345..cb0953458d 100644 --- a/src/Mod/BIM/TestArch.py +++ b/src/Mod/BIM/TestArch.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2013 Yorik van Havre * -#* * -#* This file is part of the FreeCAD CAx development system. * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#***************************************************************************/ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 Yorik van Havre * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** # Unit test for the Arch module diff --git a/src/Mod/BIM/TestArchGui.py b/src/Mod/BIM/TestArchGui.py index a0a971901b..3fd1d2c900 100644 --- a/src/Mod/BIM/TestArchGui.py +++ b/src/Mod/BIM/TestArchGui.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2013 Yorik van Havre * -#* * -#* This file is part of the FreeCAD CAx development system. * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#***************************************************************************/ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 Yorik van Havre * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** # Unit test for the Arch module diff --git a/src/Mod/BIM/bimcommands/BimArchUtils.py b/src/Mod/BIM/bimcommands/BimArchUtils.py index 9b31ef04d4..89f6b7251e 100644 --- a/src/Mod/BIM/bimcommands/BimArchUtils.py +++ b/src/Mod/BIM/bimcommands/BimArchUtils.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimAxis.py b/src/Mod/BIM/bimcommands/BimAxis.py index debbcf3682..1ba40089fd 100644 --- a/src/Mod/BIM/bimcommands/BimAxis.py +++ b/src/Mod/BIM/bimcommands/BimAxis.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimBackground.py b/src/Mod/BIM/bimcommands/BimBackground.py index 9f9051fe84..efe5382444 100644 --- a/src/Mod/BIM/bimcommands/BimBackground.py +++ b/src/Mod/BIM/bimcommands/BimBackground.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimBeam.py b/src/Mod/BIM/bimcommands/BimBeam.py index d084bcf693..22eece554f 100644 --- a/src/Mod/BIM/bimcommands/BimBeam.py +++ b/src/Mod/BIM/bimcommands/BimBeam.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimBox.py b/src/Mod/BIM/bimcommands/BimBox.py index 82968934b6..4679281859 100644 --- a/src/Mod/BIM/bimcommands/BimBox.py +++ b/src/Mod/BIM/bimcommands/BimBox.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimBuilder.py b/src/Mod/BIM/bimcommands/BimBuilder.py index b007a6cbdc..f674ad63f5 100644 --- a/src/Mod/BIM/bimcommands/BimBuilder.py +++ b/src/Mod/BIM/bimcommands/BimBuilder.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimBuildingPart.py b/src/Mod/BIM/bimcommands/BimBuildingPart.py index e90326e7e8..8fd942d0f1 100644 --- a/src/Mod/BIM/bimcommands/BimBuildingPart.py +++ b/src/Mod/BIM/bimcommands/BimBuildingPart.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * @@ -56,7 +58,7 @@ class Arch_Level: FreeCADGui.addModule("Arch") FreeCADGui.addModule("Draft") FreeCADGui.addModule("WorkingPlane") - FreeCADGui.doCommand("obj = Arch.makeFloor(FreeCADGui.Selection.getSelection())") + FreeCADGui.doCommand("obj = Arch.makeFloor(FreeCADGui.Selection.getSelection())") FreeCADGui.doCommand("obj.Placement = WorkingPlane.get_working_plane().get_placement()") FreeCADGui.doCommand("Draft.autogroup(obj)") FreeCAD.ActiveDocument.commitTransaction() diff --git a/src/Mod/BIM/bimcommands/BimClassification.py b/src/Mod/BIM/bimcommands/BimClassification.py index 32c1efed23..14f290e6a5 100644 --- a/src/Mod/BIM/bimcommands/BimClassification.py +++ b/src/Mod/BIM/bimcommands/BimClassification.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimClone.py b/src/Mod/BIM/bimcommands/BimClone.py index 872e5fb252..74ad9e8118 100644 --- a/src/Mod/BIM/bimcommands/BimClone.py +++ b/src/Mod/BIM/bimcommands/BimClone.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimColumn.py b/src/Mod/BIM/bimcommands/BimColumn.py index 994e3daa44..2877508b94 100644 --- a/src/Mod/BIM/bimcommands/BimColumn.py +++ b/src/Mod/BIM/bimcommands/BimColumn.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimCommon.py b/src/Mod/BIM/bimcommands/BimCommon.py index d3e720b00d..22a8d5f2fe 100644 --- a/src/Mod/BIM/bimcommands/BimCommon.py +++ b/src/Mod/BIM/bimcommands/BimCommon.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimCompound.py b/src/Mod/BIM/bimcommands/BimCompound.py index 216fe7fd5e..dbd5714de6 100644 --- a/src/Mod/BIM/bimcommands/BimCompound.py +++ b/src/Mod/BIM/bimcommands/BimCompound.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimConvert.py b/src/Mod/BIM/bimcommands/BimConvert.py index 79377e2c30..9f689a6ebf 100644 --- a/src/Mod/BIM/bimcommands/BimConvert.py +++ b/src/Mod/BIM/bimcommands/BimConvert.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimCopy.py b/src/Mod/BIM/bimcommands/BimCopy.py index d247753ed2..8beecc6750 100644 --- a/src/Mod/BIM/bimcommands/BimCopy.py +++ b/src/Mod/BIM/bimcommands/BimCopy.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimCurtainwall.py b/src/Mod/BIM/bimcommands/BimCurtainwall.py index 7dd821d0e1..2d24d03540 100644 --- a/src/Mod/BIM/bimcommands/BimCurtainwall.py +++ b/src/Mod/BIM/bimcommands/BimCurtainwall.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimCut.py b/src/Mod/BIM/bimcommands/BimCut.py index e9dca8d967..2f2a716b90 100644 --- a/src/Mod/BIM/bimcommands/BimCut.py +++ b/src/Mod/BIM/bimcommands/BimCut.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimCutPlane.py b/src/Mod/BIM/bimcommands/BimCutPlane.py index a19280a8ec..22c6f9fe8f 100644 --- a/src/Mod/BIM/bimcommands/BimCutPlane.py +++ b/src/Mod/BIM/bimcommands/BimCutPlane.py @@ -1,25 +1,28 @@ -#***************************************************************************** -#* Copyright (c) 2014 Jonathan Wiedemann (cutplan) * -#* Copyright (c) 2019 Jerome Laverroux (cutline)* -#* Copyright (c) 2023 FreeCAD Project Association * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* 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 * -#* * -#***************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# ***************************************************************************** +# * * +# * Copyright (c) 2014 Jonathan Wiedemann (cutplan) * +# * Copyright (c) 2019 Jerome Laverroux (cutline)* +# * Copyright (c) 2023 FreeCAD Project Association * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * 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 * +# * * +# ***************************************************************************** """The Arch CutPlane command""" diff --git a/src/Mod/BIM/bimcommands/BimDiff.py b/src/Mod/BIM/bimcommands/BimDiff.py index 0205a52f93..cef4db17ad 100644 --- a/src/Mod/BIM/bimcommands/BimDiff.py +++ b/src/Mod/BIM/bimcommands/BimDiff.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2019 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimDimensions.py b/src/Mod/BIM/bimcommands/BimDimensions.py index 18a8bd8f98..5edd401fd8 100644 --- a/src/Mod/BIM/bimcommands/BimDimensions.py +++ b/src/Mod/BIM/bimcommands/BimDimensions.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimDoor.py b/src/Mod/BIM/bimcommands/BimDoor.py index d6598fce1d..366b52e086 100644 --- a/src/Mod/BIM/bimcommands/BimDoor.py +++ b/src/Mod/BIM/bimcommands/BimDoor.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimDrawingView.py b/src/Mod/BIM/bimcommands/BimDrawingView.py index 637a68fd01..e49a53bd8e 100644 --- a/src/Mod/BIM/bimcommands/BimDrawingView.py +++ b/src/Mod/BIM/bimcommands/BimDrawingView.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimEmptyTrash.py b/src/Mod/BIM/bimcommands/BimEmptyTrash.py index 5feeb10cff..c2b0c2c851 100644 --- a/src/Mod/BIM/bimcommands/BimEmptyTrash.py +++ b/src/Mod/BIM/bimcommands/BimEmptyTrash.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimEquipment.py b/src/Mod/BIM/bimcommands/BimEquipment.py index e0bc19f7a7..b7687e4a6e 100644 --- a/src/Mod/BIM/bimcommands/BimEquipment.py +++ b/src/Mod/BIM/bimcommands/BimEquipment.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimExamples.py b/src/Mod/BIM/bimcommands/BimExamples.py index 6661f47308..8fa9581415 100644 --- a/src/Mod/BIM/bimcommands/BimExamples.py +++ b/src/Mod/BIM/bimcommands/BimExamples.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimExtrude.py b/src/Mod/BIM/bimcommands/BimExtrude.py index 6a37b4cd62..7069acf2ef 100644 --- a/src/Mod/BIM/bimcommands/BimExtrude.py +++ b/src/Mod/BIM/bimcommands/BimExtrude.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimFence.py b/src/Mod/BIM/bimcommands/BimFence.py index 2592c32c13..5534fd85b8 100644 --- a/src/Mod/BIM/bimcommands/BimFence.py +++ b/src/Mod/BIM/bimcommands/BimFence.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimFrame.py b/src/Mod/BIM/bimcommands/BimFrame.py index da946eb765..5177f2a1b2 100644 --- a/src/Mod/BIM/bimcommands/BimFrame.py +++ b/src/Mod/BIM/bimcommands/BimFrame.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * @@ -62,4 +64,3 @@ class Arch_Frame: FreeCADGui.addCommand('Arch_Frame',Arch_Frame()) - diff --git a/src/Mod/BIM/bimcommands/BimFuse.py b/src/Mod/BIM/bimcommands/BimFuse.py index b33b1edca9..e2a3f8e6ae 100644 --- a/src/Mod/BIM/bimcommands/BimFuse.py +++ b/src/Mod/BIM/bimcommands/BimFuse.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimGlue.py b/src/Mod/BIM/bimcommands/BimGlue.py index 81f2534978..4f0d40b6ee 100644 --- a/src/Mod/BIM/bimcommands/BimGlue.py +++ b/src/Mod/BIM/bimcommands/BimGlue.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimHelp.py b/src/Mod/BIM/bimcommands/BimHelp.py index 1df2bdb66b..593f80673f 100644 --- a/src/Mod/BIM/bimcommands/BimHelp.py +++ b/src/Mod/BIM/bimcommands/BimHelp.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimIfcElements.py b/src/Mod/BIM/bimcommands/BimIfcElements.py index 123afb057b..a0c9a06a4e 100644 --- a/src/Mod/BIM/bimcommands/BimIfcElements.py +++ b/src/Mod/BIM/bimcommands/BimIfcElements.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimIfcExplorer.py b/src/Mod/BIM/bimcommands/BimIfcExplorer.py index fc772f8976..919a613280 100644 --- a/src/Mod/BIM/bimcommands/BimIfcExplorer.py +++ b/src/Mod/BIM/bimcommands/BimIfcExplorer.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2019 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimIfcProperties.py b/src/Mod/BIM/bimcommands/BimIfcProperties.py index 02a8f42b16..1a68db3ebc 100644 --- a/src/Mod/BIM/bimcommands/BimIfcProperties.py +++ b/src/Mod/BIM/bimcommands/BimIfcProperties.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimIfcQuantities.py b/src/Mod/BIM/bimcommands/BimIfcQuantities.py index f1ea3d0b19..9ec97c4f8d 100644 --- a/src/Mod/BIM/bimcommands/BimIfcQuantities.py +++ b/src/Mod/BIM/bimcommands/BimIfcQuantities.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimImagePlane.py b/src/Mod/BIM/bimcommands/BimImagePlane.py index f171639c09..7ab3b0fe2c 100644 --- a/src/Mod/BIM/bimcommands/BimImagePlane.py +++ b/src/Mod/BIM/bimcommands/BimImagePlane.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimLayers.py b/src/Mod/BIM/bimcommands/BimLayers.py index 4ad159229b..43e05c102e 100644 --- a/src/Mod/BIM/bimcommands/BimLayers.py +++ b/src/Mod/BIM/bimcommands/BimLayers.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2019 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimLeader.py b/src/Mod/BIM/bimcommands/BimLeader.py index 6f65590b79..ec15c7124c 100644 --- a/src/Mod/BIM/bimcommands/BimLeader.py +++ b/src/Mod/BIM/bimcommands/BimLeader.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimLibrary.py b/src/Mod/BIM/bimcommands/BimLibrary.py index 40c9607ee9..f1d0bef6ff 100644 --- a/src/Mod/BIM/bimcommands/BimLibrary.py +++ b/src/Mod/BIM/bimcommands/BimLibrary.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- + +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimMaterial.py b/src/Mod/BIM/bimcommands/BimMaterial.py index f241a638b2..85ec5cbe11 100644 --- a/src/Mod/BIM/bimcommands/BimMaterial.py +++ b/src/Mod/BIM/bimcommands/BimMaterial.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimMoveView.py b/src/Mod/BIM/bimcommands/BimMoveView.py index b2832c5297..12bc15f885 100644 --- a/src/Mod/BIM/bimcommands/BimMoveView.py +++ b/src/Mod/BIM/bimcommands/BimMoveView.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimNudge.py b/src/Mod/BIM/bimcommands/BimNudge.py index 25186739f6..96b1db927b 100644 --- a/src/Mod/BIM/bimcommands/BimNudge.py +++ b/src/Mod/BIM/bimcommands/BimNudge.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimOffset.py b/src/Mod/BIM/bimcommands/BimOffset.py index 406d629882..b323b89fd0 100644 --- a/src/Mod/BIM/bimcommands/BimOffset.py +++ b/src/Mod/BIM/bimcommands/BimOffset.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimPanel.py b/src/Mod/BIM/bimcommands/BimPanel.py index c0cbb7352f..4b692625b5 100644 --- a/src/Mod/BIM/bimcommands/BimPanel.py +++ b/src/Mod/BIM/bimcommands/BimPanel.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimPipe.py b/src/Mod/BIM/bimcommands/BimPipe.py index 82bfe2fe1c..710af04aa2 100644 --- a/src/Mod/BIM/bimcommands/BimPipe.py +++ b/src/Mod/BIM/bimcommands/BimPipe.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimPreflight.py b/src/Mod/BIM/bimcommands/BimPreflight.py index 11fc0acdf7..2ae196e88c 100644 --- a/src/Mod/BIM/bimcommands/BimPreflight.py +++ b/src/Mod/BIM/bimcommands/BimPreflight.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimProfile.py b/src/Mod/BIM/bimcommands/BimProfile.py index d6cbc3b8b6..042de19235 100644 --- a/src/Mod/BIM/bimcommands/BimProfile.py +++ b/src/Mod/BIM/bimcommands/BimProfile.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimProject.py b/src/Mod/BIM/bimcommands/BimProject.py index 3f0f5a705c..d38a3de5c1 100644 --- a/src/Mod/BIM/bimcommands/BimProject.py +++ b/src/Mod/BIM/bimcommands/BimProject.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index c0bf3d6ff2..853f67dd9f 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimRebar.py b/src/Mod/BIM/bimcommands/BimRebar.py index 02bc0cdbee..b916ec141a 100644 --- a/src/Mod/BIM/bimcommands/BimRebar.py +++ b/src/Mod/BIM/bimcommands/BimRebar.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimReextrude.py b/src/Mod/BIM/bimcommands/BimReextrude.py index b21f06a51a..68e9815b06 100644 --- a/src/Mod/BIM/bimcommands/BimReextrude.py +++ b/src/Mod/BIM/bimcommands/BimReextrude.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimReference.py b/src/Mod/BIM/bimcommands/BimReference.py index 0a00ab5478..126d768947 100644 --- a/src/Mod/BIM/bimcommands/BimReference.py +++ b/src/Mod/BIM/bimcommands/BimReference.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimReorder.py b/src/Mod/BIM/bimcommands/BimReorder.py index 34eff7841c..5bd1065714 100644 --- a/src/Mod/BIM/bimcommands/BimReorder.py +++ b/src/Mod/BIM/bimcommands/BimReorder.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2021 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimResetCloneColors.py b/src/Mod/BIM/bimcommands/BimResetCloneColors.py index 7ef23d4e63..09fb53a28f 100644 --- a/src/Mod/BIM/bimcommands/BimResetCloneColors.py +++ b/src/Mod/BIM/bimcommands/BimResetCloneColors.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimRewire.py b/src/Mod/BIM/bimcommands/BimRewire.py index 869bcc6076..76e88ed311 100644 --- a/src/Mod/BIM/bimcommands/BimRewire.py +++ b/src/Mod/BIM/bimcommands/BimRewire.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimRoof.py b/src/Mod/BIM/bimcommands/BimRoof.py index 97e097be76..f0a9f8b8bb 100644 --- a/src/Mod/BIM/bimcommands/BimRoof.py +++ b/src/Mod/BIM/bimcommands/BimRoof.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * @@ -83,4 +85,3 @@ class Arch_Roof: FreeCADGui.addCommand("Arch_Roof", Arch_Roof()) - diff --git a/src/Mod/BIM/bimcommands/BimSchedule.py b/src/Mod/BIM/bimcommands/BimSchedule.py index 8018925232..808a3ce451 100644 --- a/src/Mod/BIM/bimcommands/BimSchedule.py +++ b/src/Mod/BIM/bimcommands/BimSchedule.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSectionPlane.py b/src/Mod/BIM/bimcommands/BimSectionPlane.py index c6a326b27a..4f92fbc4d0 100644 --- a/src/Mod/BIM/bimcommands/BimSectionPlane.py +++ b/src/Mod/BIM/bimcommands/BimSectionPlane.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSetup.py b/src/Mod/BIM/bimcommands/BimSetup.py index c5ea7ef468..e03937f9b1 100644 --- a/src/Mod/BIM/bimcommands/BimSetup.py +++ b/src/Mod/BIM/bimcommands/BimSetup.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimShape2DView.py b/src/Mod/BIM/bimcommands/BimShape2DView.py index 3d69e95c34..5c73dc04c3 100644 --- a/src/Mod/BIM/bimcommands/BimShape2DView.py +++ b/src/Mod/BIM/bimcommands/BimShape2DView.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSimpleCopy.py b/src/Mod/BIM/bimcommands/BimSimpleCopy.py index 1bf6b5edfc..501c903059 100644 --- a/src/Mod/BIM/bimcommands/BimSimpleCopy.py +++ b/src/Mod/BIM/bimcommands/BimSimpleCopy.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSite.py b/src/Mod/BIM/bimcommands/BimSite.py index 0fb487e83a..4093922c34 100644 --- a/src/Mod/BIM/bimcommands/BimSite.py +++ b/src/Mod/BIM/bimcommands/BimSite.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSketch.py b/src/Mod/BIM/bimcommands/BimSketch.py index 355d1c4732..5f325d7627 100644 --- a/src/Mod/BIM/bimcommands/BimSketch.py +++ b/src/Mod/BIM/bimcommands/BimSketch.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSlab.py b/src/Mod/BIM/bimcommands/BimSlab.py index 8a23ea471c..a090a1dac0 100644 --- a/src/Mod/BIM/bimcommands/BimSlab.py +++ b/src/Mod/BIM/bimcommands/BimSlab.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimSpace.py b/src/Mod/BIM/bimcommands/BimSpace.py index a05e39ff0f..e0216ea319 100644 --- a/src/Mod/BIM/bimcommands/BimSpace.py +++ b/src/Mod/BIM/bimcommands/BimSpace.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimStairs.py b/src/Mod/BIM/bimcommands/BimStairs.py index 1491de5645..166c8c7a16 100644 --- a/src/Mod/BIM/bimcommands/BimStairs.py +++ b/src/Mod/BIM/bimcommands/BimStairs.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimTDPage.py b/src/Mod/BIM/bimcommands/BimTDPage.py index f1f5966dd0..aadb642f8e 100644 --- a/src/Mod/BIM/bimcommands/BimTDPage.py +++ b/src/Mod/BIM/bimcommands/BimTDPage.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimTDView.py b/src/Mod/BIM/bimcommands/BimTDView.py index a80c0819d4..50bd30c857 100644 --- a/src/Mod/BIM/bimcommands/BimTDView.py +++ b/src/Mod/BIM/bimcommands/BimTDView.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimText.py b/src/Mod/BIM/bimcommands/BimText.py index f7b1fd3800..b7c4904eaa 100644 --- a/src/Mod/BIM/bimcommands/BimText.py +++ b/src/Mod/BIM/bimcommands/BimText.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * @@ -87,4 +89,3 @@ class BIM_Text: FreeCADGui.addCommand("BIM_Text", BIM_Text()) - diff --git a/src/Mod/BIM/bimcommands/BimTogglePanels.py b/src/Mod/BIM/bimcommands/BimTogglePanels.py index b77da954fe..b277d4052c 100644 --- a/src/Mod/BIM/bimcommands/BimTogglePanels.py +++ b/src/Mod/BIM/bimcommands/BimTogglePanels.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimTrash.py b/src/Mod/BIM/bimcommands/BimTrash.py index fc0db35cec..eb7e9be860 100644 --- a/src/Mod/BIM/bimcommands/BimTrash.py +++ b/src/Mod/BIM/bimcommands/BimTrash.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimTruss.py b/src/Mod/BIM/bimcommands/BimTruss.py index 6aab7bc40b..009d036a8d 100644 --- a/src/Mod/BIM/bimcommands/BimTruss.py +++ b/src/Mod/BIM/bimcommands/BimTruss.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimTutorial.py b/src/Mod/BIM/bimcommands/BimTutorial.py index e7b53e3dbc..c556772ee9 100644 --- a/src/Mod/BIM/bimcommands/BimTutorial.py +++ b/src/Mod/BIM/bimcommands/BimTutorial.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimUnclone.py b/src/Mod/BIM/bimcommands/BimUnclone.py index c6c7c78f6a..7864573232 100644 --- a/src/Mod/BIM/bimcommands/BimUnclone.py +++ b/src/Mod/BIM/bimcommands/BimUnclone.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimUngroup.py b/src/Mod/BIM/bimcommands/BimUngroup.py index 1b6ab04147..9411465c49 100644 --- a/src/Mod/BIM/bimcommands/BimUngroup.py +++ b/src/Mod/BIM/bimcommands/BimUngroup.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimViews.py b/src/Mod/BIM/bimcommands/BimViews.py index 1c03676a87..fd065a40ee 100644 --- a/src/Mod/BIM/bimcommands/BimViews.py +++ b/src/Mod/BIM/bimcommands/BimViews.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimWPCommands.py b/src/Mod/BIM/bimcommands/BimWPCommands.py index bc1e66833b..495c883192 100644 --- a/src/Mod/BIM/bimcommands/BimWPCommands.py +++ b/src/Mod/BIM/bimcommands/BimWPCommands.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimWall.py b/src/Mod/BIM/bimcommands/BimWall.py index 4c65847aa0..7de5e9158c 100644 --- a/src/Mod/BIM/bimcommands/BimWall.py +++ b/src/Mod/BIM/bimcommands/BimWall.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimWelcome.py b/src/Mod/BIM/bimcommands/BimWelcome.py index f06e52e2c4..d13cec29e2 100644 --- a/src/Mod/BIM/bimcommands/BimWelcome.py +++ b/src/Mod/BIM/bimcommands/BimWelcome.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimWindow.py b/src/Mod/BIM/bimcommands/BimWindow.py index a65114acb4..f82a47e418 100644 --- a/src/Mod/BIM/bimcommands/BimWindow.py +++ b/src/Mod/BIM/bimcommands/BimWindow.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/bimcommands/BimWindows.py b/src/Mod/BIM/bimcommands/BimWindows.py index 65839f26e4..f91e4de417 100644 --- a/src/Mod/BIM/bimcommands/BimWindows.py +++ b/src/Mod/BIM/bimcommands/BimWindows.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2017 Yorik van Havre * diff --git a/src/Mod/BIM/bimtests/TestArchBase.py b/src/Mod/BIM/bimtests/TestArchBase.py index 4394d90f29..00cbcac583 100644 --- a/src/Mod/BIM/bimtests/TestArchBase.py +++ b/src/Mod/BIM/bimtests/TestArchBase.py @@ -1,4 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2025 Furgo * @@ -36,7 +37,7 @@ class TestArchBase(unittest.TestCase): def printTestMessage(self, text, prepend_text="Test ", end="\n"): """Write messages to the console including the line ending. - + Messages will be prepended with "Test ", unless an empty string is passed as the prepend_text argument """ diff --git a/src/Mod/BIM/bimtests/TestArchRoof.py b/src/Mod/BIM/bimtests/TestArchRoof.py index ded401712a..f7af8014bf 100644 --- a/src/Mod/BIM/bimtests/TestArchRoof.py +++ b/src/Mod/BIM/bimtests/TestArchRoof.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2013 Yorik van Havre * -#* * -#* This file is part of the FreeCAD CAx development system. * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#***************************************************************************/ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 Yorik van Havre * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** # Unit tests for the Arch wall module @@ -146,5 +149,3 @@ class TestArchRoof(TestArchBase.TestArchBase): roof.recompute() self.assertFalse(roof.Shape.isNull(), "'{}' failed".format(operation)) self.assertTrue(roof.Shape.isValid(), "'{}' failed".format(operation)) - - diff --git a/src/Mod/BIM/bimtests/TestArchSpace.py b/src/Mod/BIM/bimtests/TestArchSpace.py index a542fb9129..75c3216834 100644 --- a/src/Mod/BIM/bimtests/TestArchSpace.py +++ b/src/Mod/BIM/bimtests/TestArchSpace.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2013 Yorik van Havre * -#* * -#* This file is part of the FreeCAD CAx development system. * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#***************************************************************************/ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 Yorik van Havre * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** # Unit tests for the Arch space module @@ -89,7 +92,7 @@ class TestArchSpace(TestArchBase.TestArchBase): App.ActiveDocument.recompute() # To calculate area # Create the wall - trace = Part.LineSegment(App.Vector (3000.0, 1000.0, 0.0), + trace = Part.LineSegment(App.Vector (3000.0, 1000.0, 0.0), App.Vector (-3000.0, 1000.0, 0.0)) wp = WorkingPlane.get_working_plane() base = App.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace") @@ -110,7 +113,7 @@ class TestArchSpace(TestArchBase.TestArchBase): self.assertAlmostEqual( expectedArea.Value, actualArea.Value, - msg = (f"Invalid area value. " + + msg = (f"Invalid area value. " + f"Expected: {expectedArea.UserString}, actual: {actualArea.UserString}")) def test_SpaceFromSingleWall(self): diff --git a/src/Mod/BIM/bimtests/TestArchWall.py b/src/Mod/BIM/bimtests/TestArchWall.py index 64c3676e85..7a5add3aac 100644 --- a/src/Mod/BIM/bimtests/TestArchWall.py +++ b/src/Mod/BIM/bimtests/TestArchWall.py @@ -1,25 +1,28 @@ -#*************************************************************************** -#* Copyright (c) 2013 Yorik van Havre * -#* * -#* This file is part of the FreeCAD CAx development system. * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#***************************************************************************/ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 Yorik van Havre * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** # Unit tests for the Arch wall module @@ -82,4 +85,3 @@ class TestArchWall(TestArchBase.TestArchBase): ptMax = App.Vector(box.XMax, box.YMax, 0) self.assertTrue(ptMax.isEqual(checkLst[i][1], 1e-8), "Arch Wall with MultiMaterial and 3 alignments failed") - diff --git a/src/Mod/BIM/ifc_objects.py b/src/Mod/BIM/ifc_objects.py index b0cd9e51dc..ba039e4a12 100644 --- a/src/Mod/BIM/ifc_objects.py +++ b/src/Mod/BIM/ifc_objects.py @@ -1,24 +1,26 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2022 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Library General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2022 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Library General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * 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 * +# * * +# *************************************************************************** class ifc_object: """NativeIFC class placeholder""" diff --git a/src/Mod/BIM/ifc_viewproviders.py b/src/Mod/BIM/ifc_viewproviders.py index 8f6c01f5c7..f7f0155d07 100644 --- a/src/Mod/BIM/ifc_viewproviders.py +++ b/src/Mod/BIM/ifc_viewproviders.py @@ -1,24 +1,26 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2022 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Library General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2022 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Library General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * 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 placeholders for viewproviders provided by the NativeIFC addon""" diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index fcec025928..73ef139952 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2014 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/exportIFCHelper.py b/src/Mod/BIM/importers/exportIFCHelper.py index 8e153de3af..3ebda8ff94 100644 --- a/src/Mod/BIM/importers/exportIFCHelper.py +++ b/src/Mod/BIM/importers/exportIFCHelper.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2019 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/exportIFCStructuralTools.py b/src/Mod/BIM/importers/exportIFCStructuralTools.py index 6d9d34918d..74f1fc9d41 100644 --- a/src/Mod/BIM/importers/exportIFCStructuralTools.py +++ b/src/Mod/BIM/importers/exportIFCStructuralTools.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2020 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/import3DS.py b/src/Mod/BIM/importers/import3DS.py index 0027c25c1b..89dfc8b79d 100644 --- a/src/Mod/BIM/importers/import3DS.py +++ b/src/Mod/BIM/importers/import3DS.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2016 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2016 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 * +# * * +# *************************************************************************** import os,FreeCAD,Mesh diff --git a/src/Mod/BIM/importers/importDAE.py b/src/Mod/BIM/importers/importDAE.py index 9a3797dae4..b29270705c 100644 --- a/src/Mod/BIM/importers/importDAE.py +++ b/src/Mod/BIM/importers/importDAE.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import os from typing import Optional diff --git a/src/Mod/BIM/importers/importGBXML.py b/src/Mod/BIM/importers/importGBXML.py index 5cc0f5ea18..1f2f597a06 100644 --- a/src/Mod/BIM/importers/importGBXML.py +++ b/src/Mod/BIM/importers/importGBXML.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2015 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2015 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 GbXml exporter" __author__ = "Yorik van Havre" diff --git a/src/Mod/BIM/importers/importIFC.py b/src/Mod/BIM/importers/importIFC.py index 8689280076..48a1d21eb9 100644 --- a/src/Mod/BIM/importers/importIFC.py +++ b/src/Mod/BIM/importers/importIFC.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2014 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/importIFCHelper.py b/src/Mod/BIM/importers/importIFCHelper.py index d140cab8e7..83ca7b2eed 100644 --- a/src/Mod/BIM/importers/importIFCHelper.py +++ b/src/Mod/BIM/importers/importIFCHelper.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2019 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/importIFClegacy.py b/src/Mod/BIM/importers/importIFClegacy.py index fbbf9a8f07..5fb41a9b44 100644 --- a/src/Mod/BIM/importers/importIFClegacy.py +++ b/src/Mod/BIM/importers/importIFClegacy.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** # WARNING ################################################################## # # diff --git a/src/Mod/BIM/importers/importIFCmulticore.py b/src/Mod/BIM/importers/importIFCmulticore.py index f54ee00e4d..1f87c9337a 100644 --- a/src/Mod/BIM/importers/importIFCmulticore.py +++ b/src/Mod/BIM/importers/importIFCmulticore.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2020 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/importJSON.py b/src/Mod/BIM/importers/importJSON.py index 74e6e27aff..0e206178b6 100644 --- a/src/Mod/BIM/importers/importJSON.py +++ b/src/Mod/BIM/importers/importJSON.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2017 Joseph Coffland * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2017 Joseph Coffland * +# * * +# * 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 * +# * * +# *************************************************************************** """FreeCAD JSON exporter""" diff --git a/src/Mod/BIM/importers/importOBJ.py b/src/Mod/BIM/importers/importOBJ.py index 8533ad578a..bab1fb50f3 100644 --- a/src/Mod/BIM/importers/importOBJ.py +++ b/src/Mod/BIM/importers/importOBJ.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2011 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2011 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 * +# * * +# *************************************************************************** import os import codecs diff --git a/src/Mod/BIM/importers/importSH3D.py b/src/Mod/BIM/importers/importSH3D.py index 5a1cc189e5..e800d4b465 100644 --- a/src/Mod/BIM/importers/importSH3D.py +++ b/src/Mod/BIM/importers/importSH3D.py @@ -1,23 +1,26 @@ -#*************************************************************************** -#* Copyright (c) 2016 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2016 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 SweetHome3D Importer" __author__ = "Yorik van Havre" diff --git a/src/Mod/BIM/importers/importSH3DHelper.py b/src/Mod/BIM/importers/importSH3DHelper.py index 22d4f079c7..c1cb5c91cd 100644 --- a/src/Mod/BIM/importers/importSH3DHelper.py +++ b/src/Mod/BIM/importers/importSH3DHelper.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2024 Julien Masnada * # * * # * This program is free software; you can redistribute it and/or modify * diff --git a/src/Mod/BIM/importers/importSHP.py b/src/Mod/BIM/importers/importSHP.py index 1ead995ccf..5758250446 100644 --- a/src/Mod/BIM/importers/importSHP.py +++ b/src/Mod/BIM/importers/importSHP.py @@ -1,24 +1,28 @@ # -*- coding: utf-8 -*- -#*************************************************************************** -#* Copyright (c) 2020 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 * -#* * -#*************************************************************************** + +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2020 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 * +# * * +# *************************************************************************** import os from builtins import open as pyopen diff --git a/src/Mod/BIM/importers/importWebGL.py b/src/Mod/BIM/importers/importWebGL.py index d84b241fce..df8e68c793 100644 --- a/src/Mod/BIM/importers/importWebGL.py +++ b/src/Mod/BIM/importers/importWebGL.py @@ -1,24 +1,27 @@ -#*************************************************************************** -#* Copyright (c) 2013 Yorik van Havre * -#* Copyright (c) 2020 Travis Apple * -#* * -#* 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 * -#* * -#*************************************************************************** +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * * +# * Copyright (c) 2013 Yorik van Havre * +# * Copyright (c) 2020 Travis Apple * +# * * +# * 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 * +# * * +# *************************************************************************** # # REFS: # https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_buffergeometry.html diff --git a/src/Mod/BIM/nativeifc/ifc_classification.py b/src/Mod/BIM/nativeifc/ifc_classification.py index 18de9a170f..e2d45f3e38 100644 --- a/src/Mod/BIM/nativeifc/ifc_classification.py +++ b/src/Mod/BIM/nativeifc/ifc_classification.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * diff --git a/src/Mod/BIM/nativeifc/ifc_commands.py b/src/Mod/BIM/nativeifc/ifc_commands.py index 25591cdc01..36c116866d 100644 --- a/src/Mod/BIM/nativeifc/ifc_commands.py +++ b/src/Mod/BIM/nativeifc/ifc_commands.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_diff.py b/src/Mod/BIM/nativeifc/ifc_diff.py index 43cf4822be..28c7e753a2 100644 --- a/src/Mod/BIM/nativeifc/ifc_diff.py +++ b/src/Mod/BIM/nativeifc/ifc_diff.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index 91001de2df..b8737835a1 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_generator.py b/src/Mod/BIM/nativeifc/ifc_generator.py index 4c01bf2501..9f5b95c840 100644 --- a/src/Mod/BIM/nativeifc/ifc_generator.py +++ b/src/Mod/BIM/nativeifc/ifc_generator.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_geometry.py b/src/Mod/BIM/nativeifc/ifc_geometry.py index 1cdda68be9..88126e2ea2 100644 --- a/src/Mod/BIM/nativeifc/ifc_geometry.py +++ b/src/Mod/BIM/nativeifc/ifc_geometry.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_import.py b/src/Mod/BIM/nativeifc/ifc_import.py index 5a51801e28..8bad9e81e3 100644 --- a/src/Mod/BIM/nativeifc/ifc_import.py +++ b/src/Mod/BIM/nativeifc/ifc_import.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_layers.py b/src/Mod/BIM/nativeifc/ifc_layers.py index f4fa9ab0dc..e8c918b5d7 100644 --- a/src/Mod/BIM/nativeifc/ifc_layers.py +++ b/src/Mod/BIM/nativeifc/ifc_layers.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_materials.py b/src/Mod/BIM/nativeifc/ifc_materials.py index e925116a26..1f6982260e 100644 --- a/src/Mod/BIM/nativeifc/ifc_materials.py +++ b/src/Mod/BIM/nativeifc/ifc_materials.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_objects.py b/src/Mod/BIM/nativeifc/ifc_objects.py index c3350dab3e..80f94ca6d8 100644 --- a/src/Mod/BIM/nativeifc/ifc_objects.py +++ b/src/Mod/BIM/nativeifc/ifc_objects.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_observer.py b/src/Mod/BIM/nativeifc/ifc_observer.py index f650c91101..e3b9a219f5 100644 --- a/src/Mod/BIM/nativeifc/ifc_observer.py +++ b/src/Mod/BIM/nativeifc/ifc_observer.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_openshell.py b/src/Mod/BIM/nativeifc/ifc_openshell.py index f38b866ee4..ae98728199 100644 --- a/src/Mod/BIM/nativeifc/ifc_openshell.py +++ b/src/Mod/BIM/nativeifc/ifc_openshell.py @@ -1,5 +1,7 @@ # -*- coding: utf8 -*- +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * @@ -15,10 +17,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** @@ -139,7 +141,7 @@ class IFC_UpdateIOS: try: import ifcopenshell - version = ifcopenshell.version + version = ifcopenshell.version try: Version(version) except InvalidVersion: diff --git a/src/Mod/BIM/nativeifc/ifc_performance_test.py b/src/Mod/BIM/nativeifc/ifc_performance_test.py index 7fb7740cd1..41db2f4434 100644 --- a/src/Mod/BIM/nativeifc/ifc_performance_test.py +++ b/src/Mod/BIM/nativeifc/ifc_performance_test.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_psets.py b/src/Mod/BIM/nativeifc/ifc_psets.py index bc4d993690..7a743c6301 100644 --- a/src/Mod/BIM/nativeifc/ifc_psets.py +++ b/src/Mod/BIM/nativeifc/ifc_psets.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_selftest.py b/src/Mod/BIM/nativeifc/ifc_selftest.py index 25300dd909..004a3a8210 100644 --- a/src/Mod/BIM/nativeifc/ifc_selftest.py +++ b/src/Mod/BIM/nativeifc/ifc_selftest.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_status.py b/src/Mod/BIM/nativeifc/ifc_status.py index a75375b509..ebd612d3b5 100644 --- a/src/Mod/BIM/nativeifc/ifc_status.py +++ b/src/Mod/BIM/nativeifc/ifc_status.py @@ -1,4 +1,7 @@ # -*- coding: utf8 -*- + +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2024 Yorik van Havre * @@ -14,10 +17,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index 3330f6e007..ad2e47bd45 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * diff --git a/src/Mod/BIM/nativeifc/ifc_tree.py b/src/Mod/BIM/nativeifc/ifc_tree.py index 334e3e1931..82a0ef929b 100644 --- a/src/Mod/BIM/nativeifc/ifc_tree.py +++ b/src/Mod/BIM/nativeifc/ifc_tree.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * @@ -13,10 +15,10 @@ # * 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 * +# * 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 * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_types.py b/src/Mod/BIM/nativeifc/ifc_types.py index 295d3cc8dd..bbde502a32 100644 --- a/src/Mod/BIM/nativeifc/ifc_types.py +++ b/src/Mod/BIM/nativeifc/ifc_types.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2023 Yorik van Havre * diff --git a/src/Mod/BIM/nativeifc/ifc_viewproviders.py b/src/Mod/BIM/nativeifc/ifc_viewproviders.py index 13f0c6bd43..af17cce3a3 100644 --- a/src/Mod/BIM/nativeifc/ifc_viewproviders.py +++ b/src/Mod/BIM/nativeifc/ifc_viewproviders.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2022 Yorik van Havre * diff --git a/src/Mod/BIM/utils/buildPsets.py b/src/Mod/BIM/utils/buildPsets.py index f08ba2277e..b68225cddf 100644 --- a/src/Mod/BIM/utils/buildPsets.py +++ b/src/Mod/BIM/utils/buildPsets.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** # * * # * Copyright (c) 2018 Yorik van Havre * diff --git a/src/Mod/BIM/utils/ifctree.py b/src/Mod/BIM/utils/ifctree.py index a1e3e38969..fa080d40ed 100644 --- a/src/Mod/BIM/utils/ifctree.py +++ b/src/Mod/BIM/utils/ifctree.py @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + # *************************************************************************** +# * * # * Copyright (c) 2022 Yorik van Havre * # * * # * This program is free software; you can redistribute it and/or modify * From fcd0be749c0d6de5b27f209b7c6ef55bbef5b5b4 Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Fri, 4 Apr 2025 18:15:43 +0200 Subject: [PATCH 139/316] BIM: add FreeCAD notice in license --- src/Mod/BIM/Arch.py | 2 ++ src/Mod/BIM/ArchAxis.py | 2 ++ src/Mod/BIM/ArchAxisSystem.py | 2 ++ src/Mod/BIM/ArchBuilding.py | 2 ++ src/Mod/BIM/ArchBuildingPart.py | 2 ++ src/Mod/BIM/ArchCommands.py | 2 ++ src/Mod/BIM/ArchComponent.py | 2 ++ src/Mod/BIM/ArchCurtainWall.py | 2 ++ src/Mod/BIM/ArchCutPlane.py | 2 ++ src/Mod/BIM/ArchEquipment.py | 2 ++ src/Mod/BIM/ArchFence.py | 2 ++ src/Mod/BIM/ArchFloor.py | 2 ++ src/Mod/BIM/ArchFrame.py | 2 ++ src/Mod/BIM/ArchGrid.py | 2 ++ src/Mod/BIM/ArchIFC.py | 2 ++ src/Mod/BIM/ArchIFCSchema.py | 2 ++ src/Mod/BIM/ArchIFCView.py | 2 ++ src/Mod/BIM/ArchMaterial.py | 2 ++ src/Mod/BIM/ArchNesting.py | 2 ++ src/Mod/BIM/ArchPanel.py | 2 ++ src/Mod/BIM/ArchPipe.py | 2 ++ src/Mod/BIM/ArchPrecast.py | 2 ++ src/Mod/BIM/ArchProfile.py | 2 ++ src/Mod/BIM/ArchProject.py | 2 ++ src/Mod/BIM/ArchRebar.py | 2 ++ src/Mod/BIM/ArchReference.py | 2 ++ src/Mod/BIM/ArchRoof.py | 2 ++ src/Mod/BIM/ArchSchedule.py | 2 ++ src/Mod/BIM/ArchSectionPlane.py | 2 ++ src/Mod/BIM/ArchSite.py | 2 ++ src/Mod/BIM/ArchSketchObject.py | 2 ++ src/Mod/BIM/ArchSpace.py | 2 ++ src/Mod/BIM/ArchStairs.py | 2 ++ src/Mod/BIM/ArchStructure.py | 2 ++ src/Mod/BIM/ArchTruss.py | 2 ++ src/Mod/BIM/ArchVRM.py | 2 ++ src/Mod/BIM/ArchWall.py | 2 ++ src/Mod/BIM/ArchWindow.py | 2 ++ src/Mod/BIM/ArchWindowPresets.py | 2 ++ src/Mod/BIM/BimStatus.py | 2 ++ src/Mod/BIM/Init.py | 2 ++ src/Mod/BIM/InitGui.py | 2 ++ src/Mod/BIM/OfflineRenderingUtils.py | 2 ++ src/Mod/BIM/bimcommands/BimArchUtils.py | 2 ++ src/Mod/BIM/bimcommands/BimAxis.py | 2 ++ src/Mod/BIM/bimcommands/BimBackground.py | 2 ++ src/Mod/BIM/bimcommands/BimBeam.py | 2 ++ src/Mod/BIM/bimcommands/BimBox.py | 2 ++ src/Mod/BIM/bimcommands/BimBuilder.py | 2 ++ src/Mod/BIM/bimcommands/BimBuildingPart.py | 2 ++ src/Mod/BIM/bimcommands/BimClassification.py | 2 ++ src/Mod/BIM/bimcommands/BimClone.py | 2 ++ src/Mod/BIM/bimcommands/BimColumn.py | 2 ++ src/Mod/BIM/bimcommands/BimCommon.py | 2 ++ src/Mod/BIM/bimcommands/BimCompound.py | 2 ++ src/Mod/BIM/bimcommands/BimConvert.py | 2 ++ src/Mod/BIM/bimcommands/BimCopy.py | 2 ++ src/Mod/BIM/bimcommands/BimCurtainwall.py | 2 ++ src/Mod/BIM/bimcommands/BimCut.py | 2 ++ src/Mod/BIM/bimcommands/BimCutPlane.py | 2 ++ src/Mod/BIM/bimcommands/BimDiff.py | 2 ++ src/Mod/BIM/bimcommands/BimDimensions.py | 2 ++ src/Mod/BIM/bimcommands/BimDoor.py | 2 ++ src/Mod/BIM/bimcommands/BimDrawingView.py | 2 ++ src/Mod/BIM/bimcommands/BimEmptyTrash.py | 2 ++ src/Mod/BIM/bimcommands/BimEquipment.py | 2 ++ src/Mod/BIM/bimcommands/BimExamples.py | 2 ++ src/Mod/BIM/bimcommands/BimExtrude.py | 2 ++ src/Mod/BIM/bimcommands/BimFence.py | 2 ++ src/Mod/BIM/bimcommands/BimFrame.py | 2 ++ src/Mod/BIM/bimcommands/BimFuse.py | 2 ++ src/Mod/BIM/bimcommands/BimGlue.py | 2 ++ src/Mod/BIM/bimcommands/BimHelp.py | 2 ++ src/Mod/BIM/bimcommands/BimIfcElements.py | 2 ++ src/Mod/BIM/bimcommands/BimIfcExplorer.py | 2 ++ src/Mod/BIM/bimcommands/BimIfcProperties.py | 2 ++ src/Mod/BIM/bimcommands/BimIfcQuantities.py | 2 ++ src/Mod/BIM/bimcommands/BimImagePlane.py | 2 ++ src/Mod/BIM/bimcommands/BimLayers.py | 2 ++ src/Mod/BIM/bimcommands/BimLeader.py | 2 ++ src/Mod/BIM/bimcommands/BimLibrary.py | 2 ++ src/Mod/BIM/bimcommands/BimMaterial.py | 2 ++ src/Mod/BIM/bimcommands/BimMoveView.py | 2 ++ src/Mod/BIM/bimcommands/BimNudge.py | 2 ++ src/Mod/BIM/bimcommands/BimOffset.py | 2 ++ src/Mod/BIM/bimcommands/BimPanel.py | 2 ++ src/Mod/BIM/bimcommands/BimPipe.py | 2 ++ src/Mod/BIM/bimcommands/BimPreflight.py | 2 ++ src/Mod/BIM/bimcommands/BimProfile.py | 2 ++ src/Mod/BIM/bimcommands/BimProject.py | 2 ++ src/Mod/BIM/bimcommands/BimProjectManager.py | 2 ++ src/Mod/BIM/bimcommands/BimRebar.py | 2 ++ src/Mod/BIM/bimcommands/BimReextrude.py | 2 ++ src/Mod/BIM/bimcommands/BimReference.py | 2 ++ src/Mod/BIM/bimcommands/BimReorder.py | 2 ++ src/Mod/BIM/bimcommands/BimResetCloneColors.py | 2 ++ src/Mod/BIM/bimcommands/BimRewire.py | 2 ++ src/Mod/BIM/bimcommands/BimRoof.py | 2 ++ src/Mod/BIM/bimcommands/BimSchedule.py | 2 ++ src/Mod/BIM/bimcommands/BimSectionPlane.py | 2 ++ src/Mod/BIM/bimcommands/BimSetup.py | 2 ++ src/Mod/BIM/bimcommands/BimShape2DView.py | 2 ++ src/Mod/BIM/bimcommands/BimSimpleCopy.py | 2 ++ src/Mod/BIM/bimcommands/BimSite.py | 2 ++ src/Mod/BIM/bimcommands/BimSketch.py | 2 ++ src/Mod/BIM/bimcommands/BimSlab.py | 2 ++ src/Mod/BIM/bimcommands/BimSpace.py | 2 ++ src/Mod/BIM/bimcommands/BimStairs.py | 2 ++ src/Mod/BIM/bimcommands/BimTDPage.py | 2 ++ src/Mod/BIM/bimcommands/BimTDView.py | 2 ++ src/Mod/BIM/bimcommands/BimText.py | 2 ++ src/Mod/BIM/bimcommands/BimTogglePanels.py | 2 ++ src/Mod/BIM/bimcommands/BimTrash.py | 2 ++ src/Mod/BIM/bimcommands/BimTruss.py | 2 ++ src/Mod/BIM/bimcommands/BimTutorial.py | 2 ++ src/Mod/BIM/bimcommands/BimUnclone.py | 2 ++ src/Mod/BIM/bimcommands/BimUngroup.py | 2 ++ src/Mod/BIM/bimcommands/BimViews.py | 2 ++ src/Mod/BIM/bimcommands/BimWPCommands.py | 2 ++ src/Mod/BIM/bimcommands/BimWall.py | 2 ++ src/Mod/BIM/bimcommands/BimWelcome.py | 2 ++ src/Mod/BIM/bimcommands/BimWindow.py | 2 ++ src/Mod/BIM/bimcommands/BimWindows.py | 2 ++ src/Mod/BIM/ifc_objects.py | 2 ++ src/Mod/BIM/ifc_viewproviders.py | 2 ++ src/Mod/BIM/importers/exportIFC.py | 2 ++ src/Mod/BIM/importers/exportIFCHelper.py | 2 ++ src/Mod/BIM/importers/exportIFCStructuralTools.py | 2 ++ src/Mod/BIM/importers/import3DS.py | 2 ++ src/Mod/BIM/importers/importDAE.py | 2 ++ src/Mod/BIM/importers/importGBXML.py | 2 ++ src/Mod/BIM/importers/importIFC.py | 2 ++ src/Mod/BIM/importers/importIFCHelper.py | 2 ++ src/Mod/BIM/importers/importIFClegacy.py | 2 ++ src/Mod/BIM/importers/importIFCmulticore.py | 2 ++ src/Mod/BIM/importers/importJSON.py | 2 ++ src/Mod/BIM/importers/importOBJ.py | 2 ++ src/Mod/BIM/importers/importSH3D.py | 2 ++ src/Mod/BIM/importers/importSH3DHelper.py | 2 ++ src/Mod/BIM/importers/importSHP.py | 2 ++ src/Mod/BIM/importers/importWebGL.py | 2 ++ src/Mod/BIM/nativeifc/ifc_classification.py | 2 ++ src/Mod/BIM/nativeifc/ifc_commands.py | 2 ++ src/Mod/BIM/nativeifc/ifc_diff.py | 2 ++ src/Mod/BIM/nativeifc/ifc_export.py | 2 ++ src/Mod/BIM/nativeifc/ifc_generator.py | 2 ++ src/Mod/BIM/nativeifc/ifc_geometry.py | 2 ++ src/Mod/BIM/nativeifc/ifc_import.py | 2 ++ src/Mod/BIM/nativeifc/ifc_layers.py | 2 ++ src/Mod/BIM/nativeifc/ifc_materials.py | 2 ++ src/Mod/BIM/nativeifc/ifc_objects.py | 2 ++ src/Mod/BIM/nativeifc/ifc_observer.py | 2 ++ src/Mod/BIM/nativeifc/ifc_openshell.py | 2 ++ src/Mod/BIM/nativeifc/ifc_performance_test.py | 2 ++ src/Mod/BIM/nativeifc/ifc_psets.py | 2 ++ src/Mod/BIM/nativeifc/ifc_selftest.py | 2 ++ src/Mod/BIM/nativeifc/ifc_status.py | 2 ++ src/Mod/BIM/nativeifc/ifc_tools.py | 2 ++ src/Mod/BIM/nativeifc/ifc_tree.py | 2 ++ src/Mod/BIM/nativeifc/ifc_types.py | 2 ++ src/Mod/BIM/nativeifc/ifc_viewproviders.py | 2 ++ src/Mod/BIM/utils/buildPsets.py | 2 ++ src/Mod/BIM/utils/ifctree.py | 2 ++ 163 files changed, 326 insertions(+) diff --git a/src/Mod/BIM/Arch.py b/src/Mod/BIM/Arch.py index 169b48df28..c08d8b3166 100644 --- a/src/Mod/BIM/Arch.py +++ b/src/Mod/BIM/Arch.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchAxis.py b/src/Mod/BIM/ArchAxis.py index eba177b27d..a409e818fd 100644 --- a/src/Mod/BIM/ArchAxis.py +++ b/src/Mod/BIM/ArchAxis.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchAxisSystem.py b/src/Mod/BIM/ArchAxisSystem.py index 8ed775aeb3..3e207408b9 100644 --- a/src/Mod/BIM/ArchAxisSystem.py +++ b/src/Mod/BIM/ArchAxisSystem.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchBuilding.py b/src/Mod/BIM/ArchBuilding.py index f592a40263..2f1f80a7c3 100644 --- a/src/Mod/BIM/ArchBuilding.py +++ b/src/Mod/BIM/ArchBuilding.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchBuildingPart.py b/src/Mod/BIM/ArchBuildingPart.py index 9868f70501..b1a96f906b 100644 --- a/src/Mod/BIM/ArchBuildingPart.py +++ b/src/Mod/BIM/ArchBuildingPart.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchCommands.py b/src/Mod/BIM/ArchCommands.py index 084b6dfa89..2a3e8c18dc 100644 --- a/src/Mod/BIM/ArchCommands.py +++ b/src/Mod/BIM/ArchCommands.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index 76063e4421..a1a2a5c414 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchCurtainWall.py b/src/Mod/BIM/ArchCurtainWall.py index 94cb4329c8..31c08aed04 100644 --- a/src/Mod/BIM/ArchCurtainWall.py +++ b/src/Mod/BIM/ArchCurtainWall.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchCutPlane.py b/src/Mod/BIM/ArchCutPlane.py index fb17f85659..79e749749f 100644 --- a/src/Mod/BIM/ArchCutPlane.py +++ b/src/Mod/BIM/ArchCutPlane.py @@ -6,6 +6,8 @@ # * Copyright (c) 2019 Jerome Laverroux (cutline)* # * Copyright (c) 2023 FreeCAD Project Association * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchEquipment.py b/src/Mod/BIM/ArchEquipment.py index b2e21e2ffb..a8550a06cb 100644 --- a/src/Mod/BIM/ArchEquipment.py +++ b/src/Mod/BIM/ArchEquipment.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2014 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchFence.py b/src/Mod/BIM/ArchFence.py index 5b7cad9282..d82ebe40c1 100644 --- a/src/Mod/BIM/ArchFence.py +++ b/src/Mod/BIM/ArchFence.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2019 furti * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchFloor.py b/src/Mod/BIM/ArchFloor.py index ecb7f25029..11adc470b1 100644 --- a/src/Mod/BIM/ArchFloor.py +++ b/src/Mod/BIM/ArchFloor.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchFrame.py b/src/Mod/BIM/ArchFrame.py index 3863010df1..f9ae46c74d 100644 --- a/src/Mod/BIM/ArchFrame.py +++ b/src/Mod/BIM/ArchFrame.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchGrid.py b/src/Mod/BIM/ArchGrid.py index a46a30eb06..261e559364 100644 --- a/src/Mod/BIM/ArchGrid.py +++ b/src/Mod/BIM/ArchGrid.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchIFC.py b/src/Mod/BIM/ArchIFC.py index c45d96992c..8424b84464 100644 --- a/src/Mod/BIM/ArchIFC.py +++ b/src/Mod/BIM/ArchIFC.py @@ -6,6 +6,8 @@ # * Copyright (c) 2019 Yorik van Havre * # * Copyright (c) 2020 FreeCAD Developers * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchIFCSchema.py b/src/Mod/BIM/ArchIFCSchema.py index edbcb8a386..dc560b6c52 100644 --- a/src/Mod/BIM/ArchIFCSchema.py +++ b/src/Mod/BIM/ArchIFCSchema.py @@ -6,6 +6,8 @@ # * Copyright (c) 2019 Yorik van Havre * # * Copyright (c) 2019 FreeCAD Developers * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchIFCView.py b/src/Mod/BIM/ArchIFCView.py index 6fae401fed..1dd3064509 100644 --- a/src/Mod/BIM/ArchIFCView.py +++ b/src/Mod/BIM/ArchIFCView.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchMaterial.py b/src/Mod/BIM/ArchMaterial.py index b38ef6d427..6b1b645657 100644 --- a/src/Mod/BIM/ArchMaterial.py +++ b/src/Mod/BIM/ArchMaterial.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2015 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchNesting.py b/src/Mod/BIM/ArchNesting.py index c012f6ec29..bca741c272 100644 --- a/src/Mod/BIM/ArchNesting.py +++ b/src/Mod/BIM/ArchNesting.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchPanel.py b/src/Mod/BIM/ArchPanel.py index 56e4a80291..4c91a6134b 100644 --- a/src/Mod/BIM/ArchPanel.py +++ b/src/Mod/BIM/ArchPanel.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchPipe.py b/src/Mod/BIM/ArchPipe.py index f404134691..4038306237 100644 --- a/src/Mod/BIM/ArchPipe.py +++ b/src/Mod/BIM/ArchPipe.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2016 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchPrecast.py b/src/Mod/BIM/ArchPrecast.py index ad662359b9..3cd54a411e 100644 --- a/src/Mod/BIM/ArchPrecast.py +++ b/src/Mod/BIM/ArchPrecast.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2016 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchProfile.py b/src/Mod/BIM/ArchProfile.py index 191d8b8af0..8112242cb7 100644 --- a/src/Mod/BIM/ArchProfile.py +++ b/src/Mod/BIM/ArchProfile.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchProject.py b/src/Mod/BIM/ArchProject.py index 272c68affa..7ed43da9ac 100644 --- a/src/Mod/BIM/ArchProject.py +++ b/src/Mod/BIM/ArchProject.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchRebar.py b/src/Mod/BIM/ArchRebar.py index ac33256454..2d3079daa0 100644 --- a/src/Mod/BIM/ArchRebar.py +++ b/src/Mod/BIM/ArchRebar.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchReference.py b/src/Mod/BIM/ArchReference.py index 64d2bb41fd..ee73b69c67 100644 --- a/src/Mod/BIM/ArchReference.py +++ b/src/Mod/BIM/ArchReference.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchRoof.py b/src/Mod/BIM/ArchRoof.py index 5018b1f35c..c8abc7ce89 100644 --- a/src/Mod/BIM/ArchRoof.py +++ b/src/Mod/BIM/ArchRoof.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2012 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchSchedule.py b/src/Mod/BIM/ArchSchedule.py index 17539c610b..d82be2db36 100644 --- a/src/Mod/BIM/ArchSchedule.py +++ b/src/Mod/BIM/ArchSchedule.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2015 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchSectionPlane.py b/src/Mod/BIM/ArchSectionPlane.py index fc058ec015..429dc698c0 100644 --- a/src/Mod/BIM/ArchSectionPlane.py +++ b/src/Mod/BIM/ArchSectionPlane.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchSite.py b/src/Mod/BIM/ArchSite.py index cc456ec6dd..477e0865ae 100644 --- a/src/Mod/BIM/ArchSite.py +++ b/src/Mod/BIM/ArchSite.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchSketchObject.py b/src/Mod/BIM/ArchSketchObject.py index 9c7cdc0aa5..a13b0d9243 100644 --- a/src/Mod/BIM/ArchSketchObject.py +++ b/src/Mod/BIM/ArchSketchObject.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018-25 Paul Lee * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchSpace.py b/src/Mod/BIM/ArchSpace.py index 029a9928ef..647f8b2bd6 100644 --- a/src/Mod/BIM/ArchSpace.py +++ b/src/Mod/BIM/ArchSpace.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchStairs.py b/src/Mod/BIM/ArchStairs.py index 8b6ada325e..325e4b92d8 100644 --- a/src/Mod/BIM/ArchStairs.py +++ b/src/Mod/BIM/ArchStairs.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchStructure.py b/src/Mod/BIM/ArchStructure.py index 1511d1829e..3830b53410 100644 --- a/src/Mod/BIM/ArchStructure.py +++ b/src/Mod/BIM/ArchStructure.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchTruss.py b/src/Mod/BIM/ArchTruss.py index a0e21a12ff..67a0f2afdf 100644 --- a/src/Mod/BIM/ArchTruss.py +++ b/src/Mod/BIM/ArchTruss.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchVRM.py b/src/Mod/BIM/ArchVRM.py index b8407f9757..15d7c51aa9 100644 --- a/src/Mod/BIM/ArchVRM.py +++ b/src/Mod/BIM/ArchVRM.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2012 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index cb4691f690..bd25fa5945 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchWindow.py b/src/Mod/BIM/ArchWindow.py index 680edd15b0..8f086a9dbe 100644 --- a/src/Mod/BIM/ArchWindow.py +++ b/src/Mod/BIM/ArchWindow.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ArchWindowPresets.py b/src/Mod/BIM/ArchWindowPresets.py index d415caf447..484c8446cf 100644 --- a/src/Mod/BIM/ArchWindowPresets.py +++ b/src/Mod/BIM/ArchWindowPresets.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/BimStatus.py b/src/Mod/BIM/BimStatus.py index 5832d846b1..6fbbaf5091 100644 --- a/src/Mod/BIM/BimStatus.py +++ b/src/Mod/BIM/BimStatus.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/Init.py b/src/Mod/BIM/Init.py index 77ab6a6c1f..87423b2fe5 100644 --- a/src/Mod/BIM/Init.py +++ b/src/Mod/BIM/Init.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/InitGui.py b/src/Mod/BIM/InitGui.py index b44fb2d8bd..37fccab293 100644 --- a/src/Mod/BIM/InitGui.py +++ b/src/Mod/BIM/InitGui.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/OfflineRenderingUtils.py b/src/Mod/BIM/OfflineRenderingUtils.py index bc61d6870c..49327a4b81 100755 --- a/src/Mod/BIM/OfflineRenderingUtils.py +++ b/src/Mod/BIM/OfflineRenderingUtils.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2019 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimArchUtils.py b/src/Mod/BIM/bimcommands/BimArchUtils.py index 89f6b7251e..cb03179795 100644 --- a/src/Mod/BIM/bimcommands/BimArchUtils.py +++ b/src/Mod/BIM/bimcommands/BimArchUtils.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimAxis.py b/src/Mod/BIM/bimcommands/BimAxis.py index 1ba40089fd..1ba596a2ff 100644 --- a/src/Mod/BIM/bimcommands/BimAxis.py +++ b/src/Mod/BIM/bimcommands/BimAxis.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimBackground.py b/src/Mod/BIM/bimcommands/BimBackground.py index efe5382444..5c3bb14f89 100644 --- a/src/Mod/BIM/bimcommands/BimBackground.py +++ b/src/Mod/BIM/bimcommands/BimBackground.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimBeam.py b/src/Mod/BIM/bimcommands/BimBeam.py index 22eece554f..958abedbf4 100644 --- a/src/Mod/BIM/bimcommands/BimBeam.py +++ b/src/Mod/BIM/bimcommands/BimBeam.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimBox.py b/src/Mod/BIM/bimcommands/BimBox.py index 4679281859..dca4b46037 100644 --- a/src/Mod/BIM/bimcommands/BimBox.py +++ b/src/Mod/BIM/bimcommands/BimBox.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimBuilder.py b/src/Mod/BIM/bimcommands/BimBuilder.py index f674ad63f5..5a98966e96 100644 --- a/src/Mod/BIM/bimcommands/BimBuilder.py +++ b/src/Mod/BIM/bimcommands/BimBuilder.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimBuildingPart.py b/src/Mod/BIM/bimcommands/BimBuildingPart.py index 8fd942d0f1..6ff22cbf5a 100644 --- a/src/Mod/BIM/bimcommands/BimBuildingPart.py +++ b/src/Mod/BIM/bimcommands/BimBuildingPart.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimClassification.py b/src/Mod/BIM/bimcommands/BimClassification.py index 14f290e6a5..26e298f483 100644 --- a/src/Mod/BIM/bimcommands/BimClassification.py +++ b/src/Mod/BIM/bimcommands/BimClassification.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimClone.py b/src/Mod/BIM/bimcommands/BimClone.py index 74ad9e8118..16aface163 100644 --- a/src/Mod/BIM/bimcommands/BimClone.py +++ b/src/Mod/BIM/bimcommands/BimClone.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimColumn.py b/src/Mod/BIM/bimcommands/BimColumn.py index 2877508b94..5952e50f94 100644 --- a/src/Mod/BIM/bimcommands/BimColumn.py +++ b/src/Mod/BIM/bimcommands/BimColumn.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimCommon.py b/src/Mod/BIM/bimcommands/BimCommon.py index 22a8d5f2fe..cd4549db62 100644 --- a/src/Mod/BIM/bimcommands/BimCommon.py +++ b/src/Mod/BIM/bimcommands/BimCommon.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimCompound.py b/src/Mod/BIM/bimcommands/BimCompound.py index dbd5714de6..b9b2f5569e 100644 --- a/src/Mod/BIM/bimcommands/BimCompound.py +++ b/src/Mod/BIM/bimcommands/BimCompound.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimConvert.py b/src/Mod/BIM/bimcommands/BimConvert.py index 9f689a6ebf..a1f8f92b5a 100644 --- a/src/Mod/BIM/bimcommands/BimConvert.py +++ b/src/Mod/BIM/bimcommands/BimConvert.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimCopy.py b/src/Mod/BIM/bimcommands/BimCopy.py index 8beecc6750..b8303675a2 100644 --- a/src/Mod/BIM/bimcommands/BimCopy.py +++ b/src/Mod/BIM/bimcommands/BimCopy.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimCurtainwall.py b/src/Mod/BIM/bimcommands/BimCurtainwall.py index 2d24d03540..0071f90e3a 100644 --- a/src/Mod/BIM/bimcommands/BimCurtainwall.py +++ b/src/Mod/BIM/bimcommands/BimCurtainwall.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimCut.py b/src/Mod/BIM/bimcommands/BimCut.py index 2f2a716b90..270783c6a2 100644 --- a/src/Mod/BIM/bimcommands/BimCut.py +++ b/src/Mod/BIM/bimcommands/BimCut.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimCutPlane.py b/src/Mod/BIM/bimcommands/BimCutPlane.py index 22c6f9fe8f..a0a43477d9 100644 --- a/src/Mod/BIM/bimcommands/BimCutPlane.py +++ b/src/Mod/BIM/bimcommands/BimCutPlane.py @@ -6,6 +6,8 @@ # * Copyright (c) 2019 Jerome Laverroux (cutline)* # * Copyright (c) 2023 FreeCAD Project Association * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimDiff.py b/src/Mod/BIM/bimcommands/BimDiff.py index cef4db17ad..1662a8b570 100644 --- a/src/Mod/BIM/bimcommands/BimDiff.py +++ b/src/Mod/BIM/bimcommands/BimDiff.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2019 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimDimensions.py b/src/Mod/BIM/bimcommands/BimDimensions.py index 5edd401fd8..57e60db610 100644 --- a/src/Mod/BIM/bimcommands/BimDimensions.py +++ b/src/Mod/BIM/bimcommands/BimDimensions.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimDoor.py b/src/Mod/BIM/bimcommands/BimDoor.py index 366b52e086..698b2bb5ba 100644 --- a/src/Mod/BIM/bimcommands/BimDoor.py +++ b/src/Mod/BIM/bimcommands/BimDoor.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimDrawingView.py b/src/Mod/BIM/bimcommands/BimDrawingView.py index e49a53bd8e..71dcb7bb45 100644 --- a/src/Mod/BIM/bimcommands/BimDrawingView.py +++ b/src/Mod/BIM/bimcommands/BimDrawingView.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimEmptyTrash.py b/src/Mod/BIM/bimcommands/BimEmptyTrash.py index c2b0c2c851..bb27532a83 100644 --- a/src/Mod/BIM/bimcommands/BimEmptyTrash.py +++ b/src/Mod/BIM/bimcommands/BimEmptyTrash.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimEquipment.py b/src/Mod/BIM/bimcommands/BimEquipment.py index b7687e4a6e..0fce95b511 100644 --- a/src/Mod/BIM/bimcommands/BimEquipment.py +++ b/src/Mod/BIM/bimcommands/BimEquipment.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimExamples.py b/src/Mod/BIM/bimcommands/BimExamples.py index 8fa9581415..ce0aef5b59 100644 --- a/src/Mod/BIM/bimcommands/BimExamples.py +++ b/src/Mod/BIM/bimcommands/BimExamples.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimExtrude.py b/src/Mod/BIM/bimcommands/BimExtrude.py index 7069acf2ef..0b5889b83b 100644 --- a/src/Mod/BIM/bimcommands/BimExtrude.py +++ b/src/Mod/BIM/bimcommands/BimExtrude.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimFence.py b/src/Mod/BIM/bimcommands/BimFence.py index 5534fd85b8..06217f9ebf 100644 --- a/src/Mod/BIM/bimcommands/BimFence.py +++ b/src/Mod/BIM/bimcommands/BimFence.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimFrame.py b/src/Mod/BIM/bimcommands/BimFrame.py index 5177f2a1b2..97641fead1 100644 --- a/src/Mod/BIM/bimcommands/BimFrame.py +++ b/src/Mod/BIM/bimcommands/BimFrame.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimFuse.py b/src/Mod/BIM/bimcommands/BimFuse.py index e2a3f8e6ae..610f4a2663 100644 --- a/src/Mod/BIM/bimcommands/BimFuse.py +++ b/src/Mod/BIM/bimcommands/BimFuse.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimGlue.py b/src/Mod/BIM/bimcommands/BimGlue.py index 4f0d40b6ee..07420a3069 100644 --- a/src/Mod/BIM/bimcommands/BimGlue.py +++ b/src/Mod/BIM/bimcommands/BimGlue.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimHelp.py b/src/Mod/BIM/bimcommands/BimHelp.py index 593f80673f..a598ec07b2 100644 --- a/src/Mod/BIM/bimcommands/BimHelp.py +++ b/src/Mod/BIM/bimcommands/BimHelp.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimIfcElements.py b/src/Mod/BIM/bimcommands/BimIfcElements.py index a0c9a06a4e..ca777f1714 100644 --- a/src/Mod/BIM/bimcommands/BimIfcElements.py +++ b/src/Mod/BIM/bimcommands/BimIfcElements.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimIfcExplorer.py b/src/Mod/BIM/bimcommands/BimIfcExplorer.py index 919a613280..cd2b66cc63 100644 --- a/src/Mod/BIM/bimcommands/BimIfcExplorer.py +++ b/src/Mod/BIM/bimcommands/BimIfcExplorer.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2019 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimIfcProperties.py b/src/Mod/BIM/bimcommands/BimIfcProperties.py index 1a68db3ebc..ec2595c833 100644 --- a/src/Mod/BIM/bimcommands/BimIfcProperties.py +++ b/src/Mod/BIM/bimcommands/BimIfcProperties.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimIfcQuantities.py b/src/Mod/BIM/bimcommands/BimIfcQuantities.py index 9ec97c4f8d..fe57578870 100644 --- a/src/Mod/BIM/bimcommands/BimIfcQuantities.py +++ b/src/Mod/BIM/bimcommands/BimIfcQuantities.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimImagePlane.py b/src/Mod/BIM/bimcommands/BimImagePlane.py index 7ab3b0fe2c..51eda8418d 100644 --- a/src/Mod/BIM/bimcommands/BimImagePlane.py +++ b/src/Mod/BIM/bimcommands/BimImagePlane.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimLayers.py b/src/Mod/BIM/bimcommands/BimLayers.py index 43e05c102e..4b639b242f 100644 --- a/src/Mod/BIM/bimcommands/BimLayers.py +++ b/src/Mod/BIM/bimcommands/BimLayers.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2019 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimLeader.py b/src/Mod/BIM/bimcommands/BimLeader.py index ec15c7124c..8ff8414929 100644 --- a/src/Mod/BIM/bimcommands/BimLeader.py +++ b/src/Mod/BIM/bimcommands/BimLeader.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimLibrary.py b/src/Mod/BIM/bimcommands/BimLibrary.py index f1d0bef6ff..c09bea1da7 100644 --- a/src/Mod/BIM/bimcommands/BimLibrary.py +++ b/src/Mod/BIM/bimcommands/BimLibrary.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimMaterial.py b/src/Mod/BIM/bimcommands/BimMaterial.py index 85ec5cbe11..3c1c9afb6f 100644 --- a/src/Mod/BIM/bimcommands/BimMaterial.py +++ b/src/Mod/BIM/bimcommands/BimMaterial.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimMoveView.py b/src/Mod/BIM/bimcommands/BimMoveView.py index 12bc15f885..c04bac914b 100644 --- a/src/Mod/BIM/bimcommands/BimMoveView.py +++ b/src/Mod/BIM/bimcommands/BimMoveView.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimNudge.py b/src/Mod/BIM/bimcommands/BimNudge.py index 96b1db927b..a31a1ba2e8 100644 --- a/src/Mod/BIM/bimcommands/BimNudge.py +++ b/src/Mod/BIM/bimcommands/BimNudge.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimOffset.py b/src/Mod/BIM/bimcommands/BimOffset.py index b323b89fd0..fff682dcb4 100644 --- a/src/Mod/BIM/bimcommands/BimOffset.py +++ b/src/Mod/BIM/bimcommands/BimOffset.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimPanel.py b/src/Mod/BIM/bimcommands/BimPanel.py index 4b692625b5..b41c5a8b84 100644 --- a/src/Mod/BIM/bimcommands/BimPanel.py +++ b/src/Mod/BIM/bimcommands/BimPanel.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimPipe.py b/src/Mod/BIM/bimcommands/BimPipe.py index 710af04aa2..f4024c8ae9 100644 --- a/src/Mod/BIM/bimcommands/BimPipe.py +++ b/src/Mod/BIM/bimcommands/BimPipe.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimPreflight.py b/src/Mod/BIM/bimcommands/BimPreflight.py index 2ae196e88c..14e3af586c 100644 --- a/src/Mod/BIM/bimcommands/BimPreflight.py +++ b/src/Mod/BIM/bimcommands/BimPreflight.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimProfile.py b/src/Mod/BIM/bimcommands/BimProfile.py index 042de19235..b3e14e0638 100644 --- a/src/Mod/BIM/bimcommands/BimProfile.py +++ b/src/Mod/BIM/bimcommands/BimProfile.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimProject.py b/src/Mod/BIM/bimcommands/BimProject.py index d38a3de5c1..47f3ebf9f5 100644 --- a/src/Mod/BIM/bimcommands/BimProject.py +++ b/src/Mod/BIM/bimcommands/BimProject.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index 853f67dd9f..f24d79c04d 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimRebar.py b/src/Mod/BIM/bimcommands/BimRebar.py index b916ec141a..848eb9ef1e 100644 --- a/src/Mod/BIM/bimcommands/BimRebar.py +++ b/src/Mod/BIM/bimcommands/BimRebar.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimReextrude.py b/src/Mod/BIM/bimcommands/BimReextrude.py index 68e9815b06..b36f62712a 100644 --- a/src/Mod/BIM/bimcommands/BimReextrude.py +++ b/src/Mod/BIM/bimcommands/BimReextrude.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimReference.py b/src/Mod/BIM/bimcommands/BimReference.py index 126d768947..2ab0e13f5a 100644 --- a/src/Mod/BIM/bimcommands/BimReference.py +++ b/src/Mod/BIM/bimcommands/BimReference.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimReorder.py b/src/Mod/BIM/bimcommands/BimReorder.py index 5bd1065714..9788f17018 100644 --- a/src/Mod/BIM/bimcommands/BimReorder.py +++ b/src/Mod/BIM/bimcommands/BimReorder.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2021 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimResetCloneColors.py b/src/Mod/BIM/bimcommands/BimResetCloneColors.py index 09fb53a28f..cc8281a8ab 100644 --- a/src/Mod/BIM/bimcommands/BimResetCloneColors.py +++ b/src/Mod/BIM/bimcommands/BimResetCloneColors.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimRewire.py b/src/Mod/BIM/bimcommands/BimRewire.py index 76e88ed311..eb3dd8b93c 100644 --- a/src/Mod/BIM/bimcommands/BimRewire.py +++ b/src/Mod/BIM/bimcommands/BimRewire.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimRoof.py b/src/Mod/BIM/bimcommands/BimRoof.py index f0a9f8b8bb..383c3e82a5 100644 --- a/src/Mod/BIM/bimcommands/BimRoof.py +++ b/src/Mod/BIM/bimcommands/BimRoof.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSchedule.py b/src/Mod/BIM/bimcommands/BimSchedule.py index 808a3ce451..320b09abff 100644 --- a/src/Mod/BIM/bimcommands/BimSchedule.py +++ b/src/Mod/BIM/bimcommands/BimSchedule.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSectionPlane.py b/src/Mod/BIM/bimcommands/BimSectionPlane.py index 4f92fbc4d0..8fdf969c01 100644 --- a/src/Mod/BIM/bimcommands/BimSectionPlane.py +++ b/src/Mod/BIM/bimcommands/BimSectionPlane.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSetup.py b/src/Mod/BIM/bimcommands/BimSetup.py index e03937f9b1..4ce731fbef 100644 --- a/src/Mod/BIM/bimcommands/BimSetup.py +++ b/src/Mod/BIM/bimcommands/BimSetup.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimShape2DView.py b/src/Mod/BIM/bimcommands/BimShape2DView.py index 5c73dc04c3..e1746ae579 100644 --- a/src/Mod/BIM/bimcommands/BimShape2DView.py +++ b/src/Mod/BIM/bimcommands/BimShape2DView.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSimpleCopy.py b/src/Mod/BIM/bimcommands/BimSimpleCopy.py index 501c903059..b279551900 100644 --- a/src/Mod/BIM/bimcommands/BimSimpleCopy.py +++ b/src/Mod/BIM/bimcommands/BimSimpleCopy.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSite.py b/src/Mod/BIM/bimcommands/BimSite.py index 4093922c34..1f30a24ff0 100644 --- a/src/Mod/BIM/bimcommands/BimSite.py +++ b/src/Mod/BIM/bimcommands/BimSite.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSketch.py b/src/Mod/BIM/bimcommands/BimSketch.py index 5f325d7627..c0213a626f 100644 --- a/src/Mod/BIM/bimcommands/BimSketch.py +++ b/src/Mod/BIM/bimcommands/BimSketch.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSlab.py b/src/Mod/BIM/bimcommands/BimSlab.py index a090a1dac0..a4e31b63a7 100644 --- a/src/Mod/BIM/bimcommands/BimSlab.py +++ b/src/Mod/BIM/bimcommands/BimSlab.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimSpace.py b/src/Mod/BIM/bimcommands/BimSpace.py index e0216ea319..406eff2f95 100644 --- a/src/Mod/BIM/bimcommands/BimSpace.py +++ b/src/Mod/BIM/bimcommands/BimSpace.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimStairs.py b/src/Mod/BIM/bimcommands/BimStairs.py index 166c8c7a16..2839a4bd91 100644 --- a/src/Mod/BIM/bimcommands/BimStairs.py +++ b/src/Mod/BIM/bimcommands/BimStairs.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimTDPage.py b/src/Mod/BIM/bimcommands/BimTDPage.py index aadb642f8e..014cb53a4f 100644 --- a/src/Mod/BIM/bimcommands/BimTDPage.py +++ b/src/Mod/BIM/bimcommands/BimTDPage.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimTDView.py b/src/Mod/BIM/bimcommands/BimTDView.py index 50bd30c857..72affb277a 100644 --- a/src/Mod/BIM/bimcommands/BimTDView.py +++ b/src/Mod/BIM/bimcommands/BimTDView.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimText.py b/src/Mod/BIM/bimcommands/BimText.py index b7c4904eaa..2a618c92d6 100644 --- a/src/Mod/BIM/bimcommands/BimText.py +++ b/src/Mod/BIM/bimcommands/BimText.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimTogglePanels.py b/src/Mod/BIM/bimcommands/BimTogglePanels.py index b277d4052c..5601fde425 100644 --- a/src/Mod/BIM/bimcommands/BimTogglePanels.py +++ b/src/Mod/BIM/bimcommands/BimTogglePanels.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimTrash.py b/src/Mod/BIM/bimcommands/BimTrash.py index eb7e9be860..9f5a28daf1 100644 --- a/src/Mod/BIM/bimcommands/BimTrash.py +++ b/src/Mod/BIM/bimcommands/BimTrash.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimTruss.py b/src/Mod/BIM/bimcommands/BimTruss.py index 009d036a8d..af5113da0e 100644 --- a/src/Mod/BIM/bimcommands/BimTruss.py +++ b/src/Mod/BIM/bimcommands/BimTruss.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimTutorial.py b/src/Mod/BIM/bimcommands/BimTutorial.py index c556772ee9..ed8c3a9fc9 100644 --- a/src/Mod/BIM/bimcommands/BimTutorial.py +++ b/src/Mod/BIM/bimcommands/BimTutorial.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimUnclone.py b/src/Mod/BIM/bimcommands/BimUnclone.py index 7864573232..e559d1be1b 100644 --- a/src/Mod/BIM/bimcommands/BimUnclone.py +++ b/src/Mod/BIM/bimcommands/BimUnclone.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimUngroup.py b/src/Mod/BIM/bimcommands/BimUngroup.py index 9411465c49..342c3f2901 100644 --- a/src/Mod/BIM/bimcommands/BimUngroup.py +++ b/src/Mod/BIM/bimcommands/BimUngroup.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimViews.py b/src/Mod/BIM/bimcommands/BimViews.py index fd065a40ee..3f86c3fd8e 100644 --- a/src/Mod/BIM/bimcommands/BimViews.py +++ b/src/Mod/BIM/bimcommands/BimViews.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimWPCommands.py b/src/Mod/BIM/bimcommands/BimWPCommands.py index 495c883192..39f23c02cb 100644 --- a/src/Mod/BIM/bimcommands/BimWPCommands.py +++ b/src/Mod/BIM/bimcommands/BimWPCommands.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimWall.py b/src/Mod/BIM/bimcommands/BimWall.py index 7de5e9158c..ff1b576561 100644 --- a/src/Mod/BIM/bimcommands/BimWall.py +++ b/src/Mod/BIM/bimcommands/BimWall.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimWelcome.py b/src/Mod/BIM/bimcommands/BimWelcome.py index d13cec29e2..0638843c31 100644 --- a/src/Mod/BIM/bimcommands/BimWelcome.py +++ b/src/Mod/BIM/bimcommands/BimWelcome.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimWindow.py b/src/Mod/BIM/bimcommands/BimWindow.py index f82a47e418..860c4d262c 100644 --- a/src/Mod/BIM/bimcommands/BimWindow.py +++ b/src/Mod/BIM/bimcommands/BimWindow.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/bimcommands/BimWindows.py b/src/Mod/BIM/bimcommands/BimWindows.py index f91e4de417..12b97b6388 100644 --- a/src/Mod/BIM/bimcommands/BimWindows.py +++ b/src/Mod/BIM/bimcommands/BimWindows.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/ifc_objects.py b/src/Mod/BIM/ifc_objects.py index ba039e4a12..6f6b6e5f54 100644 --- a/src/Mod/BIM/ifc_objects.py +++ b/src/Mod/BIM/ifc_objects.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Library General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * diff --git a/src/Mod/BIM/ifc_viewproviders.py b/src/Mod/BIM/ifc_viewproviders.py index f7f0155d07..764c39669f 100644 --- a/src/Mod/BIM/ifc_viewproviders.py +++ b/src/Mod/BIM/ifc_viewproviders.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Library General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index 73ef139952..0ebbd6dc58 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2014 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/exportIFCHelper.py b/src/Mod/BIM/importers/exportIFCHelper.py index 3ebda8ff94..b3d363a200 100644 --- a/src/Mod/BIM/importers/exportIFCHelper.py +++ b/src/Mod/BIM/importers/exportIFCHelper.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2019 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/exportIFCStructuralTools.py b/src/Mod/BIM/importers/exportIFCStructuralTools.py index 74f1fc9d41..5f364858e7 100644 --- a/src/Mod/BIM/importers/exportIFCStructuralTools.py +++ b/src/Mod/BIM/importers/exportIFCStructuralTools.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/import3DS.py b/src/Mod/BIM/importers/import3DS.py index 89dfc8b79d..e46ba9c39b 100644 --- a/src/Mod/BIM/importers/import3DS.py +++ b/src/Mod/BIM/importers/import3DS.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2016 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importDAE.py b/src/Mod/BIM/importers/importDAE.py index b29270705c..d4f59af303 100644 --- a/src/Mod/BIM/importers/importDAE.py +++ b/src/Mod/BIM/importers/importDAE.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importGBXML.py b/src/Mod/BIM/importers/importGBXML.py index 1f2f597a06..014ffaf0ce 100644 --- a/src/Mod/BIM/importers/importGBXML.py +++ b/src/Mod/BIM/importers/importGBXML.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2015 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importIFC.py b/src/Mod/BIM/importers/importIFC.py index 48a1d21eb9..74e910c949 100644 --- a/src/Mod/BIM/importers/importIFC.py +++ b/src/Mod/BIM/importers/importIFC.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2014 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importIFCHelper.py b/src/Mod/BIM/importers/importIFCHelper.py index 83ca7b2eed..ba3f7a092b 100644 --- a/src/Mod/BIM/importers/importIFCHelper.py +++ b/src/Mod/BIM/importers/importIFCHelper.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2019 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importIFClegacy.py b/src/Mod/BIM/importers/importIFClegacy.py index 5fb41a9b44..ceaab17cdf 100644 --- a/src/Mod/BIM/importers/importIFClegacy.py +++ b/src/Mod/BIM/importers/importIFClegacy.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importIFCmulticore.py b/src/Mod/BIM/importers/importIFCmulticore.py index 1f87c9337a..230d4bf93e 100644 --- a/src/Mod/BIM/importers/importIFCmulticore.py +++ b/src/Mod/BIM/importers/importIFCmulticore.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importJSON.py b/src/Mod/BIM/importers/importJSON.py index 0e206178b6..2cab4ceb2e 100644 --- a/src/Mod/BIM/importers/importJSON.py +++ b/src/Mod/BIM/importers/importJSON.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2017 Joseph Coffland * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importOBJ.py b/src/Mod/BIM/importers/importOBJ.py index bab1fb50f3..e8658a0c02 100644 --- a/src/Mod/BIM/importers/importOBJ.py +++ b/src/Mod/BIM/importers/importOBJ.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2011 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importSH3D.py b/src/Mod/BIM/importers/importSH3D.py index e800d4b465..ba830df7fa 100644 --- a/src/Mod/BIM/importers/importSH3D.py +++ b/src/Mod/BIM/importers/importSH3D.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2016 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importSH3DHelper.py b/src/Mod/BIM/importers/importSH3DHelper.py index c1cb5c91cd..e80e5aab3f 100644 --- a/src/Mod/BIM/importers/importSH3DHelper.py +++ b/src/Mod/BIM/importers/importSH3DHelper.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Julien Masnada * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importSHP.py b/src/Mod/BIM/importers/importSHP.py index 5758250446..f8e9f9d8ca 100644 --- a/src/Mod/BIM/importers/importSHP.py +++ b/src/Mod/BIM/importers/importSHP.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2020 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/importers/importWebGL.py b/src/Mod/BIM/importers/importWebGL.py index df8e68c793..00b11029f1 100644 --- a/src/Mod/BIM/importers/importWebGL.py +++ b/src/Mod/BIM/importers/importWebGL.py @@ -5,6 +5,8 @@ # * Copyright (c) 2013 Yorik van Havre * # * Copyright (c) 2020 Travis Apple * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_classification.py b/src/Mod/BIM/nativeifc/ifc_classification.py index e2d45f3e38..fba17a90bb 100644 --- a/src/Mod/BIM/nativeifc/ifc_classification.py +++ b/src/Mod/BIM/nativeifc/ifc_classification.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU General Public License (GPL) * # * as published by the Free Software Foundation; either version 3 of * diff --git a/src/Mod/BIM/nativeifc/ifc_commands.py b/src/Mod/BIM/nativeifc/ifc_commands.py index 36c116866d..02ad0e6701 100644 --- a/src/Mod/BIM/nativeifc/ifc_commands.py +++ b/src/Mod/BIM/nativeifc/ifc_commands.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_diff.py b/src/Mod/BIM/nativeifc/ifc_diff.py index 28c7e753a2..b34e8e3f08 100644 --- a/src/Mod/BIM/nativeifc/ifc_diff.py +++ b/src/Mod/BIM/nativeifc/ifc_diff.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index b8737835a1..7c81492a0b 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_generator.py b/src/Mod/BIM/nativeifc/ifc_generator.py index 9f5b95c840..e16df06473 100644 --- a/src/Mod/BIM/nativeifc/ifc_generator.py +++ b/src/Mod/BIM/nativeifc/ifc_generator.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_geometry.py b/src/Mod/BIM/nativeifc/ifc_geometry.py index 88126e2ea2..3f963c5557 100644 --- a/src/Mod/BIM/nativeifc/ifc_geometry.py +++ b/src/Mod/BIM/nativeifc/ifc_geometry.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_import.py b/src/Mod/BIM/nativeifc/ifc_import.py index 8bad9e81e3..697991cb35 100644 --- a/src/Mod/BIM/nativeifc/ifc_import.py +++ b/src/Mod/BIM/nativeifc/ifc_import.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_layers.py b/src/Mod/BIM/nativeifc/ifc_layers.py index e8c918b5d7..706d885800 100644 --- a/src/Mod/BIM/nativeifc/ifc_layers.py +++ b/src/Mod/BIM/nativeifc/ifc_layers.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_materials.py b/src/Mod/BIM/nativeifc/ifc_materials.py index 1f6982260e..390bc71d26 100644 --- a/src/Mod/BIM/nativeifc/ifc_materials.py +++ b/src/Mod/BIM/nativeifc/ifc_materials.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_objects.py b/src/Mod/BIM/nativeifc/ifc_objects.py index 80f94ca6d8..a8b5f28f70 100644 --- a/src/Mod/BIM/nativeifc/ifc_objects.py +++ b/src/Mod/BIM/nativeifc/ifc_objects.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_observer.py b/src/Mod/BIM/nativeifc/ifc_observer.py index e3b9a219f5..d7650eb8de 100644 --- a/src/Mod/BIM/nativeifc/ifc_observer.py +++ b/src/Mod/BIM/nativeifc/ifc_observer.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_openshell.py b/src/Mod/BIM/nativeifc/ifc_openshell.py index ae98728199..6d3fbb9dde 100644 --- a/src/Mod/BIM/nativeifc/ifc_openshell.py +++ b/src/Mod/BIM/nativeifc/ifc_openshell.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_performance_test.py b/src/Mod/BIM/nativeifc/ifc_performance_test.py index 41db2f4434..946061285e 100644 --- a/src/Mod/BIM/nativeifc/ifc_performance_test.py +++ b/src/Mod/BIM/nativeifc/ifc_performance_test.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_psets.py b/src/Mod/BIM/nativeifc/ifc_psets.py index 7a743c6301..16c1d01ff6 100644 --- a/src/Mod/BIM/nativeifc/ifc_psets.py +++ b/src/Mod/BIM/nativeifc/ifc_psets.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_selftest.py b/src/Mod/BIM/nativeifc/ifc_selftest.py index 004a3a8210..a8a6d1b4b3 100644 --- a/src/Mod/BIM/nativeifc/ifc_selftest.py +++ b/src/Mod/BIM/nativeifc/ifc_selftest.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_status.py b/src/Mod/BIM/nativeifc/ifc_status.py index ebd612d3b5..f028c82cd3 100644 --- a/src/Mod/BIM/nativeifc/ifc_status.py +++ b/src/Mod/BIM/nativeifc/ifc_status.py @@ -6,6 +6,8 @@ # * * # * Copyright (c) 2024 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index ad2e47bd45..cffedbfe48 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_tree.py b/src/Mod/BIM/nativeifc/ifc_tree.py index 82a0ef929b..c2cc4b4602 100644 --- a/src/Mod/BIM/nativeifc/ifc_tree.py +++ b/src/Mod/BIM/nativeifc/ifc_tree.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/nativeifc/ifc_types.py b/src/Mod/BIM/nativeifc/ifc_types.py index bbde502a32..e4afe43604 100644 --- a/src/Mod/BIM/nativeifc/ifc_types.py +++ b/src/Mod/BIM/nativeifc/ifc_types.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2023 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Library General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * diff --git a/src/Mod/BIM/nativeifc/ifc_viewproviders.py b/src/Mod/BIM/nativeifc/ifc_viewproviders.py index af17cce3a3..0828d0c4ca 100644 --- a/src/Mod/BIM/nativeifc/ifc_viewproviders.py +++ b/src/Mod/BIM/nativeifc/ifc_viewproviders.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Library General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * diff --git a/src/Mod/BIM/utils/buildPsets.py b/src/Mod/BIM/utils/buildPsets.py index b68225cddf..9b106dbbbb 100644 --- a/src/Mod/BIM/utils/buildPsets.py +++ b/src/Mod/BIM/utils/buildPsets.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2018 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * diff --git a/src/Mod/BIM/utils/ifctree.py b/src/Mod/BIM/utils/ifctree.py index fa080d40ed..4ae1057b4c 100644 --- a/src/Mod/BIM/utils/ifctree.py +++ b/src/Mod/BIM/utils/ifctree.py @@ -4,6 +4,8 @@ # * * # * Copyright (c) 2022 Yorik van Havre * # * * +# * This file is part of FreeCAD. * +# * * # * 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 * From cab9053be825b8f09d686d5894f333915e4ee378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Skowro=C5=84ski?= Date: Fri, 4 Apr 2025 16:13:13 +0200 Subject: [PATCH 140/316] Added sanity check for an action pointer --- src/Gui/3Dconnexion/navlib/NavlibCmds.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Gui/3Dconnexion/navlib/NavlibCmds.cpp b/src/Gui/3Dconnexion/navlib/NavlibCmds.cpp index 0afd278db2..46ad44b82a 100644 --- a/src/Gui/3Dconnexion/navlib/NavlibCmds.cpp +++ b/src/Gui/3Dconnexion/navlib/NavlibCmds.cpp @@ -153,7 +153,9 @@ long NavlibInterface::SetActiveCommand(std::string commandId) if (!std::string(command->getName()).compare(parsedData.commandName)) { if (parsedData.actionIndex == -1) { Gui::Action* pAction = command->getAction(); - pAction->action()->trigger(); + if (pAction != nullptr) { + pAction->action()->trigger(); + } } else command->invoke(parsedData.actionIndex); From 770dbe55800fd9827e38ee254333e549920cd2b9 Mon Sep 17 00:00:00 2001 From: tritao Date: Fri, 21 Mar 2025 19:27:30 +0000 Subject: [PATCH 141/316] Sketcher: Convert XML binding files to Python API bindings model. --- src/Mod/Sketcher/App/CMakeLists.txt | 8 + src/Mod/Sketcher/App/Constraint.pyi | 58 ++ .../App/ExternalGeometryExtension.pyi | 32 + .../App/ExternalGeometryExtensionPy.xml | 6 +- .../Sketcher/App/ExternalGeometryFacade.pyi | 136 +++ .../Sketcher/App/ExternalGeometryFacadePy.xml | 8 +- src/Mod/Sketcher/App/GeometryFacade.pyi | 139 +++ src/Mod/Sketcher/App/GeometryFacadePy.xml | 8 +- src/Mod/Sketcher/App/Sketch.pyi | 72 ++ .../Sketcher/App/SketchGeometryExtension.pyi | 45 + src/Mod/Sketcher/App/SketchObject.pyi | 875 ++++++++++++++++++ src/Mod/Sketcher/App/SketchObjectPy.xml | 188 ++-- src/Mod/Sketcher/App/SketchObjectSF.pyi | 16 + src/Mod/Sketcher/App/SketchPy.xml | 26 +- src/Mod/Sketcher/Gui/CMakeLists.txt | 1 + .../ViewProviderSketchGeometryExtension.pyi | 20 + 16 files changed, 1524 insertions(+), 114 deletions(-) create mode 100644 src/Mod/Sketcher/App/Constraint.pyi create mode 100644 src/Mod/Sketcher/App/ExternalGeometryExtension.pyi create mode 100644 src/Mod/Sketcher/App/ExternalGeometryFacade.pyi create mode 100644 src/Mod/Sketcher/App/GeometryFacade.pyi create mode 100644 src/Mod/Sketcher/App/Sketch.pyi create mode 100644 src/Mod/Sketcher/App/SketchGeometryExtension.pyi create mode 100644 src/Mod/Sketcher/App/SketchObject.pyi create mode 100644 src/Mod/Sketcher/App/SketchObjectSF.pyi create mode 100644 src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.pyi diff --git a/src/Mod/Sketcher/App/CMakeLists.txt b/src/Mod/Sketcher/App/CMakeLists.txt index bd75cfb0c2..09ae7ff1d0 100644 --- a/src/Mod/Sketcher/App/CMakeLists.txt +++ b/src/Mod/Sketcher/App/CMakeLists.txt @@ -31,13 +31,21 @@ set(Sketcher_LIBS ) generate_from_xml(SketchObjectSFPy) +generate_from_py_(SketchObjectSF) generate_from_xml(SketchObjectPy) +generate_from_py_(SketchObject) generate_from_xml(SketchGeometryExtensionPy) +generate_from_py_(SketchGeometryExtension) generate_from_xml(ExternalGeometryExtensionPy) +generate_from_py_(ExternalGeometryExtension) generate_from_xml(GeometryFacadePy) +generate_from_py_(GeometryFacade) generate_from_xml(ExternalGeometryFacadePy) +generate_from_py_(ExternalGeometryFacade) generate_from_xml(ConstraintPy) +generate_from_py_(Constraint) generate_from_xml(SketchPy) +generate_from_py_(Sketch) SET(Properties_SRCS diff --git a/src/Mod/Sketcher/App/Constraint.pyi b/src/Mod/Sketcher/App/Constraint.pyi new file mode 100644 index 0000000000..8c93386409 --- /dev/null +++ b/src/Mod/Sketcher/App/Constraint.pyi @@ -0,0 +1,58 @@ +from Base.Metadata import export +from Base.Persistence import Persistence +from typing import Final + +@export( + Include="Mod/Sketcher/App/Constraint.h", + Constructor=True, + Delete=True, +) +class Constraint(Persistence): + """ + With this object you can handle sketches + + Author: Juergen Riegel (FreeCAD@juergen-riegel.net) + Licence: LGPL + """ + + Type: Final[str] = "" + """Get the constraint type""" + + First: int = 0 + """First geometry index the Constraint refers to""" + + FirstPos: int = 0 + """Position of first geometry index the Constraint refers to""" + + Second: int = 0 + """Second geometry index the Constraint refers to""" + + SecondPos: int = 0 + """Position of second geometry index the Constraint refers to""" + + Third: int = 0 + """Third geometry index the Constraint refers to""" + + ThirdPos: int = 0 + """Position of third geometry index the Constraint refers to""" + + Value: Final[float] = 0.0 + """Value of the Constraint""" + + Name: str = "" + """Name of the constraint""" + + Driving: Final[bool] = False + """Driving Constraint""" + + InVirtualSpace: Final[bool] = False + """Constraint in virtual space""" + + IsActive: Final[bool] = False + """Returns whether the constraint active (enforced) or not""" + + LabelDistance: Final[float] = 0.0 + """Label distance""" + + LabelPosition: Final[float] = 0.0 + """Label position""" diff --git a/src/Mod/Sketcher/App/ExternalGeometryExtension.pyi b/src/Mod/Sketcher/App/ExternalGeometryExtension.pyi new file mode 100644 index 0000000000..3b809b32fb --- /dev/null +++ b/src/Mod/Sketcher/App/ExternalGeometryExtension.pyi @@ -0,0 +1,32 @@ +from Base.Metadata import export, constmethod +from Part.App.GeometryExtension import GeometryExtension +from typing import Final, overload + +@export( + PythonName="Sketcher.ExternalGeometryExtension", + Include="Mod/Sketcher/App/ExternalGeometryExtension.h", + FatherInclude="Mod/Part/App/GeometryExtensionPy.h", + Constructor=True, +) +class ExternalGeometryExtension(GeometryExtension): + """ + Describes a ExternalGeometryExtension + + Author: Abdullah Tahiri (abdullah.tahiri.yo@gmail.com) + Licence: LGPL + """ + + @constmethod + def testFlag(self) -> bool: + """ + Returns a boolean indicating whether the given bit is set. + """ + ... + + def setFlag(self) -> None: + """ + Sets the given bit to true/false. + """ + ... + Ref: str = "" + """Returns the reference string of this external geometry.""" diff --git a/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml b/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml index d8e2ab5b19..eb001465ff 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml +++ b/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml @@ -17,18 +17,18 @@ - returns a boolean indicating whether the given bit is set. + Returns a boolean indicating whether the given bit is set. - sets the given bit to true/false. + Sets the given bit to true/false. - returns the reference string of this external geometry. +Returns the reference string of this external geometry. diff --git a/src/Mod/Sketcher/App/ExternalGeometryFacade.pyi b/src/Mod/Sketcher/App/ExternalGeometryFacade.pyi new file mode 100644 index 0000000000..3c5ac0082d --- /dev/null +++ b/src/Mod/Sketcher/App/ExternalGeometryFacade.pyi @@ -0,0 +1,136 @@ +from Base.Metadata import export, constmethod +from Base.BaseClass import BaseClass +from typing import Final, List + +@export( + PythonName="Sketcher.ExternalGeometryFacade", + Include="Mod/Sketcher/App/ExternalGeometryFacade.h", + Constructor=True, +) +class ExternalGeometryFacade(BaseClass): + """ + Describes a GeometryFacade + + Author: Abdullah Tahiri (abdullah.tahiri.yo@gmail.com) + Licence: LGPL + """ + + Ref: str = "" + """Returns the reference string of this external geometry.""" + + Id: int = 0 + """Sets/returns the Internal Alignment Type of the Geometry.""" + + Construction: bool = False + """Sets/returns this geometry as a construction one, which will not be part of a later built shape.""" + + GeometryLayerId: int = 0 + """Returns the Id of the geometry Layer in which the geometry is located.""" + + InternalType: str = "" + """Sets/returns the Internal Alignment Type of the Geometry.""" + + Blocked: bool = False + """Sets/returns whether the geometry is blocked or not.""" + + Tag: Final[str] = "" + """Gives the tag of the geometry as string.""" + + Geometry: object = ... + """Returns the underlying geometry object.""" + + @constmethod + def testFlag(self) -> bool: + """ + Returns a boolean indicating whether the given bit is set. + """ + ... + + def setFlag(self) -> None: + """ + Sets the given bit to true/false. + """ + ... + + def mirror(self) -> None: + """ + Performs the symmetrical transformation of this geometric object + """ + ... + + def rotate(self) -> None: + """ + Rotates this geometric object at angle Ang (in radians) about axis + """ + ... + + def scale(self) -> None: + """ + Applies a scaling transformation on this geometric object with a center and scaling factor + """ + ... + + def transform(self) -> None: + """ + Applies a transformation to this geometric object + """ + ... + + def translate(self) -> None: + """ + Translates this geometric object + """ + ... + + @constmethod + def hasExtensionOfType(self) -> bool: + """ + Returns a boolean indicating whether a geometry extension of the type indicated as a string exists. + """ + ... + + @constmethod + def hasExtensionOfName(self) -> bool: + """ + Returns a boolean indicating whether a geometry extension with the name indicated as a string exists. + """ + ... + + @constmethod + def getExtensionOfType(self) -> object: + """ + Gets the first geometry extension of the type indicated by the string. + """ + ... + + @constmethod + def getExtensionOfName(self) -> object: + """ + Gets the first geometry extension of the name indicated by the string. + """ + ... + + def setExtension(self) -> None: + """ + Sets a geometry extension of the indicated type. + """ + ... + + def deleteExtensionOfType(self) -> None: + """ + Deletes all extensions of the indicated type. + """ + ... + + def deleteExtensionOfName(self) -> None: + """ + Deletes all extensions of the indicated name. + """ + ... + + @constmethod + def getExtensions(self) -> List[object]: + """ + Returns a list with information about the geometry extensions. + """ + ... diff --git a/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml b/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml index 906f3dea9b..e9592ebdfd 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml +++ b/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml @@ -28,7 +28,7 @@ - Returns the reference string of this external geometry. +Returns the reference string of this external geometry. @@ -36,7 +36,7 @@ - Sets/returns the Internal Alignment Type of the Geometry. +Sets/returns the Internal Alignment Type of the Geometry. @@ -50,7 +50,7 @@ - Returns the Id of the geometry Layer in which the geometry is located. +Returns the Id of the geometry Layer in which the geometry is located. @@ -66,7 +66,7 @@ - Sets/returns whether the geometry is blocked or not. +Sets/returns whether the geometry is blocked or not. diff --git a/src/Mod/Sketcher/App/GeometryFacade.pyi b/src/Mod/Sketcher/App/GeometryFacade.pyi new file mode 100644 index 0000000000..a78e115d2e --- /dev/null +++ b/src/Mod/Sketcher/App/GeometryFacade.pyi @@ -0,0 +1,139 @@ +from Base.Metadata import export, constmethod +from Base.BaseClass import BaseClass +from Base.Axis import Axis +from Base.CoordinateSystem import CoordinateSystem +from Base.Placement import Placement +from Base.Vector import Vector +from App.DocumentObjectExtension import DocumentObjectExtension +from typing import Final, List + +@export( + PythonName="Sketcher.GeometryFacade", + Include="Mod/Sketcher/App/GeometryFacade.h", + Constructor=True, + Delete=True, +) +class GeometryFacade(BaseClass): + """ + Describes a GeometryFacade + + Author: Abdullah Tahiri (abdullah.tahiri.yo@gmail.com) + Licence: LGPL + """ + + Id: int = ... + """Sets/returns the Id of the SketchGeometryExtension.""" + + InternalType: str = ... + """Sets/returns the Internal Alignment Type of the Geometry.""" + + Blocked: bool = ... + """Sets/returns whether the geometry is blocked or not.""" + + Construction: bool = ... + """Sets/returns this geometry as a construction one, which will not be part of a later built shape.""" + + GeometryLayerId: int = ... + """Returns the Id of the geometry Layer in which the geometry is located.""" + + Tag: Final[str] = ... + """Gives the tag of the geometry as string.""" + + Geometry: object = ... + """Returns the underlying geometry object.""" + + @constmethod + def testGeometryMode(self) -> bool: + """ + Returns a boolean indicating whether the given bit is set. + """ + ... + + def setGeometryMode(self) -> None: + """ + Sets the given bit to true/false. + """ + ... + + def mirror(self) -> None: + """ + Performs the symmetrical transformation of this geometric object + """ + ... + + def rotate(self, Ang: float, axis: Axis) -> None: + """ + Rotates this geometric object at angle Ang (in radians) about axis + """ + ... + + def scale(self, center: CoordinateSystem, factor: float) -> None: + """ + Applies a scaling transformation on this geometric object with a center and scaling factor + """ + ... + + def transform(self, transformation: Placement) -> None: + """ + Applies a transformation to this geometric object + """ + ... + + def translate(self, offset: Vector) -> None: + """ + Translates this geometric object + """ + ... + + @constmethod + def hasExtensionOfType(self, type_str: str) -> bool: + """ + Returns a boolean indicating whether a geometry extension of the type indicated as a string exists. + """ + ... + + @constmethod + def hasExtensionOfName(self, name: str) -> bool: + """ + Returns a boolean indicating whether a geometry extension with the name indicated as a string exists. + """ + ... + + @constmethod + def getExtensionOfType(self, type_str: str) -> DocumentObjectExtension: + """ + Gets the first geometry extension of the type indicated by the string. + """ + ... + + @constmethod + def getExtensionOfName(self, name: str) -> DocumentObjectExtension: + """ + Gets the first geometry extension of the name indicated by the string. + """ + ... + + def setExtension(self, extension: DocumentObjectExtension) -> None: + """ + Sets a geometry extension of the indicated type. + """ + ... + + def deleteExtensionOfType(self, type_str: str) -> None: + """ + Deletes all extensions of the indicated type. + """ + ... + + def deleteExtensionOfName(self, name: str) -> None: + """ + Deletes all extensions of the indicated name. + """ + ... + + @constmethod + def getExtensions(self) -> List[DocumentObjectExtension]: + """ + Returns a list with information about the geometry extensions. + """ + ... diff --git a/src/Mod/Sketcher/App/GeometryFacadePy.xml b/src/Mod/Sketcher/App/GeometryFacadePy.xml index d9c0fdfb2d..83ce9bf4cd 100644 --- a/src/Mod/Sketcher/App/GeometryFacadePy.xml +++ b/src/Mod/Sketcher/App/GeometryFacadePy.xml @@ -29,7 +29,7 @@ - Sets/returns the Id of the SketchGeometryExtension. +Sets/returns the Id of the SketchGeometryExtension. @@ -37,7 +37,7 @@ - Sets/returns the Internal Alignment Type of the Geometry. +Sets/returns the Internal Alignment Type of the Geometry. @@ -45,7 +45,7 @@ - Sets/returns whether the geometry is blocked or not. +Sets/returns whether the geometry is blocked or not. @@ -59,7 +59,7 @@ - Returns the Id of the geometry Layer in which the geometry is located. +Returns the Id of the geometry Layer in which the geometry is located. diff --git a/src/Mod/Sketcher/App/Sketch.pyi b/src/Mod/Sketcher/App/Sketch.pyi new file mode 100644 index 0000000000..6fa03c0c7a --- /dev/null +++ b/src/Mod/Sketcher/App/Sketch.pyi @@ -0,0 +1,72 @@ +from Base.Metadata import export, constmethod +from Base.Persistence import Persistence +from Base.Vector import Vector +from typing import Final, Tuple + +@export( + Include="Mod/Sketcher/App/Sketch.h", + FatherInclude="Base/PersistencePy.h", + Constructor=True, +) +class Sketch(Persistence): + """ + With this objects you can handle constraint sketches + + Author: Juergen Riegel (FreeCAD@juergen-riegel.net) + Licence: LGPL + """ + + Constraint: Final[int] = 0 + """0: exactly constraint, -1 under-constraint, 1 over-constraint""" + + Conflicts: Final[Tuple] = () + """Tuple of conflicting constraints""" + + Redundancies: Final[Tuple] = () + """Tuple of redundant constraints""" + + Geometries: Final[Tuple] = () + """Tuple of all geometric elements in this sketch""" + + Shape: Final[object] = None + """Resulting shape from the sketch geometry""" + + def solve(self) -> None: + """ + Solve the actual set of geometry and constraints + """ + ... + + def addGeometry(self) -> None: + """ + Add a geometric object to the sketch + """ + ... + + def addConstraint(self) -> None: + """ + Add an constraint object to the sketch + """ + ... + + def clear(self) -> None: + """ + Clear the sketch + """ + ... + + def moveGeometry( + self, GeoIndex: int, PointPos: Vector, Vector: Vector, relative: bool = False + ) -> None: + """ + moveGeometry(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve) + to another location. + It moves the specified point (or curve) to the given location by adding some + temporary weak constraints and solve the sketch. + This method is mostly used to allow the user to drag some portions of the sketch + in real time by e.g. the mouse and it works only for underconstrained portions of + the sketch. + The argument 'relative', if present, states if the new location is given + relatively to the current one. + """ + ... diff --git a/src/Mod/Sketcher/App/SketchGeometryExtension.pyi b/src/Mod/Sketcher/App/SketchGeometryExtension.pyi new file mode 100644 index 0000000000..2fda454ba4 --- /dev/null +++ b/src/Mod/Sketcher/App/SketchGeometryExtension.pyi @@ -0,0 +1,45 @@ +from Base.Metadata import export, constmethod +from Part.App.GeometryExtension import GeometryExtension + +@export( + Name="SketchGeometryExtensionPy", + PythonName="Sketcher.SketchGeometryExtension", + Include="Mod/Sketcher/App/SketchGeometryExtension.h", + FatherInclude="Mod/Part/App/GeometryExtensionPy.h", + Constructor=True, +) +class SketchGeometryExtension(GeometryExtension): + """ + Describes a SketchGeometryExtension + + Author: Abdullah Tahiri (abdullah.tahiri.yo@gmail.com) + Licence: LGPL + """ + + Id: int = 0 + """Returns the Id of the SketchGeometryExtension.""" + + InternalType: str = "" + """Returns the Id of the SketchGeometryExtension.""" + + Blocked: bool = False + """Sets/returns whether the geometry is blocked or not.""" + + Construction: bool = False + """Sets/returns this geometry as a construction one, which will not be part of a later built shape.""" + + GeometryLayerId: int = 0 + """Returns the Id of the geometry Layer in which the geometry is located.""" + + @constmethod + def testGeometryMode(self) -> bool: + """ + Returns a boolean indicating whether the given bit is set. + """ + ... + + def setGeometryMode(self) -> None: + """ + Sets the given bit to true/false. + """ + ... diff --git a/src/Mod/Sketcher/App/SketchObject.pyi b/src/Mod/Sketcher/App/SketchObject.pyi new file mode 100644 index 0000000000..ebb8615186 --- /dev/null +++ b/src/Mod/Sketcher/App/SketchObject.pyi @@ -0,0 +1,875 @@ +from Base.Metadata import export, constmethod, no_args +from Base.Quantity import Quantity +from Base.Vector import Vector +from Base.Axis import Axis +from Part.App.Part2DObject import Part2DObject +from Part.App.Geometry import Geometry +from Sketcher.App.Constraint import Constraint +from typing import List, Tuple, Union, Final, overload + +@export( + Include="Mod/Sketcher/App/SketchObject.h", + FatherInclude="Mod/Part/App/Part2DObjectPy.h", +) +class SketchObject(Part2DObject): + """ + Represents a sketch object + + Author: Juergen Riegel + Licence: LGPL + """ + + MissingPointOnPointConstraints: List = ... + """Returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected endpoint constraints.""" + + MissingVerticalHorizontalConstraints: List = ... + """Returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected vertical/horizontal constraints.""" + + MissingLineEqualityConstraints: List = ... + """Returns a list of (First FirstPos Second SecondPos) tuples with all the detected line segment equality constraints.""" + + MissingRadiusConstraints: List = ... + """Returns a list of (First FirstPos Second SecondPos) tuples with all the detected radius constraints.""" + + OpenVertices: Final[List] = ... + """Returns a list of vertices positions.""" + + ConstraintCount: Final[int] = ... + """Number of Constraints in this sketch""" + + GeometryCount: Final[int] = ... + """Number of geometric objects in this sketch""" + + AxisCount: Final[int] = ... + """Return the number of construction lines in the sketch which can be used as axes""" + + GeometryFacadeList: List = ... + """Return a list of GeometryFacade objects corresponding to the PropertyGeometryList""" + + DoF: Final[int] = ... + """Return the DoFs of the current solved sketch""" + + ConflictingConstraints: Final[List] = ... + """Return a list of integers indicating the constraints detected as conflicting""" + + RedundantConstraints: Final[List] = ... + """Return a list of integers indicating the constraints detected as redundant""" + + PartiallyRedundantConstraints: Final[List] = ... + """Return a list of integers indicating the constraints detected as partially redundant""" + + MalformedConstraints: Final[List] = ... + """Return a list of integers indicating the constraints detected as malformed""" + + def solve(self) -> int: + """ + Solve the sketch and update the geometry. + + solve() + + Returns: + 0 in case of success, otherwise the following codes in this order of + priority: + -4 if over-constrained, + -3 if conflicting constraints, + -5 if malformed constraints + -1 if solver error, + -2 if redundant constraints. + """ + ... + + @overload + def addGeometry(self, geo: Geometry, isConstruction: bool = False) -> int: ... + @overload + def addGeometry(self, geo: List[Geometry], isConstruction: bool = False) -> Tuple[int, ...]: ... + def addGeometry( + self, geo: Union[Geometry, List[Geometry]], isConstruction: bool = False + ) -> Union[int, Tuple[int, ...]]: + """ + Add geometric objects to the sketch. + + addGeometry(geo:Geometry, isConstruction=False) -> int + Add a single geometric object to the sketch. + + Args: + geo: The geometry to add. e.g. a Part.LineSegement + isConstruction: Whether the added geometry is a "construction geometry". + Defaults to `False`, i.e. by omitting, a regular geometry is added. + + Returns: + The zero-based index of the newly added geometry. + + addGeometry(geo:List(Geometry), isConstruction=False) -> Tuple(int) + Add many geometric objects to the sketch. + + Args: + geo: The geometry to add. + isConstruction: see above. + + Returns: + A tuple of zero-based indices of all newly added geometry. + """ + ... + + def delGeometry(self, geoId: int) -> None: + """ + Delete a geometric object from the sketch. + + delGeometry(geoId:int) + + Args: + geoId: The zero-based index of the geometry to delete. + Any internal alignment geometry thereof will be deleted, too. + """ + ... + + def delGeometries(self, geoIds: List[int]) -> None: + """ + Delete a list of geometric objects from the sketch. + + delGeometries(geoIds:List(int)) + + Args: + geoId: A list of zero-based indices of the geometry to delete. + Any internal alignment geometry thereof will be deleted, too. + """ + ... + + def deleteAllGeometry(self) -> None: + """ + Delete all the geometry objects from the sketch, except external geometry. + + deleteAllGeometry() + """ + ... + + def detectDegeneratedGeometries(self, tolerance: float) -> int: + """ + Detect degenerated geometries. A curve geometry is considered degenerated + if the parameter range is less than the tolerance. + + detectDegeneratedGeometries(tolerance:float) + + Args: + tolerance: The tolerance to check the parameter range of a curve. + + Returns: + The number of degenerated geometries. + """ + ... + + def removeDegeneratedGeometries(self, tolerance: float) -> int: + """ + Remove degenerated geometries. A curve geometry is considered degenerated + if the parameter range is less than the tolerance. + + removeDegeneratedGeometries(tolerance:float) + + Args: + tolerance: The tolerance to check the parameter range of a curve. + + Returns: + The number of degenerated geometries. + """ + ... + + def deleteAllConstraints(self) -> None: + """ + Delete all the constraints from the sketch. + + deleteAllConstraints() + """ + ... + + def toggleConstruction(self, geoId: int) -> None: + """ + Toggles a geometry between regular and construction. + + toggleConstruction(geoId:int) + + Args: + geoId: The zero-based index of the geometry to toggle. + """ + ... + + def setConstruction(self, geoId: int, state: bool) -> None: + """ + Set construction mode of a geometry. + + setConstruction(geoId:int, state:bool) + + Args: + geoId: The zero-based index of the geometry to configure. + state: `True` configures the geometry to "construction geometry", + `False` configures it to regular geometry. + """ + ... + + def getConstruction(self, geoId: int) -> bool: + """ + Determine whether the given geometry is a "construction geometry". + + getConstruction(geoId:int) + + Args: + geoId: The zero-based index of the geometry to query. + + Returns: + `True` if the geometry is "construction geometry" and + `False` if it s a regular geometry. + """ + ... + + @overload + def addConstraint(self, constraint: Constraint) -> int: ... + @overload + def addConstraint(self, constraints: List[Constraint]) -> Tuple[int, ...]: ... + def addConstraint( + self, constraint: Union[Constraint, List[Constraint]] + ) -> Union[int, Tuple[int, ...]]: + """ + Add constraints to the sketch. + + addConstraint(constraint:Constraint) -> int + Add a single constraint to the sketch and solves it. + + Returns: + The zero-based index of the newly added constraint. + + addConstraint(constraints:List(Constraint)) -> Tuple(int) + Add many constraints to the sketch without solving. + + Returns: + A tuple of zero-based indices of all newly added constraints. + """ + ... + + def delConstraint(self, constraintIndex: int) -> None: + """ + Delete a constraint from the sketch. + + delConstraint(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to delete. + """ + ... + + def renameConstraint(self, constraintIndex: int, name: str) -> None: + """ + Rename a constraint in the sketch. + + renameConstraint(constraintIndex:int, name:str) + + Args: + constraintIndex: The zero-based index of the constraint to rename. + name: The new name for the constraint. + An empty string makes the constraint "unnamed" again. + """ + ... + + @constmethod + def getIndexByName(self, name: str) -> int: + """ + Get the index of a constraint by name. + + getIndexByName(name:str) + + Args: + name: The name for the constraint to look up. + If there is no such constraint an exception is raised. + """ + ... + + def carbonCopy(self, objName: str, asConstruction: bool = True) -> None: + """ + Copy another sketch's geometry and constraints into this sketch. + + carbonCopy(objName:str, asConstruction=True) + + Args: + ObjName: The name of the sketch object to copy from. + asConstruction: Whether to copy the geometry as "construction geometry". + """ + ... + + def addExternal( + self, objName: str, subName: str, defining: bool = False, intersection: bool = False + ) -> None: + """ + Add a link to an external geometry. + + addExternal(objName:str, subName:str, defining:bool=False, intersection:bool=False) + + Args: + objName: The name of the document object to reference. + subName: The name of the sub-element of the object's shape to link as + "external geometry". + defining: Should the external edges be defining or construction? + intersection: Should the external edges be projections or intersections? + """ + ... + + def delExternal(self, extGeoId: int) -> None: + """ + Delete an external geometry link from the sketch. + + delExternal(extGeoId:int) + + Args: + extGeoId: The zero-based index of the external geometry to remove. + """ + ... + + @overload + def delConstraintOnPoint(self, vertexId: int) -> None: ... + @overload + def delConstraintOnPoint(self, geoId: int, pointPos: int) -> None: ... + def delConstraintOnPoint(self, *args: int) -> None: + """ + Delete coincident constraints associated with a sketch point. + + delConstraintOnPoint(vertexId:int) + + Args: + vertexId: A zero-based index of the shape's vertices. + + delConstraintOnPoint(geoId:int, pointPos:int) + + Args: + geoId: The zero-based index of the geometry that contains the point. + pointPos: Enum denoting which point on the geometry is meant: + 1: the start of a line or bounded curve. + 2: the end of a line or bounded curve. + 3: the center of a circle or ellipse. + """ + ... + + @no_args + def delConstraintsToExternal(self) -> None: + """ + Deletes all constraints referencing an external geometry. + """ + ... + + def setDatum(self, constraint: Union[int, str], value: Union[float, Quantity]) -> None: + """ + Set the value of a datum constraint (e.g. Distance or Angle) + + setDatum(constraint, value) + + Args: + constraint (int or str): The index or name of the constraint to set. + value (float or Quantity): The value to set for the constraint. When + using floats, values for linear dimensions are interpreted as + millimeter, angular ones as radians. + """ + ... + + @constmethod + def getDatum(self, constraint: Union[int, str]) -> Quantity: + """ + Get the value of a datum constraint (e.g. Distance or Angle) + + getDatum(constraint) -> Quantity + + Args: + constraint (int or str): The index or name of the constraint to query. + + Returns: + The value of the constraint. + """ + ... + + def setDriving(self, constraintIndex: int, state: bool) -> None: + """ + Set the Driving status of a datum constraint. + + setDriving(constraintIndex:int, state:bool) + + Args: + constraintIndex: The zero-based index of the constraint to configure. + state: `True` sets the constraint to driving, + `False` configures it as non-driving, i.e. reference. + """ + ... + + def setDatumsDriving(self, state: bool) -> None: + """ + Set the Driving status of all datum constraints. + + setDatumsDriving(state:bool) + + Args: + state: `True` set all datum constraints to driving, + `False` configures them as non-driving, i.e. reference. + """ + ... + + def moveDatumsToEnd(self) -> None: + """ + Moves all datum constraints to the end of the constraint list. + + moveDatumsToEnd() + + Warning: This method reorders the constraint indices. Previously held + numeric references to constraints may reference different constraints + after this operation. + """ + ... + + @constmethod + def getDriving(self, constraintIndex: int) -> bool: + """ + Get the Driving status of a datum constraint. + + getDriving(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to query. + + Returns: + `True` if the constraint is driving, + `False` if it is non-driving, i.e. reference. + """ + ... + + def toggleDriving(self, constraintIndex: int) -> None: + """ + Toggle the Driving status of a datum constraint. + + toggleDriving(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to toggle. + """ + ... + + def setVirtualSpace(self) -> None: + """ + Set the VirtualSpace status of a constraint + """ + ... + + def getVirtualSpace(self) -> bool: + """ + Get the VirtualSpace status of a constraint + """ + ... + + def toggleVirtualSpace(self) -> None: + """ + Toggle the VirtualSpace status of a constraint + """ + ... + + def setActive(self, constraintIndex: int, state: bool) -> None: + """ + Activates or deactivates a constraint (enforce it or not). + + setActive(constraintIndex:int, state:bool) + + Args: + constraintIndex: The zero-based index of the constraint to configure. + state: `True` sets the constraint to active i.e. enforced, + `False` configures it as inactive, i.e. not enforced. + """ + ... + + @constmethod + def getActive(self, constraintIndex: int) -> bool: + """ + Get whether a constraint is active, i.e. enforced, or not. + + getActive(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to query. + + Returns: + `True` if the constraint is active, i.e. enforced, + `False` if it is inactive, i.e. not enforced. + """ + ... + + def toggleActive(self, constraintIndex: int) -> None: + """ + Toggle the constraint between active (enforced) and inactive. + + toggleActive(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to toggle. + """ + ... + + @constmethod + def getLabelPosition(self, constraintIndex: int) -> float: + """ + Get label position of the constraint. + + getLabelPosition(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to query. + + Returns: + float with the current value. + """ + ... + + def setLabelPosition(self, constraintIndex: int, value: float) -> None: + """ + Set label position of the constraint. + + setLabelPosition(constraintIndex:int, value:float) + + Args: + constraintIndex: The zero-based index of the constraint to query. + value: Value of the label position. + """ + ... + + @constmethod + def getLabelDistance(self, constraintIndex: int) -> float: + """ + Get label distance of the constraint. + + getLabelDistance(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to query. + + Returns: + float with the current value. + """ + ... + + def setLabelDistance(self, constraintIndex: int, value: float) -> None: + """ + Set label distance of the constraint. + + setLabelDistance(constraintIndex:int, value:float) + + Args: + constraintIndex: The zero-based index of the constraint to query. + value: Value of the label position. + """ + ... + + def moveGeometry( + self, GeoIndex: int, PointPos: int, Vector: Vector, relative: bool = False + ) -> None: + """ + Move a given point (or curve) to another location. + + moveGeometry(GeoIndex,PointPos,Vector,[relative]) + + It moves the specified point (or curve) to the given location by adding some + temporary weak constraints and solving the sketch. + This method is mostly used to allow the user to drag some portions of the sketch + in real time by e.g. the mouse and it works only for underconstrained portions of + the sketch. + The argument 'relative', if present, states if the new location is given + relatively to the current one. + """ + ... + + def moveGeometries( + self, Geos: List[Tuple[int, int]], Vector: Vector, relative: bool = False + ) -> None: + """ + Move given points and curves to another location. + + moveGeometries(Geos,Vector,[relative]) + + It moves the specified points and curves to the given location by adding some + temporary weak constraints and solving the sketch. + This method is mostly used to allow the user to drag some portions of the sketch + in real time by e.g. the mouse and it works only for underconstrained portions of + the sketch. + The argument 'relative', if present, states if the new location is given + relatively to the current one. For group dragging this is enforced. + Geos is a vector of pairs of geoId and posId. + """ + ... + + @constmethod + def getPoint(self, GeoIndex: int, PointPos: int) -> Vector: + """ + Retrieve the vector of a point in the sketch. + + getPoint(GeoIndex,PointPos) + """ + ... + + @constmethod + def getGeoVertexIndex(self, index: int) -> Tuple[int, int]: + """ + Retrieve the GeoId and PosId of a point in the sketch. + + (geoId, posId) = getGeoVertexIndex(index) + """ + ... + + @constmethod + def getAxis(self) -> Axis: + """ + Return an axis based on the corresponding construction line + """ + ... + + def fillet(self) -> None: + """ + Create a fillet between two edges or at a point + """ + ... + + def trim(self) -> None: + """ + Trim a curve with a given id at a given reference point + """ + ... + + def extend(self) -> None: + """ + Extend a curve to new start and end positions + """ + ... + + def split(self) -> None: + """ + Split a curve with a given id at a given reference point + """ + ... + + def join(self) -> None: + """ + Join two curves at the given end points + """ + ... + + def addSymmetric(self) -> None: + """ + Add symmetric geometric objects to the sketch with respect to a reference point or line + """ + ... + + def addCopy(self) -> None: + """ + Add a copy of geometric objects to the sketch displaced by a vector3d + """ + ... + + def addMove(self) -> None: + """ + Move the geometric objects in the sketch displaced by a vector3d + """ + ... + + def addRectangularArray(self) -> None: + """ + Add an array of size cols by rows where each element is a copy of the selected geometric objects displaced by a vector3d in the cols direction and by a vector perpendicular to it in the rows direction + """ + ... + + def removeAxesAlignment(self) -> None: + """ + Modifies constraints so that the shape is not forced to be aligned with axes. + """ + ... + + def ExposeInternalGeometry(self) -> None: + """ + Deprecated -- use exposeInternalGeometry + """ + ... + + def DeleteUnusedInternalGeometry(self) -> None: + """ + Deprecated -- use deleteUnusedInternalGeometry + """ + ... + + def exposeInternalGeometry(self) -> None: + """ + Exposes all internal geometry of an object supporting internal geometry + """ + ... + + def deleteUnusedInternalGeometry(self) -> None: + """ + Deletes all unused (not further constrained) internal geometry + """ + ... + + def convertToNURBS(self) -> None: + """ + Approximates the given geometry with a B-spline + """ + ... + + def increaseBSplineDegree(self) -> None: + """ + Increases the given B-spline Degree by a number of degrees + """ + ... + + def decreaseBSplineDegree(self) -> None: + """ + Decreases the given B-spline Degree by a number of degrees by approximating this curve + """ + ... + + def modifyBSplineKnotMultiplicity(self) -> None: + """ + Increases or reduces the given BSpline knot multiplicity + """ + ... + + def insertBSplineKnot(self) -> None: + """ + Inserts a knot into the BSpline at the given param with given multiplicity. If the knot already exists, this increases the knot multiplicity by the given multiplicity. + """ + ... + + def calculateAngleViaPoint(self, GeoId1: int, GeoId2: int, px: float, py: float) -> float: + """ + calculateAngleViaPoint(GeoId1, GeoId2, px, py) - calculates angle between + curves identified by GeoId1 and GeoId2 at point (x,y). The point must be + on intersection of the curves, otherwise the result may be useless (except + line-to-line, where (0,0) is OK). Returned value is in radians. + """ + ... + + def isPointOnCurve(self, GeoIdCurve: int, x: float, y: float) -> bool: + """ + isPointOnCurve(GeoIdCurve, float x, float y) -> bool - tests if the point (x,y) + geometrically lies on a curve (e.g. ellipse). It treats lines as infinite, + arcs as full circles/ellipses/etc. + """ + ... + + def calculateConstraintError(self, index: int) -> float: + """ + calculateConstraintError(index) - calculates the error function of the + constraint identified by its index and returns the signed error value. + The error value roughly corresponds to by how much the constraint is + violated. If the constraint internally has more than one error function, + the returned value is RMS of all errors (sign is lost in this case). + """ + ... + + def changeConstraintsLocking(self, bLock: bool) -> None: + """ + changeConstraintsLocking(bLock) - locks or unlocks all tangent and + perpendicular constraints. (Constraint locking prevents it from + flipping to another valid configuration, when e.g. external geometry + is updated from outside.) The sketch solve is not triggered by the + function, but the SketchObject is touched (a recompute will be + necessary). The geometry should not be affected by the function. + + The bLock argument specifies, what to do. If true, all constraints + are unlocked and locked again. If false, all tangent and perp. + constraints are unlocked. + """ + ... + + def getGeometryWithDependentParameters(self) -> List[Tuple[int, int]]: + """ + getGeometryWithDependentParameters - returns a list of geoid posid pairs + with all the geometry element edges and vertices which the solver regards + as being dependent on other parameters. + """ + ... + + def autoconstraint(self) -> None: + """ + Automatic sketch constraining algorithm. + """ + ... + + def detectMissingPointOnPointConstraints(self) -> None: + """ + Detects missing Point On Point Constraints. The detect step just identifies possible missing constraints. + The result may be retrieved or applied using the corresponding Get / Make methods. + """ + ... + + def analyseMissingPointOnPointCoincident(self) -> None: + """ + Analyses the already detected missing Point On Point Constraints to detect endpoint tangency/perpendicular. + The result may be retrieved or applied using the corresponding Get / Make methods. + """ + ... + + def detectMissingVerticalHorizontalConstraints(self) -> None: + """ + Detects missing Horizontal/Vertical Constraints. The detect step just identifies possible missing constraints. + The result may be retrieved or applied using the corresponding Get / Make methods. + """ + ... + + def detectMissingEqualityConstraints(self) -> None: + """ + Detects missing Equality Constraints. The detect step just identifies possible missing constraints. + The result may be retrieved or applied using the corresponding Get / Make methods. + """ + ... + + def makeMissingPointOnPointCoincident(self, arg: bool) -> None: + """ + Applies the detected / set Point On Point coincident constraints. If the argument is True, then solving and redundant removal is done after each individual addition. + """ + ... + + def makeMissingVerticalHorizontal(self, arg: bool) -> None: + """ + Applies the detected / set Vertical/Horizontal constraints. If the argument is True, then solving and redundant removal is done after each individual addition. + """ + ... + + def makeMissingEquality(self, arg: bool) -> None: + """ + Applies the detected / set Equality constraints. If the argument is True, then solving and redundant removal is done after each individual addition. + """ + ... + + @constmethod + @no_args + def evaluateConstraints(self) -> bool: + """ + Check for constraints with invalid indexes. Returns True if invalid constraints are found, False otherwise. + """ + ... + + @no_args + def validateConstraints(self) -> None: + """ + Removes constraints with invalid indexes. + """ + ... + + def autoRemoveRedundants(self, arg: bool) -> None: + """ + Removes constraints currently detected as redundant by the solver. If the argument is True, then the geometry is updated after solving. + """ + ... + + def toPythonCommands(self) -> None: + """ + Prints the commands that should be executed to recreate the Geometry and Constraints of the present sketch (excluding any External Geometry). + """ + ... + + def setGeometryId(): + """ + Sets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId + """ + ... + + def getGeometryId(): + """ + Gets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId + """ + ... diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml index 43dab8c3b7..70701700c6 100644 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ b/src/Mod/Sketcher/App/SketchObjectPy.xml @@ -20,14 +20,14 @@ Solve the sketch and update the geometry. solve() - Returns: - 0 in case of success, otherwise the following codes in this order of - priority: - -4 if over-constrained, - -3 if conflicting constraints, - -5 if malformed constraints - -1 if solver error, - -2 if redundant constraints. + Returns: + 0 in case of success, otherwise the following codes in this order of + priority: + -4 if over-constrained, + -3 if conflicting constraints, + -5 if malformed constraints + -1 if solver error, + -2 if redundant constraints. @@ -366,7 +366,7 @@ Moves all datum constraints to the end of the constraint list. moveDatumsToEnd() - Warning: This method reorders the constraint indices. Previously hold + Warning: This method reorders the constraint indices. Previously held numeric references to constraints may reference different constraints after this operation. @@ -402,7 +402,7 @@ toggleDriving(constraintIndex:int) - set the VirtualSpace status of a constraint + Set the VirtualSpace status of a constraint @@ -412,7 +412,7 @@ toggleDriving(constraintIndex:int) - toggle the VirtualSpace status of a constraint + Toggle the VirtualSpace status of a constraint @@ -516,103 +516,111 @@ setLabelDistance(constraintIndex:int, value:float) - moveGeometry(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve) - to another location. - It moves the specified point (or curve) to the given location by adding some - temporary weak constraints and solve the sketch. - This method is mostly used to allow the user to drag some portions of the sketch - in real time by e.g. the mouse and it works only for underconstrained portions of - the sketch. - The argument 'relative', if present, states if the new location is given - relatively to the current one. +Move a given point (or curve) to another location. + +moveGeometry(GeoIndex,PointPos,Vector,[relative]) + +It moves the specified point (or curve) to the given location by adding some +temporary weak constraints and solving the sketch. +This method is mostly used to allow the user to drag some portions of the sketch +in real time by e.g. the mouse and it works only for underconstrained portions of +the sketch. +The argument 'relative', if present, states if the new location is given +relatively to the current one. - moveGeometries(Geos,Vector,[relative]) - move given points and curves - to another location. - It moves the specified points and curves to the given location by adding some - temporary weak constraints and solve the sketch. - This method is mostly used to allow the user to drag some portions of the sketch - in real time by e.g. the mouse and it works only for underconstrained portions of - the sketch. - The argument 'relative', if present, states if the new location is given - relatively to the current one. For group dragging this is enforced. - Geos is a vector of pairs of geoId and posId. +Move given points and curves to another location. + +moveGeometries(Geos,Vector,[relative]) + +It moves the specified points and curves to the given location by adding some +temporary weak constraints and solving the sketch. +This method is mostly used to allow the user to drag some portions of the sketch +in real time by e.g. the mouse and it works only for underconstrained portions of +the sketch. +The argument 'relative', if present, states if the new location is given +relatively to the current one. For group dragging this is enforced. +Geos is a vector of pairs of geoId and posId. - getPoint(GeoIndex,PointPos) - retrieve the vector of a point in the sketch +Retrieve the vector of a point in the sketch. + +getPoint(GeoIndex,PointPos) - (geoId, posId) = getGeoVertexIndex(index) - retrieve the GeoId and PosId of a point in the sketch +Retrieve the GeoId and PosId of a point in the sketch. + +(geoId, posId) = getGeoVertexIndex(index) - return an axis based on the corresponding construction line +Return an axis based on the corresponding construction line - create fillet between two edges or at a point + Create a fillet between two edges or at a point - trim a curve with a given id at a given reference point + Trim a curve with a given id at a given reference point - extend a curve to new start and end positions + Extend a curve to new start and end positions - split a curve with a given id at a given reference point + Split a curve with a given id at a given reference point - join two curves at the given end points + Join two curves at the given end points - add a symmetric geometric objects to the sketch with respect to a reference point or line + Add symmetric geometric objects to the sketch with respect to a reference point or line - add a copy of geometric objects to the sketch displaced by a vector3d + Add a copy of geometric objects to the sketch displaced by a vector3d - Moves the geometric objects in the sketch displaced by a vector3d + Move the geometric objects in the sketch displaced by a vector3d - add an array of size cols by rows where each element is a copy of the selected geometric objects displaced by a vector3d in the cols direction and by a vector perpendicular to it in the rows direction + Add an array of size cols by rows where each element is a copy of the selected geometric objects displaced by a vector3d in the cols direction and by a vector perpendicular to it in the rows direction - modifies constraints so that the shape is not forced to be aligned with axes. + Modifies constraints so that the shape is not forced to be aligned with axes. @@ -663,150 +671,150 @@ setLabelDistance(constraintIndex:int, value:float) - calculateAngleViaPoint(GeoId1, GeoId2, px, py) - calculates angle between - curves identified by GeoId1 and GeoId2 at point (x,y). The point must be - on intersection of the curves, otherwise the result may be useless (except - line-to-line, where (0,0) is OK). Returned value is in radians. +calculateAngleViaPoint(GeoId1, GeoId2, px, py) - calculates angle between +curves identified by GeoId1 and GeoId2 at point (x,y). The point must be +on intersection of the curves, otherwise the result may be useless (except +line-to-line, where (0,0) is OK). Returned value is in radians. - isPointOnObject(GeoIdCurve, float x, float y) - tests if the point (x,y) - geometrically lies on a curve (e.g. ellipse). It treats lines as infinite, - arcs as full circles/ellipses/etc. Returns boolean value. +isPointOnCurve(GeoIdCurve, float x, float y) -> bool - tests if the point (x,y) +geometrically lies on a curve (e.g. ellipse). It treats lines as infinite, +arcs as full circles/ellipses/etc. - calculateConstraintError(index) - calculates the error function of the - constraint identified by its index and returns the signed error value. - The error value roughly corresponds to by how much the constraint is - violated. If the constraint internally has more than one error function, - the returned value is RMS of all errors (sign is lost in this case). +calculateConstraintError(index) - calculates the error function of the +constraint identified by its index and returns the signed error value. +The error value roughly corresponds to by how much the constraint is +violated. If the constraint internally has more than one error function, +the returned value is RMS of all errors (sign is lost in this case). - changeConstraintsLocking(bLock) - locks or unlocks all tangent and - perpendicular constraints. (Constraint locking prevents it from - flipping to another valid configuration, when e.g. external geometry - is updated from outside.) The sketch solve is not triggered by the - function, but the SketchObject is touched (a recompute will be - necessary). The geometry should not be affected by the function. +changeConstraintsLocking(bLock) - locks or unlocks all tangent and +perpendicular constraints. (Constraint locking prevents it from +flipping to another valid configuration, when e.g. external geometry +is updated from outside.) The sketch solve is not triggered by the +function, but the SketchObject is touched (a recompute will be +necessary). The geometry should not be affected by the function. - The bLock argument specifies, what to do. If true, all constraints - are unlocked and locked again. If false, all tangent and perp. - constraints are unlocked. +The bLock argument specifies, what to do. If true, all constraints +are unlocked and locked again. If false, all tangent and perp. +constraints are unlocked. - getGeometryWithDependentParameters - returns a list of geoid posid pairs - with all the geometry element edges and vertices which the solver regards - as being dependent on other parameters. +getGeometryWithDependentParameters - returns a list of geoid posid pairs +with all the geometry element edges and vertices which the solver regards +as being dependent on other parameters. - Automatic sketch constraining algorithm. +Automatic sketch constraining algorithm. - Detects Missing Point On Point Constraints. The Detect step just identifies possible missing constraints. - The result may be retrieved or applied using the corresponding Get / Make methods. +Detects missing Point On Point Constraints. The detect step just identifies possible missing constraints. +The result may be retrieved or applied using the corresponding Get / Make methods. - Analyses the already detected Missing Point On Point Constraints to detect endpoint tagency/perpendicular. - The result may be retrieved or applied using the corresponding Get / Make methods. +Analyses the already detected missing Point On Point Constraints to detect endpoint tangency/perpendicular. +The result may be retrieved or applied using the corresponding Get / Make methods. - Detects Missing Horizontal/Vertical Constraints. The Detect step just identifies possible missing constraints. - The result may be retrieved or applied using the corresponding Get / Make methods. +Detects missing Horizontal/Vertical Constraints. The detect step just identifies possible missing constraints. +The result may be retrieved or applied using the corresponding Get / Make methods. - Detects Missing Equality Constraints. The Detect step just identifies possible missing constraints. - The result may be retrieved or applied using the corresponding Get / Make methods. +Detects missing Equality Constraints. The detect step just identifies possible missing constraints. +The result may be retrieved or applied using the corresponding Get / Make methods. - Applies the detected / set Point On Point coincident constraints. If the argument is True, then solving and redundant removal is done after each individual addition. +Applies the detected / set Point On Point coincident constraints. If the argument is True, then solving and redundant removal is done after each individual addition. - Applies the detected / set Vertical/Horizontal constraints. If the argument is True, then solving and redundant removal is done after each individual addition. +Applies the detected / set Vertical/Horizontal constraints. If the argument is True, then solving and redundant removal is done after each individual addition. - Applies the detected / set Equality constraints. If the argument is True, then solving and redundant removal is done after each individual addition. +Applies the detected / set Equality constraints. If the argument is True, then solving and redundant removal is done after each individual addition. - Check for constraints with invalid indexes. Returns True if invalid constraints are found, False otherwise. +Check for constraints with invalid indexes. Returns True if invalid constraints are found, False otherwise. - Removes constraints with invalid indexes. +Removes constraints with invalid indexes. - Removes constraints currently detected as redundant by the solver. If the argument is True, then the geometry is updated after solving. +Removes constraints currently detected as redundant by the solver. If the argument is True, then the geometry is updated after solving. - Prints the commands that should be executed to recreate the Geometry and Constraints of the present sketch (excluding any External Geometry). +Prints the commands that should be executed to recreate the Geometry and Constraints of the present sketch (excluding any External Geometry). - returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected endpoint constraints. +Returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected endpoint constraints. @@ -814,7 +822,7 @@ setLabelDistance(constraintIndex:int, value:float) - returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected vertical/horizontal constraints. +Returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected vertical/horizontal constraints. @@ -822,7 +830,7 @@ setLabelDistance(constraintIndex:int, value:float) - returns a list of (First FirstPos Second SecondPos) tuples with all the detected line segment equality constraints. +Returns a list of (First FirstPos Second SecondPos) tuples with all the detected line segment equality constraints. @@ -830,7 +838,7 @@ setLabelDistance(constraintIndex:int, value:float) - returns a list of (First FirstPos Second SecondPos) tuples with all the detected radius constraints. +Returns a list of (First FirstPos Second SecondPos) tuples with all the detected radius constraints. @@ -838,7 +846,7 @@ setLabelDistance(constraintIndex:int, value:float) - returns a list of vertices positions. +Returns a list of vertices positions. @@ -913,12 +921,12 @@ setLabelDistance(constraintIndex:int, value:float) - sets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId + Sets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId - gets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId + Gets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId diff --git a/src/Mod/Sketcher/App/SketchObjectSF.pyi b/src/Mod/Sketcher/App/SketchObjectSF.pyi new file mode 100644 index 0000000000..7766381e87 --- /dev/null +++ b/src/Mod/Sketcher/App/SketchObjectSF.pyi @@ -0,0 +1,16 @@ +from Base.Metadata import export +from Part.Part2DObject import Part2DObject + +@export( + Include="Mod/Sketcher/App/SketchObjectSF.h", + FatherInclude="Mod/Part/App/Part2DObjectPy.h", +) +class SketchObjectSF(Part2DObject): + """ + With this objects you can handle sketches + + Author: Juergen Riegel (FreeCAD@juergen-riegel.net) + Licence: LGPL + """ + + ... diff --git a/src/Mod/Sketcher/App/SketchPy.xml b/src/Mod/Sketcher/App/SketchPy.xml index 7285d7951e..6fd4a9f2a2 100644 --- a/src/Mod/Sketcher/App/SketchPy.xml +++ b/src/Mod/Sketcher/App/SketchPy.xml @@ -17,36 +17,36 @@ - solve the actual set of geometry and constraints + Solve the actual set of geometry and constraints - add a geometric object to the sketch + Add a geometric object to the sketch - add an constraint object to the sketch + Add an constraint object to the sketch - clear the sketch + Clear the sketch - moveGeometry(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve) - to another location. - It moves the specified point (or curve) to the given location by adding some - temporary weak constraints and solve the sketch. - This method is mostly used to allow the user to drag some portions of the sketch - in real time by e.g. the mouse and it works only for underconstrained portions of - the sketch. - The argument 'relative', if present, states if the new location is given - relatively to the current one. +moveGeometry(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve) +to another location. +It moves the specified point (or curve) to the given location by adding some +temporary weak constraints and solve the sketch. +This method is mostly used to allow the user to drag some portions of the sketch +in real time by e.g. the mouse and it works only for underconstrained portions of +the sketch. +The argument 'relative', if present, states if the new location is given +relatively to the current one. diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index 0b7b27ad7c..38ab21d39f 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -18,6 +18,7 @@ qt_create_resource_file(${Sketcher_TR_QRC} ${QM_SRCS}) qt_add_resources(SketcherGui_SRCS Resources/Sketcher.qrc ${Sketcher_TR_QRC}) generate_from_xml(ViewProviderSketchGeometryExtensionPy) +generate_from_py_(ViewProviderSketchGeometryExtension) set(SketcherGui_UIC_SRCS TaskSketcherConstraints.ui diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.pyi b/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.pyi new file mode 100644 index 0000000000..a3994baf4a --- /dev/null +++ b/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.pyi @@ -0,0 +1,20 @@ +from Base.Metadata import export +from Part.App.GeometryExtension import GeometryExtension + +@export( + PythonName="SketcherGui.ViewProviderSketchGeometryExtension", + Include="Mod/Sketcher/Gui/ViewProviderSketchGeometryExtension.h", + Namespace="SketcherGui", + FatherInclude="Mod/Part/App/GeometryExtensionPy.h", + Constructor=True, +) +class ViewProviderSketchGeometryExtension(GeometryExtension): + """ + Describes a ViewProviderSketchGeometryExtension + + Author: Abdullah Tahiri (abdullah.tahiri.yo@gmail.com) + Licence: LGPL + """ + + VisualLayerId: int = ... + """Sets/returns this geometry's Visual Layer Id.""" From 7986ea0cba326787b69d481a79c2750a09c5a230 Mon Sep 17 00:00:00 2001 From: tritao Date: Thu, 3 Apr 2025 00:46:19 +0100 Subject: [PATCH 142/316] PartGui: Convert XML bindings to Python bindings model. --- src/Mod/Part/Gui/CMakeLists.txt | 4 ++-- src/Mod/Part/Gui/ViewProviderPartExt.pyi | 17 +++++++++++++++++ src/Mod/Part/Gui/ViewProviderPartExtPy.xml | 17 ----------------- 3 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 src/Mod/Part/Gui/ViewProviderPartExt.pyi delete mode 100644 src/Mod/Part/Gui/ViewProviderPartExtPy.xml diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index 57569603b0..485ba9cecf 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -29,7 +29,7 @@ list(APPEND PartGui_LIBS ${QtConcurrent_LIBRARIES} ) -generate_from_xml(ViewProviderPartExtPy) +generate_from_py(ViewProviderPartExt) set (Part_TR_QRC ${CMAKE_CURRENT_BINARY_DIR}/Resources/Part_translation.qrc) qt_find_and_add_translation(QM_SRCS "Resources/translations/*_*.ts" @@ -70,7 +70,7 @@ set(PartGui_UIC_SRCS ) SET(Python_SRCS - ViewProviderPartExtPy.xml + ViewProviderPartExt.pyi ViewProviderPartExtPyImp.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) diff --git a/src/Mod/Part/Gui/ViewProviderPartExt.pyi b/src/Mod/Part/Gui/ViewProviderPartExt.pyi new file mode 100644 index 0000000000..8ef9d945f4 --- /dev/null +++ b/src/Mod/Part/Gui/ViewProviderPartExt.pyi @@ -0,0 +1,17 @@ +from Base.Metadata import export +from Gui.ViewProviderGeometryObject import ViewProviderGeometryObject + + +@export( + Include="Mod/Part/Gui/ViewProviderExt.h", + Namespace="PartGui", +) +class ViewProviderPartExt(ViewProviderGeometryObject): + """ + This is the ViewProvider geometry class + + Author: David Carter (dcarter@davidcarter.ca) + Licence: LGPL + """ + ... + \ No newline at end of file diff --git a/src/Mod/Part/Gui/ViewProviderPartExtPy.xml b/src/Mod/Part/Gui/ViewProviderPartExtPy.xml deleted file mode 100644 index 76b9602ab4..0000000000 --- a/src/Mod/Part/Gui/ViewProviderPartExtPy.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - This is the ViewProvider geometry class - - - From 80aca250ad48a289fede52d8063b9138630fc735 Mon Sep 17 00:00:00 2001 From: tritao Date: Wed, 26 Mar 2025 12:42:55 +0000 Subject: [PATCH 143/316] Tools: Add PyCXX includes to generated Python binding files. --- src/Tools/bindings/templates/templateClassPyExport.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tools/bindings/templates/templateClassPyExport.py b/src/Tools/bindings/templates/templateClassPyExport.py index 9dc65a8e42..c88ff1d3b5 100644 --- a/src/Tools/bindings/templates/templateClassPyExport.py +++ b/src/Tools/bindings/templates/templateClassPyExport.py @@ -122,6 +122,7 @@ class TemplateClassPyExport(template.ModelTemplate): #ifndef @self.export.Namespace.upper().replace("::", "_")@_@self.export.Name.upper()@_H #define @self.export.Namespace.upper().replace("::", "_")@_@self.export.Name.upper()@_H +#include #include <@self.export.FatherInclude@> #include <@self.export.Include@> #include From ccbae8b847d1b088034918ab7fcb632b466f262d Mon Sep 17 00:00:00 2001 From: tritao Date: Wed, 26 Mar 2025 12:43:13 +0000 Subject: [PATCH 144/316] Base: Clean up Python includes in `PyObjectBase.h`. --- src/Base/PyObjectBase.h | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/Base/PyObjectBase.h b/src/Base/PyObjectBase.h index 18237d4604..28640e7f52 100644 --- a/src/Base/PyObjectBase.h +++ b/src/Base/PyObjectBase.h @@ -25,36 +25,11 @@ // clang-format off // NOLINTBEGIN(cppcoreguidelines-macro-usage) -// Std. configurations - -// (re-)defined in pyconfig.h -#if defined (_POSIX_C_SOURCE) -# undef _POSIX_C_SOURCE -#endif -#if defined (_XOPEN_SOURCE) -# undef _XOPEN_SOURCE -#endif - -// needed header -#undef slots -#include -#ifdef FC_OS_MACOSX -#undef toupper -#undef tolower -#undef isupper -#undef islower -#undef isspace -#undef isalpha -#undef isalnum -#endif -#define slots #include #include - -#include "Exception.h" - #include +#include "Exception.h" /** Python static class macro for definition * sets up a static function entry in a class inheriting From 381cb92f0a95b98abbb82adc737c5410aaa9225b Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Sat, 5 Apr 2025 13:47:00 +0200 Subject: [PATCH 145/316] [Core] Add visibility toggling to ViewProvider With this extension of the API, view providers can indicate whether document objects should be able to be toggled for visibility. There is both a C++ and Python interface, idiomatic for FreeCAD code. --- src/Gui/FreeCADGuiInit.py | 7 ++++++- src/Gui/Tree.cpp | 4 +++- src/Gui/ViewProvider.cpp | 1 + src/Gui/ViewProvider.h | 27 +++++++++++++++++++++++++++ src/Gui/ViewProvider.pyi | 10 ++++++++++ src/Gui/ViewProviderPyImp.cpp | 31 +++++++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/Gui/FreeCADGuiInit.py b/src/Gui/FreeCADGuiInit.py index 97f4910d43..5c027d838e 100644 --- a/src/Gui/FreeCADGuiInit.py +++ b/src/Gui/FreeCADGuiInit.py @@ -29,7 +29,7 @@ # imports the one and only import FreeCAD, FreeCADGui -from enum import IntEnum +from enum import IntEnum, Enum # shortcuts Gui = FreeCADGui @@ -52,6 +52,11 @@ class SelectionStyle(IntEnum): NormalSelection = 0 GreedySelection = 1 +# The values must match with that of the Python enum class in ViewProvider.pyi +class ToggleVisibilityMode(Enum): + CanToggleVisibility = "CanToggleVisibility" + NoToggleVisibility = "NoToggleVisibility" + Gui.Selection.SelectionStyle = SelectionStyle # Important definitions diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 77adeb35ee..4cedaba752 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -5534,7 +5534,9 @@ void DocumentObjectItem::testStatus(bool resetStatus, QIcon& icon1, QIcon& icon2 QPainter pt; pt.begin(&px); pt.setPen(Qt::NoPen); - pt.drawPixmap(0, 0, px_org.width(), px_org.height(), (currentStatus & Status::Visible) ? pxVisible : pxInvisible); + if (object()->canToggleVisibility()) { + pt.drawPixmap(0, 0, px_org.width(), px_org.height(), (currentStatus & Status::Visible) ? pxVisible : pxInvisible); + } pt.drawPixmap(px_org.width() + spacing, 0, px_org.width(), px_org.height(), px_org); pt.end(); diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index 2acaebea60..15a30b7adf 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -93,6 +93,7 @@ PROPERTY_SOURCE_ABSTRACT(Gui::ViewProvider, App::TransactionalObject) ViewProvider::ViewProvider() : overrideMode("As Is") + , toggleVisibilityMode(ToggleVisibilityMode::CanToggleVisibility) { setStatus(UpdateData, true); diff --git a/src/Gui/ViewProvider.h b/src/Gui/ViewProvider.h index fd1aeb3d06..a376491ebe 100644 --- a/src/Gui/ViewProvider.h +++ b/src/Gui/ViewProvider.h @@ -121,6 +121,11 @@ class GuiExport ViewProvider : public App::TransactionalObject PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProvider); public: + enum class ToggleVisibilityMode : bool { + CanToggleVisibility = true, + NoToggleVisibility = false + }; + /// constructor. ViewProvider(); @@ -247,6 +252,22 @@ public: /// deliver the icon shown in the tree view virtual QIcon getIcon() const; + /** + * @brief Whether the viewprovider should allow to toggle the visibility. + * + * Some document objects are not rendered and for those document objects, + * it makes no sense to be able to toggle the visibility. Examples are + * VarSet and Spreadsheet. + * + * Note that "rendered" should be seen broadly here. Objects such as + * TechDraw pages, templates, views, and dimensions are not rendered by + * Coin but are "rendered" on the TechDraw page and hence this function can + * return true for those items. + */ + bool canToggleVisibility() const { + return toggleVisibilityMode == ToggleVisibilityMode::CanToggleVisibility; + } + /** @name Methods used by the Tree * If you want to take control over the * viewprovider specific overlay icons that will be drawn with color @@ -571,6 +592,8 @@ protected: /// Turn on mode switch virtual void setModeSwitch(); + void setToggleVisibility(ToggleVisibilityMode mode) { toggleVisibilityMode = mode; } + protected: /// The root Separator of the ViewProvider SoSeparator *pcRoot; @@ -584,6 +607,10 @@ protected: ViewProviderPy* pyViewObject{nullptr}; std::string overrideMode; std::bitset<32> StatusBits; + /// whether visibility can toggled + ToggleVisibilityMode toggleVisibilityMode; + + friend class ViewProviderPy; private: int _iActualMode{-1}; diff --git a/src/Gui/ViewProvider.pyi b/src/Gui/ViewProvider.pyi index 5d651e9893..46d8ec4e9e 100644 --- a/src/Gui/ViewProvider.pyi +++ b/src/Gui/ViewProvider.pyi @@ -2,6 +2,7 @@ from Base.Metadata import constmethod from Base.BoundBox import BoundBox from App.ExtensionContainer import ExtensionContainer from typing import Any, Final, List, Optional +import enum class ViewProvider(ExtensionContainer): @@ -12,6 +13,11 @@ class ViewProvider(ExtensionContainer): Licence: LGPL """ + class ToggleVisibilityMode(enum.Enum): + CanToggleVisibility = "CanToggleVisibility" + NoToggleVisibility = "NoToggleVisibility" + + def addProperty( self, type: str, @@ -367,3 +373,7 @@ class ViewProvider(ExtensionContainer): DropPrefix: Final[str] = "" """Subname referencing the sub-object for holding dropped object.""" + + ToggleVisibility: ToggleVisibilityMode = ToggleVisibilityMode.CanToggleVisibility + """Get/set whether the viewprovider can toggle the visibility of + the object.""" diff --git a/src/Gui/ViewProviderPyImp.cpp b/src/Gui/ViewProviderPyImp.cpp index e3a9f5f5a0..a38d9b0b88 100644 --- a/src/Gui/ViewProviderPyImp.cpp +++ b/src/Gui/ViewProviderPyImp.cpp @@ -706,3 +706,34 @@ Py::String ViewProviderPy::getDropPrefix() const { return {getViewProviderPtr()->getDropPrefix()}; } + +void ViewProviderPy::setToggleVisibility(Py::Object arg) +{ + std::string val; + + if (PyObject_HasAttrString(arg.ptr(), "value")) { + // we are dealing with the enum + val = Py::String(arg.getAttr("value")); + } + else { + // we are dealing with a string + val = Py::String(arg); + } + + if (val == "CanToggleVisibility") { + getViewProviderPtr()->setToggleVisibility(ViewProvider::ToggleVisibilityMode::CanToggleVisibility); + } + else if (val == "NoToggleVisibility") { + getViewProviderPtr()->setToggleVisibility(ViewProvider::ToggleVisibilityMode::NoToggleVisibility); + } + else { + throw Py::ValueError("Invalid ToggleVisibility mode. Use 'CanToggleVisibility' or 'NoToggleVisibility'."); + } +} + +Py::Object ViewProviderPy::getToggleVisibility() const +{ + bool canToggleVisibility = getViewProviderPtr()->canToggleVisibility(); + + return Py::String(canToggleVisibility ? "CanToggleVisibility" : "NoToggleVisibility"); +} From 286ddd0eea20083f87fcade64ed2b60aa4760ee7 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Tue, 1 Apr 2025 15:08:56 +0200 Subject: [PATCH 146/316] [Core] Remove DisplayMode from Spreadsheet --- src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp | 12 ------------ src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp index 6998e86773..3b17b64777 100644 --- a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp @@ -59,18 +59,6 @@ ViewProviderSheet::~ViewProviderSheet() } } -void ViewProviderSheet::setDisplayMode(const char* ModeName) -{ - ViewProviderDocumentObject::setDisplayMode(ModeName); -} - -std::vector ViewProviderSheet::getDisplayModes() const -{ - std::vector StrList; - StrList.emplace_back("Spreadsheet"); - return StrList; -} - QIcon ViewProviderSheet::getIcon() const { return QIcon(QLatin1String(":icons/Spreadsheet.svg")); diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h index ab301d3840..9bf1459dd1 100644 --- a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.h @@ -46,12 +46,10 @@ public: /// destructor. ~ViewProviderSheet() override; - void setDisplayMode(const char* ModeName) override; bool useNewSelectionModel() const override { return false; } - std::vector getDisplayModes() const override; bool doubleClicked() override; void setupContextMenu(QMenu* menu, QObject* receiver, const char* member) override; From 5915575f191ff624e6b778a7a9db7a4c42a0e356 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Tue, 1 Apr 2025 15:09:11 +0200 Subject: [PATCH 147/316] [Core] Remove various DisplayModes from FEM --- src/Mod/Fem/Gui/ViewProviderAnalysis.cpp | 5 ----- src/Mod/Fem/Gui/ViewProviderAnalysis.h | 2 -- src/Mod/Fem/Gui/ViewProviderSolver.cpp | 5 ----- src/Mod/Fem/Gui/ViewProviderSolver.h | 2 -- 4 files changed, 14 deletions(-) diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp index 51bbbe69ed..9094c2a4f7 100644 --- a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp @@ -147,11 +147,6 @@ std::vector ViewProviderFemAnalysis::claimChildren() const return Gui::ViewProviderDocumentObjectGroup::claimChildren(); } -std::vector ViewProviderFemAnalysis::getDisplayModes() const -{ - return {"Analysis"}; -} - void ViewProviderFemAnalysis::hide() { Gui::ViewProviderDocumentObjectGroup::hide(); diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.h b/src/Mod/Fem/Gui/ViewProviderAnalysis.h index f0a4e4eee9..e8f0b0bf2c 100644 --- a/src/Mod/Fem/Gui/ViewProviderAnalysis.h +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.h @@ -75,8 +75,6 @@ public: void setupContextMenu(QMenu*, QObject*, const char*) override; - /// list of all possible display modes - std::vector getDisplayModes() const override; /// shows solid in the tree bool isShow() const override { diff --git a/src/Mod/Fem/Gui/ViewProviderSolver.cpp b/src/Mod/Fem/Gui/ViewProviderSolver.cpp index e3d3e4f03f..5870c3fea8 100644 --- a/src/Mod/Fem/Gui/ViewProviderSolver.cpp +++ b/src/Mod/Fem/Gui/ViewProviderSolver.cpp @@ -46,11 +46,6 @@ ViewProviderSolver::ViewProviderSolver() ViewProviderSolver::~ViewProviderSolver() = default; -std::vector ViewProviderSolver::getDisplayModes() const -{ - return {"Solver"}; -} - bool ViewProviderSolver::onDelete(const std::vector&) { // warn the user if the object has unselected children diff --git a/src/Mod/Fem/Gui/ViewProviderSolver.h b/src/Mod/Fem/Gui/ViewProviderSolver.h index 0027bb2c93..8681ac20fd 100644 --- a/src/Mod/Fem/Gui/ViewProviderSolver.h +++ b/src/Mod/Fem/Gui/ViewProviderSolver.h @@ -53,8 +53,6 @@ public: { return Visibility.getValue(); } - /// A list of all possible display modes - std::vector getDisplayModes() const override; // handling when object is deleted bool onDelete(const std::vector&) override; From 17c601eaca30fe293787857a02940cedbeab2107 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Sat, 5 Apr 2025 14:25:51 +0200 Subject: [PATCH 148/316] [Core] Disable toggling visibility for objects - VarSet - Spreadsheet - FEM objects --- src/Gui/ViewProviderVarSet.cpp | 1 + src/Mod/Fem/Gui/ViewProviderAnalysis.cpp | 1 + src/Mod/Fem/Gui/ViewProviderSolver.cpp | 1 + src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp | 5 ++++- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Gui/ViewProviderVarSet.cpp b/src/Gui/ViewProviderVarSet.cpp index bd091d5256..d9179422d5 100644 --- a/src/Gui/ViewProviderVarSet.cpp +++ b/src/Gui/ViewProviderVarSet.cpp @@ -37,6 +37,7 @@ PROPERTY_SOURCE(Gui::ViewProviderVarSet, Gui::ViewProviderDocumentObject) ViewProviderVarSet::ViewProviderVarSet() { + setToggleVisibility(ToggleVisibilityMode::NoToggleVisibility); sPixmap = "VarSet"; } diff --git a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp index 9094c2a4f7..1aaff2ab6b 100644 --- a/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp +++ b/src/Mod/Fem/Gui/ViewProviderAnalysis.cpp @@ -101,6 +101,7 @@ PROPERTY_SOURCE(FemGui::ViewProviderFemAnalysis, Gui::ViewProviderDocumentObject ViewProviderFemAnalysis::ViewProviderFemAnalysis() { + setToggleVisibility(ToggleVisibilityMode::NoToggleVisibility); sPixmap = "FEM_Analysis"; } diff --git a/src/Mod/Fem/Gui/ViewProviderSolver.cpp b/src/Mod/Fem/Gui/ViewProviderSolver.cpp index 5870c3fea8..ea4bdfadc1 100644 --- a/src/Mod/Fem/Gui/ViewProviderSolver.cpp +++ b/src/Mod/Fem/Gui/ViewProviderSolver.cpp @@ -41,6 +41,7 @@ PROPERTY_SOURCE(FemGui::ViewProviderSolver, Gui::ViewProviderDocumentObject) ViewProviderSolver::ViewProviderSolver() { + setToggleVisibility(ToggleVisibilityMode::NoToggleVisibility); sPixmap = "FEM_SolverStandard"; } diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp index 3b17b64777..61eb3ca5a9 100644 --- a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp @@ -50,7 +50,10 @@ using namespace Spreadsheet; PROPERTY_SOURCE(SpreadsheetGui::ViewProviderSheet, Gui::ViewProviderDocumentObject) -ViewProviderSheet::ViewProviderSheet() = default; +ViewProviderSheet::ViewProviderSheet() +{ + setToggleVisibility(ToggleVisibilityMode::NoToggleVisibility); +} ViewProviderSheet::~ViewProviderSheet() { From 63ed3e8dff5f1b7cab1731a2f6ec11f5ed2fc63e Mon Sep 17 00:00:00 2001 From: tritao Date: Sat, 5 Apr 2025 12:59:19 +0100 Subject: [PATCH 149/316] Sketcher: Remove XML binding files. These are not needed anyore with the Python bindings conversion. --- src/Mod/Sketcher/App/CMakeLists.txt | 40 +- src/Mod/Sketcher/App/ConstraintPy.xml | 104 -- .../App/ExternalGeometryExtensionPy.xml | 37 - .../Sketcher/App/ExternalGeometryFacadePy.xml | 152 --- src/Mod/Sketcher/App/GeometryFacadePy.xml | 145 --- .../App/SketchGeometryExtensionPy.xml | 67 -- src/Mod/Sketcher/App/SketchObjectPy.xml | 933 ------------------ src/Mod/Sketcher/App/SketchObjectSF.pyi | 2 +- src/Mod/Sketcher/App/SketchObjectSFPy.xml | 17 - src/Mod/Sketcher/App/SketchPy.xml | 85 -- src/Mod/Sketcher/Gui/CMakeLists.txt | 5 +- .../ViewProviderSketchGeometryExtensionPy.xml | 27 - .../templates/templateClassPyExport.py | 1 + 13 files changed, 20 insertions(+), 1595 deletions(-) delete mode 100644 src/Mod/Sketcher/App/ConstraintPy.xml delete mode 100644 src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml delete mode 100644 src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml delete mode 100644 src/Mod/Sketcher/App/GeometryFacadePy.xml delete mode 100644 src/Mod/Sketcher/App/SketchGeometryExtensionPy.xml delete mode 100644 src/Mod/Sketcher/App/SketchObjectPy.xml delete mode 100644 src/Mod/Sketcher/App/SketchObjectSFPy.xml delete mode 100644 src/Mod/Sketcher/App/SketchPy.xml delete mode 100644 src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtensionPy.xml diff --git a/src/Mod/Sketcher/App/CMakeLists.txt b/src/Mod/Sketcher/App/CMakeLists.txt index 09ae7ff1d0..36f8dababb 100644 --- a/src/Mod/Sketcher/App/CMakeLists.txt +++ b/src/Mod/Sketcher/App/CMakeLists.txt @@ -30,22 +30,14 @@ set(Sketcher_LIBS FreeCADApp ) -generate_from_xml(SketchObjectSFPy) -generate_from_py_(SketchObjectSF) -generate_from_xml(SketchObjectPy) -generate_from_py_(SketchObject) -generate_from_xml(SketchGeometryExtensionPy) -generate_from_py_(SketchGeometryExtension) -generate_from_xml(ExternalGeometryExtensionPy) -generate_from_py_(ExternalGeometryExtension) -generate_from_xml(GeometryFacadePy) -generate_from_py_(GeometryFacade) -generate_from_xml(ExternalGeometryFacadePy) -generate_from_py_(ExternalGeometryFacade) -generate_from_xml(ConstraintPy) -generate_from_py_(Constraint) -generate_from_xml(SketchPy) -generate_from_py_(Sketch) +generate_from_py(SketchObjectSF) +generate_from_py(SketchObject) +generate_from_py(SketchGeometryExtension) +generate_from_py(ExternalGeometryExtension) +generate_from_py(GeometryFacade) +generate_from_py(ExternalGeometryFacade) +generate_from_py(Constraint) +generate_from_py(Sketch) SET(Properties_SRCS @@ -91,21 +83,21 @@ SET(Datatypes_SRCS SOURCE_GROUP("Datatypes" FILES ${Datatypes_SRCS}) SET(Python_SRCS - SketchObjectSFPy.xml + SketchObjectSF.pyi SketchObjectSFPyImp.cpp - SketchObjectPy.xml + SketchObject.pyi SketchObjectPyImp.cpp - SketchGeometryExtensionPy.xml + SketchGeometryExtension.pyi SketchGeometryExtensionPyImp.cpp - ExternalGeometryExtensionPy.xml + ExternalGeometryExtension.pyi ExternalGeometryExtensionPyImp.cpp - GeometryFacadePy.xml + GeometryFacade.pyi GeometryFacadePyImp.cpp - ExternalGeometryFacadePy.xml + ExternalGeometryFacade.pyi ExternalGeometryFacadePyImp.cpp ConstraintPyImp.cpp - ConstraintPy.xml - SketchPy.xml + Constraint.pyi + Sketch.pyi SketchPyImp.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) diff --git a/src/Mod/Sketcher/App/ConstraintPy.xml b/src/Mod/Sketcher/App/ConstraintPy.xml deleted file mode 100644 index 34b1c75ec9..0000000000 --- a/src/Mod/Sketcher/App/ConstraintPy.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - With this object you can handle sketches - - - - Get the constraint type - - - - - - First geometry index the Constraint refers to - - - - - - Position of first geometry index the Constraint refers to - - - - - - Second geometry index the Constraint refers to - - - - - - Position of second geometry index the Constraint refers to - - - - - - Third geometry index the Constraint refers to - - - - - - Position of third geometry index the Constraint refers to - - - - - - Value of the Constraint - - - - - - Name of the constraint - - - - - - Driving Constraint - - - - - - Constraint in virtual space - - - - - - Returns whether the constraint active (enforced) or not - - - - - - Label distance - - - - - - Label position - - - - - diff --git a/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml b/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml deleted file mode 100644 index eb001465ff..0000000000 --- a/src/Mod/Sketcher/App/ExternalGeometryExtensionPy.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Describes a ExternalGeometryExtension - - - - Returns a boolean indicating whether the given bit is set. - - - - - Sets the given bit to true/false. - - - - - -Returns the reference string of this external geometry. - - - - - - diff --git a/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml b/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml deleted file mode 100644 index e9592ebdfd..0000000000 --- a/src/Mod/Sketcher/App/ExternalGeometryFacadePy.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - Describes a GeometryFacade - - - - Returns a boolean indicating whether the given bit is set. - - - - - Sets the given bit to true/false. - - - - - -Returns the reference string of this external geometry. - - - - - - - -Sets/returns the Internal Alignment Type of the Geometry. - - - - - - - Sets/returns this geometry as a construction one, which will not be part of a later built shape. - - - - - - -Returns the Id of the geometry Layer in which the geometry is located. - - - - - - - - Sets/returns the Internal Alignment Type of the Geometry. - - - - - - - -Sets/returns whether the geometry is blocked or not. - - - - - - - Performs the symmetrical transformation of this geometric object - - - - - Rotates this geometric object at angle Ang (in radians) about axis - - - - - Applies a scaling transformation on this geometric object with a center and scaling factor - - - - - Applies a transformation to this geometric object - - - - - Translates this geometric object - - - - - Returns a boolean indicating whether a geometry extension of the type indicated as a string exists. - - - - - Returns a boolean indicating whether a geometry extension with the name indicated as a string exists. - - - - - Gets the first geometry extension of the type indicated by the string. - - - - - Gets the first geometry extension of the name indicated by the string. - - - - - Sets a geometry extension of the indicated type. - - - - - Deletes all extensions of the indicated type. - - - - - Deletes all extensions of the indicated name. - - - - - Returns a list with information about the geometry extensions. - - - - - Gives the tag of the geometry as string. - - - - - - Returns the underlying geometry object. - - - - - diff --git a/src/Mod/Sketcher/App/GeometryFacadePy.xml b/src/Mod/Sketcher/App/GeometryFacadePy.xml deleted file mode 100644 index 83ce9bf4cd..0000000000 --- a/src/Mod/Sketcher/App/GeometryFacadePy.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - Describes a GeometryFacade - - - - Returns a boolean indicating whether the given bit is set. - - - - - Sets the given bit to true/false. - - - - - -Sets/returns the Id of the SketchGeometryExtension. - - - - - - - -Sets/returns the Internal Alignment Type of the Geometry. - - - - - - - -Sets/returns whether the geometry is blocked or not. - - - - - - - Sets/returns this geometry as a construction one, which will not be part of a later built shape. - - - - - - -Returns the Id of the geometry Layer in which the geometry is located. - - - - - - - Performs the symmetrical transformation of this geometric object - - - - - Rotates this geometric object at angle Ang (in radians) about axis - - - - - Applies a scaling transformation on this geometric object with a center and scaling factor - - - - - Applies a transformation to this geometric object - - - - - Translates this geometric object - - - - - Returns a boolean indicating whether a geometry extension of the type indicated as a string exists. - - - - - Returns a boolean indicating whether a geometry extension with the name indicated as a string exists. - - - - - Gets the first geometry extension of the type indicated by the string. - - - - - Gets the first geometry extension of the name indicated by the string. - - - - - Sets a geometry extension of the indicated type. - - - - - Deletes all extensions of the indicated type. - - - - - Deletes all extensions of the indicated name. - - - - - Returns a list with information about the geometry extensions. - - - - - Gives the tag of the geometry as string. - - - - - - Returns the underlying geometry object. - - - - - diff --git a/src/Mod/Sketcher/App/SketchGeometryExtensionPy.xml b/src/Mod/Sketcher/App/SketchGeometryExtensionPy.xml deleted file mode 100644 index 4c946d1a76..0000000000 --- a/src/Mod/Sketcher/App/SketchGeometryExtensionPy.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - Describes a SketchGeometryExtension - - - - Returns a boolean indicating whether the given bit is set. - - - - - Sets the given bit to true/false. - - - - - - Returns the Id of the SketchGeometryExtension. - - - - - - - - Returns the Id of the SketchGeometryExtension. - - - - - - - - Sets/returns whether the geometry is blocked or not. - - - - - - - Sets/returns this geometry as a construction one, which will not be part of a later built shape. - - - - - - - Returns the Id of the geometry Layer in which the geometry is located. - - - - - - diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml deleted file mode 100644 index 70701700c6..0000000000 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ /dev/null @@ -1,933 +0,0 @@ - - - - - - Represents a sketch object - - - - -Solve the sketch and update the geometry. - -solve() - - Returns: - 0 in case of success, otherwise the following codes in this order of - priority: - -4 if over-constrained, - -3 if conflicting constraints, - -5 if malformed constraints - -1 if solver error, - -2 if redundant constraints. - - - - - - -Add geometric objects to the sketch. - -addGeometry(geo:Geometry, isConstruction=False) -> int - Add a single geometric object to the sketch. - - Args: - geo: The geometry to add. e.g. a Part.LineSegement - isConstruction: Whether the added geometry is a "construction geometry". - Defaults to `False`, i.e. by omitting, a regular geometry is added. - - Returns: - The zero-based index of the newly added geometry. - -addGeometry(geo:List(Geometry), isConstruction=False) -> Tuple(int) - Add many geometric objects to the sketch. - - Args: - geo: The geometry to add. - isConstruction: see above. - - Returns: - A tuple of zero-based indices of all newly added geometry. - - - - - - -Delete a geometric object from the sketch. - -delGeometry(geoId:int) - - Args: - geoId: The zero-based index of the geometry to delete. - Any internal alignment geometry thereof will be deleted, too. - - - - - - -Delete a list of geometric objects from the sketch. - -delGeometries(geoIds:List(int)) - - Args: - geoId: A list of zero-based indices of the geometry to delete. - Any internal alignment geometry thereof will be deleted, too. - - - - - - -Delete all the geometry objects from the sketch, except external geometry. - -deleteAllGeometry() - - - - - - -Detect degenerated geometries. A curve geometry is considered degenerated -if the parameter range is less than the tolerance. - -detectDegeneratedGeometries(tolerance:float) - - Args: - tolerance: The tolerance to check the parameter range of a curve. - - Returns: - The number of degenerated geometries. - - - - - - -Remove degenerated geometries. A curve geometry is considered degenerated -if the parameter range is less than the tolerance. - -removeDegeneratedGeometries(tolerance:float) - - Args: - tolerance: The tolerance to check the parameter range of a curve. - - Returns: - The number of degenerated geometries. - - - - - - -Delete all the constraints from the sketch. - -deleteAllConstraints() - - - - - - -Toggles a geometry between regular and construction. - -toggleConstruction(geoId:int) - - Args: - geoId: The zero-based index of the geometry to toggle. - - - - - - -Set construction mode of a geometry. - -setConstruction(geoId:int, state:bool) - - Args: - geoId: The zero-based index of the geometry to configure. - state: `True` configures the geometry to "construction geometry", - `False` configures it to regular geometry. - - - - - - -Determine whether the given geometry is a "construction geometry". - -getConstruction(geoId:int) - - Args: - geoId: The zero-based index of the geometry to query. - - Returns: - `True` if the geometry is "construction geometry" and - `False` if it s a regular geometry. - - - - - - -Add constraints to the sketch. - -addConstraint(constraint:Constraint) -> int - Add a single constraint to the sketch and solves it. - - Returns: - The zero-based index of the newly added constraint. - -addConstraint(constraints:List(Constraint)) -> Tuple(int) - Add many constraints to the sketch without solving. - - Returns: - A tuple of zero-based indices of all newly added constraints. - - - - - - -Delete a constraint from the sketch. - -delConstraint(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to delete. - - - - - - -Rename a constraint in the sketch. - -renameConstraint(constraintIndex:int, name:str) - - Args: - constraintIndex: The zero-based index of the constraint to rename. - name: The new name for the constraint. - An empty string makes the constraint "unnamed" again. - - - - - - -Get the index of a constraint by name. - -getIndexByName(name:str) - - Args: - name: The name for the constraint to look up. - If there is no such constraint an exception is raised. - - - - - - -Copy another sketch's geometry and constraints into this sketch. - -carbonCopy(objName:str, asConstruction=True) - - Args: - ObjName: The name of the sketch object to copy from. - asConstruction: Whether to copy the geometry as "construction geometry". - - - - - - -Add a link to an external geometry. - -addExternal(objName:str, subName:str, defining:bool=False, intersection:bool=False) - - Args: - objName: The name of the document object to reference. - subName: The name of the sub-element of the object's shape to link as - "external geometry". - defining: Should the external edges be defining or construction? - intersection: Should the external edges be projections or intersections? - - - - - - -Delete an external geometry link from the sketch. - -delExternal(extGeoId:int) - - Args: - extGeoId: The zero-based index of the external geometry to remove. - - - - - - -Delete coincident constraints associated with a sketch point. - -delConstraintOnPoint(vertexId:int) - - Args: - vertexId: A zero-based index of the shape's vertices. - -delConstraintOnPoint(geoId:int, pointPos:int) - - Args: - geoId: The zero-based index of the geometry that contains the point. - pointPos: Enum denoting which point on the geometry is meant: - 1: the start of a line or bounded curve. - 2: the end of a line or bounded curve. - 3: the center of a circle or ellipse. - - - - - - Deletes all constraints referencing an external geometry. - - - - - -Set the value of a datum constraint (e.g. Distance or Angle) - -setDatum(constraint, value) - - Args: - constraint (int or str): The index or name of the constraint to set. - value (float or Quantity): The value to set for the constraint. When - using floats, values for linear dimensions are interpreted as - millimeter, angular ones as radians. - - - - - - -Get the value of a datum constraint (e.g. Distance or Angle) - -getDatum(constraint) -> Quantity - - Args: - constraint (int or str): The index or name of the constraint to query. - - Returns: - The value of the constraint. - - - - - - -Set the Driving status of a datum constraint. - -setDriving(constraintIndex:int, state:bool) - - Args: - constraintIndex: The zero-based index of the constraint to configure. - state: `True` sets the constraint to driving, - `False` configures it as non-driving, i.e. reference. - - - - - - -Set the Driving status of all datum constraints. - -setDatumsDriving(state:bool) - - Args: - state: `True` set all datum constraints to driving, - `False` configures them as non-driving, i.e. reference. - - - - - - -Moves all datum constraints to the end of the constraint list. - -moveDatumsToEnd() - - Warning: This method reorders the constraint indices. Previously held - numeric references to constraints may reference different constraints - after this operation. - - - - - - -Get the Driving status of a datum constraint. - -getDriving(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to query. - - Returns: - `True` if the constraint is driving, - `False` if it is non-driving, i.e. reference. - - - - - - -Toggle the Driving status of a datum constraint. - -toggleDriving(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to toggle. - - - - - - Set the VirtualSpace status of a constraint - - - - - Get the VirtualSpace status of a constraint - - - - - Toggle the VirtualSpace status of a constraint - - - - - -Activates or deactivates a constraint (enforce it or not). - -setActive(constraintIndex:int, state:bool) - - Args: - constraintIndex: The zero-based index of the constraint to configure. - state: `True` sets the constraint to active i.e. enforced, - `False` configures it as inactive, i.e. not enforced. - - - - - - -Get whether a constraint is active, i.e. enforced, or not. - -getActive(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to query. - - Returns: - `True` if the constraint is active, i.e. enforced, - `False` if it is inactive, i.e. not enforced. - - - - - - -Toggle the constraint between active (enforced) and inactive. - -toggleActive(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to toggle. - - - - - - -Get label position of the constraint. - -getLabelPosition(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to query. - - Returns: - float with the current value. - - - - - - -Set label position of the constraint. - -setLabelPosition(constraintIndex:int, value:float) - - Args: - constraintIndex: The zero-based index of the constraint to query. - value: Value of the label position. - - - - - - -Get label distance of the constraint. - -getLabelDistance(constraintIndex:int) - - Args: - constraintIndex: The zero-based index of the constraint to query. - - Returns: - float with the current value. - - - - - - -Set label distance of the constraint. - -setLabelDistance(constraintIndex:int, value:float) - - Args: - constraintIndex: The zero-based index of the constraint to query. - value: Value of the label position. - - - - - - -Move a given point (or curve) to another location. - -moveGeometry(GeoIndex,PointPos,Vector,[relative]) - -It moves the specified point (or curve) to the given location by adding some -temporary weak constraints and solving the sketch. -This method is mostly used to allow the user to drag some portions of the sketch -in real time by e.g. the mouse and it works only for underconstrained portions of -the sketch. -The argument 'relative', if present, states if the new location is given -relatively to the current one. - - - - - - -Move given points and curves to another location. - -moveGeometries(Geos,Vector,[relative]) - -It moves the specified points and curves to the given location by adding some -temporary weak constraints and solving the sketch. -This method is mostly used to allow the user to drag some portions of the sketch -in real time by e.g. the mouse and it works only for underconstrained portions of -the sketch. -The argument 'relative', if present, states if the new location is given -relatively to the current one. For group dragging this is enforced. -Geos is a vector of pairs of geoId and posId. - - - - - - -Retrieve the vector of a point in the sketch. - -getPoint(GeoIndex,PointPos) - - - - - - -Retrieve the GeoId and PosId of a point in the sketch. - -(geoId, posId) = getGeoVertexIndex(index) - - - - - - -Return an axis based on the corresponding construction line - - - - - - Create a fillet between two edges or at a point - - - - - Trim a curve with a given id at a given reference point - - - - - Extend a curve to new start and end positions - - - - - Split a curve with a given id at a given reference point - - - - - Join two curves at the given end points - - - - - Add symmetric geometric objects to the sketch with respect to a reference point or line - - - - - Add a copy of geometric objects to the sketch displaced by a vector3d - - - - - Move the geometric objects in the sketch displaced by a vector3d - - - - - Add an array of size cols by rows where each element is a copy of the selected geometric objects displaced by a vector3d in the cols direction and by a vector perpendicular to it in the rows direction - - - - - Modifies constraints so that the shape is not forced to be aligned with axes. - - - - - Deprecated -- use exposeInternalGeometry - - - - - Deprecated -- use deleteUnusedInternalGeometry - - - - - Exposes all internal geometry of an object supporting internal geometry - - - - - Deletes all unused (not further constrained) internal geometry - - - - - Approximates the given geometry with a B-spline - - - - - Increases the given B-spline Degree by a number of degrees - - - - - Decreases the given B-spline Degree by a number of degrees by approximating this curve - - - - - Increases or reduces the given BSpline knot multiplicity - - - - - Inserts a knot into the BSpline at the given param with given multiplicity. If the knot already exists, this increases the knot multiplicity by the given multiplicity. - - - - - -calculateAngleViaPoint(GeoId1, GeoId2, px, py) - calculates angle between -curves identified by GeoId1 and GeoId2 at point (x,y). The point must be -on intersection of the curves, otherwise the result may be useless (except -line-to-line, where (0,0) is OK). Returned value is in radians. - - - - - - -isPointOnCurve(GeoIdCurve, float x, float y) -> bool - tests if the point (x,y) -geometrically lies on a curve (e.g. ellipse). It treats lines as infinite, -arcs as full circles/ellipses/etc. - - - - - - -calculateConstraintError(index) - calculates the error function of the -constraint identified by its index and returns the signed error value. -The error value roughly corresponds to by how much the constraint is -violated. If the constraint internally has more than one error function, -the returned value is RMS of all errors (sign is lost in this case). - - - - - - -changeConstraintsLocking(bLock) - locks or unlocks all tangent and -perpendicular constraints. (Constraint locking prevents it from -flipping to another valid configuration, when e.g. external geometry -is updated from outside.) The sketch solve is not triggered by the -function, but the SketchObject is touched (a recompute will be -necessary). The geometry should not be affected by the function. - -The bLock argument specifies, what to do. If true, all constraints -are unlocked and locked again. If false, all tangent and perp. -constraints are unlocked. - - - - - - -getGeometryWithDependentParameters - returns a list of geoid posid pairs -with all the geometry element edges and vertices which the solver regards -as being dependent on other parameters. - - - - - - -Automatic sketch constraining algorithm. - - - - - - -Detects missing Point On Point Constraints. The detect step just identifies possible missing constraints. -The result may be retrieved or applied using the corresponding Get / Make methods. - - - - - - -Analyses the already detected missing Point On Point Constraints to detect endpoint tangency/perpendicular. -The result may be retrieved or applied using the corresponding Get / Make methods. - - - - - - -Detects missing Horizontal/Vertical Constraints. The detect step just identifies possible missing constraints. -The result may be retrieved or applied using the corresponding Get / Make methods. - - - - - - -Detects missing Equality Constraints. The detect step just identifies possible missing constraints. -The result may be retrieved or applied using the corresponding Get / Make methods. - - - - - - -Applies the detected / set Point On Point coincident constraints. If the argument is True, then solving and redundant removal is done after each individual addition. - - - - - - -Applies the detected / set Vertical/Horizontal constraints. If the argument is True, then solving and redundant removal is done after each individual addition. - - - - - - -Applies the detected / set Equality constraints. If the argument is True, then solving and redundant removal is done after each individual addition. - - - - - - -Check for constraints with invalid indexes. Returns True if invalid constraints are found, False otherwise. - - - - - - -Removes constraints with invalid indexes. - - - - - - -Removes constraints currently detected as redundant by the solver. If the argument is True, then the geometry is updated after solving. - - - - - - -Prints the commands that should be executed to recreate the Geometry and Constraints of the present sketch (excluding any External Geometry). - - - - - - -Returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected endpoint constraints. - - - - - - - -Returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected vertical/horizontal constraints. - - - - - - - -Returns a list of (First FirstPos Second SecondPos) tuples with all the detected line segment equality constraints. - - - - - - - -Returns a list of (First FirstPos Second SecondPos) tuples with all the detected radius constraints. - - - - - - - -Returns a list of vertices positions. - - - - - - - Number of Constraints in this sketch - - - - - - Number of geometric objects in this sketch - - - - - - - Return the number of construction lines in the sketch which can be used as axes - - - - - - - - Return a list of GeometryFacade objects corresponding to the PropertyGeometryList - - - - - - - - Return the DoFs of the current solved sketch - - - - - - - - Return a list of integers indicating the constraints detected as conflicting - - - - - - - - Return a list of integers indicating the constraints detected as redundant - - - - - - - - Return a list of integers indicating the constraints detected as partially redundant - - - - - - - - Return a list of integers indicating the constraints detected as malformed - - - - - - - Sets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId - - - - - Gets the GeometryId of the SketchGeometryExtension of the geometry with the provided GeoId - - - - diff --git a/src/Mod/Sketcher/App/SketchObjectSF.pyi b/src/Mod/Sketcher/App/SketchObjectSF.pyi index 7766381e87..5af77c2a15 100644 --- a/src/Mod/Sketcher/App/SketchObjectSF.pyi +++ b/src/Mod/Sketcher/App/SketchObjectSF.pyi @@ -1,5 +1,5 @@ from Base.Metadata import export -from Part.Part2DObject import Part2DObject +from Part.App.Part2DObject import Part2DObject @export( Include="Mod/Sketcher/App/SketchObjectSF.h", diff --git a/src/Mod/Sketcher/App/SketchObjectSFPy.xml b/src/Mod/Sketcher/App/SketchObjectSFPy.xml deleted file mode 100644 index db7f521fa3..0000000000 --- a/src/Mod/Sketcher/App/SketchObjectSFPy.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - With this objects you can handle sketches - - - diff --git a/src/Mod/Sketcher/App/SketchPy.xml b/src/Mod/Sketcher/App/SketchPy.xml deleted file mode 100644 index 6fd4a9f2a2..0000000000 --- a/src/Mod/Sketcher/App/SketchPy.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - With this objects you can handle constraint sketches - - - - Solve the actual set of geometry and constraints - - - - - Add a geometric object to the sketch - - - - - Add an constraint object to the sketch - - - - - Clear the sketch - - - - - -moveGeometry(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve) -to another location. -It moves the specified point (or curve) to the given location by adding some -temporary weak constraints and solve the sketch. -This method is mostly used to allow the user to drag some portions of the sketch -in real time by e.g. the mouse and it works only for underconstrained portions of -the sketch. -The argument 'relative', if present, states if the new location is given -relatively to the current one. - - - - - - 0: exactly constraint, -1 under-constraint, 1 over-constraint - - - - - - Tuple of conflicting constraints - - - - - - Tuple of redundant constraints - - - - - - Tuple of all geometric elements in this sketch - - - - - - Resulting shape from the sketch geometry - - - - - - diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index 38ab21d39f..2128149650 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -17,8 +17,7 @@ qt_find_and_add_translation(QM_SRCS "Resources/translations/*_*.ts" qt_create_resource_file(${Sketcher_TR_QRC} ${QM_SRCS}) qt_add_resources(SketcherGui_SRCS Resources/Sketcher.qrc ${Sketcher_TR_QRC}) -generate_from_xml(ViewProviderSketchGeometryExtensionPy) -generate_from_py_(ViewProviderSketchGeometryExtension) +generate_from_py(ViewProviderSketchGeometryExtension) set(SketcherGui_UIC_SRCS TaskSketcherConstraints.ui @@ -166,7 +165,7 @@ SET(SketcherGui_SRCS ) SET(Python_SRCS - ViewProviderSketchGeometryExtensionPy.xml + ViewProviderSketchGeometryExtension.pyi ViewProviderSketchGeometryExtensionPyImp.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtensionPy.xml b/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtensionPy.xml deleted file mode 100644 index eff215edac..0000000000 --- a/src/Mod/Sketcher/Gui/ViewProviderSketchGeometryExtensionPy.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - Describes a ViewProviderSketchGeometryExtension - - - - - Sets/returns this geometry's Visual Layer Id. - - - - - - diff --git a/src/Tools/bindings/templates/templateClassPyExport.py b/src/Tools/bindings/templates/templateClassPyExport.py index 9dc65a8e42..a094cef5de 100644 --- a/src/Tools/bindings/templates/templateClassPyExport.py +++ b/src/Tools/bindings/templates/templateClassPyExport.py @@ -44,6 +44,7 @@ class TemplateClassPyExport(template.ModelTemplate): "Part", "PartDesign", "Material", + "Sketcher", ]: root, ext = os.path.splitext(path) return f"{root}_{ext}" From 637c21c18f3446fc93f18f4c5b1859dea2814163 Mon Sep 17 00:00:00 2001 From: marcuspollio Date: Sat, 5 Apr 2025 17:55:51 +0200 Subject: [PATCH 150/316] BIM: use FreeCAD Dev Handbook license block --- src/Mod/BIM/Arch.py | 24 ++++++++--------- src/Mod/BIM/ArchAxis.py | 24 ++++++++--------- src/Mod/BIM/ArchAxisSystem.py | 24 ++++++++--------- src/Mod/BIM/ArchBuilding.py | 24 ++++++++--------- src/Mod/BIM/ArchBuildingPart.py | 24 ++++++++--------- src/Mod/BIM/ArchCommands.py | 24 ++++++++--------- src/Mod/BIM/ArchComponent.py | 24 ++++++++--------- src/Mod/BIM/ArchCurtainWall.py | 24 ++++++++--------- src/Mod/BIM/ArchCutPlane.py | 24 ++++++++--------- src/Mod/BIM/ArchEquipment.py | 24 ++++++++--------- src/Mod/BIM/ArchFence.py | 24 ++++++++--------- src/Mod/BIM/ArchFloor.py | 24 ++++++++--------- src/Mod/BIM/ArchFrame.py | 24 ++++++++--------- src/Mod/BIM/ArchGrid.py | 24 ++++++++--------- src/Mod/BIM/ArchIFC.py | 24 ++++++++--------- src/Mod/BIM/ArchIFCSchema.py | 24 ++++++++--------- src/Mod/BIM/ArchIFCView.py | 24 ++++++++--------- src/Mod/BIM/ArchMaterial.py | 24 ++++++++--------- src/Mod/BIM/ArchNesting.py | 24 ++++++++--------- src/Mod/BIM/ArchPanel.py | 24 ++++++++--------- src/Mod/BIM/ArchPipe.py | 24 ++++++++--------- src/Mod/BIM/ArchPrecast.py | 24 ++++++++--------- src/Mod/BIM/ArchProfile.py | 24 ++++++++--------- src/Mod/BIM/ArchProject.py | 24 ++++++++--------- src/Mod/BIM/ArchRebar.py | 24 ++++++++--------- src/Mod/BIM/ArchReference.py | 24 ++++++++--------- src/Mod/BIM/ArchRoof.py | 24 ++++++++--------- src/Mod/BIM/ArchSchedule.py | 24 ++++++++--------- src/Mod/BIM/ArchSectionPlane.py | 24 ++++++++--------- src/Mod/BIM/ArchSite.py | 24 ++++++++--------- src/Mod/BIM/ArchSketchObject.py | 24 ++++++++--------- src/Mod/BIM/ArchSpace.py | 24 ++++++++--------- src/Mod/BIM/ArchStairs.py | 24 ++++++++--------- src/Mod/BIM/ArchStructure.py | 25 +++++++++--------- src/Mod/BIM/ArchTruss.py | 24 ++++++++--------- src/Mod/BIM/ArchVRM.py | 24 ++++++++--------- src/Mod/BIM/ArchWall.py | 24 ++++++++--------- src/Mod/BIM/ArchWindow.py | 24 ++++++++--------- src/Mod/BIM/ArchWindowPresets.py | 24 ++++++++--------- src/Mod/BIM/BimStatus.py | 24 ++++++++--------- src/Mod/BIM/Init.py | 24 ++++++++--------- src/Mod/BIM/InitGui.py | 24 ++++++++--------- src/Mod/BIM/OfflineRenderingUtils.py | 24 ++++++++--------- src/Mod/BIM/TestArch.py | 26 +++++++++---------- src/Mod/BIM/TestArchGui.py | 26 +++++++++---------- src/Mod/BIM/bimcommands/BimArchUtils.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimAxis.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimBackground.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimBeam.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimBox.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimBuilder.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimBuildingPart.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimClassification.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimClone.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimColumn.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimCommon.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimCompound.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimConvert.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimCopy.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimCurtainwall.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimCut.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimCutPlane.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimDiff.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimDimensions.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimDoor.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimDrawingView.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimEmptyTrash.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimEquipment.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimExamples.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimExtrude.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimFence.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimFrame.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimFuse.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimGlue.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimHelp.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimIfcElements.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimIfcExplorer.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimIfcProperties.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimIfcQuantities.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimImagePlane.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimLayers.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimLeader.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimLibrary.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimMaterial.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimMoveView.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimNudge.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimOffset.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimPanel.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimPipe.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimPreflight.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimProfile.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimProject.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimProjectManager.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimRebar.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimReextrude.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimReference.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimReorder.py | 24 ++++++++--------- .../BIM/bimcommands/BimResetCloneColors.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimRewire.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimRoof.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSchedule.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSectionPlane.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSetup.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimShape2DView.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSimpleCopy.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSite.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSketch.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSlab.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimSpace.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimStairs.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimTDPage.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimTDView.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimText.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimTogglePanels.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimTrash.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimTruss.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimTutorial.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimUnclone.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimUngroup.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimViews.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimWPCommands.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimWall.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimWelcome.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimWindow.py | 24 ++++++++--------- src/Mod/BIM/bimcommands/BimWindows.py | 24 ++++++++--------- src/Mod/BIM/bimtests/TestArchRoof.py | 26 +++++++++---------- src/Mod/BIM/bimtests/TestArchSpace.py | 26 +++++++++---------- src/Mod/BIM/bimtests/TestArchWall.py | 26 +++++++++---------- src/Mod/BIM/ifc_objects.py | 24 ++++++++--------- src/Mod/BIM/ifc_viewproviders.py | 24 ++++++++--------- src/Mod/BIM/importers/exportIFC.py | 25 +++++++++--------- src/Mod/BIM/importers/exportIFCHelper.py | 24 ++++++++--------- .../BIM/importers/exportIFCStructuralTools.py | 24 ++++++++--------- src/Mod/BIM/importers/import3DS.py | 24 ++++++++--------- src/Mod/BIM/importers/importDAE.py | 24 ++++++++--------- src/Mod/BIM/importers/importGBXML.py | 24 ++++++++--------- src/Mod/BIM/importers/importIFC.py | 25 +++++++++--------- src/Mod/BIM/importers/importIFCHelper.py | 25 +++++++++--------- src/Mod/BIM/importers/importIFClegacy.py | 24 ++++++++--------- src/Mod/BIM/importers/importIFCmulticore.py | 25 +++++++++--------- src/Mod/BIM/importers/importJSON.py | 24 ++++++++--------- src/Mod/BIM/importers/importOBJ.py | 24 ++++++++--------- src/Mod/BIM/importers/importSH3D.py | 24 ++++++++--------- src/Mod/BIM/importers/importSH3DHelper.py | 26 +++++++++---------- src/Mod/BIM/importers/importSHP.py | 24 ++++++++--------- src/Mod/BIM/importers/importWebGL.py | 26 +++++++++---------- src/Mod/BIM/nativeifc/ifc_classification.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_commands.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_diff.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_export.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_generator.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_geometry.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_import.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_layers.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_materials.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_objects.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_observer.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_openshell.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_performance_test.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_psets.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_selftest.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_status.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_tools.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_tree.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_types.py | 24 ++++++++--------- src/Mod/BIM/nativeifc/ifc_viewproviders.py | 24 ++++++++--------- src/Mod/BIM/utils/buildPsets.py | 24 ++++++++--------- src/Mod/BIM/utils/ifctree.py | 24 ++++++++--------- 168 files changed, 1860 insertions(+), 2191 deletions(-) diff --git a/src/Mod/BIM/Arch.py b/src/Mod/BIM/Arch.py index c08d8b3166..6b57c83ec1 100644 --- a/src/Mod/BIM/Arch.py +++ b/src/Mod/BIM/Arch.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchAxis.py b/src/Mod/BIM/ArchAxis.py index a409e818fd..6d8f1b52d7 100644 --- a/src/Mod/BIM/ArchAxis.py +++ b/src/Mod/BIM/ArchAxis.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchAxisSystem.py b/src/Mod/BIM/ArchAxisSystem.py index 3e207408b9..7f9fa7e836 100644 --- a/src/Mod/BIM/ArchAxisSystem.py +++ b/src/Mod/BIM/ArchAxisSystem.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchBuilding.py b/src/Mod/BIM/ArchBuilding.py index 2f1f80a7c3..c30e78d663 100644 --- a/src/Mod/BIM/ArchBuilding.py +++ b/src/Mod/BIM/ArchBuilding.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchBuildingPart.py b/src/Mod/BIM/ArchBuildingPart.py index b1a96f906b..72921bcbd2 100644 --- a/src/Mod/BIM/ArchBuildingPart.py +++ b/src/Mod/BIM/ArchBuildingPart.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchCommands.py b/src/Mod/BIM/ArchCommands.py index 2a3e8c18dc..23386f1bde 100644 --- a/src/Mod/BIM/ArchCommands.py +++ b/src/Mod/BIM/ArchCommands.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index a1a2a5c414..82bb939003 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchCurtainWall.py b/src/Mod/BIM/ArchCurtainWall.py index 31c08aed04..a5f291f266 100644 --- a/src/Mod/BIM/ArchCurtainWall.py +++ b/src/Mod/BIM/ArchCurtainWall.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchCutPlane.py b/src/Mod/BIM/ArchCutPlane.py index 79e749749f..cab22c7bd4 100644 --- a/src/Mod/BIM/ArchCutPlane.py +++ b/src/Mod/BIM/ArchCutPlane.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # ***************************************************************************** diff --git a/src/Mod/BIM/ArchEquipment.py b/src/Mod/BIM/ArchEquipment.py index a8550a06cb..a74aafc647 100644 --- a/src/Mod/BIM/ArchEquipment.py +++ b/src/Mod/BIM/ArchEquipment.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchFence.py b/src/Mod/BIM/ArchFence.py index d82ebe40c1..cdc92842a6 100644 --- a/src/Mod/BIM/ArchFence.py +++ b/src/Mod/BIM/ArchFence.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # ***************************************************************************** diff --git a/src/Mod/BIM/ArchFloor.py b/src/Mod/BIM/ArchFloor.py index 11adc470b1..dc34cb1f1e 100644 --- a/src/Mod/BIM/ArchFloor.py +++ b/src/Mod/BIM/ArchFloor.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchFrame.py b/src/Mod/BIM/ArchFrame.py index f9ae46c74d..5330dcaf31 100644 --- a/src/Mod/BIM/ArchFrame.py +++ b/src/Mod/BIM/ArchFrame.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchGrid.py b/src/Mod/BIM/ArchGrid.py index 261e559364..9590186087 100644 --- a/src/Mod/BIM/ArchGrid.py +++ b/src/Mod/BIM/ArchGrid.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchIFC.py b/src/Mod/BIM/ArchIFC.py index 8424b84464..e2b338838d 100644 --- a/src/Mod/BIM/ArchIFC.py +++ b/src/Mod/BIM/ArchIFC.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchIFCSchema.py b/src/Mod/BIM/ArchIFCSchema.py index dc560b6c52..7cbc01c118 100644 --- a/src/Mod/BIM/ArchIFCSchema.py +++ b/src/Mod/BIM/ArchIFCSchema.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchIFCView.py b/src/Mod/BIM/ArchIFCView.py index 1dd3064509..f399f9ec6a 100644 --- a/src/Mod/BIM/ArchIFCView.py +++ b/src/Mod/BIM/ArchIFCView.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchMaterial.py b/src/Mod/BIM/ArchMaterial.py index 6b1b645657..575be2eaf4 100644 --- a/src/Mod/BIM/ArchMaterial.py +++ b/src/Mod/BIM/ArchMaterial.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchNesting.py b/src/Mod/BIM/ArchNesting.py index bca741c272..7f3ed45b10 100644 --- a/src/Mod/BIM/ArchNesting.py +++ b/src/Mod/BIM/ArchNesting.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchPanel.py b/src/Mod/BIM/ArchPanel.py index 4c91a6134b..d24f152303 100644 --- a/src/Mod/BIM/ArchPanel.py +++ b/src/Mod/BIM/ArchPanel.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchPipe.py b/src/Mod/BIM/ArchPipe.py index 4038306237..211d1964ac 100644 --- a/src/Mod/BIM/ArchPipe.py +++ b/src/Mod/BIM/ArchPipe.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchPrecast.py b/src/Mod/BIM/ArchPrecast.py index 3cd54a411e..a4fa55b174 100644 --- a/src/Mod/BIM/ArchPrecast.py +++ b/src/Mod/BIM/ArchPrecast.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchProfile.py b/src/Mod/BIM/ArchProfile.py index 8112242cb7..8040f3c4a6 100644 --- a/src/Mod/BIM/ArchProfile.py +++ b/src/Mod/BIM/ArchProfile.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchProject.py b/src/Mod/BIM/ArchProject.py index 7ed43da9ac..1e4fd3e909 100644 --- a/src/Mod/BIM/ArchProject.py +++ b/src/Mod/BIM/ArchProject.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchRebar.py b/src/Mod/BIM/ArchRebar.py index 2d3079daa0..d76fac3a40 100644 --- a/src/Mod/BIM/ArchRebar.py +++ b/src/Mod/BIM/ArchRebar.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchReference.py b/src/Mod/BIM/ArchReference.py index ee73b69c67..7e552f5d19 100644 --- a/src/Mod/BIM/ArchReference.py +++ b/src/Mod/BIM/ArchReference.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchRoof.py b/src/Mod/BIM/ArchRoof.py index c8abc7ce89..5c5ad9499c 100644 --- a/src/Mod/BIM/ArchRoof.py +++ b/src/Mod/BIM/ArchRoof.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchSchedule.py b/src/Mod/BIM/ArchSchedule.py index d82be2db36..56fc009e8a 100644 --- a/src/Mod/BIM/ArchSchedule.py +++ b/src/Mod/BIM/ArchSchedule.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchSectionPlane.py b/src/Mod/BIM/ArchSectionPlane.py index 429dc698c0..babeff2cd7 100644 --- a/src/Mod/BIM/ArchSectionPlane.py +++ b/src/Mod/BIM/ArchSectionPlane.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchSite.py b/src/Mod/BIM/ArchSite.py index 477e0865ae..4d5cf310cc 100644 --- a/src/Mod/BIM/ArchSite.py +++ b/src/Mod/BIM/ArchSite.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchSketchObject.py b/src/Mod/BIM/ArchSketchObject.py index a13b0d9243..71f2c27fed 100644 --- a/src/Mod/BIM/ArchSketchObject.py +++ b/src/Mod/BIM/ArchSketchObject.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchSpace.py b/src/Mod/BIM/ArchSpace.py index 647f8b2bd6..427557c19f 100644 --- a/src/Mod/BIM/ArchSpace.py +++ b/src/Mod/BIM/ArchSpace.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchStairs.py b/src/Mod/BIM/ArchStairs.py index 325e4b92d8..5512bca77a 100644 --- a/src/Mod/BIM/ArchStairs.py +++ b/src/Mod/BIM/ArchStairs.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchStructure.py b/src/Mod/BIM/ArchStructure.py index 3830b53410..ffcfe2ec5b 100644 --- a/src/Mod/BIM/ArchStructure.py +++ b/src/Mod/BIM/ArchStructure.py @@ -6,23 +6,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** + #Modified 2016-01-03 JAndersM import FreeCAD,Draft,ArchComponent,DraftVecUtils,ArchCommands diff --git a/src/Mod/BIM/ArchTruss.py b/src/Mod/BIM/ArchTruss.py index 67a0f2afdf..6232d65468 100644 --- a/src/Mod/BIM/ArchTruss.py +++ b/src/Mod/BIM/ArchTruss.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchVRM.py b/src/Mod/BIM/ArchVRM.py index 15d7c51aa9..78d23efee2 100644 --- a/src/Mod/BIM/ArchVRM.py +++ b/src/Mod/BIM/ArchVRM.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index bd25fa5945..a24b80bf53 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchWindow.py b/src/Mod/BIM/ArchWindow.py index 8f086a9dbe..6af26efb1e 100644 --- a/src/Mod/BIM/ArchWindow.py +++ b/src/Mod/BIM/ArchWindow.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ArchWindowPresets.py b/src/Mod/BIM/ArchWindowPresets.py index 484c8446cf..a20b9bcd5e 100644 --- a/src/Mod/BIM/ArchWindowPresets.py +++ b/src/Mod/BIM/ArchWindowPresets.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/BimStatus.py b/src/Mod/BIM/BimStatus.py index 6fbbaf5091..f93bf67525 100644 --- a/src/Mod/BIM/BimStatus.py +++ b/src/Mod/BIM/BimStatus.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/Init.py b/src/Mod/BIM/Init.py index 87423b2fe5..5abea05b69 100644 --- a/src/Mod/BIM/Init.py +++ b/src/Mod/BIM/Init.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/InitGui.py b/src/Mod/BIM/InitGui.py index 37fccab293..4340f8f6d2 100644 --- a/src/Mod/BIM/InitGui.py +++ b/src/Mod/BIM/InitGui.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/OfflineRenderingUtils.py b/src/Mod/BIM/OfflineRenderingUtils.py index 49327a4b81..678fa85098 100755 --- a/src/Mod/BIM/OfflineRenderingUtils.py +++ b/src/Mod/BIM/OfflineRenderingUtils.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/TestArch.py b/src/Mod/BIM/TestArch.py index cb0953458d..e9fef39d12 100644 --- a/src/Mod/BIM/TestArch.py +++ b/src/Mod/BIM/TestArch.py @@ -4,23 +4,21 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * -# * This file is part of the FreeCAD CAx development system. * +# * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * FreeCAD is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU Library General Public License for more details. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with FreeCAD; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/TestArchGui.py b/src/Mod/BIM/TestArchGui.py index 3fd1d2c900..a92658ec7c 100644 --- a/src/Mod/BIM/TestArchGui.py +++ b/src/Mod/BIM/TestArchGui.py @@ -4,23 +4,21 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * -# * This file is part of the FreeCAD CAx development system. * +# * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * FreeCAD is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU Library General Public License for more details. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with FreeCAD; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimArchUtils.py b/src/Mod/BIM/bimcommands/BimArchUtils.py index cb03179795..6339ab9b07 100644 --- a/src/Mod/BIM/bimcommands/BimArchUtils.py +++ b/src/Mod/BIM/bimcommands/BimArchUtils.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimAxis.py b/src/Mod/BIM/bimcommands/BimAxis.py index 1ba596a2ff..9b37b15bb5 100644 --- a/src/Mod/BIM/bimcommands/BimAxis.py +++ b/src/Mod/BIM/bimcommands/BimAxis.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimBackground.py b/src/Mod/BIM/bimcommands/BimBackground.py index 5c3bb14f89..9377cd5b32 100644 --- a/src/Mod/BIM/bimcommands/BimBackground.py +++ b/src/Mod/BIM/bimcommands/BimBackground.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimBeam.py b/src/Mod/BIM/bimcommands/BimBeam.py index 958abedbf4..c86010468b 100644 --- a/src/Mod/BIM/bimcommands/BimBeam.py +++ b/src/Mod/BIM/bimcommands/BimBeam.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimBox.py b/src/Mod/BIM/bimcommands/BimBox.py index dca4b46037..fbbe88e5f6 100644 --- a/src/Mod/BIM/bimcommands/BimBox.py +++ b/src/Mod/BIM/bimcommands/BimBox.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimBuilder.py b/src/Mod/BIM/bimcommands/BimBuilder.py index 5a98966e96..441c0e9e78 100644 --- a/src/Mod/BIM/bimcommands/BimBuilder.py +++ b/src/Mod/BIM/bimcommands/BimBuilder.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimBuildingPart.py b/src/Mod/BIM/bimcommands/BimBuildingPart.py index 6ff22cbf5a..2186aee8bb 100644 --- a/src/Mod/BIM/bimcommands/BimBuildingPart.py +++ b/src/Mod/BIM/bimcommands/BimBuildingPart.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimClassification.py b/src/Mod/BIM/bimcommands/BimClassification.py index 26e298f483..328e6e4821 100644 --- a/src/Mod/BIM/bimcommands/BimClassification.py +++ b/src/Mod/BIM/bimcommands/BimClassification.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimClone.py b/src/Mod/BIM/bimcommands/BimClone.py index 16aface163..5221280642 100644 --- a/src/Mod/BIM/bimcommands/BimClone.py +++ b/src/Mod/BIM/bimcommands/BimClone.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimColumn.py b/src/Mod/BIM/bimcommands/BimColumn.py index 5952e50f94..f5d3734442 100644 --- a/src/Mod/BIM/bimcommands/BimColumn.py +++ b/src/Mod/BIM/bimcommands/BimColumn.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimCommon.py b/src/Mod/BIM/bimcommands/BimCommon.py index cd4549db62..cb9e8167c4 100644 --- a/src/Mod/BIM/bimcommands/BimCommon.py +++ b/src/Mod/BIM/bimcommands/BimCommon.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimCompound.py b/src/Mod/BIM/bimcommands/BimCompound.py index b9b2f5569e..4d352411ac 100644 --- a/src/Mod/BIM/bimcommands/BimCompound.py +++ b/src/Mod/BIM/bimcommands/BimCompound.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimConvert.py b/src/Mod/BIM/bimcommands/BimConvert.py index a1f8f92b5a..db11b8d5e8 100644 --- a/src/Mod/BIM/bimcommands/BimConvert.py +++ b/src/Mod/BIM/bimcommands/BimConvert.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimCopy.py b/src/Mod/BIM/bimcommands/BimCopy.py index b8303675a2..096644791f 100644 --- a/src/Mod/BIM/bimcommands/BimCopy.py +++ b/src/Mod/BIM/bimcommands/BimCopy.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimCurtainwall.py b/src/Mod/BIM/bimcommands/BimCurtainwall.py index 0071f90e3a..c2ccf34176 100644 --- a/src/Mod/BIM/bimcommands/BimCurtainwall.py +++ b/src/Mod/BIM/bimcommands/BimCurtainwall.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimCut.py b/src/Mod/BIM/bimcommands/BimCut.py index 270783c6a2..21b3ddd617 100644 --- a/src/Mod/BIM/bimcommands/BimCut.py +++ b/src/Mod/BIM/bimcommands/BimCut.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimCutPlane.py b/src/Mod/BIM/bimcommands/BimCutPlane.py index a0a43477d9..cb69ffebbc 100644 --- a/src/Mod/BIM/bimcommands/BimCutPlane.py +++ b/src/Mod/BIM/bimcommands/BimCutPlane.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # ***************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimDiff.py b/src/Mod/BIM/bimcommands/BimDiff.py index 1662a8b570..1ebf79f50e 100644 --- a/src/Mod/BIM/bimcommands/BimDiff.py +++ b/src/Mod/BIM/bimcommands/BimDiff.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimDimensions.py b/src/Mod/BIM/bimcommands/BimDimensions.py index 57e60db610..4e984a5d07 100644 --- a/src/Mod/BIM/bimcommands/BimDimensions.py +++ b/src/Mod/BIM/bimcommands/BimDimensions.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimDoor.py b/src/Mod/BIM/bimcommands/BimDoor.py index 698b2bb5ba..21b3821d99 100644 --- a/src/Mod/BIM/bimcommands/BimDoor.py +++ b/src/Mod/BIM/bimcommands/BimDoor.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimDrawingView.py b/src/Mod/BIM/bimcommands/BimDrawingView.py index 71dcb7bb45..73a7356fc4 100644 --- a/src/Mod/BIM/bimcommands/BimDrawingView.py +++ b/src/Mod/BIM/bimcommands/BimDrawingView.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimEmptyTrash.py b/src/Mod/BIM/bimcommands/BimEmptyTrash.py index bb27532a83..072a739d4d 100644 --- a/src/Mod/BIM/bimcommands/BimEmptyTrash.py +++ b/src/Mod/BIM/bimcommands/BimEmptyTrash.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimEquipment.py b/src/Mod/BIM/bimcommands/BimEquipment.py index 0fce95b511..b9edca9465 100644 --- a/src/Mod/BIM/bimcommands/BimEquipment.py +++ b/src/Mod/BIM/bimcommands/BimEquipment.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimExamples.py b/src/Mod/BIM/bimcommands/BimExamples.py index ce0aef5b59..a15e12eabe 100644 --- a/src/Mod/BIM/bimcommands/BimExamples.py +++ b/src/Mod/BIM/bimcommands/BimExamples.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimExtrude.py b/src/Mod/BIM/bimcommands/BimExtrude.py index 0b5889b83b..67cbc7987f 100644 --- a/src/Mod/BIM/bimcommands/BimExtrude.py +++ b/src/Mod/BIM/bimcommands/BimExtrude.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimFence.py b/src/Mod/BIM/bimcommands/BimFence.py index 06217f9ebf..6e213317b0 100644 --- a/src/Mod/BIM/bimcommands/BimFence.py +++ b/src/Mod/BIM/bimcommands/BimFence.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimFrame.py b/src/Mod/BIM/bimcommands/BimFrame.py index 97641fead1..e52c92fc06 100644 --- a/src/Mod/BIM/bimcommands/BimFrame.py +++ b/src/Mod/BIM/bimcommands/BimFrame.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimFuse.py b/src/Mod/BIM/bimcommands/BimFuse.py index 610f4a2663..b470b6e05c 100644 --- a/src/Mod/BIM/bimcommands/BimFuse.py +++ b/src/Mod/BIM/bimcommands/BimFuse.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimGlue.py b/src/Mod/BIM/bimcommands/BimGlue.py index 07420a3069..8722520f43 100644 --- a/src/Mod/BIM/bimcommands/BimGlue.py +++ b/src/Mod/BIM/bimcommands/BimGlue.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimHelp.py b/src/Mod/BIM/bimcommands/BimHelp.py index a598ec07b2..55905ae19a 100644 --- a/src/Mod/BIM/bimcommands/BimHelp.py +++ b/src/Mod/BIM/bimcommands/BimHelp.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimIfcElements.py b/src/Mod/BIM/bimcommands/BimIfcElements.py index ca777f1714..8795980aa7 100644 --- a/src/Mod/BIM/bimcommands/BimIfcElements.py +++ b/src/Mod/BIM/bimcommands/BimIfcElements.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimIfcExplorer.py b/src/Mod/BIM/bimcommands/BimIfcExplorer.py index cd2b66cc63..d4e8bd8376 100644 --- a/src/Mod/BIM/bimcommands/BimIfcExplorer.py +++ b/src/Mod/BIM/bimcommands/BimIfcExplorer.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimIfcProperties.py b/src/Mod/BIM/bimcommands/BimIfcProperties.py index ec2595c833..cbf3cd09db 100644 --- a/src/Mod/BIM/bimcommands/BimIfcProperties.py +++ b/src/Mod/BIM/bimcommands/BimIfcProperties.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimIfcQuantities.py b/src/Mod/BIM/bimcommands/BimIfcQuantities.py index fe57578870..2fc0eb80ee 100644 --- a/src/Mod/BIM/bimcommands/BimIfcQuantities.py +++ b/src/Mod/BIM/bimcommands/BimIfcQuantities.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimImagePlane.py b/src/Mod/BIM/bimcommands/BimImagePlane.py index 51eda8418d..281f62a5f2 100644 --- a/src/Mod/BIM/bimcommands/BimImagePlane.py +++ b/src/Mod/BIM/bimcommands/BimImagePlane.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimLayers.py b/src/Mod/BIM/bimcommands/BimLayers.py index 4b639b242f..ae6cf75692 100644 --- a/src/Mod/BIM/bimcommands/BimLayers.py +++ b/src/Mod/BIM/bimcommands/BimLayers.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimLeader.py b/src/Mod/BIM/bimcommands/BimLeader.py index 8ff8414929..7709ccfd63 100644 --- a/src/Mod/BIM/bimcommands/BimLeader.py +++ b/src/Mod/BIM/bimcommands/BimLeader.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimLibrary.py b/src/Mod/BIM/bimcommands/BimLibrary.py index c09bea1da7..709427a30a 100644 --- a/src/Mod/BIM/bimcommands/BimLibrary.py +++ b/src/Mod/BIM/bimcommands/BimLibrary.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimMaterial.py b/src/Mod/BIM/bimcommands/BimMaterial.py index 3c1c9afb6f..042a0eff46 100644 --- a/src/Mod/BIM/bimcommands/BimMaterial.py +++ b/src/Mod/BIM/bimcommands/BimMaterial.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimMoveView.py b/src/Mod/BIM/bimcommands/BimMoveView.py index c04bac914b..8cbf859987 100644 --- a/src/Mod/BIM/bimcommands/BimMoveView.py +++ b/src/Mod/BIM/bimcommands/BimMoveView.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimNudge.py b/src/Mod/BIM/bimcommands/BimNudge.py index a31a1ba2e8..929de509b7 100644 --- a/src/Mod/BIM/bimcommands/BimNudge.py +++ b/src/Mod/BIM/bimcommands/BimNudge.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimOffset.py b/src/Mod/BIM/bimcommands/BimOffset.py index fff682dcb4..a2396de268 100644 --- a/src/Mod/BIM/bimcommands/BimOffset.py +++ b/src/Mod/BIM/bimcommands/BimOffset.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimPanel.py b/src/Mod/BIM/bimcommands/BimPanel.py index b41c5a8b84..1c520af680 100644 --- a/src/Mod/BIM/bimcommands/BimPanel.py +++ b/src/Mod/BIM/bimcommands/BimPanel.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimPipe.py b/src/Mod/BIM/bimcommands/BimPipe.py index f4024c8ae9..32a1ee8172 100644 --- a/src/Mod/BIM/bimcommands/BimPipe.py +++ b/src/Mod/BIM/bimcommands/BimPipe.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimPreflight.py b/src/Mod/BIM/bimcommands/BimPreflight.py index 14e3af586c..7a20b25b28 100644 --- a/src/Mod/BIM/bimcommands/BimPreflight.py +++ b/src/Mod/BIM/bimcommands/BimPreflight.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimProfile.py b/src/Mod/BIM/bimcommands/BimProfile.py index b3e14e0638..c768f62b0d 100644 --- a/src/Mod/BIM/bimcommands/BimProfile.py +++ b/src/Mod/BIM/bimcommands/BimProfile.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimProject.py b/src/Mod/BIM/bimcommands/BimProject.py index 47f3ebf9f5..13ab28b139 100644 --- a/src/Mod/BIM/bimcommands/BimProject.py +++ b/src/Mod/BIM/bimcommands/BimProject.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index f24d79c04d..fa8c26c136 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimRebar.py b/src/Mod/BIM/bimcommands/BimRebar.py index 848eb9ef1e..e627f956c4 100644 --- a/src/Mod/BIM/bimcommands/BimRebar.py +++ b/src/Mod/BIM/bimcommands/BimRebar.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimReextrude.py b/src/Mod/BIM/bimcommands/BimReextrude.py index b36f62712a..bc99114561 100644 --- a/src/Mod/BIM/bimcommands/BimReextrude.py +++ b/src/Mod/BIM/bimcommands/BimReextrude.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimReference.py b/src/Mod/BIM/bimcommands/BimReference.py index 2ab0e13f5a..bac183d285 100644 --- a/src/Mod/BIM/bimcommands/BimReference.py +++ b/src/Mod/BIM/bimcommands/BimReference.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimReorder.py b/src/Mod/BIM/bimcommands/BimReorder.py index 9788f17018..3c603376f7 100644 --- a/src/Mod/BIM/bimcommands/BimReorder.py +++ b/src/Mod/BIM/bimcommands/BimReorder.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimResetCloneColors.py b/src/Mod/BIM/bimcommands/BimResetCloneColors.py index cc8281a8ab..ef82f9c6e9 100644 --- a/src/Mod/BIM/bimcommands/BimResetCloneColors.py +++ b/src/Mod/BIM/bimcommands/BimResetCloneColors.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimRewire.py b/src/Mod/BIM/bimcommands/BimRewire.py index eb3dd8b93c..128caed321 100644 --- a/src/Mod/BIM/bimcommands/BimRewire.py +++ b/src/Mod/BIM/bimcommands/BimRewire.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimRoof.py b/src/Mod/BIM/bimcommands/BimRoof.py index 383c3e82a5..4f8f9f3e91 100644 --- a/src/Mod/BIM/bimcommands/BimRoof.py +++ b/src/Mod/BIM/bimcommands/BimRoof.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSchedule.py b/src/Mod/BIM/bimcommands/BimSchedule.py index 320b09abff..8554608241 100644 --- a/src/Mod/BIM/bimcommands/BimSchedule.py +++ b/src/Mod/BIM/bimcommands/BimSchedule.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSectionPlane.py b/src/Mod/BIM/bimcommands/BimSectionPlane.py index 8fdf969c01..da8590d1f8 100644 --- a/src/Mod/BIM/bimcommands/BimSectionPlane.py +++ b/src/Mod/BIM/bimcommands/BimSectionPlane.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSetup.py b/src/Mod/BIM/bimcommands/BimSetup.py index 4ce731fbef..b1b2e2b6e8 100644 --- a/src/Mod/BIM/bimcommands/BimSetup.py +++ b/src/Mod/BIM/bimcommands/BimSetup.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimShape2DView.py b/src/Mod/BIM/bimcommands/BimShape2DView.py index e1746ae579..e627e9af14 100644 --- a/src/Mod/BIM/bimcommands/BimShape2DView.py +++ b/src/Mod/BIM/bimcommands/BimShape2DView.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSimpleCopy.py b/src/Mod/BIM/bimcommands/BimSimpleCopy.py index b279551900..6ee7e17148 100644 --- a/src/Mod/BIM/bimcommands/BimSimpleCopy.py +++ b/src/Mod/BIM/bimcommands/BimSimpleCopy.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSite.py b/src/Mod/BIM/bimcommands/BimSite.py index 1f30a24ff0..85b0a024ff 100644 --- a/src/Mod/BIM/bimcommands/BimSite.py +++ b/src/Mod/BIM/bimcommands/BimSite.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSketch.py b/src/Mod/BIM/bimcommands/BimSketch.py index c0213a626f..03f0148153 100644 --- a/src/Mod/BIM/bimcommands/BimSketch.py +++ b/src/Mod/BIM/bimcommands/BimSketch.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSlab.py b/src/Mod/BIM/bimcommands/BimSlab.py index a4e31b63a7..4745f41a79 100644 --- a/src/Mod/BIM/bimcommands/BimSlab.py +++ b/src/Mod/BIM/bimcommands/BimSlab.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimSpace.py b/src/Mod/BIM/bimcommands/BimSpace.py index 406eff2f95..d2d20badc4 100644 --- a/src/Mod/BIM/bimcommands/BimSpace.py +++ b/src/Mod/BIM/bimcommands/BimSpace.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimStairs.py b/src/Mod/BIM/bimcommands/BimStairs.py index 2839a4bd91..2b52a8ff7a 100644 --- a/src/Mod/BIM/bimcommands/BimStairs.py +++ b/src/Mod/BIM/bimcommands/BimStairs.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimTDPage.py b/src/Mod/BIM/bimcommands/BimTDPage.py index 014cb53a4f..42c19e33c1 100644 --- a/src/Mod/BIM/bimcommands/BimTDPage.py +++ b/src/Mod/BIM/bimcommands/BimTDPage.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimTDView.py b/src/Mod/BIM/bimcommands/BimTDView.py index 72affb277a..628206d57a 100644 --- a/src/Mod/BIM/bimcommands/BimTDView.py +++ b/src/Mod/BIM/bimcommands/BimTDView.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimText.py b/src/Mod/BIM/bimcommands/BimText.py index 2a618c92d6..351c2d7978 100644 --- a/src/Mod/BIM/bimcommands/BimText.py +++ b/src/Mod/BIM/bimcommands/BimText.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimTogglePanels.py b/src/Mod/BIM/bimcommands/BimTogglePanels.py index 5601fde425..2922cb4749 100644 --- a/src/Mod/BIM/bimcommands/BimTogglePanels.py +++ b/src/Mod/BIM/bimcommands/BimTogglePanels.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimTrash.py b/src/Mod/BIM/bimcommands/BimTrash.py index 9f5a28daf1..dd56316d42 100644 --- a/src/Mod/BIM/bimcommands/BimTrash.py +++ b/src/Mod/BIM/bimcommands/BimTrash.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimTruss.py b/src/Mod/BIM/bimcommands/BimTruss.py index af5113da0e..5f73278c70 100644 --- a/src/Mod/BIM/bimcommands/BimTruss.py +++ b/src/Mod/BIM/bimcommands/BimTruss.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimTutorial.py b/src/Mod/BIM/bimcommands/BimTutorial.py index ed8c3a9fc9..94b84b3fb6 100644 --- a/src/Mod/BIM/bimcommands/BimTutorial.py +++ b/src/Mod/BIM/bimcommands/BimTutorial.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimUnclone.py b/src/Mod/BIM/bimcommands/BimUnclone.py index e559d1be1b..0f0566a6f9 100644 --- a/src/Mod/BIM/bimcommands/BimUnclone.py +++ b/src/Mod/BIM/bimcommands/BimUnclone.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimUngroup.py b/src/Mod/BIM/bimcommands/BimUngroup.py index 342c3f2901..f29dc4b69b 100644 --- a/src/Mod/BIM/bimcommands/BimUngroup.py +++ b/src/Mod/BIM/bimcommands/BimUngroup.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimViews.py b/src/Mod/BIM/bimcommands/BimViews.py index 3f86c3fd8e..ba7a0344f5 100644 --- a/src/Mod/BIM/bimcommands/BimViews.py +++ b/src/Mod/BIM/bimcommands/BimViews.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimWPCommands.py b/src/Mod/BIM/bimcommands/BimWPCommands.py index 39f23c02cb..bcc3921972 100644 --- a/src/Mod/BIM/bimcommands/BimWPCommands.py +++ b/src/Mod/BIM/bimcommands/BimWPCommands.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimWall.py b/src/Mod/BIM/bimcommands/BimWall.py index ff1b576561..8dcfedecc4 100644 --- a/src/Mod/BIM/bimcommands/BimWall.py +++ b/src/Mod/BIM/bimcommands/BimWall.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimWelcome.py b/src/Mod/BIM/bimcommands/BimWelcome.py index 0638843c31..6cc17722fc 100644 --- a/src/Mod/BIM/bimcommands/BimWelcome.py +++ b/src/Mod/BIM/bimcommands/BimWelcome.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimWindow.py b/src/Mod/BIM/bimcommands/BimWindow.py index 860c4d262c..289c8046e7 100644 --- a/src/Mod/BIM/bimcommands/BimWindow.py +++ b/src/Mod/BIM/bimcommands/BimWindow.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimcommands/BimWindows.py b/src/Mod/BIM/bimcommands/BimWindows.py index 12b97b6388..f41cb452e7 100644 --- a/src/Mod/BIM/bimcommands/BimWindows.py +++ b/src/Mod/BIM/bimcommands/BimWindows.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimtests/TestArchRoof.py b/src/Mod/BIM/bimtests/TestArchRoof.py index f7af8014bf..4905c2fa0d 100644 --- a/src/Mod/BIM/bimtests/TestArchRoof.py +++ b/src/Mod/BIM/bimtests/TestArchRoof.py @@ -4,23 +4,21 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * -# * This file is part of the FreeCAD CAx development system. * +# * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * FreeCAD is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU Library General Public License for more details. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with FreeCAD; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimtests/TestArchSpace.py b/src/Mod/BIM/bimtests/TestArchSpace.py index 75c3216834..c11d518eb0 100644 --- a/src/Mod/BIM/bimtests/TestArchSpace.py +++ b/src/Mod/BIM/bimtests/TestArchSpace.py @@ -4,23 +4,21 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * -# * This file is part of the FreeCAD CAx development system. * +# * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * FreeCAD is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU Library General Public License for more details. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with FreeCAD; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/bimtests/TestArchWall.py b/src/Mod/BIM/bimtests/TestArchWall.py index 7a5add3aac..66359841c8 100644 --- a/src/Mod/BIM/bimtests/TestArchWall.py +++ b/src/Mod/BIM/bimtests/TestArchWall.py @@ -4,23 +4,21 @@ # * * # * Copyright (c) 2013 Yorik van Havre * # * * -# * This file is part of the FreeCAD CAx development system. * +# * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * FreeCAD is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU Library General Public License for more details. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with FreeCAD; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ifc_objects.py b/src/Mod/BIM/ifc_objects.py index 6f6b6e5f54..a077f87f73 100644 --- a/src/Mod/BIM/ifc_objects.py +++ b/src/Mod/BIM/ifc_objects.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Library General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/ifc_viewproviders.py b/src/Mod/BIM/ifc_viewproviders.py index 764c39669f..973a1ca517 100644 --- a/src/Mod/BIM/ifc_viewproviders.py +++ b/src/Mod/BIM/ifc_viewproviders.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Library General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index 0ebbd6dc58..91ef9b9c53 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -6,23 +6,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** + """Provide the exporter for IFC files used above all in Arch and BIM. Internally it uses IfcOpenShell, which must be installed before using. diff --git a/src/Mod/BIM/importers/exportIFCHelper.py b/src/Mod/BIM/importers/exportIFCHelper.py index b3d363a200..0374d94a8b 100644 --- a/src/Mod/BIM/importers/exportIFCHelper.py +++ b/src/Mod/BIM/importers/exportIFCHelper.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/exportIFCStructuralTools.py b/src/Mod/BIM/importers/exportIFCStructuralTools.py index 5f364858e7..35471f6184 100644 --- a/src/Mod/BIM/importers/exportIFCStructuralTools.py +++ b/src/Mod/BIM/importers/exportIFCStructuralTools.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/import3DS.py b/src/Mod/BIM/importers/import3DS.py index e46ba9c39b..c326acdbd6 100644 --- a/src/Mod/BIM/importers/import3DS.py +++ b/src/Mod/BIM/importers/import3DS.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importDAE.py b/src/Mod/BIM/importers/importDAE.py index d4f59af303..1eda12a3a4 100644 --- a/src/Mod/BIM/importers/importDAE.py +++ b/src/Mod/BIM/importers/importDAE.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importGBXML.py b/src/Mod/BIM/importers/importGBXML.py index 014ffaf0ce..a0e60f01fa 100644 --- a/src/Mod/BIM/importers/importGBXML.py +++ b/src/Mod/BIM/importers/importGBXML.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importIFC.py b/src/Mod/BIM/importers/importIFC.py index 74e910c949..f0f4a99246 100644 --- a/src/Mod/BIM/importers/importIFC.py +++ b/src/Mod/BIM/importers/importIFC.py @@ -6,23 +6,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** + """Provide the importer for IFC files used above all in Arch and BIM. Internally it uses IfcOpenShell, which must be installed before using. diff --git a/src/Mod/BIM/importers/importIFCHelper.py b/src/Mod/BIM/importers/importIFCHelper.py index ba3f7a092b..1d7740831d 100644 --- a/src/Mod/BIM/importers/importIFCHelper.py +++ b/src/Mod/BIM/importers/importIFCHelper.py @@ -6,23 +6,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** + """Helper functions that are used by IFC importer and exporter.""" import sys import math diff --git a/src/Mod/BIM/importers/importIFClegacy.py b/src/Mod/BIM/importers/importIFClegacy.py index ceaab17cdf..fe08a7b7a7 100644 --- a/src/Mod/BIM/importers/importIFClegacy.py +++ b/src/Mod/BIM/importers/importIFClegacy.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importIFCmulticore.py b/src/Mod/BIM/importers/importIFCmulticore.py index 230d4bf93e..186ef2214c 100644 --- a/src/Mod/BIM/importers/importIFCmulticore.py +++ b/src/Mod/BIM/importers/importIFCmulticore.py @@ -6,23 +6,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** + """FreeCAD IFC importer - Multicore version""" import sys diff --git a/src/Mod/BIM/importers/importJSON.py b/src/Mod/BIM/importers/importJSON.py index 2cab4ceb2e..d371953917 100644 --- a/src/Mod/BIM/importers/importJSON.py +++ b/src/Mod/BIM/importers/importJSON.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importOBJ.py b/src/Mod/BIM/importers/importOBJ.py index e8658a0c02..27c3dfacc0 100644 --- a/src/Mod/BIM/importers/importOBJ.py +++ b/src/Mod/BIM/importers/importOBJ.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importSH3D.py b/src/Mod/BIM/importers/importSH3D.py index ba830df7fa..73b5296053 100644 --- a/src/Mod/BIM/importers/importSH3D.py +++ b/src/Mod/BIM/importers/importSH3D.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importSH3DHelper.py b/src/Mod/BIM/importers/importSH3DHelper.py index e80e5aab3f..36b5f40779 100644 --- a/src/Mod/BIM/importers/importSH3DHelper.py +++ b/src/Mod/BIM/importers/importSH3DHelper.py @@ -6,23 +6,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** + """Helper functions that are used by SH3D importer.""" import itertools import numpy as np @@ -3016,4 +3015,3 @@ def convex_hull(points, tol=1e-6): # point_coords = np.array([[p.x, p.y] for p in points]) # new_points = [points[i] for i in scipy.spatial.ConvexHull(point_coords).vertices] # return new_points[0] - diff --git a/src/Mod/BIM/importers/importSHP.py b/src/Mod/BIM/importers/importSHP.py index f8e9f9d8ca..52af7d61ca 100644 --- a/src/Mod/BIM/importers/importSHP.py +++ b/src/Mod/BIM/importers/importSHP.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/importers/importWebGL.py b/src/Mod/BIM/importers/importWebGL.py index 00b11029f1..93354f845a 100644 --- a/src/Mod/BIM/importers/importWebGL.py +++ b/src/Mod/BIM/importers/importWebGL.py @@ -7,24 +7,22 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** -# + # REFS: # https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_buffergeometry.html # https://threejs.org/examples/#webgl_buffergeometry_lines diff --git a/src/Mod/BIM/nativeifc/ifc_classification.py b/src/Mod/BIM/nativeifc/ifc_classification.py index fba17a90bb..531f293e63 100644 --- a/src/Mod/BIM/nativeifc/ifc_classification.py +++ b/src/Mod/BIM/nativeifc/ifc_classification.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU General Public License (GPL) * -# * as published by the Free Software Foundation; either version 3 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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 General Public License for more details. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_commands.py b/src/Mod/BIM/nativeifc/ifc_commands.py index 02ad0e6701..d5ce447c6b 100644 --- a/src/Mod/BIM/nativeifc/ifc_commands.py +++ b/src/Mod/BIM/nativeifc/ifc_commands.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_diff.py b/src/Mod/BIM/nativeifc/ifc_diff.py index b34e8e3f08..d49ba6fe81 100644 --- a/src/Mod/BIM/nativeifc/ifc_diff.py +++ b/src/Mod/BIM/nativeifc/ifc_diff.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index 7c81492a0b..192f55daa9 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_generator.py b/src/Mod/BIM/nativeifc/ifc_generator.py index e16df06473..b0ed45a8db 100644 --- a/src/Mod/BIM/nativeifc/ifc_generator.py +++ b/src/Mod/BIM/nativeifc/ifc_generator.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_geometry.py b/src/Mod/BIM/nativeifc/ifc_geometry.py index 3f963c5557..a1069016b8 100644 --- a/src/Mod/BIM/nativeifc/ifc_geometry.py +++ b/src/Mod/BIM/nativeifc/ifc_geometry.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_import.py b/src/Mod/BIM/nativeifc/ifc_import.py index 697991cb35..5209401baa 100644 --- a/src/Mod/BIM/nativeifc/ifc_import.py +++ b/src/Mod/BIM/nativeifc/ifc_import.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_layers.py b/src/Mod/BIM/nativeifc/ifc_layers.py index 706d885800..1b30c37cad 100644 --- a/src/Mod/BIM/nativeifc/ifc_layers.py +++ b/src/Mod/BIM/nativeifc/ifc_layers.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_materials.py b/src/Mod/BIM/nativeifc/ifc_materials.py index 390bc71d26..e05b7d7314 100644 --- a/src/Mod/BIM/nativeifc/ifc_materials.py +++ b/src/Mod/BIM/nativeifc/ifc_materials.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_objects.py b/src/Mod/BIM/nativeifc/ifc_objects.py index a8b5f28f70..2ca3e25587 100644 --- a/src/Mod/BIM/nativeifc/ifc_objects.py +++ b/src/Mod/BIM/nativeifc/ifc_objects.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_observer.py b/src/Mod/BIM/nativeifc/ifc_observer.py index d7650eb8de..c82ae79734 100644 --- a/src/Mod/BIM/nativeifc/ifc_observer.py +++ b/src/Mod/BIM/nativeifc/ifc_observer.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_openshell.py b/src/Mod/BIM/nativeifc/ifc_openshell.py index 6d3fbb9dde..85fb0379db 100644 --- a/src/Mod/BIM/nativeifc/ifc_openshell.py +++ b/src/Mod/BIM/nativeifc/ifc_openshell.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_performance_test.py b/src/Mod/BIM/nativeifc/ifc_performance_test.py index 946061285e..813d50099d 100644 --- a/src/Mod/BIM/nativeifc/ifc_performance_test.py +++ b/src/Mod/BIM/nativeifc/ifc_performance_test.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_psets.py b/src/Mod/BIM/nativeifc/ifc_psets.py index 16c1d01ff6..ef760a22ba 100644 --- a/src/Mod/BIM/nativeifc/ifc_psets.py +++ b/src/Mod/BIM/nativeifc/ifc_psets.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_selftest.py b/src/Mod/BIM/nativeifc/ifc_selftest.py index a8a6d1b4b3..b0ff258b26 100644 --- a/src/Mod/BIM/nativeifc/ifc_selftest.py +++ b/src/Mod/BIM/nativeifc/ifc_selftest.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_status.py b/src/Mod/BIM/nativeifc/ifc_status.py index f028c82cd3..220cf05c23 100644 --- a/src/Mod/BIM/nativeifc/ifc_status.py +++ b/src/Mod/BIM/nativeifc/ifc_status.py @@ -8,21 +8,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index cffedbfe48..5a1121f1cd 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_tree.py b/src/Mod/BIM/nativeifc/ifc_tree.py index c2cc4b4602..97d53d64c7 100644 --- a/src/Mod/BIM/nativeifc/ifc_tree.py +++ b/src/Mod/BIM/nativeifc/ifc_tree.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_types.py b/src/Mod/BIM/nativeifc/ifc_types.py index e4afe43604..6a6b5ad9d2 100644 --- a/src/Mod/BIM/nativeifc/ifc_types.py +++ b/src/Mod/BIM/nativeifc/ifc_types.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Library General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/nativeifc/ifc_viewproviders.py b/src/Mod/BIM/nativeifc/ifc_viewproviders.py index 0828d0c4ca..5ad53edfe5 100644 --- a/src/Mod/BIM/nativeifc/ifc_viewproviders.py +++ b/src/Mod/BIM/nativeifc/ifc_viewproviders.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Library General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/utils/buildPsets.py b/src/Mod/BIM/utils/buildPsets.py index 9b106dbbbb..365d2c9b88 100644 --- a/src/Mod/BIM/utils/buildPsets.py +++ b/src/Mod/BIM/utils/buildPsets.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** diff --git a/src/Mod/BIM/utils/ifctree.py b/src/Mod/BIM/utils/ifctree.py index 4ae1057b4c..9d764f5660 100644 --- a/src/Mod/BIM/utils/ifctree.py +++ b/src/Mod/BIM/utils/ifctree.py @@ -6,21 +6,19 @@ # * * # * This file is part of FreeCAD. * # * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU Lesser General Public License (LGPL) * -# * as published by the Free Software Foundation; either version 2 of * -# * the License, or (at your option) any later version. * -# * for detail see the LICENCE text file. * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * # * * -# * 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. * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * # * * -# * You should have received a copy of the GNU Library General Public * -# * License along with this program; if not, write to the Free Software * -# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -# * USA * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * # * * # *************************************************************************** From 75b55658a755a8fcc50d53bfe7e088ea104fda36 Mon Sep 17 00:00:00 2001 From: Kevin Martin Date: Mon, 31 Mar 2025 15:52:05 -0400 Subject: [PATCH 151/316] Check for a null scene object Under certain unusual circumstances getSceneGraph can be called when the scene is null, causing a native exception when the scene's reference count is incremented. This changes the code to return python None in this condition, allowing the calling cod eto handle the no-scene case itself. --- src/Gui/View3DPy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Gui/View3DPy.cpp b/src/Gui/View3DPy.cpp index dab66a874b..30eaf2a56a 100644 --- a/src/Gui/View3DPy.cpp +++ b/src/Gui/View3DPy.cpp @@ -2135,6 +2135,9 @@ Py::Object View3DInventorPy::getSceneGraph() { try { SoNode* scene = getView3DInventorPtr()->getViewer()->getSceneGraph(); + if (scene == nullptr) { + return Py::None(); + } PyObject* proxy = nullptr; proxy = Base::Interpreter().createSWIGPointerObj("pivy.coin", "SoSeparator *", static_cast(scene), 1); scene->ref(); From 7a12d2f96f44dcb0fb98e34dbba055833cafb984 Mon Sep 17 00:00:00 2001 From: luzpaz Date: Sat, 5 Apr 2025 23:58:20 -0400 Subject: [PATCH 152/316] Fix various typos (#20651) * Fix various typos Found via `codespell -q 3 -L aci,addmin,ake,aline,alle,alledges,alocation,als,ang,anid,anormal,anull,aply,apoints,ba,beginn,behaviour,bloaded,bottome,brushin,bu,byteorder,calculater,cancelled,cancelling,cas,cascade,centimetre,childrens,childs,colour,colours,commen,connexion,currenty,documentin,dof,doubleclick,dum,eiter,elemente,ende,feld,finde,findf,findn,fle,freez,graphin,groupe,hist,iff,incrementin,indexin,indicies,initialisation,initialise,initialised,initialises,initialisiert,inout,ist,itsel,kilometre,leadin,localy,lod,mantatory,matc,methode,metres,millimetre,modell,nd,noe,normale,normaly,nto,numer,oce,oder,ontop,orgin,orginx,orginy,ot,pard,parm,parms,pres,programm,que,rady,recurrance,renderin,re-use,re-used,re-using,rin,ro,rougly,sectionin,seperator,sergent,serie,shs,sinc,siz,som,stpo,strack,substraction,te,technic,thist,thru,tread,tru,ue,uint,unter,uupper,uptodate,vas,vertexes,vew,wallthickness,whitespaces -S "./.git,*.po,*.ts,*.pdf,./ChangeLog.txt,./src/3rdParty,./src/Mod/Assembly/App/opendcm,./src/CXX,./src/zipios++,./src/Base/swig*,./src/Mod/Robot/App/kdl_cp,./src/Mod/Import/App/SCL,./src/WindowsInstaller,./src/Doc/FreeCAD.uml,./src/Base/StackWalker.cpp,./build/doc/SourceDoc,./tools/build/WindowsInstaller/lang,./src/Mod/TechDraw/Templates/locale"` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Doc/BuildWebDoc.cfg.in | 2 +- src/Mod/CAM/App/Area.cpp | 2 +- src/Mod/Draft/importAirfoilDAT.py | 2 +- src/Mod/Part/App/PropertyTopoShape.cpp | 2 +- src/Mod/Part/App/WireJoiner.cpp | 16 +++++----- src/Mod/Sketcher/App/SketchObject.cpp | 2 +- src/Mod/Spreadsheet/Gui/LineEdit.cpp | 2 +- src/Mod/TechDraw/Gui/QGILeaderLine.cpp | 2 +- tests/src/App/DocumentObserver.cpp | 10 +++--- tests/src/Mod/Part/App/PartFeature.cpp | 2 +- tests/src/Mod/Part/App/WireJoiner.cpp | 44 +++++++++++++------------- 11 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/Doc/BuildWebDoc.cfg.in b/src/Doc/BuildWebDoc.cfg.in index cd2adc6aee..ddbfab9da4 100644 --- a/src/Doc/BuildWebDoc.cfg.in +++ b/src/Doc/BuildWebDoc.cfg.in @@ -2794,7 +2794,7 @@ TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to # YES then Doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is set to NO, # can be accomplished by means of the command \includegraph. Disabling an # include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. diff --git a/src/Mod/CAM/App/Area.cpp b/src/Mod/CAM/App/Area.cpp index 0e593cd448..100bba2a90 100644 --- a/src/Mod/CAM/App/Area.cpp +++ b/src/Mod/CAM/App/Area.cpp @@ -875,7 +875,7 @@ static inline void getEndPoints(const TopoDS_Wire& wire, gp_Pnt& p1, gp_Pnt& p2) } // Toponaming integration note: there's a new class called WireJoiner in Mod/Part/App/ that has been -// imported from RT's fork. Is's an improved version of the following struct, therefor +// imported from RT's fork. It's an improved version of the following struct, therefore // probably at some point this struct should be replaced with the new imported class. // See https://github.com/realthunder/FreeCAD/blob/LinkStable/src/Mod/Part/App/WireJoiner.h for the // original implementation of the class and https://github.com/FreeCAD/FreeCAD/pull/12535 for the diff --git a/src/Mod/Draft/importAirfoilDAT.py b/src/Mod/Draft/importAirfoilDAT.py index 3488ed85a6..9380975ff4 100644 --- a/src/Mod/Draft/importAirfoilDAT.py +++ b/src/Mod/Draft/importAirfoilDAT.py @@ -132,7 +132,7 @@ def process(filename): regex = re.compile(_regex) afile = pyopen(filename, 'r') - # read the airfoil name which is always at the first line + # read the airfoil name which is always in the first line airfoilname = afile.readline().strip() coords = [] diff --git a/src/Mod/Part/App/PropertyTopoShape.cpp b/src/Mod/Part/App/PropertyTopoShape.cpp index dba06ef6d5..d874442c27 100644 --- a/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/src/Mod/Part/App/PropertyTopoShape.cpp @@ -603,7 +603,7 @@ void PropertyPartShape::RestoreDocFile(Base::Reader &reader) // Now it's not possible anymore because both PropertyPartShape::loadFromFile() and // PropertyPartShape::loadFromStream() calls PropertyPartShape::setValue() which clears the // value of _Ver. - // Therefor we're storing the value of _Ver here so that we don't lose it. + // Therefore we're storing the value of _Ver here so that we don't lose it. std::string ver = _Ver; diff --git a/src/Mod/Part/App/WireJoiner.cpp b/src/Mod/Part/App/WireJoiner.cpp index f3688caf0f..b976501d07 100644 --- a/src/Mod/Part/App/WireJoiner.cpp +++ b/src/Mod/Part/App/WireJoiner.cpp @@ -1722,7 +1722,7 @@ public: } // Originally here there was the definition of the method checkStack(), which does nothing and - // therefor has been removed. See + // therefore has been removed. See // https://github.com/realthunder/FreeCAD/blob/6f15849be2505f98927e75d0e8352185e14e7b72/src/Mod/Part/App/WireJoiner.cpp#L1366 // for reference @@ -1768,7 +1768,7 @@ public: ++stack.back().iEnd; // Originally here there was a call to the method checkStack(), - // which does nothing and therefor has been removed. + // which does nothing and therefore has been removed. } } } @@ -1985,7 +1985,7 @@ public: auto stackEnd = stack.size(); // Originally here there was a call to the method checkStack(), which does nothing and - // therefor has been removed. + // therefore has been removed. // pstart and pend is the start and end vertex of the current wire while (true) { @@ -2004,7 +2004,7 @@ public: beginInfo); // Originally here there was a call to the method checkStack(), which does nothing and - // therefor has been removed. + // therefore has been removed. if (proceed) { if (_findClosedWiresUpdateEdges(currentVertex, @@ -2182,7 +2182,7 @@ public: vertexStack.push_back(currentVertex); // Originally here there was a call to the method checkStack(), which does - // nothing and therefor has been removed. + // nothing and therefore has been removed. int idxEnd = (int)wireVertices.size(); int stackStart = (int)stack.size() - 1; @@ -2381,7 +2381,7 @@ public: edgeSet.insert(wireVertices[idxV].edgeInfo()); // Originally here there was a call to the method checkStack(), which does - // nothing and therefor has been removed. + // nothing and therefore has been removed. } if (!newWire) { @@ -2425,7 +2425,7 @@ public: vertexStack.push_back(currentVertex); // Originally here there a call to the method checkStack(), which - // does nothing and therefor has been removed. + // does nothing and therefore has been removed. TopoDS_Wire wire; if (pstart.SquareDistance(currentVertex.ptOther()) > myTol2) { @@ -2511,7 +2511,7 @@ public: edgeSet.insert(wireVertices[idxV].edgeInfo()); // Originally here there a call to the method checkStack(), which does - // nothing and therefor has been removed. + // nothing and therefore has been removed. } } diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 77fadd32bd..b3c644c2f0 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -10708,7 +10708,7 @@ void SketchObject::updateGeometryRefs() { FC_ERR("External geometry reference corrupted in " << getFullName() << " Please check."); // This could happen if someone saved the sketch containing - // external geometries using some rouge releases during the + // external geometries using some rogue releases during the // migration period. As a remedy, We re-initiate the // external geometry here to trigger rebuild later, with // call to rebuildExternalGeometry() diff --git a/src/Mod/Spreadsheet/Gui/LineEdit.cpp b/src/Mod/Spreadsheet/Gui/LineEdit.cpp index 0d9d18d35e..2b41b8991c 100644 --- a/src/Mod/Spreadsheet/Gui/LineEdit.cpp +++ b/src/Mod/Spreadsheet/Gui/LineEdit.cpp @@ -49,7 +49,7 @@ void LineEdit::setDocumentObject(const App::DocumentObject* currentDocObj, bool /* The code below is supposed to fix the input of an expression and to make the popup * functional. The input seems to be broken because of installed event filters. My solution is - * to readd the widget into the scene. Only a parentless widget can be added to the scene. + * to re-add the widget into the scene. Only a parentless widget can be added to the scene. * Making a widget parentless makes it lose its windowFlags, even if it is added to the scene. * So, the algorithm is to obtain globalPos, then to make the widget parentless, * to add it to the scene, setting the globalPos after. */ diff --git a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp index b8e23aac6c..c6256f14be 100644 --- a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp +++ b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp @@ -461,7 +461,7 @@ QPainterPath QGILeaderLine::makeLeaderPath(std::vector qPoints) //! returns the point (on the parent) to which the leader is attached. //! result is relative to the center of the unscaled, unrotated parent. -//! result is is not inverted (Y grows upwards). +//! result is not inverted (Y grows upwards). QPointF QGILeaderLine::getAttachFromFeature() { TechDraw::DrawLeaderLine* featLeader = getLeaderFeature(); diff --git a/tests/src/App/DocumentObserver.cpp b/tests/src/App/DocumentObserver.cpp index 0b4c27ada6..5779d23e62 100644 --- a/tests/src/App/DocumentObserver.cpp +++ b/tests/src/App/DocumentObserver.cpp @@ -74,12 +74,12 @@ TEST_F(DISABLED_DocumentObserverTest, hasSubObject) // Assert - // The subname of subObjTWithoutSubObj doesn't contain the name of a sub object, therefor + // The subname of subObjTWithoutSubObj doesn't contain the name of a sub object, therefore // hasNoSubObj should be false EXPECT_FALSE(hasNoSubObj); - // The subname of subObjTWithSubObj doesn't contain the name of a sub object, therefor hasSubObj - // should be true + // The subname of subObjTWithSubObj doesn't contain the name of a sub object, therefore + // hasSubObj should be true EXPECT_TRUE(hasSubObj); } @@ -118,11 +118,11 @@ TEST_F(DISABLED_DocumentObserverTest, hasSubElement) // Assert - // The subname of subObjTWithoutSubEl doesn't contain the name of a sub element, therefor + // The subname of subObjTWithoutSubEl doesn't contain the name of a sub element, therefore // hasNoSubEl should be false EXPECT_FALSE(hasNoSubEl); - // The subname of subObjTWithSubEl doesn't contain the name of a sub element, therefor hasSubEl + // The subname of subObjTWithSubEl doesn't contain the name of a sub element, therefore hasSubEl // should be true EXPECT_TRUE(hasSubEl); } diff --git a/tests/src/Mod/Part/App/PartFeature.cpp b/tests/src/Mod/Part/App/PartFeature.cpp index db20e801df..200e08869e 100644 --- a/tests/src/Mod/Part/App/PartFeature.cpp +++ b/tests/src/Mod/Part/App/PartFeature.cpp @@ -111,7 +111,7 @@ TEST_F(FeaturePartTest, create) // without modifications EXPECT_STREQ(_doc->getObjectName(featureNoDoc), "Vertex"); - // The feature is created in otherDoc, which doesn't have other features and thertherefor the + // The feature is created in otherDoc, which doesn't have other features and thertherefore the // feature's name will be assigned without modifications EXPECT_STREQ(otherDoc->getObjectName(feature), "Vertex"); diff --git a/tests/src/Mod/Part/App/WireJoiner.cpp b/tests/src/Mod/Part/App/WireJoiner.cpp index 2fb72bc585..982f91c4b3 100644 --- a/tests/src/Mod/Part/App/WireJoiner.cpp +++ b/tests/src/Mod/Part/App/WireJoiner.cpp @@ -92,19 +92,19 @@ TEST_F(WireJoinerTest, addShape) wjTS.addShape(wireTS); wjTS.Build(); - // The wire in wjTS is open, therefor to see the effect of wjTS.addShape() we must call + // The wire in wjTS is open, therefore to see the effect of wjTS.addShape() we must call // wjTS.getOpenWires() and put the result in wireTS wjTS.getOpenWires(wireTS, nullptr, false); wjvTS.addShape({edge1TS, edge2TS}); wjvTS.Build(); - // The wire in wjvTS is open, therefor to see the effect of wjvTS.addShape() we must call + // The wire in wjvTS is open, therefore to see the effect of wjvTS.addShape() we must call // wjvTS.getOpenWires() and put the result in wirevTS wjvTS.getOpenWires(wirevTS, nullptr, false); wjvTDS.addShape(edges); wjvTDS.Build(); - // The wire in wjvTDS is closed, therefor to see the effect of wjvTDS.addShape() we can smply + // The wire in wjvTDS is closed, therefore to see the effect of wjvTDS.addShape() we can simply // call wjvTDS.Shape() to replace the shape in wirevTDS wirevTDS.setShape(wjvTDS.Shape()); @@ -452,12 +452,12 @@ TEST_F(WireJoinerTest, setMergeEdges) EXPECT_FALSE(wjNoBuild.IsDone()); // In this case the number of edges is equal to 9 because all the 3 edges intersect the other 2 - // and are therefor split in 3 edges each. + // and are therefore split in 3 edges each. EXPECT_EQ(wireNoMergeEdges.getSubTopoShapes(TopAbs_EDGE).size(), 9); // In this case the number of edges is equal to 6 because, among the 9 produced by // WireJoiner::WireJoinerP::splitEdges(), 3 of them are connected to more than one other edge - // and therefor aren't added by WireJoiner::WireJoinerP::findSuperEdges() + // and therefore aren't added by WireJoiner::WireJoinerP::findSuperEdges() EXPECT_EQ(wireMergeEdges.getSubTopoShapes(TopAbs_EDGE).size(), 6); } @@ -524,7 +524,7 @@ TEST_F(WireJoinerTest, setTolerance) // WireJoiner::getOpenWires() to get the edges, if any, that aren't used to create a closed wire wjNegtol.addShape(edgesNegtol); - // Setting tol to a negative value won't have effect and therefor wjNegtol.pimpl->myTol will + // Setting tol to a negative value won't have effect and therefore wjNegtol.pimpl->myTol will // keep the default value. // It's better also to give a negative value for the argument atol otherwise setTolerance() // will set it to 0.0 @@ -541,17 +541,17 @@ TEST_F(WireJoinerTest, setTolerance) wjtol.getOpenWires(wiretol, nullptr, false); wjNegatol.addShape(edgesNegatol); - // Setting atol to a negative value won't have effect and therefor wjNegatol.pimpl->myAngularTol - // will keep the default value. - // The tol value must be given in any case. + // Setting atol to a negative value won't have effect and therefore + // wjNegatol.pimpl->myAngularTol will keep the default value. The tol value must be given in any + // case. wjNegatol.setTolerance(-0.1, -pi); wjNegatol.Build(); wjNegatol.getOpenWires(wireNegatol, nullptr, false); wjatol.addShape(edgesatol); - // Setting atol to a negative value won't have effect and therefor wjNegatol.pimpl->myAngularTol - // will keep the default value. - // We give also the tol value so that a closed wire can be created. + // Setting atol to a negative value won't have effect and therefore + // wjNegatol.pimpl->myAngularTol will keep the default value. We give also the tol value so that + // a closed wire can be created. wjatol.setTolerance(0.2, pi / 9); wjatol.Build(); wjatol.getOpenWires(wireatol, nullptr, false); @@ -570,7 +570,7 @@ TEST_F(WireJoinerTest, setTolerance) // In this case, as the gap between edge1 and edge3 is smaller than tol, a closed wire can be // created and it contains all the edges added with wjtol.addShape(). EXPECT_EQ(TopoShape(wjtol.Shape()).getSubTopoShapes(TopAbs_EDGE).size(), 3); - // There are no open wires and therefor no edges that create them + // There are no open wires and therefore no edges that create them EXPECT_EQ(wiretol.getSubTopoShapes(TopAbs_EDGE).size(), 0); // In this case, as there's a gap between edge2, edge4 and edge5, no closed wires are created. @@ -580,12 +580,12 @@ TEST_F(WireJoinerTest, setTolerance) // In this case, as the gap between edge2, edge4 and edge5 is smaller than tol, a closed wire // can be created. - // Because of atol, edge4 and edge5 are considerated as duplicates and therefor one of them is + // Because of atol, edge4 and edge5 are considerated as duplicates and therefore one of them is // removed by WireJoiner::WireJoinerP::add(). // The closed wire is then created using all the edges added with wjatol.addShape() except the // removed one EXPECT_EQ(TopoShape(wjatol.Shape()).getSubTopoShapes(TopAbs_EDGE).size(), 3); - // There are no open wires and therefor no edges that create them + // There are no open wires and therefore no edges that create them EXPECT_EQ(wireatol.getSubTopoShapes(TopAbs_EDGE).size(), 0); } @@ -665,7 +665,7 @@ TEST_F(WireJoinerTest, getOpenWires) // Assert - // All the edges added with wjNoOpenWires.addShape() are used to create a closed wire, therefor + // All the edges added with wjNoOpenWires.addShape() are used to create a closed wire, therefore // wireNoOpenWires should be null EXPECT_TRUE(wireNoOpenWires.isNull()); @@ -673,7 +673,7 @@ TEST_F(WireJoinerTest, getOpenWires) // except those ones that are split, and all the edges generated by splitting an edge with // another one. // edge1 and edge2 are left untouched, while edge4 is split in two at the intersection point - // (1.0, 1.0, 0.0), therefor 4 edges. + // (1.0, 1.0, 0.0), therefore 4 edges. EXPECT_EQ(wireOriginal.getSubTopoShapes(TopAbs_EDGE).size(), 4); // In this case wireNoOriginal should contain only the edges generated by splitting one of them @@ -753,7 +753,7 @@ TEST_F(WireJoinerTest, getResultWires) // Assert - // All the edges added with wjNoResultWires.addShape() can't create a closed wire, therefor + // All the edges added with wjNoResultWires.addShape() can't create a closed wire, therefore // wireNoResultWires shouldn't have any edges // It's not possible to get an useful result from wireNoResultWires.isNull() because // WireJoiner::WireJoinerP::compound is always created by @@ -801,7 +801,7 @@ TEST_F(WireJoinerTest, Build) // Assert - // theRange isn't used in WireJoiner::Build() and therefor not attached to any indicator. + // theRange isn't used in WireJoiner::Build() and therefore not attached to any indicator. // For more reference see // https://dev.opencascade.org/doc/occt-7.6.0/refman/html/class_message___progress_range.html // and @@ -878,7 +878,7 @@ TEST_F(WireJoinerTest, Generated) // Assert // There aren't calls to WireJoiner::WireJoinerP::aHistory->AddGenerated() or similar methods in - // WireJoiner::WireJoinerP, therefor nothing is returned by calling + // WireJoiner::WireJoinerP, therefore nothing is returned by calling // WireJoiner::WireJoinerP::aHistory->Generated(). // There's a call to WireJoiner::WireJoinerP::aHistory->Merge() that uses the history produced // by a ShapeFix_Wire object in WireJoiner::WireJoinerP::makeCleanWire() that however looks @@ -921,11 +921,11 @@ TEST_F(WireJoinerTest, IsDeleted) EXPECT_FALSE(wjIsDeleted.IsDeleted(edge2)); EXPECT_FALSE(wjIsDeleted.IsDeleted(edge3)); - // edge4 is a duplicate of edge3 and therefor deleted + // edge4 is a duplicate of edge3 and therefore deleted EXPECT_TRUE(wjIsDeleted.IsDeleted(edge4)); // edge5 is smaller that the smallest shape that can be considered with the given value of - // tolerance and therefor deleted + // tolerance and therefore deleted EXPECT_TRUE(wjIsDeleted.IsDeleted(edge5)); } From 30ce3023fa0f08911af60ad6e74f12ccc1bdf83a Mon Sep 17 00:00:00 2001 From: Luz Paz Date: Sat, 5 Apr 2025 14:26:15 -0400 Subject: [PATCH 153/316] Draft: fix source typo Corrected source variable name so it wouldn't show up in codespell check --- src/Mod/Draft/draftutils/gui_utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Mod/Draft/draftutils/gui_utils.py b/src/Mod/Draft/draftutils/gui_utils.py index 17862bba04..698f5e9481 100644 --- a/src/Mod/Draft/draftutils/gui_utils.py +++ b/src/Mod/Draft/draftutils/gui_utils.py @@ -373,16 +373,16 @@ def get_diffuse_color(objs): if obj.ColoredElements is None: return cols face_num = len(base.Shape.Faces) - for elm, overide in zip(obj.ColoredElements[1], obj.ViewObject.OverrideColorList): + 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 "." in elm: elm0, elm1 = elm.split(".") i = (int(elm0) * face_num) + int(elm1[4:]) - 1 - cols[i] = overide + cols[i] = override else: i = int(elm[4:]) - 1 for j in range(count): - cols[(j * face_num) + i] = overide + cols[(j * face_num) + i] = override return cols elif hasattr(obj, "ElementList"): # LinkGroup @@ -392,10 +392,10 @@ def get_diffuse_color(objs): if obj.ColoredElements is None: cols += sub_cols else: - for elm, overide 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 - sub_cols[i] = overide + sub_cols[i] = override cols += sub_cols return cols else: From e537278f1296211edb90bf1c938dfaebd2626f0d Mon Sep 17 00:00:00 2001 From: Andrea Date: Sat, 5 Apr 2025 20:42:33 +0200 Subject: [PATCH 154/316] Cosmetic Fix Fix double "--" during print configuration : ---- Version: 7.1.9 -- -- Found OpenCASCADE version: 7.8.1 -- -- OpenCASCADE include directory: /usr/include/opencascade -- -- OpenCASCADE shared libraries directory: /usr/lib/x86_64-linux-gnu -- Found OpenGL: /usr/lib/x86_64-linux-gnu/libOpenGL.so -- VTK components: -- Found OpenGL: /usr/lib/x86_64-linux-gnu/libOpenGL.so found components: OpenGL GLX . --- cMake/FindOCC.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cMake/FindOCC.cmake b/cMake/FindOCC.cmake index 6a91e6871b..2b084e3a56 100644 --- a/cMake/FindOCC.cmake +++ b/cMake/FindOCC.cmake @@ -130,7 +130,7 @@ if (OCC_FOUND) else () list(APPEND OCC_LIBRARIES TKDESTEP TKDEIGES TKDEGLTF TKDESTL) endif () - message(STATUS "-- Found OpenCASCADE version: ${OCC_VERSION_STRING}") - message(STATUS "-- OpenCASCADE include directory: ${OCC_INCLUDE_DIR}") - message(STATUS "-- OpenCASCADE shared libraries directory: ${OCC_LIBRARY_DIR}") + message(STATUS "Found OpenCASCADE version: ${OCC_VERSION_STRING}") + message(STATUS " OpenCASCADE include directory: ${OCC_INCLUDE_DIR}") + message(STATUS " OpenCASCADE shared libraries directory: ${OCC_LIBRARY_DIR}") endif () From ceee26765e16e08e826cb9f4ba7eb08a7d978e2d Mon Sep 17 00:00:00 2001 From: Francisco Neves Date: Fri, 28 Mar 2025 19:32:02 +0000 Subject: [PATCH 155/316] Preferences: Fixed a bug in 'Animation curve type' label position Deleted a line in DlgSettingsAdvanced.cpp that made the label move after selecting a animation curve type. Fixes #18376. Signed-off-by: Francisco Neves --- src/Gui/PreferencePages/DlgSettingsAdvanced.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp b/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp index 8000159f39..875f8a4ed2 100644 --- a/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp +++ b/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp @@ -554,7 +554,6 @@ void DlgSettingsAdvanced::setOffset1(qreal t) QPoint pos(width(), 0); this->b1 = width() - label->fontMetrics().boundingRect(label->text()).width() - 5; } - label->move(this->a1 * (1-t) + this->b1 * t, label->y()); } void DlgSettingsAdvanced::onCurveChange(int index) From 9884b67741887264241a586e58055d13a33ddb7e Mon Sep 17 00:00:00 2001 From: MisterMaker Date: Sun, 6 Apr 2025 14:33:52 +0200 Subject: [PATCH 156/316] Gui: Title bar color fix for windows QT 6.5+ Remove dark mode variable --- src/Main/MainGui.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index 1066298cab..8d37610671 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -179,9 +179,6 @@ int main(int argc, char** argv) } argv_.push_back(0); // 0-terminated string } - - // https://www.qt.io/blog/dark-mode-on-windows-11-with-qt-6.5 - _putenv("QT_QPA_PLATFORM=windows:darkmode=1"); #endif // Name and Version of the Application From 79008331b30d098b2c32e59752e24e0705b350bc Mon Sep 17 00:00:00 2001 From: Luz Paz Date: Sun, 6 Apr 2025 08:01:36 -0400 Subject: [PATCH 157/316] Mesh: Fix source typo Modified so it wouldn't show up in codespell results. --- src/Mod/Mesh/App/Mesh.cpp | 12 ++++++------ src/Mod/MeshPart/App/MeshAlgos.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index dffcaaf981..42d551e589 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -952,7 +952,7 @@ void MeshObject::offsetSpecial2(float fSize) Base::Builder3D builder; std::vector PointNormals = _kernel.CalcVertexNormals(); std::vector FaceNormals; - std::set fliped; + std::set flipped; MeshCore::MeshFacetIterator it(_kernel); for (it.Init(); it.More(); it.Next()) { @@ -988,20 +988,20 @@ void MeshObject::offsetSpecial2(float fSize) drawStyle, Base::ColorRGB {1.0F, 0.0F, 0.0F}}; builder.addNode(item); - fliped.insert(it.Position()); + flipped.insert(it.Position()); } } // if there are no flipped triangles -> stop - // int f =fliped.size(); - if (fliped.empty()) { + // int f =flipped.size(); + if (flipped.empty()) { break; } - for (FacetIndex It : fliped) { + for (FacetIndex It : flipped) { alg.CollapseFacet(It); } - fliped.clear(); + flipped.clear(); } alg.Cleanup(); diff --git a/src/Mod/MeshPart/App/MeshAlgos.cpp b/src/Mod/MeshPart/App/MeshAlgos.cpp index 96c5169d5e..573402bfb1 100644 --- a/src/Mod/MeshPart/App/MeshAlgos.cpp +++ b/src/Mod/MeshPart/App/MeshAlgos.cpp @@ -61,7 +61,7 @@ void MeshAlgos::offsetSpecial2(MeshCore::MeshKernel* Mesh, float fSize) Base::Builder3D builder; std::vector PointNormals = Mesh->CalcVertexNormals(); std::vector FaceNormals; - std::set fliped; + std::set flipped; MeshFacetIterator it(*Mesh); for (it.Init(); it.More(); it.Next()) { @@ -98,18 +98,18 @@ void MeshAlgos::offsetSpecial2(MeshCore::MeshKernel* Mesh, float fSize) drawStyle, Base::ColorRGB {1.0F, 0.0F, 0.0F}}; builder.addNode(item); - fliped.insert(it.Position()); + flipped.insert(it.Position()); } } - if (fliped.empty()) { + if (flipped.empty()) { break; } - for (MeshCore::FacetIndex It : fliped) { + for (MeshCore::FacetIndex It : flipped) { alg.CollapseFacet(It); } - fliped.clear(); + flipped.clear(); } alg.Cleanup(); From 95c1db7e3c32b9c0445e24ad64024daea89f442f Mon Sep 17 00:00:00 2001 From: jonzirk76 Date: Thu, 3 Apr 2025 05:13:47 -0400 Subject: [PATCH 158/316] Moved DrawUtil.cpp member functions to DrawViewPart.cpp Updated ownership of member functions & updated headers Removed redundant ownership lines Removed reference to removed ownership line Removed owner from function head static reference removed from header file, function heads updated attempt to fix CosmeticExtension.cpp attempt to fix CosmeticExtension.cpp #2 attempt to fix CosmeticExtension.cpp #3 CosmeticExtension.cpp refactored based on DrawUtil member functions move --- src/Mod/TechDraw/App/CosmeticExtension.cpp | 7 +++-- src/Mod/TechDraw/App/DrawUtil.cpp | 34 ---------------------- src/Mod/TechDraw/App/DrawUtil.h | 4 --- src/Mod/TechDraw/App/DrawViewPart.cpp | 31 ++++++++++++++++++++ src/Mod/TechDraw/App/DrawViewPart.h | 4 +++ 5 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/Mod/TechDraw/App/CosmeticExtension.cpp b/src/Mod/TechDraw/App/CosmeticExtension.cpp index 0d9c9ec446..6f835d0ce1 100644 --- a/src/Mod/TechDraw/App/CosmeticExtension.cpp +++ b/src/Mod/TechDraw/App/CosmeticExtension.cpp @@ -66,16 +66,17 @@ TechDraw::DrawViewPart* CosmeticExtension::getOwner() void CosmeticExtension::deleteCosmeticElements(std::vector removables) { // Base::Console().Message("CEx::deleteCosmeticElements(%d removables)\n", removables.size()); + DrawViewPart* viewPart = getOwner(); for (auto& name : removables) { if (DU::getGeomTypeFromName(name) == "Vertex" && - DU::isCosmeticVertex(getOwner(), name)) { + viewPart->isCosmeticVertex(name)) { CosmeticVertex* vert = getCosmeticVertexBySelection(name); removeCosmeticVertex(vert->getTagAsString()); continue; } if (DU::getGeomTypeFromName(name) == "Edge" && - ( DU::isCosmeticEdge(getOwner(), name) || - DU::isCenterLine(getOwner(), name) ) ) { + ( viewPart->isCosmeticEdge(name) || + viewPart->isCenterLine(name))) { CosmeticEdge* edge = getCosmeticEdgeBySelection(name); if (edge) { // if not edge, something has gone very wrong! diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index b3ca7edba7..b09ab5d22f 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -1859,40 +1859,6 @@ std::string DrawUtil::translateArbitrary(std::string context, std::string baseNa return qTranslated.toStdString() + suffix; } -// true if owner->element is a cosmetic vertex -bool DrawUtil::isCosmeticVertex(App::DocumentObject* owner, std::string element) -{ - auto ownerView = static_cast(owner); - auto vertexIndex = DrawUtil::getIndexFromName(element); - auto vertex = ownerView->getProjVertexByIndex(vertexIndex); - if (vertex) { - return vertex->getCosmetic(); - } - return false; -} - -// true if owner->element is a cosmetic edge -bool DrawUtil::isCosmeticEdge(App::DocumentObject* owner, std::string element) -{ - auto ownerView = static_cast(owner); - auto edge = ownerView->getEdge(element); - if (edge && edge->source() == SourceType::COSMETICEDGE && edge->getCosmetic()) { - return true; - } - return false; -} - -// true if owner->element is a center line -bool DrawUtil::isCenterLine(App::DocumentObject* owner, std::string element) -{ - auto ownerView = static_cast(owner); - auto edge = ownerView->getEdge(element); - if (edge && edge->source() == SourceType::CENTERLINE && edge->getCosmetic()) { - return true; - } - return false; -} - //! convert a filespec (string) containing '\' to only use '/'. //! prevents situation where '\' is interpreted as an escape of the next character in Python //! commands. diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 95e61017e4..bcded6a3c5 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -247,10 +247,6 @@ public: static std::string translateArbitrary(std::string context, std::string baseName, std::string uniqueName); - static bool isCosmeticVertex(App::DocumentObject* owner, std::string element); - static bool isCosmeticEdge(App::DocumentObject* owner, std::string element); - static bool isCenterLine(App::DocumentObject* owner, std::string element); - static Base::Vector3d toAppSpace(const DrawViewPart& dvp, const Base::Vector3d& inPoint); static Base::Vector3d toAppSpace(const DrawViewPart& dvp, const QPointF& inPoint); diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index dcc6a31333..48ef38fde2 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -1501,6 +1501,37 @@ void DrawViewPart::handleChangedPropertyType(Base::XMLReader &reader, const char } } +// true if owner->element is a cosmetic vertex +bool DrawViewPart::isCosmeticVertex(const std::string& element) +{ + auto vertexIndex = DrawUtil::getIndexFromName(element); + auto vertex = getProjVertexByIndex(vertexIndex); + if (vertex) { + return vertex->getCosmetic(); + } + return false; +} + +// true if owner->element is a cosmetic edge +bool DrawViewPart::isCosmeticEdge(const std::string& element) +{ + auto edge = getEdge(element); + if (edge && edge->source() == SourceType::COSMETICEDGE && edge->getCosmetic()) { + return true; + } + return false; +} + +// true if owner->element is a center line +bool DrawViewPart::isCenterLine(const std::string& element) +{ + auto edge = getEdge(element); + if (edge && edge->source() == SourceType::CENTERLINE && edge->getCosmetic()) { + return true; + } + return false; +} + // debugging ---------------------------------------------------------------------------- void DrawViewPart::dumpVerts(std::string text) diff --git a/src/Mod/TechDraw/App/DrawViewPart.h b/src/Mod/TechDraw/App/DrawViewPart.h index 71f5da4b6e..c1bf992e5c 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.h +++ b/src/Mod/TechDraw/App/DrawViewPart.h @@ -239,6 +239,10 @@ public: virtual bool waitingForResult() const; void progressValueChanged(int v); + bool isCosmeticVertex(const std::string& element); + bool isCosmeticEdge(const std::string& element); + bool isCenterLine(const std::string& element); + public Q_SLOTS: void onHlrFinished(void); void onFacesFinished(void); From 6b5030f391a85de0b41de86dc63e855c4f6c13d6 Mon Sep 17 00:00:00 2001 From: bofdahof <172177156+bofdahof@users.noreply.github.com> Date: Tue, 24 Dec 2024 12:38:38 +1000 Subject: [PATCH 159/316] App: constify variables in Application class --- src/App/Application.cpp | 109 +++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 0f3fce5d17..bf52ffd19f 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -514,7 +514,7 @@ Document* Application::newDocument(const char * proposedName, const char * propo bool Application::closeDocument(const char* name) { - auto pos = DocMap.find( name ); + const auto pos = DocMap.find( name ); if (pos == DocMap.end()) // no such document return false; @@ -525,9 +525,10 @@ bool Application::closeDocument(const char* name) signalDeleteDocument(*pos->second); // For exception-safety use a smart pointer - if (_pActiveDoc == pos->second) + if (_pActiveDoc == pos->second) { setActiveDocument(static_cast(nullptr)); - std::unique_ptr delDoc (pos->second); + } + const std::unique_ptr delDoc (pos->second); DocMap.erase( pos ); DocFileMap.erase(Base::FileInfo(delDoc->FileName.getValue()).filePath()); @@ -615,7 +616,7 @@ int Application::addPendingDocument(const char *FileName, const char *objName, b assert(!Base::Tools::isNullOrEmpty(objName)); if(!_docReloadAttempts[FileName].emplace(objName).second) return -1; - auto ret = _pendingDocMap.emplace(FileName,std::vector()); + const auto ret = _pendingDocMap.emplace(FileName,std::vector()); ret.first->second.emplace_back(objName); if(ret.second) { _pendingDocs.emplace_back(ret.first->first.c_str()); @@ -675,28 +676,30 @@ Document* Application::openDocument(const char * FileName, DocumentInitFlags ini Document *Application::getDocumentByPath(const char *path, PathMatchMode checkCanonical) const { if(Base::Tools::isNullOrEmpty(path)) return nullptr; - if(DocFileMap.empty()) { + if (DocFileMap.empty()) { for(const auto &v : DocMap) { const auto &file = v.second->FileName.getStrValue(); if(!file.empty()) DocFileMap[Base::FileInfo(file.c_str()).filePath()] = v.second; } } - auto it = DocFileMap.find(Base::FileInfo(path).filePath()); + const auto it = DocFileMap.find(Base::FileInfo(path).filePath()); if(it != DocFileMap.end()) return it->second; - if (checkCanonical == PathMatchMode::MatchAbsolute) + if (checkCanonical == PathMatchMode::MatchAbsolute) { return nullptr; + } - std::string filepath = Base::FileInfo(path).filePath(); - QString canonicalPath = QFileInfo(QString::fromUtf8(path)).canonicalFilePath(); + const std::string filepath = Base::FileInfo(path).filePath(); + const QString canonicalPath = QFileInfo(QString::fromUtf8(path)).canonicalFilePath(); for (const auto &v : DocMap) { QFileInfo fi(QString::fromUtf8(v.second->FileName.getValue())); if (canonicalPath == fi.canonicalFilePath()) { - if (checkCanonical == PathMatchMode::MatchCanonical) + if (checkCanonical == PathMatchMode::MatchCanonical) { return v.second; - bool samePath = (canonicalPath == QString::fromUtf8(filepath.c_str())); + } + const bool samePath = (canonicalPath == QString::fromUtf8(filepath.c_str())); FC_WARN("Identical physical path '" << canonicalPath.toUtf8().constData() << "'\n" << (samePath?"":" for file '") << (samePath?"":filepath.c_str()) << (samePath?"":"'\n") << " with existing document '" << v.second->Label.getValue() @@ -1038,7 +1041,7 @@ void Application::setActiveDocumentNoSignal(Document* pDoc) // make sure that the active document is set in case no GUI is up if (pDoc) { Base::PyGILStateLocker lock; - Py::Object active(pDoc->getPyObject(), true); + const Py::Object active(pDoc->getPyObject(), true); Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"), active); } else { @@ -1093,9 +1096,9 @@ Application::TransactionSignaller::~TransactionSignaller() { int64_t Application::applicationPid() { static int64_t randomNumber = []() { - auto tp = std::chrono::high_resolution_clock::now(); - auto dur = tp.time_since_epoch(); - auto seed = dur.count(); + const auto tp = std::chrono::high_resolution_clock::now(); + const auto dur = tp.time_since_epoch(); + const auto seed = dur.count(); std::mt19937 generator(static_cast(seed)); constexpr int64_t minValue {1}; constexpr int64_t maxValue {1000000}; @@ -1162,7 +1165,7 @@ std::string Application::getResourceDir() // #6892: Conda may inject null characters => remove them using c_str() std::string path = std::string(RESOURCEDIR).c_str(); path += PATHSEP; - QDir dir(QString::fromStdString(path)); + const QDir dir(QString::fromStdString(path)); if (dir.isAbsolute()) return path; return mConfig["AppHomePath"] + path; @@ -1176,7 +1179,7 @@ std::string Application::getLibraryDir() #ifdef LIBRARYDIR // #6892: Conda may inject null characters => remove them using c_str() std::string path = std::string(LIBRARYDIR).c_str(); - QDir dir(QString::fromStdString(path)); + const QDir dir(QString::fromStdString(path)); if (dir.isAbsolute()) return path; return mConfig["AppHomePath"] + path; @@ -1191,7 +1194,7 @@ std::string Application::getHelpDir() // #6892: Conda may inject null characters => remove them using c_str() std::string path = std::string(DOCDIR).c_str(); path += PATHSEP; - QDir dir(QString::fromStdString(path)); + const QDir dir(QString::fromStdString(path)); if (dir.isAbsolute()) return path; return mConfig["AppHomePath"] + path; @@ -1204,13 +1207,13 @@ int Application::checkLinkDepth(int depth, MessageOption option) { if (_objCount < 0) { _objCount = 0; - for (auto &v : DocMap) { + for (const auto &v : DocMap) { _objCount += v.second->countObjects(); } } if (depth > _objCount + 2) { - auto msg = "Link recursion limit reached. " + const auto msg = "Link recursion limit reached. " "Please check for cyclic reference."; switch (option) { case MessageOption::Quiet: @@ -1238,7 +1241,7 @@ std::set Application::getLinksTo( } } else { std::set docs; - for(auto o : obj->getInList()) { + for (const auto o : obj->getInList()) { if(o && o->isAttachedToDocument() && docs.insert(o->getDocument()).second) { o->getDocument()->getLinksTo(links,obj,options,maxCount); if(maxCount && static_cast(links.size())>=maxCount) @@ -1265,7 +1268,7 @@ ParameterManager & Application::GetUserParameter() ParameterManager * Application::GetParameterSet(const char* sName) const { - auto it = mpcPramManager.find(sName); + const auto it = mpcPramManager.find(sName); return it != mpcPramManager.end() ? it->second : nullptr; } @@ -1278,7 +1281,7 @@ Application::GetParameterSetList() const void Application::AddParameterSet(const char* sName) { - auto it = mpcPramManager.find(sName); + const auto it = mpcPramManager.find(sName); if ( it != mpcPramManager.end() ) return; mpcPramManager[sName] = ParameterManager::Create(); @@ -1286,7 +1289,7 @@ void Application::AddParameterSet(const char* sName) void Application::RemoveParameterSet(const char* sName) { - auto it = mpcPramManager.find(sName); + const auto it = mpcPramManager.find(sName); // Must not delete user or system parameter if ( it == mpcPramManager.end() || it->second == _pcUserParamMngr || it->second == _pcSysParamMngr ) return; @@ -1295,9 +1298,9 @@ void Application::RemoveParameterSet(const char* sName) Base::Reference Application::GetParameterGroupByPath(const char* sName) { - std::string cName = sName,cTemp; + std::string cName = sName, cTemp; - std::string::size_type pos = cName.find(':'); + const std::string::size_type pos = cName.find(':'); // is there a path separator ? if (pos == std::string::npos) { @@ -1308,7 +1311,7 @@ Base::Reference Application::GetParameterGroupByPath(const char* cName.erase(0,pos+1); // test if name is valid - auto It = mpcPramManager.find(cTemp); + const auto It = mpcPramManager.find(cTemp); if (It == mpcPramManager.end()) throw Base::ValueError("Application::GetParameterGroupByPath() unknown parameter set name specified"); @@ -1324,8 +1327,8 @@ void Application::addImportType(const char* Type, const char* ModuleName) // Extract each filetype from 'Type' literal std::string::size_type pos = item.filter.find("*."); while ( pos != std::string::npos ) { - std::string::size_type next = item.filter.find_first_of(" )", pos+1); - std::string::size_type len = next-pos-2; + const std::string::size_type next = item.filter.find_first_of(" )", pos + 1); + const std::string::size_type len = next-pos-2; std::string type = item.filter.substr(pos+2,len); item.types.push_back(std::move(type)); pos = item.filter.find("*.", next); @@ -1449,8 +1452,8 @@ void Application::addExportType(const char* Type, const char* ModuleName) // Extract each filetype from 'Type' literal std::string::size_type pos = item.filter.find("*."); while ( pos != std::string::npos ) { - std::string::size_type next = item.filter.find_first_of(" )", pos+1); - std::string::size_type len = next-pos-2; + const std::string::size_type next = item.filter.find_first_of(" )", pos + 1); + const std::string::size_type len = next-pos-2; std::string type = item.filter.substr(pos+2,len); item.types.push_back(std::move(type)); pos = item.filter.find("*.", next); @@ -2782,7 +2785,7 @@ void Application::initConfig(int argc, char ** argv) void Application::SaveEnv(const char* s) { - char *c = getenv(s); + const char *c = getenv(s); if (c) mConfig[s] = c; } @@ -2801,16 +2804,15 @@ void Application::initApplication() Application::_pcSingleton = new Application(mConfig); // set up Unit system default - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + const ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/Units"); Base::UnitsApi::setSchema(static_cast(hGrp->GetInt("UserSchema", 0))); Base::UnitsApi::setDecimals(static_cast(hGrp->GetInt("Decimals", Base::UnitsApi::getDecimals()))); // In case we are using fractional inches, get user setting for min unit - int denom = static_cast(hGrp->GetInt("FracInch", Base::QuantityFormat::getDefaultDenominator())); + const int denom = static_cast(hGrp->GetInt("FracInch", Base::QuantityFormat::getDefaultDenominator())); Base::QuantityFormat::setDefaultDenominator(denom); - #if defined (_DEBUG) Base::Console().Log("Application is built with debug information\n"); #endif @@ -2915,8 +2917,8 @@ std::list Application::processFiles(const std::list& f void Application::processCmdLineFiles() { // process files passed to command line - std::list files = getCmdLineFiles(); - std::list processed = processFiles(files); + const std::list files = getCmdLineFiles(); + const std::list processed = processFiles(files); if (files.empty()) { if (mConfig["RunMode"] == "Exit") @@ -2925,7 +2927,7 @@ void Application::processCmdLineFiles() else if (processed.empty() && files.size() == 1 && mConfig["RunMode"] == "Cmd") { // In case we are in console mode and the argument is not a file but Python code // then execute it. This is to behave like the standard Python executable. - Base::FileInfo file(files.front()); + const Base::FileInfo file(files.front()); if (!file.exists()) { Base::Interpreter().runString(files.front().c_str()); mConfig["RunMode"] = "Exit"; @@ -2933,15 +2935,15 @@ void Application::processCmdLineFiles() } const std::map& cfg = Application::Config(); - auto it = cfg.find("SaveFile"); + const auto it = cfg.find("SaveFile"); if (it != cfg.end()) { std::string output = it->second; output = Base::Tools::escapeEncodeFilename(output); - Base::FileInfo fi(output); - std::string ext = fi.extension(); + const Base::FileInfo fi(output); + const std::string ext = fi.extension(); try { - std::vector mods = App::GetApplication().getExportModules(ext.c_str()); + const std::vector mods = App::GetApplication().getExportModules(ext.c_str()); if (!mods.empty()) { Base::Interpreter().loadModule(mods.front().c_str()); Base::Interpreter().runStringArg("import %s",mods.front().c_str()); @@ -2986,7 +2988,7 @@ void Application::runApplication() void Application::logStatus() { - std::string time_str = boost::posix_time::to_simple_string( + const std::string time_str = boost::posix_time::to_simple_string( boost::posix_time::second_clock::local_time()); Base::Console().Log("Time = %s\n", time_str.c_str()); @@ -3034,14 +3036,14 @@ void Application::LoadParameters() if (_pcUserParamMngr->LoadOrCreateDocument() && mConfig["Verbose"] != "Strict") { // The user parameter file doesn't exist. When an alternative parameter file is offered // this will be used. - auto it = mConfig.find("UserParameterTemplate"); + const auto it = mConfig.find("UserParameterTemplate"); if (it != mConfig.end()) { QString path = QString::fromUtf8(it->second.c_str()); if (QDir(path).isRelative()) { - QString home = QString::fromUtf8(mConfig["AppHomePath"].c_str()); + const QString home = QString::fromUtf8(mConfig["AppHomePath"].c_str()); path = QFileInfo(QDir(home), path).absoluteFilePath(); } - QFileInfo fi(path); + const QFileInfo fi(path); if (fi.exists()) { _pcUserParamMngr->LoadDocument(path.toUtf8().constData()); } @@ -3097,7 +3099,7 @@ QString getUserHome() struct passwd *result; const std::size_t buflen = 16384; std::vector buffer(buflen); - int error = getpwuid_r(getuid(), &pwd, buffer.data(), buffer.size(), &result); + const int error = getpwuid_r(getuid(), &pwd, buffer.data(), buffer.size(), &result); Q_UNUSED(error) if (!result) throw Base::RuntimeError("Getting HOME path from system failed!"); @@ -3225,14 +3227,14 @@ std::filesystem::path findPath(const QString& stdHome, const QString& customHome */ std::tuple getCustomPaths() { - QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); + const QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); QString userHome = env.value(QStringLiteral("FREECAD_USER_HOME")); QString userData = env.value(QStringLiteral("FREECAD_USER_DATA")); QString userTemp = env.value(QStringLiteral("FREECAD_USER_TEMP")); auto toNativePath = [](QString& path) { if (!path.isEmpty()) { - QDir dir(path); + const QDir dir(path); if (dir.exists()) path = QDir::toNativeSeparators(dir.canonicalPath()); else @@ -3252,9 +3254,9 @@ std::tuple getCustomPaths() // if FREECAD_USER_HOME is set but not FREECAD_USER_TEMP if (!userHome.isEmpty() && userTemp.isEmpty()) { - QDir dir(userHome); + const QDir dir(userHome); dir.mkdir(QStringLiteral("temp")); - QFileInfo fi(dir, QStringLiteral("temp")); + const QFileInfo fi(dir, QStringLiteral("temp")); userTemp = fi.absoluteFilePath(); } @@ -3484,11 +3486,12 @@ std::string Application::FindHomePath(const char* sCall) if (const auto buf = new char[++sz]; _NSGetExecutablePath(buf, &sz) == 0) { char resolved[PATH_MAX]; - char* path = realpath(buf, resolved); + const char* path = realpath(buf, resolved); delete [] buf; if (path) { - std::string Call(resolved), TempHomePath; + const std::string Call(resolved); + std::string TempHomePath; std::string::size_type pos = Call.find_last_of(PATHSEP); TempHomePath.assign(Call,0,pos); pos = TempHomePath.find_last_of(PATHSEP); From 7013f913b6bfd8221b02ab7e759f910f335d02eb Mon Sep 17 00:00:00 2001 From: bofdahof <172177156+bofdahof@users.noreply.github.com> Date: Tue, 24 Dec 2024 12:29:03 +1000 Subject: [PATCH 160/316] App: remove redundant qualifier from Application class --- src/App/Application.cpp | 116 ++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index bf52ffd19f..8fdaf9f2d2 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -177,8 +177,8 @@ namespace sp = std::placeholders; // Application //========================================================================== -Base::Reference App::Application::_pcSysParamMngr; -Base::Reference App::Application::_pcUserParamMngr; +Base::Reference Application::_pcSysParamMngr; +Base::Reference Application::_pcUserParamMngr; Base::ConsoleObserverStd *Application::_pConsoleObserverStd = nullptr; Base::ConsoleObserverFile *Application::_pConsoleObserverFile = nullptr; @@ -475,25 +475,25 @@ Document* Application::newDocument(const char * proposedName, const char * propo //NOLINTBEGIN // clang-format off // connect the signals to the application for the new document - doc->signalBeforeChange.connect(std::bind(&App::Application::slotBeforeChangeDocument, this, sp::_1, sp::_2)); - doc->signalChanged.connect(std::bind(&App::Application::slotChangedDocument, this, sp::_1, sp::_2)); - doc->signalNewObject.connect(std::bind(&App::Application::slotNewObject, this, sp::_1)); - doc->signalDeletedObject.connect(std::bind(&App::Application::slotDeletedObject, this, sp::_1)); - doc->signalBeforeChangeObject.connect(std::bind(&App::Application::slotBeforeChangeObject, this, sp::_1, sp::_2)); - doc->signalChangedObject.connect(std::bind(&App::Application::slotChangedObject, this, sp::_1, sp::_2)); - doc->signalRelabelObject.connect(std::bind(&App::Application::slotRelabelObject, this, sp::_1)); - doc->signalActivatedObject.connect(std::bind(&App::Application::slotActivatedObject, this, sp::_1)); - doc->signalUndo.connect(std::bind(&App::Application::slotUndoDocument, this, sp::_1)); - doc->signalRedo.connect(std::bind(&App::Application::slotRedoDocument, this, sp::_1)); - doc->signalRecomputedObject.connect(std::bind(&App::Application::slotRecomputedObject, this, sp::_1)); - doc->signalRecomputed.connect(std::bind(&App::Application::slotRecomputed, this, sp::_1)); - doc->signalBeforeRecompute.connect(std::bind(&App::Application::slotBeforeRecompute, this, sp::_1)); - doc->signalOpenTransaction.connect(std::bind(&App::Application::slotOpenTransaction, this, sp::_1, sp::_2)); - doc->signalCommitTransaction.connect(std::bind(&App::Application::slotCommitTransaction, this, sp::_1)); - doc->signalAbortTransaction.connect(std::bind(&App::Application::slotAbortTransaction, this, sp::_1)); - doc->signalStartSave.connect(std::bind(&App::Application::slotStartSaveDocument, this, sp::_1, sp::_2)); - doc->signalFinishSave.connect(std::bind(&App::Application::slotFinishSaveDocument, this, sp::_1, sp::_2)); - doc->signalChangePropertyEditor.connect(std::bind(&App::Application::slotChangePropertyEditor, this, sp::_1, sp::_2)); + doc->signalBeforeChange.connect(std::bind(&Application::slotBeforeChangeDocument, this, sp::_1, sp::_2)); + doc->signalChanged.connect(std::bind(&Application::slotChangedDocument, this, sp::_1, sp::_2)); + doc->signalNewObject.connect(std::bind(&Application::slotNewObject, this, sp::_1)); + doc->signalDeletedObject.connect(std::bind(&Application::slotDeletedObject, this, sp::_1)); + doc->signalBeforeChangeObject.connect(std::bind(&Application::slotBeforeChangeObject, this, sp::_1, sp::_2)); + doc->signalChangedObject.connect(std::bind(&Application::slotChangedObject, this, sp::_1, sp::_2)); + doc->signalRelabelObject.connect(std::bind(&Application::slotRelabelObject, this, sp::_1)); + doc->signalActivatedObject.connect(std::bind(&Application::slotActivatedObject, this, sp::_1)); + doc->signalUndo.connect(std::bind(&Application::slotUndoDocument, this, sp::_1)); + doc->signalRedo.connect(std::bind(&Application::slotRedoDocument, this, sp::_1)); + doc->signalRecomputedObject.connect(std::bind(&Application::slotRecomputedObject, this, sp::_1)); + doc->signalRecomputed.connect(std::bind(&Application::slotRecomputed, this, sp::_1)); + doc->signalBeforeRecompute.connect(std::bind(&Application::slotBeforeRecompute, this, sp::_1)); + doc->signalOpenTransaction.connect(std::bind(&Application::slotOpenTransaction, this, sp::_1, sp::_2)); + doc->signalCommitTransaction.connect(std::bind(&Application::slotCommitTransaction, this, sp::_1)); + doc->signalAbortTransaction.connect(std::bind(&Application::slotAbortTransaction, this, sp::_1)); + doc->signalStartSave.connect(std::bind(&Application::slotStartSaveDocument, this, sp::_1, sp::_2)); + doc->signalFinishSave.connect(std::bind(&Application::slotFinishSaveDocument, this, sp::_1, sp::_2)); + doc->signalChangePropertyEditor.connect(std::bind(&Application::slotChangePropertyEditor, this, sp::_1, sp::_2)); // clang-format on //NOLINTEND @@ -548,7 +548,7 @@ void Application::closeAllDocuments() closeDocument(pos->first.c_str()); } -App::Document* Application::getDocument(const char *Name) const +Document* Application::getDocument(const char *Name) const { const auto pos = DocMap.find(Name); @@ -559,7 +559,7 @@ App::Document* Application::getDocument(const char *Name) const return pos->second; } -const char * Application::getDocumentName(const App::Document* doc) const +const char * Application::getDocumentName(const Document* doc) const { for (const auto & it : DocMap) { if (it.second == doc) { @@ -570,9 +570,9 @@ const char * Application::getDocumentName(const App::Document* doc) const return nullptr; } -std::vector Application::getDocuments() const +std::vector Application::getDocuments() const { - std::vector docs; + std::vector docs; docs.reserve(DocMap.size()); for (const auto & it : DocMap) docs.push_back(it.second); @@ -745,7 +745,7 @@ std::vector Application::openDocuments(const std::vector int pass = 0; do { - std::set newDocs; + std::set newDocs; for (std::size_t count=0;; ++count) { std::string name = std::move(_pendingDocs.front()); _pendingDocs.pop_front(); @@ -931,8 +931,8 @@ Document* Application::openDocumentPrivate(const char * FileName, // Before creating a new document we check whether the document is already open auto doc = getDocumentByPath(File.filePath().c_str(), PathMatchMode::MatchCanonicalWarning); if(doc) { - if(doc->testStatus(App::Document::PartialDoc) - || doc->testStatus(App::Document::PartialRestore)) { + if(doc->testStatus(Document::PartialDoc) + || doc->testStatus(Document::PartialRestore)) { // Here means a document is already partially loaded, but the document // is requested again, either partial or not. We must check if the // document contains the required object @@ -945,7 +945,7 @@ Document* Application::openDocumentPrivate(const char * FileName, bool reopen = false; for(const auto &name : objNames) { auto obj = doc->getObject(name.c_str()); - if(!obj || obj->testStatus(App::PartialObject)) { + if(!obj || obj->testStatus(PartialObject)) { reopen = true; // NOTE: We are about to reload this document with // extra objects. However, it is possible to repeat @@ -1121,7 +1121,7 @@ std::string Application::getExecutableName() std::string Application::getNameWithVersion() { auto appname = QCoreApplication::applicationName().toStdString(); - auto config = App::Application::Config(); + auto config = Application::Config(); auto major = config["BuildVersionMajor"]; auto minor = config["BuildVersionMinor"]; auto point = config["BuildVersionPoint"]; @@ -1570,54 +1570,54 @@ std::map Application::getExportFilters() const //************************************************************************** // signaling -void Application::slotBeforeChangeDocument(const App::Document& doc, const Property& prop) +void Application::slotBeforeChangeDocument(const Document& doc, const Property& prop) { this->signalBeforeChangeDocument(doc, prop); } -void Application::slotChangedDocument(const App::Document& doc, const Property& prop) +void Application::slotChangedDocument(const Document& doc, const Property& prop) { this->signalChangedDocument(doc, prop); } -void Application::slotNewObject(const App::DocumentObject& obj) +void Application::slotNewObject(const DocumentObject& obj) { this->signalNewObject(obj); _objCount = -1; } -void Application::slotDeletedObject(const App::DocumentObject& obj) +void Application::slotDeletedObject(const DocumentObject& obj) { this->signalDeletedObject(obj); _objCount = -1; } -void Application::slotBeforeChangeObject(const App::DocumentObject& obj, const App::Property& prop) +void Application::slotBeforeChangeObject(const DocumentObject& obj, const Property& prop) { this->signalBeforeChangeObject(obj, prop); } -void Application::slotChangedObject(const App::DocumentObject& obj, const App::Property& prop) +void Application::slotChangedObject(const DocumentObject& obj, const Property& prop) { this->signalChangedObject(obj, prop); } -void Application::slotRelabelObject(const App::DocumentObject& obj) +void Application::slotRelabelObject(const DocumentObject& obj) { this->signalRelabelObject(obj); } -void Application::slotActivatedObject(const App::DocumentObject& obj) +void Application::slotActivatedObject(const DocumentObject& obj) { this->signalActivatedObject(obj); } -void Application::slotUndoDocument(const App::Document& doc) +void Application::slotUndoDocument(const Document& doc) { this->signalUndoDocument(doc); } -void Application::slotRedoDocument(const App::Document& doc) +void Application::slotRedoDocument(const Document& doc) { this->signalRedoDocument(doc); } @@ -1652,18 +1652,18 @@ void Application::slotAbortTransaction(const Document& doc) this->signalAbortTransaction(doc); } -void Application::slotStartSaveDocument(const App::Document& doc, const std::string& filename) +void Application::slotStartSaveDocument(const Document& doc, const std::string& filename) { this->signalStartSaveDocument(doc, filename); } -void Application::slotFinishSaveDocument(const App::Document& doc, const std::string& filename) +void Application::slotFinishSaveDocument(const Document& doc, const std::string& filename) { DocFileMap.clear(); this->signalFinishSaveDocument(doc, filename); } -void Application::slotChangePropertyEditor(const App::Document& doc, const App::Property& prop) +void Application::slotChangePropertyEditor(const Document& doc, const Property& prop) { this->signalChangePropertyEditor(doc, prop); } @@ -2546,24 +2546,24 @@ void Application::initConfig(int argc, char ** argv) // Version of the application extracted from SubWCRef into src/Build/Version.h // We only set these keys if not yet defined. Therefore it suffices to search // only for 'BuildVersionMajor'. - if (App::Application::Config().find("BuildVersionMajor") == App::Application::Config().end()) { + if (Application::Config().find("BuildVersionMajor") == Application::Config().end()) { std::stringstream str; str << FCVersionMajor << "." << FCVersionMinor << "." << FCVersionPoint; - App::Application::Config()["ExeVersion" ] = str.str(); - App::Application::Config()["BuildVersionMajor" ] = FCVersionMajor; - App::Application::Config()["BuildVersionMinor" ] = FCVersionMinor; - App::Application::Config()["BuildVersionPoint" ] = FCVersionPoint; - App::Application::Config()["BuildVersionSuffix" ] = FCVersionSuffix; - App::Application::Config()["BuildRevision" ] = FCRevision; - App::Application::Config()["BuildRepositoryURL" ] = FCRepositoryURL; - App::Application::Config()["BuildRevisionDate" ] = FCRevisionDate; + Application::Config()["ExeVersion" ] = str.str(); + Application::Config()["BuildVersionMajor" ] = FCVersionMajor; + Application::Config()["BuildVersionMinor" ] = FCVersionMinor; + Application::Config()["BuildVersionPoint" ] = FCVersionPoint; + Application::Config()["BuildVersionSuffix" ] = FCVersionSuffix; + Application::Config()["BuildRevision" ] = FCRevision; + Application::Config()["BuildRepositoryURL" ] = FCRepositoryURL; + Application::Config()["BuildRevisionDate" ] = FCRevisionDate; #if defined(FCRepositoryHash) - App::Application::Config()["BuildRevisionHash" ] = FCRepositoryHash; + Application::Config()["BuildRevisionHash" ] = FCRepositoryHash; #endif #if defined(FCRepositoryBranch) - App::Application::Config()["BuildRevisionBranch"] = FCRepositoryBranch; + Application::Config()["BuildRevisionBranch"] = FCRepositoryBranch; #endif } @@ -2577,7 +2577,7 @@ void Application::initConfig(int argc, char ** argv) if (fi.exists() && brand.readFile(fi.absoluteFilePath())) { Branding::XmlConfig cfg = brand.getUserDefines(); for (Branding::XmlConfig::iterator it = cfg.begin(); it != cfg.end(); ++it) { - App::Application::Config()[it.key()] = it.value(); + Application::Config()[it.key()] = it.value(); } } @@ -2804,7 +2804,7 @@ void Application::initApplication() Application::_pcSingleton = new Application(mConfig); // set up Unit system default - const ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + const ParameterGrp::handle hGrp = GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/Units"); Base::UnitsApi::setSchema(static_cast(hGrp->GetInt("UserSchema", 0))); Base::UnitsApi::setDecimals(static_cast(hGrp->GetInt("Decimals", Base::UnitsApi::getDecimals()))); @@ -2883,7 +2883,7 @@ std::list Application::processFiles(const std::list& f } else { std::string ext = file.extension(); - std::vector mods = App::GetApplication().getImportModules(ext.c_str()); + std::vector mods = GetApplication().getImportModules(ext.c_str()); if (!mods.empty()) { std::string escapedstr = Base::Tools::escapedUnicodeFromUtf8(file.filePath().c_str()); escapedstr = Base::Tools::escapeEncodeFilename(escapedstr); @@ -2943,7 +2943,7 @@ void Application::processCmdLineFiles() const Base::FileInfo fi(output); const std::string ext = fi.extension(); try { - const std::vector mods = App::GetApplication().getExportModules(ext.c_str()); + const std::vector mods = GetApplication().getExportModules(ext.c_str()); if (!mods.empty()) { Base::Interpreter().loadModule(mods.front().c_str()); Base::Interpreter().runStringArg("import %s",mods.front().c_str()); From acd40ce725fe0016ef4c27a1bc81c9c547f842aa Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Mon, 7 Apr 2025 08:28:02 +0200 Subject: [PATCH 161/316] Gui: Fix operator mistake in previous c++constant refactoring --- src/Gui/SoDatumLabel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index 928284e67f..ba39d4f4e0 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -965,7 +965,7 @@ void SoDatumLabel::generatePrimitives(SoAction * action) { // Initialisation check (needs something more sensible) prevents an infinite loop bug constexpr float floatEpsilon = std::numeric_limits::epsilon(); - if (this->imgHeight <= floatEpsilon | this->imgWidth <= floatEpsilon) { + if (this->imgHeight <= floatEpsilon || this->imgWidth <= floatEpsilon) { return; } From 2aba9a86ceb0f900f6f40efdf7dec8d52b33edeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Br=C3=A6strup=20Sayoc?= Date: Wed, 2 Apr 2025 16:05:05 +0200 Subject: [PATCH 162/316] TechDraw: fix wrong color on edges Fixes #20561 --- src/Mod/TechDraw/Gui/QGIEdge.cpp | 5 ++--- src/Mod/TechDraw/Gui/TaskCenterLine.cpp | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Mod/TechDraw/Gui/QGIEdge.cpp b/src/Mod/TechDraw/Gui/QGIEdge.cpp index e900685afb..ef198f2520 100644 --- a/src/Mod/TechDraw/Gui/QGIEdge.cpp +++ b/src/Mod/TechDraw/Gui/QGIEdge.cpp @@ -80,10 +80,9 @@ void QGIEdge::setPrettyNormal() { // Base::Console().Message("QGIE::setPrettyNormal()\n"); if (isHiddenEdge) { m_pen.setColor(getHiddenColor()); - } else { - m_pen.setColor(getNormalColor()); + return; } - //should call QGIPP::setPrettyNormal()? + QGIPrimPath::setPrettyNormal(); } QColor QGIEdge::getHiddenColor() diff --git a/src/Mod/TechDraw/Gui/TaskCenterLine.cpp b/src/Mod/TechDraw/Gui/TaskCenterLine.cpp index 657c6bdd90..544fce3095 100644 --- a/src/Mod/TechDraw/Gui/TaskCenterLine.cpp +++ b/src/Mod/TechDraw/Gui/TaskCenterLine.cpp @@ -313,9 +313,8 @@ void TaskCenterLine::onColorChanged() return; } - Base::Color ac; - ac.setValue(ui->cpLineColor->color()); - m_cl->m_format.getColor().setValue(ui->cpLineColor->color()); + Base::Color color = Base::Color::fromValue(ui->cpLineColor->color()); + m_cl->m_format.setColor(color); m_partFeat->recomputeFeature(); } From 893e4a2ff1513a2e296c6f3969126b8de2575815 Mon Sep 17 00:00:00 2001 From: xtemp09 Date: Mon, 7 Apr 2025 20:43:04 +0700 Subject: [PATCH 163/316] Make some context menu actions translatable (#20401) * Make some context menu actions translatable * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Gui/MainWindow.cpp | 2 ++ src/Mod/BIM/BimStatus.py | 3 +++ src/Mod/Draft/draftutils/init_draft_statusbar.py | 10 ++++++---- src/Mod/Tux/NavigationIndicatorGui.py | 6 ++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 524a032e56..81ccba8424 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -403,6 +403,8 @@ MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags f) if(notificationAreaEnabled) { NotificationArea* notificationArea = new NotificationArea(statusBar()); notificationArea->setObjectName(QStringLiteral("notificationArea")); + //: A context menu action used to show or hide the 'notificationArea' toolbar widget + notificationArea->setWindowTitle(tr("Notification area")); notificationArea->setStyleSheet(QStringLiteral("text-align:left;")); statusBar()->addPermanentWidget(notificationArea); } diff --git a/src/Mod/BIM/BimStatus.py b/src/Mod/BIM/BimStatus.py index 9da009da0d..c223a7fa3c 100644 --- a/src/Mod/BIM/BimStatus.py +++ b/src/Mod/BIM/BimStatus.py @@ -121,6 +121,9 @@ def setStatusIcons(show=True): else: statuswidget = FreeCADGui.UiLoader().createWidget("Gui::ToolBar") statuswidget.setObjectName("BIMStatusWidget") + text = translate("BIMStatusWidget", "BIM status widget", + "A context menu action used to show or hide this toolbar widget") + statuswidget.setWindowTitle(text) s = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/General").GetInt("ToolbarIconSize", 24) statuswidget.setIconSize(QtCore.QSize(s,s)) st.insertPermanentWidget(2, statuswidget) diff --git a/src/Mod/Draft/draftutils/init_draft_statusbar.py b/src/Mod/Draft/draftutils/init_draft_statusbar.py index 80e048f6e4..8e41841d30 100644 --- a/src/Mod/Draft/draftutils/init_draft_statusbar.py +++ b/src/Mod/Draft/draftutils/init_draft_statusbar.py @@ -184,8 +184,9 @@ 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") - # WindowTitle is just in case, should not be visible in the GUI. - scale_widget.setWindowTitle(translate("draft", "Draft scale 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 draft_scales = get_scales() @@ -245,8 +246,9 @@ 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") - # WindowTitle is just in case, should not be visible in the GUI. - snap_widget.setWindowTitle(translate("draft", "Draft snap 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)) sb.insertPermanentWidget(2, snap_widget) diff --git a/src/Mod/Tux/NavigationIndicatorGui.py b/src/Mod/Tux/NavigationIndicatorGui.py index b76ea9afd5..5a0cc2fb34 100644 --- a/src/Mod/Tux/NavigationIndicatorGui.py +++ b/src/Mod/Tux/NavigationIndicatorGui.py @@ -619,6 +619,12 @@ indicator = IndicatorButton(statusBar) indicator.setFlat(True) indicator.adjustSize() indicator.setObjectName("NavigationIndicator") +text = translate( + "NavigationIndicator", + "Navigation indicator", + "A context menu action used to show or hide the 'Navigation indicator' toolbar widget", +) +indicator.setWindowTitle(text) menu = QtGui.QMenu(indicator) indicator.setMenu(menu) From 307a4661aff0974f90adbedae148543de85a463f Mon Sep 17 00:00:00 2001 From: runzh-crypto <1206904210@qq.com> Date: Mon, 7 Apr 2025 20:25:35 +0800 Subject: [PATCH 164/316] Build:add maximum cmake compatible version --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index abced4aca7..ddbb46ef63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ # As of February 2025 we require CMake 3.22.0 cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) +# Check for maximum version +if (CMAKE_VERSION VERSION_GREATER_EQUAL "4.0.0") + message(FATAL_ERROR "The required CMake version is before 4.0.0.") +endif() # As of cMake 3.27, find_package() will look for both case-sensitive and all-uppercase versions # of the package. This seems to affect FLANN as included by Pixi From 35a9673a75376951195566ff2d3696249bfbed1d Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Fri, 28 Mar 2025 23:15:04 +0100 Subject: [PATCH 165/316] Base: Rename Base::freecad_dynamic_cast into freecad_cast This is to make it shorter and easier to use. QT does the same thing with their qobject_cast. --- src/App/Document.cpp | 8 +-- src/App/DocumentObject.cpp | 8 +-- src/App/DocumentObserver.h | 6 +-- src/App/Expression.cpp | 34 ++++++------ src/App/Expression.h | 2 +- src/App/GeoFeature.cpp | 4 +- src/App/GeoFeatureGroupExtension.cpp | 2 +- src/App/GroupExtension.cpp | 2 +- src/App/Link.cpp | 38 +++++++------- src/App/ObjectIdentifier.cpp | 12 ++--- src/App/PropertyContainerPyImp.cpp | 4 +- src/App/PropertyExpressionEngine.cpp | 10 ++-- src/App/PropertyGeo.cpp | 6 +-- src/App/PropertyLinks.cpp | 24 ++++----- src/Base/BaseClass.h | 17 ++++-- src/Gui/Application.cpp | 4 +- src/Gui/CommandLink.cpp | 6 +-- src/Gui/DAGView/DAGModel.cpp | 2 +- src/Gui/DemoMode.cpp | 2 +- src/Gui/Dialogs/DlgAddProperty.cpp | 6 +-- src/Gui/Dialogs/DlgExpressionInput.cpp | 4 +- src/Gui/Dialogs/DlgObjectSelection.cpp | 2 +- src/Gui/Dialogs/DlgPropertyLink.cpp | 8 +-- src/Gui/Document.cpp | 2 +- src/Gui/DocumentObserver.h | 4 +- src/Gui/InputField.cpp | 4 +- src/Gui/QuantitySpinBox.cpp | 2 +- src/Gui/SpinBox.cpp | 4 +- src/Gui/Tree.cpp | 16 +++--- src/Gui/ViewProviderDocumentObject.cpp | 6 +-- src/Gui/ViewProviderLink.cpp | 32 ++++++------ src/Gui/propertyeditor/PropertyEditor.cpp | 4 +- src/Gui/propertyeditor/PropertyItem.cpp | 6 +-- src/Mod/CAM/Gui/ViewProviderPath.cpp | 3 +- .../Drawing/App/FeatureViewSpreadsheet.cpp | 6 +-- src/Mod/Fem/App/FemPostFilter.cpp | 4 +- src/Mod/Fem/App/FemPostPipeline.cpp | 2 +- src/Mod/Fem/Gui/TaskPostBoxes.h | 4 +- .../Fem/Gui/ViewProviderFemPostPipeline.cpp | 4 +- src/Mod/Import/App/ImportOCAF2.cpp | 3 +- src/Mod/Measure/Gui/TaskMeasure.cpp | 2 +- .../Gui/ViewProviderMeasureDistance.cpp | 12 ++--- src/Mod/Mesh/Gui/ViewProvider.cpp | 18 +++---- src/Mod/MeshPart/Gui/Tessellation.cpp | 4 +- src/Mod/Part/App/AttachExtension.cpp | 4 +- src/Mod/Part/App/Geometry.cpp | 6 +-- src/Mod/Part/App/PartFeature.cpp | 4 +- src/Mod/Part/App/PropertyGeometryList.cpp | 4 +- src/Mod/Part/App/PropertyTopoShape.cpp | 12 ++--- src/Mod/Part/Gui/CommandSimple.cpp | 4 +- src/Mod/PartDesign/App/Body.cpp | 2 +- src/Mod/PartDesign/App/Feature.cpp | 2 +- src/Mod/PartDesign/App/FeatureDressUp.cpp | 2 +- .../PartDesign/App/FeatureMultiTransform.cpp | 6 +-- src/Mod/PartDesign/App/FeatureScaled.cpp | 2 +- src/Mod/PartDesign/App/FeatureSketchBased.cpp | 2 +- src/Mod/PartDesign/App/FeatureTransformed.cpp | 20 +++---- src/Mod/PartDesign/App/ShapeBinder.cpp | 2 +- src/Mod/PartDesign/Gui/Command.cpp | 4 +- src/Mod/PartDesign/Gui/TaskFeaturePick.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProvider.cpp | 2 +- .../Gui/ViewProviderShapeBinder.cpp | 2 +- src/Mod/Sketcher/App/SketchObject.cpp | 2 +- src/Mod/Spreadsheet/App/Cell.cpp | 31 +++++------ src/Mod/Spreadsheet/App/PropertySheet.cpp | 12 ++--- src/Mod/Spreadsheet/App/Sheet.cpp | 32 ++++++------ src/Mod/Spreadsheet/Gui/Command.cpp | 52 +++++++++---------- src/Mod/Spreadsheet/Gui/DlgBindSheet.cpp | 4 +- src/Mod/Spreadsheet/Gui/DlgSheetConf.cpp | 9 ++-- .../Gui/ViewProviderSpreadsheet.cpp | 2 +- src/Mod/Spreadsheet/Gui/Workbench.cpp | 4 +- src/Mod/TechDraw/Gui/QGSPage.cpp | 32 ++++++------ src/Tools/params_utils.py | 2 +- 73 files changed, 302 insertions(+), 315 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 5b22ef1b8a..1f51d9d925 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1630,9 +1630,9 @@ std::vector Document::importObjects(Base::XMLReader& reade o->setStatus(App::ObjImporting, true); FC_LOG("importing " << o->getFullName()); if (auto propUUID = - Base::freecad_dynamic_cast(o->getPropertyByName("_ObjectUUID"))) { + freecad_cast(o->getPropertyByName("_ObjectUUID"))) { auto propSource = - Base::freecad_dynamic_cast(o->getPropertyByName("_SourceUUID")); + freecad_cast(o->getPropertyByName("_SourceUUID")); if (!propSource) { propSource = static_cast( o->addDynamicProperty("App::PropertyUUID", @@ -2439,7 +2439,7 @@ bool Document::afterRestore(const std::vector& objArray, bool c // refresh properties in case the object changes its property list obj->getPropertyList(props); for (auto prop : props) { - auto link = Base::freecad_dynamic_cast(prop); + auto link = freecad_cast(prop); int res; std::string errMsg; if (link && (res = link->checkRestore(&errMsg))) { @@ -3987,7 +3987,7 @@ Document::importLinks(const std::vector& objArray) propList.clear(); obj->getPropertyList(propList); for (auto prop : propList) { - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); if (linkProp && !prop->testStatus(Property::Immutable) && !obj->isReadOnly(prop)) { auto copy = linkProp->CopyOnImportExternal(nameMap); if (copy) { diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index df544afd0b..f513648573 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -949,7 +949,7 @@ DocumentObject* DocumentObject::getSubObject(const char* subname, // objects (think of the claimed children of a Fusion). But I do think we // should change that. if (transform && mat) { - auto pla = Base::freecad_dynamic_cast(getPropertyByName("Placement")); + auto pla = freecad_cast(getPropertyByName("Placement")); if (pla) { *mat *= pla->getValue().toMatrix(); } @@ -1476,7 +1476,7 @@ bool DocumentObject::adjustRelativeLinks(const std::set& i std::vector props; getPropertyList(props); for (auto prop : props) { - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); if (linkProp && linkProp->adjustLink(inList)) { touched = true; } @@ -1495,7 +1495,7 @@ bool DocumentObject::adjustRelativeLinks(const std::set& i std::string DocumentObject::getElementMapVersion(const App::Property* _prop, bool restored) const { - auto prop = Base::freecad_dynamic_cast(_prop); + auto prop = freecad_cast(_prop); if (!prop) { return std::string(); } @@ -1504,7 +1504,7 @@ std::string DocumentObject::getElementMapVersion(const App::Property* _prop, boo bool DocumentObject::checkElementMapVersion(const App::Property* _prop, const char* ver) const { - auto prop = Base::freecad_dynamic_cast(_prop); + auto prop = freecad_cast(_prop); if (!prop) { return false; } diff --git a/src/App/DocumentObserver.h b/src/App/DocumentObserver.h index 693d64346a..6933d3cc64 100644 --- a/src/App/DocumentObserver.h +++ b/src/App/DocumentObserver.h @@ -148,12 +148,12 @@ public: template inline T* getObjectAs() const { - return Base::freecad_dynamic_cast(getObject()); + return freecad_cast(getObject()); } template inline T* getPropertyAs() const { - return Base::freecad_dynamic_cast(getProperty()); + return freecad_cast(getProperty()); } private: @@ -409,7 +409,7 @@ public: template inline T* get() const noexcept { - return Base::freecad_dynamic_cast(_get()); + return freecad_cast(_get()); } private: diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index a081b351d4..0405af5fa3 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -1478,7 +1478,7 @@ Expression *OperatorExpression::simplify() const Expression * v2 = right->simplify(); // Both arguments reduced to numerics? Then evaluate and return answer - if (freecad_dynamic_cast(v1) && freecad_dynamic_cast(v2)) { + if (freecad_cast(v1) && freecad_cast(v2)) { delete v1; delete v2; return eval(); @@ -1499,7 +1499,7 @@ void OperatorExpression::_toString(std::ostream &s, bool persistent,int) const Operator leftOperator(NONE), rightOperator(NONE); needsParens = false; - if (freecad_dynamic_cast(left)) + if (freecad_cast(left)) leftOperator = static_cast(left)->op; if (left->priority() < priority()) // Check on operator priority first needsParens = true; @@ -1571,7 +1571,7 @@ void OperatorExpression::_toString(std::ostream &s, bool persistent,int) const } needsParens = false; - if (freecad_dynamic_cast(right)) + if (freecad_cast(right)) rightOperator = static_cast(right)->op; if (right->priority() < priority()) // Check on operator priority first needsParens = true; @@ -2012,11 +2012,11 @@ Py::Object FunctionExpression::evalAggregate( if (!p) continue; - if ((qp = freecad_dynamic_cast(p))) + if ((qp = freecad_cast(p))) c->collect(qp->getQuantityValue()); - else if ((fp = freecad_dynamic_cast(p))) + else if ((fp = freecad_cast(p))) c->collect(Quantity(fp->getValue())); - else if ((ip = freecad_dynamic_cast(p))) + else if ((ip = freecad_cast(p))) c->collect(Quantity(ip->getValue())); else _EXPR_THROW("Invalid property type for aggregate.", owner); @@ -2614,7 +2614,7 @@ Expression *FunctionExpression::simplify() const for (auto it : args) { Expression * v = it->simplify(); - if (freecad_dynamic_cast(v)) + if (freecad_cast(v)) ++numerics; a.push_back(v); } @@ -2869,16 +2869,16 @@ void VariableExpression::addComponent(Component *c) { } long l1=0,l2=0,l3=1; if(c->e3) { - auto n3 = freecad_dynamic_cast(c->e3); + auto n3 = freecad_cast(c->e3); if(!n3 || !essentiallyEqual(n3->getValue(),(double)l3)) break; } if(c->e1) { - auto n1 = freecad_dynamic_cast(c->e1); + auto n1 = freecad_cast(c->e1); if(!n1) { if(c->e2 || c->e3) break; - auto s = freecad_dynamic_cast(c->e1); + auto s = freecad_cast(c->e1); if(!s) break; var << ObjectIdentifier::MapComponent( @@ -2895,7 +2895,7 @@ void VariableExpression::addComponent(Component *c) { return; } } - auto n2 = freecad_dynamic_cast(c->e2); + auto n2 = freecad_cast(c->e2); if(n2 && essentiallyInteger(n2->getValue(),l2)) { var << ObjectIdentifier::RangeComponent(l1,l2,l3); return; @@ -3195,7 +3195,7 @@ Py::Object ConditionalExpression::_getPyValue() const { Expression *ConditionalExpression::simplify() const { std::unique_ptr e(condition->simplify()); - NumberExpression * v = freecad_dynamic_cast(e.get()); + NumberExpression * v = freecad_cast(e.get()); if (!v) return new ConditionalExpression(owner, condition->simplify(), trueExpr->simplify(), falseExpr->simplify()); @@ -3752,11 +3752,11 @@ UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, c Expression * simplified = ScanResult->simplify(); if (!unitExpression) { - OperatorExpression * fraction = freecad_dynamic_cast(ScanResult); + OperatorExpression * fraction = freecad_cast(ScanResult); if (fraction && fraction->getOperator() == OperatorExpression::DIV) { - NumberExpression * nom = freecad_dynamic_cast(fraction->getLeft()); - UnitExpression * denom = freecad_dynamic_cast(fraction->getRight()); + NumberExpression * nom = freecad_cast(fraction->getLeft()); + UnitExpression * denom = freecad_cast(fraction->getRight()); // If not initially a unit expression, but value is equal to 1, it means the expression is something like 1/unit if (denom && nom && essentiallyEqual(nom->getValue(), 1.0)) @@ -3766,13 +3766,13 @@ UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, c delete ScanResult; if (unitExpression) { - NumberExpression * num = freecad_dynamic_cast(simplified); + NumberExpression * num = freecad_cast(simplified); if (num) { simplified = new UnitExpression(num->getOwner(), num->getQuantity()); delete num; } - return freecad_dynamic_cast(simplified); + return freecad_cast(simplified); } else { delete simplified; diff --git a/src/App/Expression.h b/src/App/Expression.h index a17a2267ba..a7971ba1f3 100644 --- a/src/App/Expression.h +++ b/src/App/Expression.h @@ -84,7 +84,7 @@ template class ExpressionModifier : public ExpressionVisitor { public: explicit ExpressionModifier(P & _prop) : prop(_prop) - , propLink(Base::freecad_dynamic_cast(&prop)) + , propLink(freecad_cast(&prop)) , signaller(_prop,false) {} diff --git a/src/App/GeoFeature.cpp b/src/App/GeoFeature.cpp index 886eb2f26f..d94d9f1835 100644 --- a/src/App/GeoFeature.cpp +++ b/src/App/GeoFeature.cpp @@ -160,11 +160,11 @@ DocumentObject* GeoFeature::resolveElement(const DocumentObject* obj, return nullptr; } auto linked = sobj->getLinkedObject(true); - auto geo = Base::freecad_dynamic_cast(linked); + auto geo = freecad_cast(linked); if (!geo && linked) { auto ext = linked->getExtensionByType(true); if (ext) { - geo = Base::freecad_dynamic_cast(ext->getTrueLinkedObject(true)); + geo = freecad_cast(ext->getTrueLinkedObject(true)); } } if (geoFeature) { diff --git a/src/App/GeoFeatureGroupExtension.cpp b/src/App/GeoFeatureGroupExtension.cpp index be3379784b..91571feb74 100644 --- a/src/App/GeoFeatureGroupExtension.cpp +++ b/src/App/GeoFeatureGroupExtension.cpp @@ -285,7 +285,7 @@ std::vector GeoFeatureGroupExtension::getScopedObjectsFromLink( } std::vector result; - auto link = Base::freecad_dynamic_cast(prop); + auto link = freecad_cast(prop); if (link && link->getScope() == scope) { link->getLinks(result); } diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index 8e1481310f..64405714fd 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -414,7 +414,7 @@ bool GroupExtension::extensionGetSubObject(DocumentObject*& ret, { const char* dot; if (!subname || *subname == 0) { - auto obj = Base::freecad_dynamic_cast(getExtendedContainer()); + auto obj = freecad_cast(getExtendedContainer()); ret = const_cast(obj); return true; } diff --git a/src/App/Link.cpp b/src/App/Link.cpp index 1645c495e2..e9dc78fb99 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -286,7 +286,7 @@ void LinkBaseExtension::setProperty(int idx, Property* prop) } case PropLinkCopyOnChangeSource: case PropLinkCopyOnChangeGroup: - if (auto linkProp = Base::freecad_dynamic_cast(prop)) { + if (auto linkProp = freecad_cast(prop)) { linkProp->setScope(LinkScope::Global); } // fall through @@ -356,7 +356,7 @@ App::DocumentObjectExecReturn* LinkBaseExtension::extensionExecute() if (!linked) { std::ostringstream ss; ss << "Link broken!"; - auto xlink = Base::freecad_dynamic_cast(getLinkedObjectProperty()); + auto xlink = freecad_cast(getLinkedObjectProperty()); if (xlink) { const char* objname = xlink->getObjectName(); if (!Base::Tools::isNullOrEmpty(objname)) { @@ -389,7 +389,7 @@ App::DocumentObjectExecReturn* LinkBaseExtension::extensionExecute() || !container->getDocument()->getObjectByID(_LinkOwner.getValue()))) { // Check if this is an element link. Do not invoke appLinkExecute() // if so, because it will be called from the link array. - proxy = Base::freecad_dynamic_cast( + proxy = freecad_cast( linked->getPropertyByName("Proxy")); } if (proxy) { @@ -491,7 +491,7 @@ LinkBaseExtension::getOnChangeCopyObjects(std::vector* exc continue; } auto prop = - Base::freecad_dynamic_cast(obj->getPropertyByName("_CopyOnChangeControl")); + freecad_cast(obj->getPropertyByName("_CopyOnChangeControl")); static std::map dummy; const auto& map = prop && prop->getContainer() == obj ? prop->getValues() : dummy; const char* v = ""; @@ -526,7 +526,7 @@ void LinkBaseExtension::setOnChangeCopyObject(App::DocumentObject* obj, OnChange bool exclude = flags.testFlag(OnChangeCopyOptions::Exclude); bool external = parent->getDocument() != obj->getDocument(); auto prop = - Base::freecad_dynamic_cast(obj->getPropertyByName("_CopyOnChangeControl")); + freecad_cast(obj->getPropertyByName("_CopyOnChangeControl")); if (external == exclude && !prop) { return; @@ -583,7 +583,7 @@ void LinkBaseExtension::syncCopyOnChange() // dependencies. LinkGroup* copyOnChangeGroup = nullptr; if (auto prop = getLinkCopyOnChangeGroupProperty()) { - copyOnChangeGroup = Base::freecad_dynamic_cast(prop->getValue()); + copyOnChangeGroup = freecad_cast(prop->getValue()); if (!copyOnChangeGroup) { // Create the LinkGroup if not exist auto group = new LinkGroup; @@ -601,7 +601,7 @@ void LinkBaseExtension::syncCopyOnChange() continue; } auto prop = - Base::freecad_dynamic_cast(obj->getPropertyByName("_SourceUUID")); + freecad_cast(obj->getPropertyByName("_SourceUUID")); if (prop && prop->getContainer() == obj) { oldObjs.emplace_back(prop); } @@ -665,7 +665,7 @@ void LinkBaseExtension::syncCopyOnChange() std::map newObjs; for (auto obj : copiedObjs) { - auto prop = Base::freecad_dynamic_cast(obj->getPropertyByName("_SourceUUID")); + auto prop = freecad_cast(obj->getPropertyByName("_SourceUUID")); if (prop) { newObjs.insert(std::make_pair(prop->getValue(), obj)); } @@ -673,7 +673,7 @@ void LinkBaseExtension::syncCopyOnChange() std::vector> replacements; for (const auto& objT : oldObjs) { - auto prop = Base::freecad_dynamic_cast(objT.getProperty()); + auto prop = freecad_cast(objT.getProperty()); if (!prop) { continue; } @@ -707,7 +707,7 @@ void LinkBaseExtension::syncCopyOnChange() if (prop->getContainer() != o) { continue; } - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); if (!linkProp) { continue; } @@ -1739,7 +1739,7 @@ void LinkBaseExtension::parseSubName() const bool hasSubElement = !mySubElements.empty(); mySubElements.clear(); mySubName.clear(); - auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); + auto xlink = freecad_cast(getLinkedObjectProperty()); if (!xlink || xlink->getSubValues().empty()) { if (hasSubElement) { mySubElements.emplace_back(""); @@ -1896,7 +1896,7 @@ void LinkBaseExtension::update(App::DocumentObject* parent, const Property* prop std::vector scales; scales.reserve(objs.size()); for (auto obj : objs) { - auto element = freecad_dynamic_cast(obj); + auto element = freecad_cast(obj); if (element) { placements.push_back(element->Placement.getValue()); scales.push_back(element->getScaleVector()); @@ -1990,7 +1990,7 @@ void LinkBaseExtension::update(App::DocumentObject* parent, const Property* prop // It is possible to have orphan LinkElement here due to, // for example, undo and redo. So we try to re-claim the // children element first. - auto obj = freecad_dynamic_cast(doc->getObject(name.c_str())); + auto obj = freecad_cast(doc->getObject(name.c_str())); if (obj && (!obj->_LinkOwner.getValue() || obj->_LinkOwner.getValue() == ownerID)) { obj->Visibility.setValue(false); @@ -2034,7 +2034,7 @@ void LinkBaseExtension::update(App::DocumentObject* parent, const Property* prop auto owner = getContainer(); long ownerID = owner ? owner->getID() : 0; while (objs.size() > elementCount) { - auto element = freecad_dynamic_cast(objs.back()); + auto element = freecad_cast(objs.back()); if (element && element->_LinkOwner.getValue() == ownerID) { tmpObjs.push_back(objs.back()); } @@ -2201,13 +2201,13 @@ void LinkBaseExtension::syncElementList() { auto transform = getLinkTransformProperty(); auto link = getLinkedObjectProperty(); - auto xlink = freecad_dynamic_cast(link); + auto xlink = freecad_cast(link); auto owner = getContainer(); auto ownerID = owner ? owner->getID() : 0; auto elements = getElementListValue(); for (auto i : elements) { - auto element = freecad_dynamic_cast(i); + auto element = freecad_cast(i); if (!element || (element->_LinkOwner.getValue() && element->_LinkOwner.getValue() != ownerID)) { continue; @@ -2251,7 +2251,7 @@ void LinkBaseExtension::onExtendedDocumentRestored() hasOldSubElement = false; // SubElements was stored as a PropertyStringList. It is now migrated to be // stored inside PropertyXLink. - auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); + auto xlink = freecad_cast(getLinkedObjectProperty()); if (!xlink) { FC_ERR("Failed to restore SubElements for " << parent->getFullName()); } @@ -2393,7 +2393,7 @@ void LinkBaseExtension::setLink(int index, link->Label.setValue(linked->Label.getValue()); } auto pla = - freecad_dynamic_cast(obj->getPropertyByName("Placement")); + freecad_cast(obj->getPropertyByName("Placement")); if (pla) { link->Placement.setValue(pla->getValue()); } @@ -2424,7 +2424,7 @@ void LinkBaseExtension::setLink(int index, // Here means we are assigning a Link - auto xlink = freecad_dynamic_cast(linkProp); + auto xlink = freecad_cast(linkProp); if (obj) { if (!obj->isAttachedToDocument()) { LINK_THROW(Base::ValueError, "Invalid document object"); diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index fde8bff2ff..1d9b1e3988 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -119,7 +119,7 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, , _hash(0) { if (_owner) { - const DocumentObject* docObj = freecad_dynamic_cast(_owner); + const DocumentObject* docObj = freecad_cast(_owner); if (!docObj) { FC_THROWM(Base::RuntimeError, "Property must be owned by a document object."); } @@ -145,7 +145,7 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, bool lo , _hash(0) { if (_owner) { - const DocumentObject* docObj = freecad_dynamic_cast(_owner); + const DocumentObject* docObj = freecad_cast(_owner); if (!docObj) { FC_THROWM(Base::RuntimeError, "Property must be owned by a document object."); } @@ -166,7 +166,7 @@ ObjectIdentifier::ObjectIdentifier(const Property& prop, int index) , localProperty(false) , _hash(0) { - DocumentObject* docObj = freecad_dynamic_cast(prop.getContainer()); + DocumentObject* docObj = freecad_cast(prop.getContainer()); if (!docObj) { FC_THROWM(Base::TypeError, "Property must be owned by a document object."); @@ -1364,7 +1364,7 @@ ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier& other) con ObjectIdentifier ObjectIdentifier::parse(const DocumentObject* docObj, const std::string& str) { std::unique_ptr expr(ExpressionParser::parse(docObj, str.c_str())); - VariableExpression* v = freecad_dynamic_cast(expr.get()); + VariableExpression* v = freecad_cast(expr.get()); if (v) { return v->getPath(); @@ -1853,12 +1853,12 @@ ObjectIdentifier::access(const ResolveResults& result, Py::Object* value, Depend } if (prop && prop->getContainer() != obj) { auto linkTouched = - Base::freecad_dynamic_cast(obj->getPropertyByName("_LinkTouched")); + freecad_cast(obj->getPropertyByName("_LinkTouched")); if (linkTouched) { propName = linkTouched->getName(); } else { - auto propOwner = Base::freecad_dynamic_cast(prop->getContainer()); + auto propOwner = freecad_cast(prop->getContainer()); if (propOwner) { obj = propOwner; } diff --git a/src/App/PropertyContainerPyImp.cpp b/src/App/PropertyContainerPyImp.cpp index 6cff166d53..5da225589c 100644 --- a/src/App/PropertyContainerPyImp.cpp +++ b/src/App/PropertyContainerPyImp.cpp @@ -247,7 +247,7 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject* args) return nullptr; } - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); std::bitset<32> status(prop->getStatus()); std::vector items; @@ -326,7 +326,7 @@ PyObject* PropertyContainerPy::getPropertyStatus(PyObject* args) return nullptr; } - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); if (linkProp && linkProp->testFlag(App::PropertyLinkBase::LinkAllowPartial)) { ret.append(Py::String("AllowPartial")); } diff --git a/src/App/PropertyExpressionEngine.cpp b/src/App/PropertyExpressionEngine.cpp index 3f00faad18..36c5c0d10a 100644 --- a/src/App/PropertyExpressionEngine.cpp +++ b/src/App/PropertyExpressionEngine.cpp @@ -408,7 +408,7 @@ void PropertyExpressionEngine::buildGraphStructures( ObjectIdentifier PropertyExpressionEngine::canonicalPath(const ObjectIdentifier& p) const { - DocumentObject* docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_cast(getContainer()); // Am I owned by a DocumentObject? if (!docObj) { @@ -448,7 +448,7 @@ size_t PropertyExpressionEngine::numExpressions() const void PropertyExpressionEngine::afterRestore() { - DocumentObject* docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_cast(getContainer()); if (restoredExpressions && docObj) { Base::FlagToggler flag(restoring); AtomicPropertyChange signaller(*this); @@ -669,7 +669,7 @@ PropertyExpressionEngine::computeEvaluationOrder(ExecuteOption option) DocumentObjectExecReturn* App::PropertyExpressionEngine::execute(ExecuteOption option, bool* touched) { - DocumentObject* docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_cast(getContainer()); if (!docObj) { throw Base::RuntimeError("PropertyExpressionEngine must be owned by a DocumentObject."); @@ -739,7 +739,7 @@ DocumentObjectExecReturn* App::PropertyExpressionEngine::execute(ExecuteOption o throw Base::RuntimeError("Path does not resolve to a property."); } - DocumentObject* parent = freecad_dynamic_cast(prop->getContainer()); + DocumentObject* parent = freecad_cast(prop->getContainer()); /* Make sure property belongs to the same container as this PropertyExpressionEngine */ if (parent != docObj) { @@ -808,7 +808,7 @@ void PropertyExpressionEngine::getPathsToDocumentObject( DocumentObject* obj, std::vector& paths) const { - DocumentObject* owner = freecad_dynamic_cast(getContainer()); + DocumentObject* owner = freecad_cast(getContainer()); if (!owner || owner == obj) { return; diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index aeb2454960..313881c469 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -1301,7 +1301,7 @@ std::string PropertyComplexGeoData::getElementMapVersion(bool) const if (!data) { return std::string(); } - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); std::ostringstream ss; if (owner && owner->getDocument() && owner->getDocument()->getStringHasher() == data->Hasher) { ss << "1."; @@ -1319,7 +1319,7 @@ bool PropertyComplexGeoData::checkElementMapVersion(const char* ver) const if (!data) { return false; } - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); std::ostringstream ss; const char* prefix; if (owner && owner->getDocument() && owner->getDocument()->getStringHasher() == data->Hasher) { @@ -1340,7 +1340,7 @@ void PropertyComplexGeoData::afterRestore() auto data = getComplexData(); if (data && data->isRestoreFailed()) { data->resetRestoreFailure(); - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); if (owner && owner->getDocument() && !owner->getDocument()->testStatus(App::Document::PartialDoc)) { owner->getDocument()->addRecomputeObject(owner); diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 483b51bccf..39a8faa2a9 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -249,7 +249,7 @@ static std::string propertyName(const Property* prop) return {}; } if (!prop->getContainer() || !prop->hasName()) { - auto xlink = Base::freecad_dynamic_cast(prop); + auto xlink = freecad_cast(prop); if (xlink) { return propertyName(xlink->parent()); } @@ -976,7 +976,7 @@ void PropertyLinkList::setValues(const std::vector& value) return; } - auto parent = Base::freecad_dynamic_cast(getContainer()); + auto parent = freecad_cast(getContainer()); for (auto obj : value) { if (!obj || !obj->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkList: invalid document object"); @@ -1321,7 +1321,7 @@ void PropertyLinkSub::setValue(App::DocumentObject* lValue, std::vector&& subs, std::vector&& shadows) { - auto parent = Base::freecad_dynamic_cast(getContainer()); + auto parent = freecad_cast(getContainer()); if (lValue) { if (!lValue->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkSub: invalid document object"); @@ -2216,7 +2216,7 @@ int PropertyLinkSubList::getSize() const void PropertyLinkSubList::setValue(DocumentObject* lValue, const char* SubName) { - auto parent = Base::freecad_dynamic_cast(getContainer()); + auto parent = freecad_cast(getContainer()); verifyObject(lValue, parent); // maintain backlinks @@ -2255,7 +2255,7 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue, const char* SubName) void PropertyLinkSubList::setValues(const std::vector& lValue, const std::vector& lSubNames) { - auto parent = Base::freecad_dynamic_cast(getContainer()); + auto parent = freecad_cast(getContainer()); for (auto obj : lValue) { verifyObject(obj, parent); } @@ -2316,7 +2316,7 @@ void PropertyLinkSubList::setValues(std::vector&& lValue, std::vector&& lSubNames, std::vector&& ShadowSubList) { - auto parent = Base::freecad_dynamic_cast(getContainer()); + auto parent = freecad_cast(getContainer()); for (auto obj : lValue) { verifyObject(obj, parent); } @@ -2411,7 +2411,7 @@ void PropertyLinkSubList::addValue(App::DocumentObject* obj, const std::vector& subs, bool reset) { - auto parent = Base::freecad_dynamic_cast(getContainer()); + auto parent = freecad_cast(getContainer()); verifyObject(obj, parent); // maintain backlinks. @@ -2729,7 +2729,7 @@ void PropertyLinkSubList::updateElementReference(DocumentObject* feature, bool r unregisterElementReference(); } _ShadowSubList.resize(_lSubList.size()); - auto owner = freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); if (owner && owner->isRestoring()) { return; } @@ -3370,7 +3370,7 @@ public: if (info->pcDoc) { // make sure to attach only external object - auto owner = Base::freecad_dynamic_cast(l->getContainer()); + auto owner = freecad_cast(l->getContainer()); if (owner && owner->getDocument() == info->pcDoc) { return info; } @@ -4332,7 +4332,7 @@ void PropertyXLink::Restore(Base::XMLReader& reader) Property* PropertyXLink::CopyOnImportExternal(const std::map& nameMap) const { - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); if (!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) { return nullptr; } @@ -5735,7 +5735,7 @@ void PropertyXLinkContainer::Save(Base::Writer& writer) const writer.Stream() << writer.ind() << " docSet; - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); if (owner && !owner->isExporting()) { // Document name and label can change on restore, we shall record the // current document name and label and pair it with the associated @@ -5878,7 +5878,7 @@ bool PropertyXLinkContainer::isLinkedToDocument(const App::Document& doc) const void PropertyXLinkContainer::updateDeps(std::map&& newDeps) { - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); if (!owner || !owner->isAttachedToDocument()) { return; } diff --git a/src/Base/BaseClass.h b/src/Base/BaseClass.h index 3c3dced6d8..f6e204c8e5 100644 --- a/src/Base/BaseClass.h +++ b/src/Base/BaseClass.h @@ -201,9 +201,10 @@ bool BaseClass::isDerivedFrom() const * */ template -T* freecad_dynamic_cast(Base::BaseClass* type) +T* freecad_cast(Base::BaseClass* type) { - static_assert(std::is_base_of::value, "T must be derived from Base::BaseClass"); + static_assert(std::is_base_of::value, + "T must be derived from Base::BaseClass"); if (type && type->isDerivedFrom(T::getClassTypeId())) { return static_cast(type); @@ -218,9 +219,10 @@ T* freecad_dynamic_cast(Base::BaseClass* type) * */ template -const T* freecad_dynamic_cast(const Base::BaseClass* type) +const T* freecad_cast(const Base::BaseClass* type) { - static_assert(std::is_base_of::value, "T must be derived from Base::BaseClass"); + static_assert(std::is_base_of::value, + "T must be derived from Base::BaseClass"); if (type && type->isDerivedFrom(T::getClassTypeId())) { return static_cast(type); @@ -229,7 +231,12 @@ const T* freecad_dynamic_cast(const Base::BaseClass* type) return nullptr; } - } // namespace Base +// We define global alias for freecad_cast to be used by all FreeCAD files that include +// BaseClass.h. While doing using on header level is non-ideal it allows for much easier use +// of the important freecad_cast. In that case the name is prefixed with freecad so there is no +// chance of symbols collision. +using Base::freecad_cast; + #endif // BASE_BASECLASS_H diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index d69188b1e9..83f5b6f007 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -159,7 +159,7 @@ public: void newObject(const ViewProvider& vp) { auto vpd = - Base::freecad_dynamic_cast(const_cast(&vp)); + freecad_cast(const_cast(&vp)); if (vpd && vpd->getObject()) { map[vpd->getObject()] = vpd; } @@ -167,7 +167,7 @@ public: void deleteObject(const ViewProvider& vp) { auto vpd = - Base::freecad_dynamic_cast(const_cast(&vp)); + freecad_cast(const_cast(&vp)); if (vpd && vpd->getObject()) { map.erase(vpd->getObject()); } diff --git a/src/Gui/CommandLink.cpp b/src/Gui/CommandLink.cpp index 76eafdbd63..f172521848 100644 --- a/src/Gui/CommandLink.cpp +++ b/src/Gui/CommandLink.cpp @@ -398,7 +398,7 @@ static void linkConvert(bool unlink) { for(auto &v : infos) { auto &info = v.second; auto parent = info.parent.getObject(); - auto parentVp = Base::freecad_dynamic_cast( + auto parentVp = freecad_cast( Application::Instance->getViewProvider(parent)); auto obj = info.obj.getObject(); if(!parent || !obj || !parentVp) @@ -418,7 +418,7 @@ static void linkConvert(bool unlink) { FC_THROWM(Base::RuntimeError,"Failed to create link"); link->setLink(-1,obj); link->Label.setValue(obj->Label.getValue()); - auto pla = Base::freecad_dynamic_cast( + auto pla = freecad_cast( obj->getPropertyByName("Placement")); if(pla) link->Placement.setValue(pla->getValue()); @@ -662,7 +662,7 @@ static App::DocumentObject *getSelectedLink(bool finalLink, std::string *subname auto sobj = sels[0].pObject->getSubObject(sels[0].SubName); if(!sobj) return nullptr; - auto vp = Base::freecad_dynamic_cast( + auto vp = freecad_cast( Application::Instance->getViewProvider(sobj)); if(!vp) return nullptr; diff --git a/src/Gui/DAGView/DAGModel.cpp b/src/Gui/DAGView/DAGModel.cpp index a699d94470..70f32bc6d5 100644 --- a/src/Gui/DAGView/DAGModel.cpp +++ b/src/Gui/DAGView/DAGModel.cpp @@ -146,7 +146,7 @@ Model::Model(QObject *parentIn, const Gui::Document &documentIn) : QGraphicsScen //NOLINTEND for (auto obj : documentIn.getDocument()->getObjects()) { - auto vpd = Base::freecad_dynamic_cast(documentIn.getViewProvider(obj)); + auto vpd = freecad_cast(documentIn.getViewProvider(obj)); if (vpd) slotNewObject(*vpd); } diff --git a/src/Gui/DemoMode.cpp b/src/Gui/DemoMode.cpp index a4eef9d65c..e55b216819 100644 --- a/src/Gui/DemoMode.cpp +++ b/src/Gui/DemoMode.cpp @@ -145,7 +145,7 @@ void DemoMode::hideEvent(QHideEvent*) Gui::View3DInventor* DemoMode::activeView() const { if (Document* doc = Application::Instance->activeDocument()) { - return Base::freecad_dynamic_cast(doc->getActiveView()); + return freecad_cast(doc->getActiveView()); } return nullptr; diff --git a/src/Gui/Dialogs/DlgAddProperty.cpp b/src/Gui/Dialogs/DlgAddProperty.cpp index f307dbf8bd..700e5ea9d9 100644 --- a/src/Gui/Dialogs/DlgAddProperty.cpp +++ b/src/Gui/Dialogs/DlgAddProperty.cpp @@ -82,13 +82,13 @@ DlgAddProperty::DlgAddProperty(QWidget* parent, DlgAddProperty::~DlgAddProperty() = default; static std::string containerName(const App::PropertyContainer *c) { - auto doc = Base::freecad_dynamic_cast(c); + auto doc = freecad_cast(c); if(doc) return doc->getName(); - auto obj = Base::freecad_dynamic_cast(c); + auto obj = freecad_cast(c); if(obj) return obj->getFullName(); - auto vpd = Base::freecad_dynamic_cast(c); + auto vpd = freecad_cast(c); if(vpd) return vpd->getObject()->getFullName(); return "?"; diff --git a/src/Gui/Dialogs/DlgExpressionInput.cpp b/src/Gui/Dialogs/DlgExpressionInput.cpp index 0b1116d0c5..aef3d2c38e 100644 --- a/src/Gui/Dialogs/DlgExpressionInput.cpp +++ b/src/Gui/Dialogs/DlgExpressionInput.cpp @@ -286,7 +286,7 @@ void DlgExpressionInput::checkExpression(const QString& text) //set default palette as we may have read text right now ui->msg->setPalette(ui->okBtn->palette()); - auto * n = Base::freecad_dynamic_cast(result.get()); + auto * n = freecad_cast(result.get()); if (n) { Base::Quantity value = n->getQuantity(); if (!value.isValid()) { @@ -554,7 +554,7 @@ static void addGroupsVarSetComboBox(App::VarSet* varSet, QTreeWidgetItem* varSet static void addVarSetsVarSetComboBox(std::vector& varSets, QTreeWidgetItem* docItem) { for (auto varSet : varSets) { - auto vp = Base::freecad_dynamic_cast( + auto vp = freecad_cast( Gui::Application::Instance->getViewProvider(varSet)); // the item will be automatically destroyed when the docItem will be destroyed auto item = new QTreeWidgetItem(docItem); diff --git a/src/Gui/Dialogs/DlgObjectSelection.cpp b/src/Gui/Dialogs/DlgObjectSelection.cpp index 89869fc7f8..9c86365c2a 100644 --- a/src/Gui/Dialogs/DlgObjectSelection.cpp +++ b/src/Gui/Dialogs/DlgObjectSelection.cpp @@ -194,7 +194,7 @@ QTreeWidgetItem *DlgObjectSelection::getItem(App::DocumentObject *obj, if (!items.empty()) return items[0]; item = new QTreeWidgetItem(ui->treeWidget); - auto vp = Base::freecad_dynamic_cast( + auto vp = freecad_cast( Gui::Application::Instance->getViewProvider(obj)); if (vp) item->setIcon(0, vp->getIcon()); App::SubObjectT objT(obj, ""); diff --git a/src/Gui/Dialogs/DlgPropertyLink.cpp b/src/Gui/Dialogs/DlgPropertyLink.cpp index 7de89699f2..2d0e65b283 100644 --- a/src/Gui/Dialogs/DlgPropertyLink.cpp +++ b/src/Gui/Dialogs/DlgPropertyLink.cpp @@ -272,7 +272,7 @@ void DlgPropertyLink::init(const App::DocumentObjectT& prop, bool tryFilter) ui->searchBox->setDocumentObject(owner); - auto propLink = Base::freecad_dynamic_cast(objProp.getProperty()); + auto propLink = freecad_cast(objProp.getProperty()); if (!propLink) { return; } @@ -580,7 +580,7 @@ void DlgPropertyLink::onItemSelectionChanged() focus = ui->treeWidget->hasFocus(); auto doc = Gui::Application::Instance->getDocument(sobjs.front().getDocumentName().c_str()); if (doc) { - auto vp = Base::freecad_dynamic_cast( + auto vp = freecad_cast( doc->getViewProvider(obj)); if (vp) { // If the view provider uses a special window for rendering, switch to it @@ -1016,7 +1016,7 @@ QTreeWidgetItem* DlgPropertyLink::createItem(App::DocumentObject* obj, QTreeWidg return nullptr; } - auto vp = Base::freecad_dynamic_cast( + auto vp = freecad_cast( Application::Instance->getViewProvider(obj)); if (!vp) { return nullptr; @@ -1047,7 +1047,7 @@ QTreeWidgetItem* DlgPropertyLink::createItem(App::DocumentObject* obj, QTreeWidg QByteArray proxyType; auto prop = - Base::freecad_dynamic_cast(obj->getPropertyByName("Proxy")); + freecad_cast(obj->getPropertyByName("Proxy")); if (prop) { Base::PyGILStateLocker lock; Py::Object proxy = prop->getValue(); diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index a3e1e75acb..4fd7a05eb8 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -1932,7 +1932,7 @@ void Document::importObjects(const std::vector& obj, Base: Gui::ViewProvider* pObj = this->getViewProviderByName(name.c_str()); if (pObj) { pObj->setStatus(Gui::isRestoring,true); - auto vpd = Base::freecad_dynamic_cast(pObj); + auto vpd = freecad_cast(pObj); if(vpd) vpd->startRestoring(); pObj->Restore(*localreader); if (expanded && vpd) diff --git a/src/Gui/DocumentObserver.h b/src/Gui/DocumentObserver.h index fdd9a1e2a0..ba9eb9ddb1 100644 --- a/src/Gui/DocumentObserver.h +++ b/src/Gui/DocumentObserver.h @@ -120,7 +120,7 @@ public: template inline T* getObjectAs() const { - return Base::freecad_dynamic_cast(getViewProvider()); + return freecad_cast(getViewProvider()); } private: @@ -215,7 +215,7 @@ public: template inline T* get() const noexcept { - return Base::freecad_dynamic_cast(_get()); + return freecad_cast(_get()); } private: diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index 6ebeb16844..e72f71815d 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -120,7 +120,7 @@ void InputField::bind(const App::ObjectIdentifier &_path) { ExpressionBinding::bind(_path); - auto * prop = freecad_dynamic_cast(getPath().getProperty()); + auto * prop = freecad_cast(getPath().getProperty()); if (prop) actQuantity = Base::Quantity(prop->getValue()); @@ -259,7 +259,7 @@ void InputField::newInput(const QString & text) std::unique_ptr evalRes(getExpression()->eval()); - auto * value = freecad_dynamic_cast(evalRes.get()); + auto * value = freecad_cast(evalRes.get()); if (value) { res.setValue(value->getValue()); res.setUnit(value->getUnit()); diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index 18657e6ed5..222b4cba93 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -139,7 +139,7 @@ public: if (expr) { std::unique_ptr res(expr->eval()); - NumberExpression * n = Base::freecad_dynamic_cast(res.get()); + NumberExpression * n = freecad_cast(res.get()); if (n){ result = n->getQuantity(); value = result.getValue(); diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index bc26dc7658..931d8f2fdb 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -103,7 +103,7 @@ void ExpressionSpinBox::showInvalidExpression(const QString& tip) void ExpressionSpinBox::showValidExpression(ExpressionSpinBox::Number number) { std::unique_ptr result(getExpression()->eval()); - auto * value = freecad_dynamic_cast(result.get()); + auto * value = freecad_cast(result.get()); if (value) { switch (number) { @@ -187,7 +187,7 @@ void ExpressionSpinBox::openFormulaDialog() { Q_ASSERT(isBound()); - auto * qprop = freecad_dynamic_cast(getPath().getProperty()); + auto * qprop = freecad_cast(getPath().getProperty()); Unit unit; if (qprop) diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index ccb23dc5be..064b8ead5c 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -1918,14 +1918,14 @@ namespace { if (topObj) { auto sobj = topObj->getSubObject(info.topSubname.c_str(), nullptr, &mat); if (sobj == obj) { - propPlacement = Base::freecad_dynamic_cast( + propPlacement = freecad_cast( obj->getPropertyByName("Placement")); } } } } else { - propPlacement = Base::freecad_dynamic_cast( + propPlacement = freecad_cast( obj->getPropertyByName("Placement")); if (propPlacement) mat = propPlacement->getValue().toMatrix(); @@ -2484,7 +2484,7 @@ bool TreeWidget::dropInObject(QDropEvent* event, TargetItemInfo& targetInfo, for (auto& info : infos) { auto& subname = info.subname; targetObj = targetDoc->getObject(target.c_str()); - vp = Base::freecad_dynamic_cast( Application::Instance->getViewProvider(targetObj)); + vp = freecad_cast( Application::Instance->getViewProvider(targetObj)); if (!vp) { FC_ERR("Cannot find drop target object " << target); break; @@ -2652,7 +2652,7 @@ bool TreeWidget::dropInObject(QDropEvent* event, TargetItemInfo& targetInfo, (!info.dragging && sobj->getLinkedObject(false) == obj)) { if (!info.dragging) - propPlacement = Base::freecad_dynamic_cast( + propPlacement = freecad_cast( sobj->getPropertyByName("Placement")); if (propPlacement) { newMat *= propPlacement->getValue().inverse().toMatrix(); @@ -2791,7 +2791,7 @@ void TreeWidget::sortDroppedObjects(TargetItemInfo& targetInfo, std::vector(targetInfo.targetItem); App::DocumentObject* targetObj = targetItemObj->object()->getObject(); - auto propGroup = Base::freecad_dynamic_cast(targetObj->getPropertyByName("Group")); + auto propGroup = freecad_cast(targetObj->getPropertyByName("Group")); if (!propGroup) { return; } @@ -3061,7 +3061,7 @@ void TreeWidget::onUpdateStatus() errors.push_back(obj); if (docItem->ObjectMap.count(obj)) continue; - auto vpd = Base::freecad_dynamic_cast(gdoc->getViewProvider(obj)); + auto vpd = freecad_cast(gdoc->getViewProvider(obj)); if (vpd) docItem->createNewItem(*vpd); } @@ -3746,7 +3746,7 @@ void TreeWidget::selectLinkedObject(App::DocumentObject* linked) { if (!isSelectionAttached() || isSelectionBlocked()) return; - auto linkedVp = Base::freecad_dynamic_cast( + auto linkedVp = freecad_cast( Application::Instance->getViewProvider(linked)); if (!linkedVp) { TREE_ERR("invalid linked view provider"); @@ -3962,7 +3962,7 @@ bool DocumentItem::createNewItem(const Gui::ViewProviderDocumentObject& obj, } ViewProviderDocumentObject* DocumentItem::getViewProvider(App::DocumentObject* obj) { - return Base::freecad_dynamic_cast( + return freecad_cast( Application::Instance->getViewProvider(obj)); } diff --git a/src/Gui/ViewProviderDocumentObject.cpp b/src/Gui/ViewProviderDocumentObject.cpp index 7de7919277..5ac6bcb22f 100644 --- a/src/Gui/ViewProviderDocumentObject.cpp +++ b/src/Gui/ViewProviderDocumentObject.cpp @@ -547,7 +547,7 @@ int ViewProviderDocumentObject::replaceObject( std::vector props; obj->getPropertyList(props); for(auto prop : props) { - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); if(!linkProp) continue; std::unique_ptr copy(linkProp->CopyOnLinkReplace(obj, oldObj,newObj)); @@ -567,7 +567,7 @@ int ViewProviderDocumentObject::replaceObject( std::vector props; o->getPropertyList(props); for(auto prop : props) { - auto linkProp = Base::freecad_dynamic_cast(prop); + auto linkProp = freecad_cast(prop); if(!linkProp) continue; std::unique_ptr copy(linkProp->CopyOnLinkReplace(obj,oldObj,newObj)); @@ -691,7 +691,7 @@ ViewProviderDocumentObject *ViewProviderDocumentObject::getLinkedViewProvider( auto linked = pcObject->getLinkedObject(recursive); if(!linked || linked == pcObject) return self; - auto res = Base::freecad_dynamic_cast( + auto res = freecad_cast( Application::Instance->getViewProvider(linked)); if(!res) res = self; diff --git a/src/Gui/ViewProviderLink.cpp b/src/Gui/ViewProviderLink.cpp index e278d5a2cf..3ed56f0fc5 100644 --- a/src/Gui/ViewProviderLink.cpp +++ b/src/Gui/ViewProviderLink.cpp @@ -745,7 +745,7 @@ void ViewProviderLinkObserver::extensionBeforeDelete() { void ViewProviderLinkObserver::extensionReattach(App::DocumentObject *) { if(linkInfo) { linkInfo->pcLinked = - Base::freecad_dynamic_cast(getExtendedContainer()); + freecad_cast(getExtendedContainer()); linkInfo->update(); } } @@ -755,7 +755,7 @@ void ViewProviderLinkObserver::extensionOnChanged(const App::Property *prop) { } void ViewProviderLinkObserver::extensionModeSwitchChange() { - auto owner = freecad_dynamic_cast(getExtendedContainer()); + auto owner = freecad_cast(getExtendedContainer()); if(owner && linkInfo) linkInfo->updateSwitch(); } @@ -1026,7 +1026,7 @@ void LinkView::setMaterial(int index, const App::Material *material) { } void LinkView::setLink(App::DocumentObject *obj, const std::vector &subs) { - setLinkViewObject(Base::freecad_dynamic_cast( + setLinkViewObject(freecad_cast( Application::Instance->getViewProvider(obj)),subs); } @@ -1743,7 +1743,7 @@ QPixmap ViewProviderLink::getOverlayPixmap() const { void ViewProviderLink::onChanged(const App::Property* prop) { if(prop==&ChildViewProvider) { - childVp = freecad_dynamic_cast(ChildViewProvider.getObject().get()); + childVp = freecad_cast(ChildViewProvider.getObject().get()); if(childVp && getObject()) { if(strcmp(childVp->getTypeId().getName(),getObject()->getViewProviderName())!=0 && !childVp->allowOverride(*getObject())) @@ -1864,7 +1864,7 @@ void ViewProviderLink::updateDataPrivate(App::LinkBaseExtension *ext, const App: } }else if(prop == ext->getLinkCopyOnChangeGroupProperty()) { if (auto group = ext->getLinkCopyOnChangeGroupValue()) { - auto vp = Base::freecad_dynamic_cast( + auto vp = freecad_cast( Application::Instance->getViewProvider(group)); if (vp) { vp->hide(); @@ -1915,7 +1915,7 @@ void ViewProviderLink::updateDataPrivate(App::LinkBaseExtension *ext, const App: }else if(prop == ext->_getShowElementProperty()) { if(!ext->_getShowElementValue()) { - auto linked = freecad_dynamic_cast(getLinkedView(true,ext)); + auto linked = freecad_cast(getLinkedView(true,ext)); if(linked && linked->getDocument()==getDocument()) linked->hide(); @@ -1929,9 +1929,9 @@ void ViewProviderLink::updateDataPrivate(App::LinkBaseExtension *ext, const App: bool hasMaterial = false; materials.reserve(elements.size()); for(size_t i=0;i(elements[i]); + auto element = freecad_cast(elements[i]); if(!element) continue; - auto vp = freecad_dynamic_cast( + auto vp = freecad_cast( Application::Instance->getViewProvider(element)); if(!vp) continue; overrideMaterial = overrideMaterial || vp->OverrideMaterial.getValue(); @@ -2016,7 +2016,7 @@ void ViewProviderLink::updateElementList(App::LinkBaseExtension *ext) { int i=-1; for(auto obj : elements) { ++i; - auto vp = freecad_dynamic_cast( + auto vp = freecad_cast( Application::Instance->getViewProvider(obj)); if(!vp) continue; if(OverrideMaterialList.getSize()>i) @@ -2234,7 +2234,7 @@ bool ViewProviderLink::canDropObjectEx(App::DocumentObject *obj, if(!hasSubName && linkView->isLinked()) { auto linked = getLinkedView(false,ext); if(linked) { - auto linkedVdp = freecad_dynamic_cast(linked); + auto linkedVdp = freecad_cast(linked); if(linkedVdp) { if(linkedVdp->getObject()==obj || linkedVdp->getObject()==owner) return false; @@ -2243,7 +2243,7 @@ bool ViewProviderLink::canDropObjectEx(App::DocumentObject *obj, } } if(obj->getDocument() != getObject()->getDocument() && - !freecad_dynamic_cast(ext->getLinkedObjectProperty())) + !freecad_cast(ext->getLinkedObjectProperty())) return false; return true; @@ -2600,7 +2600,7 @@ void ViewProviderLink::_setupContextMenu( App::LinkBaseExtension *ext, QMenu* menu, QObject* receiver, const char* member) { if(linkEdit(ext)) { - if (auto linkvp = Base::freecad_dynamic_cast(linkView->getLinkedView())) + if (auto linkvp = freecad_cast(linkView->getLinkedView())) linkvp->_setupContextMenu(ext, menu, receiver, member); else linkView->getLinkedView()->setupContextMenu(menu,receiver,member); @@ -2743,7 +2743,7 @@ bool ViewProviderLink::initDraggingPlacement() { { App::PropertyPlacement *propPla = nullptr; if(ext->getLinkTransformValue() && ext->getLinkedObjectValue()) { - propPla = Base::freecad_dynamic_cast( + propPla = freecad_cast( ext->getLinkedObjectValue()->getPropertyByName("Placement")); } if(propPla) { @@ -2828,7 +2828,7 @@ ViewProvider *ViewProviderLink::startEditing(int mode) { FC_ERR("no linked object"); return nullptr; } - auto vpd = freecad_dynamic_cast( + auto vpd = freecad_cast( Application::Instance->getViewProvider(linked)); if(!vpd) { FC_ERR("no linked viewprovider"); @@ -3018,7 +3018,7 @@ std::map ViewProviderLink::getElementColors(const char auto link = vp->getObject()->getLinkedObject(false); if(!link || link==vp->getObject()) break; - auto next = freecad_dynamic_cast( + auto next = freecad_cast( Application::Instance->getViewProvider(link)); if(!next) break; @@ -3341,7 +3341,7 @@ ViewProviderDocumentObject *ViewProviderLink::getLinkedViewProvider( linked = ext->getTrueLinkedObject(recursive); if(!linked) return self; - auto res = Base::freecad_dynamic_cast( + auto res = freecad_cast( Application::Instance->getViewProvider(linked)); if(res) return res; diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index f36d561ce7..e5a717ba67 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -319,9 +319,9 @@ void PropertyEditor::openEditor(const QModelIndex& index) } auto prop = items[0]; auto parent = prop->getContainer(); - auto obj = Base::freecad_dynamic_cast(parent); + auto obj = freecad_cast(parent); if (!obj) { - auto view = Base::freecad_dynamic_cast(parent); + auto view = freecad_cast(parent); if (view) { obj = view->getObject(); } diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 37031fd741..d4e4c8b335 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -158,7 +158,7 @@ void PropertyItem::setPropertyData(const std::vector& items) try { // Check for 'DocumentObject' as parent because otherwise 'ObjectIdentifier' raises an // exception - auto* docObj = Base::freecad_dynamic_cast(prop.getContainer()); + auto* docObj = freecad_cast(prop.getContainer()); if (docObj && !docObj->isReadOnly(&prop)) { App::ObjectIdentifier id(prop); std::vector paths; @@ -4558,7 +4558,7 @@ void LinkLabel::updatePropertyLink() { QString text; auto owner = objProp.getObject(); - auto prop = Base::freecad_dynamic_cast(objProp.getProperty()); + auto prop = freecad_cast(objProp.getProperty()); link = QVariant(); @@ -4673,7 +4673,7 @@ QVariant PropertyLinkItem::data(int column, int role) const QVariant PropertyLinkItem::value(const App::Property* prop) const { - auto propLink = Base::freecad_dynamic_cast(prop); + auto propLink = freecad_cast(prop); if (!propLink) { return {}; } diff --git a/src/Mod/CAM/Gui/ViewProviderPath.cpp b/src/Mod/CAM/Gui/ViewProviderPath.cpp index ce48d19271..24cc979792 100644 --- a/src/Mod/CAM/Gui/ViewProviderPath.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPath.cpp @@ -111,8 +111,7 @@ public: } Base::Matrix4D linkMat; auto linked = sobj->getLinkedObject(true, &linkMat, false); - auto vp = Base::freecad_dynamic_cast( - Application::Instance->getViewProvider(linked)); + auto vp = freecad_cast(Application::Instance->getViewProvider(linked)); if (!vp) { setArrow(); return; diff --git a/src/Mod/Drawing/App/FeatureViewSpreadsheet.cpp b/src/Mod/Drawing/App/FeatureViewSpreadsheet.cpp index 3466383018..86b6585e93 100644 --- a/src/Mod/Drawing/App/FeatureViewSpreadsheet.cpp +++ b/src/Mod/Drawing/App/FeatureViewSpreadsheet.cpp @@ -186,13 +186,13 @@ App::DocumentObjectExecReturn* FeatureViewSpreadsheet::execute(void) App::Property* prop = sheet->getPropertyByName(address.toString().c_str()); std::stringstream field; if (prop) { - if (auto* p = Base::freecad_dynamic_cast(prop)) { + if (auto* p = freecad_cast(prop)) { field << p->getValue(); } - else if (auto p = Base::freecad_dynamic_cast(prop)) { + else if (auto p = freecad_cast(prop)) { field << p->getValue(); } - else if (auto p = Base::freecad_dynamic_cast(prop)) { + else if (auto p = freecad_cast(prop)) { field << p->getValue(); } else { diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index ddf41382d1..80a926db7f 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -616,7 +616,7 @@ void FemPostClipFilter::onChanged(const Property* prop) { if (prop == &Function) { - if (auto* value = Base::freecad_dynamic_cast(Function.getValue())) { + if (auto* value = freecad_cast(Function.getValue())) { m_clipper->SetClipFunction(value->getImplicitFunction()); m_extractor->SetImplicitFunction(value->getImplicitFunction()); } @@ -1078,7 +1078,7 @@ FemPostCutFilter::~FemPostCutFilter() = default; void FemPostCutFilter::onChanged(const Property* prop) { if (prop == &Function) { - if (auto* value = Base::freecad_dynamic_cast(Function.getValue())) { + if (auto* value = freecad_cast(Function.getValue())) { m_cutter->SetCutFunction(value->getImplicitFunction()); } else { diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index 1136682c52..ec29613cd4 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -459,7 +459,7 @@ void FemPostPipeline::onChanged(const Property* prop) value = frames[Frame.getValue()]; } for (const auto& obj : Group.getValues()) { - if (auto* postFilter = Base::freecad_dynamic_cast(obj)) { + if (auto* postFilter = freecad_cast(obj)) { postFilter->Frame.setValue(value); } } diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.h b/src/Mod/Fem/Gui/TaskPostBoxes.h index 74842dcc5e..095a380437 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.h +++ b/src/Mod/Fem/Gui/TaskPostBoxes.h @@ -83,7 +83,7 @@ public: template T* getObject() const { - return Base::freecad_dynamic_cast(getObject()); + return freecad_cast(getObject()); } QMetaObject::Connection connSelectPoint; @@ -159,7 +159,7 @@ protected: template T* getObject() const { - return Base::freecad_dynamic_cast(getObject()); + return freecad_cast(getObject()); } template T* getTypedObject() const diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp index 15fc8c01c0..d1a6c8a5d8 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp @@ -94,8 +94,8 @@ ViewProviderFemAnalysis* getAnalyzeView(App::DocumentObject* obj) ViewProviderFemAnalysis* analyzeView = nullptr; App::DocumentObject* grp = App::GroupExtension::getGroupOfObject(obj); - if (Fem::FemAnalysis* analyze = Base::freecad_dynamic_cast(grp)) { - analyzeView = Base::freecad_dynamic_cast( + if (Fem::FemAnalysis* analyze = freecad_cast(grp)) { + analyzeView = freecad_cast( Gui::Application::Instance->getViewProvider(analyze)); } diff --git a/src/Mod/Import/App/ImportOCAF2.cpp b/src/Mod/Import/App/ImportOCAF2.cpp index 6c8778e63f..0acbdf2351 100644 --- a/src/Mod/Import/App/ImportOCAF2.cpp +++ b/src/Mod/Import/App/ImportOCAF2.cpp @@ -478,8 +478,7 @@ bool ImportOCAF2::createGroup(App::Document* doc, auto link = doc->addObject("Link"); link->Label.setValue(child->Label.getValue()); link->setLink(-1, child); - auto pla = Base::freecad_dynamic_cast( - child->getPropertyByName("Placement")); + auto pla = freecad_cast(child->getPropertyByName("Placement")); if (pla) { link->Placement.setValue(pla->getValue()); } diff --git a/src/Mod/Measure/Gui/TaskMeasure.cpp b/src/Mod/Measure/Gui/TaskMeasure.cpp index b5234d62d2..ab03896d8c 100644 --- a/src/Mod/Measure/Gui/TaskMeasure.cpp +++ b/src/Mod/Measure/Gui/TaskMeasure.cpp @@ -249,7 +249,7 @@ void TaskMeasure::update() App::DocumentObject* sub = ob->getSubObject(sel.SubName); // Resolve App::Link - if (auto link = Base::freecad_dynamic_cast(sub)) { + if (auto link = freecad_cast(sub)) { sub = link->getLinkedObject(true); } diff --git a/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp b/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp index 8d3bd96af6..6e1095eb0c 100644 --- a/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp +++ b/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp @@ -237,10 +237,8 @@ SbMatrix ViewProviderMeasureDistance::getMatrix() return {}; } - auto prop1 = - Base::freecad_dynamic_cast(pcObject->getPropertyByName("Position1")); - auto prop2 = - Base::freecad_dynamic_cast(pcObject->getPropertyByName("Position2")); + auto prop1 = freecad_cast(pcObject->getPropertyByName("Position1")); + auto prop2 = freecad_cast(pcObject->getPropertyByName("Position2")); if (!prop1 || !prop2) { return {}; @@ -458,10 +456,8 @@ void ViewProviderMeasureDistance::redrawAnnotation() return; } - auto prop1 = - Base::freecad_dynamic_cast(pcObject->getPropertyByName("Position1")); - auto prop2 = - Base::freecad_dynamic_cast(pcObject->getPropertyByName("Position2")); + auto prop1 = freecad_cast(pcObject->getPropertyByName("Position1")); + auto prop2 = freecad_cast(pcObject->getPropertyByName("Position2")); if (!prop1 || !prop2) { return; diff --git a/src/Mod/Mesh/Gui/ViewProvider.cpp b/src/Mod/Mesh/Gui/ViewProvider.cpp index 41446b94f8..60abc7b905 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.cpp +++ b/src/Mod/Mesh/Gui/ViewProvider.cpp @@ -386,12 +386,12 @@ void ViewProviderMesh::setOpenEdgeColorFrom(const Base::Color& c) const Mesh::PropertyMeshKernel& ViewProviderMesh::getMeshProperty() const { - return Base::freecad_dynamic_cast(getObject())->Mesh; + return freecad_cast(getObject())->Mesh; } Mesh::PropertyMeshKernel& ViewProviderMesh::getMeshProperty() { - return Base::freecad_dynamic_cast(getObject())->Mesh; + return freecad_cast(getObject())->Mesh; } const Mesh::MeshObject& ViewProviderMesh::getMeshObject() const @@ -2420,15 +2420,14 @@ void ViewProviderMesh::highlightColors() { const Mesh::MeshObject& rMesh = getMeshObject(); { - auto prop = Base::freecad_dynamic_cast( - pcObject->getPropertyByName("FaceColors")); + auto prop = freecad_cast(pcObject->getPropertyByName("FaceColors")); if (prop && prop->getSize() == int(rMesh.countFacets())) { setColorPerFace(prop); } } { - auto prop = Base::freecad_dynamic_cast( - pcObject->getPropertyByName("VertexColors")); + auto prop = + freecad_cast(pcObject->getPropertyByName("VertexColors")); if (prop && prop->getSize() == int(rMesh.countPoints())) { setColorPerVertex(prop); } @@ -2439,15 +2438,14 @@ bool ViewProviderMesh::canHighlightColors() const { const Mesh::MeshObject& rMesh = getMeshObject(); { - auto prop = Base::freecad_dynamic_cast( - pcObject->getPropertyByName("FaceColors")); + auto prop = freecad_cast(pcObject->getPropertyByName("FaceColors")); if (prop && prop->getSize() == int(rMesh.countFacets())) { return true; } } { - auto prop = Base::freecad_dynamic_cast( - pcObject->getPropertyByName("VertexColors")); + auto prop = + freecad_cast(pcObject->getPropertyByName("VertexColors")); if (prop && prop->getSize() == int(rMesh.countPoints())) { return true; } diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp index c726659bbe..6553c469c7 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.cpp +++ b/src/Mod/MeshPart/Gui/Tessellation.cpp @@ -374,7 +374,7 @@ void Tessellation::setFaceColors(int method, App::Document* doc, App::DocumentOb Gui::Application::Instance->getViewProvider(doc->getActiveObject()); auto vpmesh = dynamic_cast(vpm); - auto svp = Base::freecad_dynamic_cast( + auto svp = freecad_cast( Gui::Application::Instance->getViewProvider(obj)); if (vpmesh && svp) { std::vector diff_col = svp->ShapeAppearance.getDiffuseColors(); @@ -463,7 +463,7 @@ QString Tessellation::getStandardParameters(App::DocumentObject* obj) const param += QStringLiteral(",Segments=True"); } - auto svp = Base::freecad_dynamic_cast( + auto svp = freecad_cast( Gui::Application::Instance->getViewProvider(obj)); if (ui->groupsFaceColors->isChecked() && svp) { // TODO: currently, we can only retrieve part feature diff --git a/src/Mod/Part/App/AttachExtension.cpp b/src/Mod/Part/App/AttachExtension.cpp index 0aaf11602d..d84543c591 100644 --- a/src/Mod/Part/App/AttachExtension.cpp +++ b/src/Mod/Part/App/AttachExtension.cpp @@ -168,7 +168,7 @@ static inline bool getProp(bool force, const char* name, const char* doc) { - prop = Base::freecad_dynamic_cast(owner->getDynamicPropertyByName(name)); + prop = freecad_cast(owner->getDynamicPropertyByName(name)); if (prop || !force) { return false; } @@ -573,7 +573,7 @@ AttachExtension::Properties AttachExtension::getInitedProperties(bool base) App::PropertyPlacement& AttachExtension::getPlacement() const { - auto pla = Base::freecad_dynamic_cast( + auto pla = freecad_cast( getExtendedObject()->getPropertyByName("Placement")); if (!pla) { throw Base::RuntimeError("AttachExtension cannot find placement property"); diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index 4245c39884..0f676335e4 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -215,9 +215,9 @@ bool Geometry::hasSameExtensions(const Geometry& other) const size_t index = 0; for (const auto& ext : extensions) { if (auto persistExt = - Base::freecad_dynamic_cast(ext.get())) { + freecad_cast(ext.get())) { for (; index < other.extensions.size(); ++index) { - if (auto extOther = Base::freecad_dynamic_cast( + if (auto extOther = freecad_cast( other.extensions[index].get())) { if (!persistExt->isSame(*extOther)) { return false; @@ -232,7 +232,7 @@ bool Geometry::hasSameExtensions(const Geometry& other) const } } for (; index < other.extensions.size(); ++index) { - if (Base::freecad_dynamic_cast( + if (freecad_cast( other.extensions[index].get())) { return false; } diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index 15792536de..9481a63b66 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -166,7 +166,7 @@ App::ElementNamePair Feature::getElementName(const char* name, // This function is overridden to provide higher level shape topo names that // are generated on demand, e.g. Wire, Shell, Solid, etc. - auto prop = Base::freecad_dynamic_cast(getPropertyOfGeometry()); + auto prop = freecad_cast(getPropertyOfGeometry()); if (!prop) { return App::GeoFeature::getElementName(name, type); } @@ -1686,7 +1686,7 @@ bool Feature::isElementMappingDisabled(App::PropertyContainer* container) // if (prop && prop->getValue()) { // return true; // } -// if (auto obj = Base::freecad_dynamic_cast(container)) { +// if (auto obj = freecad_cast(container)) { // if (auto doc = obj->getDocument()) { // if (auto prop = propDisableMapping(doc, /*forced*/ false)) { // return prop->getValue(); diff --git a/src/Mod/Part/App/PropertyGeometryList.cpp b/src/Mod/Part/App/PropertyGeometryList.cpp index 604ceacdce..1f0138255e 100644 --- a/src/Mod/Part/App/PropertyGeometryList.cpp +++ b/src/Mod/Part/App/PropertyGeometryList.cpp @@ -191,7 +191,7 @@ void PropertyGeometryList::trySaveGeometry(Geometry * geom, Base::Writer &writer geom->Save(writer); for( auto & ext : geom->getExtensions() ) { auto extension = ext.lock(); - auto gpe = freecad_dynamic_cast(extension.get()); + auto gpe = freecad_cast(extension.get()); if (gpe) gpe->postSave(writer); } @@ -232,7 +232,7 @@ void PropertyGeometryList::Save(Writer &writer) const << _lValueList[i]->getTypeId().getName() << "\""; for (auto &e : _lValueList[i]->getExtensions() ) { auto ext = e.lock(); - if (auto gpe = freecad_dynamic_cast(ext.get())) { + if (auto gpe = freecad_cast(ext.get())) { gpe->preSave(writer); } } diff --git a/src/Mod/Part/App/PropertyTopoShape.cpp b/src/Mod/Part/App/PropertyTopoShape.cpp index d874442c27..b5fe8a3d16 100644 --- a/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/src/Mod/Part/App/PropertyTopoShape.cpp @@ -67,7 +67,7 @@ void PropertyPartShape::setValue(const TopoShape& sh) { aboutToSetValue(); _Shape = sh; - auto obj = Base::freecad_dynamic_cast(getContainer()); + auto obj = freecad_cast(getContainer()); if(obj) { auto tag = obj->getID(); if(_Shape.Tag && tag!=_Shape.Tag) { @@ -109,7 +109,7 @@ const TopoShape& PropertyPartShape::getShape() const // res.Tag = -1; // else if (!res.Tag) { if (!_Shape.Tag) { - if (auto parent = Base::freecad_dynamic_cast(getContainer())) { + if (auto parent = freecad_cast(getContainer())) { _Shape.Tag = parent->getID(); } } @@ -219,7 +219,7 @@ App::Property *PropertyPartShape::Copy() const void PropertyPartShape::Paste(const App::Property &from) { - auto prop = Base::freecad_dynamic_cast(&from); + auto prop = freecad_cast(&from); if(prop) { setValue(prop->_Shape); _Ver = prop->_Ver; @@ -249,7 +249,7 @@ void PropertyPartShape::beforeSave() const { _HasherIndex = 0; _SaveHasher = false; - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); if(owner && !_Shape.isNull() && _Shape.getElementMapSize()>0) { auto ret = owner->getDocument()->addStringHasher(_Shape.Hasher); _HasherIndex = ret.second; @@ -323,7 +323,7 @@ void PropertyPartShape::Restore(Base::XMLReader &reader) { reader.readElement("Part"); - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); _Ver = "?"; bool has_ver = reader.hasAttribute("ElementMap"); if (has_ver) @@ -943,7 +943,7 @@ void PropertyShapeCache::setPyObject(PyObject *value) { * @return The shape cache, or null if we aren't creating and it doesn't exist */ PropertyShapeCache *PropertyShapeCache::get(const App::DocumentObject *obj, bool create) { - auto prop = Base::freecad_dynamic_cast( + auto prop = freecad_cast( obj->getDynamicPropertyByName(SHAPE_CACHE_NAME)); if(prop && prop->getContainer()==obj) return prop; diff --git a/src/Mod/Part/Gui/CommandSimple.cpp b/src/Mod/Part/Gui/CommandSimple.cpp index 70d0ee2ea3..e470632456 100644 --- a/src/Mod/Part/Gui/CommandSimple.cpp +++ b/src/Mod/Part/Gui/CommandSimple.cpp @@ -154,12 +154,12 @@ void CmdPartPointsFromMesh::activated(int iMsg) double distance{1.0}; auto found = std::find_if(geoms.begin(), geoms.end(), [](App::DocumentObject* obj) { - return Base::freecad_dynamic_cast(obj); + return freecad_cast(obj); }); if (found != geoms.end()) { - double defaultDistance = getDefaultDistance(Base::freecad_dynamic_cast(*found)); + double defaultDistance = getDefaultDistance(freecad_cast(*found)); double STD_OCC_TOLERANCE = 1e-6; diff --git a/src/Mod/PartDesign/App/Body.cpp b/src/Mod/PartDesign/App/Body.cpp index 6f3ec09edd..ea9f6a977d 100644 --- a/src/Mod/PartDesign/App/Body.cpp +++ b/src/Mod/PartDesign/App/Body.cpp @@ -194,7 +194,7 @@ bool Body::isSolidFeature(const App::DocumentObject *obj) // Datum objects are not solid return false; } - if (auto transFeature = Base::freecad_dynamic_cast(obj)) { + if (auto transFeature = freecad_cast(obj)) { // Transformed Features inside a MultiTransform are not solid features return !transFeature->isMultiTransformChild(); } diff --git a/src/Mod/PartDesign/App/Feature.cpp b/src/Mod/PartDesign/App/Feature.cpp index 868c619e31..2447d5ed42 100644 --- a/src/Mod/PartDesign/App/Feature.cpp +++ b/src/Mod/PartDesign/App/Feature.cpp @@ -389,7 +389,7 @@ TopoShape Feature::makeTopoShapeFromPlane(const App::DocumentObject* obj) Body* Feature::getFeatureBody() const { - auto body = Base::freecad_dynamic_cast(_Body.getValue()); + auto body = freecad_cast(_Body.getValue()); if(body) return body; diff --git a/src/Mod/PartDesign/App/FeatureDressUp.cpp b/src/Mod/PartDesign/App/FeatureDressUp.cpp index d98a3ab7ad..84241b36b3 100644 --- a/src/Mod/PartDesign/App/FeatureDressUp.cpp +++ b/src/Mod/PartDesign/App/FeatureDressUp.cpp @@ -310,7 +310,7 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap // feature (which must be of type FeatureAddSub), and skipping // any consecutive DressUp in-between. for(Feature *current=this; ;current=static_cast(base)) { - base = Base::freecad_dynamic_cast(current->getBaseObject(true)); + base = freecad_cast(current->getBaseObject(true)); if(!base) FC_THROWM(Base::CADKernelError, "Cannot find additive or subtractive support for " << getFullName()); diff --git a/src/Mod/PartDesign/App/FeatureMultiTransform.cpp b/src/Mod/PartDesign/App/FeatureMultiTransform.cpp index 14cc57177b..9ba3453299 100644 --- a/src/Mod/PartDesign/App/FeatureMultiTransform.cpp +++ b/src/Mod/PartDesign/App/FeatureMultiTransform.cpp @@ -52,7 +52,7 @@ void MultiTransform::positionBySupport() PartDesign::Transformed::positionBySupport(); std::vector transFeatures = Transformations.getValues(); for (auto f : transFeatures) { - auto transFeature = Base::freecad_dynamic_cast(f); + auto transFeature = freecad_cast(f); if (!transFeature) { throw Base::TypeError("Transformation features must be subclasses of Transformed"); } @@ -85,7 +85,7 @@ MultiTransform::getTransformations(const std::vector origi // Find centre of gravity of first original // FIXME: This method will NOT give the expected result for more than one original! if (auto addFeature = - Base::freecad_dynamic_cast(originals.front())) { + freecad_cast(originals.front())) { TopoDS_Shape original = addFeature->AddSubShape.getShape().getShape(); GProp_GProps props; @@ -98,7 +98,7 @@ MultiTransform::getTransformations(const std::vector origi std::list cogs; for (auto const& f : transFeatures) { - auto transFeature = Base::freecad_dynamic_cast(f); + auto transFeature = freecad_cast(f); if (!transFeature) { throw Base::TypeError("Transformation features must be subclasses of Transformed"); } diff --git a/src/Mod/PartDesign/App/FeatureScaled.cpp b/src/Mod/PartDesign/App/FeatureScaled.cpp index a6a0b8fd7d..0bbd29ec81 100644 --- a/src/Mod/PartDesign/App/FeatureScaled.cpp +++ b/src/Mod/PartDesign/App/FeatureScaled.cpp @@ -72,7 +72,7 @@ Scaled::getTransformations(const std::vector originals) if (!originals.empty()) { // Find centre of gravity of first original // FIXME: This method will NOT give the expected result for more than one original! - if (auto feature = Base::freecad_dynamic_cast(originals.front())) { + if (auto feature = freecad_cast(originals.front())) { TopoDS_Shape original = feature->AddSubShape.getShape().getShape(); GProp_GProps props; diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 3c3afbb2ad..f43e0c8949 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -1449,7 +1449,7 @@ Base::Vector3d ProfileBased::getProfileNormal() const { // If the shape is a line, then return an arbitrary direction that is perpendicular to the line auto geom = Part::Geometry::fromShape(shape.getSubShape(TopAbs_EDGE, 1), true); - auto geomLine = Base::freecad_dynamic_cast(geom.get()); + auto geomLine = freecad_cast(geom.get()); if (geomLine) { Base::Vector3d dir = geomLine->getDir(); double x = std::fabs(dir.x); diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index 50fb6ff218..e6d439715b 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -95,7 +95,7 @@ Part::Feature* Transformed::getBaseObject(bool silent) const // first App::DocumentObject* firstOriginal = originals.empty() ? nullptr : originals.front(); if (firstOriginal) { - rv = Base::freecad_dynamic_cast(firstOriginal); + rv = freecad_cast(firstOriginal); if (!rv) { err = QT_TRANSLATE_NOOP("Exception", "Transformation feature Linked object is not a Part object"); @@ -117,19 +117,19 @@ App::DocumentObject* Transformed::getSketchObject() const std::vector originals = Originals.getValues(); DocumentObject const* firstOriginal = !originals.empty() ? originals.front() : nullptr; - if (auto feature = Base::freecad_dynamic_cast(firstOriginal)) { + if (auto feature = freecad_cast(firstOriginal)) { return feature->getVerifiedSketch(true); } - if (Base::freecad_dynamic_cast(firstOriginal)) { + if (freecad_cast(firstOriginal)) { return nullptr; } - if (auto pattern = Base::freecad_dynamic_cast(this)) { + if (auto pattern = freecad_cast(this)) { return pattern->Direction.getValue(); } - if (auto pattern = Base::freecad_dynamic_cast(this)) { + if (auto pattern = freecad_cast(this)) { return pattern->Axis.getValue(); } - if (auto pattern = Base::freecad_dynamic_cast(this)) { + if (auto pattern = freecad_cast(this)) { return pattern->MirrorPlane.getValue(); } @@ -147,7 +147,7 @@ bool Transformed::isMultiTransformChild() const // because the dependencies are only established after creation. /* for (auto const* obj : getInList()) { - auto mt = Base::freecad_dynamic_cast(obj); + auto mt = freecad_cast(obj); if (!mt) { continue; } @@ -175,7 +175,7 @@ void Transformed::handleChangedPropertyType(Base::XMLReader& reader, // The property 'Angle' of PolarPattern has changed from PropertyFloat // to PropertyAngle and the property 'Length' has changed to PropertyLength. Base::Type inputType = Base::Type::fromName(TypeName); - if (auto property = Base::freecad_dynamic_cast(prop); + if (auto property = freecad_cast(prop); property != nullptr && inputType.isDerivedFrom(App::PropertyFloat::getClassTypeId())) { // Do not directly call the property's Restore method in case the implementation // has changed. So, create a temporary PropertyFloat object and assign the value. @@ -214,7 +214,7 @@ App::DocumentObjectExecReturn* Transformed::execute() // there auto eraseIter = std::remove_if(originals.begin(), originals.end(), [](App::DocumentObject const* obj) { - auto feature = Base::freecad_dynamic_cast(obj); + auto feature = freecad_cast(obj); return feature != nullptr && feature->Suppressed.getValue(); }); originals.erase(eraseIter, originals.end()); @@ -298,7 +298,7 @@ App::DocumentObjectExecReturn* Transformed::execute() Part::TopoShape fuseShape; Part::TopoShape cutShape; - auto feature = Base::freecad_dynamic_cast(original); + auto feature = freecad_cast(original); if (!feature) { return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP( "Exception", diff --git a/src/Mod/PartDesign/App/ShapeBinder.cpp b/src/Mod/PartDesign/App/ShapeBinder.cpp index 2f84429815..c97f80a06a 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.cpp +++ b/src/Mod/PartDesign/App/ShapeBinder.cpp @@ -718,7 +718,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) { if (!forced) { bool hit = true; for (auto& v : mats) { - auto prop = Base::freecad_dynamic_cast( + auto prop = freecad_cast( getDynamicPropertyByName(cacheName(v.first))); if (!prop || prop->getValue() != v.second) { hit = false; diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index d01d07ae2b..c8ba66fa9b 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -677,7 +677,7 @@ bool importExternalElements(App::PropertyLinkSub& prop, std::vector(prop.getContainer()); + auto editObj = freecad_cast(prop.getContainer()); if (!editObj) { FC_THROWM(Base::RuntimeError, "Editing object not found"); } @@ -784,7 +784,7 @@ void prepareProfileBased(PartDesign::Body *pcActiveBody, Gui::Command* cmd, cons // Populate the subs parameter by checking for external elements before // we construct our command. - auto ProfileFeature = Base::freecad_dynamic_cast(Feat); + auto ProfileFeature = freecad_cast(Feat); std::vector& cmdSubs = const_cast&>(subs); if (subs.size() == 0) { diff --git a/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp b/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp index 023c8017e6..8ceaa82a74 100644 --- a/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp +++ b/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp @@ -391,7 +391,7 @@ TaskFeaturePick::makeCopy(App::DocumentObject* obj, std::string sub, bool indepe // we are a independent copy, therefore no external geometry was copied. WE therefore // can delete all constraints - if (auto* sketchObj = Base::freecad_dynamic_cast(obj)) { + if (auto* sketchObj = freecad_cast(obj)) { sketchObj->delConstraintsToExternal(); } } diff --git a/src/Mod/PartDesign/Gui/ViewProvider.cpp b/src/Mod/PartDesign/Gui/ViewProvider.cpp index 512b87c62a..328bdde456 100644 --- a/src/Mod/PartDesign/Gui/ViewProvider.cpp +++ b/src/Mod/PartDesign/Gui/ViewProvider.cpp @@ -192,7 +192,7 @@ void ViewProvider::onChanged(const App::Property* prop) { for(App::DocumentObject* obj : body->Group.getValues()) { if(obj->isDerivedFrom() && obj != getObject()) { - auto vpd = Base::freecad_dynamic_cast( + auto vpd = freecad_cast( Gui::Application::Instance->getViewProvider(obj)); if(vpd && vpd->Visibility.getValue()) vpd->Visibility.setValue(false); diff --git a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp index 7c54e1003b..4c447d66ea 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp @@ -413,7 +413,7 @@ void ViewProviderSubShapeBinder::updatePlacement(bool transaction) { std::vector ViewProviderSubShapeBinder::claimChildren() const { std::vector ret; - auto self = Base::freecad_dynamic_cast(getObject()); + auto self = freecad_cast(getObject()); if (self && self->ClaimChildren.getValue() && self->Support.getValue()) { std::set objSet; for (auto& l : self->Support.getSubListValues()) { diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index b3c644c2f0..7d992153c7 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -8226,7 +8226,7 @@ static Part::Geometry *fitArcs(std::vector > &ar double m = 0.0; Base::Vector3d center; for (auto &geo : arcs) { - if (auto arc = Base::freecad_dynamic_cast(geo.get())) { + if (auto arc = freecad_cast(geo.get())) { if (radius == 0.0) { radius = arc->getRadius(); center = arc->getCenter(); diff --git a/src/Mod/Spreadsheet/App/Cell.cpp b/src/Mod/Spreadsheet/App/Cell.cpp index 89414cd1de..73c551d36c 100644 --- a/src/Mod/Spreadsheet/App/Cell.cpp +++ b/src/Mod/Spreadsheet/App/Cell.cpp @@ -250,14 +250,14 @@ bool Cell::getStringContent(std::string& s, bool persistent) const if (expression->hasComponent()) { s = "=" + expression->toString(persistent); } - else if (freecad_dynamic_cast(expression.get())) { + else if (freecad_cast(expression.get())) { s = static_cast(expression.get())->getText(); s = "'" + s; } - else if (freecad_dynamic_cast(expression.get())) { + else if (freecad_cast(expression.get())) { s = "=" + expression->toString(); } - else if (freecad_dynamic_cast(expression.get())) { + else if (freecad_cast(expression.get())) { s = expression->toString(); } else { @@ -274,7 +274,7 @@ bool Cell::getStringContent(std::string& s, bool persistent) const void Cell::afterRestore() { - auto expr = freecad_dynamic_cast(expression.get()); + auto expr = freecad_cast(expression.get()); if (expr) { setContent(expr->getText().c_str()); } @@ -331,13 +331,10 @@ void Cell::setContent(const char* value) try { ExpressionPtr parsedExpr(App::ExpressionParser::parse(owner->sheet(), value)); - if (const auto fraction = - freecad_dynamic_cast(parsedExpr.get())) { + if (const auto fraction = freecad_cast(parsedExpr.get())) { if (fraction->getOperator() == OperatorExpression::UNIT) { - const auto left = - freecad_dynamic_cast(fraction->getLeft()); - const auto right = - freecad_dynamic_cast(fraction->getRight()); + const auto left = freecad_cast(fraction->getLeft()); + const auto right = freecad_cast(fraction->getRight()); if (left && right) { newExpr = std::move(parsedExpr); } @@ -348,23 +345,22 @@ void Cell::setContent(const char* value) // check for numbers in (de)nominator const bool isNumberNom = - freecad_dynamic_cast(fraction->getLeft()); + freecad_cast(fraction->getLeft()); const bool isNumberDenom = - freecad_dynamic_cast(fraction->getRight()); + freecad_cast(fraction->getRight()); // check for numbers with units in (de)nominator const auto opNom = - freecad_dynamic_cast(fraction->getLeft()); + freecad_cast(fraction->getLeft()); const auto opDenom = - freecad_dynamic_cast(fraction->getRight()); + freecad_cast(fraction->getRight()); const bool isQuantityNom = opNom && opNom->getOperator() == OperatorExpression::UNIT; const bool isQuantityDenom = opDenom && opDenom->getOperator() == OperatorExpression::UNIT; // check for units in denomainator - const auto uDenom = - freecad_dynamic_cast(fraction->getRight()); + const auto uDenom = freecad_cast(fraction->getRight()); const bool isUnitDenom = uDenom && uDenom->is(); const bool isNomValid = isNumberNom || isQuantityNom; @@ -375,8 +371,7 @@ void Cell::setContent(const char* value) } } } - else if (const auto number = - freecad_dynamic_cast(parsedExpr.get())) { + else if (const auto number = freecad_cast(parsedExpr.get())) { // NumbersExpressions can accept more than can be parsed with strtod. // Example: 12.34 and 12,34 are both valid NumberExpressions newExpr = std::move(parsedExpr); diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index 211fd79d1c..9a5f4664a0 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -378,7 +378,7 @@ void PropertySheet::Paste(const Property& from) if (!spanChanges.empty()) { mergedCells = froms.mergedCells; - if (auto sheet = Base::freecad_dynamic_cast(getContainer())) { + if (auto sheet = freecad_cast(getContainer())) { for (const auto& addr : spanChanges) { sheet->cellSpanChanged(addr); } @@ -1476,7 +1476,7 @@ void PropertySheet::recomputeDependants(const App::DocumentObject* owner, const // Check for hidden reference. Because a hidden reference is not // protected by cyclic dependency checking, we need to take special // care to prevent it from misbehave. - Sheet* sheet = Base::freecad_dynamic_cast(getContainer()); + Sheet* sheet = freecad_cast(getContainer()); if (!sheet || sheet->testStatus(App::ObjectStatus::Recompute2) || !owner || owner->testStatus(App::ObjectStatus::Recompute2)) { return; @@ -2078,8 +2078,7 @@ PropertySheet::BindingType PropertySheet::getBinding(const Range& range, if (expr->getFunction() == FunctionExpression::TUPLE && expr->getArgs().size() == 3) { if (pTarget) { - if (auto e = - Base::freecad_dynamic_cast(expr->getArgs()[0])) { + if (auto e = freecad_cast(expr->getArgs()[0])) { *pTarget = e->getPath(); } } @@ -2118,8 +2117,7 @@ void PropertySheet::setPathValue(const ObjectIdentifier& path, const boost::any& && Py::Object(seq[1].ptr()).isString() && Py::Object(seq[2].ptr()).isString()) { AtomicPropertyChange signaller(*this, false); auto other = static_cast(seq[0].ptr())->getPropertySheetPtr(); - auto otherOwner = - Base::freecad_dynamic_cast(other->getContainer()); + auto otherOwner = freecad_cast(other->getContainer()); if (!otherOwner) { FC_THROWM(Base::RuntimeError, "Invalid binding of '" << other->getFullName() << " in " @@ -2289,7 +2287,7 @@ void PropertySheet::getLinksTo(std::vector& identifiers, auto subObject = objT.getSubObject(); auto subElement = objT.getOldElementName(); - auto owner = Base::freecad_dynamic_cast(getContainer()); + auto owner = freecad_cast(getContainer()); for (const auto& [cellName, cellExpression] : data) { if (auto expr = cellExpression->getExpression()) { const auto& deps = expr->getDeps(option); diff --git a/src/Mod/Spreadsheet/App/Sheet.cpp b/src/Mod/Spreadsheet/App/Sheet.cpp index 71da191938..9f7ed76aea 100644 --- a/src/Mod/Spreadsheet/App/Sheet.cpp +++ b/src/Mod/Spreadsheet/App/Sheet.cpp @@ -344,18 +344,16 @@ bool Sheet::exportToFile(const std::string& filename, std::stringstream field; - using Base::freecad_dynamic_cast; - - if (auto p = freecad_dynamic_cast(prop)) { + if (auto p = freecad_cast(prop)) { field << p->getValue(); } - else if (auto p = freecad_dynamic_cast(prop)) { + else if (auto p = freecad_cast(prop)) { field << p->getValue(); } - else if (auto p = freecad_dynamic_cast(prop)) { + else if (auto p = freecad_cast(prop)) { field << p->getValue(); } - else if (auto p = freecad_dynamic_cast(prop)) { + else if (auto p = freecad_cast(prop)) { field << p->getValue(); } else { @@ -595,7 +593,7 @@ Property* Sheet::setFloatProperty(CellAddress key, double value) this->removeDynamicProperty(name.c_str()); propAddress.erase(prop); } - floatProp = freecad_dynamic_cast( + floatProp = freecad_cast( addDynamicProperty("App::PropertyFloat", name.c_str(), nullptr, @@ -623,7 +621,7 @@ Property* Sheet::setIntegerProperty(CellAddress key, long value) this->removeDynamicProperty(name.c_str()); propAddress.erase(prop); } - intProp = freecad_dynamic_cast( + intProp = freecad_cast( addDynamicProperty("App::PropertyInteger", name.c_str(), nullptr, @@ -668,7 +666,7 @@ Property* Sheet::setQuantityProperty(CellAddress key, double value, const Base:: nullptr, nullptr, Prop_ReadOnly | Prop_Hidden | Prop_NoPersist); - quantityProp = freecad_dynamic_cast(p); + quantityProp = freecad_cast(p); } else { quantityProp = static_cast(prop); @@ -697,14 +695,14 @@ Property* Sheet::setStringProperty(CellAddress key, const std::string& value) { std::string name = key.toString(CellAddress::Cell::ShowRowColumn); Property* prop = props.getDynamicPropertyByName(name.c_str()); - PropertyString* stringProp = freecad_dynamic_cast(prop); + PropertyString* stringProp = freecad_cast(prop); if (!stringProp) { if (prop) { this->removeDynamicProperty(name.c_str()); propAddress.erase(prop); } - stringProp = freecad_dynamic_cast( + stringProp = freecad_cast( addDynamicProperty("App::PropertyString", name.c_str(), nullptr, @@ -722,14 +720,14 @@ Property* Sheet::setObjectProperty(CellAddress key, Py::Object object) { std::string name = key.toString(CellAddress::Cell::ShowRowColumn); Property* prop = props.getDynamicPropertyByName(name.c_str()); - PropertyPythonObject* pyProp = freecad_dynamic_cast(prop); + PropertyPythonObject* pyProp = freecad_cast(prop); if (!pyProp) { if (prop) { this->removeDynamicProperty(name.c_str()); propAddress.erase(prop); } - pyProp = freecad_dynamic_cast( + pyProp = freecad_cast( addDynamicProperty("App::PropertyPythonObject", name.c_str(), nullptr, @@ -796,10 +794,10 @@ void Sheet::updateProperty(CellAddress key) /* Eval returns either NumberExpression or StringExpression, or * PyObjectExpression objects */ - auto number = freecad_dynamic_cast(output.get()); + auto number = freecad_cast(output.get()); if (number) { long l; - auto constant = freecad_dynamic_cast(output.get()); + auto constant = freecad_cast(output.get()); if (constant && !constant->isNumber()) { Base::PyGILStateLocker lock; setObjectProperty(key, constant->getPyValue()); @@ -815,13 +813,13 @@ void Sheet::updateProperty(CellAddress key) } } else { - auto str_expr = freecad_dynamic_cast(output.get()); + auto str_expr = freecad_cast(output.get()); if (str_expr) { setStringProperty(key, str_expr->getText().c_str()); } else { Base::PyGILStateLocker lock; - auto py_expr = freecad_dynamic_cast(output.get()); + auto py_expr = freecad_cast(output.get()); if (py_expr) { setObjectProperty(key, py_expr->getPyValue()); } diff --git a/src/Mod/Spreadsheet/Gui/Command.cpp b/src/Mod/Spreadsheet/Gui/Command.cpp index edc1a4ecb8..220a70a534 100644 --- a/src/Mod/Spreadsheet/Gui/Command.cpp +++ b/src/Mod/Spreadsheet/Gui/Command.cpp @@ -71,7 +71,7 @@ void CmdSpreadsheetMergeCells::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -101,7 +101,7 @@ bool CmdSpreadsheetMergeCells::isActive() if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { return (sheetView->selectedIndexesRaw().size() > 1); @@ -132,7 +132,7 @@ void CmdSpreadsheetSplitCell::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -157,7 +157,7 @@ bool CmdSpreadsheetSplitCell::isActive() if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { QModelIndex current = sheetView->currentIndex(); @@ -246,7 +246,7 @@ void CmdSpreadsheetExport::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -263,7 +263,7 @@ bool CmdSpreadsheetExport::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -292,7 +292,7 @@ void CmdSpreadsheetAlignLeft::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -320,7 +320,7 @@ bool CmdSpreadsheetAlignLeft::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -349,7 +349,7 @@ void CmdSpreadsheetAlignCenter::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -377,7 +377,7 @@ bool CmdSpreadsheetAlignCenter::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -406,7 +406,7 @@ void CmdSpreadsheetAlignRight::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -434,7 +434,7 @@ bool CmdSpreadsheetAlignRight::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -463,7 +463,7 @@ void CmdSpreadsheetAlignTop::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -491,7 +491,7 @@ bool CmdSpreadsheetAlignTop::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -520,7 +520,7 @@ void CmdSpreadsheetAlignBottom::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -548,7 +548,7 @@ bool CmdSpreadsheetAlignBottom::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -577,7 +577,7 @@ void CmdSpreadsheetAlignVCenter::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -605,7 +605,7 @@ bool CmdSpreadsheetAlignVCenter::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -635,7 +635,7 @@ void CmdSpreadsheetStyleBold::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -689,7 +689,7 @@ bool CmdSpreadsheetStyleBold::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -719,7 +719,7 @@ void CmdSpreadsheetStyleItalic::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -773,7 +773,7 @@ bool CmdSpreadsheetStyleItalic::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -803,7 +803,7 @@ void CmdSpreadsheetStyleUnderline::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -857,7 +857,7 @@ bool CmdSpreadsheetStyleUnderline::isActive() { if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); - if (activeWindow && freecad_dynamic_cast(activeWindow)) { + if (activeWindow && freecad_cast(activeWindow)) { return true; } } @@ -887,7 +887,7 @@ void CmdSpreadsheetSetAlias::activated(int iMsg) if (getActiveGuiDocument()) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -921,7 +921,7 @@ bool CmdSpreadsheetSetAlias::isActive() if (activeWindow) { SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { QModelIndexList selection = sheetView->selectedIndexes(); diff --git a/src/Mod/Spreadsheet/Gui/DlgBindSheet.cpp b/src/Mod/Spreadsheet/Gui/DlgBindSheet.cpp index 6df7a3a10c..feece7f35f 100644 --- a/src/Mod/Spreadsheet/Gui/DlgBindSheet.cpp +++ b/src/Mod/Spreadsheet/Gui/DlgBindSheet.cpp @@ -168,10 +168,10 @@ void DlgBindSheet::accept() if (!doc) { FC_THROWM(Base::RuntimeError, "Cannot find document " << docname); } - obj = Base::freecad_dynamic_cast(doc->getObject(sep + 1)); + obj = freecad_cast(doc->getObject(sep + 1)); } else { - obj = Base::freecad_dynamic_cast(sheet->getDocument()->getObject(ref)); + obj = freecad_cast(sheet->getDocument()->getObject(ref)); } if (!obj) { FC_THROWM(Base::RuntimeError, "Cannot find Spreadsheet '" << ref << "'"); diff --git a/src/Mod/Spreadsheet/Gui/DlgSheetConf.cpp b/src/Mod/Spreadsheet/Gui/DlgSheetConf.cpp index 41f73305c6..82f710db2b 100644 --- a/src/Mod/Spreadsheet/Gui/DlgSheetConf.cpp +++ b/src/Mod/Spreadsheet/Gui/DlgSheetConf.cpp @@ -140,7 +140,7 @@ App::Property* DlgSheetConf::prepare(CellAddress& from, if (cell && cell->getExpression()) { auto expr = cell->getExpression(); if (expr->isDerivedFrom()) { - auto fexpr = Base::freecad_dynamic_cast(cell->getExpression()); + auto fexpr = freecad_cast(cell->getExpression()); if (fexpr && (fexpr->getFunction() == FunctionExpression::HREF || fexpr->getFunction() == FunctionExpression::HIDDENREF) @@ -148,12 +148,11 @@ App::Property* DlgSheetConf::prepare(CellAddress& from, expr = fexpr->getArgs().front(); } } - auto vexpr = Base::freecad_dynamic_cast(expr); + auto vexpr = freecad_cast(expr); if (vexpr) { - auto prop = - Base::freecad_dynamic_cast(vexpr->getPath().getProperty()); + auto prop = freecad_cast(vexpr->getPath().getProperty()); if (prop) { - auto obj = Base::freecad_dynamic_cast(prop->getContainer()); + auto obj = freecad_cast(prop->getContainer()); if (obj && prop->hasName()) { path = ObjectIdentifier(sheet); path.setDocumentObjectName(obj, true); diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp index 6998e86773..f44cf08b90 100644 --- a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp @@ -146,7 +146,7 @@ void ViewProviderSheet::setupContextMenu(QMenu* menu, QObject* receiver, const c Sheet* ViewProviderSheet::getSpreadsheetObject() const { - return freecad_dynamic_cast(pcObject); + return freecad_cast(pcObject); } void ViewProviderSheet::beforeDelete() diff --git a/src/Mod/Spreadsheet/Gui/Workbench.cpp b/src/Mod/Spreadsheet/Gui/Workbench.cpp index c76e17d451..ca0cb3db8d 100644 --- a/src/Mod/Spreadsheet/Gui/Workbench.cpp +++ b/src/Mod/Spreadsheet/Gui/Workbench.cpp @@ -129,7 +129,7 @@ void WorkbenchHelper::setForegroundColor(const QColor& color) if (doc) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); @@ -163,7 +163,7 @@ void WorkbenchHelper::setBackgroundColor(const QColor& color) if (doc) { Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow(); SpreadsheetGui::SheetView* sheetView = - freecad_dynamic_cast(activeWindow); + freecad_cast(activeWindow); if (sheetView) { Sheet* sheet = sheetView->getSheet(); diff --git a/src/Mod/TechDraw/Gui/QGSPage.cpp b/src/Mod/TechDraw/Gui/QGSPage.cpp index d5d612d93e..8a3e41075a 100644 --- a/src/Mod/TechDraw/Gui/QGSPage.cpp +++ b/src/Mod/TechDraw/Gui/QGSPage.cpp @@ -390,51 +390,49 @@ bool QGSPage::attachView(App::DocumentObject* obj) QGIView* qview(nullptr); - using Base::freecad_dynamic_cast; - - if (auto o = freecad_dynamic_cast(obj)) { + if (auto o = freecad_cast(obj)) { qview = addViewSection(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addViewPart(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addProjectionGroup(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addDrawView(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addViewDimension(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addViewBalloon(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addAnnotation(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addDrawViewSymbol(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addDrawViewClip(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addDrawViewSpreadsheet(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addDrawViewImage(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addViewLeader(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addRichAnno(o); } - else if (auto o = freecad_dynamic_cast(obj)) { + else if (auto o = freecad_cast(obj)) { qview = addWeldSymbol(o); } - else if (freecad_dynamic_cast(obj)) { + else if (freecad_cast(obj)) { //Hatch is not attached like other Views (since it isn't really a View) return true; } diff --git a/src/Tools/params_utils.py b/src/Tools/params_utils.py index cf9f8389ff..c27d7d291b 100644 --- a/src/Tools/params_utils.py +++ b/src/Tools/params_utils.py @@ -1197,7 +1197,7 @@ class Property: ) cog.out( f""" - if (auto prop = Base::freecad_dynamic_cast<{self.type_name}>( + if (auto prop = freecad_cast<{self.type_name}>( obj->getPropertyByName("{self.name}"))) {{ if (prop->getContainer() == obj) From 5639728e8ae72896be55ce89aa7dc4ac855ccdc0 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 7 Apr 2025 17:34:13 +0200 Subject: [PATCH 166/316] PartDesign: Fix use of App::Planes to create sketches (#20453) --- src/App/Datums.cpp | 35 ++++----- src/App/Datums.h | 35 ++++----- src/App/Document.cpp | 15 +++- src/App/Document.h | 1 + src/Gui/Selection/Selection.cpp | 95 +++++++++++++++++++++++ src/Gui/Selection/Selection.h | 20 +++++ src/Gui/Selection/SelectionFilter.cpp | 13 ++-- src/Gui/Selection/SelectionFilter.h | 5 +- src/Mod/PartDesign/Gui/SketchWorkflow.cpp | 33 +++++--- 9 files changed, 190 insertions(+), 62 deletions(-) diff --git a/src/App/Datums.cpp b/src/App/Datums.cpp index 0d315ed859..b0279766d9 100644 --- a/src/App/Datums.cpp +++ b/src/App/Datums.cpp @@ -39,7 +39,7 @@ PROPERTY_SOURCE(App::DatumElement, App::GeoFeature) PROPERTY_SOURCE(App::Plane, App::DatumElement) PROPERTY_SOURCE(App::Line, App::DatumElement) PROPERTY_SOURCE(App::Point, App::DatumElement) -PROPERTY_SOURCE(App::LocalCoordinateSystem, App::GeoFeature) +PROPERTY_SOURCE_WITH_EXTENSIONS(App::LocalCoordinateSystem, App::GeoFeature) DatumElement::DatumElement(bool hideRole) : baseDir{0.0, 0.0, 1.0} @@ -125,7 +125,6 @@ Point::Point() // ---------------------------------------------------------------------------- LocalCoordinateSystem::LocalCoordinateSystem() - : extension(this) { ADD_PROPERTY_TYPE(OriginFeatures, (nullptr), @@ -133,8 +132,11 @@ LocalCoordinateSystem::LocalCoordinateSystem() App::Prop_Hidden, "Axis and baseplanes controlled by the LCS"); + Group.setStatus(Property::Transient, true); + setStatus(App::NoAutoExpand, true); - extension.initExtension(this); + + GroupExtension::initExtension(this); } @@ -201,12 +203,6 @@ App::Point* LocalCoordinateSystem::getPoint(const char* role) const throw Base::RuntimeError(err.str().c_str()); } -bool LocalCoordinateSystem::hasObject(const DocumentObject* obj) const -{ - const auto& features = OriginFeatures.getValues(); - return std::ranges::find(features, obj) != features.end(); -} - short LocalCoordinateSystem::mustExecute() const { if (OriginFeatures.isTouched()) { @@ -340,18 +336,7 @@ void LocalCoordinateSystem::migrateOriginPoint() // ---------------------------------------------------------------------------- -LocalCoordinateSystem::LCSExtension::LCSExtension(LocalCoordinateSystem* obj) - : obj(obj) -{ - Group.setStatus(Property::Transient, true); -} - -void LocalCoordinateSystem::LCSExtension::initExtension(ExtensionContainer* obj) -{ - App::GroupExtension::initExtension(obj); -} - -bool LocalCoordinateSystem::LCSExtension::extensionGetSubObject(DocumentObject*& ret, +bool LocalCoordinateSystem::extensionGetSubObject(DocumentObject*& ret, const char* subname, PyObject** pyobj, Base::Matrix4D* mat, @@ -380,7 +365,7 @@ bool LocalCoordinateSystem::LCSExtension::extensionGetSubObject(DocumentObject*& } try { - ret = obj->getDatumElement(name.c_str()); + ret = getDatumElement(name.c_str()); if (!ret) { return false; } @@ -399,3 +384,9 @@ bool LocalCoordinateSystem::LCSExtension::extensionGetSubObject(DocumentObject*& return false; } } + +bool LocalCoordinateSystem::hasObject(const DocumentObject* obj, [[maybe_unused]] bool recursive) const +{ + const auto& features = OriginFeatures.getValues(); + return std::ranges::find(features, obj) != features.end(); +} diff --git a/src/App/Datums.h b/src/App/Datums.h index 9426f4afc5..e59b854728 100644 --- a/src/App/Datums.h +++ b/src/App/Datums.h @@ -102,10 +102,9 @@ public: } }; - -class AppExport LocalCoordinateSystem: public App::GeoFeature +class AppExport LocalCoordinateSystem: public App::GeoFeature, public App::GeoFeatureGroupExtension { - PROPERTY_HEADER_WITH_OVERRIDE(App::LocalCoordinateSystem); + PROPERTY_HEADER_WITH_EXTENSIONS(App::LocalCoordinateSystem); Q_DECLARE_TR_FUNCTIONS(App::LocalCoordinateSystem) public: @@ -195,9 +194,6 @@ public: App::Point* getPoint(const char* role) const; ///@} - /// Returns true if the given object is part of the origin - bool hasObject(const DocumentObject* obj) const; - /// Returns true on changing DatumElement set short mustExecute() const override; @@ -216,6 +212,17 @@ public: // Axis links PropertyLinkList OriginFeatures; + // GeoFeatureGroupExtension overrides: + bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject**, + Base::Matrix4D*, + bool, + int) const override; + + // Reimplement the hasObject because LCS doesn't use Group but stores objects in OriginFeatures for whatever reason. + bool hasObject(const DocumentObject* obj, bool recursive = false) const override; + protected: /// Checks integrity of the LCS App::DocumentObjectExecReturn* execute() override; @@ -229,22 +236,6 @@ private: struct SetupData; void setupDatumElement(App::PropertyLink& featProp, const SetupData& data); - class LCSExtension: public GeoFeatureGroupExtension - { - LocalCoordinateSystem* obj; - - public: - explicit LCSExtension(LocalCoordinateSystem* obj); - void initExtension(ExtensionContainer* obj) override; - bool extensionGetSubObject(DocumentObject*& ret, - const char* subname, - PyObject**, - Base::Matrix4D*, - bool, - int) const override; - }; - LCSExtension extension; - struct SetupData { Base::Type type; diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 1f51d9d925..ae3da65da5 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -4154,7 +4154,6 @@ const std::vector& Document::getObjects() const return d->objectArray; } - std::vector Document::getObjectsOfType(const Base::Type& typeId) const { std::vector Objects; @@ -4166,6 +4165,20 @@ std::vector Document::getObjectsOfType(const Base::Type& typeId return Objects; } +std::vector Document::getObjectsOfType(const std::vector& types) const +{ + std::vector Objects; + for (auto it : d->objectArray) { + for (auto& typeId : types) { + if (it->isDerivedFrom(typeId)) { + Objects.push_back(it); + break; // Prevent adding several times the same object. + } + } + } + return Objects; +} + std::vector Document::getObjectsWithExtension(const Base::Type& typeId, bool derived) const { diff --git a/src/App/Document.h b/src/App/Document.h index dce5b1a553..a7f9574df0 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -357,6 +357,7 @@ public: /// Returns a list of all Objects const std::vector& getObjects() const; std::vector getObjectsOfType(const Base::Type& typeId) const; + std::vector getObjectsOfType(const std::vector& types) const; /// Returns all object with given extensions. If derived=true also all objects with extensions /// derived from the given one std::vector getObjectsWithExtension(const Base::Type& typeId, diff --git a/src/Gui/Selection/Selection.cpp b/src/Gui/Selection/Selection.cpp index 9aa562fcf2..112edc9e3b 100644 --- a/src/Gui/Selection/Selection.cpp +++ b/src/Gui/Selection/Selection.cpp @@ -311,6 +311,101 @@ std::vector SelectionSingleton::getPickedList(const return temp; } +std::vector SelectionSingleton::getSelectionIn(App::DocumentObject* container, + Base::Type typeId, bool single) const +{ + if (!container) { + return getSelectionEx(nullptr, typeId, ResolveMode::NoResolve, single); + } + + std::vector sels = getSelectionEx(nullptr, App::DocumentObject::getClassTypeId(), ResolveMode::NoResolve, single); + + std::vector ret; + std::map SortMap; + + for (auto& sel : sels) { + auto* rootObj = sel.getObject(); + App::Document* doc = rootObj->getDocument(); + std::vector subs = sel.getSubNames(); + bool objPassed = false; + + for (size_t i = 0; i < subs.size(); ++i) { + auto& sub = subs[i]; + App::DocumentObject* newRootObj = nullptr; + std::string newSub = ""; + + std::vector names = Base::Tools::splitSubName(sub); + + if (container == rootObj) { + objPassed = true; + } + + if (rootObj->isLink()) { + // Update doc in case its an external link. + doc = rootObj->getLinkedObject()->getDocument(); + } + + for (auto& name : names) { + App::DocumentObject* obj = doc->getObject(name.c_str()); + if (!obj) { // We reached the element name (for example 'edge1') + newSub += name; + break; + } + + if (objPassed) { + if (!newRootObj) { + // We are the first object after the container is passed. + newRootObj = obj; + } + else { + newSub += name + "."; + } + } + + if (obj == container) { + objPassed = true; + } + if (obj->isLink()) { + // Update doc in case its an external link. + doc = obj->getLinkedObject()->getDocument(); + } + } + + if (newRootObj) { + // Make sure selected object is of correct type + auto* lastObj = newRootObj->resolve(newSub.c_str()); + if (!lastObj || !lastObj->isDerivedFrom(typeId)) { + continue; + } + + auto it = SortMap.find(newRootObj); + if (it != SortMap.end()) { + // only add sub-element + if (newSub != "") { + ret[it->second].SubNames.emplace_back(newSub); + ret[it->second].SelPoses.emplace_back(sel.SelPoses[i]); + } + } + else { + if (single && !ret.empty()) { + ret.clear(); + break; + } + // create a new entry + ret.emplace_back(newRootObj); + if (newSub != "") { + ret.back().SubNames.emplace_back(newSub); + ret.back().SelPoses.emplace_back(sel.SelPoses[i]); + } + SortMap.insert(std::make_pair(newRootObj, ret.size() - 1)); + } + } + } + } + + return ret; +} + std::vector SelectionSingleton::getSelectionEx(const char* pDocName, Base::Type typeId, ResolveMode resolve, bool single) const { diff --git a/src/Gui/Selection/Selection.h b/src/Gui/Selection/Selection.h index f5e594c249..f207474f26 100644 --- a/src/Gui/Selection/Selection.h +++ b/src/Gui/Selection/Selection.h @@ -445,6 +445,26 @@ public: */ std::vector getSelectionEx(const char* pDocName=nullptr, Base::Type typeId=App::DocumentObject::getClassTypeId(), ResolveMode resolve = ResolveMode::OldStyleElement, bool single=false) const; + /** Returns a vector of selection objects children of an object + * + * @param obj: Object within which you want to find a selection. + * The selection objects returned will be direct children of Obj. The rest of the subname will be unresolved. + * So this is equivalent to ResolveMode::NoResolve, but starting from obj. + * For instance if you have : Assembly.Part.Body.LCS.PlaneXY + * - If obj = Assembly : SelectionObject = Part, subname = "Body.LCS.PlaneXY." + * - If obj = Part : SelectionObject = Body, subname = "LCS.PlaneXY." + * - If obj = Body : SelectionObject = LCS, subname = "PlaneXY." + * The docname used is the document of obj. + * if obj is nullptr, this acts as getSelectionEx with empty docName + * + * @param typeId: specify the type of object to be returned. + * @param single: if set to true, then it will return an empty vector if + * there is more than one selection. + * + * @return The returned vector reflects the sequence of selection. + */ + std::vector getSelectionIn(App::DocumentObject* obj=nullptr, + Base::Type typeId=App::DocumentObject::getClassTypeId(), bool single=false) const; /** * @brief getAsPropertyLinkSubList fills PropertyLinkSubList with current selection. diff --git a/src/Gui/Selection/SelectionFilter.cpp b/src/Gui/Selection/SelectionFilter.cpp index b189ba02cd..75fab0f327 100644 --- a/src/Gui/Selection/SelectionFilter.cpp +++ b/src/Gui/Selection/SelectionFilter.cpp @@ -131,14 +131,16 @@ bool SelectionFilterGatePython::allow(App::Document*, App::DocumentObject* obj, // ---------------------------------------------------------------------------- -SelectionFilter::SelectionFilter(const char* filter) - : Ast(nullptr) +SelectionFilter::SelectionFilter(const char* filter, App::DocumentObject* container) + : Ast(nullptr) + , container(container) { setFilter(filter); } -SelectionFilter::SelectionFilter(const std::string& filter) - : Ast(nullptr) +SelectionFilter::SelectionFilter(const std::string& filter, App::DocumentObject* container) + : Ast(nullptr) + , container(container) { setFilter(filter.c_str()); } @@ -172,8 +174,7 @@ bool SelectionFilter::match() min = it->Slice->Min; max = it->Slice->Max; } - - std::vector temp = Gui::Selection().getSelectionEx(nullptr, it->ObjectType); + std::vector temp = container ? Gui::Selection().getSelectionIn(container, it->ObjectType) : Gui::Selection().getSelectionEx(nullptr, it->ObjectType); // test if subnames present if (it->SubName.empty()) { diff --git a/src/Gui/Selection/SelectionFilter.h b/src/Gui/Selection/SelectionFilter.h index 13981dabbc..c4faf33357 100644 --- a/src/Gui/Selection/SelectionFilter.h +++ b/src/Gui/Selection/SelectionFilter.h @@ -53,8 +53,8 @@ class GuiExport SelectionFilter public: /** Constructs a SelectionFilter object. */ - explicit SelectionFilter(const char* filter); - explicit SelectionFilter(const std::string& filter); + explicit SelectionFilter(const char* filter, App::DocumentObject* container = nullptr); + explicit SelectionFilter(const std::string& filter, App::DocumentObject* container = nullptr); virtual ~SelectionFilter(); /// Set a new filter string @@ -88,6 +88,7 @@ protected: std::string Filter; std::string Errors; bool parse(); + App::DocumentObject* container; std::shared_ptr Ast; }; diff --git a/src/Mod/PartDesign/Gui/SketchWorkflow.cpp b/src/Mod/PartDesign/Gui/SketchWorkflow.cpp index 945bdc5126..7d68c46b76 100644 --- a/src/Mod/PartDesign/Gui/SketchWorkflow.cpp +++ b/src/Mod/PartDesign/Gui/SketchWorkflow.cpp @@ -181,7 +181,7 @@ public: std::string getSupport() const { - return Gui::Command::getObjectCmd(getObject(), "(",",'')"); + return faceSelection.getAsPropertyLinkSubString(); } App::DocumentObject* getObject() const @@ -387,11 +387,17 @@ public: void findDatumPlanes() { App::GeoFeatureGroupExtension *geoGroup = getGroupExtensionOfBody(); - auto datumPlanes( appdocument->getObjectsOfType(PartDesign::Plane::getClassTypeId()) ); + const std::vector types = { PartDesign::Plane::getClassTypeId(), App::Plane::getClassTypeId() }; + auto datumPlanes = appdocument->getObjectsOfType(types); + for (auto plane : datumPlanes) { + if (std::find(planes.begin(), planes.end(), plane) != planes.end()) { + continue; // Skip if already in planes (for base planes) + } + planes.push_back ( plane ); // Check whether this plane belongs to the active body - if ( activeBody->hasObject(plane) ) { + if ( activeBody->hasObject(plane, true) ) { if ( !activeBody->isAfterInsertPoint ( plane ) ) { validPlaneCount++; status.push_back(PartDesignGui::TaskFeaturePick::validFeature); @@ -675,11 +681,20 @@ private: { // may happen when the user switched to an empty document while the // dialog is open - if (features.empty()) + if (features.empty()) { return; - App::Plane* plane = static_cast(features.front()); + } std::string FeatName = documentOfBody->getUniqueObjectName("Sketch"); - std::string supportString = Gui::Command::getObjectCmd(plane,"(",",[''])"); + auto* plane = static_cast(features.front()); + auto* lcs = plane->getLCS(); + + std::string supportString; + if (lcs) { + supportString = Gui::Command::getObjectCmd(lcs, "(") + ",['" + plane->getNameInDocument() + "'])"; + } + else { + supportString = Gui::Command::getObjectCmd(plane, "(", ",[''])"); + } App::Document* doc = partDesignBody->getDocument(); if (!doc->hasPendingTransaction()) { @@ -797,9 +812,9 @@ std::tuple SketchWorkflow::getFaceAn // a new sketch. // See https://forum.freecad.org/viewtopic.php?f=3&t=44070 - Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1"); - Gui::SelectionFilter PlaneFilter ("SELECT App::Plane COUNT 1"); - Gui::SelectionFilter PlaneFilter2("SELECT PartDesign::Plane COUNT 1"); + Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1", activeBody); + Gui::SelectionFilter PlaneFilter ("SELECT App::Plane COUNT 1", activeBody); + Gui::SelectionFilter PlaneFilter2("SELECT PartDesign::Plane COUNT 1", activeBody); if (PlaneFilter2.match()) { PlaneFilter = PlaneFilter2; From 35b433e56636b3a82b0f4b9a6742f604788dbebb Mon Sep 17 00:00:00 2001 From: Furgo <148809153+furgo16@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:49:26 +0200 Subject: [PATCH 167/316] BIM: add missing ifc_tools import (#20368) * BIM: add module-level import for ifc_tools * Do not load ifc_tools at the start of module to avoid breaking tests --- src/Mod/BIM/bimcommands/BimProjectManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index a22e349a8d..93c0296850 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -124,6 +124,7 @@ class BIM_ProjectManager: if not buildings: buildings = [o for o in doc.Objects if getattr(o, "IfcType", "") == "Building"] if buildings: + from nativeifc import ifc_tools self.building = buildings[0] self.form.buildingName.setText(self.building.Label) levels = ifc_tools.get_children(self.building, ifctype="IfcBuildingStorey") From b9aa5c5d83a4dec91f481a0475b1638f05daced7 Mon Sep 17 00:00:00 2001 From: bdieterm <119257544+bdieterm@users.noreply.github.com> Date: Sun, 30 Mar 2025 16:10:35 +0200 Subject: [PATCH 168/316] CAM: fix context menu callbacks for Qt6 --- src/Mod/CAM/Path/Base/Gui/IconViewProvider.py | 5 ++++- src/Mod/CAM/Path/Main/Gui/Job.py | 5 ++++- src/Mod/CAM/Path/Op/Gui/Base.py | 5 ++++- src/Mod/CAM/Path/Tool/Gui/Controller.py | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Mod/CAM/Path/Base/Gui/IconViewProvider.py b/src/Mod/CAM/Path/Base/Gui/IconViewProvider.py index 6154b3307f..83ab71aabd 100644 --- a/src/Mod/CAM/Path/Base/Gui/IconViewProvider.py +++ b/src/Mod/CAM/Path/Base/Gui/IconViewProvider.py @@ -95,9 +95,12 @@ class ViewProvider(object): edit = translate("Path", "Edit") action = QtGui.QAction(edit, menu) - action.triggered.connect(self.setEdit) + action.triggered.connect(self._editInContextMenuTriggered) menu.addAction(action) + def _editInContextMenuTriggered(self, checked): + self.setEdit() + _factory = {} diff --git a/src/Mod/CAM/Path/Main/Gui/Job.py b/src/Mod/CAM/Path/Main/Gui/Job.py index e5f9e2f060..c2277e83e9 100644 --- a/src/Mod/CAM/Path/Main/Gui/Job.py +++ b/src/Mod/CAM/Path/Main/Gui/Job.py @@ -345,9 +345,12 @@ class ViewProvider: for action in menu.actions(): menu.removeAction(action) action = QtGui.QAction(translate("CAM_Job", "Edit"), menu) - action.triggered.connect(self.setEdit) + action.triggered.connect(self._editInContextMenuTriggered) menu.addAction(action) + def _editInContextMenuTriggered(self, checked): + self.setEdit() + class MaterialDialog(QtWidgets.QDialog): def __init__(self, parent=None): diff --git a/src/Mod/CAM/Path/Op/Gui/Base.py b/src/Mod/CAM/Path/Op/Gui/Base.py index 8203eaefc1..bbd76cf8d9 100644 --- a/src/Mod/CAM/Path/Op/Gui/Base.py +++ b/src/Mod/CAM/Path/Op/Gui/Base.py @@ -187,9 +187,12 @@ class ViewProvider(object): for action in menu.actions(): menu.removeAction(action) action = QtGui.QAction(translate("PathOp", "Edit"), menu) - action.triggered.connect(self.setEdit) + action.triggered.connect(self._editInContextMenuTriggered) menu.addAction(action) + def _editInContextMenuTriggered(self, checked): + self.setEdit() + class TaskPanelPage(object): """Base class for all task panel pages.""" diff --git a/src/Mod/CAM/Path/Tool/Gui/Controller.py b/src/Mod/CAM/Path/Tool/Gui/Controller.py index 29a107943a..7035ba5bb5 100644 --- a/src/Mod/CAM/Path/Tool/Gui/Controller.py +++ b/src/Mod/CAM/Path/Tool/Gui/Controller.py @@ -114,9 +114,12 @@ class ViewProvider: for action in menu.actions(): menu.removeAction(action) action = QtGui.QAction(translate("CAM", "Edit"), menu) - action.triggered.connect(self.setEdit) + action.triggered.connect(self._editInContextMenuTriggered) menu.addAction(action) + def _editInContextMenuTriggered(self, checked): + self.setEdit() + def claimChildren(self): obj = self.vobj.Object if obj and obj.Proxy and obj.Tool: From 45ee9ad16ee04cfc13f92d73493f5af51cd6575d Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Mon, 7 Apr 2025 17:55:41 +0200 Subject: [PATCH 169/316] [Doc] Fix CMake issues for documentation (#20479) * [Doc] Ensure to create the target dir in CMake * [Doc] Fix CMake issue preventing regenerating docs --- src/Doc/CMakeLists.txt | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Doc/CMakeLists.txt b/src/Doc/CMakeLists.txt index d0f659e64f..6662518710 100644 --- a/src/Doc/CMakeLists.txt +++ b/src/Doc/CMakeLists.txt @@ -24,11 +24,16 @@ if(DOXYGEN_FOUND) SET(DOXYGEN_LANGUAGE "English" CACHE STRING "Language used by doxygen") MARK_AS_ADVANCED(DOXYGEN_LANGUAGE) -# note: this test is obsolete if DevDoc target is used + # note: this test is obsolete if DevDoc target is used if (NOT BUILD_GUI) message("Note: Gui is not built. Documentation may lack some parts.") endif (NOT BUILD_GUI) + # Check required options + if(NOT BUILD_FEM) + message(FATAL_ERROR "Web documentation requires BUILD_FEM to be ON.") + endif() + # directory order seems important for correct macro expansion # (files containing macros definitions must be parsed before the files using them) SET(DOXYGEN_SOURCE_DIR ${COIN3D_INCLUDE_DIRS}/Inventor/fields/SoSubField.h @@ -65,7 +70,7 @@ if(DOXYGEN_FOUND) find_package(Coin3DDoc) if( COIN3D_DOC_FOUND ) - SET(DOXYGEN_TAGFILES + SET(DOXYGEN_TAGFILES ${COIN3D_DOC_TAGFILE}=${COIN3D_DOC_PATH} ) endif( COIN3D_DOC_FOUND ) @@ -88,26 +93,25 @@ if(DOXYGEN_FOUND) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mainpage.dox.in ${CMAKE_CURRENT_BINARY_DIR}/mainpage.dox @ONLY) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BuildDevDoc.cfg.in + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BuildDevDoc.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/BuildDevDoc.cfg @ONLY) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BuildWebDoc.cfg.in + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BuildWebDoc.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/BuildWebDoc.cfg @ONLY) - - # reconfigure to have all sources files generated from xml, whatever build options were - # generate source documentation - # delete CMakeCache to reset to default build options next time + + file(MAKE_DIRECTORY "${DOXYGEN_OUTPUT_DIR}") + + # Note that these two targets do not pick up changes in *.pyi and *Py.xml + # files. To ensure these changes are propagated, execute a build before + # executing these targets. ADD_CUSTOM_TARGET(DevDoc - ${CMAKE_COMMAND} -D BUILD_GUI:BOOL=ON -D BUILD_FEM:BOOL=ON ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/Doc/templates ${CMAKE_CURRENT_BINARY_DIR}/templates COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/BuildDevDoc.cfg - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/CMakeCache.txt WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) # lightweight version for the web ADD_CUSTOM_TARGET(WebDoc - ${CMAKE_COMMAND} -D BUILD_GUI:BOOL=ON -D BUILD_FEM:BOOL=ON ${CMAKE_SOURCE_DIR} COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/Doc/templates ${CMAKE_CURRENT_BINARY_DIR}/templates COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/BuildWebDoc.cfg - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/CMakeCache.txt WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) From 967d719bdc37444ae8c61ff3dbaebe3ef85469a9 Mon Sep 17 00:00:00 2001 From: Andrew Shkolik Date: Mon, 24 Mar 2025 17:24:01 -0500 Subject: [PATCH 170/316] Automatically switch to edge selection mode when creating surface --- src/Mod/Surface/Gui/TaskGeomFillSurface.cpp | 5 +++++ src/Mod/Surface/Gui/TaskSections.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/Mod/Surface/Gui/TaskGeomFillSurface.cpp b/src/Mod/Surface/Gui/TaskGeomFillSurface.cpp index 06fd928d5d..90b6456641 100644 --- a/src/Mod/Surface/Gui/TaskGeomFillSurface.cpp +++ b/src/Mod/Surface/Gui/TaskGeomFillSurface.cpp @@ -338,6 +338,11 @@ void GeomFillSurface::open() checkOpenCommand(); this->vp->highlightReferences(true); Gui::Selection().clearSelection(); + + // if the surface is not yet created then automatically start "AppendEdge" mode + if (editedObject->Shape.getShape().isNull()) { + ui->buttonEdgeAdd->setChecked(true); + } } void GeomFillSurface::clearSelection() diff --git a/src/Mod/Surface/Gui/TaskSections.cpp b/src/Mod/Surface/Gui/TaskSections.cpp index 955831a0d3..4b0b2b99ff 100644 --- a/src/Mod/Surface/Gui/TaskSections.cpp +++ b/src/Mod/Surface/Gui/TaskSections.cpp @@ -368,6 +368,11 @@ void SectionsPanel::open() true); Gui::Selection().clearSelection(); + + // if the surface is not yet created then automatically start "AppendEdge" mode + if (editedObject->Shape.getShape().isNull()) { + ui->buttonEdgeAdd->setChecked(true); + } } void SectionsPanel::clearSelection() From 8963a0d8bce901eb0c5f0b7b0a55b87b63323de8 Mon Sep 17 00:00:00 2001 From: drwho495 <70452450+drwho495@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:13:15 -0500 Subject: [PATCH 171/316] Assembly: Fix hasher missing ref warning and speed bug. (#20405) * fixed hasher ref bug and fixed speed of updateJCSPlacements * remove debug info * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix hasher mismatch when editing or creating a joint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix issues raised in PR * add warning * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Mod/Assembly/UtilsAssembly.py | 42 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Mod/Assembly/UtilsAssembly.py b/src/Mod/Assembly/UtilsAssembly.py index b88ca8b24e..0830a7ccc9 100644 --- a/src/Mod/Assembly/UtilsAssembly.py +++ b/src/Mod/Assembly/UtilsAssembly.py @@ -443,7 +443,7 @@ def findElementClosestVertex(ref, mousePos): return element_name elif elt_type == "Edge": - edge = obj.Shape.Edges[elt_index - 1] + edge = obj.Shape.getElement(element_name) curve = edge.Curve if curve.TypeId == "Part::GeomCircle": # For centers, as they are not shape vertexes, we return the element name. @@ -463,12 +463,14 @@ def findElementClosestVertex(ref, mousePos): # If line center is closest then we have no vertex name to set so we put element name return element_name - vertex_name = findVertexNameInObject(edge.Vertexes[closest_vertex_index], obj) + vertexes = edge.Vertexes + + vertex_name = findVertexNameInObject(vertexes[closest_vertex_index], obj) return vertex_name elif elt_type == "Face": - face = obj.Shape.Faces[elt_index - 1] + face = obj.Shape.getElement(element_name) surface = face.Surface _type = surface.TypeId if _type == "Part::GeomSphere" or _type == "Part::GeomTorus": @@ -564,9 +566,13 @@ def findClosestPointToMousePos(candidates_points, mousePos): def findVertexNameInObject(vertex, obj): - for i, vtx in enumerate(obj.Shape.Vertexes): - if vtx.Point == vertex.Point: - return "Vertex" + str(i + 1) + for i, _ in enumerate(obj.Shape.Vertexes): + vertexName = "Vertex" + str(i + 1) + + if ( + obj.Shape.getElement(vertexName).Point == vertex.Point + ): # Don't use the vtx param from enumerate's 2nd output to avoid hasher warning + return vertexName return "" @@ -966,17 +972,17 @@ def findPlacement(ref, ignoreVertex=False): plc = App.Placement() elt_type, elt_index = extract_type_and_number(elt) - vtx_type, vtx_index = extract_type_and_number(vtx) + vtx_type, _ = extract_type_and_number(vtx) isLine = False if elt_type == "Vertex": - vertex = get_element(obj.Shape.Vertexes, elt_index, elt) + vertex = get_element(obj.Shape, elt) if vertex is None: return App.Placement() plc.Base = (vertex.X, vertex.Y, vertex.Z) elif elt_type == "Edge": - edge = get_element(obj.Shape.Edges, elt_index, elt) + edge = get_element(obj.Shape, elt) if edge is None: return App.Placement() @@ -993,7 +999,7 @@ def findPlacement(ref, ignoreVertex=False): line_middle = (edge_points[0] + edge_points[1]) * 0.5 plc.Base = line_middle else: - vertex = get_element(obj.Shape.Vertexes, vtx_index, vtx) + vertex = get_element(obj.Shape, vtx) if vertex is None: return App.Placement() @@ -1010,7 +1016,7 @@ def findPlacement(ref, ignoreVertex=False): plane = Part.Plane(plane_origin, plane_normal) plc.Rotation = App.Rotation(plane.Rotation) elif elt_type == "Face": - face = get_element(obj.Shape.Faces, elt_index, elt) + face = get_element(obj.Shape, elt) if face is None: return App.Placement() @@ -1031,7 +1037,7 @@ def findPlacement(ref, ignoreVertex=False): plc.Base = face.CenterOfGravity elif vtx_type == "Edge": # In this case the edge is a circle/arc and the wanted vertex is its center. - edge = get_element(face.Edges, vtx_index, vtx) + edge = get_element(face, vtx) if edge is None: return App.Placement() @@ -1047,7 +1053,7 @@ def findPlacement(ref, ignoreVertex=False): plc.Base = findCylindersIntersection(obj, surface, edge, elt_index) else: - vertex = get_element(obj.Shape.Vertexes, vtx_index, vtx) + vertex = get_element(obj.Shape, vtx) if vertex is None: return App.Placement() @@ -1083,11 +1089,11 @@ def findPlacement(ref, ignoreVertex=False): return plc -def get_element(shape_elements, index, sub): - if index - 1 < 0 or index - 1 >= len(shape_elements): - print(f"Joint Corrupted: Index of {sub} out of bound.") - return None - return shape_elements[index - 1] +def get_element(shape, name): + element = shape.getElement(name) + if element is None: + App.Console.PrintWarning(f"Unable to find element {name}.") + return element def isRefValid(ref, number_sub): From 0bfc022191a0bae5c4461bd0c53492dfbfa7f350 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 3 Apr 2025 09:49:42 +0200 Subject: [PATCH 172/316] MOD: TECHDRAW (Removed unused functions) Unused functions removed. --- src/Mod/TechDraw/Gui/CommandHelpers.cpp | 97 ------------------------- src/Mod/TechDraw/Gui/CommandHelpers.h | 7 -- src/Mod/TechDraw/Gui/PATPathMaker.cpp | 46 ------------ src/Mod/TechDraw/Gui/PATPathMaker.h | 4 +- 4 files changed, 1 insertion(+), 153 deletions(-) diff --git a/src/Mod/TechDraw/Gui/CommandHelpers.cpp b/src/Mod/TechDraw/Gui/CommandHelpers.cpp index 45ab2af998..44ee90a48d 100644 --- a/src/Mod/TechDraw/Gui/CommandHelpers.cpp +++ b/src/Mod/TechDraw/Gui/CommandHelpers.cpp @@ -70,26 +70,6 @@ TechDraw::DrawView* CommandHelpers::firstViewInSelection(Gui::Command* cmd) return baseView; } -//! find the first DrawView in the current selection for use as a base view (owner) -TechDraw::DrawView* CommandHelpers::firstNonSpreadsheetInSelection(Gui::Command* cmd) -{ - std::vector selection = cmd->getSelection().getSelectionEx(); - TechDraw::DrawView* baseView{nullptr}; - if (!selection.empty()) { - for (auto& selobj : selection) { - if (selobj.getObject()->isDerivedFrom()) { - continue; - } else { - auto docobj = selobj.getObject(); - baseView = static_cast(docobj); - break; - } - } - } - return baseView; -} - - std::vector CommandHelpers::getSelectedSubElements(Gui::Command* cmd, TechDraw::DrawViewPart* &dvp, std::string subType) @@ -129,83 +109,6 @@ std::vector CommandHelpers::getSelectedSubElements(Gui::Command* cm return selectedSubs; } -//! extract the selected shapes and xShapes and determine if a face has been -//! selected to define the projection direction -void CommandHelpers::getSelectedShapes(Gui::Command* cmd, - std::vector& shapes, - std::vector& xShapes, - App::DocumentObject* faceObj, - std::string& faceName) -{ - auto resolve = Gui::ResolveMode::OldStyleElement; - bool single = false; - auto selection = cmd->getSelection().getSelectionEx(nullptr, App::DocumentObject::getClassTypeId(), - resolve, single); - for (auto& sel : selection) { - bool is_linked = false; - auto obj = sel.getObject(); - if (obj->isDerivedFrom()) { - continue; - } - if (obj->isDerivedFrom() - || obj->isDerivedFrom() - || obj->isDerivedFrom()) { - is_linked = true; - } - // If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too - // 1st, is obj in another document? - if (obj->getDocument() != cmd->getDocument()) { - std::set parents = obj->getInListEx(true); - for (auto& parent : parents) { - // Only consider parents in the current document, i.e. possible links in this View's document - if (parent->getDocument() != cmd->getDocument()) { - continue; - } - // 2nd, do we really have a link to obj? - if (parent->isDerivedFrom() - || parent->isDerivedFrom() - || parent->isDerivedFrom()) { - // We have a link chain from this document to obj, and obj is in another document -> it is an XLink target - is_linked = true; - } - } - } - if (is_linked) { - xShapes.push_back(obj); - continue; - } - //not a Link and not null. assume to be drawable. Undrawables will be - // skipped later. - shapes.push_back(obj); - if (faceObj) { - continue; - } - //don't know if this works for an XLink - for (auto& sub : sel.getSubNames()) { - if (TechDraw::DrawUtil::getGeomTypeFromName(sub) == "Face") { - faceName = sub; - // - faceObj = obj; - break; - } - } - } -} - - -std::pair CommandHelpers::viewDirection() -{ - if (!Preferences::useCameraDirection()) { - return { Base::Vector3d(0, -1, 0), Base::Vector3d(1, 0, 0) }; - } - - auto faceInfo = faceFromSelection(); - if (faceInfo.first) { - return DrawGuiUtil::getProjDirFromFace(faceInfo.first, faceInfo.second); - } - - return DrawGuiUtil::get3DDirAndRot(); -} std::pair CommandHelpers::faceFromSelection() { diff --git a/src/Mod/TechDraw/Gui/CommandHelpers.h b/src/Mod/TechDraw/Gui/CommandHelpers.h index ed86dbefae..ac854f45bc 100644 --- a/src/Mod/TechDraw/Gui/CommandHelpers.h +++ b/src/Mod/TechDraw/Gui/CommandHelpers.h @@ -47,7 +47,6 @@ class DrawView; class DrawViewPart; namespace CommandHelpers { - TechDraw::DrawView* firstViewInSelection(Gui::Command* cmd); TechDraw::DrawView* firstNonSpreadsheetInSelection(Gui::Command* cmd); @@ -55,14 +54,8 @@ std::vector getSelectedSubElements(Gui::Command* cmd, TechDraw::DrawViewPart* &dvp, std::string subType = "Edge"); -void getSelectedShapes(Gui::Command* cmd, - std::vector& shapes, - std::vector& xShapes, - App::DocumentObject* faceObj, - std::string& faceName); std::pair faceFromSelection(); -std::pair viewDirection(); } // end namespace CommandHelpers diff --git a/src/Mod/TechDraw/Gui/PATPathMaker.cpp b/src/Mod/TechDraw/Gui/PATPathMaker.cpp index 7bca467518..076d297492 100644 --- a/src/Mod/TechDraw/Gui/PATPathMaker.cpp +++ b/src/Mod/TechDraw/Gui/PATPathMaker.cpp @@ -115,37 +115,6 @@ QGraphicsPathItem* PATPathMaker::simpleLine(TechDraw::BaseGeomPtr base) } -//! make a fragment (length = remain) of a dashed line, with pattern starting at +offset -QGraphicsPathItem* PATPathMaker::geomToStubbyLine(TechDraw::BaseGeomPtr base, double remain, LineSet& ls) -{ - QGraphicsPathItem* fillItem = new QGraphicsPathItem(m_parent); - Base::Vector3d start(base->getStartPoint().x, - base->getStartPoint().y, - 0.0); - Base::Vector3d end(base->getEndPoint().x, - base->getEndPoint().y, - 0.0); - double origLen = (end - start).Length(); - - double appRemain = Rez::appX(remain); - Base::Vector3d newEnd = start + (ls.getUnitDir() * appRemain); - - double newLen = (newEnd - start).Length(); - - if (newLen > origLen) { - newEnd = end; - } - - double offset = Rez::guiX(m_fillScale * ls.getDashSpec().length()) - remain; - - fillItem->setPath(dashedPPath(offsetDash(decodeDashSpec(ls.getDashSpec()), offset), - Rez::guiX(start), - Rez::guiX(newEnd))); - m_fillItems.push_back(fillItem); - return fillItem; -} - - //! convert from mm to scene units std::vector PATPathMaker::decodeDashSpec(DashSpec patDash) { @@ -257,18 +226,3 @@ std::vector PATPathMaker::offsetDash(const std::vector dashPatte return result; } - -//! find remaining length of a dash pattern after offset -double PATPathMaker::dashRemain(const std::vector dashPattern, const double offset) -{ - double length = 0.0; - for (auto& d: dashPattern) { - length += fabs(d); - } - if (offset > length) { - return 0.0; - } - return length - offset; -} - - diff --git a/src/Mod/TechDraw/Gui/PATPathMaker.h b/src/Mod/TechDraw/Gui/PATPathMaker.h index d775f22449..ced1214845 100644 --- a/src/Mod/TechDraw/Gui/PATPathMaker.h +++ b/src/Mod/TechDraw/Gui/PATPathMaker.h @@ -45,17 +45,15 @@ public: void setPen(QPen pen) { m_pen = pen; } QPen getPen() { return m_pen; } void setParent(QGraphicsItem* parent) { m_parent = parent; } - + void lineSetToFillItems(TechDraw::LineSet& ls); protected: QGraphicsPathItem* geomToLine(TechDraw::BaseGeomPtr base, TechDraw::LineSet& ls); QGraphicsPathItem* simpleLine(TechDraw::BaseGeomPtr base); - QGraphicsPathItem* geomToStubbyLine(TechDraw::BaseGeomPtr base, double offset, TechDraw::LineSet& ls); QGraphicsPathItem* lineFromPoints(Base::Vector3d start, Base::Vector3d end, TechDraw::DashSpec ds); std::vector offsetDash(const std::vector dv, const double offset); QPainterPath dashedPPath(const std::vector dv, const Base::Vector3d start, const Base::Vector3d end); - double dashRemain(const std::vector dv, const double offset); double calcOffset(TechDraw::BaseGeomPtr g, TechDraw::LineSet ls); std::vector decodeDashSpec(TechDraw::DashSpec d); From 01609b54797434aea1993c4cb3accbe9ba21dbe4 Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 2 Apr 2025 22:10:10 +0200 Subject: [PATCH 173/316] Remove old python files Remove not necessary python files --- src/Tools/MemoryLeaks.py | 30 ----- src/Tools/WinVersion.py | 49 ------- src/Tools/chm.css | 274 --------------------------------------- src/Tools/pythondoc.py | 91 ------------- src/Tools/updateppa.py | 51 -------- 5 files changed, 495 deletions(-) delete mode 100755 src/Tools/MemoryLeaks.py delete mode 100644 src/Tools/WinVersion.py delete mode 100644 src/Tools/chm.css delete mode 100644 src/Tools/pythondoc.py delete mode 100644 src/Tools/updateppa.py diff --git a/src/Tools/MemoryLeaks.py b/src/Tools/MemoryLeaks.py deleted file mode 100755 index c5417f9627..0000000000 --- a/src/Tools/MemoryLeaks.py +++ /dev/null @@ -1,30 +0,0 @@ -#! python -# -*- coding: utf-8 -*- -# (c) 2006 Werner Mayer LGPL -# FreeCAD report memory leaks script to get provide the log file of Visual Studio in more readable file. - -import string, re - -# Open the memory leak file -file = open("MemLog.txt") -lines = file.readlines() -file.close() - -d = dict() -l = list() -for line in lines: - r = re.search("\\(#\\s*\\d+\\)", line) - if r is not None: - s = line[r.start() : r.end()] - t = re.search("^Leak", line) - if t is not None: - m = d[s] - l.append(m) - else: - d[s] = line - -file = open("MemLog_leaks.txt", "w") -for line in l: - line = string.replace(line, "Alloc", "Leak") - file.write(line) -file.close() diff --git a/src/Tools/WinVersion.py b/src/Tools/WinVersion.py deleted file mode 100644 index bb3abc71b8..0000000000 --- a/src/Tools/WinVersion.py +++ /dev/null @@ -1,49 +0,0 @@ -#! python -# -*- coding: utf-8 -*- -# (c) 2012 Juergen Riegel LGPL -# -# Script to create files used in Windows build -# uses SubWCRev.py for version detection# - -import SubWCRev, getopt, sys, string - - -def main(): - - input = "" - output = "." - - try: - opts, args = getopt.getopt(sys.argv[1:], "dso:", ["dir=", "src=", "out="]) - except getopt.GetoptError: - pass - - for o, a in opts: - if o in ("-d", "--dir"): - print("The %s option is deprecated. Ignoring." % (o)) - if o in ("-s", "--src"): - input = a - if o in ("-o", "--out"): - output = a - git = SubWCRev.GitControl() - - if git.extractInfo(input, ""): - print(git.hash) - print(git.branch) - print(git.rev[0:4]) - print(git.date) - print(git.url) - print(input) - print(output) - - f = open(input, "r") - o = open(output, "w") - for line in f.readlines(): - line = string.replace(line, "$WCREV$", git.rev[0:4]) - line = string.replace(line, "$WCDATE$", git.date) - line = string.replace(line, "$WCURL$", git.url) - o.write(line) - - -if __name__ == "__main__": - main() diff --git a/src/Tools/chm.css b/src/Tools/chm.css deleted file mode 100644 index 10602b080e..0000000000 --- a/src/Tools/chm.css +++ /dev/null @@ -1,274 +0,0 @@ -a.new{ color:#ba0000; text-decoration:none; } - -#toc { - /*border:1px solid #2f6fab;*/ - border:1px solid #aaaaaa; - background-color:#f9f9f9; - padding:5px; -} -.tocindent { - margin-left: 2em; -} -.tocline { - margin-bottom: 0px; -} -.toctoggle, .editsection { - font-size: smaller; -} - -/* images */ -div.floatright { - float: right; - margin: 0; - position:relative; - border: 0.5em solid White; - border-width: 0.5em 0 0.8em 1.4em; -} -div.floatright p { font-style: italic;} -div.floatleft { - float: left; - margin: 0.3em 0.5em 0.5em 0; - position:relative; - border: 0.5em solid White; - border-width: 0.5em 1.4em 0.8em 0; -} -div.floatleft p { font-style: italic; } -/* thumbnails */ -div.thumb { - margin-bottom: 0.5em; - border-style: solid; border-color: White; - width: auto; - overflow: hidden; -} -div.thumb div { - border:1px solid #cccccc; - padding: 3px !important; - background-color:#f9f9f9; - font-size: 94%; - text-align: center; -} -div.thumb div a img { - border:1px solid #cccccc; -} -div.thumb div div.thumbcaption { - border: none; - padding: 0.3em 0 0.1em 0; -} -div.magnify { display: none; } -div.tright { - float: right; - border-width: 0.5em 0 0.8em 1.4em; -} -div.tleft { - float: left; - margin-right:0.5em; - border-width: 0.5em 1.4em 0.8em 0; -} - -/* table standards */ -table.rimage { - float:right; - width:1pt; - position:relative; - margin-left:1em; - margin-bottom:1em; - text-align:center; -} - -body { - background: White; - /*font-size: 11pt !important;*/ - color: Black; - margin: 0; - padding: 0; -} - -.noprint, -div#jump-to-nav, -div.top, -div#column-one, -#colophon, -.editsection, -.toctoggle, -.tochidden, -div#f-poweredbyico, -div#f-copyrightico, -div#footer, -li#f-viewcount, -li#f-about, -li#f-disclaimer, -h3#siteSub, -li#f-privacy { - /* Hides all the elements irrelevant for printing */ - display: none; -} - -ul { - list-style-type: square; -} - -#content { - background: none; - border: none ! important; - font-size: 11pt; - /*padding: 0 ! important; - margin: 0 ! important;*/ -} - -h1, h2, h3, h4, h5, h6 -{ - font-weight: bold; -} - -p, .documentDescription { - /*margin: 1em 0 ! important;*/ - line-height: 1.2em; -} - -.tocindent p { - margin: 0 0 0 0 ! important; -} - -pre { - border: 1px dashed #2F6FAB; - white-space: pre; - font-size: 95%; - overflow: auto; - padding: 5px; - background : #F9F9F9; - color : black; -} - -table.listing, -table.listing td { - border: 1pt solid black; - border-collapse: collapse; -} -/* -a { - color: Black !important; - padding: 0 !important -} - -a:link, a:visited { - color: #520; - background: transparent; - text-decoration: underline; -} -*/ -#content a.external.text:after, #content a.external.autonumber:after { - /* Expand URLs for printing */ - content: " (" attr(href) ") "; -} - -#globalWrapper { - width: 100% !important; - min-width: 0 !important; -} - -#content { - background : white; - color : black; -} - -#column-content { - margin: 0 !important; -} - -#column-content #content { - padding: 1em; - margin: 0 !important; -} -/* MSIE/Win doesn't understand 'inherit' */ -/*a, a.external, a.new, a.stub { - color: black ! important; - text-decoration: none ! important; -} -*/ -/* Continue ... */ -/*a, a.external, a.new, a.stub { - color: inherit ! important; - text-decoration: inherit ! important; -} -*/ -img { border: none; } -img.tex { vertical-align: middle; } -span.texhtml { font-family: serif; } - -div.townBox { - position:relative; - float:right; - background:White; - margin-left:1em; - border: 1px solid gray; - padding:0.3em; - width: 200px; - overflow: hidden; - clear: right; -} -div.townBox dl { - padding: 0; - margin: 0 0 0.3em 0; - font-size: 96%; -} -div.townBox dl dt { - background: none; - margin: 0.4em 0 0 0; -} -div.townBox dl dd { - margin: 0.1em 0 0 1.1em; - background-color: #f3f3f3; -} - -#siteNotice { display: none; } - -table.gallery { - border: 1px solid #cccccc; - margin: 2px; - padding: 2px; - background-color:#ffffff; -} - -table.gallery tr { - vertical-align:top; -} - -div.gallerybox { - border: 1px solid #cccccc; - margin: 2px; - background-color:#f9f9f9; - width: 150px; -} - -div.gallerybox div.thumb { - text-align: center; - border: 1px solid #cccccc; - margin: 2px; -} - -div.gallerytext { - font-size: 94%; - padding: 2px 4px; -} - -/* -** Diff rendering -*/ -table.diff { background:white; } -td.diff-otitle { background:#ffffff; } -td.diff-ntitle { background:#ffffff; } -td.diff-addedline { - background:#ccffcc; - font-size: smaller; - border: solid 2px black; -} -td.diff-deletedline { - background:#ffffaa; - font-size: smaller; - border: dotted 2px black; -} -td.diff-context { - background:#eeeeee; - font-size: smaller; -} -span.diffchange { color: silver; font-weight: bold; text-decoration: underline; } diff --git a/src/Tools/pythondoc.py b/src/Tools/pythondoc.py deleted file mode 100644 index 5e0547efab..0000000000 --- a/src/Tools/pythondoc.py +++ /dev/null @@ -1,91 +0,0 @@ -#! python -# -*- coding: utf-8 -*- -# (c) 2007 Werner Mayer LGPL -# Create HTML documentation from FreeCAD's Python modules and classes. - -import pydoc, pkgutil, sys, os, dircache, zipfile - - -def generateDoc(): - # Get the path to the FreeCAD module relative to this directory - toolspath = os.path.dirname(__file__) - homepath = toolspath + "/../../" - homepath = os.path.realpath(homepath) - binpath = os.path.join(homepath, "bin") - docpath = os.path.join(homepath, "doc") - modpath = os.path.join(homepath, "Mod") - - # Change to the doc directory - cwd = os.getcwd() - print("Change to " + docpath) - os.chdir(homepath) - if os.path.exists("doc") == False: - os.mkdir("doc") - os.chdir("doc") - - # Add the bin path to the system path - if os.name == "nt": - os.environ["PATH"] = os.environ["PATH"] + ";" + binpath - else: - os.environ["PATH"] = os.environ["PATH"] + ":" + binpath - - # Import FreeCAD module - sys.path.append(binpath) - print("Write documentation for module 'FreeCAD'") - pydoc.writedoc("FreeCAD") - print("") - - # Module directory - ModDirs = dircache.listdir(modpath) - - # Search for module paths and append them to Python path - # for Dir in ModDirs: - # if (Dir != '__init__.py'): - # sys.path.append( os.path.join(modpath,Dir) ) - - # Walk through the module paths again and try loading the modules to create HTML files - for Dir in ModDirs: - dest = os.path.join(modpath, Dir) - print("Write documentation for module '" + Dir + "'") - if Dir != "__init__.py": - writedocs(dest) - print("") - - # Now we must create a document and create instances of all Python classes which - # cannot be directly created by a module. - - # Create a ZIP archive from all HTML files - print("Creating ZIP archive 'docs.zip'...") - zip = zipfile.ZipFile("docs.zip", "w") - for file in os.listdir("."): - if not os.path.isdir(file): - if file.find(".html") > 0: - print(" Adding file " + file + " to archive") - zip.write(file) - - print("done.") - zip.close() - - # Remove all HTML files - print("Cleaning up HTML files...") - for file in os.listdir("."): - if not os.path.isdir(file): - if file.find(".html") > 0: - print(" Removing " + file) - os.remove(file) - - os.chdir(cwd) - print("done.") - - -def writedocs(dir, pkgpath=""): - """Write out HTML documentation for all modules in a directory tree.""" - for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath): - # Ignore all debug modules - if modname[-2:] != "_d": - pydoc.writedoc(modname) - return - - -if __name__ == "__main__": - generateDoc() diff --git a/src/Tools/updateppa.py b/src/Tools/updateppa.py deleted file mode 100644 index db79afff92..0000000000 --- a/src/Tools/updateppa.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# (c) 2012 Werner Mayer LGPL - -import sys -from os import path -from tempfile import gettempdir - -from bzrlib.branch import Branch -from bzrlib.workingtree import WorkingTree - - -def runUpdate(filename): - branch = "versioning.git" - REMOTE_URL = "bzr+ssh://bazaar.launchpad.net/~freecad-maintainers/freecad/%s" % (branch) - LOCAL_BRANCH = path.join(gettempdir(), branch) - - # Location of branch on Launchpad - remote_branch = Branch.open(REMOTE_URL) - - # Location of branch on local system - local_branch = remote_branch.bzrdir.sprout(LOCAL_BRANCH).open_branch() - ( - False if local_branch.__name__ else True - ) # "Use" to silence analyzers, pending PEP 640 or similar - - # Change a file in the local branch - try: - wf = open(LOCAL_BRANCH + "/src/Build/Version.h", "w") - rf = open(filename, "r") - except IOError as error: - raise error - else: - wf.write(rf.read()) - wf.close() - - # Commit the change - tree = WorkingTree.open(LOCAL_BRANCH) - tree.commit("Update version number") - - # Push back to Launchpad - # transport = get_transport(PUSHTO_URL) - # local_branch.create_clone_on_transport(transport) - - -def main(): - runUpdate(sys.argv[1]) - - -if __name__ == "__main__": - main() From ee426de9b9e97aab9afbe923f21160e32031b66d Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 3 Apr 2025 22:23:51 -0500 Subject: [PATCH 174/316] CMake: Only set /NODEFAULTLIB for MSVC < 19.30 Corresponds to anything earlier than VS 2022. --- .../SetGlobalCompilerAndLinkerSettings.cmake | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/cMake/FreeCAD_Helpers/SetGlobalCompilerAndLinkerSettings.cmake b/cMake/FreeCAD_Helpers/SetGlobalCompilerAndLinkerSettings.cmake index 7710219fe0..3a09db02d2 100644 --- a/cMake/FreeCAD_Helpers/SetGlobalCompilerAndLinkerSettings.cmake +++ b/cMake/FreeCAD_Helpers/SetGlobalCompilerAndLinkerSettings.cmake @@ -24,13 +24,15 @@ macro(SetGlobalCompilerAndLinkerSettings) add_definitions(-D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR -DNOMINMAX) add_compile_options(/Zm150 /bigobj) set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFC_DEBUG") - # set default libs - set (CMAKE_C_STANDARD_LIBRARIES "kernel32.lib user32.lib gdi32.lib winspool.lib SHFolder.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib comsupp.lib Ws2_32.lib dbghelp.lib ") - set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}") - # set linker flag /nodefaultlib - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB") - set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /NODEFAULTLIB") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB") + if (MSVC_VERSION LESS 1930) # Anything before VS 2022 + # set default libs + set (CMAKE_C_STANDARD_LIBRARIES "kernel32.lib user32.lib gdi32.lib winspool.lib SHFolder.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib comsupp.lib Ws2_32.lib dbghelp.lib ") + set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}") + # set linker flag /nodefaultlib + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB") + set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /NODEFAULTLIB") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB") + endif() if(FREECAD_RELEASE_PDB) set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") set (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") From cdff0da672053a96b0a0c522c90caa2d8b452ed3 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 3 Apr 2025 00:03:58 +0200 Subject: [PATCH 175/316] BASE: remove FileTemplate class Removed unnecessary and old filetemplate class --- src/Base/CMakeLists.txt | 2 - src/Base/FileTemplate.cpp | 82 --------------------- src/Base/FileTemplate.h | 148 -------------------------------------- 3 files changed, 232 deletions(-) delete mode 100644 src/Base/FileTemplate.cpp delete mode 100644 src/Base/FileTemplate.h diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index 43ee4cc2bb..58c8d3c0d3 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -199,7 +199,6 @@ SET(FreeCADBase_CPP_SRCS ExceptionFactory.cpp Factory.cpp FileInfo.cpp - FileTemplate.cpp FutureWatcherProgress.cpp GeometryPyCXX.cpp Handle.cpp @@ -270,7 +269,6 @@ SET(FreeCADBase_HPP_SRCS ExceptionFactory.h Factory.h FileInfo.h - FileTemplate.h FutureWatcherProgress.h GeometryPyCXX.h Handle.h diff --git a/src/Base/FileTemplate.cpp b/src/Base/FileTemplate.cpp deleted file mode 100644 index 6533bd7d18..0000000000 --- a/src/Base/FileTemplate.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2011 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" - -#include "FileTemplate.h" - - -using namespace Base; - - -//************************************************************************** -// Construction/Destruction - -/** - * A constructor. - * A more elaborate description of the constructor. - */ -ClassTemplate::ClassTemplate() = default; - -ClassTemplate::ClassTemplate(const ClassTemplate&) = default; - -ClassTemplate::ClassTemplate(ClassTemplate&&) = default; - -/** - * A destructor. - * A more elaborate description of the destructor. - */ -ClassTemplate::~ClassTemplate() = default; - -ClassTemplate& ClassTemplate::operator=(const ClassTemplate&) = default; - -ClassTemplate& ClassTemplate::operator=(ClassTemplate&&) = default; - -//************************************************************************** -// separator for other implementation aspects - -/** - * a normal member taking two arguments and returning an integer value. - * \par - * You can use a printf like interface like: - * \code - * GetConsole().Warning("Some defects in %s, loading anyway\n",str); - * \endcode - * @param a an integer argument. - * @param s a constant character pointer. - * @see ClassTemplate() - * @see ~ClassTemplate() - * @see testMeToo() - * @see publicVar() - * @return The test results - */ -int ClassTemplate::testMe(int /*a*/, const char* /*s*/) -{ - return 0; -} - - -//************************************************************************** -//************************************************************************** -// Separator for additional classes -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/Base/FileTemplate.h b/src/Base/FileTemplate.h deleted file mode 100644 index e2b61435d8..0000000000 --- a/src/Base/FileTemplate.h +++ /dev/null @@ -1,148 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2011 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#ifndef BASE_FILETEMPLATE_H -#define BASE_FILETEMPLATE_H - -#include -#ifndef FC_GLOBAL_H -#include -#endif - - -namespace Base -{ - - -/** A test class. A more elaborate class description. - * Detailed description with some formatting: - * \par - * bla blablablablablablabl: - * \code - * #include - * Base::Console().Log("Stage: %d",i); - * \endcode - * \par - * another blablablablablablablablablabl: - * Text before the list - * - list item 1 - * - sub item 1 - * - sub sub item 1 - * - sub sub item 2 - * . - * The dot above ends the sub sub item list. - * More text for the first sub item - * . - * The dot above ends the first sub item. - * More text for the first list item - * - sub item 2 - * - sub item 3 - * - list item 2 - * . - * More text in the same paragraph. - * - * More text in a new paragraph. - * Also with HTML tags: - *
      - *
    • mouse events - *
        - *
      1. mouse move event - *
      2. mouse click event - * More info about the click event. - *
      3. mouse double click event - *
      - *
    • keyboard events - *
        - *
      1. key down event - *
      2. key up event - *
      - *
    - * More text here. - * - * \author YOUR NAME - */ -class BaseExport ClassTemplate -{ -public: - /// Construction - ClassTemplate(); - ClassTemplate(const ClassTemplate&); - ClassTemplate(ClassTemplate&&); - /// Destruction - virtual ~ClassTemplate(); - - ClassTemplate& operator=(const ClassTemplate&); - ClassTemplate& operator=(ClassTemplate&&); - int testMe(int a, const char* s); - - /** - * An enum. - * More detailed enum description. - */ - - enum TEnum - { - TVal1, /**< enum value TVal1. */ - TVal2, /**< enum value TVal2. */ - TVal3 /**< enum value TVal3. */ - } - * enumPtr {nullptr}, /**< enum pointer. Details. */ - enumVar {TVal1}; /**< enum variable. Details. */ - - /** - * A pure virtual member. - * @see testMe() - * @param c1 the first argument. - * @param c2 the second argument. - */ - virtual void testMeToo(char c1, char c2) = 0; - - /** @name a group of methods */ - //@{ - /// I am method one - virtual void one() = 0; - /// I am method two - virtual void two() = 0; - /// I am method three - virtual void three() = 0; - //@} - - - /** - * a public variable. - * Details. - */ - int publicVar {0}; - - /** - * a function variable. - * Details. - */ - int (*handler)(int a, int b) {nullptr}; - - std::string something; -}; - -} // namespace Base - -#endif // BASE_FILETEMPLATE_H From fa3c6e1068267505d27fbad4e0e22a2fd8791cc9 Mon Sep 17 00:00:00 2001 From: Syres916 <46537884+Syres916@users.noreply.github.com> Date: Sat, 5 Apr 2025 13:42:05 +0100 Subject: [PATCH 176/316] =?UTF-8?q?[PartDesign]=20Fix=20spelling=20of=20au?= =?UTF-8?q?xiliary=20and=20curvilinear=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …but also handle the properties name change from old files --- src/Mod/PartDesign/App/FeaturePipe.cpp | 40 ++++++++++++++---- src/Mod/PartDesign/App/FeaturePipe.h | 10 +++-- src/Mod/PartDesign/Gui/TaskPipeOrientation.ui | 4 +- src/Mod/PartDesign/Gui/TaskPipeParameters.cpp | 42 +++++++++---------- src/Mod/PartDesign/Gui/TaskPipeParameters.h | 2 +- src/Mod/PartDesign/Gui/Utils.cpp | 4 +- src/Mod/PartDesign/Gui/ViewProviderPipe.cpp | 6 +-- 7 files changed, 68 insertions(+), 40 deletions(-) diff --git a/src/Mod/PartDesign/App/FeaturePipe.cpp b/src/Mod/PartDesign/App/FeaturePipe.cpp index f5010885cf..7b60026224 100644 --- a/src/Mod/PartDesign/App/FeaturePipe.cpp +++ b/src/Mod/PartDesign/App/FeaturePipe.cpp @@ -72,11 +72,11 @@ Pipe::Pipe() ADD_PROPERTY_TYPE(Spine, (nullptr), "Sweep", App::Prop_None, "Path to sweep along"); ADD_PROPERTY_TYPE(SpineTangent, (false), "Sweep", App::Prop_None, "Include tangent edges into path"); - ADD_PROPERTY_TYPE(AuxillerySpine, (nullptr), "Sweep", App::Prop_None, + ADD_PROPERTY_TYPE(AuxiliarySpine, (nullptr), "Sweep", App::Prop_None, "Secondary path to orient sweep"); - ADD_PROPERTY_TYPE(AuxillerySpineTangent, (false), "Sweep", App::Prop_None, + ADD_PROPERTY_TYPE(AuxiliarySpineTangent, (false), "Sweep", App::Prop_None, "Include tangent edges into secondary path"); - ADD_PROPERTY_TYPE(AuxilleryCurvelinear, (true), "Sweep", App::Prop_None, + ADD_PROPERTY_TYPE(AuxiliaryCurvilinear, (true), "Sweep", App::Prop_None, "Calculate normal between equidistant points on both spines"); ADD_PROPERTY_TYPE(Mode, (long(0)), "Sweep", App::Prop_None, "Profile mode"); ADD_PROPERTY_TYPE(Binormal, (Base::Vector3d()), "Sweep", App::Prop_None, @@ -191,10 +191,10 @@ App::DocumentObjectExecReturn *Pipe::execute() // auxiliary TopoDS_Shape auxpath; if (Mode.getValue() == 3) { - App::DocumentObject* auxspine = AuxillerySpine.getValue(); + App::DocumentObject* auxspine = AuxiliarySpine.getValue(); if (!(auxspine && auxspine->isDerivedFrom())) return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "No auxiliary spine linked.")); - std::vector auxsubedge = AuxillerySpine.getSubValues(); + std::vector auxsubedge = AuxiliarySpine.getSubValues(); const Part::TopoShape& auxshape = static_cast(auxspine)->Shape.getValue(); @@ -479,8 +479,8 @@ void Pipe::setupAlgorithm(BRepOffsetAPI_MakePipeShell& mkPipeShell, const TopoDS } if (auxiliary) { - mkPipeShell.SetMode(TopoDS::Wire(auxshape), AuxilleryCurvelinear.getValue()); - // mkPipeShell.SetMode(TopoDS::Wire(auxshape), AuxilleryCurvelinear.getValue(), + mkPipeShell.SetMode(TopoDS::Wire(auxshape), AuxiliaryCurvilinear.getValue()); + // mkPipeShell.SetMode(TopoDS::Wire(auxshape), AuxiliaryCurvilinear.getValue(), // BRepFill_ContactOnBorder); } } @@ -613,3 +613,29 @@ void Pipe::handleChangedPropertyType(Base::XMLReader& reader, const char* TypeNa ProfileBased::handleChangedPropertyType(reader, TypeName, prop); } } + +void Pipe::handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) +{ + // The AuxiliarySpine property was AuxillerySpine in the past + std::string strAuxillerySpine("AuxillerySpine"); + // The AuxiliarySpineTangent property was AuxillerySpineTangent in the past + std::string strAuxillerySpineTangent("AuxillerySpineTangent"); + // The AuxiliaryCurvilinear property was AuxilleryCurvelinear in the past + std::string strAuxilleryCurvelinear("AuxilleryCurvelinear"); + Base::Type type = Base::Type::fromName(TypeName); + if (AuxiliarySpine.getClassTypeId() == type && strAuxillerySpine == PropName) { + AuxiliarySpine.Restore(reader); + } + else if (AuxiliarySpineTangent.getClassTypeId() == type + && strAuxillerySpineTangent == PropName) { + AuxiliarySpineTangent.Restore(reader); + } + else if (AuxiliaryCurvilinear.getClassTypeId() == type && strAuxilleryCurvelinear == PropName) { + AuxiliaryCurvilinear.Restore(reader); + } + else { + ProfileBased::handleChangedPropertyName(reader, TypeName, PropName); + } +} diff --git a/src/Mod/PartDesign/App/FeaturePipe.h b/src/Mod/PartDesign/App/FeaturePipe.h index 227a869f36..8987d1453f 100644 --- a/src/Mod/PartDesign/App/FeaturePipe.h +++ b/src/Mod/PartDesign/App/FeaturePipe.h @@ -39,9 +39,9 @@ public: App::PropertyLinkSub Spine; App::PropertyBool SpineTangent; - App::PropertyLinkSub AuxillerySpine; - App::PropertyBool AuxillerySpineTangent; - App::PropertyBool AuxilleryCurvelinear; + App::PropertyLinkSub AuxiliarySpine; + App::PropertyBool AuxiliarySpineTangent; + App::PropertyBool AuxiliaryCurvilinear; App::PropertyEnumeration Mode; App::PropertyVector Binormal; App::PropertyEnumeration Transition; @@ -59,7 +59,7 @@ public: const TopLoc_Location &invObjLoc = TopLoc_Location(), int transition = 0, const TopoShape &auxpath = TopoShape(), - bool auxCurveLinear = true, + bool auxCurviLinear = true, int mode = 2, const Base::Vector3d &binormalVector = Base::Vector3d(), int transformation = 0, @@ -74,6 +74,8 @@ protected: void setupAlgorithm(BRepOffsetAPI_MakePipeShell& mkPipeShell, const TopoDS_Shape& auxshape); /// handle changed property void handleChangedPropertyType(Base::XMLReader& reader, const char* TypeName, App::Property* prop) override; + void handleChangedPropertyName(Base::XMLReader& reader, const char* TypeName, + const char* PropName) override; private: static const char* TypeEnums[]; diff --git a/src/Mod/PartDesign/Gui/TaskPipeOrientation.ui b/src/Mod/PartDesign/Gui/TaskPipeOrientation.ui index 23c69f10c4..d1310ea473 100644 --- a/src/Mod/PartDesign/Gui/TaskPipeOrientation.ui +++ b/src/Mod/PartDesign/Gui/TaskPipeOrientation.ui @@ -71,9 +71,9 @@ - + - Curvelinear equivalence + Curvilinear equivalence diff --git a/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp b/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp index 31986fe5fe..d3656020ef 100644 --- a/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp @@ -124,8 +124,8 @@ TaskPipeParameters::TaskPipeParameters(ViewProviderPipe* PipeView, bool /*newObj make2DLabel(pipe->Profile.getValue(), pipe->Profile.getSubValues())); } // the auxiliary spine - if (pipe->AuxillerySpine.getValue()) { - auto* svp = doc->getViewProvider(pipe->AuxillerySpine.getValue()); + if (pipe->AuxiliarySpine.getValue()) { + auto* svp = doc->getViewProvider(pipe->AuxiliarySpine.getValue()); auxSpineShow = svp->isShow(); svp->show(); } @@ -432,8 +432,8 @@ void TaskPipeParameters::setVisibilityOfSpineAndProfile() profileVP->setVisible(profileShow); profileShow = false; } - if (pipe->AuxillerySpine.getValue()) { - auto* svp = doc->getViewProvider(pipe->AuxillerySpine.getValue()); + if (pipe->AuxiliarySpine.getValue()) { + auto* svp = doc->getViewProvider(pipe->AuxiliarySpine.getValue()); svp->setVisible(auxSpineShow); auxSpineShow = false; } @@ -456,7 +456,7 @@ bool TaskPipeParameters::accept() bool extReference = false; App::DocumentObject* spine = pipe->Spine.getValue(); - App::DocumentObject* auxSpine = pipe->AuxillerySpine.getValue(); + App::DocumentObject* auxSpine = pipe->AuxiliarySpine.getValue(); // If a spine isn't set but user entered a label then search for the appropriate document object QString label = ui->spineBaseEdit->text(); @@ -509,12 +509,12 @@ bool TaskPipeParameters::accept() } else if (!pcActiveBody->hasObject(auxSpine) && !pcActiveBody->getOrigin()->hasObject(auxSpine)) { - pipe->AuxillerySpine.setValue( + pipe->AuxiliarySpine.setValue( PartDesignGui::TaskFeaturePick::makeCopy(auxSpine, "", dlg.radioIndependent->isChecked()), - pipe->AuxillerySpine.getSubValues()); - copies.push_back(pipe->AuxillerySpine.getValue()); + pipe->AuxiliarySpine.getSubValues()); + copies.push_back(pipe->AuxiliarySpine.getValue()); } std::vector subSets; @@ -597,8 +597,8 @@ TaskPipeOrientation::TaskPipeOrientation(ViewProviderPipe* PipeView, this, &TaskPipeOrientation::onClearButton); connect(ui->stackedWidget, &QStackedWidget::currentChanged, this, &TaskPipeOrientation::updateUI); - connect(ui->curvelinear, &QCheckBox::toggled, - this, &TaskPipeOrientation::onCurvelinearChanged); + connect(ui->curvilinear, &QCheckBox::toggled, + this, &TaskPipeOrientation::onCurvilinearChanged); connect(ui->doubleSpinBoxX, qOverload(&QDoubleSpinBox::valueChanged), this, &TaskPipeOrientation::onBinormalChanged); connect(ui->doubleSpinBoxY, qOverload(&QDoubleSpinBox::valueChanged), @@ -628,12 +628,12 @@ TaskPipeOrientation::TaskPipeOrientation(ViewProviderPipe* PipeView, PartDesign::Pipe* pipe = PipeView->getObject(); // add initial values - if (pipe->AuxillerySpine.getValue()) { + if (pipe->AuxiliarySpine.getValue()) { ui->profileBaseEdit->setText( - QString::fromUtf8(pipe->AuxillerySpine.getValue()->Label.getValue())); + QString::fromUtf8(pipe->AuxiliarySpine.getValue()->Label.getValue())); } - std::vector strings = pipe->AuxillerySpine.getSubValues(); + std::vector strings = pipe->AuxiliarySpine.getSubValues(); for (const auto& string : strings) { QString label = QString::fromStdString(string); QListWidgetItem* item = new QListWidgetItem(); @@ -643,7 +643,7 @@ TaskPipeOrientation::TaskPipeOrientation(ViewProviderPipe* PipeView, } ui->comboBoxMode->setCurrentIndex(pipe->Mode.getValue()); - ui->curvelinear->setChecked(pipe->AuxilleryCurvelinear.getValue()); + ui->curvilinear->setChecked(pipe->AuxiliaryCurvilinear.getValue()); // should be called after panel has become visible QMetaObject::invokeMethod(this, @@ -690,14 +690,14 @@ void TaskPipeOrientation::onClearButton() ui->profileBaseEdit->clear(); if (auto view = getViewObject()) { view->highlightReferences(ViewProviderPipe::AuxiliarySpine, false); - getObject()->AuxillerySpine.setValue(nullptr); + getObject()->AuxiliarySpine.setValue(nullptr); } } -void TaskPipeOrientation::onCurvelinearChanged(bool checked) +void TaskPipeOrientation::onCurvilinearChanged(bool checked) { if (auto pipe = getObject()) { - pipe->AuxilleryCurvelinear.setValue(checked); + pipe->AuxiliaryCurvilinear.setValue(checked); recomputeFeature(); } } @@ -795,7 +795,7 @@ bool TaskPipeOrientation::referenceSelected(const SelectionChanges& msg) const if (const auto pipe = getObject()) { // change the references const std::string subName(msg.pSubName); - std::vector refs = pipe->AuxillerySpine.getSubValues(); + std::vector refs = pipe->AuxiliarySpine.getSubValues(); const auto f = std::ranges::find(refs, subName); if (selectionMode == StateHandlerTaskPipe::SelectionModes::refAuxSpine) { @@ -817,7 +817,7 @@ bool TaskPipeOrientation::referenceSelected(const SelectionChanges& msg) const } App::Document* doc = pipe->getDocument(); - pipe->AuxillerySpine.setValue(doc->getObject(msg.pObjectName), refs); + pipe->AuxiliarySpine.setValue(doc->getObject(msg.pObjectName), refs); return true; } } @@ -847,13 +847,13 @@ void TaskPipeOrientation::onDeleteItem() // search inside the list of spines if (const auto pipe = getObject()) { - std::vector refs = pipe->AuxillerySpine.getSubValues(); + std::vector refs = pipe->AuxiliarySpine.getSubValues(); const std::string obj = data.constData(); // if something was found, delete it and update the spine list if (const auto f = std::ranges::find(refs, obj); f != refs.end()) { refs.erase(f); - pipe->AuxillerySpine.setValue(pipe->AuxillerySpine.getValue(), refs); + pipe->AuxiliarySpine.setValue(pipe->AuxiliarySpine.getValue(), refs); clearButtons(); recomputeFeature(); } diff --git a/src/Mod/PartDesign/Gui/TaskPipeParameters.h b/src/Mod/PartDesign/Gui/TaskPipeParameters.h index 5577c91826..6cbb0b2f51 100644 --- a/src/Mod/PartDesign/Gui/TaskPipeParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPipeParameters.h @@ -125,7 +125,7 @@ private Q_SLOTS: void onOrientationChanged(int); void updateUI(int idx); void onClearButton(); - void onCurvelinearChanged(bool checked); + void onCurvilinearChanged(bool checked); void onBinormalChanged(double); void onDeleteItem(); diff --git a/src/Mod/PartDesign/Gui/Utils.cpp b/src/Mod/PartDesign/Gui/Utils.cpp index 09346de5d7..e56b4d468f 100644 --- a/src/Mod/PartDesign/Gui/Utils.cpp +++ b/src/Mod/PartDesign/Gui/Utils.cpp @@ -504,7 +504,7 @@ bool isFeatureMovable(App::DocumentObject* const feat) } } - if (auto prop = dynamic_cast(prim->getPropertyByName("AuxillerySpine"))) { + if (auto prop = dynamic_cast(prim->getPropertyByName("AuxiliarySpine"))) { App::DocumentObject* auxSpine = prop->getValue(); if (auxSpine && !isFeatureMovable(auxSpine)) { return false; @@ -557,7 +557,7 @@ std::vector collectMovableDependencies(std::vector(prim->getPropertyByName("AuxillerySpine"))) { + if (auto prop = dynamic_cast(prim->getPropertyByName("AuxiliarySpine"))) { App::DocumentObject* axis = prop->getValue(); if (axis && !axis->isDerivedFrom()){ unique_objs.insert(axis); diff --git a/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp b/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp index 044a52dd85..02bf485cd6 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp @@ -62,7 +62,7 @@ std::vector ViewProviderPipe::claimChildren()const if (spine && spine->isDerivedFrom()) temp.push_back(spine); - App::DocumentObject* auxspine = pcPipe->AuxillerySpine.getValue(); + App::DocumentObject* auxspine = pcPipe->AuxiliarySpine.getValue(); if (auxspine && auxspine->isDerivedFrom()) temp.push_back(auxspine); @@ -120,8 +120,8 @@ void ViewProviderPipe::highlightReferences(ViewProviderPipe::Reference mode, boo pcPipe->Spine.getSubValuesStartsWith("Edge"), on); break; case AuxiliarySpine: - highlightReferences(dynamic_cast(pcPipe->AuxillerySpine.getValue()), - pcPipe->AuxillerySpine.getSubValuesStartsWith("Edge"), on); + highlightReferences(dynamic_cast(pcPipe->AuxiliarySpine.getValue()), + pcPipe->AuxiliarySpine.getSubValuesStartsWith("Edge"), on); break; case Profile: highlightReferences(dynamic_cast(pcPipe->Profile.getValue()), From f0e9a6475f6dfd73a46f98883183f0a46e48c2b9 Mon Sep 17 00:00:00 2001 From: phaseloop <90922095+phaseloop@users.noreply.github.com> Date: Mon, 7 Apr 2025 19:04:27 +0100 Subject: [PATCH 177/316] CAM: change design of origin axis (#20358) * change design of CAM origin axis * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * change Inventor example comment * move to SoFCPlacementIndicatorKit - increase stock point size display * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Use So3DAnnotation for origin axis --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Mod/CAM/Path/Main/Gui/Job.py | 45 +++++++------------------------- src/Mod/CAM/Path/Main/Stock.py | 1 + 2 files changed, 10 insertions(+), 36 deletions(-) diff --git a/src/Mod/CAM/Path/Main/Gui/Job.py b/src/Mod/CAM/Path/Main/Gui/Job.py index c2277e83e9..2c19d35973 100644 --- a/src/Mod/CAM/Path/Main/Gui/Job.py +++ b/src/Mod/CAM/Path/Main/Gui/Job.py @@ -127,48 +127,21 @@ class ViewProvider: # Setup the axis display at the origin self.switch = coin.SoSwitch() - self.sep = coin.SoSeparator() - self.axs = coin.SoType.fromName("SoAxisCrossKit").createInstance() + self.sep = coin.SoType.fromName("So3DAnnotation").createInstance() - # Adjust the axis heads if needed, the scale here is just for the head - self.axs.set("xHead.transform", "scaleFactor 1.5 1.5 1") - self.axs.set("yHead.transform", "scaleFactor 1.5 1.5 1") - self.axs.set("zHead.transform", "scaleFactor 1.5 1.5 1") + self.axs = coin.SoType.fromName("SoFCPlacementIndicatorKit").createInstance() + self.axs.axisLength.setValue(1.2) - # Adjust the axis heads if needed, the scale here is just for the head - self.axs.set("xHead.transform", "translation 50 0 0") - self.axs.set("yHead.transform", "translation 0 50 0") - self.axs.set("zHead.transform", "translation 0 0 50") + # enum values for SoFCPlacementIndicatorKit + AXES = 1 + LABELS = 4 + ARROWHEADS = 8 - # Adjust the axis line width if needed - self.axs.set("xAxis.transform", "scaleFactor 0.5 0.5 1") - self.axs.set("xAxis.appearance.drawStyle", "lineWidth 9") - self.axs.set("yAxis.transform", "scaleFactor 0.5 0.5 1") - self.axs.set("yAxis.appearance.drawStyle", "lineWidth 9") - self.axs.set("zAxis.transform", "scaleFactor 0.5 0.5 1") - self.axs.set("zAxis.appearance.drawStyle", "lineWidth 9") + self.axs.parts.setValue(AXES | LABELS | ARROWHEADS) - self.sca = coin.SoType.fromName("SoShapeScale").createInstance() - self.sca.setPart("shape", self.axs) - self.sca.scaleFactor.setValue(2) # Keep or adjust if needed - - self.mat = coin.SoMaterial() - # Set sphere color to bright yellow - self.mat.diffuseColor = coin.SbColor(1, 1, 0) - self.mat.transparency = 0.35 # Keep or adjust if needed - - self.sph = coin.SoSphere() - self.scs = coin.SoType.fromName("SoShapeScale").createInstance() - self.scs.setPart("shape", self.sph) - # Increase the scaleFactor to make the sphere larger - self.scs.scaleFactor.setValue(20) # Adjust this value as needed - - self.sep.addChild(self.sca) - self.sep.addChild(self.mat) - self.sep.addChild(self.scs) + self.sep.addChild(self.axs) self.switch.addChild(self.sep) - self.switch.addChild(self.sep) vobj.RootNode.addChild(self.switch) self.showOriginAxis(True) diff --git a/src/Mod/CAM/Path/Main/Stock.py b/src/Mod/CAM/Path/Main/Stock.py index 939512abeb..afbb5236ce 100644 --- a/src/Mod/CAM/Path/Main/Stock.py +++ b/src/Mod/CAM/Path/Main/Stock.py @@ -341,6 +341,7 @@ def SetupStockObject(obj, stockType): PathIconViewProvider.ViewProvider(obj.ViewObject, "Stock") obj.ViewObject.Transparency = 90 + obj.ViewObject.PointSize = 5 obj.ViewObject.DisplayMode = "Wireframe" From 7d233dc95c1c10ec493653d7712521fdbda85aa8 Mon Sep 17 00:00:00 2001 From: tritao Date: Sat, 29 Mar 2025 11:09:38 +0000 Subject: [PATCH 178/316] Gui: Rename generated lexer files to match core naming pattern. So as title says, this renames generated lexerfiles from `SelectionFilter.l` to use the suffix .lex, instead of the `lex.SelectionFilter.c`. --- src/Gui/Selection/SelectionFilter.cpp | 2 +- src/Gui/Selection/SelectionFilter.l | 2 +- ...lex.SelectionFilter.c => SelectionFilter.lex.cpp} | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) rename src/Gui/Selection/{lex.SelectionFilter.c => SelectionFilter.lex.cpp} (99%) diff --git a/src/Gui/Selection/SelectionFilter.cpp b/src/Gui/Selection/SelectionFilter.cpp index 75fab0f327..4508ec6167 100644 --- a/src/Gui/Selection/SelectionFilter.cpp +++ b/src/Gui/Selection/SelectionFilter.cpp @@ -291,7 +291,7 @@ int SelectionFilterlex(); # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wsign-compare" #endif -#include "lex.SelectionFilter.c" +#include "SelectionFilter.lex.cpp" #if defined(__clang__) # pragma clang diagnostic pop #elif defined (__GNUC__) diff --git a/src/Gui/Selection/SelectionFilter.l b/src/Gui/Selection/SelectionFilter.l index fe96a20d6b..69ea0c98f7 100644 --- a/src/Gui/Selection/SelectionFilter.l +++ b/src/Gui/Selection/SelectionFilter.l @@ -21,7 +21,7 @@ /* Lexer for the FreeCAD selection filter language */ -/* flex -o lex.SelectionFilter.c SelectionFilter.l */ +/* flex -o SelectionFilter.lex.cpp SelectionFilter.l */ #include diff --git a/src/Gui/Selection/lex.SelectionFilter.c b/src/Gui/Selection/SelectionFilter.lex.cpp similarity index 99% rename from src/Gui/Selection/lex.SelectionFilter.c rename to src/Gui/Selection/SelectionFilter.lex.cpp index de32cd0e5b..37b63d1a92 100644 --- a/src/Gui/Selection/lex.SelectionFilter.c +++ b/src/Gui/Selection/SelectionFilter.lex.cpp @@ -18,9 +18,9 @@ * * ***************************************************************************/ -#line 2 "lex.SelectionFilter.c" +#line 2 "SelectionFilter.lex.cpp" -#line 4 "lex.SelectionFilter.c" +#line 4 "SelectionFilter.lex.cpp" #define YY_INT_ALIGNED short int @@ -528,7 +528,7 @@ char *SelectionFiltertext; /* Lexer for the FreeCAD selection filter language */ /* Copyright (c) 2010 Jürgen Riegel LGPL */ -/* flex -o lex.SelectionFilter.c SelectionFilter.l */ +/* flex -o SelectionFilter.lex.cpp SelectionFilter.l */ #include @@ -543,7 +543,7 @@ char *SelectionFiltertext; /* change the name of the scanner class. results in "SelectionFilterFlexLexer" */ /* the manual says "somewhat more optimized" */ /* no support for include files is planned */ -#line 527 "lex.SelectionFilter.c" +#line 527 "SelectionFilter.lex.cpp" #define INITIAL 0 @@ -763,7 +763,7 @@ YY_DECL -#line 747 "lex.SelectionFilter.c" +#line 747 "SelectionFilter.lex.cpp" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -874,7 +874,7 @@ YY_RULE_SETUP #line 54 "SelectionFilter.l" ECHO; YY_BREAK -#line 858 "lex.SelectionFilter.c" +#line 858 "SelectionFilter.lex.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); From 4c7fb9625b34bb8aa6027763071c554fe38055b2 Mon Sep 17 00:00:00 2001 From: aprospero <36386989+aprospero@users.noreply.github.com> Date: Tue, 8 Apr 2025 01:12:02 +0200 Subject: [PATCH 179/316] Draft: parametrize Draft vector utils precision (#20199) * parametrize draft vector utils precision * fix: a single function didn't get the complete latest update. * compatibility: reintroduce DraftVecUtils.precision() as deprecated. --- src/Mod/Draft/DraftVecUtils.py | 123 +++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 43 deletions(-) diff --git a/src/Mod/Draft/DraftVecUtils.py b/src/Mod/Draft/DraftVecUtils.py index ac69a2365b..415e7e2c80 100644 --- a/src/Mod/Draft/DraftVecUtils.py +++ b/src/Mod/Draft/DraftVecUtils.py @@ -35,11 +35,13 @@ but which can also be used in other workbenches and in macros. # flake8 --ignore=E226,E266,E401,W503 import math +import warnings import FreeCAD from FreeCAD import Vector from draftutils import params from draftutils import messages +from draftutils.utils import precision as draft_precision __title__ = "FreeCAD Draft Workbench - Vector library" __author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline" @@ -48,17 +50,28 @@ __url__ = "https://www.freecad.org" ## \addtogroup DRAFTVECUTILS # @{ - +# @deprecated("use Draft.precision() instead.") def precision(): - """Get the number of decimal numbers used for precision. + """ + Get the number of fractional decimal digits as configured + in Draft preferences. + This function is deprecated since it is a doublette of + Draft.precision() + Returns ------- int - Return the number of decimal places set up in the preferences, - or a standard value (6), if the parameter is missing. + Return the number of fractional decimal digits as configured + in Draft preferences. """ - return params.get_param("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() def typecheck(args_and_types, name="?"): @@ -177,7 +190,7 @@ def neg(u): return Vector(-u.x, -u.y, -u.z) -def equals(u, v): +def equals(u, v, precision=None): """Check for equality between two vectors. Due to rounding errors, two vectors will rarely be `equal`. @@ -191,10 +204,13 @@ def equals(u, v): Parameters ---------- - u : Base::Vector3 - The first vector. - v : Base::Vector3 - The second vector. + u : Base::Vector3 + The first vector. + v : Base::Vector3 + The second vector. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -202,7 +218,7 @@ def equals(u, v): `True` if the vectors are within the precision, `False` otherwise. """ typecheck([(u, Vector), (v, Vector)], "equals") - return isNull(u.sub(v)) + return isNull(u.sub(v), precision) def scale(u, scalar): @@ -525,19 +541,22 @@ def getRotation(vector, reference=Vector(1, 0, 0)): return (c.x, c.y, c.z, Q) -def isNull(vector): +def isNull(vector, precision=None): """Return False if each of the components of the vector is zero. Due to rounding errors, an element is probably never going to be exactly zero. Therefore, it rounds the element by the number - of decimals specified in the `precision` parameter - in the parameter database, accessed through `FreeCAD.ParamGet()`. - It then compares the rounded numbers against zero. + of decimals specified in the `precision` parameter - if `precision` + is not set or set to None configured Draft precision is used. + It then compares the rounded coordinates against zero. Parameters ---------- vector : Base::Vector3 The tested vector. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -545,14 +564,15 @@ def isNull(vector): `True` if each of the elements is zero within the precision. `False` otherwise. """ - p = precision() - x = round(vector.x, p) - y = round(vector.y, p) - z = round(vector.z, p) + if precision is None: + precision = params.get_param("precision") + x = round(vector.x, precision) + y = round(vector.y, precision) + z = round(vector.z, precision) return (x == 0 and y == 0 and z == 0) -def find(vector, vlist): +def find(vector, vlist, precision=None): """Find a vector in a list of vectors, and return the index. Finding a vector tests for `equality` which depends on the `precision` @@ -564,10 +584,13 @@ def find(vector, vlist): The tested vector. vlist : list A list of Base::Vector3 vectors. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- - int + int | None The index of the list where the vector is found, or `None` if the vector is not found. @@ -577,7 +600,7 @@ def find(vector, vlist): """ typecheck([(vector, Vector), (vlist, list)], "find") for i, v in enumerate(vlist): - if equals(vector, v): + if equals(vector, v, precision): return i return None @@ -628,7 +651,7 @@ def closest(vector, vlist, return_length=False): return index -def isColinear(vlist): +def isColinear(vlist, precision=None): """Check if the vectors in the list are colinear. Colinear vectors are those whose angle between them is zero. @@ -655,6 +678,9 @@ def isColinear(vlist): vlist : list List of Base::Vector3 vectors. At least three elements must be present. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -676,8 +702,8 @@ def isColinear(vlist): # This doesn't test for colinearity between the first two vectors. if len(vlist) < 3: return True - - p = precision() + if precision is None: + precision = params.get_param("precision") # Difference between the second vector and the first one first = vlist[1].sub(vlist[0]) @@ -691,12 +717,12 @@ def isColinear(vlist): # The angle between the difference and the first difference. _angle = angle(diff, first) - if round(_angle, p) != 0: + if round(_angle, precision) != 0: return False return True -def rounded(v,d=None): +def rounded(v,precision=None): """Return a vector rounded to the `precision` in the parameter database or to the given decimals value @@ -705,9 +731,12 @@ def rounded(v,d=None): Parameters ---------- - v : Base::Vector3 - The input vector. - d : (Optional) the number of decimals to round to + v : Base::Vector3 + The input vector. + precision : int | None + mathematical precision - if None use configured draft + precision + Returns ------- @@ -716,10 +745,9 @@ def rounded(v,d=None): to the number of decimals specified in the `precision` parameter in the parameter database. """ - p = precision() - if d: - p = d - return Vector(round(v.x, p), round(v.y, p), round(v.z, p)) + if precision is None: + precision = params.get_param("precision") + return Vector(round(v.x, precision), round(v.y, precision), round(v.z, precision)) def getPlaneRotation(u, v, _ = None): @@ -766,7 +794,7 @@ def getPlaneRotation(u, v, _ = None): return m -def removeDoubles(vlist): +def removeDoubles(vlist, precision=None): """Remove duplicated vectors from a list of vectors. It removes only the duplicates that are next to each other in the list. @@ -784,9 +812,12 @@ def removeDoubles(vlist): Parameters ---------- - vlist : list of Base::Vector3 - List with vectors. - + vlist : list of Base::Vector3 + List with vectors. + precision : int | None + mathematical precision - if None use configured draft + precision + Returns ------- list of Base::Vector3 @@ -805,20 +836,23 @@ def removeDoubles(vlist): # 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]): + 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): +def get_spherical_coords(x, y, z, precision=None): """Get the Spherical coordinates of the vector represented by Cartesian coordinates (x, y, z). Parameters ---------- - vector : Base::Vector3 - The input vector. + vector : Base::Vector3 + The input vector. + precision : int | None + mathematical precision - if None use configured draft + precision Returns ------- @@ -836,13 +870,16 @@ def get_spherical_coords(x, y, z): (0, 0, z) -> (radius, theta, 0) """ + 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) rad = v.Length - if not bool(round(rad, precision())): + if not bool(round(rad, precision)): return (0, math.pi/2, 0) theta = v.getAngle(z_axis) From f7c8ce50bc7c682695cdb36995054c6c75be95d1 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Sun, 14 Jul 2024 01:04:55 +0200 Subject: [PATCH 180/316] Base: Quantity: indent lexer and parser input files --- src/Base/QuantityParser.l | 301 +++++++++++++++++++------------------- src/Base/QuantityParser.y | 108 +++++++------- 2 files changed, 199 insertions(+), 210 deletions(-) diff --git a/src/Base/QuantityParser.l b/src/Base/QuantityParser.l index bd697d4dea..1daf9a4e25 100644 --- a/src/Base/QuantityParser.l +++ b/src/Base/QuantityParser.l @@ -60,189 +60,188 @@ CGRP '\,'[0-9][0-9][0-9] . { ;} -[ \t] ; -[\n]+ ; +[ \t] ; +[\n]+ ; -[+()=/*^] { return *yytext; } +[+()=/*^] return *yytext; -"-" return MINUSSIGN; -"\xe2\x88\x92" return MINUSSIGN; +"-" return MINUSSIGN; +"\xe2\x88\x92" return MINUSSIGN; -"nm" yylval = Quantity::NanoMetre; return UNIT; // nano meter -"um" yylval = Quantity::MicroMetre; return UNIT; // micro meter -"\xC2\xB5m" yylval = Quantity::MicroMetre; return UNIT; // micro meter (greek micro in UTF8) -"mm" yylval = Quantity::MilliMetre; return UNIT; // milli meter (internal standard length) -"cm" yylval = Quantity::CentiMetre; return UNIT; // centi meter -"dm" yylval = Quantity::DeciMetre; return UNIT; // deci meter -"m" yylval = Quantity::Metre; return UNIT; // Metre -"km" yylval = Quantity::KiloMetre; return UNIT; // kilo meter +"nm" yylval = Quantity::NanoMetre; return UNIT; // nano meter +"um" yylval = Quantity::MicroMetre; return UNIT; // micro meter +"\xC2\xB5m" yylval = Quantity::MicroMetre; return UNIT; // micro meter (greek micro in UTF8) +"mm" yylval = Quantity::MilliMetre; return UNIT; // milli meter (internal standard length) +"cm" yylval = Quantity::CentiMetre; return UNIT; // centi meter +"dm" yylval = Quantity::DeciMetre; return UNIT; // deci meter +"m" yylval = Quantity::Metre; return UNIT; // Metre +"km" yylval = Quantity::KiloMetre; return UNIT; // kilo meter -"l" yylval = Quantity::Liter; return UNIT; // Liter (dm^3) -"ml" yylval = Quantity::MilliLiter; return UNIT; // milli Liter +"l" yylval = Quantity::Liter; return UNIT; // Liter (dm^3) +"ml" yylval = Quantity::MilliLiter; return UNIT; // milli Liter -"Hz" yylval = Quantity::Hertz; return UNIT; // Hertz -"kHz" yylval = Quantity::KiloHertz; return UNIT; // kilo Hertz -"MHz" yylval = Quantity::MegaHertz; return UNIT; // mega Hertz -"GHz" yylval = Quantity::GigaHertz; return UNIT; // giga Hertz -"THz" yylval = Quantity::TeraHertz; return UNIT; // tera Hertz +"Hz" yylval = Quantity::Hertz; return UNIT; // Hertz +"kHz" yylval = Quantity::KiloHertz; return UNIT; // kilo Hertz +"MHz" yylval = Quantity::MegaHertz; return UNIT; // mega Hertz +"GHz" yylval = Quantity::GigaHertz; return UNIT; // giga Hertz +"THz" yylval = Quantity::TeraHertz; return UNIT; // tera Hertz -"ug" yylval = Quantity::MicroGram; return UNIT; // micro gram -"\xC2\xB5g" yylval = Quantity::MicroGram; return UNIT; // micro gram -"mg" yylval = Quantity::MilliGram; return UNIT; // milli gram -"g" yylval = Quantity::Gram; return UNIT; // gram -"kg" yylval = Quantity::KiloGram; return UNIT; // kilo gram (internal standard for mass) -"t" yylval = Quantity::Ton; return UNIT; // Metric Tonne +"ug" yylval = Quantity::MicroGram; return UNIT; // micro gram +"\xC2\xB5g" yylval = Quantity::MicroGram; return UNIT; // micro gram +"mg" yylval = Quantity::MilliGram; return UNIT; // milli gram +"g" yylval = Quantity::Gram; return UNIT; // gram +"kg" yylval = Quantity::KiloGram; return UNIT; // kilo gram (internal standard for mass) +"t" yylval = Quantity::Ton; return UNIT; // Metric Tonne -"s" yylval = Quantity::Second; return UNIT; // second (internal standard time) -"min" yylval = Quantity::Minute; return UNIT; // minute -"h" yylval = Quantity::Hour; return UNIT; // hour +"s" yylval = Quantity::Second; return UNIT; // second (internal standard time) +"min" yylval = Quantity::Minute; return UNIT; // minute +"h" yylval = Quantity::Hour; return UNIT; // hour -"A" yylval = Quantity::Ampere; return UNIT; // Ampere (internal standard electric current) -"mA" yylval = Quantity::MilliAmpere; return UNIT; // milli Ampere -"kA" yylval = Quantity::KiloAmpere; return UNIT; // kilo Ampere -"MA" yylval = Quantity::MegaAmpere; return UNIT; // mega Ampere +"A" yylval = Quantity::Ampere; return UNIT; // Ampere (internal standard electric current) +"mA" yylval = Quantity::MilliAmpere; return UNIT; // milli Ampere +"kA" yylval = Quantity::KiloAmpere; return UNIT; // kilo Ampere +"MA" yylval = Quantity::MegaAmpere; return UNIT; // mega Ampere -"K" yylval = Quantity::Kelvin; return UNIT; // Kelvin (internal standard thermodynamic temperature) -"mK" yylval = Quantity::MilliKelvin; return UNIT; // milli Kelvin -"\xC2\xB5K" yylval = Quantity::MicroKelvin; return UNIT; // micro Kelvin -"uK" yylval = Quantity::MicroKelvin; return UNIT; // micro Kelvin +"K" yylval = Quantity::Kelvin; return UNIT; // Kelvin (internal standard thermodynamic temperature) +"mK" yylval = Quantity::MilliKelvin; return UNIT; // milli Kelvin +"\xC2\xB5K" yylval = Quantity::MicroKelvin; return UNIT; // micro Kelvin +"uK" yylval = Quantity::MicroKelvin; return UNIT; // micro Kelvin -"mol" yylval = Quantity::Mole; return UNIT; // Mole (internal standard amount of substance) -"mmol" yylval = Quantity::MilliMole; return UNIT; // Milli Mole +"mol" yylval = Quantity::Mole; return UNIT; // Mole (internal standard amount of substance) +"mmol" yylval = Quantity::MilliMole; return UNIT; // Milli Mole -"cd" yylval = Quantity::Candela; return UNIT; // Candela (internal standard luminous intensity) +"cd" yylval = Quantity::Candela; return UNIT; // Candela (internal standard luminous intensity) -"in" yylval = Quantity::Inch; return UNIT; // inch -"\"" yylval = Quantity::Inch; return UNIT; // inch -"ft" yylval = Quantity::Foot; return UNIT; // foot -"'" yylval = Quantity::Foot; return UNIT; // foot -"thou" yylval = Quantity::Thou; return UNIT; // thou (in/1000) -"mil" yylval = Quantity::Thou; return UNIT; // mil (the thou in US) -"yd" yylval = Quantity::Yard; return UNIT; // yard -"mi" yylval = Quantity::Mile; return UNIT; // mile +"in" yylval = Quantity::Inch; return UNIT; // inch +"\"" yylval = Quantity::Inch; return UNIT; // inch +"ft" yylval = Quantity::Foot; return UNIT; // foot +"'" yylval = Quantity::Foot; return UNIT; // foot +"thou" yylval = Quantity::Thou; return UNIT; // thou (in/1000) +"mil" yylval = Quantity::Thou; return UNIT; // mil (the thou in US) +"yd" yylval = Quantity::Yard; return UNIT; // yard +"mi" yylval = Quantity::Mile; return UNIT; // mile -"mph" yylval = Quantity::MilePerHour; return UNIT; // mile per hour -"sqft" yylval = Quantity::SquareFoot; return UNIT; // square foot -"cft" yylval = Quantity::CubicFoot; return UNIT; // cubic foot +"mph" yylval = Quantity::MilePerHour; return UNIT; // mile per hour +"sqft" yylval = Quantity::SquareFoot; return UNIT; // square foot +"cft" yylval = Quantity::CubicFoot; return UNIT; // cubic foot -"lb" yylval = Quantity::Pound; return UNIT; // pound -"lbm" yylval = Quantity::Pound; return UNIT; // pound -"oz" yylval = Quantity::Ounce; return UNIT; // ounce -"st" yylval = Quantity::Stone; return UNIT; // Stone -"cwt" yylval = Quantity::Hundredweights; return UNIT; // hundredweights +"lb" yylval = Quantity::Pound; return UNIT; // pound +"lbm" yylval = Quantity::Pound; return UNIT; // pound +"oz" yylval = Quantity::Ounce; return UNIT; // ounce +"st" yylval = Quantity::Stone; return UNIT; // Stone +"cwt" yylval = Quantity::Hundredweights; return UNIT; // hundredweights -"lbf" yylval = Quantity::PoundForce; return UNIT; // pound +"lbf" yylval = Quantity::PoundForce; return UNIT; // pound -"N" yylval = Quantity::Newton; return UNIT; // Newton (kg*m/s^2) -"mN" yylval = Quantity::MilliNewton; return UNIT; // milli Newton -"kN" yylval = Quantity::KiloNewton; return UNIT; // kilo Newton -"MN" yylval = Quantity::MegaNewton; return UNIT; // mega Newton +"N" yylval = Quantity::Newton; return UNIT; // Newton (kg*m/s^2) +"mN" yylval = Quantity::MilliNewton; return UNIT; // milli Newton +"kN" yylval = Quantity::KiloNewton; return UNIT; // kilo Newton +"MN" yylval = Quantity::MegaNewton; return UNIT; // mega Newton -"Pa" yylval = Quantity::Pascal; return UNIT; // Pascal (kg/m/s^2 or N/m^2) -"kPa" yylval = Quantity::KiloPascal; return UNIT; // kilo Pascal -"MPa" yylval = Quantity::MegaPascal; return UNIT; // mega Pascal -"GPa" yylval = Quantity::GigaPascal; return UNIT; // giga Pascal +"Pa" yylval = Quantity::Pascal; return UNIT; // Pascal (kg/m/s^2 or N/m^2) +"kPa" yylval = Quantity::KiloPascal; return UNIT; // kilo Pascal +"MPa" yylval = Quantity::MegaPascal; return UNIT; // mega Pascal +"GPa" yylval = Quantity::GigaPascal; return UNIT; // giga Pascal -"bar" yylval = Quantity::Bar; return UNIT; // 1 bar = 100 kPa -"mbar" yylval = Quantity::MilliBar; return UNIT; // milli Bar +"bar" yylval = Quantity::Bar; return UNIT; // 1 bar = 100 kPa +"mbar" yylval = Quantity::MilliBar; return UNIT; // milli Bar -"Torr" yylval = Quantity::Torr; return UNIT; // portion of Pascal ( 101325/760 ) -"mTorr" yylval = Quantity::mTorr; return UNIT; // -"uTorr" yylval = Quantity::yTorr; return UNIT; // -"\xC2\xB5Torr" yylval = Quantity::yTorr; return UNIT; // +"Torr" yylval = Quantity::Torr; return UNIT; // portion of Pascal ( 101325/760 ) +"mTorr" yylval = Quantity::mTorr; return UNIT; // +"uTorr" yylval = Quantity::yTorr; return UNIT; // +"\xC2\xB5Torr" yylval = Quantity::yTorr; return UNIT; // -"psi" yylval = Quantity::PSI; return UNIT; // pounds/in^2 -"ksi" yylval = Quantity::KSI; return UNIT; // 1000 x pounds/in^2 -"Mpsi" yylval = Quantity::MPSI; return UNIT; // 1000 ksi +"psi" yylval = Quantity::PSI; return UNIT; // pounds/in^2 +"ksi" yylval = Quantity::KSI; return UNIT; // 1000 x pounds/in^2 +"Mpsi" yylval = Quantity::MPSI; return UNIT; // 1000 ksi -"W" yylval = Quantity::Watt; return UNIT; // Watt (kg*m^2/s^3) -"mW" yylval = Quantity::MilliWatt; return UNIT; // milli Watt -"kW" yylval = Quantity::KiloWatt; return UNIT; // kilo Watt -"VA" yylval = Quantity::VoltAmpere; return UNIT; // VoltAmpere (kg*m^2/s^3) +"W" yylval = Quantity::Watt; return UNIT; // Watt (kg*m^2/s^3) +"mW" yylval = Quantity::MilliWatt; return UNIT; // milli Watt +"kW" yylval = Quantity::KiloWatt; return UNIT; // kilo Watt +"VA" yylval = Quantity::VoltAmpere; return UNIT; // VoltAmpere (kg*m^2/s^3) -"V" yylval = Quantity::Volt; return UNIT; // Volt (kg*m^2/A/s^3) -"kV" yylval = Quantity::KiloVolt; return UNIT; // kilo Volt -"mV" yylval = Quantity::MilliVolt; return UNIT; // milli Volt +"V" yylval = Quantity::Volt; return UNIT; // Volt (kg*m^2/A/s^3) +"kV" yylval = Quantity::KiloVolt; return UNIT; // kilo Volt +"mV" yylval = Quantity::MilliVolt; return UNIT; // milli Volt -"MS" yylval = Quantity::MegaSiemens; return UNIT; // mega Siemens -"kS" yylval = Quantity::KiloSiemens; return UNIT; // kilo Siemens -"S" yylval = Quantity::Siemens; return UNIT; // Siemens (A^2*s^3/kg/m^2) -"mS" yylval = Quantity::MilliSiemens; return UNIT; // milli Siemens -"\xC2\xB5S" yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens -"uS" yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens +"MS" yylval = Quantity::MegaSiemens; return UNIT; // mega Siemens +"kS" yylval = Quantity::KiloSiemens; return UNIT; // kilo Siemens +"S" yylval = Quantity::Siemens; return UNIT; // Siemens (A^2*s^3/kg/m^2) +"mS" yylval = Quantity::MilliSiemens; return UNIT; // milli Siemens +"\xC2\xB5S" yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens +"uS" yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens -"Ohm" yylval = Quantity::Ohm; return UNIT; // Ohm (kg*m^2/A^2/s^3) -"kOhm" yylval = Quantity::KiloOhm; return UNIT; // kilo Ohm -"MOhm" yylval = Quantity::MegaOhm; return UNIT; // mega Ohm +"Ohm" yylval = Quantity::Ohm; return UNIT; // Ohm (kg*m^2/A^2/s^3) +"kOhm" yylval = Quantity::KiloOhm; return UNIT; // kilo Ohm +"MOhm" yylval = Quantity::MegaOhm; return UNIT; // mega Ohm -"C" yylval = Quantity::Coulomb; return UNIT; // Coulomb (A*s) +"C" yylval = Quantity::Coulomb; return UNIT; // Coulomb (A*s) -"T" yylval = Quantity::Tesla; return UNIT; // Tesla (kg/s^2/A) -"G" yylval = Quantity::Gauss; return UNIT; // Gauss (1 G = 1e-4 T) +"T" yylval = Quantity::Tesla; return UNIT; // Tesla (kg/s^2/A) +"G" yylval = Quantity::Gauss; return UNIT; // Gauss (1 G = 1e-4 T) -"Wb" yylval = Quantity::Weber; return UNIT; // Weber (kg*m^2/s^2/A) +"Wb" yylval = Quantity::Weber; return UNIT; // Weber (kg*m^2/s^2/A) -"F" yylval = Quantity::Farad; return UNIT; // Farad (s^4*A^2/m^2/kg) -"mF" yylval = Quantity::MilliFarad; return UNIT; // milli Farad -"\xC2\xB5F" yylval = Quantity::MicroFarad; return UNIT; // micro Farad -"uF" yylval = Quantity::MicroFarad; return UNIT; // micro Farad -"nF" yylval = Quantity::NanoFarad; return UNIT; // nano Farad -"pF" yylval = Quantity::PicoFarad; return UNIT; // pico Farad +"F" yylval = Quantity::Farad; return UNIT; // Farad (s^4*A^2/m^2/kg) +"mF" yylval = Quantity::MilliFarad; return UNIT; // milli Farad +"\xC2\xB5F" yylval = Quantity::MicroFarad; return UNIT; // micro Farad +"uF" yylval = Quantity::MicroFarad; return UNIT; // micro Farad +"nF" yylval = Quantity::NanoFarad; return UNIT; // nano Farad +"pF" yylval = Quantity::PicoFarad; return UNIT; // pico Farad -"H" yylval = Quantity::Henry; return UNIT; // Henry (kg*m^2/s^2/A^2) -"mH" yylval = Quantity::MilliHenry; return UNIT; // milli Henry -"\xC2\xB5H" yylval = Quantity::MicroHenry; return UNIT; // micro Henry -"uH" yylval = Quantity::MicroHenry; return UNIT; // micro Henry -"nH" yylval = Quantity::NanoHenry; return UNIT; // nano Henry +"H" yylval = Quantity::Henry; return UNIT; // Henry (kg*m^2/s^2/A^2) +"mH" yylval = Quantity::MilliHenry; return UNIT; // milli Henry +"\xC2\xB5H" yylval = Quantity::MicroHenry; return UNIT; // micro Henry +"uH" yylval = Quantity::MicroHenry; return UNIT; // micro Henry +"nH" yylval = Quantity::NanoHenry; return UNIT; // nano Henry -"J" yylval = Quantity::Joule; return UNIT; // Joule (kg*m^2/s^2) -"mJ" yylval = Quantity::MilliJoule; return UNIT; // milli Joule -"kJ" yylval = Quantity::KiloJoule; return UNIT; // kilo Joule -"Nm" yylval = Quantity::NewtonMeter; return UNIT; // N*m = Joule -"VAs" yylval = Quantity::VoltAmpereSecond; return UNIT; // V*A*s = Joule -"CV" yylval = Quantity::WattSecond; return UNIT; // -"Ws" yylval = Quantity::WattSecond; return UNIT; // W*s = Joule -"kWh" yylval = Quantity::KiloWattHour; return UNIT; // 1 kWh = 3.6e6 J -"eV" yylval = Quantity::ElectronVolt; return UNIT; // 1 eV = 1.602176634e-19 J -"keV" yylval = Quantity::KiloElectronVolt; return UNIT; -"MeV" yylval = Quantity::MegaElectronVolt; return UNIT; -"cal" yylval = Quantity::Calorie; return UNIT; // 1 cal = 4.1868 J -"kcal" yylval = Quantity::KiloCalorie; return UNIT; +"J" yylval = Quantity::Joule; return UNIT; // Joule (kg*m^2/s^2) +"mJ" yylval = Quantity::MilliJoule; return UNIT; // milli Joule +"kJ" yylval = Quantity::KiloJoule; return UNIT; // kilo Joule +"Nm" yylval = Quantity::NewtonMeter; return UNIT; // N*m = Joule +"VAs" yylval = Quantity::VoltAmpereSecond; return UNIT; // V*A*s = Joule +"CV" yylval = Quantity::WattSecond; return UNIT; // +"Ws" yylval = Quantity::WattSecond; return UNIT; // W*s = Joule +"kWh" yylval = Quantity::KiloWattHour; return UNIT; // 1 kWh = 3.6e6 J +"eV" yylval = Quantity::ElectronVolt; return UNIT; // 1 eV = 1.602176634e-19 J +"keV" yylval = Quantity::KiloElectronVolt; return UNIT; +"MeV" yylval = Quantity::MegaElectronVolt; return UNIT; +"cal" yylval = Quantity::Calorie; return UNIT; // 1 cal = 4.1868 J +"kcal" yylval = Quantity::KiloCalorie; return UNIT; -"\xC2\xB0" yylval = Quantity::Degree; return UNIT; // degree (internal standard angle) -"deg" yylval = Quantity::Degree; return UNIT; // degree (internal standard angle) -"rad" yylval = Quantity::Radian; return UNIT; // radian -"gon" yylval = Quantity::Gon; return UNIT; // gon -"M" yylval = Quantity::AngMinute; return UNIT; // minute(Angular) -"\xE2\x80\xB2" yylval = Quantity::AngMinute; return UNIT; // minute(Angular) -"AS" yylval = Quantity::AngSecond; return UNIT; // second(Angular) -"\xE2\x80\xB3" yylval = Quantity::AngSecond; return UNIT; // second(Angular) +"\xC2\xB0" yylval = Quantity::Degree; return UNIT; // degree (internal standard angle) +"deg" yylval = Quantity::Degree; return UNIT; // degree (internal standard angle) +"rad" yylval = Quantity::Radian; return UNIT; // radian +"gon" yylval = Quantity::Gon; return UNIT; // gon +"M" yylval = Quantity::AngMinute; return UNIT; // minute(Angular) +"\xE2\x80\xB2" yylval = Quantity::AngMinute; return UNIT; // minute(Angular) +"AS" yylval = Quantity::AngSecond; return UNIT; // second(Angular) +"\xE2\x80\xB3" yylval = Quantity::AngSecond; return UNIT; // second(Angular) -"1" yylval = Quantity(1.0); return ONE; -{DIGIT}+"."?{DIGIT}*{EXPO}? { yylval = Quantity(num_change(yytext,'.',','));return NUM; } -"."?{DIGIT}+{EXPO}? { yylval = Quantity(num_change(yytext,'.',','));return NUM; } -{DIGIT}+","?{DIGIT}*{EXPO}? { yylval = Quantity(num_change(yytext,',','.'));return NUM; } -","?{DIGIT}+{EXPO}? { yylval = Quantity(num_change(yytext,',','.'));return NUM; } +"1" yylval = Quantity(1.0); return ONE; +{DIGIT}+"."?{DIGIT}*{EXPO}? yylval = Quantity(num_change(yytext,'.',',')); return NUM; +"."?{DIGIT}+{EXPO}? yylval = Quantity(num_change(yytext,'.',',')); return NUM; +{DIGIT}+","?{DIGIT}*{EXPO}? yylval = Quantity(num_change(yytext,',','.')); return NUM; +","?{DIGIT}+{EXPO}? yylval = Quantity(num_change(yytext,',','.')); return NUM; +"pi" yylval = Quantity(std::numbers::pi); return NUM; // constant pi +"e" yylval = Quantity(std::numbers::e); return NUM; // constant e -"pi" {yylval = Quantity(std::numbers::pi) ; return NUM;} // constant pi -"e" {yylval = Quantity(std::numbers::e) ; return NUM;} // constant e +"acos" return ACOS; +"asin" return ASIN; +"atan" return ATAN; +"atan2" return ATAN2; +"cos" return COS; +"exp" return EXP; +"abs" return ABS; +"mod" return MOD; +"log" return LOG; +"log10" return LOG10; +"pow" return POW; +"sin" return SIN; +"sinh" return SINH; +"tan" return TAN; +"tanh" return TANH; +"sqrt" return SQRT; -"acos" return ACOS; -"asin" return ASIN; -"atan" return ATAN; -"atan2" return ATAN2; -"cos" return COS; -"exp" return EXP; -"abs" return ABS; -"mod" return MOD; -"log" return LOG; -"log10" return LOG10; -"pow" return POW; -"sin" return SIN; -"sinh" return SINH; -"tan" return TAN; -"tanh" return TANH; -"sqrt" return SQRT; - -. return *yytext; +. return *yytext; diff --git a/src/Base/QuantityParser.y b/src/Base/QuantityParser.y index b652151c81..bf66b1802f 100644 --- a/src/Base/QuantityParser.y +++ b/src/Base/QuantityParser.y @@ -18,78 +18,68 @@ * * ***************************************************************************/ -//* Parser for the FreeCAD Units language */ +/* Parser for the FreeCAD Units language */ /* Represents the many different ways we can access our data */ %{ - #define YYSTYPE Quantity - #define yyparse Quantity_yyparse - #define yyerror Quantity_yyerror - - - - - - - + #define YYSTYPE Quantity + #define yyparse Quantity_yyparse + #define yyerror Quantity_yyerror %} - /* Bison declarations. */ - %token UNIT ONE NUM MINUSSIGN - %token ACOS ASIN ATAN ATAN2 COS EXP ABS MOD LOG LOG10 POW SIN SINH TAN TANH SQRT; - %left MINUSSIGN '+' - %left '*' '/' - %left NEG /* negation--unary minus */ - %right '^' /* exponentiation */ - %left ONE NUM - - + /* Bison declarations. */ + %token UNIT ONE NUM MINUSSIGN + %token ACOS ASIN ATAN ATAN2 COS EXP ABS MOD LOG LOG10 POW SIN SINH TAN TANH SQRT; + %left MINUSSIGN '+' + %left '*' '/' + %left NEG /* negation--unary minus */ + %right '^' /* exponentiation */ + %left ONE NUM %start input %% - input: { QuantResult = Quantity(std::numeric_limits::min()); /* empty input */ } - | num { QuantResult = $1 ; } - | unit { QuantResult = $1 ; } - | quantity { QuantResult = $1 ; } - | quantity quantity { QuantResult = $1 + $2; } - | quantity quantity quantity { QuantResult = $1 + $2 + $3; } - ; - num: NUM { $$ = $1; } - | ONE { $$ = $1; } - | num '+' num { $$ = Quantity($1.getValue() + $3.getValue()); } - | num MINUSSIGN num { $$ = Quantity($1.getValue() - $3.getValue()); } - | num '*' num { $$ = Quantity($1.getValue() * $3.getValue()); } - | num '/' num { $$ = Quantity($1.getValue() / $3.getValue()); } - | MINUSSIGN num %prec NEG { $$ = Quantity(-$2.getValue()); } - | num '^' num { $$ = Quantity(pow ($1.getValue(), $3.getValue()));} - | '(' num ')' { $$ = $2; } - | ACOS '(' num ')' { $$ = Quantity(acos($3.getValue())); } - | ASIN '(' num ')' { $$ = Quantity(asin($3.getValue())); } - | ATAN '(' num ')' { $$ = Quantity(atan($3.getValue())); } - | ABS '(' num ')' { $$ = Quantity(fabs($3.getValue())); } - | EXP '(' num ')' { $$ = Quantity(exp($3.getValue())); } - | LOG '(' num ')' { $$ = Quantity(log($3.getValue())); } - | LOG10 '(' num ')' { $$ = Quantity(log10($3.getValue())); } - | SIN '(' num ')' { $$ = Quantity(sin($3.getValue())); } - | SINH '(' num ')' { $$ = Quantity(sinh($3.getValue())); } - | TAN '(' num ')' { $$ = Quantity(tan($3.getValue())); } - | TANH '(' num ')' { $$ = Quantity(tanh($3.getValue())); } - | SQRT '(' num ')' { $$ = Quantity(sqrt($3.getValue())); } - | COS '(' num ')' { $$ = Quantity(cos($3.getValue())); } + input: { QuantResult = Quantity(std::numeric_limits::min()); /* empty input */ } + | num { QuantResult = $1; } + | unit { QuantResult = $1; } + | quantity { QuantResult = $1; } + | quantity quantity { QuantResult = $1 + $2; } + | quantity quantity quantity { QuantResult = $1 + $2 + $3; } +; + num: NUM { $$ = $1; } + | ONE { $$ = $1; } + | num '+' num { $$ = Quantity($1.getValue() + $3.getValue()); } + | num MINUSSIGN num { $$ = Quantity($1.getValue() - $3.getValue()); } + | num '*' num { $$ = Quantity($1.getValue() * $3.getValue()); } + | num '/' num { $$ = Quantity($1.getValue() / $3.getValue()); } + | MINUSSIGN num %prec NEG { $$ = Quantity(-$2.getValue()); } + | num '^' num { $$ = Quantity(pow($1.getValue(), $3.getValue())); } + | '(' num ')' { $$ = $2; } + | ACOS '(' num ')' { $$ = Quantity(acos($3.getValue())); } + | ASIN '(' num ')' { $$ = Quantity(asin($3.getValue())); } + | ATAN '(' num ')' { $$ = Quantity(atan($3.getValue())); } + | ABS '(' num ')' { $$ = Quantity(fabs($3.getValue())); } + | EXP '(' num ')' { $$ = Quantity(exp($3.getValue())); } + | LOG '(' num ')' { $$ = Quantity(log($3.getValue())); } + | LOG10 '(' num ')' { $$ = Quantity(log10($3.getValue())); } + | SIN '(' num ')' { $$ = Quantity(sin($3.getValue())); } + | SINH '(' num ')' { $$ = Quantity(sinh($3.getValue())); } + | TAN '(' num ')' { $$ = Quantity(tan($3.getValue())); } + | TANH '(' num ')' { $$ = Quantity(tanh($3.getValue())); } + | SQRT '(' num ')' { $$ = Quantity(sqrt($3.getValue())); } + | COS '(' num ')' { $$ = Quantity(cos($3.getValue())); } ; - unit: UNIT { $$ = $1; } - | ONE '/' unit { $$ = Quantity(1.0)/$3; } - | unit '*' unit { $$ = $1 * $3; } - | unit '/' unit { $$ = $1 / $3; } - | unit '^' num { $$ = $1.pow ($3); } - | '(' unit ')' { $$ = $2; } + unit: UNIT { $$ = $1; } + | ONE '/' unit { $$ = Quantity(1.0)/$3; } + | unit '*' unit { $$ = $1 * $3; } + | unit '/' unit { $$ = $1 / $3; } + | unit '^' num { $$ = $1.pow ($3); } + | '(' unit ')' { $$ = $2; } ; - quantity: num unit { $$ = $1*$2; } - | num '/' unit { $$ = Quantity($1)/$3; } + quantity: num unit { $$ = $1*$2; } + | num '/' unit { $$ = Quantity($1)/$3; } ; - %% From ed00a6673cd7a27c05c78952937a20406af5b4f0 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Mon, 7 Apr 2025 16:31:57 +0200 Subject: [PATCH 181/316] Base: Quantity: rename lexer and parser files Rename files according 7d233dc ("Gui: Rename generated lexer files to match core naming pattern"). Note that C space errors (space before tabs, spaces on blank lines, etc.) still need to be fixed manually after regenerating lexer file. --- src/Base/CMakeLists.txt | 4 +- src/Base/Parser.bat | 4 +- src/Base/Parser.sh | 8 +- src/Base/Quantity.cpp | 8 +- src/Base/{QuantityParser.l => Quantity.l} | 7 - src/Base/{QuantityLexer.c => Quantity.lex.c} | 374 +++-- src/Base/{QuantityParser.c => Quantity.tab.c} | 1332 ++++++++--------- src/Base/{QuantityParser.y => Quantity.y} | 0 src/Base/QuantityParser.h | 85 -- 9 files changed, 806 insertions(+), 1016 deletions(-) rename src/Base/{QuantityParser.l => Quantity.l} (97%) rename src/Base/{QuantityLexer.c => Quantity.lex.c} (91%) rename src/Base/{QuantityParser.c => Quantity.tab.c} (54%) rename src/Base/{QuantityParser.y => Quantity.y} (100%) delete mode 100644 src/Base/QuantityParser.h diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index 58c8d3c0d3..c7ef083eea 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -167,8 +167,8 @@ SET(FreeCADBase_UNITAPI_SRCS Quantity.h Quantity.cpp QuantityPyImp.cpp - QuantityParser.l - QuantityParser.y + Quantity.l + Quantity.y Unit.h Unit.cpp UnitPyImp.cpp diff --git a/src/Base/Parser.bat b/src/Base/Parser.bat index d5620b88f4..6b67cd3d76 100644 --- a/src/Base/Parser.bat +++ b/src/Base/Parser.bat @@ -1,2 +1,2 @@ -C:\cygwin\bin\flex.exe -oQuantityLexer.c QuantityParser.l -C:\cygwin\bin\bison -oQuantityParser.c QuantityParser.y +C:\cygwin\bin\flex.exe -oQuantity.lex.c Quantity.l +C:\cygwin\bin\bison -oQuantity.tab.c Quantity.y diff --git a/src/Base/Parser.sh b/src/Base/Parser.sh index c82c9b8cb7..2e7d75aaf3 100644 --- a/src/Base/Parser.sh +++ b/src/Base/Parser.sh @@ -1,2 +1,6 @@ -flex -oQuantityLexer.c < QuantityParser.l -bison -oQuantityParser.c QuantityParser.y +(cd "$(dirname "$0")" && \ + flex -oQuantity.lex.c Quantity.l && \ + bison -oQuantity.tab.c Quantity.y && \ + sed -i '1s|^|// clang-format off\n|' Quantity.tab.c && \ + sed -i '1s|^|// clang-format off\n|' Quantity.lex.c \ +) diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index 1b25793824..e5102dbb16 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -523,14 +523,14 @@ namespace QuantityParser #define yylex QuantityLexer int QuantityLexer(); -// Parser, defined in QuantityParser.y +// Parser, defined in Quantity.y // NOLINTNEXTLINE -#include "QuantityParser.c" +#include "Quantity.tab.c" #ifndef DOXYGEN_SHOULD_SKIP_THIS -// Scanner, defined in QuantityParser.l +// Scanner, defined in Quantity.l // NOLINTNEXTLINE -#include "QuantityLexer.c" +#include "Quantity.lex.c" #endif // DOXYGEN_SHOULD_SKIP_THIS class StringBufferCleaner diff --git a/src/Base/QuantityParser.l b/src/Base/Quantity.l similarity index 97% rename from src/Base/QuantityParser.l rename to src/Base/Quantity.l index 1daf9a4e25..08d0c03fd4 100644 --- a/src/Base/QuantityParser.l +++ b/src/Base/Quantity.l @@ -21,13 +21,6 @@ /* Lexer for the FreeCAD Units language */ -/* use this file to generate the file 'QuantityLexer.c' using the program flex - * the command for this operation is: - * flex --outfile=QuantityLexer.c QuantityParser.l - * (flex for Windows is available here: - * https://sourceforge.net/projects/winflexbison/ - * (you must then change 'flex' to 'win_flex' in the command)) */ - /* This disables inclusion of unistd.h, which is not available under Visual C++ * on Win32. The C++ scanner uses STL streams instead. */ #define YY_NO_UNISTD_H diff --git a/src/Base/QuantityLexer.c b/src/Base/Quantity.lex.c similarity index 91% rename from src/Base/QuantityLexer.c rename to src/Base/Quantity.lex.c index 547916b50b..8a645130a6 100644 --- a/src/Base/QuantityLexer.c +++ b/src/Base/Quantity.lex.c @@ -1,7 +1,7 @@ // clang-format off -#line 1 "QuantityLexer.c" +#line 2 "Quantity.lex.c" -#line 3 "QuantityLexer.c" +#line 4 "Quantity.lex.c" #define YY_INT_ALIGNED short int @@ -627,8 +627,8 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "QuantityParser.l" -#line 2 "QuantityParser.l" +#line 1 "Quantity.l" +#line 2 "Quantity.l" /*************************************************************************** * Copyright (c) 2013 Jürgen Riegel * * * @@ -651,23 +651,16 @@ char *yytext; /* Lexer for the FreeCAD Units language */ -/* use this file to generate the file 'QuantityLexer.c' using the program flex - * the command for this operation is: - * flex --outfile=QuantityLexer.c QuantityParser.l - * (flex for Windows is available here: - * https://sourceforge.net/projects/winflexbison/ - * (you must then change 'flex' to 'win_flex' in the command)) */ - /* This disables inclusion of unistd.h, which is not available under Visual C++ * on Win32. The C++ scanner uses STL streams instead. */ #define YY_NO_UNISTD_H -#line 664 "QuantityLexer.c" +#line 658 "Quantity.lex.c" /*** Flex Declarations and Options ***/ /* the manual says "somewhat more optimized" */ /* no support for include files is planned */ -#line 669 "QuantityLexer.c" +#line 663 "Quantity.lex.c" #define INITIAL 0 #define C_COMMENT 1 @@ -883,10 +876,10 @@ YY_DECL } { -#line 56 "QuantityParser.l" +#line 49 "Quantity.l" -#line 888 "QuantityLexer.c" +#line 882 "Quantity.lex.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -941,776 +934,776 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 58 "QuantityParser.l" +#line 51 "Quantity.l" { BEGIN(C_COMMENT); } YY_BREAK case 2: YY_RULE_SETUP -#line 59 "QuantityParser.l" +#line 52 "Quantity.l" { BEGIN(INITIAL); } YY_BREAK case 3: YY_RULE_SETUP -#line 60 "QuantityParser.l" +#line 53 "Quantity.l" { ;} YY_BREAK case 4: YY_RULE_SETUP -#line 63 "QuantityParser.l" +#line 56 "Quantity.l" ; YY_BREAK case 5: /* rule 5 can match eol */ YY_RULE_SETUP -#line 64 "QuantityParser.l" +#line 57 "Quantity.l" ; YY_BREAK case 6: YY_RULE_SETUP -#line 66 "QuantityParser.l" -{ return *yytext; } +#line 59 "Quantity.l" +return *yytext; YY_BREAK case 7: YY_RULE_SETUP -#line 68 "QuantityParser.l" +#line 61 "Quantity.l" return MINUSSIGN; YY_BREAK case 8: YY_RULE_SETUP -#line 69 "QuantityParser.l" +#line 62 "Quantity.l" return MINUSSIGN; YY_BREAK case 9: YY_RULE_SETUP -#line 71 "QuantityParser.l" +#line 64 "Quantity.l" yylval = Quantity::NanoMetre; return UNIT; // nano meter YY_BREAK case 10: YY_RULE_SETUP -#line 72 "QuantityParser.l" +#line 65 "Quantity.l" yylval = Quantity::MicroMetre; return UNIT; // micro meter YY_BREAK case 11: YY_RULE_SETUP -#line 73 "QuantityParser.l" +#line 66 "Quantity.l" yylval = Quantity::MicroMetre; return UNIT; // micro meter (greek micro in UTF8) YY_BREAK case 12: YY_RULE_SETUP -#line 74 "QuantityParser.l" +#line 67 "Quantity.l" yylval = Quantity::MilliMetre; return UNIT; // milli meter (internal standard length) YY_BREAK case 13: YY_RULE_SETUP -#line 75 "QuantityParser.l" +#line 68 "Quantity.l" yylval = Quantity::CentiMetre; return UNIT; // centi meter YY_BREAK case 14: YY_RULE_SETUP -#line 76 "QuantityParser.l" +#line 69 "Quantity.l" yylval = Quantity::DeciMetre; return UNIT; // deci meter YY_BREAK case 15: YY_RULE_SETUP -#line 77 "QuantityParser.l" +#line 70 "Quantity.l" yylval = Quantity::Metre; return UNIT; // Metre YY_BREAK case 16: YY_RULE_SETUP -#line 78 "QuantityParser.l" +#line 71 "Quantity.l" yylval = Quantity::KiloMetre; return UNIT; // kilo meter YY_BREAK case 17: YY_RULE_SETUP -#line 80 "QuantityParser.l" +#line 73 "Quantity.l" yylval = Quantity::Liter; return UNIT; // Liter (dm^3) YY_BREAK case 18: YY_RULE_SETUP -#line 81 "QuantityParser.l" +#line 74 "Quantity.l" yylval = Quantity::MilliLiter; return UNIT; // milli Liter YY_BREAK case 19: YY_RULE_SETUP -#line 83 "QuantityParser.l" +#line 76 "Quantity.l" yylval = Quantity::Hertz; return UNIT; // Hertz YY_BREAK case 20: YY_RULE_SETUP -#line 84 "QuantityParser.l" +#line 77 "Quantity.l" yylval = Quantity::KiloHertz; return UNIT; // kilo Hertz YY_BREAK case 21: YY_RULE_SETUP -#line 85 "QuantityParser.l" +#line 78 "Quantity.l" yylval = Quantity::MegaHertz; return UNIT; // mega Hertz YY_BREAK case 22: YY_RULE_SETUP -#line 86 "QuantityParser.l" +#line 79 "Quantity.l" yylval = Quantity::GigaHertz; return UNIT; // giga Hertz YY_BREAK case 23: YY_RULE_SETUP -#line 87 "QuantityParser.l" +#line 80 "Quantity.l" yylval = Quantity::TeraHertz; return UNIT; // tera Hertz YY_BREAK case 24: YY_RULE_SETUP -#line 89 "QuantityParser.l" +#line 82 "Quantity.l" yylval = Quantity::MicroGram; return UNIT; // micro gram YY_BREAK case 25: YY_RULE_SETUP -#line 90 "QuantityParser.l" +#line 83 "Quantity.l" yylval = Quantity::MicroGram; return UNIT; // micro gram YY_BREAK case 26: YY_RULE_SETUP -#line 91 "QuantityParser.l" +#line 84 "Quantity.l" yylval = Quantity::MilliGram; return UNIT; // milli gram YY_BREAK case 27: YY_RULE_SETUP -#line 92 "QuantityParser.l" +#line 85 "Quantity.l" yylval = Quantity::Gram; return UNIT; // gram YY_BREAK case 28: YY_RULE_SETUP -#line 93 "QuantityParser.l" +#line 86 "Quantity.l" yylval = Quantity::KiloGram; return UNIT; // kilo gram (internal standard for mass) YY_BREAK case 29: YY_RULE_SETUP -#line 94 "QuantityParser.l" +#line 87 "Quantity.l" yylval = Quantity::Ton; return UNIT; // Metric Tonne YY_BREAK case 30: YY_RULE_SETUP -#line 96 "QuantityParser.l" +#line 89 "Quantity.l" yylval = Quantity::Second; return UNIT; // second (internal standard time) YY_BREAK case 31: YY_RULE_SETUP -#line 97 "QuantityParser.l" +#line 90 "Quantity.l" yylval = Quantity::Minute; return UNIT; // minute YY_BREAK case 32: YY_RULE_SETUP -#line 98 "QuantityParser.l" +#line 91 "Quantity.l" yylval = Quantity::Hour; return UNIT; // hour YY_BREAK case 33: YY_RULE_SETUP -#line 100 "QuantityParser.l" +#line 93 "Quantity.l" yylval = Quantity::Ampere; return UNIT; // Ampere (internal standard electric current) YY_BREAK case 34: YY_RULE_SETUP -#line 101 "QuantityParser.l" +#line 94 "Quantity.l" yylval = Quantity::MilliAmpere; return UNIT; // milli Ampere YY_BREAK case 35: YY_RULE_SETUP -#line 102 "QuantityParser.l" +#line 95 "Quantity.l" yylval = Quantity::KiloAmpere; return UNIT; // kilo Ampere YY_BREAK case 36: YY_RULE_SETUP -#line 103 "QuantityParser.l" +#line 96 "Quantity.l" yylval = Quantity::MegaAmpere; return UNIT; // mega Ampere YY_BREAK case 37: YY_RULE_SETUP -#line 105 "QuantityParser.l" +#line 98 "Quantity.l" yylval = Quantity::Kelvin; return UNIT; // Kelvin (internal standard thermodynamic temperature) YY_BREAK case 38: YY_RULE_SETUP -#line 106 "QuantityParser.l" +#line 99 "Quantity.l" yylval = Quantity::MilliKelvin; return UNIT; // milli Kelvin YY_BREAK case 39: YY_RULE_SETUP -#line 107 "QuantityParser.l" +#line 100 "Quantity.l" yylval = Quantity::MicroKelvin; return UNIT; // micro Kelvin YY_BREAK case 40: YY_RULE_SETUP -#line 108 "QuantityParser.l" +#line 101 "Quantity.l" yylval = Quantity::MicroKelvin; return UNIT; // micro Kelvin YY_BREAK case 41: YY_RULE_SETUP -#line 110 "QuantityParser.l" +#line 103 "Quantity.l" yylval = Quantity::Mole; return UNIT; // Mole (internal standard amount of substance) YY_BREAK case 42: YY_RULE_SETUP -#line 111 "QuantityParser.l" +#line 104 "Quantity.l" yylval = Quantity::MilliMole; return UNIT; // Milli Mole YY_BREAK case 43: YY_RULE_SETUP -#line 113 "QuantityParser.l" +#line 106 "Quantity.l" yylval = Quantity::Candela; return UNIT; // Candela (internal standard luminous intensity) YY_BREAK case 44: YY_RULE_SETUP -#line 115 "QuantityParser.l" +#line 108 "Quantity.l" yylval = Quantity::Inch; return UNIT; // inch YY_BREAK case 45: YY_RULE_SETUP -#line 116 "QuantityParser.l" +#line 109 "Quantity.l" yylval = Quantity::Inch; return UNIT; // inch YY_BREAK case 46: YY_RULE_SETUP -#line 117 "QuantityParser.l" +#line 110 "Quantity.l" yylval = Quantity::Foot; return UNIT; // foot YY_BREAK case 47: YY_RULE_SETUP -#line 118 "QuantityParser.l" +#line 111 "Quantity.l" yylval = Quantity::Foot; return UNIT; // foot YY_BREAK case 48: YY_RULE_SETUP -#line 119 "QuantityParser.l" +#line 112 "Quantity.l" yylval = Quantity::Thou; return UNIT; // thou (in/1000) YY_BREAK case 49: YY_RULE_SETUP -#line 120 "QuantityParser.l" +#line 113 "Quantity.l" yylval = Quantity::Thou; return UNIT; // mil (the thou in US) YY_BREAK case 50: YY_RULE_SETUP -#line 121 "QuantityParser.l" +#line 114 "Quantity.l" yylval = Quantity::Yard; return UNIT; // yard YY_BREAK case 51: YY_RULE_SETUP -#line 122 "QuantityParser.l" +#line 115 "Quantity.l" yylval = Quantity::Mile; return UNIT; // mile YY_BREAK case 52: YY_RULE_SETUP -#line 124 "QuantityParser.l" +#line 117 "Quantity.l" yylval = Quantity::MilePerHour; return UNIT; // mile per hour YY_BREAK case 53: YY_RULE_SETUP -#line 125 "QuantityParser.l" +#line 118 "Quantity.l" yylval = Quantity::SquareFoot; return UNIT; // square foot YY_BREAK case 54: YY_RULE_SETUP -#line 126 "QuantityParser.l" +#line 119 "Quantity.l" yylval = Quantity::CubicFoot; return UNIT; // cubic foot YY_BREAK case 55: YY_RULE_SETUP -#line 128 "QuantityParser.l" +#line 121 "Quantity.l" yylval = Quantity::Pound; return UNIT; // pound YY_BREAK case 56: YY_RULE_SETUP -#line 129 "QuantityParser.l" +#line 122 "Quantity.l" yylval = Quantity::Pound; return UNIT; // pound YY_BREAK case 57: YY_RULE_SETUP -#line 130 "QuantityParser.l" +#line 123 "Quantity.l" yylval = Quantity::Ounce; return UNIT; // ounce YY_BREAK case 58: YY_RULE_SETUP -#line 131 "QuantityParser.l" +#line 124 "Quantity.l" yylval = Quantity::Stone; return UNIT; // Stone YY_BREAK case 59: YY_RULE_SETUP -#line 132 "QuantityParser.l" +#line 125 "Quantity.l" yylval = Quantity::Hundredweights; return UNIT; // hundredweights YY_BREAK case 60: YY_RULE_SETUP -#line 134 "QuantityParser.l" +#line 127 "Quantity.l" yylval = Quantity::PoundForce; return UNIT; // pound YY_BREAK case 61: YY_RULE_SETUP -#line 136 "QuantityParser.l" +#line 129 "Quantity.l" yylval = Quantity::Newton; return UNIT; // Newton (kg*m/s^2) YY_BREAK case 62: YY_RULE_SETUP -#line 137 "QuantityParser.l" +#line 130 "Quantity.l" yylval = Quantity::MilliNewton; return UNIT; // milli Newton YY_BREAK case 63: YY_RULE_SETUP -#line 138 "QuantityParser.l" +#line 131 "Quantity.l" yylval = Quantity::KiloNewton; return UNIT; // kilo Newton YY_BREAK case 64: YY_RULE_SETUP -#line 139 "QuantityParser.l" +#line 132 "Quantity.l" yylval = Quantity::MegaNewton; return UNIT; // mega Newton YY_BREAK case 65: YY_RULE_SETUP -#line 141 "QuantityParser.l" +#line 134 "Quantity.l" yylval = Quantity::Pascal; return UNIT; // Pascal (kg/m/s^2 or N/m^2) YY_BREAK case 66: YY_RULE_SETUP -#line 142 "QuantityParser.l" +#line 135 "Quantity.l" yylval = Quantity::KiloPascal; return UNIT; // kilo Pascal YY_BREAK case 67: YY_RULE_SETUP -#line 143 "QuantityParser.l" +#line 136 "Quantity.l" yylval = Quantity::MegaPascal; return UNIT; // mega Pascal YY_BREAK case 68: YY_RULE_SETUP -#line 144 "QuantityParser.l" +#line 137 "Quantity.l" yylval = Quantity::GigaPascal; return UNIT; // giga Pascal YY_BREAK case 69: YY_RULE_SETUP -#line 146 "QuantityParser.l" +#line 139 "Quantity.l" yylval = Quantity::Bar; return UNIT; // 1 bar = 100 kPa YY_BREAK case 70: YY_RULE_SETUP -#line 147 "QuantityParser.l" +#line 140 "Quantity.l" yylval = Quantity::MilliBar; return UNIT; // milli Bar YY_BREAK case 71: YY_RULE_SETUP -#line 149 "QuantityParser.l" +#line 142 "Quantity.l" yylval = Quantity::Torr; return UNIT; // portion of Pascal ( 101325/760 ) YY_BREAK case 72: YY_RULE_SETUP -#line 150 "QuantityParser.l" +#line 143 "Quantity.l" yylval = Quantity::mTorr; return UNIT; // YY_BREAK case 73: YY_RULE_SETUP -#line 151 "QuantityParser.l" +#line 144 "Quantity.l" yylval = Quantity::yTorr; return UNIT; // YY_BREAK case 74: YY_RULE_SETUP -#line 152 "QuantityParser.l" +#line 145 "Quantity.l" yylval = Quantity::yTorr; return UNIT; // YY_BREAK case 75: YY_RULE_SETUP -#line 154 "QuantityParser.l" +#line 147 "Quantity.l" yylval = Quantity::PSI; return UNIT; // pounds/in^2 YY_BREAK case 76: YY_RULE_SETUP -#line 155 "QuantityParser.l" +#line 148 "Quantity.l" yylval = Quantity::KSI; return UNIT; // 1000 x pounds/in^2 YY_BREAK case 77: YY_RULE_SETUP -#line 156 "QuantityParser.l" +#line 149 "Quantity.l" yylval = Quantity::MPSI; return UNIT; // 1000 ksi YY_BREAK case 78: YY_RULE_SETUP -#line 158 "QuantityParser.l" +#line 151 "Quantity.l" yylval = Quantity::Watt; return UNIT; // Watt (kg*m^2/s^3) YY_BREAK case 79: YY_RULE_SETUP -#line 159 "QuantityParser.l" +#line 152 "Quantity.l" yylval = Quantity::MilliWatt; return UNIT; // milli Watt YY_BREAK case 80: YY_RULE_SETUP -#line 160 "QuantityParser.l" +#line 153 "Quantity.l" yylval = Quantity::KiloWatt; return UNIT; // kilo Watt YY_BREAK case 81: YY_RULE_SETUP -#line 161 "QuantityParser.l" +#line 154 "Quantity.l" yylval = Quantity::VoltAmpere; return UNIT; // VoltAmpere (kg*m^2/s^3) YY_BREAK case 82: YY_RULE_SETUP -#line 163 "QuantityParser.l" +#line 156 "Quantity.l" yylval = Quantity::Volt; return UNIT; // Volt (kg*m^2/A/s^3) YY_BREAK case 83: YY_RULE_SETUP -#line 164 "QuantityParser.l" +#line 157 "Quantity.l" yylval = Quantity::KiloVolt; return UNIT; // kilo Volt YY_BREAK case 84: YY_RULE_SETUP -#line 165 "QuantityParser.l" +#line 158 "Quantity.l" yylval = Quantity::MilliVolt; return UNIT; // milli Volt YY_BREAK case 85: YY_RULE_SETUP -#line 167 "QuantityParser.l" +#line 160 "Quantity.l" yylval = Quantity::MegaSiemens; return UNIT; // mega Siemens YY_BREAK case 86: YY_RULE_SETUP -#line 168 "QuantityParser.l" +#line 161 "Quantity.l" yylval = Quantity::KiloSiemens; return UNIT; // kilo Siemens YY_BREAK case 87: YY_RULE_SETUP -#line 169 "QuantityParser.l" +#line 162 "Quantity.l" yylval = Quantity::Siemens; return UNIT; // Siemens (A^2*s^3/kg/m^2) YY_BREAK case 88: YY_RULE_SETUP -#line 170 "QuantityParser.l" +#line 163 "Quantity.l" yylval = Quantity::MilliSiemens; return UNIT; // milli Siemens YY_BREAK case 89: YY_RULE_SETUP -#line 171 "QuantityParser.l" -yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens +#line 164 "Quantity.l" +yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens YY_BREAK case 90: YY_RULE_SETUP -#line 172 "QuantityParser.l" +#line 165 "Quantity.l" yylval = Quantity::MicroSiemens; return UNIT; // micro Siemens YY_BREAK case 91: YY_RULE_SETUP -#line 174 "QuantityParser.l" +#line 167 "Quantity.l" yylval = Quantity::Ohm; return UNIT; // Ohm (kg*m^2/A^2/s^3) YY_BREAK case 92: YY_RULE_SETUP -#line 175 "QuantityParser.l" +#line 168 "Quantity.l" yylval = Quantity::KiloOhm; return UNIT; // kilo Ohm YY_BREAK case 93: YY_RULE_SETUP -#line 176 "QuantityParser.l" +#line 169 "Quantity.l" yylval = Quantity::MegaOhm; return UNIT; // mega Ohm YY_BREAK case 94: YY_RULE_SETUP -#line 178 "QuantityParser.l" +#line 171 "Quantity.l" yylval = Quantity::Coulomb; return UNIT; // Coulomb (A*s) YY_BREAK case 95: YY_RULE_SETUP -#line 180 "QuantityParser.l" +#line 173 "Quantity.l" yylval = Quantity::Tesla; return UNIT; // Tesla (kg/s^2/A) YY_BREAK case 96: YY_RULE_SETUP -#line 181 "QuantityParser.l" +#line 174 "Quantity.l" yylval = Quantity::Gauss; return UNIT; // Gauss (1 G = 1e-4 T) YY_BREAK case 97: YY_RULE_SETUP -#line 183 "QuantityParser.l" +#line 176 "Quantity.l" yylval = Quantity::Weber; return UNIT; // Weber (kg*m^2/s^2/A) YY_BREAK case 98: YY_RULE_SETUP -#line 185 "QuantityParser.l" +#line 178 "Quantity.l" yylval = Quantity::Farad; return UNIT; // Farad (s^4*A^2/m^2/kg) YY_BREAK case 99: YY_RULE_SETUP -#line 186 "QuantityParser.l" +#line 179 "Quantity.l" yylval = Quantity::MilliFarad; return UNIT; // milli Farad YY_BREAK case 100: YY_RULE_SETUP -#line 187 "QuantityParser.l" -yylval = Quantity::MicroFarad; return UNIT; // micro Farad +#line 180 "Quantity.l" +yylval = Quantity::MicroFarad; return UNIT; // micro Farad YY_BREAK case 101: YY_RULE_SETUP -#line 188 "QuantityParser.l" +#line 181 "Quantity.l" yylval = Quantity::MicroFarad; return UNIT; // micro Farad YY_BREAK case 102: YY_RULE_SETUP -#line 189 "QuantityParser.l" +#line 182 "Quantity.l" yylval = Quantity::NanoFarad; return UNIT; // nano Farad YY_BREAK case 103: YY_RULE_SETUP -#line 190 "QuantityParser.l" +#line 183 "Quantity.l" yylval = Quantity::PicoFarad; return UNIT; // pico Farad YY_BREAK case 104: YY_RULE_SETUP -#line 192 "QuantityParser.l" +#line 185 "Quantity.l" yylval = Quantity::Henry; return UNIT; // Henry (kg*m^2/s^2/A^2) YY_BREAK case 105: YY_RULE_SETUP -#line 193 "QuantityParser.l" +#line 186 "Quantity.l" yylval = Quantity::MilliHenry; return UNIT; // milli Henry YY_BREAK case 106: YY_RULE_SETUP -#line 194 "QuantityParser.l" -yylval = Quantity::MicroHenry; return UNIT; // micro Henry +#line 187 "Quantity.l" +yylval = Quantity::MicroHenry; return UNIT; // micro Henry YY_BREAK case 107: YY_RULE_SETUP -#line 195 "QuantityParser.l" +#line 188 "Quantity.l" yylval = Quantity::MicroHenry; return UNIT; // micro Henry YY_BREAK case 108: YY_RULE_SETUP -#line 196 "QuantityParser.l" +#line 189 "Quantity.l" yylval = Quantity::NanoHenry; return UNIT; // nano Henry YY_BREAK case 109: YY_RULE_SETUP -#line 198 "QuantityParser.l" +#line 191 "Quantity.l" yylval = Quantity::Joule; return UNIT; // Joule (kg*m^2/s^2) YY_BREAK case 110: YY_RULE_SETUP -#line 199 "QuantityParser.l" +#line 192 "Quantity.l" yylval = Quantity::MilliJoule; return UNIT; // milli Joule YY_BREAK case 111: YY_RULE_SETUP -#line 200 "QuantityParser.l" +#line 193 "Quantity.l" yylval = Quantity::KiloJoule; return UNIT; // kilo Joule YY_BREAK case 112: YY_RULE_SETUP -#line 201 "QuantityParser.l" +#line 194 "Quantity.l" yylval = Quantity::NewtonMeter; return UNIT; // N*m = Joule YY_BREAK case 113: YY_RULE_SETUP -#line 202 "QuantityParser.l" +#line 195 "Quantity.l" yylval = Quantity::VoltAmpereSecond; return UNIT; // V*A*s = Joule YY_BREAK case 114: YY_RULE_SETUP -#line 203 "QuantityParser.l" +#line 196 "Quantity.l" yylval = Quantity::WattSecond; return UNIT; // YY_BREAK case 115: YY_RULE_SETUP -#line 204 "QuantityParser.l" +#line 197 "Quantity.l" yylval = Quantity::WattSecond; return UNIT; // W*s = Joule YY_BREAK case 116: YY_RULE_SETUP -#line 205 "QuantityParser.l" +#line 198 "Quantity.l" yylval = Quantity::KiloWattHour; return UNIT; // 1 kWh = 3.6e6 J YY_BREAK case 117: YY_RULE_SETUP -#line 206 "QuantityParser.l" +#line 199 "Quantity.l" yylval = Quantity::ElectronVolt; return UNIT; // 1 eV = 1.602176634e-19 J YY_BREAK case 118: YY_RULE_SETUP -#line 207 "QuantityParser.l" +#line 200 "Quantity.l" yylval = Quantity::KiloElectronVolt; return UNIT; YY_BREAK case 119: YY_RULE_SETUP -#line 208 "QuantityParser.l" +#line 201 "Quantity.l" yylval = Quantity::MegaElectronVolt; return UNIT; YY_BREAK case 120: YY_RULE_SETUP -#line 209 "QuantityParser.l" +#line 202 "Quantity.l" yylval = Quantity::Calorie; return UNIT; // 1 cal = 4.1868 J YY_BREAK case 121: YY_RULE_SETUP -#line 210 "QuantityParser.l" +#line 203 "Quantity.l" yylval = Quantity::KiloCalorie; return UNIT; YY_BREAK case 122: YY_RULE_SETUP -#line 212 "QuantityParser.l" +#line 205 "Quantity.l" yylval = Quantity::Degree; return UNIT; // degree (internal standard angle) YY_BREAK case 123: YY_RULE_SETUP -#line 213 "QuantityParser.l" +#line 206 "Quantity.l" yylval = Quantity::Degree; return UNIT; // degree (internal standard angle) YY_BREAK case 124: YY_RULE_SETUP -#line 214 "QuantityParser.l" +#line 207 "Quantity.l" yylval = Quantity::Radian; return UNIT; // radian YY_BREAK case 125: YY_RULE_SETUP -#line 215 "QuantityParser.l" +#line 208 "Quantity.l" yylval = Quantity::Gon; return UNIT; // gon YY_BREAK case 126: YY_RULE_SETUP -#line 216 "QuantityParser.l" +#line 209 "Quantity.l" yylval = Quantity::AngMinute; return UNIT; // minute(Angular) YY_BREAK case 127: YY_RULE_SETUP -#line 217 "QuantityParser.l" -yylval = Quantity::AngMinute; return UNIT; // minute(Angular) +#line 210 "Quantity.l" +yylval = Quantity::AngMinute; return UNIT; // minute(Angular) YY_BREAK case 128: YY_RULE_SETUP -#line 218 "QuantityParser.l" +#line 211 "Quantity.l" yylval = Quantity::AngSecond; return UNIT; // second(Angular) YY_BREAK case 129: YY_RULE_SETUP -#line 219 "QuantityParser.l" -yylval = Quantity::AngSecond; return UNIT; // second(Angular) +#line 212 "Quantity.l" +yylval = Quantity::AngSecond; return UNIT; // second(Angular) YY_BREAK case 130: YY_RULE_SETUP -#line 221 "QuantityParser.l" +#line 214 "Quantity.l" yylval = Quantity(1.0); return ONE; YY_BREAK case 131: YY_RULE_SETUP -#line 222 "QuantityParser.l" -{ yylval = Quantity(num_change(yytext,'.',','));return NUM; } +#line 215 "Quantity.l" +yylval = Quantity(num_change(yytext,'.',',')); return NUM; YY_BREAK case 132: YY_RULE_SETUP -#line 223 "QuantityParser.l" -{ yylval = Quantity(num_change(yytext,'.',','));return NUM; } +#line 216 "Quantity.l" +yylval = Quantity(num_change(yytext,'.',',')); return NUM; YY_BREAK case 133: YY_RULE_SETUP -#line 224 "QuantityParser.l" -{ yylval = Quantity(num_change(yytext,',','.'));return NUM; } +#line 217 "Quantity.l" +yylval = Quantity(num_change(yytext,',','.')); return NUM; YY_BREAK case 134: YY_RULE_SETUP -#line 225 "QuantityParser.l" -{ yylval = Quantity(num_change(yytext,',','.'));return NUM; } +#line 218 "Quantity.l" +yylval = Quantity(num_change(yytext,',','.')); return NUM; YY_BREAK case 135: YY_RULE_SETUP -#line 228 "QuantityParser.l" -{yylval = Quantity(std::numbers::pi) ; return NUM;} // constant pi +#line 220 "Quantity.l" +yylval = Quantity(std::numbers::pi); return NUM; // constant pi YY_BREAK case 136: YY_RULE_SETUP -#line 229 "QuantityParser.l" -{yylval = Quantity(std::numbers::e) ; return NUM;} // constant e +#line 221 "Quantity.l" +yylval = Quantity(std::numbers::e); return NUM; // constant e YY_BREAK case 137: YY_RULE_SETUP -#line 231 "QuantityParser.l" +#line 223 "Quantity.l" return ACOS; YY_BREAK case 138: YY_RULE_SETUP -#line 232 "QuantityParser.l" +#line 224 "Quantity.l" return ASIN; YY_BREAK case 139: YY_RULE_SETUP -#line 233 "QuantityParser.l" +#line 225 "Quantity.l" return ATAN; YY_BREAK case 140: YY_RULE_SETUP -#line 234 "QuantityParser.l" +#line 226 "Quantity.l" return ATAN2; YY_BREAK case 141: YY_RULE_SETUP -#line 235 "QuantityParser.l" +#line 227 "Quantity.l" return COS; YY_BREAK case 142: YY_RULE_SETUP -#line 236 "QuantityParser.l" +#line 228 "Quantity.l" return EXP; YY_BREAK case 143: YY_RULE_SETUP -#line 237 "QuantityParser.l" +#line 229 "Quantity.l" return ABS; YY_BREAK case 144: YY_RULE_SETUP -#line 238 "QuantityParser.l" +#line 230 "Quantity.l" return MOD; YY_BREAK case 145: YY_RULE_SETUP -#line 239 "QuantityParser.l" +#line 231 "Quantity.l" return LOG; YY_BREAK case 146: YY_RULE_SETUP -#line 240 "QuantityParser.l" +#line 232 "Quantity.l" return LOG10; YY_BREAK case 147: YY_RULE_SETUP -#line 241 "QuantityParser.l" +#line 233 "Quantity.l" return POW; YY_BREAK case 148: YY_RULE_SETUP -#line 242 "QuantityParser.l" +#line 234 "Quantity.l" return SIN; YY_BREAK case 149: YY_RULE_SETUP -#line 243 "QuantityParser.l" +#line 235 "Quantity.l" return SINH; YY_BREAK case 150: YY_RULE_SETUP -#line 244 "QuantityParser.l" +#line 236 "Quantity.l" return TAN; YY_BREAK case 151: YY_RULE_SETUP -#line 245 "QuantityParser.l" +#line 237 "Quantity.l" return TANH; YY_BREAK case 152: YY_RULE_SETUP -#line 246 "QuantityParser.l" +#line 238 "Quantity.l" return SQRT; YY_BREAK case 153: YY_RULE_SETUP -#line 248 "QuantityParser.l" +#line 240 "Quantity.l" return *yytext; YY_BREAK case 154: YY_RULE_SETUP -#line 249 "QuantityParser.l" +#line 241 "Quantity.l" ECHO; YY_BREAK -#line 1712 "QuantityLexer.c" +#line 1706 "Quantity.lex.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(C_COMMENT): yyterminate(); @@ -1855,7 +1848,7 @@ case YY_STATE_EOF(C_COMMENT): */ static int yy_get_next_buffer (void) { - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); int number_to_move, i; int ret_val; @@ -2026,7 +2019,7 @@ static int yy_get_next_buffer (void) static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; - char *yy_cp = (yy_c_buf_p); + char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) @@ -2149,7 +2142,7 @@ static int yy_get_next_buffer (void) void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { - /* TODO: We should be able to replace this entire function body + /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); @@ -2179,7 +2172,7 @@ static int yy_get_next_buffer (void) static void yy_load_buffer_state (void) { - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); @@ -2268,7 +2261,7 @@ static void yy_load_buffer_state (void) */ void yy_flush_buffer (YY_BUFFER_STATE b ) { - if ( ! b ) + if ( ! b ) return; b->yy_n_chars = 0; @@ -2297,7 +2290,7 @@ static void yy_load_buffer_state (void) */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { - if (new_buffer == NULL) + if (new_buffer == NULL) return; yyensure_buffer_stack(); @@ -2327,7 +2320,7 @@ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) */ void yypop_buffer_state (void) { - if (!YY_CURRENT_BUFFER) + if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); @@ -2680,5 +2673,4 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 249 "QuantityParser.l" -// clang-format on +#line 241 "Quantity.l" diff --git a/src/Base/QuantityParser.c b/src/Base/Quantity.tab.c similarity index 54% rename from src/Base/QuantityParser.c rename to src/Base/Quantity.tab.c index e38a289ab8..37374eae03 100644 --- a/src/Base/QuantityParser.c +++ b/src/Base/Quantity.tab.c @@ -1,9 +1,10 @@ // clang-format off -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -34,6 +35,10 @@ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. @@ -41,11 +46,11 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ -/* Identify Bison output. */ -#define YYBISON 1 +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 -/* Bison version. */ -#define YYBISON_VERSION "3.0.4" +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -62,37 +67,35 @@ -/* Copy the first part of user declarations. */ -#line 6 "QuantityParser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 24 "Quantity.y" - #define YYSTYPE Quantity - #define yyparse Quantity_yyparse - #define yyerror Quantity_yyerror + #define YYSTYPE Quantity + #define yyparse Quantity_yyparse + #define yyerror Quantity_yyerror +#line 77 "Quantity.tab.c" - - - - - - -#line 79 "QuantityParser.c" /* yacc.c:339 */ - -# ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) # else -# define YY_NULLPTR 0 +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) # endif # endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif /* Debug traces. */ @@ -103,33 +106,38 @@ extern int yydebug; #endif -/* Token type. */ +/* Token kinds. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { - UNIT = 258, - ONE = 259, - NUM = 260, - MINUSSIGN = 261, - ACOS = 262, - ASIN = 263, - ATAN = 264, - ATAN2 = 265, - COS = 266, - EXP = 267, - ABS = 268, - MOD = 269, - LOG = 270, - LOG10 = 271, - POW = 272, - SIN = 273, - SINH = 274, - TAN = 275, - TANH = 276, - SQRT = 277, - NEG = 278 + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + UNIT = 258, /* UNIT */ + ONE = 259, /* ONE */ + NUM = 260, /* NUM */ + MINUSSIGN = 261, /* MINUSSIGN */ + ACOS = 262, /* ACOS */ + ASIN = 263, /* ASIN */ + ATAN = 264, /* ATAN */ + ATAN2 = 265, /* ATAN2 */ + COS = 266, /* COS */ + EXP = 267, /* EXP */ + ABS = 268, /* ABS */ + MOD = 269, /* MOD */ + LOG = 270, /* LOG */ + LOG10 = 271, /* LOG10 */ + POW = 272, /* POW */ + SIN = 273, /* SIN */ + SINH = 274, /* SINH */ + TAN = 275, /* TAN */ + TANH = 276, /* TANH */ + SQRT = 277, /* SQRT */ + NEG = 278 /* NEG */ }; + typedef enum yytokentype yytoken_kind_t; #endif /* Value type. */ @@ -142,40 +150,141 @@ typedef int YYSTYPE; extern YYSTYPE yylval; + int yyparse (void); -/* Copy the second part of user declarations. */ +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_UNIT = 3, /* UNIT */ + YYSYMBOL_ONE = 4, /* ONE */ + YYSYMBOL_NUM = 5, /* NUM */ + YYSYMBOL_MINUSSIGN = 6, /* MINUSSIGN */ + YYSYMBOL_ACOS = 7, /* ACOS */ + YYSYMBOL_ASIN = 8, /* ASIN */ + YYSYMBOL_ATAN = 9, /* ATAN */ + YYSYMBOL_ATAN2 = 10, /* ATAN2 */ + YYSYMBOL_COS = 11, /* COS */ + YYSYMBOL_EXP = 12, /* EXP */ + YYSYMBOL_ABS = 13, /* ABS */ + YYSYMBOL_MOD = 14, /* MOD */ + YYSYMBOL_LOG = 15, /* LOG */ + YYSYMBOL_LOG10 = 16, /* LOG10 */ + YYSYMBOL_POW = 17, /* POW */ + YYSYMBOL_SIN = 18, /* SIN */ + YYSYMBOL_SINH = 19, /* SINH */ + YYSYMBOL_TAN = 20, /* TAN */ + YYSYMBOL_TANH = 21, /* TANH */ + YYSYMBOL_SQRT = 22, /* SQRT */ + YYSYMBOL_23_ = 23, /* '+' */ + YYSYMBOL_24_ = 24, /* '*' */ + YYSYMBOL_25_ = 25, /* '/' */ + YYSYMBOL_NEG = 26, /* NEG */ + YYSYMBOL_27_ = 27, /* '^' */ + YYSYMBOL_28_ = 28, /* '(' */ + YYSYMBOL_29_ = 29, /* ')' */ + YYSYMBOL_YYACCEPT = 30, /* $accept */ + YYSYMBOL_input = 31, /* input */ + YYSYMBOL_num = 32, /* num */ + YYSYMBOL_unit = 33, /* unit */ + YYSYMBOL_quantity = 34 /* quantity */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + -#line 151 "QuantityParser.c" /* yacc.c:358 */ #ifdef short # undef short #endif -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif #endif -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; #else typedef signed char yytype_int8; #endif -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; #else -typedef unsigned short int yytype_uint16; +typedef short yytype_int16; #endif -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; #else -typedef short int yytype_int16; +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif #endif #ifndef YYSIZE_T @@ -183,15 +292,28 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int8 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS @@ -205,47 +327,43 @@ typedef short int yytype_int16; # endif #endif -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) # else -# define YY_ATTRIBUTE(Spec) /* empty */ +# define YY_ATTRIBUTE_PURE # endif #endif -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - #ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) # else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# define YY_ATTRIBUTE_UNUSED # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value @@ -258,8 +376,22 @@ typedef short int yytype_int16; # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif -#if ! defined yyoverflow || YYERROR_VERBOSE + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -324,8 +456,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - +#endif /* !defined yyoverflow */ #if (! defined yyoverflow \ && (! defined __cplusplus \ @@ -334,17 +465,17 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; + yy_state_t yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 @@ -357,11 +488,11 @@ union yyalloc # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ - YYSIZE_T yynewbytes; \ + YYPTRDIFF_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ } \ while (0) @@ -373,12 +504,12 @@ union yyalloc # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ - YYSIZE_T yyi; \ + YYPTRDIFF_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ @@ -401,17 +532,20 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 96 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ -#define YYUNDEFTOK 2 +/* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 278 -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ -static const yytype_uint8 yytranslate[] = + as returned by yylex. */ +static const yytype_int8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -444,52 +578,54 @@ static const yytype_uint8 yytranslate[] = }; #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint8 yyrline[] = +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int8 yyrline[] = { - 0, 34, 34, 35, 36, 37, 38, 39, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 65, 66, 67, 68, 69, 70, 72, 73 + 0, 43, 43, 44, 45, 46, 47, 48, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 74, 75, 76, 77, 78, 79, 81, 82 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || 0 +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "UNIT", "ONE", "NUM", "MINUSSIGN", - "ACOS", "ASIN", "ATAN", "ATAN2", "COS", "EXP", "ABS", "MOD", "LOG", - "LOG10", "POW", "SIN", "SINH", "TAN", "TANH", "SQRT", "'+'", "'*'", - "'/'", "NEG", "'^'", "'('", "')'", "$accept", "input", "num", "unit", - "quantity", YY_NULLPTR + "\"end of file\"", "error", "\"invalid token\"", "UNIT", "ONE", "NUM", + "MINUSSIGN", "ACOS", "ASIN", "ATAN", "ATAN2", "COS", "EXP", "ABS", "MOD", + "LOG", "LOG10", "POW", "SIN", "SINH", "TAN", "TANH", "SQRT", "'+'", + "'*'", "'/'", "NEG", "'^'", "'('", "')'", "$accept", "input", "num", + "unit", "quantity", YY_NULLPTR }; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} #endif -# ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 43, 42, 47, 278, 94, 40, 41 -}; -# endif +#define YYPACT_NINF (-26) -#define YYPACT_NINF -26 +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-26))) +#define YYTABLE_NINF (-1) -#define YYTABLE_NINF -1 - -#define yytable_value_is_error(Yytable_value) \ +#define yytable_value_is_error(Yyn) \ 0 - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ static const yytype_int16 yypact[] = { 72, -26, -26, -26, 117, -25, -23, -10, -7, -5, @@ -504,10 +640,10 @@ static const yytype_int16 yypact[] = -26, -26, -26, -26, -26, -26 }; - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int8 yydefact[] = { 2, 30, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -521,22 +657,22 @@ static const yytype_uint8 yydefact[] = 23, 24, 25, 26, 27, 28 }; - /* YYPGOTO[NTERM-NUM]. */ +/* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -26, -26, 0, 20, -14 }; - /* YYDEFGOTO[NTERM-NUM]. */ +/* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 19, 40, 41, 22 + 0, 19, 40, 41, 22 }; - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_uint8 yytable[] = +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = { 20, 1, 43, 27, 26, 28, 51, 52, 55, 53, 45, 72, 51, 52, 48, 53, 46, 57, 29, 48, @@ -592,9 +728,9 @@ static const yytype_int8 yycheck[] = 23, 24, 25, -1, 27, -1, 29 }; - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int8 yystos[] = { 0, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 28, 31, @@ -608,8 +744,8 @@ static const yytype_uint8 yystos[] = 29, 29, 29, 29, 29, 29 }; - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr1[] = { 0, 30, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, @@ -617,8 +753,8 @@ static const yytype_uint8 yyr1[] = 33, 33, 33, 33, 33, 33, 34, 34 }; - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = { 0, 2, 0, 1, 1, 1, 2, 3, 1, 1, 3, 3, 3, 3, 2, 3, 3, 4, 4, 4, @@ -627,39 +763,39 @@ static const yytype_uint8 yyr2[] = }; +enum { YYENOMEM = -2 }; + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF /* Enable debugging if requested. */ @@ -676,55 +812,52 @@ do { \ YYFPRINTF Args; \ } while (0) -/* This macro is provided for backward compatibility. */ -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value); \ + Kind, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YY_USE (yyoutput); if (!yyvaluep) return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) { - YYFPRINTF (yyoutput, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); + yy_symbol_value_print (yyo, yykind, yyvaluep); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -733,7 +866,7 @@ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) `------------------------------------------------------------------*/ static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) @@ -756,21 +889,21 @@ do { \ `------------------------------------------------*/ static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule) { - unsigned long int yylno = yyrline[yyrule]; + int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)]); YYFPRINTF (stderr, "\n"); } } @@ -785,8 +918,8 @@ do { \ multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ @@ -809,249 +942,30 @@ int yydebug; #endif -#if YYERROR_VERBOSE -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -yystrlen (const char *yystr) -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep) { - YYUSE (yyvaluep); + YY_USE (yyvaluep); if (!yymsg) yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yytype); + YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } - - -/* The lookahead symbol. */ +/* Lookahead token kind. */ int yychar; /* The semantic value of the lookahead symbol. */ @@ -1060,6 +974,8 @@ YYSTYPE yylval; int yynerrs; + + /*----------. | yyparse. | `----------*/ @@ -1067,43 +983,36 @@ int yynerrs; int yyparse (void) { - int yystate; + yy_state_fast_t yystate = 0; /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; + int yyerrstatus = 0; - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow + /* Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; - /* The semantic value stack. */ + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; int yyn; + /* The return value of yyparse. */ int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif + #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) @@ -1111,71 +1020,75 @@ yyparse (void) Keep to zero when no symbol should be popped. */ int yylen = 0; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - YYDPRINTF ((stderr, "Starting parse\n")); - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + YYNOMEM; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYPTRDIFF_T yysize = yyssp - yyss + 1; -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ + yy_state_t *yyss1 = yyss; YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), &yystacksize); - yyss = yyss1; yyvs = yyvs1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { - yytype_int16 *yyss1 = yyss; + yy_state_t *yyss1 = yyss; union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) - goto yyexhaustedlab; + YYNOMEM; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE @@ -1183,30 +1096,31 @@ yyparse (void) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -1217,18 +1131,29 @@ yybackup: /* Not known => get a lookahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ if (yychar == YYEMPTY) { - YYDPRINTF ((stderr, "Reading a token: ")); + YYDPRINTF ((stderr, "Reading a token\n")); yychar = yylex (); } if (yychar <= YYEOF) { - yychar = yytoken = YYEOF; + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } else { yytoken = YYTRANSLATE (yychar); @@ -1256,15 +1181,13 @@ yybackup: /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END + /* Discard the shifted token. */ + yychar = YYEMPTY; goto yynewstate; @@ -1279,7 +1202,7 @@ yydefault: /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -1299,224 +1222,225 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 34 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = Quantity(std::numeric_limits::min()); /* empty input */ } -#line 1305 "QuantityParser.c" /* yacc.c:1646 */ + case 2: /* input: %empty */ +#line 43 "Quantity.y" + { QuantResult = Quantity(std::numeric_limits::min()); /* empty input */ } +#line 1228 "Quantity.tab.c" break; - case 3: -#line 35 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = (yyvsp[0]) ; } -#line 1311 "QuantityParser.c" /* yacc.c:1646 */ + case 3: /* input: num */ +#line 44 "Quantity.y" + { QuantResult = yyvsp[0]; } +#line 1234 "Quantity.tab.c" break; - case 4: -#line 36 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = (yyvsp[0]) ; } -#line 1317 "QuantityParser.c" /* yacc.c:1646 */ + case 4: /* input: unit */ +#line 45 "Quantity.y" + { QuantResult = yyvsp[0]; } +#line 1240 "Quantity.tab.c" break; - case 5: -#line 37 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = (yyvsp[0]) ; } -#line 1323 "QuantityParser.c" /* yacc.c:1646 */ + case 5: /* input: quantity */ +#line 46 "Quantity.y" + { QuantResult = yyvsp[0]; } +#line 1246 "Quantity.tab.c" break; - case 6: -#line 38 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = (yyvsp[-1]) + (yyvsp[0]); } -#line 1329 "QuantityParser.c" /* yacc.c:1646 */ + case 6: /* input: quantity quantity */ +#line 47 "Quantity.y" + { QuantResult = yyvsp[-1] + yyvsp[0]; } +#line 1252 "Quantity.tab.c" break; - case 7: -#line 39 "QuantityParser.y" /* yacc.c:1646 */ - { QuantResult = (yyvsp[-2]) + (yyvsp[-1]) + (yyvsp[0]); } -#line 1335 "QuantityParser.c" /* yacc.c:1646 */ + case 7: /* input: quantity quantity quantity */ +#line 48 "Quantity.y" + { QuantResult = yyvsp[-2] + yyvsp[-1] + yyvsp[0]; } +#line 1258 "Quantity.tab.c" break; - case 8: -#line 41 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[0]); } -#line 1341 "QuantityParser.c" /* yacc.c:1646 */ + case 8: /* num: NUM */ +#line 50 "Quantity.y" + { yyval = yyvsp[0]; } +#line 1264 "Quantity.tab.c" break; - case 9: -#line 42 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[0]); } -#line 1347 "QuantityParser.c" /* yacc.c:1646 */ + case 9: /* num: ONE */ +#line 51 "Quantity.y" + { yyval = yyvsp[0]; } +#line 1270 "Quantity.tab.c" break; - case 10: -#line 43 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity((yyvsp[-2]).getValue() + (yyvsp[0]).getValue()); } -#line 1353 "QuantityParser.c" /* yacc.c:1646 */ + case 10: /* num: num '+' num */ +#line 52 "Quantity.y" + { yyval = Quantity(yyvsp[-2].getValue() + yyvsp[0].getValue()); } +#line 1276 "Quantity.tab.c" break; - case 11: -#line 44 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity((yyvsp[-2]).getValue() - (yyvsp[0]).getValue()); } -#line 1359 "QuantityParser.c" /* yacc.c:1646 */ + case 11: /* num: num MINUSSIGN num */ +#line 53 "Quantity.y" + { yyval = Quantity(yyvsp[-2].getValue() - yyvsp[0].getValue()); } +#line 1282 "Quantity.tab.c" break; - case 12: -#line 45 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity((yyvsp[-2]).getValue() * (yyvsp[0]).getValue()); } -#line 1365 "QuantityParser.c" /* yacc.c:1646 */ + case 12: /* num: num '*' num */ +#line 54 "Quantity.y" + { yyval = Quantity(yyvsp[-2].getValue() * yyvsp[0].getValue()); } +#line 1288 "Quantity.tab.c" break; - case 13: -#line 46 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity((yyvsp[-2]).getValue() / (yyvsp[0]).getValue()); } -#line 1371 "QuantityParser.c" /* yacc.c:1646 */ + case 13: /* num: num '/' num */ +#line 55 "Quantity.y" + { yyval = Quantity(yyvsp[-2].getValue() / yyvsp[0].getValue()); } +#line 1294 "Quantity.tab.c" break; - case 14: -#line 47 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(-(yyvsp[0]).getValue()); } -#line 1377 "QuantityParser.c" /* yacc.c:1646 */ + case 14: /* num: MINUSSIGN num */ +#line 56 "Quantity.y" + { yyval = Quantity(-yyvsp[0].getValue()); } +#line 1300 "Quantity.tab.c" break; - case 15: -#line 48 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(pow ((yyvsp[-2]).getValue(), (yyvsp[0]).getValue()));} -#line 1383 "QuantityParser.c" /* yacc.c:1646 */ + case 15: /* num: num '^' num */ +#line 57 "Quantity.y" + { yyval = Quantity(pow(yyvsp[-2].getValue(), yyvsp[0].getValue())); } +#line 1306 "Quantity.tab.c" break; - case 16: -#line 49 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[-1]); } -#line 1389 "QuantityParser.c" /* yacc.c:1646 */ + case 16: /* num: '(' num ')' */ +#line 58 "Quantity.y" + { yyval = yyvsp[-1]; } +#line 1312 "Quantity.tab.c" break; - case 17: -#line 50 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(acos((yyvsp[-1]).getValue())); } -#line 1395 "QuantityParser.c" /* yacc.c:1646 */ + case 17: /* num: ACOS '(' num ')' */ +#line 59 "Quantity.y" + { yyval = Quantity(acos(yyvsp[-1].getValue())); } +#line 1318 "Quantity.tab.c" break; - case 18: -#line 51 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(asin((yyvsp[-1]).getValue())); } -#line 1401 "QuantityParser.c" /* yacc.c:1646 */ + case 18: /* num: ASIN '(' num ')' */ +#line 60 "Quantity.y" + { yyval = Quantity(asin(yyvsp[-1].getValue())); } +#line 1324 "Quantity.tab.c" break; - case 19: -#line 52 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(atan((yyvsp[-1]).getValue())); } -#line 1407 "QuantityParser.c" /* yacc.c:1646 */ + case 19: /* num: ATAN '(' num ')' */ +#line 61 "Quantity.y" + { yyval = Quantity(atan(yyvsp[-1].getValue())); } +#line 1330 "Quantity.tab.c" break; - case 20: -#line 53 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(fabs((yyvsp[-1]).getValue())); } -#line 1413 "QuantityParser.c" /* yacc.c:1646 */ + case 20: /* num: ABS '(' num ')' */ +#line 62 "Quantity.y" + { yyval = Quantity(fabs(yyvsp[-1].getValue())); } +#line 1336 "Quantity.tab.c" break; - case 21: -#line 54 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(exp((yyvsp[-1]).getValue())); } -#line 1419 "QuantityParser.c" /* yacc.c:1646 */ + case 21: /* num: EXP '(' num ')' */ +#line 63 "Quantity.y" + { yyval = Quantity(exp(yyvsp[-1].getValue())); } +#line 1342 "Quantity.tab.c" break; - case 22: -#line 55 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(log((yyvsp[-1]).getValue())); } -#line 1425 "QuantityParser.c" /* yacc.c:1646 */ + case 22: /* num: LOG '(' num ')' */ +#line 64 "Quantity.y" + { yyval = Quantity(log(yyvsp[-1].getValue())); } +#line 1348 "Quantity.tab.c" break; - case 23: -#line 56 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(log10((yyvsp[-1]).getValue())); } -#line 1431 "QuantityParser.c" /* yacc.c:1646 */ + case 23: /* num: LOG10 '(' num ')' */ +#line 65 "Quantity.y" + { yyval = Quantity(log10(yyvsp[-1].getValue())); } +#line 1354 "Quantity.tab.c" break; - case 24: -#line 57 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(sin((yyvsp[-1]).getValue())); } -#line 1437 "QuantityParser.c" /* yacc.c:1646 */ + case 24: /* num: SIN '(' num ')' */ +#line 66 "Quantity.y" + { yyval = Quantity(sin(yyvsp[-1].getValue())); } +#line 1360 "Quantity.tab.c" break; - case 25: -#line 58 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(sinh((yyvsp[-1]).getValue())); } -#line 1443 "QuantityParser.c" /* yacc.c:1646 */ + case 25: /* num: SINH '(' num ')' */ +#line 67 "Quantity.y" + { yyval = Quantity(sinh(yyvsp[-1].getValue())); } +#line 1366 "Quantity.tab.c" break; - case 26: -#line 59 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(tan((yyvsp[-1]).getValue())); } -#line 1449 "QuantityParser.c" /* yacc.c:1646 */ + case 26: /* num: TAN '(' num ')' */ +#line 68 "Quantity.y" + { yyval = Quantity(tan(yyvsp[-1].getValue())); } +#line 1372 "Quantity.tab.c" break; - case 27: -#line 60 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(tanh((yyvsp[-1]).getValue())); } -#line 1455 "QuantityParser.c" /* yacc.c:1646 */ + case 27: /* num: TANH '(' num ')' */ +#line 69 "Quantity.y" + { yyval = Quantity(tanh(yyvsp[-1].getValue())); } +#line 1378 "Quantity.tab.c" break; - case 28: -#line 61 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(sqrt((yyvsp[-1]).getValue())); } -#line 1461 "QuantityParser.c" /* yacc.c:1646 */ + case 28: /* num: SQRT '(' num ')' */ +#line 70 "Quantity.y" + { yyval = Quantity(sqrt(yyvsp[-1].getValue())); } +#line 1384 "Quantity.tab.c" break; - case 29: -#line 62 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(cos((yyvsp[-1]).getValue())); } -#line 1467 "QuantityParser.c" /* yacc.c:1646 */ + case 29: /* num: COS '(' num ')' */ +#line 71 "Quantity.y" + { yyval = Quantity(cos(yyvsp[-1].getValue())); } +#line 1390 "Quantity.tab.c" break; - case 30: -#line 65 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[0]); } -#line 1473 "QuantityParser.c" /* yacc.c:1646 */ + case 30: /* unit: UNIT */ +#line 74 "Quantity.y" + { yyval = yyvsp[0]; } +#line 1396 "Quantity.tab.c" break; - case 31: -#line 66 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity(1.0)/(yyvsp[0]); } -#line 1479 "QuantityParser.c" /* yacc.c:1646 */ + case 31: /* unit: ONE '/' unit */ +#line 75 "Quantity.y" + { yyval = Quantity(1.0)/yyvsp[0]; } +#line 1402 "Quantity.tab.c" break; - case 32: -#line 67 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[-2]) * (yyvsp[0]); } -#line 1485 "QuantityParser.c" /* yacc.c:1646 */ + case 32: /* unit: unit '*' unit */ +#line 76 "Quantity.y" + { yyval = yyvsp[-2] * yyvsp[0]; } +#line 1408 "Quantity.tab.c" break; - case 33: -#line 68 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[-2]) / (yyvsp[0]); } -#line 1491 "QuantityParser.c" /* yacc.c:1646 */ + case 33: /* unit: unit '/' unit */ +#line 77 "Quantity.y" + { yyval = yyvsp[-2] / yyvsp[0]; } +#line 1414 "Quantity.tab.c" break; - case 34: -#line 69 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[-2]).pow ((yyvsp[0])); } -#line 1497 "QuantityParser.c" /* yacc.c:1646 */ + case 34: /* unit: unit '^' num */ +#line 78 "Quantity.y" + { yyval = yyvsp[-2].pow (yyvsp[0]); } +#line 1420 "Quantity.tab.c" break; - case 35: -#line 70 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[-1]); } -#line 1503 "QuantityParser.c" /* yacc.c:1646 */ + case 35: /* unit: '(' unit ')' */ +#line 79 "Quantity.y" + { yyval = yyvsp[-1]; } +#line 1426 "Quantity.tab.c" break; - case 36: -#line 72 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[-1])*(yyvsp[0]); } -#line 1509 "QuantityParser.c" /* yacc.c:1646 */ + case 36: /* quantity: num unit */ +#line 81 "Quantity.y" + { yyval = yyvsp[-1]*yyvsp[0]; } +#line 1432 "Quantity.tab.c" break; - case 37: -#line 73 "QuantityParser.y" /* yacc.c:1646 */ - { (yyval) = Quantity((yyvsp[-2]))/(yyvsp[0]); } -#line 1515 "QuantityParser.c" /* yacc.c:1646 */ + case 37: /* quantity: num '/' unit */ +#line 82 "Quantity.y" + { yyval = Quantity(yyvsp[-2])/yyvsp[0]; } +#line 1438 "Quantity.tab.c" break; -#line 1519 "QuantityParser.c" /* yacc.c:1646 */ +#line 1442 "Quantity.tab.c" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1530,25 +1454,23 @@ yyreduce: case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; - YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -1559,50 +1481,14 @@ yyreduce: yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; -#if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif } - - if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an @@ -1631,12 +1517,11 @@ yyerrlab: | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + ++yynerrs; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1653,13 +1538,14 @@ yyerrorlab: yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ + /* Pop stack until we find a state that shifts the error token. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) { yyn = yytable[yyn]; if (0 < yyn) @@ -1673,7 +1559,7 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp); + YY_ACCESSING_SYMBOL (yystate), yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -1685,7 +1571,7 @@ yyerrlab1: /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); yystate = yyn; goto yynewstate; @@ -1696,26 +1582,30 @@ yyerrlab1: `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ -#endif + goto yyreturnlab; -yyreturn: + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at @@ -1731,19 +1621,15 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif + return yyresult; } -#line 77 "QuantityParser.y" /* yacc.c:1906 */ -// clang-format on +#line 85 "Quantity.y" diff --git a/src/Base/QuantityParser.y b/src/Base/Quantity.y similarity index 100% rename from src/Base/QuantityParser.y rename to src/Base/Quantity.y diff --git a/src/Base/QuantityParser.h b/src/Base/QuantityParser.h deleted file mode 100644 index 7143ebc41e..0000000000 --- a/src/Base/QuantityParser.h +++ /dev/null @@ -1,85 +0,0 @@ -// clang-format off -/* A Bison parser, made by GNU Bison 3.0.4. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -#ifndef YY_YY_QUANTITYPARSER_H_INCLUDED -# define YY_YY_QUANTITYPARSER_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - UNIT = 258, - NUM = 259, - MINUSSIGN = 260, - ACOS = 261, - ASIN = 262, - ATAN = 263, - ATAN2 = 264, - COS = 265, - EXP = 266, - ABS = 267, - MOD = 268, - LOG = 269, - LOG10 = 270, - POW = 271, - SIN = 272, - SINH = 273, - TAN = 274, - TANH = 275, - SQRT = 276, - NEG = 277 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE yylval; - -int yyparse (void); - -#endif /* !YY_YY_QUANTITYPARSER_H_INCLUDED */ -// clang-format on From 7218e7b030fa23772973489b92f09278c87f0f51 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Mon, 7 Apr 2025 21:51:14 +0200 Subject: [PATCH 182/316] App: Expression: rename lexer and parser files Rename files according 7d233dc ("Gui: Rename generated lexer files to match core naming pattern"). Note that C space errors (space before tabs, spaces on blank lines, etc.) still need to be fixed manually after regenerating lexer file. --- src/App/Expression.cpp | 8 +- src/App/{ExpressionParser.l => Expression.l} | 17 +- ...ex.ExpressionParser.c => Expression.lex.c} | 428 ++++++++-------- ...xpressionParser.tab.c => Expression.tab.c} | 384 ++++++++------- ...xpressionParser.tab.h => Expression.tab.h} | 6 +- src/App/{ExpressionParser.y => Expression.y} | 458 +++++++++--------- src/App/ExpressionParser.h | 2 +- src/App/ExpressionParser.sh | 10 +- 8 files changed, 648 insertions(+), 665 deletions(-) rename src/App/{ExpressionParser.l => Expression.l} (99%) rename src/App/{lex.ExpressionParser.c => Expression.lex.c} (98%) rename src/App/{ExpressionParser.tab.c => Expression.tab.c} (91%) rename src/App/{ExpressionParser.tab.h => Expression.tab.h} (95%) rename src/App/{ExpressionParser.y => Expression.y} (96%) diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index 0405af5fa3..d825d2d81a 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -3544,13 +3544,13 @@ int ExpressionParserlex(); # pragma GCC diagnostic ignored "-Wfree-nonheap-object" #endif -// Parser, defined in ExpressionParser.y +// Parser, defined in Expression.y # define YYTOKENTYPE -#include "ExpressionParser.tab.c" +#include "Expression.tab.c" #ifndef DOXYGEN_SHOULD_SKIP_THIS -// Scanner, defined in ExpressionParser.l -#include "lex.ExpressionParser.c" +// Scanner, defined in Expression.l +#include "Expression.lex.c" #endif // DOXYGEN_SHOULD_SKIP_THIS class StringBufferCleaner diff --git a/src/App/ExpressionParser.l b/src/App/Expression.l similarity index 99% rename from src/App/ExpressionParser.l rename to src/App/Expression.l index 566dab95e0..f89bf02636 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/Expression.l @@ -22,14 +22,7 @@ * * ***************************************************************************/ -/* Lexer for the FreeCAD Expression language */ - -/* use this file to generate the file 'lex.ExpressionParser.c' using the program flex - * the command for this operation is: - * flex --outfile=lex.ExpressionParser.c ExpressionParser.l - * (flex for Windows is available here: - * https://sourceforge.net/projects/winflexbison/ - * (you must then change 'flex' to 'win_flex' in the command)) */ +/* Lexer for the FreeCAD Expression language */ /* This disables inclusion of unistd.h, which is not available under Visual C++ * on Win32. The C++ scanner uses STL streams instead. */ @@ -165,7 +158,7 @@ S ({S1}|{S2}) Z (\x20|\xc2\xa0|\xe1(\x9a\x80)|\xe2(\x80[\x80-\x8a\xa8-\xa9\xaf]|\x81\x9f)|\xe3(\x80\x80)) DIGIT [0-9] -EXPO [eE][-+]?[0-9]+ +EXPO [eE][-+]?[0-9]+ %% /*** Filter language Part ***/ @@ -174,7 +167,7 @@ EXPO [eE][-+]?[0-9]+ \<\<(\\(.|\n)|[^\\>\n])*\>\> COUNTCHARS; yylval.string = unquote(yytext); return STRING; -[%+()=/*^,\.\{\}\[\]:;@\?#] COUNTCHARS; return *yytext; +[%+()=/*^,\.\{\}\[\]:;@\?#] COUNTCHARS; return *yytext; "==" COUNTCHARS; return EQ; "!=" COUNTCHARS; return NEQ; @@ -332,9 +325,9 @@ EXPO [eE][-+]?[0-9]+ "rad" COUNTCHARS; yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = yytext; return UNIT; // radian "gon" COUNTCHARS; yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = yytext; return UNIT; // gon "M" COUNTCHARS; yylval.quantity.scaler = Quantity::AngMinute; yylval.quantity.unitStr = yytext; return UNIT; // angminute -"\xE2\x80\xB2" COUNTCHARS; yylval.quantity.scaler = Quantity::AngMinute; yylval.quantity.unitStr = yytext; return UNIT; // angminute U+2032 ′ ′ ′ +"\xE2\x80\xB2" COUNTCHARS; yylval.quantity.scaler = Quantity::AngMinute; yylval.quantity.unitStr = yytext; return UNIT; // angminute U+2032 ′ ′ ′ "AS" COUNTCHARS; yylval.quantity.scaler = Quantity::AngSecond; yylval.quantity.unitStr = yytext; return UNIT; // angsecond -"\xE2\x80\xB3" COUNTCHARS; yylval.quantity.scaler = Quantity::AngSecond; yylval.quantity.unitStr = yytext; return UNIT; // angsecond U+2033 ″ ″ ″ +"\xE2\x80\xB3" COUNTCHARS; yylval.quantity.scaler = Quantity::AngSecond; yylval.quantity.unitStr = yytext; return UNIT; // angsecond U+2033 ″ ″ ″ {DIGIT}*"."{DIGIT}+{EXPO}? COUNTCHARS; yylval.fvalue = num_change(yytext,'.',','); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}*","{DIGIT}+{EXPO}? COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; diff --git a/src/App/lex.ExpressionParser.c b/src/App/Expression.lex.c similarity index 98% rename from src/App/lex.ExpressionParser.c rename to src/App/Expression.lex.c index cc9777e092..c01442d52b 100644 --- a/src/App/lex.ExpressionParser.c +++ b/src/App/Expression.lex.c @@ -1,6 +1,7 @@ -#line 1 "lex.ExpressionParser.c" +// clang-format off +#line 2 "Expression.lex.c" -#line 3 "lex.ExpressionParser.c" +#line 4 "Expression.lex.c" #define YY_INT_ALIGNED short int @@ -293,7 +294,7 @@ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. + * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 @@ -310,7 +311,7 @@ typedef uint32_t flex_uint32_t; typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; +typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; @@ -421,10 +422,10 @@ extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - + #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) - + /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ @@ -8560,8 +8561,8 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "ExpressionParser.l" -#line 2 "ExpressionParser.l" +#line 1 "Expression.l" +#line 2 "Expression.l" /*************************************************************************** * Copyright (c) 2010 Jürgen Riegel * * Copyright (c) 2015 Eivind Kvedalen * @@ -8585,14 +8586,7 @@ char *yytext; * * ***************************************************************************/ -/* Lexer for the FreeCAD Expression language */ - -/* use this file to generate the file 'lex.ExpressionParser.c' using the program flex - * the command for this operation is: - * flex --outfile=lex.ExpressionParser.c ExpressionParser.l - * (flex for Windows is available here: - * https://sourceforge.net/projects/winflexbison/ - * (you must then change 'flex' to 'win_flex' in the command)) */ +/* Lexer for the FreeCAD Expression language */ /* This disables inclusion of unistd.h, which is not available under Visual C++ * on Win32. The C++ scanner uses STL streams instead. */ @@ -8608,14 +8602,14 @@ extern int column; #define COUNTCHARS do { last_column = column; column += yyleng; } while (0) -#line 8611 "lex.ExpressionParser.c" +#line 8605 "Expression.lex.c" /*** Flex Declarations and Options ***/ /* change the name of the scanner class. */ /* the manual says "somewhat more optimized" */ /* no support for include files is planned */ /* UTF-8 unicode regular expressions. */ /* http://www.unicode.org/reports/tr44/#General_Category_Values */ -#line 8618 "lex.ExpressionParser.c" +#line 8612 "Expression.lex.c" #define INITIAL 0 @@ -8675,7 +8669,7 @@ extern int yywrap ( void ); #endif #ifndef YY_NO_UNPUT - + #endif #ifndef yytext_ptr @@ -8802,7 +8796,7 @@ YY_DECL yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; - + if ( !(yy_init) ) { (yy_init) = 1; @@ -8830,10 +8824,10 @@ YY_DECL } { -#line 170 "ExpressionParser.l" +#line 163 "Expression.l" -#line 8836 "lex.ExpressionParser.c" +#line 8830 "Expression.lex.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -8888,751 +8882,751 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 172 "ExpressionParser.l" +#line 165 "Expression.l" COUNTCHARS; YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP -#line 173 "ExpressionParser.l" +#line 166 "Expression.l" column = 0; YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 175 "ExpressionParser.l" +#line 168 "Expression.l" COUNTCHARS; yylval.string = unquote(yytext); return STRING; YY_BREAK case 4: YY_RULE_SETUP -#line 177 "ExpressionParser.l" +#line 170 "Expression.l" COUNTCHARS; return *yytext; YY_BREAK case 5: YY_RULE_SETUP -#line 179 "ExpressionParser.l" +#line 172 "Expression.l" COUNTCHARS; return EQ; YY_BREAK case 6: YY_RULE_SETUP -#line 180 "ExpressionParser.l" +#line 173 "Expression.l" COUNTCHARS; return NEQ; YY_BREAK case 7: YY_RULE_SETUP -#line 181 "ExpressionParser.l" +#line 174 "Expression.l" COUNTCHARS; return GT; YY_BREAK case 8: YY_RULE_SETUP -#line 182 "ExpressionParser.l" +#line 175 "Expression.l" COUNTCHARS; return LT; YY_BREAK case 9: YY_RULE_SETUP -#line 183 "ExpressionParser.l" +#line 176 "Expression.l" COUNTCHARS; return GTE; YY_BREAK case 10: YY_RULE_SETUP -#line 184 "ExpressionParser.l" +#line 177 "Expression.l" COUNTCHARS; return LTE; YY_BREAK case 11: YY_RULE_SETUP -#line 186 "ExpressionParser.l" +#line 179 "Expression.l" COUNTCHARS; return MINUSSIGN; YY_BREAK case 12: YY_RULE_SETUP -#line 187 "ExpressionParser.l" +#line 180 "Expression.l" COUNTCHARS; return MINUSSIGN; YY_BREAK case 13: YY_RULE_SETUP -#line 189 "ExpressionParser.l" +#line 182 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::NanoMetre; yylval.quantity.unitStr = yytext; return UNIT; // nano meter YY_BREAK case 14: YY_RULE_SETUP -#line 190 "ExpressionParser.l" +#line 183 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter YY_BREAK case 15: YY_RULE_SETUP -#line 191 "ExpressionParser.l" +#line 184 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroMetre; yylval.quantity.unitStr = yytext; return UNIT; // micro meter (greek micro in UTF8) YY_BREAK case 16: YY_RULE_SETUP -#line 192 "ExpressionParser.l" +#line 185 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliMetre; yylval.quantity.unitStr = yytext; return UNIT; // milli meter (internal standard length) YY_BREAK case 17: YY_RULE_SETUP -#line 193 "ExpressionParser.l" +#line 186 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::CentiMetre; yylval.quantity.unitStr = yytext; return UNIT; // centi meter YY_BREAK case 18: YY_RULE_SETUP -#line 194 "ExpressionParser.l" +#line 187 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::DeciMetre; yylval.quantity.unitStr = yytext; return UNIT; // deci meter YY_BREAK case 19: YY_RULE_SETUP -#line 195 "ExpressionParser.l" +#line 188 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Metre; yylval.quantity.unitStr = yytext; return UNIT; // Metre YY_BREAK case 20: YY_RULE_SETUP -#line 196 "ExpressionParser.l" +#line 189 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloMetre; yylval.quantity.unitStr = yytext; return UNIT; // kilo meter YY_BREAK case 21: YY_RULE_SETUP -#line 198 "ExpressionParser.l" +#line 191 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Liter; yylval.quantity.unitStr = yytext; return UNIT; // Liter dm^3 YY_BREAK case 22: YY_RULE_SETUP -#line 199 "ExpressionParser.l" +#line 192 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliLiter; yylval.quantity.unitStr = yytext; return UNIT; // milli Liter YY_BREAK case 23: YY_RULE_SETUP -#line 201 "ExpressionParser.l" +#line 194 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Hertz; yylval.quantity.unitStr = yytext; return UNIT; // Hertz YY_BREAK case 24: YY_RULE_SETUP -#line 202 "ExpressionParser.l" +#line 195 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloHertz; yylval.quantity.unitStr = yytext; return UNIT; // kilo Hertz YY_BREAK case 25: YY_RULE_SETUP -#line 203 "ExpressionParser.l" +#line 196 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaHertz; yylval.quantity.unitStr = yytext; return UNIT; // mega Hertz YY_BREAK case 26: YY_RULE_SETUP -#line 204 "ExpressionParser.l" +#line 197 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::GigaHertz; yylval.quantity.unitStr = yytext; return UNIT; // giga Hertz YY_BREAK case 27: YY_RULE_SETUP -#line 205 "ExpressionParser.l" +#line 198 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::TeraHertz; yylval.quantity.unitStr = yytext; return UNIT; // tera Hertz YY_BREAK case 28: YY_RULE_SETUP -#line 207 "ExpressionParser.l" +#line 200 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram YY_BREAK case 29: YY_RULE_SETUP -#line 208 "ExpressionParser.l" +#line 201 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroGram; yylval.quantity.unitStr = yytext; return UNIT; // micro gram YY_BREAK case 30: YY_RULE_SETUP -#line 209 "ExpressionParser.l" +#line 202 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliGram; yylval.quantity.unitStr = yytext; return UNIT; // milli gram YY_BREAK case 31: YY_RULE_SETUP -#line 210 "ExpressionParser.l" +#line 203 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Gram; yylval.quantity.unitStr = yytext; return UNIT; // gram YY_BREAK case 32: YY_RULE_SETUP -#line 211 "ExpressionParser.l" +#line 204 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloGram; yylval.quantity.unitStr = yytext; return UNIT; // kilo gram (internal standard for mass) YY_BREAK case 33: YY_RULE_SETUP -#line 212 "ExpressionParser.l" +#line 205 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Ton; yylval.quantity.unitStr = yytext; return UNIT; // Metric Tonne YY_BREAK case 34: YY_RULE_SETUP -#line 214 "ExpressionParser.l" +#line 207 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Second; yylval.quantity.unitStr = yytext; return UNIT; // second (internal standard time) YY_BREAK case 35: YY_RULE_SETUP -#line 215 "ExpressionParser.l" +#line 208 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Minute; yylval.quantity.unitStr = yytext; return UNIT; // minute YY_BREAK case 36: YY_RULE_SETUP -#line 216 "ExpressionParser.l" +#line 209 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Hour; yylval.quantity.unitStr = yytext; return UNIT; // hour YY_BREAK case 37: YY_RULE_SETUP -#line 218 "ExpressionParser.l" +#line 211 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Ampere; yylval.quantity.unitStr = yytext; return UNIT; // Ampere (internal standard electric current) YY_BREAK case 38: YY_RULE_SETUP -#line 219 "ExpressionParser.l" +#line 212 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliAmpere; yylval.quantity.unitStr = yytext; return UNIT; // milli Ampere YY_BREAK case 39: YY_RULE_SETUP -#line 220 "ExpressionParser.l" +#line 213 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloAmpere; yylval.quantity.unitStr = yytext; return UNIT; // kilo Ampere YY_BREAK case 40: YY_RULE_SETUP -#line 221 "ExpressionParser.l" +#line 214 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaAmpere; yylval.quantity.unitStr = yytext; return UNIT; // mega Ampere YY_BREAK case 41: YY_RULE_SETUP -#line 223 "ExpressionParser.l" +#line 216 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Kelvin; yylval.quantity.unitStr = yytext; return UNIT; // Kelvin (internal standard thermodynamic temperature) YY_BREAK case 42: YY_RULE_SETUP -#line 224 "ExpressionParser.l" +#line 217 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliKelvin; yylval.quantity.unitStr = yytext; return UNIT; // milli Kelvin YY_BREAK case 43: YY_RULE_SETUP -#line 225 "ExpressionParser.l" +#line 218 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // micro Kelvin YY_BREAK case 44: YY_RULE_SETUP -#line 226 "ExpressionParser.l" +#line 219 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroKelvin; yylval.quantity.unitStr = yytext; return UNIT; // micro Kelvin YY_BREAK case 45: YY_RULE_SETUP -#line 228 "ExpressionParser.l" +#line 221 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Mole; yylval.quantity.unitStr = yytext; return UNIT; // Mole (internal standard amount of substance) YY_BREAK case 46: YY_RULE_SETUP -#line 229 "ExpressionParser.l" +#line 222 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliMole; yylval.quantity.unitStr = yytext; return UNIT; // milli Mole YY_BREAK case 47: YY_RULE_SETUP -#line 231 "ExpressionParser.l" +#line 224 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Candela; yylval.quantity.unitStr = yytext; return UNIT; // Candela (internal standard luminous intensity) YY_BREAK case 48: YY_RULE_SETUP -#line 233 "ExpressionParser.l" +#line 226 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return UNIT; // inch YY_BREAK case 49: YY_RULE_SETUP -#line 234 "ExpressionParser.l" +#line 227 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Inch; yylval.quantity.unitStr = yytext; return USUNIT; // inch YY_BREAK case 50: YY_RULE_SETUP -#line 235 "ExpressionParser.l" +#line 228 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return UNIT; // foot YY_BREAK case 51: YY_RULE_SETUP -#line 236 "ExpressionParser.l" +#line 229 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Foot; yylval.quantity.unitStr = yytext; return USUNIT; // foot YY_BREAK case 52: YY_RULE_SETUP -#line 237 "ExpressionParser.l" +#line 230 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // thou (in/1000) YY_BREAK case 53: YY_RULE_SETUP -#line 238 "ExpressionParser.l" +#line 231 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Thou; yylval.quantity.unitStr = yytext; return UNIT; // mil (the thou in US) YY_BREAK case 54: YY_RULE_SETUP -#line 239 "ExpressionParser.l" +#line 232 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Yard; yylval.quantity.unitStr = yytext; return UNIT; // yard YY_BREAK case 55: YY_RULE_SETUP -#line 240 "ExpressionParser.l" +#line 233 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Mile; yylval.quantity.unitStr = yytext; return UNIT; // mile YY_BREAK case 56: YY_RULE_SETUP -#line 242 "ExpressionParser.l" +#line 235 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilePerHour; yylval.quantity.unitStr = yytext; return UNIT; // mile per hour YY_BREAK case 57: YY_RULE_SETUP -#line 243 "ExpressionParser.l" +#line 236 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::SquareFoot; yylval.quantity.unitStr = yytext; return UNIT; // square foot YY_BREAK case 58: YY_RULE_SETUP -#line 244 "ExpressionParser.l" +#line 237 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::CubicFoot; yylval.quantity.unitStr = yytext; return UNIT; // cubic foot YY_BREAK case 59: YY_RULE_SETUP -#line 246 "ExpressionParser.l" +#line 239 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound YY_BREAK case 60: YY_RULE_SETUP -#line 247 "ExpressionParser.l" +#line 240 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Pound; yylval.quantity.unitStr = yytext; return UNIT; // pound YY_BREAK case 61: YY_RULE_SETUP -#line 248 "ExpressionParser.l" +#line 241 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Ounce; yylval.quantity.unitStr = yytext; return UNIT; // ounce YY_BREAK case 62: YY_RULE_SETUP -#line 249 "ExpressionParser.l" +#line 242 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Stone; yylval.quantity.unitStr = yytext; return UNIT; // Stone YY_BREAK case 63: YY_RULE_SETUP -#line 250 "ExpressionParser.l" +#line 243 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Hundredweights; yylval.quantity.unitStr = yytext; return UNIT; // hundredweights YY_BREAK case 64: YY_RULE_SETUP -#line 252 "ExpressionParser.l" +#line 245 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::PoundForce; yylval.quantity.unitStr = yytext; return UNIT; // pound YY_BREAK case 65: YY_RULE_SETUP -#line 254 "ExpressionParser.l" +#line 247 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Newton; yylval.quantity.unitStr = yytext; return UNIT; // Newton (kg*m/s^2)a-za-za-z YY_BREAK case 66: YY_RULE_SETUP -#line 255 "ExpressionParser.l" +#line 248 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliNewton; yylval.quantity.unitStr = yytext; return UNIT; // milli Newton YY_BREAK case 67: YY_RULE_SETUP -#line 256 "ExpressionParser.l" +#line 249 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloNewton; yylval.quantity.unitStr = yytext; return UNIT; // kilo Newton YY_BREAK case 68: YY_RULE_SETUP -#line 257 "ExpressionParser.l" +#line 250 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaNewton; yylval.quantity.unitStr = yytext; return UNIT; // mega Newton YY_BREAK case 69: YY_RULE_SETUP -#line 259 "ExpressionParser.l" +#line 252 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Pascal; yylval.quantity.unitStr = yytext; return UNIT; // Pascal (kg/m*s^2 or N/m^2) YY_BREAK case 70: YY_RULE_SETUP -#line 260 "ExpressionParser.l" +#line 253 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloPascal; yylval.quantity.unitStr = yytext; return UNIT; // kilo Pascal YY_BREAK case 71: YY_RULE_SETUP -#line 261 "ExpressionParser.l" +#line 254 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaPascal; yylval.quantity.unitStr = yytext; return UNIT; // mega Pascal YY_BREAK case 72: YY_RULE_SETUP -#line 262 "ExpressionParser.l" +#line 255 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::GigaPascal; yylval.quantity.unitStr = yytext; return UNIT; // giga Pascal YY_BREAK case 73: YY_RULE_SETUP -#line 264 "ExpressionParser.l" +#line 257 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Bar; yylval.quantity.unitStr = yytext; return UNIT; // Bar YY_BREAK case 74: YY_RULE_SETUP -#line 265 "ExpressionParser.l" +#line 258 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliBar; yylval.quantity.unitStr = yytext; return UNIT; // milli Bar YY_BREAK case 75: YY_RULE_SETUP -#line 267 "ExpressionParser.l" +#line 260 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Torr; yylval.quantity.unitStr = yytext; return UNIT; // portion of Pascal ( 101325/760 ) YY_BREAK case 76: YY_RULE_SETUP -#line 268 "ExpressionParser.l" +#line 261 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::mTorr; yylval.quantity.unitStr = yytext; return UNIT; // YY_BREAK case 77: YY_RULE_SETUP -#line 269 "ExpressionParser.l" +#line 262 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; // YY_BREAK case 78: YY_RULE_SETUP -#line 270 "ExpressionParser.l" +#line 263 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::yTorr; yylval.quantity.unitStr = yytext; return UNIT; // YY_BREAK case 79: YY_RULE_SETUP -#line 272 "ExpressionParser.l" +#line 265 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::PSI; yylval.quantity.unitStr = yytext; return UNIT; // pounds/in^2 YY_BREAK case 80: YY_RULE_SETUP -#line 273 "ExpressionParser.l" +#line 266 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KSI; yylval.quantity.unitStr = yytext; return UNIT; // 1000 x pounds/in^2 YY_BREAK case 81: YY_RULE_SETUP -#line 274 "ExpressionParser.l" +#line 267 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MPSI; yylval.quantity.unitStr = yytext; return UNIT; // 1000 ksi YY_BREAK case 82: YY_RULE_SETUP -#line 276 "ExpressionParser.l" +#line 269 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Watt; yylval.quantity.unitStr = yytext; return UNIT; // Watt (kg*m^2/s^3) YY_BREAK case 83: YY_RULE_SETUP -#line 277 "ExpressionParser.l" +#line 270 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliWatt; yylval.quantity.unitStr = yytext; return UNIT; // milli Watt YY_BREAK case 84: YY_RULE_SETUP -#line 278 "ExpressionParser.l" +#line 271 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloWatt; yylval.quantity.unitStr = yytext; return UNIT; // kilo Watt YY_BREAK case 85: YY_RULE_SETUP -#line 279 "ExpressionParser.l" +#line 272 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::VoltAmpere; yylval.quantity.unitStr = yytext; return UNIT; // VoltAmpere (kg*m^2/s^3) YY_BREAK case 86: YY_RULE_SETUP -#line 281 "ExpressionParser.l" +#line 274 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Volt; yylval.quantity.unitStr = yytext; return UNIT; // Volt (kg*m^2/A/s^3) YY_BREAK case 87: YY_RULE_SETUP -#line 282 "ExpressionParser.l" +#line 275 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloVolt; yylval.quantity.unitStr = yytext; return UNIT; // kilo Volt YY_BREAK case 88: YY_RULE_SETUP -#line 283 "ExpressionParser.l" +#line 276 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliVolt; yylval.quantity.unitStr = yytext; return UNIT; // milli Volt YY_BREAK case 89: YY_RULE_SETUP -#line 285 "ExpressionParser.l" +#line 278 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaSiemens; yylval.quantity.unitStr = yytext; return UNIT; // mega Siemens YY_BREAK case 90: YY_RULE_SETUP -#line 286 "ExpressionParser.l" +#line 279 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloSiemens; yylval.quantity.unitStr = yytext; return UNIT; // kilo Siemens YY_BREAK case 91: YY_RULE_SETUP -#line 287 "ExpressionParser.l" +#line 280 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Siemens; yylval.quantity.unitStr = yytext; return UNIT; // Siemens (A^2*s^3/kg/m^2) YY_BREAK case 92: YY_RULE_SETUP -#line 288 "ExpressionParser.l" +#line 281 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliSiemens; yylval.quantity.unitStr = yytext; return UNIT; // milli Siemens YY_BREAK case 93: YY_RULE_SETUP -#line 289 "ExpressionParser.l" +#line 282 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroSiemens; yylval.quantity.unitStr = yytext; return UNIT; // micro Siemens YY_BREAK case 94: YY_RULE_SETUP -#line 290 "ExpressionParser.l" +#line 283 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroSiemens; yylval.quantity.unitStr = yytext; return UNIT; // micro Siemens YY_BREAK case 95: YY_RULE_SETUP -#line 292 "ExpressionParser.l" +#line 285 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Ohm; yylval.quantity.unitStr = yytext; return UNIT; // Ohm (kg*m^2/A^2/s^3) YY_BREAK case 96: YY_RULE_SETUP -#line 293 "ExpressionParser.l" +#line 286 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloOhm; yylval.quantity.unitStr = yytext; return UNIT; // kilo Ohm YY_BREAK case 97: YY_RULE_SETUP -#line 294 "ExpressionParser.l" +#line 287 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaOhm; yylval.quantity.unitStr = yytext; return UNIT; // mega Ohm YY_BREAK case 98: YY_RULE_SETUP -#line 296 "ExpressionParser.l" +#line 289 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Coulomb; yylval.quantity.unitStr = yytext; return UNIT; // Coulomb (A*s) YY_BREAK case 99: YY_RULE_SETUP -#line 298 "ExpressionParser.l" +#line 291 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Tesla; yylval.quantity.unitStr = yytext; return UNIT; // Tesla (kg/s^2/A) YY_BREAK case 100: YY_RULE_SETUP -#line 299 "ExpressionParser.l" +#line 292 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Gauss; yylval.quantity.unitStr = yytext; return UNIT; // Gauss (1 G = 1e-4 T) YY_BREAK case 101: YY_RULE_SETUP -#line 301 "ExpressionParser.l" +#line 294 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Weber; yylval.quantity.unitStr = yytext; return UNIT; // Weber (kg*m^2/s^2/A) YY_BREAK case 102: YY_RULE_SETUP -#line 303 "ExpressionParser.l" +#line 296 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Farad; yylval.quantity.unitStr = yytext; return UNIT; // Farad (s^4*A^2/m^2/kg) YY_BREAK case 103: YY_RULE_SETUP -#line 304 "ExpressionParser.l" +#line 297 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliFarad; yylval.quantity.unitStr = yytext; return UNIT; // milli Farad YY_BREAK case 104: YY_RULE_SETUP -#line 305 "ExpressionParser.l" +#line 298 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroFarad; yylval.quantity.unitStr = yytext; return UNIT; // micro Farad YY_BREAK case 105: YY_RULE_SETUP -#line 306 "ExpressionParser.l" +#line 299 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroFarad; yylval.quantity.unitStr = yytext; return UNIT; // micro Farad YY_BREAK case 106: YY_RULE_SETUP -#line 307 "ExpressionParser.l" +#line 300 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::NanoFarad; yylval.quantity.unitStr = yytext; return UNIT; // nano Farad YY_BREAK case 107: YY_RULE_SETUP -#line 308 "ExpressionParser.l" +#line 301 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::PicoFarad; yylval.quantity.unitStr = yytext; return UNIT; // pico Farad YY_BREAK case 108: YY_RULE_SETUP -#line 310 "ExpressionParser.l" +#line 303 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Henry; yylval.quantity.unitStr = yytext; return UNIT; // Henry (kg*m^2/s^2/A^2) YY_BREAK case 109: YY_RULE_SETUP -#line 311 "ExpressionParser.l" +#line 304 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliHenry; yylval.quantity.unitStr = yytext; return UNIT; // milli Henry YY_BREAK case 110: YY_RULE_SETUP -#line 312 "ExpressionParser.l" +#line 305 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroHenry; yylval.quantity.unitStr = yytext; return UNIT; // micro Henry YY_BREAK case 111: YY_RULE_SETUP -#line 313 "ExpressionParser.l" +#line 306 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MicroHenry; yylval.quantity.unitStr = yytext; return UNIT; // micro Henry) YY_BREAK case 112: YY_RULE_SETUP -#line 314 "ExpressionParser.l" +#line 307 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::NanoHenry; yylval.quantity.unitStr = yytext; return UNIT; // nano Henry YY_BREAK case 113: YY_RULE_SETUP -#line 316 "ExpressionParser.l" +#line 309 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Joule; yylval.quantity.unitStr = yytext; return UNIT; // Joule (kg*m^2/s^2) YY_BREAK case 114: YY_RULE_SETUP -#line 317 "ExpressionParser.l" +#line 310 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MilliJoule; yylval.quantity.unitStr = yytext; return UNIT; // milli Joule YY_BREAK case 115: YY_RULE_SETUP -#line 318 "ExpressionParser.l" +#line 311 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloJoule; yylval.quantity.unitStr = yytext; return UNIT; // kilo Joule YY_BREAK case 116: YY_RULE_SETUP -#line 319 "ExpressionParser.l" +#line 312 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::NewtonMeter; yylval.quantity.unitStr = yytext; return UNIT; // N*m = Joule YY_BREAK case 117: YY_RULE_SETUP -#line 320 "ExpressionParser.l" +#line 313 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::VoltAmpereSecond; yylval.quantity.unitStr = yytext; return UNIT; // V*A*s = Joule YY_BREAK case 118: YY_RULE_SETUP -#line 321 "ExpressionParser.l" +#line 314 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; // YY_BREAK case 119: YY_RULE_SETUP -#line 322 "ExpressionParser.l" +#line 315 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::WattSecond; yylval.quantity.unitStr = yytext; return UNIT; // W*s = Joule YY_BREAK case 120: YY_RULE_SETUP -#line 323 "ExpressionParser.l" +#line 316 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloWattHour; yylval.quantity.unitStr = yytext; return UNIT; // 1 kWh = 3.6e6 J YY_BREAK case 121: YY_RULE_SETUP -#line 324 "ExpressionParser.l" +#line 317 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::ElectronVolt; yylval.quantity.unitStr = yytext; return UNIT; // 1 eV = 1.602176634e-19 J YY_BREAK case 122: YY_RULE_SETUP -#line 325 "ExpressionParser.l" +#line 318 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloElectronVolt; yylval.quantity.unitStr = yytext; return UNIT; YY_BREAK case 123: YY_RULE_SETUP -#line 326 "ExpressionParser.l" +#line 319 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::MegaElectronVolt; yylval.quantity.unitStr = yytext; return UNIT; YY_BREAK case 124: YY_RULE_SETUP -#line 327 "ExpressionParser.l" +#line 320 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Calorie; yylval.quantity.unitStr = yytext; return UNIT; // 1 cal = 4.1868 J YY_BREAK case 125: YY_RULE_SETUP -#line 328 "ExpressionParser.l" +#line 321 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::KiloCalorie; yylval.quantity.unitStr = yytext; return UNIT; YY_BREAK case 126: YY_RULE_SETUP -#line 330 "ExpressionParser.l" +#line 323 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle) YY_BREAK case 127: YY_RULE_SETUP -#line 331 "ExpressionParser.l" +#line 324 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Degree; yylval.quantity.unitStr = yytext; return UNIT; // degree (internal standard angle) YY_BREAK case 128: YY_RULE_SETUP -#line 332 "ExpressionParser.l" +#line 325 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Radian; yylval.quantity.unitStr = yytext; return UNIT; // radian YY_BREAK case 129: YY_RULE_SETUP -#line 333 "ExpressionParser.l" +#line 326 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::Gon; yylval.quantity.unitStr = yytext; return UNIT; // gon YY_BREAK case 130: YY_RULE_SETUP -#line 334 "ExpressionParser.l" +#line 327 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::AngMinute; yylval.quantity.unitStr = yytext; return UNIT; // angminute YY_BREAK case 131: YY_RULE_SETUP -#line 335 "ExpressionParser.l" -COUNTCHARS; yylval.quantity.scaler = Quantity::AngMinute; yylval.quantity.unitStr = yytext; return UNIT; // angminute U+2032 ′ ′ ′ +#line 328 "Expression.l" +COUNTCHARS; yylval.quantity.scaler = Quantity::AngMinute; yylval.quantity.unitStr = yytext; return UNIT; // angminute U+2032 ′ ′ ′ YY_BREAK case 132: YY_RULE_SETUP -#line 336 "ExpressionParser.l" +#line 329 "Expression.l" COUNTCHARS; yylval.quantity.scaler = Quantity::AngSecond; yylval.quantity.unitStr = yytext; return UNIT; // angsecond YY_BREAK case 133: YY_RULE_SETUP -#line 337 "ExpressionParser.l" -COUNTCHARS; yylval.quantity.scaler = Quantity::AngSecond; yylval.quantity.unitStr = yytext; return UNIT; // angsecond U+2033 ″ ″ ″ +#line 330 "Expression.l" +COUNTCHARS; yylval.quantity.scaler = Quantity::AngSecond; yylval.quantity.unitStr = yytext; return UNIT; // angsecond U+2033 ″ ″ ″ YY_BREAK case 134: YY_RULE_SETUP -#line 339 "ExpressionParser.l" +#line 332 "Expression.l" COUNTCHARS; yylval.fvalue = num_change(yytext,'.',','); return yylval.fvalue == 1 ? ONE : NUM; YY_BREAK case 135: YY_RULE_SETUP -#line 340 "ExpressionParser.l" +#line 333 "Expression.l" COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; YY_BREAK case 136: YY_RULE_SETUP -#line 341 "ExpressionParser.l" +#line 334 "Expression.l" COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; YY_BREAK case 137: YY_RULE_SETUP -#line 342 "ExpressionParser.l" +#line 335 "Expression.l" { COUNTCHARS; yylval.ivalue = strtoll( yytext, NULL, 10 ); - if (yylval.ivalue == LLONG_MIN) + if (yylval.ivalue == std::numeric_limits::min()) throw Base::UnderflowError("Integer underflow"); - else if (yylval.ivalue == LLONG_MAX) + else if (yylval.ivalue == std::numeric_limits::max()) throw Base::OverflowError("Integer overflow"); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; } YY_BREAK case 138: YY_RULE_SETUP -#line 351 "ExpressionParser.l" +#line 344 "Expression.l" COUNTCHARS; yylval.constant.fvalue = std::numbers::pi; yylval.constant.name = "pi"; return CONSTANT; // constant pi YY_BREAK case 139: YY_RULE_SETUP -#line 352 "ExpressionParser.l" +#line 345 "Expression.l" COUNTCHARS; yylval.constant.fvalue = std::numbers::e; yylval.constant.name = "e"; return CONSTANT; // constant e YY_BREAK case 140: YY_RULE_SETUP -#line 354 "ExpressionParser.l" +#line 347 "Expression.l" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "None"; return CONSTANT; YY_BREAK case 141: YY_RULE_SETUP -#line 355 "ExpressionParser.l" +#line 348 "Expression.l" COUNTCHARS; yylval.constant.fvalue = 1; yylval.constant.name = "True"; return CONSTANT; YY_BREAK case 142: YY_RULE_SETUP -#line 356 "ExpressionParser.l" +#line 349 "Expression.l" COUNTCHARS; yylval.constant.fvalue = 1; yylval.constant.name = "True"; return CONSTANT; YY_BREAK case 143: YY_RULE_SETUP -#line 357 "ExpressionParser.l" +#line 350 "Expression.l" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "False"; return CONSTANT; YY_BREAK case 144: YY_RULE_SETUP -#line 358 "ExpressionParser.l" +#line 351 "Expression.l" COUNTCHARS; yylval.constant.fvalue = 0; yylval.constant.name = "False"; return CONSTANT; YY_BREAK case 145: YY_RULE_SETUP -#line 360 "ExpressionParser.l" +#line 353 "Expression.l" COUNTCHARS; yylval.string = yytext; return CELLADDRESS; YY_BREAK case 146: YY_RULE_SETUP -#line 361 "ExpressionParser.l" +#line 354 "Expression.l" COUNTCHARS; yylval.string = yytext; return CELLADDRESS; YY_BREAK case 147: YY_RULE_SETUP -#line 362 "ExpressionParser.l" +#line 355 "Expression.l" COUNTCHARS; yylval.string = yytext; return CELLADDRESS; YY_BREAK case 148: YY_RULE_SETUP -#line 364 "ExpressionParser.l" +#line 357 "Expression.l" { COUNTCHARS; std::string s = yytext; @@ -9650,15 +9644,15 @@ YY_RULE_SETUP YY_BREAK case 149: YY_RULE_SETUP -#line 379 "ExpressionParser.l" +#line 372 "Expression.l" COUNTCHARS; yylval.string = yytext; return IDENTIFIER; YY_BREAK case 150: YY_RULE_SETUP -#line 380 "ExpressionParser.l" +#line 373 "Expression.l" ECHO; YY_BREAK -#line 9661 "lex.ExpressionParser.c" +#line 9655 "Expression.lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -9942,7 +9936,7 @@ static int yy_get_next_buffer (void) { yy_state_type yy_current_state; char *yy_cp; - + yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) @@ -9973,7 +9967,7 @@ static int yy_get_next_buffer (void) static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; - char *yy_cp = (yy_c_buf_p); + char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) @@ -10006,7 +10000,7 @@ static int yy_get_next_buffer (void) { int c; - + *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) @@ -10073,12 +10067,12 @@ static int yy_get_next_buffer (void) /** Immediately switch to a different input stream. * @param input_file A readable stream. - * + * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { - + if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = @@ -10091,11 +10085,11 @@ static int yy_get_next_buffer (void) /** Switch to a different input buffer. * @param new_buffer The new input buffer. - * + * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { - + /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); @@ -10126,7 +10120,7 @@ static int yy_get_next_buffer (void) static void yy_load_buffer_state (void) { - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); @@ -10135,13 +10129,13 @@ static void yy_load_buffer_state (void) /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * + * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; - + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -10164,11 +10158,11 @@ static void yy_load_buffer_state (void) /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() - * + * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { - + if ( ! b ) return; @@ -10189,7 +10183,7 @@ static void yy_load_buffer_state (void) { int oerrno = errno; - + yy_flush_buffer( b ); b->yy_input_file = file; @@ -10205,17 +10199,17 @@ static void yy_load_buffer_state (void) } b->yy_is_interactive = 0; - + errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * + * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { - if ( ! b ) + if ( ! b ) return; b->yy_n_chars = 0; @@ -10240,11 +10234,11 @@ static void yy_load_buffer_state (void) * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. - * + * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { - if (new_buffer == NULL) + if (new_buffer == NULL) return; yyensure_buffer_stack(); @@ -10270,11 +10264,11 @@ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. - * + * */ void yypop_buffer_state (void) { - if (!YY_CURRENT_BUFFER) + if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); @@ -10294,7 +10288,7 @@ void yypop_buffer_state (void) static void yyensure_buffer_stack (void) { yy_size_t num_to_alloc; - + if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this @@ -10337,13 +10331,13 @@ static void yyensure_buffer_stack (void) /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer - * + * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; - + if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) @@ -10372,14 +10366,14 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan - * + * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (const char * yystr ) { - + return yy_scan_bytes( yystr, (int) strlen(yystr) ); } @@ -10387,7 +10381,7 @@ YY_BUFFER_STATE yy_scan_string (const char * yystr ) * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * + * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) @@ -10396,7 +10390,7 @@ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) char *buf; yy_size_t n; int i; - + /* Get memory for full buffer, including space for trailing EOB's. */ n = (yy_size_t) (_yybytes_len + 2); buf = (char *) yyalloc( n ); @@ -10450,16 +10444,16 @@ static void yynoreturn yy_fatal_error (const char* msg ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. - * + * */ int yyget_lineno (void) { - + return yylineno; } /** Get the input stream. - * + * */ FILE *yyget_in (void) { @@ -10467,7 +10461,7 @@ FILE *yyget_in (void) } /** Get the output stream. - * + * */ FILE *yyget_out (void) { @@ -10475,7 +10469,7 @@ FILE *yyget_out (void) } /** Get the length of the current token. - * + * */ int yyget_leng (void) { @@ -10483,7 +10477,7 @@ int yyget_leng (void) } /** Get the current token. - * + * */ char *yyget_text (void) @@ -10493,18 +10487,18 @@ char *yyget_text (void) /** Set the current line number. * @param _line_number line number - * + * */ void yyset_lineno (int _line_number ) { - + yylineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. - * + * * @see yy_switch_to_buffer */ void yyset_in (FILE * _in_str ) @@ -10558,7 +10552,7 @@ static int yy_init_globals (void) /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { - + /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER ); @@ -10584,7 +10578,7 @@ int yylex_destroy (void) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, const char * s2, int n ) { - + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; @@ -10609,7 +10603,7 @@ void *yyalloc (yy_size_t size ) void *yyrealloc (void * ptr, yy_size_t size ) { - + /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter @@ -10627,4 +10621,4 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 380 "ExpressionParser.l" +#line 373 "Expression.l" diff --git a/src/App/ExpressionParser.tab.c b/src/App/Expression.tab.c similarity index 91% rename from src/App/ExpressionParser.tab.c rename to src/App/Expression.tab.c index 3c1dcc7510..d25df1e97b 100644 --- a/src/App/ExpressionParser.tab.c +++ b/src/App/Expression.tab.c @@ -1,3 +1,4 @@ +// clang-format off /* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C @@ -67,18 +68,16 @@ /* First part of user prologue. */ -#line 28 "ExpressionParser.y" - - -#define YYSTYPE App::ExpressionParser::semantic_type - -std::stack functions; /**< Function identifier */ - - //#define YYSTYPE yystype - #define yyparse ExpressionParser_yyparse - #define yyerror ExpressionParser_yyerror +#line 26 "Expression.y" -#line 82 "ExpressionParser.tab.c" +#define YYSTYPE App::ExpressionParser::semantic_type + +std::stack functions; /**< Function identifier */ + +#define yyparse ExpressionParser_yyparse +#define yyerror ExpressionParser_yyerror + +#line 80 "Expression.tab.c" # ifndef YY_CAST # ifdef __cplusplus @@ -101,7 +100,7 @@ std::stack functions; /**< Function # endif # endif -#include "ExpressionParser.tab.h" +#include "Expression.tab.h" /* Symbol kind. */ enum yysymbol_kind_t { @@ -555,14 +554,14 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 86, 86, 87, 90, 91, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 113, 114, 115, 116, 118, 119, 120, - 121, 122, 123, 126, 129, 130, 131, 132, 133, 134, - 135, 138, 139, 141, 142, 143, 144, 145, 146, 147, - 150, 151, 155, 156, 160, 161, 165, 170, 175, 181, - 188, 195, 202, 206, 207, 208, 209, 210, 211, 212, - 213, 217, 218, 219, 223, 224, 228, 229 + 0, 81, 81, 82, 85, 86, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 108, 109, 110, 111, 113, 114, 115, + 116, 117, 118, 121, 124, 125, 126, 127, 128, 129, + 130, 133, 134, 136, 137, 138, 139, 140, 141, 142, + 145, 146, 150, 151, 155, 156, 160, 165, 170, 176, + 183, 190, 197, 201, 202, 203, 204, 205, 206, 207, + 208, 212, 213, 214, 218, 219, 223, 224 }; #endif @@ -1008,51 +1007,51 @@ yydestruct (const char *yymsg, switch (yykind) { case YYSYMBOL_exp: /* exp */ -#line 78 "ExpressionParser.y" +#line 73 "Expression.y" { delete ((*yyvaluep).expr); } -#line 1014 "ExpressionParser.tab.c" +#line 1012 "Expression.tab.c" break; case YYSYMBOL_num: /* num */ -#line 78 "ExpressionParser.y" +#line 73 "Expression.y" { delete ((*yyvaluep).expr); } -#line 1020 "ExpressionParser.tab.c" +#line 1018 "Expression.tab.c" break; case YYSYMBOL_args: /* args */ -#line 80 "ExpressionParser.y" +#line 75 "Expression.y" { std::vector::const_iterator i = ((*yyvaluep).arguments).begin(); while (i != ((*yyvaluep).arguments).end()) { delete *i; ++i; } } -#line 1026 "ExpressionParser.tab.c" +#line 1024 "Expression.tab.c" break; case YYSYMBOL_range: /* range */ -#line 78 "ExpressionParser.y" +#line 73 "Expression.y" { delete ((*yyvaluep).expr); } -#line 1032 "ExpressionParser.tab.c" +#line 1030 "Expression.tab.c" break; case YYSYMBOL_cond: /* cond */ -#line 78 "ExpressionParser.y" +#line 73 "Expression.y" { delete ((*yyvaluep).expr); } -#line 1038 "ExpressionParser.tab.c" +#line 1036 "Expression.tab.c" break; case YYSYMBOL_unit_exp: /* unit_exp */ -#line 78 "ExpressionParser.y" +#line 73 "Expression.y" { delete ((*yyvaluep).expr); } -#line 1044 "ExpressionParser.tab.c" +#line 1042 "Expression.tab.c" break; case YYSYMBOL_indexer: /* indexer */ -#line 79 "ExpressionParser.y" +#line 74 "Expression.y" { delete ((*yyvaluep).component); } -#line 1050 "ExpressionParser.tab.c" +#line 1048 "Expression.tab.c" break; case YYSYMBOL_indexable: /* indexable */ -#line 78 "ExpressionParser.y" +#line 73 "Expression.y" { delete ((*yyvaluep).expr); } -#line 1056 "ExpressionParser.tab.c" +#line 1054 "Expression.tab.c" break; default: @@ -1320,362 +1319,362 @@ yyreduce: switch (yyn) { case 2: /* input: exp */ -#line 86 "ExpressionParser.y" +#line 81 "Expression.y" { ScanResult = (yyvsp[0].expr); valueExpression = true; } -#line 1326 "ExpressionParser.tab.c" +#line 1324 "Expression.tab.c" break; case 3: /* input: unit_exp */ -#line 87 "ExpressionParser.y" +#line 82 "Expression.y" { ScanResult = (yyvsp[0].expr); unitExpression = true; } -#line 1332 "ExpressionParser.tab.c" +#line 1330 "Expression.tab.c" break; case 4: /* unit_num: num unit_exp */ -#line 90 "ExpressionParser.y" +#line 85 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-1].expr), OperatorExpression::UNIT, (yyvsp[0].expr)); } -#line 1338 "ExpressionParser.tab.c" +#line 1336 "Expression.tab.c" break; case 5: /* unit_num: num us_building_unit num us_building_unit */ -#line 91 "ExpressionParser.y" +#line 86 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, new OperatorExpression(DocumentObject, (yyvsp[-3].expr), OperatorExpression::UNIT, (yyvsp[-2].expr)), OperatorExpression::ADD, new OperatorExpression(DocumentObject, (yyvsp[-1].expr), OperatorExpression::UNIT, (yyvsp[0].expr)));} -#line 1344 "ExpressionParser.tab.c" +#line 1342 "Expression.tab.c" break; case 6: /* exp: num */ -#line 94 "ExpressionParser.y" +#line 89 "Expression.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 1350 "ExpressionParser.tab.c" +#line 1348 "Expression.tab.c" break; case 7: /* exp: unit_num */ -#line 95 "ExpressionParser.y" +#line 90 "Expression.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 1356 "ExpressionParser.tab.c" +#line 1354 "Expression.tab.c" break; case 8: /* exp: STRING */ -#line 96 "ExpressionParser.y" +#line 91 "Expression.y" { (yyval.expr) = new StringExpression(DocumentObject, (yyvsp[0].string)); } -#line 1362 "ExpressionParser.tab.c" +#line 1360 "Expression.tab.c" break; case 9: /* exp: identifier */ -#line 97 "ExpressionParser.y" +#line 92 "Expression.y" { (yyval.expr) = new VariableExpression(DocumentObject, (yyvsp[0].path)); } -#line 1368 "ExpressionParser.tab.c" +#line 1366 "Expression.tab.c" break; case 10: /* exp: MINUSSIGN exp */ -#line 98 "ExpressionParser.y" +#line 93 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[0].expr), OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1))); } -#line 1374 "ExpressionParser.tab.c" +#line 1372 "Expression.tab.c" break; case 11: /* exp: '+' exp */ -#line 99 "ExpressionParser.y" +#line 94 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[0].expr), OperatorExpression::POS, new NumberExpression(DocumentObject, Quantity(1))); } -#line 1380 "ExpressionParser.tab.c" +#line 1378 "Expression.tab.c" break; case 12: /* exp: exp '+' exp */ -#line 100 "ExpressionParser.y" +#line 95 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::ADD, (yyvsp[0].expr)); } -#line 1386 "ExpressionParser.tab.c" +#line 1384 "Expression.tab.c" break; case 13: /* exp: exp MINUSSIGN exp */ -#line 101 "ExpressionParser.y" +#line 96 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::SUB, (yyvsp[0].expr)); } -#line 1392 "ExpressionParser.tab.c" +#line 1390 "Expression.tab.c" break; case 14: /* exp: exp '*' exp */ -#line 102 "ExpressionParser.y" +#line 97 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::MUL, (yyvsp[0].expr)); } -#line 1398 "ExpressionParser.tab.c" +#line 1396 "Expression.tab.c" break; case 15: /* exp: exp '/' exp */ -#line 103 "ExpressionParser.y" +#line 98 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::DIV, (yyvsp[0].expr)); } -#line 1404 "ExpressionParser.tab.c" +#line 1402 "Expression.tab.c" break; case 16: /* exp: exp '%' exp */ -#line 104 "ExpressionParser.y" +#line 99 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::MOD, (yyvsp[0].expr)); } -#line 1410 "ExpressionParser.tab.c" +#line 1408 "Expression.tab.c" break; case 17: /* exp: exp '/' unit_exp */ -#line 105 "ExpressionParser.y" +#line 100 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::DIV, (yyvsp[0].expr)); } -#line 1416 "ExpressionParser.tab.c" +#line 1414 "Expression.tab.c" break; case 18: /* exp: exp '^' exp */ -#line 106 "ExpressionParser.y" +#line 101 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::POW, (yyvsp[0].expr)); } -#line 1422 "ExpressionParser.tab.c" +#line 1420 "Expression.tab.c" break; case 19: /* exp: indexable */ -#line 107 "ExpressionParser.y" +#line 102 "Expression.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 1428 "ExpressionParser.tab.c" +#line 1426 "Expression.tab.c" break; case 20: /* exp: FUNC args ')' */ -#line 108 "ExpressionParser.y" +#line 103 "Expression.y" { (yyval.expr) = new FunctionExpression(DocumentObject, (yyvsp[-2].func).first, std::move((yyvsp[-2].func).second), (yyvsp[-1].arguments));} -#line 1434 "ExpressionParser.tab.c" +#line 1432 "Expression.tab.c" break; case 21: /* exp: cond '?' exp ':' exp */ -#line 109 "ExpressionParser.y" +#line 104 "Expression.y" { (yyval.expr) = new ConditionalExpression(DocumentObject, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); } -#line 1440 "ExpressionParser.tab.c" +#line 1438 "Expression.tab.c" break; case 22: /* exp: '(' exp ')' */ -#line 110 "ExpressionParser.y" +#line 105 "Expression.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 1446 "ExpressionParser.tab.c" +#line 1444 "Expression.tab.c" break; case 23: /* num: ONE */ -#line 113 "ExpressionParser.y" +#line 108 "Expression.y" { (yyval.expr) = new NumberExpression(DocumentObject, Quantity((yyvsp[0].fvalue))); } -#line 1452 "ExpressionParser.tab.c" +#line 1450 "Expression.tab.c" break; case 24: /* num: NUM */ -#line 114 "ExpressionParser.y" +#line 109 "Expression.y" { (yyval.expr) = new NumberExpression(DocumentObject, Quantity((yyvsp[0].fvalue))); } -#line 1458 "ExpressionParser.tab.c" +#line 1456 "Expression.tab.c" break; case 25: /* num: INTEGER */ -#line 115 "ExpressionParser.y" +#line 110 "Expression.y" { (yyval.expr) = new NumberExpression(DocumentObject, Quantity((double)(yyvsp[0].ivalue))); } -#line 1464 "ExpressionParser.tab.c" +#line 1462 "Expression.tab.c" break; case 26: /* num: CONSTANT */ -#line 116 "ExpressionParser.y" +#line 111 "Expression.y" { (yyval.expr) = new ConstantExpression(DocumentObject, (yyvsp[0].constant).name, Quantity((yyvsp[0].constant).fvalue)); } -#line 1470 "ExpressionParser.tab.c" +#line 1468 "Expression.tab.c" break; case 27: /* args: exp */ -#line 118 "ExpressionParser.y" +#line 113 "Expression.y" { (yyval.arguments).push_back((yyvsp[0].expr)); } -#line 1476 "ExpressionParser.tab.c" +#line 1474 "Expression.tab.c" break; case 28: /* args: range */ -#line 119 "ExpressionParser.y" +#line 114 "Expression.y" { (yyval.arguments).push_back((yyvsp[0].expr)); } -#line 1482 "ExpressionParser.tab.c" +#line 1480 "Expression.tab.c" break; case 29: /* args: args ',' exp */ -#line 120 "ExpressionParser.y" +#line 115 "Expression.y" { (yyvsp[-2].arguments).push_back((yyvsp[0].expr)); (yyval.arguments) = (yyvsp[-2].arguments); } -#line 1488 "ExpressionParser.tab.c" +#line 1486 "Expression.tab.c" break; case 30: /* args: args ';' exp */ -#line 121 "ExpressionParser.y" +#line 116 "Expression.y" { (yyvsp[-2].arguments).push_back((yyvsp[0].expr)); (yyval.arguments) = (yyvsp[-2].arguments); } -#line 1494 "ExpressionParser.tab.c" +#line 1492 "Expression.tab.c" break; case 31: /* args: args ',' range */ -#line 122 "ExpressionParser.y" +#line 117 "Expression.y" { (yyvsp[-2].arguments).push_back((yyvsp[0].expr)); (yyval.arguments) = (yyvsp[-2].arguments); } -#line 1500 "ExpressionParser.tab.c" +#line 1498 "Expression.tab.c" break; case 32: /* args: args ';' range */ -#line 123 "ExpressionParser.y" +#line 118 "Expression.y" { (yyvsp[-2].arguments).push_back((yyvsp[0].expr)); (yyval.arguments) = (yyvsp[-2].arguments); } -#line 1506 "ExpressionParser.tab.c" +#line 1504 "Expression.tab.c" break; case 33: /* range: id_or_cell ':' id_or_cell */ -#line 126 "ExpressionParser.y" +#line 121 "Expression.y" { (yyval.expr) = new RangeExpression(DocumentObject, (yyvsp[-2].string), (yyvsp[0].string)); } -#line 1512 "ExpressionParser.tab.c" +#line 1510 "Expression.tab.c" break; case 34: /* cond: exp EQ exp */ -#line 129 "ExpressionParser.y" +#line 124 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::EQ, (yyvsp[0].expr)); } -#line 1518 "ExpressionParser.tab.c" +#line 1516 "Expression.tab.c" break; case 35: /* cond: exp NEQ exp */ -#line 130 "ExpressionParser.y" +#line 125 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::NEQ, (yyvsp[0].expr)); } -#line 1524 "ExpressionParser.tab.c" +#line 1522 "Expression.tab.c" break; case 36: /* cond: exp LT exp */ -#line 131 "ExpressionParser.y" +#line 126 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::LT, (yyvsp[0].expr)); } -#line 1530 "ExpressionParser.tab.c" +#line 1528 "Expression.tab.c" break; case 37: /* cond: exp GT exp */ -#line 132 "ExpressionParser.y" +#line 127 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::GT, (yyvsp[0].expr)); } -#line 1536 "ExpressionParser.tab.c" +#line 1534 "Expression.tab.c" break; case 38: /* cond: exp GTE exp */ -#line 133 "ExpressionParser.y" +#line 128 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::GTE, (yyvsp[0].expr)); } -#line 1542 "ExpressionParser.tab.c" +#line 1540 "Expression.tab.c" break; case 39: /* cond: exp LTE exp */ -#line 134 "ExpressionParser.y" +#line 129 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::LTE, (yyvsp[0].expr)); } -#line 1548 "ExpressionParser.tab.c" +#line 1546 "Expression.tab.c" break; case 40: /* cond: '(' cond ')' */ -#line 135 "ExpressionParser.y" +#line 130 "Expression.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 1554 "ExpressionParser.tab.c" +#line 1552 "Expression.tab.c" break; case 41: /* us_building_unit: USUNIT */ -#line 138 "ExpressionParser.y" - { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[0].quantity).scaler, (yyvsp[0].quantity).unitStr ); } -#line 1560 "ExpressionParser.tab.c" +#line 133 "Expression.y" + { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[0].quantity).scaler, (yyvsp[0].quantity).unitStr ); } +#line 1558 "Expression.tab.c" break; case 42: /* other_unit: UNIT */ -#line 139 "ExpressionParser.y" - { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[0].quantity).scaler, (yyvsp[0].quantity).unitStr ); } -#line 1566 "ExpressionParser.tab.c" +#line 134 "Expression.y" + { (yyval.expr) = new UnitExpression(DocumentObject, (yyvsp[0].quantity).scaler, (yyvsp[0].quantity).unitStr ); } +#line 1564 "Expression.tab.c" break; case 43: /* unit_exp: other_unit */ -#line 141 "ExpressionParser.y" +#line 136 "Expression.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 1572 "ExpressionParser.tab.c" +#line 1570 "Expression.tab.c" break; case 44: /* unit_exp: us_building_unit */ -#line 142 "ExpressionParser.y" +#line 137 "Expression.y" { (yyval.expr) = (yyvsp[0].expr); } -#line 1578 "ExpressionParser.tab.c" +#line 1576 "Expression.tab.c" break; case 45: /* unit_exp: unit_exp '/' unit_exp */ -#line 143 "ExpressionParser.y" +#line 138 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::DIV, (yyvsp[0].expr)); } -#line 1584 "ExpressionParser.tab.c" +#line 1582 "Expression.tab.c" break; case 46: /* unit_exp: unit_exp '*' unit_exp */ -#line 144 "ExpressionParser.y" +#line 139 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::MUL, (yyvsp[0].expr)); } -#line 1590 "ExpressionParser.tab.c" +#line 1588 "Expression.tab.c" break; case 47: /* unit_exp: unit_exp '^' integer */ -#line 145 "ExpressionParser.y" +#line 140 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-2].expr), OperatorExpression::POW, new NumberExpression(DocumentObject, Quantity((double)(yyvsp[0].ivalue)))); } -#line 1596 "ExpressionParser.tab.c" +#line 1594 "Expression.tab.c" break; case 48: /* unit_exp: unit_exp '^' MINUSSIGN integer */ -#line 146 "ExpressionParser.y" +#line 141 "Expression.y" { (yyval.expr) = new OperatorExpression(DocumentObject, (yyvsp[-3].expr), OperatorExpression::POW, new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, Quantity((double)(yyvsp[0].ivalue))), OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1)))); } -#line 1602 "ExpressionParser.tab.c" +#line 1600 "Expression.tab.c" break; case 49: /* unit_exp: '(' unit_exp ')' */ -#line 147 "ExpressionParser.y" +#line 142 "Expression.y" { (yyval.expr) = (yyvsp[-1].expr); } -#line 1608 "ExpressionParser.tab.c" +#line 1606 "Expression.tab.c" break; case 50: /* integer: INTEGER */ -#line 150 "ExpressionParser.y" +#line 145 "Expression.y" { (yyval.ivalue) = (yyvsp[0].ivalue); } -#line 1614 "ExpressionParser.tab.c" +#line 1612 "Expression.tab.c" break; case 51: /* integer: ONE */ -#line 151 "ExpressionParser.y" +#line 146 "Expression.y" { (yyval.ivalue) = (yyvsp[0].fvalue); } -#line 1620 "ExpressionParser.tab.c" +#line 1618 "Expression.tab.c" break; case 52: /* id_or_cell: IDENTIFIER */ -#line 155 "ExpressionParser.y" +#line 150 "Expression.y" { (yyval.string) = std::move((yyvsp[0].string)); } -#line 1626 "ExpressionParser.tab.c" +#line 1624 "Expression.tab.c" break; case 53: /* id_or_cell: CELLADDRESS */ -#line 156 "ExpressionParser.y" +#line 151 "Expression.y" { (yyval.string) = std::move((yyvsp[0].string)); } -#line 1632 "ExpressionParser.tab.c" +#line 1630 "Expression.tab.c" break; case 54: /* identifier: id_or_cell */ -#line 160 "ExpressionParser.y" +#line 155 "Expression.y" { (yyval.path) = ObjectIdentifier(DocumentObject); (yyval.path) << ObjectIdentifier::SimpleComponent((yyvsp[0].string)); } -#line 1638 "ExpressionParser.tab.c" +#line 1636 "Expression.tab.c" break; case 55: /* identifier: iden */ -#line 161 "ExpressionParser.y" +#line 156 "Expression.y" { (yyval.path) = std::move((yyvsp[0].path)); } -#line 1644 "ExpressionParser.tab.c" +#line 1642 "Expression.tab.c" break; case 56: /* iden: '.' STRING '.' id_or_cell */ -#line 165 "ExpressionParser.y" +#line 160 "Expression.y" { /* Path to property of a sub-object of the current object*/ (yyval.path) = ObjectIdentifier(DocumentObject,true); (yyval.path).setDocumentObjectName(DocumentObject,false,ObjectIdentifier::String(std::move((yyvsp[-2].string)),true),true); (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); } -#line 1654 "ExpressionParser.tab.c" +#line 1652 "Expression.tab.c" break; case 57: /* iden: '.' id_or_cell */ -#line 170 "ExpressionParser.y" +#line 165 "Expression.y" { /* Path to property of the current document object */ (yyval.path) = ObjectIdentifier(DocumentObject,true); (yyval.path).setDocumentObjectName(DocumentObject); (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); } -#line 1664 "ExpressionParser.tab.c" +#line 1662 "Expression.tab.c" break; case 58: /* iden: object '.' STRING '.' id_or_cell */ -#line 175 "ExpressionParser.y" +#line 170 "Expression.y" { /* Path to property of a sub-object */ (yyval.path) = ObjectIdentifier(DocumentObject); (yyval.path).setDocumentObjectName(std::move((yyvsp[-4].string_or_identifier)), true, ObjectIdentifier::String(std::move((yyvsp[-2].string)),true),true); (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); (yyval.path).resolveAmbiguity(); } -#line 1675 "ExpressionParser.tab.c" +#line 1673 "Expression.tab.c" break; case 59: /* iden: object '.' id_or_cell */ -#line 181 "ExpressionParser.y" +#line 176 "Expression.y" { /* Path to property of a given document object */ (yyval.path) = ObjectIdentifier(DocumentObject); (yyvsp[-2].string_or_identifier).checkImport(DocumentObject); @@ -1683,11 +1682,11 @@ yyreduce: (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); (yyval.path).resolveAmbiguity(); } -#line 1687 "ExpressionParser.tab.c" +#line 1685 "Expression.tab.c" break; case 60: /* iden: document '#' object '.' id_or_cell */ -#line 188 "ExpressionParser.y" +#line 183 "Expression.y" { /* Path to property from an external document, within a named document object */ (yyval.path) = ObjectIdentifier(DocumentObject); (yyval.path).setDocumentName(std::move((yyvsp[-4].string_or_identifier)), true); @@ -1695,118 +1694,118 @@ yyreduce: (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); (yyval.path).resolveAmbiguity(); } -#line 1699 "ExpressionParser.tab.c" +#line 1697 "Expression.tab.c" break; case 61: /* iden: document '#' object '.' STRING '.' id_or_cell */ -#line 196 "ExpressionParser.y" +#line 191 "Expression.y" { (yyval.path) = ObjectIdentifier(DocumentObject); (yyval.path).setDocumentName(std::move((yyvsp[-6].string_or_identifier)), true); (yyval.path).setDocumentObjectName(std::move((yyvsp[-4].string_or_identifier)), true, ObjectIdentifier::String(std::move((yyvsp[-2].string)),true)); (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); (yyval.path).resolveAmbiguity(); } -#line 1710 "ExpressionParser.tab.c" +#line 1708 "Expression.tab.c" break; case 62: /* iden: iden '.' IDENTIFIER */ -#line 202 "ExpressionParser.y" +#line 197 "Expression.y" { (yyval.path)= std::move((yyvsp[-2].path)); (yyval.path).addComponent(ObjectIdentifier::SimpleComponent((yyvsp[0].string))); } -#line 1716 "ExpressionParser.tab.c" +#line 1714 "Expression.tab.c" break; case 63: /* indexer: '[' exp ']' */ -#line 206 "ExpressionParser.y" +#line 201 "Expression.y" { (yyval.component) = Expression::createComponent((yyvsp[-1].expr)); } -#line 1722 "ExpressionParser.tab.c" +#line 1720 "Expression.tab.c" break; case 64: /* indexer: '[' exp ':' ']' */ -#line 207 "ExpressionParser.y" +#line 202 "Expression.y" { (yyval.component) = Expression::createComponent((yyvsp[-2].expr),0,0,true); } -#line 1728 "ExpressionParser.tab.c" +#line 1726 "Expression.tab.c" break; case 65: /* indexer: '[' ':' exp ']' */ -#line 208 "ExpressionParser.y" +#line 203 "Expression.y" { (yyval.component) = Expression::createComponent(0,(yyvsp[-1].expr)); } -#line 1734 "ExpressionParser.tab.c" +#line 1732 "Expression.tab.c" break; case 66: /* indexer: '[' ':' ':' exp ']' */ -#line 209 "ExpressionParser.y" +#line 204 "Expression.y" { (yyval.component) = Expression::createComponent(0,0,(yyvsp[-1].expr)); } -#line 1740 "ExpressionParser.tab.c" +#line 1738 "Expression.tab.c" break; case 67: /* indexer: '[' exp ':' exp ']' */ -#line 210 "ExpressionParser.y" +#line 205 "Expression.y" { (yyval.component) = Expression::createComponent((yyvsp[-3].expr),(yyvsp[-1].expr));} -#line 1746 "ExpressionParser.tab.c" +#line 1744 "Expression.tab.c" break; case 68: /* indexer: '[' exp ':' ':' exp ']' */ -#line 211 "ExpressionParser.y" +#line 206 "Expression.y" { (yyval.component) = Expression::createComponent((yyvsp[-4].expr),0,(yyvsp[-1].expr)); } -#line 1752 "ExpressionParser.tab.c" +#line 1750 "Expression.tab.c" break; case 69: /* indexer: '[' ':' exp ':' exp ']' */ -#line 212 "ExpressionParser.y" +#line 207 "Expression.y" { (yyval.component) = Expression::createComponent(0,(yyvsp[-3].expr),(yyvsp[-1].expr)); } -#line 1758 "ExpressionParser.tab.c" +#line 1756 "Expression.tab.c" break; case 70: /* indexer: '[' exp ':' exp ':' exp ']' */ -#line 213 "ExpressionParser.y" +#line 208 "Expression.y" { (yyval.component) = Expression::createComponent((yyvsp[-5].expr),(yyvsp[-3].expr),(yyvsp[-1].expr));} -#line 1764 "ExpressionParser.tab.c" +#line 1762 "Expression.tab.c" break; case 71: /* indexable: identifier indexer */ -#line 217 "ExpressionParser.y" +#line 212 "Expression.y" { (yyval.expr) = new VariableExpression(DocumentObject,(yyvsp[-1].path)); (yyval.expr)->addComponent((yyvsp[0].component)); } -#line 1770 "ExpressionParser.tab.c" +#line 1768 "Expression.tab.c" break; case 72: /* indexable: indexable indexer */ -#line 218 "ExpressionParser.y" +#line 213 "Expression.y" { (yyvsp[-1].expr)->addComponent(std::move((yyvsp[0].component))); (yyval.expr) = (yyvsp[-1].expr); } -#line 1776 "ExpressionParser.tab.c" +#line 1774 "Expression.tab.c" break; case 73: /* indexable: indexable '.' IDENTIFIER */ -#line 219 "ExpressionParser.y" +#line 214 "Expression.y" { (yyvsp[-2].expr)->addComponent(Expression::createComponent((yyvsp[0].string))); (yyval.expr) = (yyvsp[-2].expr); } -#line 1782 "ExpressionParser.tab.c" +#line 1780 "Expression.tab.c" break; case 74: /* document: STRING */ -#line 223 "ExpressionParser.y" +#line 218 "Expression.y" { (yyval.string_or_identifier) = ObjectIdentifier::String(std::move((yyvsp[0].string)), true); } -#line 1788 "ExpressionParser.tab.c" +#line 1786 "Expression.tab.c" break; case 75: /* document: IDENTIFIER */ -#line 224 "ExpressionParser.y" +#line 219 "Expression.y" { (yyval.string_or_identifier) = ObjectIdentifier::String(std::move((yyvsp[0].string)), false, true);} -#line 1794 "ExpressionParser.tab.c" +#line 1792 "Expression.tab.c" break; case 76: /* object: STRING */ -#line 228 "ExpressionParser.y" +#line 223 "Expression.y" { (yyval.string_or_identifier) = ObjectIdentifier::String(std::move((yyvsp[0].string)), true); } -#line 1800 "ExpressionParser.tab.c" +#line 1798 "Expression.tab.c" break; case 77: /* object: id_or_cell */ -#line 229 "ExpressionParser.y" +#line 224 "Expression.y" { (yyval.string_or_identifier) = ObjectIdentifier::String(std::move((yyvsp[0].string)), false);} -#line 1806 "ExpressionParser.tab.c" +#line 1804 "Expression.tab.c" break; -#line 1810 "ExpressionParser.tab.c" +#line 1808 "Expression.tab.c" default: break; } @@ -1999,5 +1998,4 @@ yyreturnlab: return yyresult; } -#line 232 "ExpressionParser.y" - +#line 227 "Expression.y" diff --git a/src/App/ExpressionParser.tab.h b/src/App/Expression.tab.h similarity index 95% rename from src/App/ExpressionParser.tab.h rename to src/App/Expression.tab.h index effb065853..dddad9207f 100644 --- a/src/App/ExpressionParser.tab.h +++ b/src/App/Expression.tab.h @@ -35,8 +35,8 @@ especially those whose name start with YY_ or yy_. They are private implementation details that can be changed or removed. */ -#ifndef YY_YY_EXPRESSIONPARSER_TAB_H_INCLUDED -# define YY_YY_EXPRESSIONPARSER_TAB_H_INCLUDED +#ifndef YY_YY_EXPRESSION_TAB_H_INCLUDED +# define YY_YY_EXPRESSION_TAB_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -91,4 +91,4 @@ extern YYSTYPE yylval; int yyparse (void); -#endif /* !YY_YY_EXPRESSIONPARSER_TAB_H_INCLUDED */ +#endif /* !YY_YY_EXPRESSION_TAB_H_INCLUDED */ diff --git a/src/App/ExpressionParser.y b/src/App/Expression.y similarity index 96% rename from src/App/ExpressionParser.y rename to src/App/Expression.y index 976d3eaa20..e1a90ebf56 100644 --- a/src/App/ExpressionParser.y +++ b/src/App/Expression.y @@ -1,231 +1,227 @@ -/*************************************************************************** - * Copyright (c) 2010 Jürgen Riegel * - * Copyright (c) 2015 Eivind Kvedalen * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - -/* Parser for the FreeCAD Units language */ -/* Represents the many different ways we can access our data */ - - -%{ - -#define YYSTYPE App::ExpressionParser::semantic_type - -std::stack functions; /**< Function identifier */ - - //#define YYSTYPE yystype - #define yyparse ExpressionParser_yyparse - #define yyerror ExpressionParser_yyerror -%} - - %token FUNC - %token ONE - %token NUM - %token IDENTIFIER - %token UNIT USUNIT - %token INTEGER - %token CONSTANT - %token CELLADDRESS - %token EQ NEQ LT GT GTE LTE - %token STRING MINUSSIGN PROPERTY_REF - %token DOCUMENT OBJECT - %token EXPONENT - %type args - %type input unit_num us_building_unit other_unit exp unit_exp cond indexable - %type UNIT USUNIT - %type id_or_cell STRING IDENTIFIER CELLADDRESS - %type INTEGER - %type PROPERTY_REF - %type ONE - %type NUM - %type CONSTANT - %type num - %type range - %type identifier iden - %type indexer - %type FUNC - %type document - %type object - %type integer - %precedence EQ NEQ LT GT GTE LTE - %precedence ':' - %left MINUSSIGN '+' - %left '*' '/' '%' - %precedence NUM_AND_UNIT - %left '^' - %precedence NEG - %precedence POS - -%destructor { delete $$; } num range exp cond unit_exp indexable -%destructor { delete $$; } -%destructor { std::vector::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args - -%start input -%% - - -input: exp { ScanResult = $1; valueExpression = true; } - | unit_exp { ScanResult = $1; unitExpression = true; } - ; - -unit_num: num unit_exp %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); } - | num us_building_unit num us_building_unit %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2), OperatorExpression::ADD, new OperatorExpression(DocumentObject, $3, OperatorExpression::UNIT, $4));} - ; - -exp: num { $$ = $1; } - | unit_num { $$ = $1; } - | STRING { $$ = new StringExpression(DocumentObject, $1); } - | identifier { $$ = new VariableExpression(DocumentObject, $1); } - | MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1))); } - | '+' exp %prec POS { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::POS, new NumberExpression(DocumentObject, Quantity(1))); } - | exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); } - | exp MINUSSIGN exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::SUB, $3); } - | exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } - | exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } - | exp '%' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MOD, $3); } - | exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } - | exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); } - | indexable { $$ = $1; } - | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2);} - | cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); } - | '(' exp ')' { $$ = $2; } - ; - -num: ONE { $$ = new NumberExpression(DocumentObject, Quantity($1)); } - | NUM { $$ = new NumberExpression(DocumentObject, Quantity($1)); } - | INTEGER { $$ = new NumberExpression(DocumentObject, Quantity((double)$1)); } - | CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, Quantity($1.fvalue)); } - -args: exp { $$.push_back($1); } - | range { $$.push_back($1); } - | args ',' exp { $1.push_back($3); $$ = $1; } - | args ';' exp { $1.push_back($3); $$ = $1; } - | args ',' range { $1.push_back($3); $$ = $1; } - | args ';' range { $1.push_back($3); $$ = $1; } - ; - -range: id_or_cell ':' id_or_cell { $$ = new RangeExpression(DocumentObject, $1, $3); } - ; - -cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); } - | exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); } - | exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); } - | exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); } - | exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); } - | exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); } - | '(' cond ')' { $$ = $2; } - ; - -us_building_unit: USUNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); } -other_unit: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); } - -unit_exp: other_unit { $$ = $1; } - | us_building_unit { $$ = $1; } - | unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } - | unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } - | unit_exp '^' integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, Quantity((double)$3))); } - | unit_exp '^' MINUSSIGN integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, Quantity((double)$4)), OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1)))); } - | '(' unit_exp ')' { $$ = $2; } - ; - -integer: INTEGER { $$ = $1; } - | ONE { $$ = $1; } - ; - -id_or_cell - : IDENTIFIER { $$ = std::move($1); } - | CELLADDRESS { $$ = std::move($1); } - ; - -identifier - : id_or_cell { $$ = ObjectIdentifier(DocumentObject); $$ << ObjectIdentifier::SimpleComponent($1); } - | iden { $$ = std::move($1); } - ; - -iden - : '.' STRING '.' id_or_cell { /* Path to property of a sub-object of the current object*/ - $$ = ObjectIdentifier(DocumentObject,true); - $$.setDocumentObjectName(DocumentObject,false,ObjectIdentifier::String(std::move($2),true),true); - $$.addComponent(ObjectIdentifier::SimpleComponent($4)); - } - | '.' id_or_cell { /* Path to property of the current document object */ - $$ = ObjectIdentifier(DocumentObject,true); - $$.setDocumentObjectName(DocumentObject); - $$.addComponent(ObjectIdentifier::SimpleComponent($2)); - } - | object '.' STRING '.' id_or_cell { /* Path to property of a sub-object */ - $$ = ObjectIdentifier(DocumentObject); - $$.setDocumentObjectName(std::move($1), true, ObjectIdentifier::String(std::move($3),true),true); - $$.addComponent(ObjectIdentifier::SimpleComponent($5)); - $$.resolveAmbiguity(); - } - | object '.' id_or_cell { /* Path to property of a given document object */ - $$ = ObjectIdentifier(DocumentObject); - $1.checkImport(DocumentObject); - $$.addComponent(ObjectIdentifier::SimpleComponent($1)); - $$.addComponent(ObjectIdentifier::SimpleComponent($3)); - $$.resolveAmbiguity(); - } - | document '#' object '.' id_or_cell { /* Path to property from an external document, within a named document object */ - $$ = ObjectIdentifier(DocumentObject); - $$.setDocumentName(std::move($1), true); - $$.setDocumentObjectName(std::move($3), true); - $$.addComponent(ObjectIdentifier::SimpleComponent($5)); - $$.resolveAmbiguity(); - } - | document '#' object '.' STRING '.' id_or_cell - { $$ = ObjectIdentifier(DocumentObject); - $$.setDocumentName(std::move($1), true); - $$.setDocumentObjectName(std::move($3), true, ObjectIdentifier::String(std::move($5),true)); - $$.addComponent(ObjectIdentifier::SimpleComponent($7)); - $$.resolveAmbiguity(); - } - | iden '.' IDENTIFIER { $$= std::move($1); $$.addComponent(ObjectIdentifier::SimpleComponent($3)); } - ; - -indexer - : '[' exp ']' { $$ = Expression::createComponent($2); } - | '[' exp ':' ']' { $$ = Expression::createComponent($2,0,0,true); } - | '[' ':' exp ']' { $$ = Expression::createComponent(0,$3); } - | '[' ':' ':' exp ']' { $$ = Expression::createComponent(0,0,$4); } - | '[' exp ':' exp ']' { $$ = Expression::createComponent($2,$4);} - | '[' exp ':' ':' exp ']' { $$ = Expression::createComponent($2,0,$5); } - | '[' ':' exp ':' exp ']' { $$ = Expression::createComponent(0,$3,$5); } - | '[' exp ':' exp ':' exp ']' { $$ = Expression::createComponent($2,$4,$6);} - ; - -indexable - : identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); } - | indexable indexer { $1->addComponent(std::move($2)); $$ = $1; } - | indexable '.' IDENTIFIER { $1->addComponent(Expression::createComponent($3)); $$ = $1; } - ; - -document - : STRING { $$ = ObjectIdentifier::String(std::move($1), true); } - | IDENTIFIER { $$ = ObjectIdentifier::String(std::move($1), false, true);} - ; - -object - : STRING { $$ = ObjectIdentifier::String(std::move($1), true); } - | id_or_cell { $$ = ObjectIdentifier::String(std::move($1), false);} - ; - -%% +/*************************************************************************** + * Copyright (c) 2010 Jürgen Riegel * + * Copyright (c) 2015 Eivind Kvedalen * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +/* Parser for the FreeCAD Expression language */ + +%{ +#define YYSTYPE App::ExpressionParser::semantic_type + +std::stack functions; /**< Function identifier */ + +#define yyparse ExpressionParser_yyparse +#define yyerror ExpressionParser_yyerror +%} + + %token FUNC + %token ONE + %token NUM + %token IDENTIFIER + %token UNIT USUNIT + %token INTEGER + %token CONSTANT + %token CELLADDRESS + %token EQ NEQ LT GT GTE LTE + %token STRING MINUSSIGN PROPERTY_REF + %token DOCUMENT OBJECT + %token EXPONENT + %type args + %type input unit_num us_building_unit other_unit exp unit_exp cond indexable + %type UNIT USUNIT + %type id_or_cell STRING IDENTIFIER CELLADDRESS + %type INTEGER + %type PROPERTY_REF + %type ONE + %type NUM + %type CONSTANT + %type num + %type range + %type identifier iden + %type indexer + %type FUNC + %type document + %type object + %type integer + %precedence EQ NEQ LT GT GTE LTE + %precedence ':' + %left MINUSSIGN '+' + %left '*' '/' '%' + %precedence NUM_AND_UNIT + %left '^' + %precedence NEG + %precedence POS + +%destructor { delete $$; } num range exp cond unit_exp indexable +%destructor { delete $$; } +%destructor { std::vector::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args + +%start input +%% + + +input: exp { ScanResult = $1; valueExpression = true; } + | unit_exp { ScanResult = $1; unitExpression = true; } + ; + +unit_num: num unit_exp %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); } + | num us_building_unit num us_building_unit %prec NUM_AND_UNIT { $$ = new OperatorExpression(DocumentObject, new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2), OperatorExpression::ADD, new OperatorExpression(DocumentObject, $3, OperatorExpression::UNIT, $4));} + ; + +exp: num { $$ = $1; } + | unit_num { $$ = $1; } + | STRING { $$ = new StringExpression(DocumentObject, $1); } + | identifier { $$ = new VariableExpression(DocumentObject, $1); } + | MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1))); } + | '+' exp %prec POS { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::POS, new NumberExpression(DocumentObject, Quantity(1))); } + | exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); } + | exp MINUSSIGN exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::SUB, $3); } + | exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } + | exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } + | exp '%' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MOD, $3); } + | exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } + | exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); } + | indexable { $$ = $1; } + | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2);} + | cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); } + | '(' exp ')' { $$ = $2; } + ; + +num: ONE { $$ = new NumberExpression(DocumentObject, Quantity($1)); } + | NUM { $$ = new NumberExpression(DocumentObject, Quantity($1)); } + | INTEGER { $$ = new NumberExpression(DocumentObject, Quantity((double)$1)); } + | CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, Quantity($1.fvalue)); } + +args: exp { $$.push_back($1); } + | range { $$.push_back($1); } + | args ',' exp { $1.push_back($3); $$ = $1; } + | args ';' exp { $1.push_back($3); $$ = $1; } + | args ',' range { $1.push_back($3); $$ = $1; } + | args ';' range { $1.push_back($3); $$ = $1; } + ; + +range: id_or_cell ':' id_or_cell { $$ = new RangeExpression(DocumentObject, $1, $3); } + ; + +cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); } + | exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); } + | exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); } + | exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); } + | exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); } + | exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); } + | '(' cond ')' { $$ = $2; } + ; + +us_building_unit: USUNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); } +other_unit: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); } + +unit_exp: other_unit { $$ = $1; } + | us_building_unit { $$ = $1; } + | unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } + | unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); } + | unit_exp '^' integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, Quantity((double)$3))); } + | unit_exp '^' MINUSSIGN integer { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, Quantity((double)$4)), OperatorExpression::NEG, new NumberExpression(DocumentObject, Quantity(-1)))); } + | '(' unit_exp ')' { $$ = $2; } + ; + +integer: INTEGER { $$ = $1; } + | ONE { $$ = $1; } + ; + +id_or_cell + : IDENTIFIER { $$ = std::move($1); } + | CELLADDRESS { $$ = std::move($1); } + ; + +identifier + : id_or_cell { $$ = ObjectIdentifier(DocumentObject); $$ << ObjectIdentifier::SimpleComponent($1); } + | iden { $$ = std::move($1); } + ; + +iden + : '.' STRING '.' id_or_cell { /* Path to property of a sub-object of the current object*/ + $$ = ObjectIdentifier(DocumentObject,true); + $$.setDocumentObjectName(DocumentObject,false,ObjectIdentifier::String(std::move($2),true),true); + $$.addComponent(ObjectIdentifier::SimpleComponent($4)); + } + | '.' id_or_cell { /* Path to property of the current document object */ + $$ = ObjectIdentifier(DocumentObject,true); + $$.setDocumentObjectName(DocumentObject); + $$.addComponent(ObjectIdentifier::SimpleComponent($2)); + } + | object '.' STRING '.' id_or_cell { /* Path to property of a sub-object */ + $$ = ObjectIdentifier(DocumentObject); + $$.setDocumentObjectName(std::move($1), true, ObjectIdentifier::String(std::move($3),true),true); + $$.addComponent(ObjectIdentifier::SimpleComponent($5)); + $$.resolveAmbiguity(); + } + | object '.' id_or_cell { /* Path to property of a given document object */ + $$ = ObjectIdentifier(DocumentObject); + $1.checkImport(DocumentObject); + $$.addComponent(ObjectIdentifier::SimpleComponent($1)); + $$.addComponent(ObjectIdentifier::SimpleComponent($3)); + $$.resolveAmbiguity(); + } + | document '#' object '.' id_or_cell { /* Path to property from an external document, within a named document object */ + $$ = ObjectIdentifier(DocumentObject); + $$.setDocumentName(std::move($1), true); + $$.setDocumentObjectName(std::move($3), true); + $$.addComponent(ObjectIdentifier::SimpleComponent($5)); + $$.resolveAmbiguity(); + } + | document '#' object '.' STRING '.' id_or_cell + { $$ = ObjectIdentifier(DocumentObject); + $$.setDocumentName(std::move($1), true); + $$.setDocumentObjectName(std::move($3), true, ObjectIdentifier::String(std::move($5),true)); + $$.addComponent(ObjectIdentifier::SimpleComponent($7)); + $$.resolveAmbiguity(); + } + | iden '.' IDENTIFIER { $$= std::move($1); $$.addComponent(ObjectIdentifier::SimpleComponent($3)); } + ; + +indexer + : '[' exp ']' { $$ = Expression::createComponent($2); } + | '[' exp ':' ']' { $$ = Expression::createComponent($2,0,0,true); } + | '[' ':' exp ']' { $$ = Expression::createComponent(0,$3); } + | '[' ':' ':' exp ']' { $$ = Expression::createComponent(0,0,$4); } + | '[' exp ':' exp ']' { $$ = Expression::createComponent($2,$4);} + | '[' exp ':' ':' exp ']' { $$ = Expression::createComponent($2,0,$5); } + | '[' ':' exp ':' exp ']' { $$ = Expression::createComponent(0,$3,$5); } + | '[' exp ':' exp ':' exp ']' { $$ = Expression::createComponent($2,$4,$6);} + ; + +indexable + : identifier indexer { $$ = new VariableExpression(DocumentObject,$1); $$->addComponent($2); } + | indexable indexer { $1->addComponent(std::move($2)); $$ = $1; } + | indexable '.' IDENTIFIER { $1->addComponent(Expression::createComponent($3)); $$ = $1; } + ; + +document + : STRING { $$ = ObjectIdentifier::String(std::move($1), true); } + | IDENTIFIER { $$ = ObjectIdentifier::String(std::move($1), false, true);} + ; + +object + : STRING { $$ = ObjectIdentifier::String(std::move($1), true); } + | id_or_cell { $$ = ObjectIdentifier::String(std::move($1), false);} + ; + +%% diff --git a/src/App/ExpressionParser.h b/src/App/ExpressionParser.h index 3836d64a99..f9b8b7d8d5 100644 --- a/src/App/ExpressionParser.h +++ b/src/App/ExpressionParser.h @@ -649,7 +649,7 @@ public: }; #define YYSTYPE semantic_type -#include "ExpressionParser.tab.h" +#include "Expression.tab.h" #undef YYTOKENTYPE #undef YYSTYPE #undef YYSTYPE_ISDECLARED diff --git a/src/App/ExpressionParser.sh b/src/App/ExpressionParser.sh index bb12396b7a..dfa85af868 100755 --- a/src/App/ExpressionParser.sh +++ b/src/App/ExpressionParser.sh @@ -1,6 +1,8 @@ #!/usr/bin/env sh -cd "$(dirname "$0")" - -flex -v -olex.ExpressionParser.c ExpressionParser.l -bison -d -v -Wall -oExpressionParser.tab.c ExpressionParser.y +(cd "$(dirname "$0")" && \ + flex -v -oExpression.lex.c Expression.l && \ + bison -d -v -Wall -oExpression.tab.c Expression.y && \ + sed -i '1s|^|// clang-format off\n|' Expression.tab.c && \ + sed -i '1s|^|// clang-format off\n|' Expression.lex.c \ +) From 045ca4611488b6f5918d53c1c0fab6c316c6c241 Mon Sep 17 00:00:00 2001 From: xtemp09 Date: Tue, 8 Apr 2025 14:13:50 +0700 Subject: [PATCH 183/316] [TUX] Fix typo in PR #20401 --- src/Mod/Tux/NavigationIndicatorGui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Tux/NavigationIndicatorGui.py b/src/Mod/Tux/NavigationIndicatorGui.py index 5a0cc2fb34..38a9111afc 100644 --- a/src/Mod/Tux/NavigationIndicatorGui.py +++ b/src/Mod/Tux/NavigationIndicatorGui.py @@ -619,7 +619,7 @@ indicator = IndicatorButton(statusBar) indicator.setFlat(True) indicator.adjustSize() indicator.setObjectName("NavigationIndicator") -text = translate( +text = QtGui.QApplication.translate( "NavigationIndicator", "Navigation indicator", "A context menu action used to show or hide the 'Navigation indicator' toolbar widget", From 5195cb49de4df0d1ef7e725e2e6f00cb6b7894cb Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 8 Apr 2025 13:13:45 +0200 Subject: [PATCH 184/316] PartDesign : New sketch: Fix regression --- src/Mod/PartDesign/Gui/SketchWorkflow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/PartDesign/Gui/SketchWorkflow.cpp b/src/Mod/PartDesign/Gui/SketchWorkflow.cpp index 7d68c46b76..7697239afc 100644 --- a/src/Mod/PartDesign/Gui/SketchWorkflow.cpp +++ b/src/Mod/PartDesign/Gui/SketchWorkflow.cpp @@ -812,7 +812,7 @@ std::tuple SketchWorkflow::getFaceAn // a new sketch. // See https://forum.freecad.org/viewtopic.php?f=3&t=44070 - Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1", activeBody); + Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1"); Gui::SelectionFilter PlaneFilter ("SELECT App::Plane COUNT 1", activeBody); Gui::SelectionFilter PlaneFilter2("SELECT PartDesign::Plane COUNT 1", activeBody); From fc782a6c8d1cf92ee62aeede42ba717aca0ab4d0 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Tue, 8 Apr 2025 09:40:31 -0500 Subject: [PATCH 185/316] Addon Manager: Move to git submodule (#20672) --- .gitmodules | 3 + .pre-commit-config.yaml | 1 - src/Mod/AddonManager | 1 + .../AddonManager/ALLOWED_PYTHON_PACKAGES.txt | 35 - src/Mod/AddonManager/Addon.py | 863 -- src/Mod/AddonManager/AddonCatalog.py | 143 - src/Mod/AddonManager/AddonManager.py | 951 -- src/Mod/AddonManager/AddonManager.ui | 20 - src/Mod/AddonManager/AddonManagerOptions.py | 314 - src/Mod/AddonManager/AddonManagerOptions.ui | 482 - ...AddonManagerOptions_AddCustomRepository.ui | 84 - .../AddonManager/AddonManagerTest/__init__.py | 0 .../AddonManagerTest/app/__init__.py | 0 .../AddonManagerTest/app/mocks.py | 463 - .../AddonManagerTest/app/test_addon.py | 407 - .../AddonManagerTest/app/test_addoncatalog.py | 213 - .../AddonManagerTest/app/test_cache.py | 126 - .../app/test_dependency_installer.py | 195 - .../app/test_freecad_interface.py | 299 - .../AddonManagerTest/app/test_git.py | 177 - .../AddonManagerTest/app/test_installer.py | 412 - .../AddonManagerTest/app/test_macro.py | 213 - .../AddonManagerTest/app/test_macro_parser.py | 344 - .../AddonManagerTest/app/test_metadata.py | 649 -- .../AddonManagerTest/app/test_uninstaller.py | 437 - .../AddonManagerTest/app/test_utilities.py | 287 - .../AddonManagerTest/data/DoNothing.FCMacro | 30 - .../data/MacrosRecipesWikiPage.zip | Bin 30203 -> 0 bytes .../AddonManagerTest/data/TestWorkbench.zip | Bin 25149 -> 0 bytes .../AddonManagerTest/data/__init__.py | 0 .../data/addon_update_stats.json | 156 - .../AddonManagerTest/data/bundle_only.xml | 23 - .../AddonManagerTest/data/combination.xml | 34 - .../data/corrupted_metadata.zip | Bin 9300 -> 0 bytes .../data/depends_on_all_workbenches.xml | 34 - .../AddonManagerTest/data/git_submodules.txt | 23 - .../AddonManagerTest/data/good_package.xml | 25 - .../AddonManagerTest/data/icon_cache.zip | Bin 9447 -> 0 bytes .../AddonManagerTest/data/icon_cache.zip.sha1 | 1 - .../AddonManagerTest/data/macro_only.xml | 22 - .../data/macro_template.FCStd | 37 - .../AddonManagerTest/data/metadata.zip | Bin 9325 -> 0 bytes .../data/missing_macro_metadata.FCStd | 25 - .../AddonManagerTest/data/other_only.xml | 18 - .../AddonManagerTest/data/prefpack_only.xml | 24 - .../data/test_addon_with_fcmacro.zip | Bin 202 -> 0 bytes .../data/test_github_style_repo.zip | Bin 170 -> 0 bytes .../AddonManagerTest/data/test_repo.zip | Bin 23052 -> 0 bytes .../data/test_simple_repo.zip | Bin 110 -> 0 bytes .../data/test_version_detection.xml | 33 - .../AddonManagerTest/data/workbench_only.xml | 27 - .../AddonManagerTest/gui/__init__.py | 0 .../AddonManagerTest/gui/gui_mocks.py | 157 - .../gui/test_change_branch.py | 234 - .../AddonManagerTest/gui/test_gui.py | 33 - .../gui/test_installer_gui.py | 650 -- .../gui/test_python_deps_gui.py | 139 - .../gui/test_uninstaller_gui.py | 131 - .../gui/test_update_all_gui.py | 260 - .../gui/test_widget_progress_bar.py | 145 - .../gui/test_workers_startup.py | 200 - .../gui/test_workers_utility.py | 78 - .../AddonManagerTest/test_information.md | 3 - src/Mod/AddonManager/AddonStats.py | 81 - src/Mod/AddonManager/CMakeLists.txt | 189 - src/Mod/AddonManager/Init.py | 8 - src/Mod/AddonManager/InitGui.py | 13 - src/Mod/AddonManager/NetworkManager.py | 714 -- .../PythonDependencyUpdateDialog.ui | 109 - .../AddonManager/Resources/AddonManager.qrc | 127 - .../3D_Printing_Tools_workbench_icon.svg | 179 - .../Resources/icons/A2plus_workbench_icon.svg | 194 - .../Resources/icons/AddonMgrWithWarning.svg | 49 - .../icons/AirPlaneDesign_workbench_icon.svg | 300 - .../icons/ArchTextures_workbench_icon.svg | 216 - .../icons/Assembly4_workbench_icon.svg | 411 - .../icons/BCFPlugin_workbench_icon.svg | 1 - .../icons/BIMBots_workbench_icon.svg | 99 - .../Resources/icons/BIM_workbench_icon.svg | 83 - .../icons/BOLTSFC_workbench_icon.svg | 84 - .../icons/CADExchanger_workbench_icon.svg | 84 - .../Resources/icons/CfdOF_workbench_icon.svg | 106 - .../Resources/icons/Cfd_workbench_icon.svg | 84 - .../icons/CurvedShapes_workbench_icon.svg | 744 -- .../Resources/icons/Curves_workbench_icon.svg | 270 - .../icons/Defeaturing_workbench_icon.svg | 347 - .../icons/DesignSPHysics_workbench_icon.svg | 197 - .../icons/DynamicData_workbench_icon.svg | 90 - .../Resources/icons/EM_workbench_icon.svg | 602 -- .../icons/ExplodedAssembly_workbench_icon.svg | 112 - .../Resources/icons/ExtMan_workbench_icon.svg | 149 - .../Resources/icons/FCGear_workbench_icon.svg | 194 - .../icons/FEM_FrontISTR_workbench_icon.svg | 42 - .../Resources/icons/GDML_workbench_icon.svg | 159 - .../Resources/icons/GDT_workbench_icon.svg | 420 - .../icons/Geomatics_workbench_icon.svg | 1 - .../icons/ImportNURBS_workbench_icon.svg | 72 - .../icons/InventorLoader_workbench_icon.svg | 329 - .../icons/LCInterlocking_workbench_icon.svg | 86 - .../icons/Lithophane_workbench_icon.svg | 117 - .../Resources/icons/MOOC_workbench_icon.svg | 1175 --- .../Resources/icons/Maker_workbench_icon.svg | 244 - .../icons/Manipulator_workbench_icon.svg | 387 - .../Resources/icons/Marz_workbench_icon.svg | 36 - .../icons/MeshRemodel_workbench_icon.svg | 108 - .../icons/MnesarcoUtils_workbench_icon.svg | 11 - .../icons/ModernUI_workbench_icon.svg | 259 - .../icons/OSE3dPrinter_workbench_icon.svg | 3 - .../POV-Ray-Rendering_workbench_icon.svg | 80 - .../icons/Part-o-magic_workbench_icon.svg | 255 - .../Resources/icons/Plot_workbench_icon.svg | 148 - ...yramids-and-Polyhedrons_workbench_icon.svg | 102 - .../icons/Reinforcement_workbench_icon.svg | 169 - .../Resources/icons/Render_workbench_icon.svg | 116 - .../icons/Reporting_workbench_icon.svg | 102 - .../Resources/icons/Rocket_workbench_icon.svg | 111 - .../Resources/icons/Ship_workbench_icon.svg | 157 - .../Resources/icons/Silk_workbench_icon.svg | 56 - .../icons/TaackPLM_workbench_icon.svg | 40 - .../icons/ThreadProfile_workbench_icon.svg | 83 - .../icons/WebTools_workbench_icon.svg | 277 - .../icons/cadquery_module_workbench_icon.svg | 78 - .../Resources/icons/compact_view.svg | 215 - .../Resources/icons/composite_view.svg | 217 - .../Resources/icons/dodo_workbench_icon.svg | 212 - .../Resources/icons/expanded_view.svg | 224 - .../icons/fasteners_workbench_icon.svg | 215 - .../icons/flamingo_workbench_icon.svg | 145 - .../icons/kicadStepUpMod_workbench_icon.svg | 405 - .../icons/lattice2_workbench_icon.svg | 264 - .../icons/preferences-addon_manager.svg | 203 - .../Resources/icons/pyrate_workbench_icon.svg | 140 - .../icons/sheetmetal_workbench_icon.svg | 468 - .../icons/slic3r-tools_workbench_icon.svg | 330 - .../Resources/icons/sort_ascending.svg | 118 - .../Resources/icons/sort_descending.svg | 118 - .../Resources/icons/timber_workbench_icon.svg | 96 - .../icons/workfeature_workbench_icon.svg | 452 - .../icons/yaml-workspace_workbench_icon.svg | 182 - .../Resources/licenses/Apache-2.0.txt | 202 - .../Resources/licenses/BSD-2-Clause.txt | 20 - .../Resources/licenses/BSD-3-Clause.txt | 23 - .../Resources/licenses/CC0-1.0.txt | 97 - .../Resources/licenses/GPL-2.0-or-later.txt | 265 - .../Resources/licenses/GPL-3.0-or-later.txt | 674 -- .../Resources/licenses/LGPL-2.1-or-later.txt | 502 -- .../Resources/licenses/LGPL-3.0-or-later.txt | 165 - .../AddonManager/Resources/licenses/MIT.txt | 16 - .../Resources/licenses/MPL-2.0.txt | 258 - .../AddonManager/Resources/licenses/spdx.json | 7835 ----------------- .../Resources/translations/AddonManager.ts | 2473 ------ .../Resources/translations/AddonManager_af.qm | Bin 13491 -> 0 bytes .../Resources/translations/AddonManager_af.ts | 427 - .../Resources/translations/AddonManager_ar.qm | Bin 13452 -> 0 bytes .../Resources/translations/AddonManager_ar.ts | 427 - .../Resources/translations/AddonManager_be.qm | Bin 71050 -> 0 bytes .../Resources/translations/AddonManager_be.ts | 2493 ------ .../Resources/translations/AddonManager_bg.qm | Bin 14373 -> 0 bytes .../Resources/translations/AddonManager_bg.ts | 424 - .../Resources/translations/AddonManager_ca.qm | Bin 75103 -> 0 bytes .../Resources/translations/AddonManager_ca.ts | 2487 ------ .../Resources/translations/AddonManager_cs.qm | Bin 68683 -> 0 bytes .../Resources/translations/AddonManager_cs.ts | 2484 ------ .../Resources/translations/AddonManager_da.qm | Bin 68363 -> 0 bytes .../Resources/translations/AddonManager_da.ts | 2487 ------ .../Resources/translations/AddonManager_de.qm | Bin 73197 -> 0 bytes .../Resources/translations/AddonManager_de.ts | 2487 ------ .../Resources/translations/AddonManager_el.qm | Bin 74781 -> 0 bytes .../Resources/translations/AddonManager_el.ts | 2488 ------ .../translations/AddonManager_es-AR.qm | Bin 74062 -> 0 bytes .../translations/AddonManager_es-AR.ts | 2485 ------ .../translations/AddonManager_es-ES.qm | Bin 74200 -> 0 bytes .../translations/AddonManager_es-ES.ts | 2485 ------ .../Resources/translations/AddonManager_eu.qm | Bin 71603 -> 0 bytes .../Resources/translations/AddonManager_eu.ts | 2486 ------ .../Resources/translations/AddonManager_fi.qm | Bin 68277 -> 0 bytes .../Resources/translations/AddonManager_fi.ts | 2487 ------ .../translations/AddonManager_fil.qm | Bin 29789 -> 0 bytes .../translations/AddonManager_fil.ts | 1168 --- .../Resources/translations/AddonManager_fr.qm | Bin 75471 -> 0 bytes .../Resources/translations/AddonManager_fr.ts | 2483 ------ .../Resources/translations/AddonManager_gl.qm | Bin 68368 -> 0 bytes .../Resources/translations/AddonManager_gl.ts | 2516 ------ .../Resources/translations/AddonManager_hr.qm | Bin 70490 -> 0 bytes .../Resources/translations/AddonManager_hr.ts | 2486 ------ .../Resources/translations/AddonManager_hu.qm | Bin 71336 -> 0 bytes .../Resources/translations/AddonManager_hu.ts | 2487 ------ .../Resources/translations/AddonManager_id.qm | Bin 68510 -> 0 bytes .../Resources/translations/AddonManager_id.ts | 2514 ------ .../Resources/translations/AddonManager_it.qm | Bin 71925 -> 0 bytes .../Resources/translations/AddonManager_it.ts | 2487 ------ .../Resources/translations/AddonManager_ja.qm | Bin 54812 -> 0 bytes .../Resources/translations/AddonManager_ja.ts | 2483 ------ .../Resources/translations/AddonManager_ka.qm | Bin 70807 -> 0 bytes .../Resources/translations/AddonManager_ka.ts | 2486 ------ .../translations/AddonManager_kab.qm | Bin 13467 -> 0 bytes .../translations/AddonManager_kab.ts | 427 - .../Resources/translations/AddonManager_ko.qm | Bin 64916 -> 0 bytes .../Resources/translations/AddonManager_ko.ts | 2487 ------ .../Resources/translations/AddonManager_lt.qm | Bin 67207 -> 0 bytes .../Resources/translations/AddonManager_lt.ts | 2487 ------ .../Resources/translations/AddonManager_nl.qm | Bin 69711 -> 0 bytes .../Resources/translations/AddonManager_nl.ts | 2487 ------ .../Resources/translations/AddonManager_no.qm | Bin 13995 -> 0 bytes .../Resources/translations/AddonManager_no.ts | 424 - .../Resources/translations/AddonManager_pl.qm | Bin 73201 -> 0 bytes .../Resources/translations/AddonManager_pl.ts | 2492 ------ .../translations/AddonManager_pt-BR.qm | Bin 71404 -> 0 bytes .../translations/AddonManager_pt-BR.ts | 2487 ------ .../translations/AddonManager_pt-PT.qm | Bin 70232 -> 0 bytes .../translations/AddonManager_pt-PT.ts | 2487 ------ .../Resources/translations/AddonManager_ro.qm | Bin 66678 -> 0 bytes .../Resources/translations/AddonManager_ro.ts | 2485 ------ .../Resources/translations/AddonManager_ru.qm | Bin 70826 -> 0 bytes .../Resources/translations/AddonManager_ru.ts | 2487 ------ .../Resources/translations/AddonManager_sk.qm | Bin 29800 -> 0 bytes .../Resources/translations/AddonManager_sk.ts | 1168 --- .../Resources/translations/AddonManager_sl.qm | Bin 68930 -> 0 bytes .../Resources/translations/AddonManager_sl.ts | 2487 ------ .../translations/AddonManager_sr-CS.qm | Bin 70115 -> 0 bytes .../translations/AddonManager_sr-CS.ts | 2487 ------ .../Resources/translations/AddonManager_sr.qm | Bin 69684 -> 0 bytes .../Resources/translations/AddonManager_sr.ts | 2487 ------ .../translations/AddonManager_sv-SE.qm | Bin 67422 -> 0 bytes .../translations/AddonManager_sv-SE.ts | 2486 ------ .../Resources/translations/AddonManager_tr.qm | Bin 67980 -> 0 bytes .../Resources/translations/AddonManager_tr.ts | 2488 ------ .../Resources/translations/AddonManager_uk.qm | Bin 70004 -> 0 bytes .../Resources/translations/AddonManager_uk.ts | 2488 ------ .../translations/AddonManager_val-ES.qm | Bin 67330 -> 0 bytes .../translations/AddonManager_val-ES.ts | 2494 ------ .../Resources/translations/AddonManager_vi.qm | Bin 67679 -> 0 bytes .../Resources/translations/AddonManager_vi.ts | 2477 ------ .../translations/AddonManager_zh-CN.qm | Bin 49059 -> 0 bytes .../translations/AddonManager_zh-CN.ts | 2486 ------ .../translations/AddonManager_zh-TW.qm | Bin 49589 -> 0 bytes .../translations/AddonManager_zh-TW.ts | 2487 ------ src/Mod/AddonManager/TODO.md | 8 - src/Mod/AddonManager/TestAddonManagerApp.py | 100 - src/Mod/AddonManager/TestAddonManagerGui.py | 65 - src/Mod/AddonManager/Widgets/CMakeLists.txt | 28 - src/Mod/AddonManager/Widgets/__init__.py | 0 .../Widgets/addonmanager_colors.py | 48 - .../addonmanager_widget_addon_buttons.py | 118 - .../addonmanager_widget_filter_selector.py | 259 - .../addonmanager_widget_global_buttons.py | 110 - ...ddonmanager_widget_package_details_view.py | 361 - .../addonmanager_widget_progress_bar.py | 168 - .../addonmanager_widget_readme_browser.py | 132 - .../Widgets/addonmanager_widget_search.py | 104 - .../addonmanager_widget_view_control_bar.py | 169 - .../addonmanager_widget_view_selector.py | 161 - src/Mod/AddonManager/__init__.py | 0 .../AddonManager/add_toolbar_button_dialog.ui | 105 - src/Mod/AddonManager/addonmanager.dox | 4 - src/Mod/AddonManager/addonmanager_cache.py | 118 - .../addonmanager_connection_checker.py | 125 - .../addonmanager_dependency_installer.py | 195 - src/Mod/AddonManager/addonmanager_devmode.py | 699 -- .../addonmanager_devmode_add_content.py | 635 -- .../addonmanager_devmode_license_selector.py | 275 - .../addonmanager_devmode_licenses_table.py | 129 - .../addonmanager_devmode_metadata_checker.py | 184 - .../addonmanager_devmode_people_table.py | 153 - .../addonmanager_devmode_person_editor.py | 72 - .../addonmanager_devmode_predictor.py | 286 - .../addonmanager_devmode_validators.py | 166 - src/Mod/AddonManager/addonmanager_firstrun.py | 66 - .../addonmanager_freecad_interface.py | 291 - src/Mod/AddonManager/addonmanager_git.py | 480 - .../AddonManager/addonmanager_installer.py | 579 -- .../addonmanager_installer_gui.py | 815 -- src/Mod/AddonManager/addonmanager_licenses.py | 187 - src/Mod/AddonManager/addonmanager_macro.py | 439 - .../AddonManager/addonmanager_macro_parser.py | 257 - src/Mod/AddonManager/addonmanager_metadata.py | 435 - ...addonmanager_package_details_controller.py | 284 - .../addonmanager_preferences_defaults.json | 50 - .../addonmanager_pyside_interface.py | 60 - .../addonmanager_python_deps_gui.py | 505 -- .../addonmanager_readme_controller.py | 286 - .../AddonManager/addonmanager_uninstaller.py | 292 - .../addonmanager_uninstaller_gui.py | 137 - .../addonmanager_update_all_gui.py | 242 - .../AddonManager/addonmanager_utilities.py | 599 -- .../addonmanager_workers_installation.py | 315 - .../addonmanager_workers_startup.py | 1006 --- .../addonmanager_workers_utility.py | 93 - src/Mod/AddonManager/change_branch.py | 310 - src/Mod/AddonManager/change_branch.ui | 105 - src/Mod/AddonManager/compact_view.py | 95 - src/Mod/AddonManager/compact_view.ui | 110 - src/Mod/AddonManager/composite_view.py | 170 - .../dependency_resolution_dialog.ui | 125 - src/Mod/AddonManager/developer_mode.ui | 364 - .../developer_mode_add_content.ui | 419 - ...eveloper_mode_advanced_freecad_versions.ui | 131 - .../developer_mode_copyright_info.ui | 88 - .../developer_mode_dependencies.ui | 132 - .../developer_mode_edit_dependency.ui | 123 - .../developer_mode_freecad_versions.ui | 99 - .../AddonManager/developer_mode_license.ui | 134 - .../developer_mode_licenses_table.ui | 123 - src/Mod/AddonManager/developer_mode_people.ui | 99 - .../developer_mode_people_table.ui | 116 - .../developer_mode_select_from_list.ui | 77 - src/Mod/AddonManager/developer_mode_tags.ui | 86 - src/Mod/AddonManager/expanded_view.py | 136 - src/Mod/AddonManager/expanded_view.ui | 204 - src/Mod/AddonManager/first_run.ui | 113 - src/Mod/AddonManager/install_to_toolbar.py | 293 - src/Mod/AddonManager/loading.html | 96 - src/Mod/AddonManager/package_details.ui | 106 - src/Mod/AddonManager/package_list.py | 792 -- src/Mod/AddonManager/proxy_authentication.ui | 150 - src/Mod/AddonManager/select_toolbar_dialog.ui | 87 - src/Mod/AddonManager/toolbar_button.ui | 56 - src/Mod/AddonManager/update_all.ui | 111 - src/Mod/CMakeLists.txt | 4 + src/Tools/updatecrowdin.py | 5 - src/Tools/updatets.py | 5 - 321 files changed, 8 insertions(+), 148747 deletions(-) create mode 160000 src/Mod/AddonManager delete mode 100644 src/Mod/AddonManager/ALLOWED_PYTHON_PACKAGES.txt delete mode 100644 src/Mod/AddonManager/Addon.py delete mode 100644 src/Mod/AddonManager/AddonCatalog.py delete mode 100644 src/Mod/AddonManager/AddonManager.py delete mode 100644 src/Mod/AddonManager/AddonManager.ui delete mode 100644 src/Mod/AddonManager/AddonManagerOptions.py delete mode 100644 src/Mod/AddonManager/AddonManagerOptions.ui delete mode 100644 src/Mod/AddonManager/AddonManagerOptions_AddCustomRepository.ui delete mode 100644 src/Mod/AddonManager/AddonManagerTest/__init__.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/__init__.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/mocks.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_addon.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_addoncatalog.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_cache.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_freecad_interface.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_git.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_installer.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_macro.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_macro_parser.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_metadata.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_uninstaller.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/app/test_utilities.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/DoNothing.FCMacro delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/MacrosRecipesWikiPage.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/TestWorkbench.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/__init__.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/addon_update_stats.json delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/bundle_only.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/combination.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/corrupted_metadata.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/depends_on_all_workbenches.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/git_submodules.txt delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/good_package.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip.sha1 delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/macro_only.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/macro_template.FCStd delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/metadata.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/missing_macro_metadata.FCStd delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/other_only.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/prefpack_only.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/test_addon_with_fcmacro.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/test_github_style_repo.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/test_repo.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/test_simple_repo.zip delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/test_version_detection.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/data/workbench_only.xml delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/__init__.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/gui_mocks.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_gui.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_installer_gui.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_python_deps_gui.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_uninstaller_gui.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_update_all_gui.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_widget_progress_bar.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/gui/test_workers_utility.py delete mode 100644 src/Mod/AddonManager/AddonManagerTest/test_information.md delete mode 100644 src/Mod/AddonManager/AddonStats.py delete mode 100644 src/Mod/AddonManager/CMakeLists.txt delete mode 100644 src/Mod/AddonManager/Init.py delete mode 100644 src/Mod/AddonManager/InitGui.py delete mode 100644 src/Mod/AddonManager/NetworkManager.py delete mode 100644 src/Mod/AddonManager/PythonDependencyUpdateDialog.ui delete mode 100644 src/Mod/AddonManager/Resources/AddonManager.qrc delete mode 100644 src/Mod/AddonManager/Resources/icons/3D_Printing_Tools_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/A2plus_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/AddonMgrWithWarning.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/AirPlaneDesign_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/ArchTextures_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Assembly4_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/BCFPlugin_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/BIMBots_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/BIM_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/BOLTSFC_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/CADExchanger_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/CfdOF_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Cfd_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/CurvedShapes_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Curves_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Defeaturing_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/DesignSPHysics_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/DynamicData_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/EM_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/ExplodedAssembly_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/ExtMan_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/FCGear_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/FEM_FrontISTR_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/GDML_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/GDT_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Geomatics_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/ImportNURBS_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/InventorLoader_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/LCInterlocking_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Lithophane_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/MOOC_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Maker_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Manipulator_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Marz_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/MeshRemodel_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/MnesarcoUtils_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/ModernUI_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/OSE3dPrinter_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/POV-Ray-Rendering_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Part-o-magic_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Plot_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Pyramids-and-Polyhedrons_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Reinforcement_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Render_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Reporting_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Rocket_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Ship_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/Silk_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/TaackPLM_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/ThreadProfile_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/WebTools_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/cadquery_module_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/compact_view.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/composite_view.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/dodo_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/expanded_view.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/fasteners_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/flamingo_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/kicadStepUpMod_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/lattice2_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/preferences-addon_manager.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/pyrate_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/sheetmetal_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/slic3r-tools_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/sort_ascending.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/sort_descending.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/timber_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/workfeature_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/icons/yaml-workspace_workbench_icon.svg delete mode 100644 src/Mod/AddonManager/Resources/licenses/Apache-2.0.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/BSD-2-Clause.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/BSD-3-Clause.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/CC0-1.0.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/GPL-2.0-or-later.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/GPL-3.0-or-later.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/LGPL-2.1-or-later.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/LGPL-3.0-or-later.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/MIT.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/MPL-2.0.txt delete mode 100644 src/Mod/AddonManager/Resources/licenses/spdx.json delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_af.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_af.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ar.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ar.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_be.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_be.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_bg.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_bg.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ca.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ca.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_cs.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_cs.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_da.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_da.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_de.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_de.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_el.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_el.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_eu.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_eu.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_fi.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_fi.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_fil.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_fil.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_fr.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_fr.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_gl.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_gl.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_hr.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_hr.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_hu.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_hu.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_id.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_id.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_it.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_it.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ja.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ja.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ka.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ka.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_kab.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_kab.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ko.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ko.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_lt.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_lt.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_nl.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_nl.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_no.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_no.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_pl.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_pl.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_pt-BR.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_pt-BR.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ro.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ro.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ru.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_ru.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sk.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sk.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sl.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sl.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sr-CS.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sr-CS.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sr.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sr.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_tr.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_tr.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_uk.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_uk.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_val-ES.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_val-ES.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_vi.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_vi.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.ts delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.qm delete mode 100644 src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.ts delete mode 100644 src/Mod/AddonManager/TODO.md delete mode 100644 src/Mod/AddonManager/TestAddonManagerApp.py delete mode 100644 src/Mod/AddonManager/TestAddonManagerGui.py delete mode 100644 src/Mod/AddonManager/Widgets/CMakeLists.txt delete mode 100644 src/Mod/AddonManager/Widgets/__init__.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_colors.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_readme_browser.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_search.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py delete mode 100644 src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py delete mode 100644 src/Mod/AddonManager/__init__.py delete mode 100644 src/Mod/AddonManager/add_toolbar_button_dialog.ui delete mode 100644 src/Mod/AddonManager/addonmanager.dox delete mode 100644 src/Mod/AddonManager/addonmanager_cache.py delete mode 100644 src/Mod/AddonManager/addonmanager_connection_checker.py delete mode 100644 src/Mod/AddonManager/addonmanager_dependency_installer.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_add_content.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_license_selector.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_licenses_table.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_people_table.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_person_editor.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_predictor.py delete mode 100644 src/Mod/AddonManager/addonmanager_devmode_validators.py delete mode 100644 src/Mod/AddonManager/addonmanager_firstrun.py delete mode 100644 src/Mod/AddonManager/addonmanager_freecad_interface.py delete mode 100644 src/Mod/AddonManager/addonmanager_git.py delete mode 100644 src/Mod/AddonManager/addonmanager_installer.py delete mode 100644 src/Mod/AddonManager/addonmanager_installer_gui.py delete mode 100644 src/Mod/AddonManager/addonmanager_licenses.py delete mode 100644 src/Mod/AddonManager/addonmanager_macro.py delete mode 100644 src/Mod/AddonManager/addonmanager_macro_parser.py delete mode 100644 src/Mod/AddonManager/addonmanager_metadata.py delete mode 100644 src/Mod/AddonManager/addonmanager_package_details_controller.py delete mode 100644 src/Mod/AddonManager/addonmanager_preferences_defaults.json delete mode 100644 src/Mod/AddonManager/addonmanager_pyside_interface.py delete mode 100644 src/Mod/AddonManager/addonmanager_python_deps_gui.py delete mode 100644 src/Mod/AddonManager/addonmanager_readme_controller.py delete mode 100644 src/Mod/AddonManager/addonmanager_uninstaller.py delete mode 100644 src/Mod/AddonManager/addonmanager_uninstaller_gui.py delete mode 100644 src/Mod/AddonManager/addonmanager_update_all_gui.py delete mode 100644 src/Mod/AddonManager/addonmanager_utilities.py delete mode 100644 src/Mod/AddonManager/addonmanager_workers_installation.py delete mode 100644 src/Mod/AddonManager/addonmanager_workers_startup.py delete mode 100644 src/Mod/AddonManager/addonmanager_workers_utility.py delete mode 100644 src/Mod/AddonManager/change_branch.py delete mode 100644 src/Mod/AddonManager/change_branch.ui delete mode 100644 src/Mod/AddonManager/compact_view.py delete mode 100644 src/Mod/AddonManager/compact_view.ui delete mode 100644 src/Mod/AddonManager/composite_view.py delete mode 100644 src/Mod/AddonManager/dependency_resolution_dialog.ui delete mode 100644 src/Mod/AddonManager/developer_mode.ui delete mode 100644 src/Mod/AddonManager/developer_mode_add_content.ui delete mode 100644 src/Mod/AddonManager/developer_mode_advanced_freecad_versions.ui delete mode 100644 src/Mod/AddonManager/developer_mode_copyright_info.ui delete mode 100644 src/Mod/AddonManager/developer_mode_dependencies.ui delete mode 100644 src/Mod/AddonManager/developer_mode_edit_dependency.ui delete mode 100644 src/Mod/AddonManager/developer_mode_freecad_versions.ui delete mode 100644 src/Mod/AddonManager/developer_mode_license.ui delete mode 100644 src/Mod/AddonManager/developer_mode_licenses_table.ui delete mode 100644 src/Mod/AddonManager/developer_mode_people.ui delete mode 100644 src/Mod/AddonManager/developer_mode_people_table.ui delete mode 100644 src/Mod/AddonManager/developer_mode_select_from_list.ui delete mode 100644 src/Mod/AddonManager/developer_mode_tags.ui delete mode 100644 src/Mod/AddonManager/expanded_view.py delete mode 100644 src/Mod/AddonManager/expanded_view.ui delete mode 100644 src/Mod/AddonManager/first_run.ui delete mode 100644 src/Mod/AddonManager/install_to_toolbar.py delete mode 100644 src/Mod/AddonManager/loading.html delete mode 100644 src/Mod/AddonManager/package_details.ui delete mode 100644 src/Mod/AddonManager/package_list.py delete mode 100644 src/Mod/AddonManager/proxy_authentication.ui delete mode 100644 src/Mod/AddonManager/select_toolbar_dialog.ui delete mode 100644 src/Mod/AddonManager/toolbar_button.ui delete mode 100644 src/Mod/AddonManager/update_all.ui diff --git a/.gitmodules b/.gitmodules index b6bc63efd4..e6a738fdf5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "src/3rdParty/GSL"] path = src/3rdParty/GSL url = https://github.com/microsoft/GSL +[submodule "src/Mod/AddonManager"] + path = src/Mod/AddonManager + url = https://github.com/FreeCAD/AddonManager.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22f43d741a..36430fd6c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,6 @@ files: | src/Main| src/Tools| tests/src| - src/Mod/AddonManager| src/Mod/Assembly| src/Mod/CAM| src/Mod/Cloud| diff --git a/src/Mod/AddonManager b/src/Mod/AddonManager new file mode 160000 index 0000000000..34d433a02c --- /dev/null +++ b/src/Mod/AddonManager @@ -0,0 +1 @@ +Subproject commit 34d433a02c7ec5c73bec9c57d0a27ea70b36c90d diff --git a/src/Mod/AddonManager/ALLOWED_PYTHON_PACKAGES.txt b/src/Mod/AddonManager/ALLOWED_PYTHON_PACKAGES.txt deleted file mode 100644 index eec6400eaf..0000000000 --- a/src/Mod/AddonManager/ALLOWED_PYTHON_PACKAGES.txt +++ /dev/null @@ -1,35 +0,0 @@ -# This file lists the Python packages that the Addon Manager allows to be installed -# automatically via pip. To request that a package be added to this list, submit a -# pull request to the FreeCAD git repository with the requested package added. Only -# packages in this list will be processed from the metadata.txt and requirements.txt -# files specified by an Addon. Note that this is NOT a requirements.txt-format file, -# no version information may be specified, and no wildcards are supported. - -# Allow these packages to be installed: -aiofiles -autobahn -ezdxf -gmsh -gmsh-dev -lxml -markdown -matplotlib -msgpack -numpy -ocp -olefile -openpyxl -pandas -pillow -ply -py-slvs -pycollada -pygit2 -pynastran -requests -rhino3dm -scipy -xlrd -xlutils -xlwt -PyYAML diff --git a/src/Mod/AddonManager/Addon.py b/src/Mod/AddonManager/Addon.py deleted file mode 100644 index 8ec60ce48e..0000000000 --- a/src/Mod/AddonManager/Addon.py +++ /dev/null @@ -1,863 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines the Addon class to encapsulate information about FreeCAD Addons""" - -import os -import re -from datetime import datetime -from urllib.parse import urlparse -from typing import Dict, Set, List, Optional -from threading import Lock -from enum import IntEnum, auto -import xml.etree.ElementTree - -import addonmanager_freecad_interface as fci -from addonmanager_macro import Macro -import addonmanager_utilities as utils -from addonmanager_utilities import construct_git_url, process_date_string_to_python_datetime -from addonmanager_metadata import ( - Metadata, - MetadataReader, - UrlType, - Version, - DependencyType, -) -from AddonStats import AddonStats - -translate = fci.translate - -# A list of internal workbenches that can be used as a dependency of an Addon -INTERNAL_WORKBENCHES = { - "bim": "BIM", - "assembly": "Assembly", - "draft": "Draft", - "fem": "FEM", - "mesh": "Mesh", - "openscad": "OpenSCAD", - "part": "Part", - "partdesign": "PartDesign", - "cam": "CAM", - "plot": "Plot", - "points": "Points", - "robot": "Robot", - "sketcher": "Sketcher", - "spreadsheet": "Spreadsheet", - "techdraw": "TechDraw", -} - - -class Addon: - """Encapsulates information about a FreeCAD addon""" - - class Kind(IntEnum): - """The type of Addon: Workbench, macro, or package""" - - WORKBENCH = 1 - MACRO = 2 - PACKAGE = 3 - - def __str__(self) -> str: - if self.value == 1: - return "Workbench" - if self.value == 2: - return "Macro" - if self.value == 3: - return "Package" - return "ERROR_TYPE" - - class Status(IntEnum): - """The installation status of an Addon""" - - NOT_INSTALLED = 0 - UNCHECKED = 1 - NO_UPDATE_AVAILABLE = 2 - UPDATE_AVAILABLE = 3 - PENDING_RESTART = 4 - CANNOT_CHECK = 5 # If we don't have git, etc. - UNKNOWN = 100 - - def __lt__(self, other): - if self.__class__ is other.__class__: - return self.value < other.value - return NotImplemented - - def __str__(self) -> str: - if self.value == 0: - result = "Not installed" - elif self.value == 1: - result = "Unchecked" - elif self.value == 2: - result = "No update available" - elif self.value == 3: - result = "Update available" - elif self.value == 4: - result = "Restart required" - elif self.value == 5: - result = "Can't check" - else: - result = "ERROR_STATUS" - return result - - class Dependencies: - """Addon dependency information""" - - def __init__(self): - self.required_external_addons = [] # A list of Addons - self.blockers = [] # A list of Addons - self.replaces = [] # A list of Addons - self.internal_workbenches: Set[str] = set() # Required internal workbenches - self.python_requires: Set[str] = set() - self.python_optional: Set[str] = set() - self.python_min_version = {"major": 3, "minor": 0} - - class DependencyType(IntEnum): - """Several types of dependency information is stored""" - - INTERNAL_WORKBENCH = auto() - REQUIRED_ADDON = auto() - BLOCKED_ADDON = auto() - REPLACED_ADDON = auto() - REQUIRED_PYTHON = auto() - OPTIONAL_PYTHON = auto() - - class ResolutionFailed(RuntimeError): - """An exception type for dependency resolution failure.""" - - # The location of Addon Manager cache files: overridden by testing code - cache_directory = os.path.join(fci.DataPaths().cache_dir, "AddonManager") - - # The location of the Mod directory: overridden by testing code - mod_directory = fci.DataPaths().mod_dir - - # The location of the Macro directory: overridden by testing code - macro_directory = fci.DataPaths().macro_dir - - def __init__( - self, - name: str, - url: str = "", - status: Status = Status.UNKNOWN, - branch: str = "", - ): - self.name = name.strip() - self.display_name = self.name - self.url = url.strip() - self.branch = branch.strip() - self.python2 = False - self.obsolete = False - self.rejected = False - self.repo_type = Addon.Kind.WORKBENCH - self.description = None - self.tags = set() # Just a cache, loaded from Metadata - self.last_updated = None - self.stats = AddonStats() - self.score = 0 - - # To prevent multiple threads from running git actions on this repo at the - # same time - self.git_lock = Lock() - - # To prevent multiple threads from accessing the status at the same time - self.status_lock = Lock() - self.update_status = status - - self._clean_url() - - if utils.recognized_git_location(self): - self.metadata_url = construct_git_url(self, "package.xml") - else: - self.metadata_url = None - self.metadata: Optional[Metadata] = None - self.icon = None # A QIcon version of this Addon's icon - self.icon_file: str = "" # Absolute local path to cached icon file - self.best_icon_relative_path = "" - self.macro = None # Bridge to Gaël Écorchard's macro management class - self.updated_timestamp = None - self.installed_version = None - self.installed_metadata = None - - # Each repo is also a node in a directed dependency graph (referenced by name so - # they can be serialized): - self.requires: Set[str] = set() - self.blocks: Set[str] = set() - - # And maintains a list of required and optional Python dependencies - self.python_requires: Set[str] = set() - self.python_optional: Set[str] = set() - self.python_min_version = {"major": 3, "minor": 0} - - self._icon_file = None - self._cached_license: str = "" - self._cached_update_date = None - - def _clean_url(self): - # The url should never end in ".git", so strip it if it's there - parsed_url = urlparse(self.url) - if parsed_url.path.endswith(".git"): - self.url = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path[:-4] - if parsed_url.query: - self.url += "?" + parsed_url.query - if parsed_url.fragment: - self.url += "#" + parsed_url.fragment - - def __str__(self) -> str: - result = f"FreeCAD {self.repo_type}\n" - result += f"Name: {self.name}\n" - result += f"URL: {self.url}\n" - result += "Has metadata\n" if self.metadata is not None else "No metadata found\n" - if self.macro is not None: - result += "Has linked Macro object\n" - return result - - @property - def license(self): - if not self._cached_license: - self._cached_license = "UNLICENSED" - if self.metadata and self.metadata.license: - self._cached_license = self.metadata.license - elif self.stats and self.stats.license: - self._cached_license = self.stats.license - elif self.macro: - if self.macro.license: - self._cached_license = self.macro.license - elif self.macro.on_wiki: - self._cached_license = "CC-BY-3.0" - return self._cached_license - - @property - def update_date(self): - if self._cached_update_date is None: - self._cached_update_date = 0 - if self.stats and self.stats.last_update_time: - self._cached_update_date = self.stats.last_update_time - elif self.macro and self.macro.date: - # Try to parse the date: - try: - self._cached_update_date = process_date_string_to_python_datetime( - self.macro.date - ) - except ValueError as e: - fci.Console.PrintWarning(str(e) + "\n") - else: - fci.Console.PrintWarning(f"No update date info for {self.name}\n") - return self._cached_update_date - - @classmethod - def from_macro(cls, macro: Macro): - """Create an Addon object from a Macro wrapper object""" - - if macro.is_installed(): - status = Addon.Status.UNCHECKED - else: - status = Addon.Status.NOT_INSTALLED - instance = Addon(macro.name, macro.url, status, "master") - instance.macro = macro - instance.repo_type = Addon.Kind.MACRO - instance.description = macro.desc - return instance - - @classmethod - def from_cache(cls, cache_dict: Dict): - """Load basic data from cached dict data. Does not include Macro or Metadata - information, which must be populated separately.""" - - mod_dir = os.path.join(cls.mod_directory, cache_dict["name"]) - if os.path.isdir(mod_dir): - status = Addon.Status.UNCHECKED - else: - status = Addon.Status.NOT_INSTALLED - instance = Addon(cache_dict["name"], cache_dict["url"], status, cache_dict["branch"]) - - for key, value in cache_dict.items(): - if not str(key).startswith("_"): - instance.__dict__[key] = value - - instance.repo_type = Addon.Kind(cache_dict["repo_type"]) - if instance.repo_type == Addon.Kind.PACKAGE: - # There must be a cached metadata file, too - cached_package_xml_file = os.path.join( - instance.cache_directory, - "PackageMetadata", - instance.name, - ) - if os.path.isfile(cached_package_xml_file): - instance.load_metadata_file(cached_package_xml_file) - - instance._load_installed_metadata() - - if "requires" in cache_dict: - instance.requires = set(cache_dict["requires"]) - instance.blocks = set(cache_dict["blocks"]) - instance.python_requires = set(cache_dict["python_requires"]) - instance.python_optional = set(cache_dict["python_optional"]) - - instance._clean_url() - - return instance - - def to_cache(self) -> Dict: - """Returns a dictionary with cache information that can be used later with - from_cache to recreate this object.""" - - return { - "name": self.name, - "display_name": self.display_name, - "url": self.url, - "branch": self.branch, - "repo_type": int(self.repo_type), - "description": self.description, - "cached_icon_filename": self.get_cached_icon_filename(), - "best_icon_relative_path": self.get_best_icon_relative_path(), - "python2": self.python2, - "obsolete": self.obsolete, - "rejected": self.rejected, - "requires": list(self.requires), - "blocks": list(self.blocks), - "python_requires": list(self.python_requires), - "python_optional": list(self.python_optional), - } - - def load_metadata_file(self, file: str) -> None: - """Read a given metadata file and set it as this object's metadata""" - - if os.path.exists(file): - try: - metadata = MetadataReader.from_file(file) - except xml.etree.ElementTree.ParseError: - fci.Console.PrintWarning( - "An invalid or corrupted package.xml file was found in the cache for" - ) - fci.Console.PrintWarning(f" {self.name}... ignoring the bad data.\n") - return - self.set_metadata(metadata) - self._clean_url() - else: - fci.Console.PrintLog(f"Internal error: {file} does not exist") - - def _load_installed_metadata(self) -> None: - # If it is actually installed, there is a SECOND metadata file, in the actual installation, - # that may not match the cached one if the Addon has not been updated but the cache has. - mod_dir = os.path.join(self.mod_directory, self.name) - installed_metadata_path = os.path.join(mod_dir, "package.xml") - if os.path.isfile(installed_metadata_path): - try: - self.installed_metadata = MetadataReader.from_file(installed_metadata_path) - except xml.etree.ElementTree.ParseError: - fci.Console.PrintWarning( - "An invalid or corrupted package.xml file was found in installation of" - ) - fci.Console.PrintWarning(f" {self.name}... ignoring the bad data.\n") - return - - def set_metadata(self, metadata: Metadata) -> None: - """Set the given metadata object as this object's metadata, updating the - object's display name and package type information to match, as well as - updating any dependency information, etc. - """ - - self.metadata = metadata - self.display_name = metadata.name - self.repo_type = Addon.Kind.PACKAGE - self.description = metadata.description - for url in metadata.url: - if url.type == UrlType.repository: - self.url = url.location - self.branch = url.branch if url.branch else "master" - self._clean_url() - self.extract_tags(self.metadata) - self.extract_metadata_dependencies(self.metadata) - - @staticmethod - def version_is_ok(metadata: Metadata) -> bool: - """Checks to see if the current running version of FreeCAD meets the - requirements set by the passed-in metadata parameter.""" - - from_fci = list(fci.Version()) - fc_version = Version(from_list=from_fci) - - dep_fc_min = metadata.freecadmin if metadata.freecadmin else fc_version - dep_fc_max = metadata.freecadmax if metadata.freecadmax else fc_version - - return dep_fc_min <= fc_version <= dep_fc_max - - def extract_metadata_dependencies(self, metadata: Metadata): - """Read dependency information from a metadata object and store it in this - Addon""" - - # Version check: if this piece of metadata doesn't apply to this version of - # FreeCAD, just skip it. - if not Addon.version_is_ok(metadata): - return - - if metadata.pythonmin: - self.python_min_version["major"] = metadata.pythonmin.version_as_list[0] - self.python_min_version["minor"] = metadata.pythonmin.version_as_list[1] - - for dep in metadata.depend: - if dep.dependency_type == DependencyType.internal: - if dep.package in INTERNAL_WORKBENCHES: - self.requires.add(dep.package) - else: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "{}: Unrecognized internal workbench '{}'", - ).format(self.name, dep.package) - ) - elif dep.dependency_type == DependencyType.addon: - self.requires.add(dep.package) - elif dep.dependency_type == DependencyType.python: - if dep.optional: - self.python_optional.add(dep.package) - else: - self.python_requires.add(dep.package) - else: - # Automatic resolution happens later, once we have a complete list of - # Addons - self.requires.add(dep.package) - - for dep in metadata.conflict: - self.blocks.add(dep.package) - - # Recurse - content = metadata.content - for _, value in content.items(): - for item in value: - self.extract_metadata_dependencies(item) - - def verify_url_and_branch(self, url: str, branch: str) -> None: - """Print diagnostic information for Addon Developers if their metadata is - inconsistent with the actual fetch location. Most often this is due to using - the wrong branch name.""" - - if self.url != url: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({})", - ).format(self.display_name, self.url, url) - + "\n" - ) - if self.branch != branch: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({})", - ).format(self.display_name, self.branch, branch) - + "\n" - ) - - def extract_tags(self, metadata: Metadata) -> None: - """Read the tags from the metadata object""" - - # Version check: if this piece of metadata doesn't apply to this version of - # FreeCAD, just skip it. - if not Addon.version_is_ok(metadata): - return - - for new_tag in metadata.tag: - self.tags.add(new_tag) - - content = metadata.content - for _, value in content.items(): - for item in value: - self.extract_tags(item) - - def contains_workbench(self) -> bool: - """Determine if this package contains (or is) a workbench""" - - if self.repo_type == Addon.Kind.WORKBENCH: - return True - return self.contains_packaged_content("workbench") - - def contains_macro(self) -> bool: - """Determine if this package contains (or is) a macro""" - - if self.repo_type == Addon.Kind.MACRO: - return True - return self.contains_packaged_content("macro") - - def contains_packaged_content(self, content_type: str): - """Determine if the package contains content_type""" - if self.repo_type == Addon.Kind.PACKAGE: - if self.metadata is None: - fci.Console.PrintLog( - f"Addon Manager internal error: lost metadata for package {self.name}\n" - ) - return False - content = self.metadata.content - return content_type in content - return False - - def contains_preference_pack(self) -> bool: - """Determine if this package contains a preference pack""" - return self.contains_packaged_content("preferencepack") - - def contains_bundle(self) -> bool: - """Determine if this package contains a bundle""" - return self.contains_packaged_content("bundle") - - def contains_other(self) -> bool: - """Determine if this package contains an "other" content item""" - return self.contains_packaged_content("other") - - def get_best_icon_relative_path(self) -> str: - """Get the path within the repo the addon's icon. Usually specified by - top-level metadata, but some authors omit it and specify only icons for the - contents. Find the first one of those, in such cases.""" - - if self.best_icon_relative_path: - return self.best_icon_relative_path - - if not self.metadata: - return "" - - real_icon = self.metadata.icon - if not real_icon: - # If there is no icon set for the entire package, see if there are any - # workbenches, which are required to have icons, and grab the first one - # we find: - content = self.metadata.content - if "workbench" in content: - wb = content["workbench"][0] - if wb.icon: - if wb.subdirectory: - subdir = wb.subdirectory - else: - subdir = wb.name - real_icon = subdir + wb.icon - - self.best_icon_relative_path = real_icon - return self.best_icon_relative_path - - def get_cached_icon_filename(self) -> str: - """NOTE: This function is deprecated and will be removed in a coming update.""" - - if hasattr(self, "cached_icon_filename") and self.cached_icon_filename: - return self.cached_icon_filename - - if not self.metadata: - return "" - - real_icon = self.metadata.icon - if not real_icon: - # If there is no icon set for the entire package, see if there are any - # workbenches, which are required to have icons, and grab the first one - # we find: - content = self.metadata.content - if "workbench" in content: - wb = content["workbench"][0] - if wb.icon: - if wb.subdirectory: - subdir = wb.subdirectory - else: - subdir = wb.name - real_icon = subdir + wb.icon - - real_icon = real_icon.replace( - "/", os.path.sep - ) # Required path separator in the metadata.xml file to local separator - - _, file_extension = os.path.splitext(real_icon) - store = os.path.join(self.cache_directory, "PackageMetadata") - self.cached_icon_filename = os.path.join(store, self.name, "cached_icon" + file_extension) - - return self.cached_icon_filename - - def walk_dependency_tree(self, all_repos, deps): - """Compute the total dependency tree for this repo (recursive) - - all_repos is a dictionary of repos, keyed on the name of the repo - - deps is an Addon.Dependency object encapsulating all the types of dependency - information that may be needed. - """ - - deps.python_requires |= self.python_requires - deps.python_optional |= self.python_optional - - deps.python_min_version["major"] = max( - deps.python_min_version["major"], self.python_min_version["major"] - ) - if deps.python_min_version["major"] == 3: - deps.python_min_version["minor"] = max( - deps.python_min_version["minor"], self.python_min_version["minor"] - ) - else: - fci.Console.PrintWarning("Unrecognized Python version information") - - for dep in self.requires: - if dep in all_repos: - if dep not in deps.required_external_addons: - deps.required_external_addons.append(all_repos[dep]) - all_repos[dep].walk_dependency_tree(all_repos, deps) - else: - # See if this is an internal workbench: - if dep.upper().endswith("WB"): - real_name = dep[:-2].strip().lower() - elif dep.upper().endswith("WORKBENCH"): - real_name = dep[:-9].strip().lower() - else: - real_name = dep.strip().lower() - - if real_name in INTERNAL_WORKBENCHES: - deps.internal_workbenches.add(INTERNAL_WORKBENCHES[real_name]) - else: - # Assume it's a Python requirement of some kind: - deps.python_requires.add(dep) - - for dep in self.blocks: - if dep in all_repos: - deps.blockers[dep] = all_repos[dep] - - def status(self): - """Threadsafe access to the current update status""" - with self.status_lock: - return self.update_status - - def set_status(self, status): - """Threadsafe setting of the update status""" - with self.status_lock: - self.update_status = status - - def is_disabled(self): - """Check to see if the disabling stopfile exists""" - - stopfile = os.path.join(self.mod_directory, self.name, "ADDON_DISABLED") - return os.path.exists(stopfile) - - def disable(self): - """Disable this addon from loading when FreeCAD starts up by creating a - stopfile""" - - stopfile = os.path.join(self.mod_directory, self.name, "ADDON_DISABLED") - with open(stopfile, "w", encoding="utf-8") as f: - f.write( - "The existence of this file prevents FreeCAD from loading this Addon. To re-enable, delete the file." - ) - - if self.contains_workbench(): - self.disable_workbench() - - def enable(self): - """Re-enable loading this addon by deleting the stopfile""" - - stopfile = os.path.join(self.mod_directory, self.name, "ADDON_DISABLED") - try: - os.unlink(stopfile) - except FileNotFoundError: - pass - - if self.contains_workbench(): - self.enable_workbench() - - def enable_workbench(self): - wbName = self.get_workbench_name() - - # Remove from the list of disabled. - self.remove_from_disabled_wbs(wbName) - - def disable_workbench(self): - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches") - wbName = self.get_workbench_name() - - # Add the wb to the list of disabled if it was not already - disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench") - # print(f"start disabling {disabled_wbs}") - disabled_wbs_list = disabled_wbs.split(",") - if not (wbName in disabled_wbs_list): - disabled_wbs += "," + wbName - pref.SetString("Disabled", disabled_wbs) - # print(f"done disabling : {disabled_wbs} \n") - - def desinstall_workbench(self): - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches") - wbName = self.get_workbench_name() - - # Remove from the list of ordered. - ordered_wbs = pref.GetString("Ordered", "") - # print(f"start remove from ordering {ordered_wbs}") - ordered_wbs_list = ordered_wbs.split(",") - ordered_wbs = "" - for wb in ordered_wbs_list: - if wb != wbName: - if ordered_wbs != "": - ordered_wbs += "," - ordered_wbs += wb - pref.SetString("Ordered", ordered_wbs) - # print(f"end remove from ordering {ordered_wbs}") - - # Remove from the list of disabled. - self.remove_from_disabled_wbs(wbName) - - def remove_from_disabled_wbs(self, wbName: str): - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches") - - disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench") - # print(f"start enabling : {disabled_wbs}") - disabled_wbs_list = disabled_wbs.split(",") - disabled_wbs = "" - for wb in disabled_wbs_list: - if wb != wbName: - if disabled_wbs != "": - disabled_wbs += "," - disabled_wbs += wb - pref.SetString("Disabled", disabled_wbs) - # print(f"Done enabling {disabled_wbs} \n") - - def get_workbench_name(self) -> str: - """Find the name of the workbench class (ie the name under which it's - registered in freecad core)'""" - wb_name = "" - - if self.repo_type == Addon.Kind.PACKAGE: - for wb in self.metadata.content["workbench"]: # we may have more than one wb. - if wb_name != "": - wb_name += "," - wb_name += wb.classname - if self.repo_type == Addon.Kind.WORKBENCH or wb_name == "": - wb_name = self.try_find_wbname_in_files() - if wb_name == "": - wb_name = self.name - return wb_name - - def try_find_wbname_in_files(self) -> str: - """Attempt to locate a line with an addWorkbench command in the workbench's - Python files. If it is directly instantiating a workbench, then we can use - the line to determine classname for this workbench. If it uses a variable, - or if the line doesn't exist at all, an empty string is returned.""" - mod_dir = os.path.join(self.mod_directory, self.name) - - for root, _, files in os.walk(mod_dir): - for f in files: - current_file = os.path.join(root, f) - if not os.path.isdir(current_file): - filename, extension = os.path.splitext(current_file) - if extension == ".py": - wb_classname = self._find_classname_in_file(current_file) - if wb_classname: - return wb_classname - return "" - - @staticmethod - def _find_classname_in_file(current_file) -> str: - try: - with open(current_file, "r", encoding="utf-8") as python_file: - content = python_file.read() - search_result = re.search(r"Gui.addWorkbench\s*\(\s*(\w+)\s*\(\s*\)\s*\)", content) - if search_result: - return search_result.group(1) - except OSError: - pass - return "" - - -# @dataclass(frozen) -class MissingDependencies: - """Encapsulates a group of four types of dependencies: - * Internal workbenches -> wbs - * External addons -> external_addons - * Required Python packages -> python_requires - * Optional Python packages -> python_optional - """ - - def __init__(self, repo: Addon, all_repos: List[Addon]): - deps = Addon.Dependencies() - repo_name_dict = {} - for r in all_repos: - repo_name_dict[r.name] = r - if hasattr(r, "display_name"): - # Test harness might not provide a display name - repo_name_dict[r.display_name] = r - - if hasattr(repo, "walk_dependency_tree"): - # Sometimes the test harness doesn't provide this function, to override - # any dependency checking - repo.walk_dependency_tree(repo_name_dict, deps) - - self.external_addons = [] - for dep in deps.required_external_addons: - if dep.status() == Addon.Status.NOT_INSTALLED: - self.external_addons.append(dep.name) - - # Now check the loaded addons to see if we are missing an internal workbench: - if fci.FreeCADGui: - wbs = [wb.lower() for wb in fci.FreeCADGui.listWorkbenches()] - else: - wbs = [] - - self.wbs = [] - for dep in deps.internal_workbenches: - if dep.lower() + "workbench" not in wbs: - if dep.lower() == "plot": - # Special case for plot, which is no longer a full workbench: - try: - __import__("Plot") - except ImportError: - # Plot might fail for a number of reasons - self.wbs.append(dep) - fci.Console.PrintLog("Failed to import Plot module") - else: - self.wbs.append(dep) - - # Check the Python dependencies: - self.python_min_version = deps.python_min_version - self.python_requires = [] - for py_dep in deps.python_requires: - if py_dep not in self.python_requires: - try: - __import__(py_dep) - except ImportError: - self.python_requires.append(py_dep) - except (OSError, NameError, TypeError, RuntimeError) as e: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Got an error when trying to import {}", - ).format(py_dep) - + ":\n" - + str(e) - ) - - self.python_optional = [] - for py_dep in deps.python_optional: - try: - __import__(py_dep) - except ImportError: - self.python_optional.append(py_dep) - except (OSError, NameError, TypeError, RuntimeError) as e: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Got an error when trying to import {}", - ).format(py_dep) - + ":\n" - + str(e) - ) - - self.wbs.sort() - self.external_addons.sort() - self.python_requires.sort() - self.python_optional.sort() - self.python_optional = [ - option for option in self.python_optional if option not in self.python_requires - ] diff --git a/src/Mod/AddonManager/AddonCatalog.py b/src/Mod/AddonManager/AddonCatalog.py deleted file mode 100644 index 9140c48e94..0000000000 --- a/src/Mod/AddonManager/AddonCatalog.py +++ /dev/null @@ -1,143 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2025 The FreeCAD project association AISBL * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""The Addon Catalog is the main list of all Addons along with their various -sources and compatible versions. Added in FreeCAD 1.1 to replace .gitmodules.""" - -from dataclasses import dataclass -from hashlib import sha256 -from typing import Any, Dict, List, Optional, Tuple -from addonmanager_metadata import Version -from Addon import Addon - -import addonmanager_freecad_interface as fci - - -@dataclass -class AddonCatalogEntry: - """Each individual entry in the catalog, storing data about a particular version of an - Addon. Note that this class needs to be identical to the one that is used in the remote cache - generation, so don't make changes here without ensuring that the classes are synchronized.""" - - freecad_min: Optional[Version] = None - freecad_max: Optional[Version] = None - repository: Optional[str] = None - git_ref: Optional[str] = None - zip_url: Optional[str] = None - note: Optional[str] = None - branch_display_name: Optional[str] = None - - def __init__(self, raw_data: Dict[str, str]) -> None: - """Create an AddonDictionaryEntry from the raw JSON data""" - super().__init__() - for key, value in raw_data.items(): - if hasattr(self, key): - if key in ("freecad_min", "freecad_max"): - value = Version(from_string=value) - setattr(self, key, value) - - def is_compatible(self) -> bool: - """Check whether this AddonCatalogEntry is compatible with the current version of FreeCAD""" - if self.freecad_min is None and self.freecad_max is None: - return True - current_version = Version(from_list=fci.Version()) - if self.freecad_min is None: - return current_version <= self.freecad_max - if self.freecad_max is None: - return current_version >= self.freecad_min - return self.freecad_min <= current_version <= self.freecad_max - - def unique_identifier(self) -> str: - """Return a unique identifier of the AddonCatalogEntry, guaranteed to be repeatable: when - given the same basic information, the same ID is created. Used as the key when storing - the metadata for a given AddonCatalogEntry.""" - sha256_hash = sha256() - sha256_hash.update(str(self).encode("utf-8")) - return sha256_hash.hexdigest() - - -class AddonCatalog: - """A catalog of addons grouped together into sets representing versions that are - compatible with different versions of FreeCAD and/or represent different available branches - of a given addon (e.g. a Development branch that users are presented).""" - - def __init__(self, data: Dict[str, Any]): - self._original_data = data - self._dictionary = {} - self._parse_raw_data() - - def _parse_raw_data(self): - self._dictionary = {} # Clear pre-existing contents - for key, value in self._original_data.items(): - if key == "_meta": # Don't add the documentation object to the tree - continue - self._dictionary[key] = [] - for entry in value: - self._dictionary[key].append(AddonCatalogEntry(entry)) - - def load_metadata_cache(self, cache: Dict[str, Any]): - """Given the raw dictionary, couple that with the remote metadata cache to create the - final working addon dictionary. Only create Addons that are compatible with the current - version of FreeCAD.""" - for value in self._dictionary.values(): - for entry in value: - sha256_hash = entry.unique_identifier() - print(sha256_hash) - if sha256_hash in cache and entry.is_compatible(): - entry.addon = Addon.from_cache(cache[sha256_hash]) - - def get_available_addon_ids(self) -> List[str]: - """Get a list of IDs that have at least one entry compatible with the current version of - FreeCAD""" - id_list = [] - for key, value in self._dictionary.items(): - for entry in value: - if entry.is_compatible(): - id_list.append(key) - break - return id_list - - def get_available_branches(self, addon_id: str) -> List[Tuple[str, str]]: - """For a given ID, get the list of available branches compatible with this version of - FreeCAD along with the branch display name. Either field may be empty, but not both. The - first entry in the list is expected to be the "primary".""" - if addon_id not in self._dictionary: - return [] - result = [] - for entry in self._dictionary[addon_id]: - if entry.is_compatible(): - result.append((entry.git_ref, entry.branch_display_name)) - return result - - def get_addon_from_id(self, addon_id: str, branch: Optional[Tuple[str, str]] = None) -> Addon: - """Get the instantiated Addon object for the given ID and optionally branch. If no - branch is provided, whichever branch is the "primary" branch will be returned (i.e. the - first branch that matches). Raises a ValueError if no addon matches the request.""" - if addon_id not in self._dictionary: - raise ValueError(f"Addon '{addon_id}' not found") - for entry in self._dictionary[addon_id]: - if not entry.is_compatible(): - continue - if not branch or entry.branch_display_name == branch: - return entry.addon - raise ValueError(f"Addon '{addon_id}' has no compatible branches named '{branch}'") diff --git a/src/Mod/AddonManager/AddonManager.py b/src/Mod/AddonManager/AddonManager.py deleted file mode 100644 index e84cb1a770..0000000000 --- a/src/Mod/AddonManager/AddonManager.py +++ /dev/null @@ -1,951 +0,0 @@ -#!/usr/bin/env python3 - -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * Copyright (c) 2015 Yorik van Havre * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import os -import functools -import tempfile -import threading -import json -from datetime import date -from typing import Dict - -from PySide import QtGui, QtCore, QtWidgets -import FreeCAD -import FreeCADGui - -from addonmanager_workers_startup import ( - CreateAddonListWorker, - LoadPackagesFromCacheWorker, - LoadMacrosFromCacheWorker, - CheckWorkbenchesForUpdatesWorker, - CacheMacroCodeWorker, - GetBasicAddonStatsWorker, - GetAddonScoreWorker, -) -from addonmanager_workers_installation import ( - UpdateMetadataCacheWorker, -) -from addonmanager_installer_gui import AddonInstallerGUI, MacroInstallerGUI -from addonmanager_uninstaller_gui import AddonUninstallerGUI -from addonmanager_update_all_gui import UpdateAllGUI -import addonmanager_utilities as utils -import addonmanager_freecad_interface as fci -import AddonManager_rc # pylint: disable=unused-import -from composite_view import CompositeView -from Widgets.addonmanager_widget_global_buttons import WidgetGlobalButtonBar -from Widgets.addonmanager_widget_progress_bar import Progress -from package_list import PackageListItemModel -from Addon import Addon -from addonmanager_python_deps_gui import ( - PythonPackageManager, -) -from addonmanager_cache import local_cache_needs_update -from addonmanager_devmode import DeveloperMode -from addonmanager_firstrun import FirstRunDialog -from addonmanager_connection_checker import ConnectionCheckerGUI -from addonmanager_devmode_metadata_checker import MetadataValidators - -import NetworkManager - -from AddonManagerOptions import AddonManagerOptions - -translate = FreeCAD.Qt.translate - - -def QT_TRANSLATE_NOOP(_, txt): - return txt - - -__title__ = "FreeCAD Addon Manager Module" -__author__ = "Yorik van Havre", "Jonathan Wiedemann", "Kurt Kremitzki", "Chris Hennes" -__url__ = "https://www.freecad.org" - -""" -FreeCAD Addon Manager Module - -Fetches various types of addons from a variety of sources. Built-in sources are: -* https://github.com/FreeCAD/FreeCAD-addons -* https://github.com/FreeCAD/FreeCAD-macros -* https://wiki.freecad.org/ - -Additional git sources may be configure via user preferences. - -You need a working internet connection, and optionally git -- if git is not available, ZIP archives -are downloaded instead. -""" - -# \defgroup ADDONMANAGER AddonManager -# \ingroup ADDONMANAGER -# \brief The Addon Manager allows users to install workbenches and macros made by other users -# @{ - -INSTANCE = None - - -def get_icon(repo: Addon, update: bool = False) -> QtGui.QIcon: - """Returns an icon for an Addon. Uses a cached icon if possible, unless update is True, - in which case the icon is regenerated.""" - - if not update and repo.icon and not repo.icon.isNull() and repo.icon.isValid(): - return repo.icon - - path = ":/icons/" + repo.name.replace(" ", "_") - default_icon = QtGui.QIcon(":/icons/document-package.svg") - if repo.repo_type == Addon.Kind.WORKBENCH: - path += "_workbench_icon.svg" - default_icon = QtGui.QIcon(":/icons/document-package.svg") - elif repo.repo_type == Addon.Kind.MACRO: - if repo.macro and repo.macro.icon: - if os.path.isabs(repo.macro.icon): - path = repo.macro.icon - default_icon = QtGui.QIcon(":/icons/document-python.svg") - else: - path = os.path.join(os.path.dirname(repo.macro.src_filename), repo.macro.icon) - default_icon = QtGui.QIcon(":/icons/document-python.svg") - elif repo.macro and repo.macro.xpm: - cache_path = FreeCAD.getUserCachePath() - am_path = os.path.join(cache_path, "AddonManager", "MacroIcons") - os.makedirs(am_path, exist_ok=True) - path = os.path.join(am_path, repo.name + "_icon.xpm") - if not os.path.exists(path): - with open(path, "w") as f: - f.write(repo.macro.xpm) - default_icon = QtGui.QIcon(repo.macro.xpm) - else: - path += "_macro_icon.svg" - default_icon = QtGui.QIcon(":/icons/document-python.svg") - elif repo.repo_type == Addon.Kind.PACKAGE: - # The cache might not have been downloaded yet, check to see if it's there... - if os.path.isfile(repo.get_cached_icon_filename()): - path = repo.get_cached_icon_filename() - elif repo.contains_workbench(): - path += "_workbench_icon.svg" - default_icon = QtGui.QIcon(":/icons/document-package.svg") - elif repo.contains_macro(): - path += "_macro_icon.svg" - default_icon = QtGui.QIcon(":/icons/document-python.svg") - else: - default_icon = QtGui.QIcon(":/icons/document-package.svg") - - if QtCore.QFile.exists(path): - addon_icon = QtGui.QIcon(path) - else: - addon_icon = default_icon - repo.icon = addon_icon - - return addon_icon - - -class CommandAddonManager(QtCore.QObject): - """The main Addon Manager class and FreeCAD command""" - - workers = [ - "create_addon_list_worker", - "check_worker", - "show_worker", - "showmacro_worker", - "macro_worker", - "update_metadata_cache_worker", - "load_macro_metadata_worker", - "update_all_worker", - "check_for_python_package_updates_worker", - "get_basic_addon_stats_worker", - "get_addon_score_worker", - ] - - lock = threading.Lock() - restart_required = False - - finished = QtCore.Signal() - - def __init__(self): - super().__init__() - - QT_TRANSLATE_NOOP("QObject", "Addon Manager") - FreeCADGui.addPreferencePage( - AddonManagerOptions, - "Addon Manager", - ) - - self.item_model = None - self.developer_mode = None - self.installer_gui = None - self.composite_view = None - self.button_bar = None - - self.update_cache = False - self.dialog = None - self.startup_sequence = [] - self.packages_with_updates = set() - - self.macro_repo_dir = None - self.number_of_progress_regions = 0 - self.current_progress_region = 0 - - self.check_worker = None - self.check_for_python_package_updates_worker = None - self.update_all_worker = None - self.update_metadata_cache_worker = None - self.macro_worker = None - self.create_addon_list_worker = None - self.get_addon_score_worker = None - self.get_basic_addon_stats_worker = None - self.load_macro_metadata_worker = None - - self.macro_cache = [] - self.package_cache = {} - self.manage_python_packages_dialog = None - - # Set up the connection checker - self.connection_checker = ConnectionCheckerGUI() - self.connection_checker.connection_available.connect(self.launch) - - # Give other parts of the AM access to the current instance - global INSTANCE - INSTANCE = self - - def GetResources(self) -> Dict[str, str]: - """FreeCAD-required function: get the core resource information for this Mod.""" - return { - "Pixmap": "AddonManager", - "MenuText": QT_TRANSLATE_NOOP("Std_AddonMgr", "&Addon manager"), - "ToolTip": QT_TRANSLATE_NOOP( - "Std_AddonMgr", - "Manage external workbenches, macros, and preference packs", - ), - "Group": "Tools", - } - - def Activated(self) -> None: - """FreeCAD-required function: called when the command is activated.""" - NetworkManager.InitializeNetworkManager() - first_run_dialog = FirstRunDialog() - if not first_run_dialog.exec(): - return - self.connection_checker.start() - - def launch(self) -> None: - """Shows the Addon Manager UI""" - - # create the dialog - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "AddonManager.ui") - ) - self.dialog.setObjectName("AddonManager_Main_Window") - # self.dialog.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True) - - # cleanup the leftovers from previous runs - self.macro_repo_dir = FreeCAD.getUserMacroDir(True) - self.packages_with_updates = set() - self.startup_sequence = [] - self.cleanup_workers() - self.update_cache = local_cache_needs_update() - - # restore window geometry from stored state - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - w = pref.GetInt("WindowWidth", 800) - h = pref.GetInt("WindowHeight", 600) - self.composite_view = CompositeView(self.dialog) - self.button_bar = WidgetGlobalButtonBar(self.dialog) - - # If we are checking for updates automatically, hide the Check for updates button: - autocheck = pref.GetBool("AutoCheck", True) - if autocheck: - self.button_bar.check_for_updates.hide() - else: - self.button_bar.update_all_addons.hide() - - # Set up the listing of packages using the model-view-controller architecture - self.item_model = PackageListItemModel() - self.composite_view.setModel(self.item_model) - self.dialog.layout().addWidget(self.composite_view) - self.dialog.layout().addWidget(self.button_bar) - - # set nice icons to everything, by theme with fallback to FreeCAD icons - self.dialog.setWindowIcon(QtGui.QIcon(":/icons/AddonManager.svg")) - - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - dev_mode_active = pref.GetBool("developerMode", False) - - # enable/disable stuff - self.button_bar.update_all_addons.setEnabled(False) - self.hide_progress_widgets() - self.button_bar.refresh_local_cache.setEnabled(False) - self.button_bar.refresh_local_cache.setText(translate("AddonsInstaller", "Starting up...")) - if dev_mode_active: - self.button_bar.developer_tools.show() - else: - self.button_bar.developer_tools.hide() - - # connect slots - self.dialog.rejected.connect(self.reject) - self.dialog.accepted.connect(self.accept) - self.button_bar.update_all_addons.clicked.connect(self.update_all) - self.button_bar.close.clicked.connect(self.dialog.reject) - self.button_bar.refresh_local_cache.clicked.connect(self.on_button_update_cache_clicked) - self.button_bar.check_for_updates.clicked.connect( - lambda: self.force_check_updates(standalone=True) - ) - self.button_bar.python_dependencies.clicked.connect(self.show_python_updates_dialog) - self.button_bar.developer_tools.clicked.connect(self.show_developer_tools) - self.composite_view.package_list.stop_loading.connect(self.stop_update) - self.composite_view.package_list.setEnabled(False) - self.composite_view.execute.connect(self.execute_macro) - self.composite_view.install.connect(self.launch_installer_gui) - self.composite_view.uninstall.connect(self.remove) - self.composite_view.update.connect(self.update) - self.composite_view.update_status.connect(self.status_updated) - - # center the dialog over the FreeCAD window - self.dialog.resize(w, h) - mw = FreeCADGui.getMainWindow() - self.dialog.move( - mw.frameGeometry().topLeft() + mw.rect().center() - self.dialog.rect().center() - ) - - # begin populating the table in a set of sub-threads - self.startup() - - # rock 'n roll!!! - self.dialog.exec() - - def cleanup_workers(self) -> None: - """Ensure that no workers are running by explicitly asking them to stop and waiting for - them until they do""" - for worker in self.workers: - if hasattr(self, worker): - thread = getattr(self, worker) - if thread: - if not thread.isFinished(): - thread.blockSignals(True) - thread.requestInterruption() - for worker in self.workers: - if hasattr(self, worker): - thread = getattr(self, worker) - if thread: - if not thread.isFinished(): - finished = thread.wait(500) - if not finished: - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "Worker process {} is taking a long time to stop...", - ).format(worker) - + "\n" - ) - - def accept(self) -> None: - self.finished.emit() - - def reject(self) -> None: - """called when the window has been closed""" - - # save window geometry for next use - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - pref.SetInt("WindowWidth", self.dialog.width()) - pref.SetInt("WindowHeight", self.dialog.height()) - - # ensure all threads are finished before closing - ok_to_close = True - worker_killed = False - self.startup_sequence = [] - for worker in self.workers: - if hasattr(self, worker): - thread = getattr(self, worker) - if thread: - if not thread.isFinished(): - thread.blockSignals(True) - thread.requestInterruption() - worker_killed = True - ok_to_close = False - while not ok_to_close: - ok_to_close = True - for worker in self.workers: - if hasattr(self, worker): - thread = getattr(self, worker) - if thread: - thread.wait(25) - if not thread.isFinished(): - ok_to_close = False - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - - # Write the cache data if it's safe to do so: - if not worker_killed: - for repo in self.item_model.repos: - if repo.repo_type == Addon.Kind.MACRO: - self.cache_macro(repo) - else: - self.cache_package(repo) - self.write_package_cache() - self.write_macro_cache() - else: - self.write_cache_stopfile() - FreeCAD.Console.PrintLog( - "Not writing the cache because a process was forcibly terminated and the state is " - "unknown.\n" - ) - - if self.restart_required: - # display restart dialog - m = QtWidgets.QMessageBox() - m.setWindowTitle(translate("AddonsInstaller", "Addon manager")) - m.setWindowIcon(QtGui.QIcon(":/icons/AddonManager.svg")) - m.setText( - translate( - "AddonsInstaller", - "You must restart FreeCAD for changes to take effect.", - ) - ) - m.setIcon(QtWidgets.QMessageBox.Icon.Warning) - m.setStandardButtons( - QtWidgets.QMessageBox.StandardButton.Ok - | QtWidgets.QMessageBox.StandardButton.Cancel - ) - m.setDefaultButton(QtWidgets.QMessageBox.StandardButton.Cancel) - ok_btn = m.button(QtWidgets.QMessageBox.StandardButton.Ok) - cancel_btn = m.button(QtWidgets.QMessageBox.StandardButton.Cancel) - ok_btn.setText(translate("AddonsInstaller", "Restart now")) - cancel_btn.setText(translate("AddonsInstaller", "Restart later")) - ret = m.exec_() - if ret == QtWidgets.QMessageBox.StandardButton.Ok: - # restart FreeCAD after a delay to give time to this dialog to close - QtCore.QTimer.singleShot(1000, utils.restart_freecad) - - self.finished.emit() - - def startup(self) -> None: - """Downloads the available packages listings and populates the table - - This proceeds in four stages: first, the main GitHub repository is queried for a list of - possible addons. Each addon is specified as a git submodule with name and branch - information. The actual specific commit ID of the submodule (as listed on GitHub) is - ignored. Any extra repositories specified by the user are appended to this list. - - Second, the list of macros is downloaded from the FreeCAD/FreeCAD-macros repository and - the wiki. - - Third, each of these items is queried for a package.xml metadata file. If that file exists - it is downloaded, cached, and any icons that it references are also downloaded and cached. - - Finally, for workbenches that are not contained within a package (e.g. they provide no - metadata), an additional git query is made to see if an update is available. Macros are - checked for file changes. - - Each of these stages is launched in a separate thread to ensure that the UI remains - responsive, and the operation can be cancelled. - - Each stage is also subject to caching, so may return immediately, if no cache update has - been requested.""" - - # Each function in this list is expected to launch a thread and connect its completion - # signal to self.do_next_startup_phase, or to shortcut to calling - # self.do_next_startup_phase if it is not launching a worker - self.startup_sequence = [ - self.populate_packages_table, - self.activate_table_widgets, - self.populate_macros, - self.update_metadata_cache, - self.check_updates, - self.check_python_updates, - self.fetch_addon_stats, - self.fetch_addon_score, - self.select_addon, - ] - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - if pref.GetBool("DownloadMacros", True): - self.startup_sequence.append(self.load_macro_metadata) - self.number_of_progress_regions = len(self.startup_sequence) - self.current_progress_region = 0 - self.do_next_startup_phase() - - def do_next_startup_phase(self) -> None: - """Pop the top item in self.startup_sequence off the list and run it""" - - if len(self.startup_sequence) > 0: - phase_runner = self.startup_sequence.pop(0) - self.current_progress_region += 1 - phase_runner() - else: - self.hide_progress_widgets() - self.update_cache = False - self.button_bar.refresh_local_cache.setEnabled(True) - self.button_bar.refresh_local_cache.setText( - translate("AddonsInstaller", "Refresh local cache") - ) - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - pref.SetString("LastCacheUpdate", date.today().isoformat()) - self.composite_view.package_list.item_filter.invalidateFilter() - - def populate_packages_table(self) -> None: - self.item_model.clear() - - use_cache = not self.update_cache - if use_cache: - if os.path.isfile(utils.get_cache_file_name("package_cache.json")): - with open(utils.get_cache_file_name("package_cache.json"), encoding="utf-8") as f: - data = f.read() - try: - from_json = json.loads(data) - if len(from_json) == 0: - use_cache = False - except json.JSONDecodeError: - use_cache = False - else: - use_cache = False - - if not use_cache: - self.update_cache = True # Make sure to trigger the other cache updates, if the json - # file was missing - self.create_addon_list_worker = CreateAddonListWorker() - self.create_addon_list_worker.addon_repo.connect(self.add_addon_repo) - self.update_progress_bar(translate("AddonsInstaller", "Creating addon list"), 10, 100) - self.create_addon_list_worker.finished.connect( - self.do_next_startup_phase - ) # Link to step 2 - self.create_addon_list_worker.start() - else: - self.create_addon_list_worker = LoadPackagesFromCacheWorker( - utils.get_cache_file_name("package_cache.json") - ) - self.create_addon_list_worker.addon_repo.connect(self.add_addon_repo) - self.update_progress_bar(translate("AddonsInstaller", "Loading addon list"), 10, 100) - self.create_addon_list_worker.finished.connect( - self.do_next_startup_phase - ) # Link to step 2 - self.create_addon_list_worker.start() - - def cache_package(self, repo: Addon): - if not hasattr(self, "package_cache"): - self.package_cache = {} - self.package_cache[repo.name] = repo.to_cache() - - def write_package_cache(self): - if hasattr(self, "package_cache"): - package_cache_path = utils.get_cache_file_name("package_cache.json") - with open(package_cache_path, "w", encoding="utf-8") as f: - f.write(json.dumps(self.package_cache, indent=" ")) - - def activate_table_widgets(self) -> None: - self.composite_view.package_list.setEnabled(True) - self.composite_view.package_list.ui.view_bar.search.setFocus() - self.do_next_startup_phase() - - def populate_macros(self) -> None: - macro_cache_file = utils.get_cache_file_name("macro_cache.json") - cache_is_bad = True - if os.path.isfile(macro_cache_file): - size = os.path.getsize(macro_cache_file) - if size > 1000: # Make sure there is actually data in there - cache_is_bad = False - if cache_is_bad: - if not self.update_cache: - self.update_cache = True # Make sure to trigger the other cache updates, if the - # json file was missing - self.create_addon_list_worker = CreateAddonListWorker() - self.create_addon_list_worker.addon_repo.connect(self.add_addon_repo) - self.update_progress_bar( - translate("AddonsInstaller", "Creating macro list"), 10, 100 - ) - self.create_addon_list_worker.finished.connect( - self.do_next_startup_phase - ) # Link to step 2 - self.create_addon_list_worker.start() - else: - # It's already been done in the previous step (TODO: Refactor to eliminate this - # step) - self.do_next_startup_phase() - else: - self.macro_worker = LoadMacrosFromCacheWorker( - utils.get_cache_file_name("macro_cache.json") - ) - self.macro_worker.add_macro_signal.connect(self.add_addon_repo) - self.macro_worker.finished.connect(self.do_next_startup_phase) - self.macro_worker.start() - - def cache_macro(self, repo: Addon): - if not hasattr(self, "macro_cache"): - self.macro_cache = [] - if repo.macro is not None: - self.macro_cache.append(repo.macro.to_cache()) - else: - FreeCAD.Console.PrintError( - f"Addon Manager: Internal error, cache_macro called on non-macro {repo.name}\n" - ) - - def write_macro_cache(self): - if not hasattr(self, "macro_cache"): - return - macro_cache_path = utils.get_cache_file_name("macro_cache.json") - with open(macro_cache_path, "w", encoding="utf-8") as f: - f.write(json.dumps(self.macro_cache, indent=" ")) - self.macro_cache = [] - - def update_metadata_cache(self) -> None: - if self.update_cache: - self.update_metadata_cache_worker = UpdateMetadataCacheWorker(self.item_model.repos) - self.update_metadata_cache_worker.finished.connect( - self.do_next_startup_phase - ) # Link to step 4 - self.update_metadata_cache_worker.progress_made.connect(self.update_progress_bar) - self.update_metadata_cache_worker.package_updated.connect(self.on_package_updated) - self.update_metadata_cache_worker.start() - else: - self.do_next_startup_phase() - - def on_button_update_cache_clicked(self) -> None: - self.update_cache = True - cache_path = FreeCAD.getUserCachePath() - am_path = os.path.join(cache_path, "AddonManager") - utils.rmdir(am_path) - self.button_bar.refresh_local_cache.setEnabled(False) - self.button_bar.refresh_local_cache.setText( - translate("AddonsInstaller", "Updating cache...") - ) - self.startup() - - # Re-caching implies checking for updates, regardless of the user's autocheck option - if self.check_updates in self.startup_sequence: - self.startup_sequence.remove(self.check_updates) - self.startup_sequence.append(self.force_check_updates) - - def on_package_updated(self, repo: Addon) -> None: - """Called when the named package has either new metadata or a new icon (or both)""" - - with self.lock: - repo.icon = get_icon(repo, update=True) - self.item_model.reload_item(repo) - - def load_macro_metadata(self) -> None: - if self.update_cache: - self.load_macro_metadata_worker = CacheMacroCodeWorker(self.item_model.repos) - self.load_macro_metadata_worker.update_macro.connect(self.on_package_updated) - self.load_macro_metadata_worker.progress_made.connect(self.update_progress_bar) - self.load_macro_metadata_worker.finished.connect(self.do_next_startup_phase) - self.load_macro_metadata_worker.start() - else: - self.do_next_startup_phase() - - def select_addon(self) -> None: - prefs = fci.Preferences() - selection = prefs.get("SelectedAddon") - if selection: - self.composite_view.package_list.select_addon(selection) - prefs.set("SelectedAddon", "") - self.do_next_startup_phase() - - def check_updates(self) -> None: - """checks every installed addon for available updates""" - - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - autocheck = pref.GetBool("AutoCheck", True) - if not autocheck: - FreeCAD.Console.PrintLog( - "Addon Manager: Skipping update check because AutoCheck user preference is False\n" - ) - self.do_next_startup_phase() - return - if not self.packages_with_updates: - self.force_check_updates(standalone=False) - else: - self.do_next_startup_phase() - - def force_check_updates(self, standalone=False) -> None: - if hasattr(self, "check_worker"): - thread = self.check_worker - if thread: - if not thread.isFinished(): - self.do_next_startup_phase() - return - - self.button_bar.update_all_addons.setText( - translate("AddonsInstaller", "Checking for updates...") - ) - self.packages_with_updates.clear() - self.button_bar.update_all_addons.show() - self.button_bar.check_for_updates.setDisabled(True) - self.check_worker = CheckWorkbenchesForUpdatesWorker(self.item_model.repos) - self.check_worker.finished.connect(self.do_next_startup_phase) - self.check_worker.finished.connect(self.update_check_complete) - self.check_worker.progress_made.connect(self.update_progress_bar) - if standalone: - self.current_progress_region = 1 - self.number_of_progress_regions = 1 - self.check_worker.update_status.connect(self.status_updated) - self.check_worker.start() - self.enable_updates(len(self.packages_with_updates)) - - def status_updated(self, repo: Addon) -> None: - self.item_model.reload_item(repo) - if repo.status() == Addon.Status.UPDATE_AVAILABLE: - self.packages_with_updates.add(repo) - self.enable_updates(len(self.packages_with_updates)) - elif repo.status() == Addon.Status.PENDING_RESTART: - self.restart_required = True - - def enable_updates(self, number_of_updates: int) -> None: - """enables the update button""" - - if number_of_updates: - self.button_bar.set_number_of_available_updates(number_of_updates) - elif ( - hasattr(self, "check_worker") - and self.check_worker is not None - and self.check_worker.isRunning() - ): - self.button_bar.update_all_addons.setText( - translate("AddonsInstaller", "Checking for updates...") - ) - else: - self.button_bar.set_number_of_available_updates(0) - - def update_check_complete(self) -> None: - self.enable_updates(len(self.packages_with_updates)) - self.button_bar.check_for_updates.setEnabled(True) - - def check_python_updates(self) -> None: - PythonPackageManager.migrate_old_am_installations() # Migrate 0.20 to 0.21 - self.do_next_startup_phase() - - def show_python_updates_dialog(self) -> None: - if not self.manage_python_packages_dialog: - self.manage_python_packages_dialog = PythonPackageManager(self.item_model.repos) - self.manage_python_packages_dialog.show() - - def fetch_addon_stats(self) -> None: - """Fetch the Addon Stats JSON data from a URL""" - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - url = pref.GetString("AddonsStatsURL", "https://freecad.org/addon_stats.json") - if url and url != "NONE": - self.get_basic_addon_stats_worker = GetBasicAddonStatsWorker( - url, self.item_model.repos, self.dialog - ) - self.get_basic_addon_stats_worker.finished.connect(self.do_next_startup_phase) - self.get_basic_addon_stats_worker.update_addon_stats.connect(self.update_addon_stats) - self.get_basic_addon_stats_worker.start() - else: - self.do_next_startup_phase() - - def update_addon_stats(self, addon: Addon): - self.item_model.reload_item(addon) - - def fetch_addon_score(self) -> None: - """Fetch the Addon score JSON data from a URL""" - prefs = fci.Preferences() - url = prefs.get("AddonsScoreURL") - if url and url != "NONE": - self.get_addon_score_worker = GetAddonScoreWorker( - url, self.item_model.repos, self.dialog - ) - self.get_addon_score_worker.finished.connect(self.score_fetched_successfully) - self.get_addon_score_worker.finished.connect(self.do_next_startup_phase) - self.get_addon_score_worker.update_addon_score.connect(self.update_addon_score) - self.get_addon_score_worker.start() - else: - self.composite_view.package_list.ui.view_bar.set_rankings_available(False) - self.do_next_startup_phase() - - def update_addon_score(self, addon: Addon): - self.item_model.reload_item(addon) - - def score_fetched_successfully(self): - self.composite_view.package_list.ui.view_bar.set_rankings_available(True) - - def show_developer_tools(self) -> None: - """Display the developer tools dialog""" - if not self.developer_mode: - self.developer_mode = DeveloperMode() - self.developer_mode.show() - - checker = MetadataValidators() - checker.validate_all(self.item_model.repos) - - def add_addon_repo(self, addon_repo: Addon) -> None: - """adds a workbench to the list""" - - if addon_repo.icon is None or addon_repo.icon.isNull(): - addon_repo.icon = get_icon(addon_repo) - for repo in self.item_model.repos: - if repo.name == addon_repo.name: - # self.item_model.reload_item(repo) # If we want to have later additions superseded - # earlier - return - self.item_model.append_item(addon_repo) - - def append_to_repos_list(self, repo: Addon) -> None: - """this function allows threads to update the main list of workbenches""" - self.item_model.append_item(repo) - - def update(self, repo: Addon) -> None: - self.launch_installer_gui(repo) - - def mark_repo_update_available(self, repo: Addon, available: bool) -> None: - if available: - repo.set_status(Addon.Status.UPDATE_AVAILABLE) - else: - repo.set_status(Addon.Status.NO_UPDATE_AVAILABLE) - self.item_model.reload_item(repo) - self.composite_view.package_details_controller.show_repo(repo) - - def launch_installer_gui(self, addon: Addon) -> None: - if self.installer_gui is not None: - FreeCAD.Console.PrintError( - translate( - "AddonsInstaller", - "Cannot launch a new installer until the previous one has finished.", - ) - ) - return - if addon.macro is not None: - self.installer_gui = MacroInstallerGUI(addon) - else: - self.installer_gui = AddonInstallerGUI(addon, self.item_model.repos) - self.installer_gui.success.connect(self.on_package_status_changed) - self.installer_gui.finished.connect(self.cleanup_installer) - self.installer_gui.run() # Does not block - - def cleanup_installer(self) -> None: - QtCore.QTimer.singleShot(500, self.no_really_clean_up_the_installer) - - def no_really_clean_up_the_installer(self) -> None: - self.installer_gui = None - - def update_all(self) -> None: - """Asynchronously apply all available updates: individual failures are noted, but do not - stop other updates""" - - if self.installer_gui is not None: - FreeCAD.Console.PrintError( - translate( - "AddonsInstaller", - "Cannot launch a new installer until the previous one has finished.", - ) - ) - return - - self.installer_gui = UpdateAllGUI(self.item_model.repos) - self.installer_gui.addon_updated.connect(self.on_package_status_changed) - self.installer_gui.finished.connect(self.cleanup_installer) - self.installer_gui.run() # Does not block - - def hide_progress_widgets(self) -> None: - """hides the progress bar and related widgets""" - self.composite_view.package_list.set_loading(False) - - def show_progress_widgets(self) -> None: - self.composite_view.package_list.set_loading(True) - - def update_progress_bar(self, message: str, current_value: int, max_value: int) -> None: - """Update the progress bar, showing it if it's hidden""" - - max_value = max_value if max_value > 0 else 1 - - if current_value < 0: - current_value = 0 - elif current_value > max_value: - current_value = max_value - - self.show_progress_widgets() - - progress = Progress( - status_text=message, - number_of_tasks=self.number_of_progress_regions, - current_task=self.current_progress_region - 1, - current_task_progress=current_value / max_value, - ) - self.composite_view.package_list.update_loading_progress(progress) - - def stop_update(self) -> None: - self.cleanup_workers() - self.hide_progress_widgets() - self.write_cache_stopfile() - self.button_bar.refresh_local_cache.setEnabled(True) - self.button_bar.refresh_local_cache.setText( - translate("AddonsInstaller", "Refresh local cache") - ) - - @staticmethod - def write_cache_stopfile() -> None: - stopfile = utils.get_cache_file_name("CACHE_UPDATE_INTERRUPTED") - with open(stopfile, "w", encoding="utf8") as f: - f.write( - "This file indicates that a cache operation was interrupted, and " - "the cache is in an unknown state. It will be deleted next time " - "AddonManager re-caches." - ) - - def on_package_status_changed(self, repo: Addon) -> None: - if repo.status() == Addon.Status.PENDING_RESTART: - self.restart_required = True - self.item_model.reload_item(repo) - self.composite_view.package_details_controller.show_repo(repo) - if repo in self.packages_with_updates: - self.packages_with_updates.remove(repo) - self.enable_updates(len(self.packages_with_updates)) - - def execute_macro(self, repo: Addon) -> None: - """executes a selected macro""" - - macro = repo.macro - if not macro or not macro.code: - return - - if macro.is_installed(): - macro_path = os.path.join(self.macro_repo_dir, macro.filename) - FreeCADGui.open(str(macro_path)) - self.dialog.hide() - FreeCADGui.SendMsgToActiveView("Run") - else: - with tempfile.TemporaryDirectory() as temp_dir: - temp_install_succeeded = macro.install(temp_dir) - if not temp_install_succeeded: - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "Temporary installation of macro failed.") - ) - return - macro_path = os.path.join(temp_dir, macro.filename) - FreeCADGui.open(str(macro_path)) - self.dialog.hide() - FreeCADGui.SendMsgToActiveView("Run") - - def remove(self, addon: Addon) -> None: - """Remove this addon.""" - if self.installer_gui is not None: - FreeCAD.Console.PrintError( - translate( - "AddonsInstaller", - "Cannot launch a new installer until the previous one has finished.", - ) - ) - return - self.installer_gui = AddonUninstallerGUI(addon) - self.installer_gui.finished.connect(self.cleanup_installer) - self.installer_gui.finished.connect( - functools.partial(self.on_package_status_changed, addon) - ) - self.installer_gui.run() # Does not block - - -# @} diff --git a/src/Mod/AddonManager/AddonManager.ui b/src/Mod/AddonManager/AddonManager.ui deleted file mode 100644 index b2d31fcb15..0000000000 --- a/src/Mod/AddonManager/AddonManager.ui +++ /dev/null @@ -1,20 +0,0 @@ - - - Dialog - - - - 0 - 0 - 928 - 600 - - - - Addon Manager - - - - - - diff --git a/src/Mod/AddonManager/AddonManagerOptions.py b/src/Mod/AddonManager/AddonManagerOptions.py deleted file mode 100644 index 783f1a733a..0000000000 --- a/src/Mod/AddonManager/AddonManagerOptions.py +++ /dev/null @@ -1,314 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains a the Addon Manager's preferences dialog management class""" - -import os - -import FreeCAD -import FreeCADGui - -from PySide import QtCore -from PySide.QtGui import QIcon -from PySide.QtWidgets import ( - QWidget, - QCheckBox, - QComboBox, - QDialog, - QHeaderView, - QRadioButton, - QLineEdit, - QTextEdit, -) - -translate = FreeCAD.Qt.translate - -# pylint: disable=too-few-public-methods - - -class AddonManagerOptions: - """A class containing a form element that is inserted as a FreeCAD preference page.""" - - def __init__(self, _=None): - self.form = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "AddonManagerOptions.ui") - ) - self.table_model = CustomRepoDataModel() - self.form.customRepositoriesTableView.setModel(self.table_model) - - self.form.addCustomRepositoryButton.setIcon( - QIcon.fromTheme("add", QIcon(":/icons/list-add.svg")) - ) - self.form.removeCustomRepositoryButton.setIcon( - QIcon.fromTheme("remove", QIcon(":/icons/list-remove.svg")) - ) - - self.form.customRepositoriesTableView.horizontalHeader().setStretchLastSection(False) - self.form.customRepositoriesTableView.horizontalHeader().setSectionResizeMode( - 0, QHeaderView.Stretch - ) - self.form.customRepositoriesTableView.horizontalHeader().setSectionResizeMode( - 1, QHeaderView.ResizeToContents - ) - - self.form.addCustomRepositoryButton.clicked.connect(self._add_custom_repo_clicked) - self.form.removeCustomRepositoryButton.clicked.connect(self._remove_custom_repo_clicked) - self.form.customRepositoriesTableView.doubleClicked.connect(self._row_double_clicked) - - def saveSettings(self): - """Required function: called by the preferences dialog when Apply or Save is clicked, - saves out the preference data by reading it from the widgets.""" - for widget in self.form.children(): - self.recursive_widget_saver(widget) - self.table_model.save_model() - - def recursive_widget_saver(self, widget): - """Writes out the data for this widget and all of its children, recursively.""" - if isinstance(widget, QWidget): - # See if it's one of ours: - pref_path = widget.property("prefPath") - pref_entry = widget.property("prefEntry") - if pref_path and pref_entry: - pref_path = pref_path.data() - pref_entry = pref_entry.data() - pref_access_string = f"User parameter:BaseApp/Preferences/{str(pref_path,'utf-8')}" - pref = FreeCAD.ParamGet(pref_access_string) - if isinstance(widget, QCheckBox): - checked = widget.isChecked() - pref.SetBool(str(pref_entry, "utf-8"), checked) - elif isinstance(widget, QRadioButton): - checked = widget.isChecked() - pref.SetBool(str(pref_entry, "utf-8"), checked) - elif isinstance(widget, QComboBox): - new_index = widget.currentIndex() - pref.SetInt(str(pref_entry, "utf-8"), new_index) - elif isinstance(widget, QTextEdit): - text = widget.toPlainText() - pref.SetString(str(pref_entry, "utf-8"), text) - elif isinstance(widget, QLineEdit): - text = widget.text() - pref.SetString(str(pref_entry, "utf-8"), text) - elif widget.metaObject().className() == "Gui::PrefFileChooser": - filename = str(widget.property("fileName")) - filename = pref.SetString(str(pref_entry, "utf-8"), filename) - - # Recurse over children - if isinstance(widget, QtCore.QObject): - for child in widget.children(): - self.recursive_widget_saver(child) - - def loadSettings(self): - """Required function: called by the preferences dialog when it is launched, - loads the preference data and assigns it to the widgets.""" - for widget in self.form.children(): - self.recursive_widget_loader(widget) - self.table_model.load_model() - - def recursive_widget_loader(self, widget): - """Loads the data for this widget and all of its children, recursively.""" - if isinstance(widget, QWidget): - # See if it's one of ours: - pref_path = widget.property("prefPath") - pref_entry = widget.property("prefEntry") - if pref_path and pref_entry: - pref_path = pref_path.data() - pref_entry = pref_entry.data() - pref_access_string = f"User parameter:BaseApp/Preferences/{str(pref_path,'utf-8')}" - pref = FreeCAD.ParamGet(pref_access_string) - if isinstance(widget, QCheckBox): - widget.setChecked(pref.GetBool(str(pref_entry, "utf-8"))) - elif isinstance(widget, QRadioButton): - if pref.GetBool(str(pref_entry, "utf-8")): - widget.setChecked(True) - elif isinstance(widget, QComboBox): - new_index = pref.GetInt(str(pref_entry, "utf-8")) - widget.setCurrentIndex(new_index) - elif isinstance(widget, QTextEdit): - text = pref.GetString(str(pref_entry, "utf-8")) - widget.setText(text) - elif isinstance(widget, QLineEdit): - text = pref.GetString(str(pref_entry, "utf-8")) - widget.setText(text) - elif widget.metaObject().className() == "Gui::PrefFileChooser": - filename = pref.GetString(str(pref_entry, "utf-8")) - widget.setProperty("fileName", filename) - - # Recurse over children - if isinstance(widget, QtCore.QObject): - for child in widget.children(): - self.recursive_widget_loader(child) - - def _add_custom_repo_clicked(self): - """Callback: show the Add custom repo dialog""" - dlg = CustomRepositoryDialog() - url, branch = dlg.exec() - if url and branch: - self.table_model.appendData(url, branch) - - def _remove_custom_repo_clicked(self): - """Callback: when the remove button is clicked, get the current selection and remove it.""" - item = self.form.customRepositoriesTableView.currentIndex() - if not item.isValid(): - return - row = item.row() - self.table_model.removeRows(row, 1, QtCore.QModelIndex()) - - def _row_double_clicked(self, item): - """Edit the row that was double-clicked""" - row = item.row() - dlg = CustomRepositoryDialog() - url_index = self.table_model.createIndex(row, 0) - branch_index = self.table_model.createIndex(row, 1) - dlg.dialog.urlLineEdit.setText(self.table_model.data(url_index)) - dlg.dialog.branchLineEdit.setText(self.table_model.data(branch_index)) - url, branch = dlg.exec() - if url and branch: - self.table_model.setData(url_index, url) - self.table_model.setData(branch_index, branch) - - -class CustomRepoDataModel(QtCore.QAbstractTableModel): - """The model for the custom repositories: wraps the underlying preference data and uses that - as its main data store.""" - - def __init__(self): - super().__init__() - pref_access_string = "User parameter:BaseApp/Preferences/Addons" - self.pref = FreeCAD.ParamGet(pref_access_string) - self.load_model() - - def load_model(self): - """Load the data from the preferences entry""" - pref_entry: str = self.pref.GetString("CustomRepositories", "") - - # The entry is saved as a space- and newline-delimited text block: break it into its - # constituent parts - lines = pref_entry.split("\n") - self.model = [] - for line in lines: - if not line: - continue - split_data = line.split() - if len(split_data) > 1: - branch = split_data[1] - else: - branch = "master" - url = split_data[0] - self.model.append([url, branch]) - - def save_model(self): - """Save the data into a preferences entry""" - entry = "" - for row in self.model: - entry += f"{row[0]} {row[1]}\n" - self.pref.SetString("CustomRepositories", entry) - - def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: - """The number of rows""" - if parent.isValid(): - return 0 - return len(self.model) - - def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: - """The number of columns (which is always 2)""" - if parent.isValid(): - return 0 - return 2 - - def data(self, index, role=QtCore.Qt.DisplayRole): - """The data at an index.""" - if role != QtCore.Qt.DisplayRole: - return None - row = index.row() - column = index.column() - if row > len(self.model): - return None - if column > 1: - return None - return self.model[row][column] - - def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): - """Get the row and column header data.""" - if role != QtCore.Qt.DisplayRole: - return None - if orientation == QtCore.Qt.Vertical: - return section + 1 - if section == 0: - return translate( - "AddonsInstaller", - "Repository URL", - "Preferences header for custom repositories", - ) - if section == 1: - return translate( - "AddonsInstaller", - "Branch name", - "Preferences header for custom repositories", - ) - return None - - def removeRows(self, row, count, parent): - """Remove rows""" - self.beginRemoveRows(parent, row, row + count - 1) - for _ in range(count): - self.model.pop(row) - self.endRemoveRows() - - def insertRows(self, row, count, parent): - """Insert blank rows""" - self.beginInsertRows(parent, row, row + count - 1) - for _ in range(count): - self.model.insert(["", ""]) - self.endInsertRows() - - def appendData(self, url, branch): - """Append this url and branch to the end of the list""" - row = self.rowCount() - self.beginInsertRows(QtCore.QModelIndex(), row, row) - self.model.append([url, branch]) - self.endInsertRows() - - def setData(self, index, value, role=QtCore.Qt.EditRole): - """Set the data at this index""" - if role != QtCore.Qt.EditRole: - return - self.model[index.row()][index.column()] = value - self.dataChanged.emit(index, index) - - -class CustomRepositoryDialog: - """A dialog for setting up a custom repository, with branch information""" - - def __init__(self): - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "AddonManagerOptions_AddCustomRepository.ui") - ) - - def exec(self): - """Run the dialog modally, and return either None or a tuple or (url,branch)""" - result = self.dialog.exec() - if result == QDialog.Accepted: - url = self.dialog.urlLineEdit.text() - branch = self.dialog.branchLineEdit.text() - return (url, branch) - return (None, None) diff --git a/src/Mod/AddonManager/AddonManagerOptions.ui b/src/Mod/AddonManager/AddonManagerOptions.ui deleted file mode 100644 index 8c9869e5e3..0000000000 --- a/src/Mod/AddonManager/AddonManagerOptions.ui +++ /dev/null @@ -1,482 +0,0 @@ - - - Gui::Dialog::DlgSettingsAddonManager - - - - 0 - 0 - 757 - 783 - - - - Addon manager options - - - - 0 - - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - Automatically check for updates at start (requires Git) - - - false - - - AutoCheck - - - Addons - - - - - - - Download Macro metadata (approximately 10MB) - - - DownloadMacros - - - Addons - - - - - - - - - Cache update frequency - - - - - - - - 0 - 0 - - - - UpdateFrequencyComboEntry - - - Addons - - - - Manual (no automatic updates) - - - - - Daily - - - - - Weekly - - - - - - - - - - Hide Addons without a license - - - true - - - HideUnlicensed - - - Addons - - - - - - - Hide Addons with non-FSF Free/Libre license - - - false - - - HideNonFSFFreeLibre - - - Addons - - - - - - - Hide Addons with non-OSI-approved license - - - true - - - HideNonOSIApproved - - - Addons - - - - - - - Hide Addons marked Python 2 Only - - - true - - - HidePy2 - - - Addons - - - - - - - Hide Addons marked Obsolete - - - true - - - HideObsolete - - - Addons - - - - - - - Hide Addons that require a newer version of FreeCAD - - - true - - - Addons - - - HideNewerFreeCADRequired - - - - - - - - 75 - true - - - - Custom repositories - - - - - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - false - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - ... - - - - - - - ... - - - - - - - - - Proxy - - - - - - No proxy - - - true - - - NoProxyCheck - - - Addons - - - - - - - User system proxy - - - SystemProxyCheck - - - Addons - - - - - - - User-defined proxy: - - - false - - - UserProxyCheck - - - Addons - - - - - - - ProxyUrl - - - Addons - - - - - - - - - - - - Score source URL - - - - - - - - 0 - 0 - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - AddonsScoreURL - - - Addons - - - - - - - - - - - Path to Git executable (optional): - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - The path to the Git executable. Autodetected if needed and not specified. - - - GitExecutable - - - Addons - - - - - - - - - - 0 - 0 - - - - Advanced Options - - - - - - Show option to change branches (requires Git) - - - ShowBranchSwitcher - - - Addons - - - - - - - Disable Git (fall back to ZIP downloads only) - - - disableGit - - - Addons - - - - - - - Activate Addon Manager options intended for developers of new Addons. - - - Addon developer mode - - - Addons - - - developerMode - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Gui::PrefCheckBox - QCheckBox -
    Gui/PrefWidgets.h
    -
    - - Gui::PrefComboBox - QComboBox -
    Gui/PrefWidgets.h
    -
    - - Gui::PrefRadioButton - QRadioButton -
    Gui/PrefWidgets.h
    -
    - - Gui::PrefLineEdit - QLineEdit -
    Gui/PrefWidgets.h
    -
    - - Gui::PrefFileChooser - QWidget -
    Gui/PrefWidgets.h
    -
    -
    - - -
    diff --git a/src/Mod/AddonManager/AddonManagerOptions_AddCustomRepository.ui b/src/Mod/AddonManager/AddonManagerOptions_AddCustomRepository.ui deleted file mode 100644 index 17d9190b49..0000000000 --- a/src/Mod/AddonManager/AddonManagerOptions_AddCustomRepository.ui +++ /dev/null @@ -1,84 +0,0 @@ - - - AddCustomRepositoryDialog - - - - 0 - 0 - 400 - 95 - - - - Custom repository - - - - - - Repository URL - - - - - - - - - - Branch - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - buttonBox - accepted() - AddCustomRepositoryDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AddCustomRepositoryDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/__init__.py b/src/Mod/AddonManager/AddonManagerTest/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Mod/AddonManager/AddonManagerTest/app/__init__.py b/src/Mod/AddonManager/AddonManagerTest/app/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Mod/AddonManager/AddonManagerTest/app/mocks.py b/src/Mod/AddonManager/AddonManagerTest/app/mocks.py deleted file mode 100644 index 3e94f7e161..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/mocks.py +++ /dev/null @@ -1,463 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Mock objects for use when testing the addon manager non-GUI code.""" - -# pylint: disable=too-few-public-methods,too-many-instance-attributes,missing-function-docstring - -import os -from typing import Union, List -import xml.etree.ElementTree as ElemTree - - -class GitFailed(RuntimeError): - pass - - -class MockConsole: - """Spy for the FreeCAD.Console -- does NOT print anything out, just logs it.""" - - def __init__(self): - self.log = [] - self.messages = [] - self.warnings = [] - self.errors = [] - - def PrintLog(self, data: str): - self.log.append(data) - - def PrintMessage(self, data: str): - self.messages.append(data) - - def PrintWarning(self, data: str): - self.warnings.append(data) - - def PrintError(self, data: str): - self.errors.append(data) - - def missing_newlines(self) -> int: - """In most cases, all console entries should end with newlines: this is a - convenience function for unit testing that is true.""" - counter = 0 - counter += self._count_missing_newlines(self.log) - counter += self._count_missing_newlines(self.messages) - counter += self._count_missing_newlines(self.warnings) - counter += self._count_missing_newlines(self.errors) - return counter - - @staticmethod - def _count_missing_newlines(some_list) -> int: - counter = 0 - for line in some_list: - if line[-1] != "\n": - counter += 1 - return counter - - -class MockAddon: - """Minimal Addon class""" - - # pylint: disable=too-many-instance-attributes - - def __init__( - self, - name: str = None, - url: str = None, - status: object = None, - branch: str = "main", - ): - test_dir = os.path.join(os.path.dirname(__file__), "..", "data") - if name: - self.name = name - self.display_name = name - else: - self.name = "MockAddon" - self.display_name = "Mock Addon" - self.url = url if url else os.path.join(test_dir, "test_simple_repo.zip") - self.branch = branch - self.status = status - self.macro = None - self.update_status = None - self.metadata = None - self.icon_file = None - self.last_updated = None - self.requires = set() - self.python_requires = set() - self.python_optional = set() - self.on_git = False - self.on_wiki = True - - def set_status(self, status): - self.update_status = status - - @staticmethod - def get_best_icon_relative_path(): - return "" - - -class MockMacro: - """Minimal Macro class""" - - def __init__(self, name="MockMacro"): - self.name = name - self.filename = self.name + ".FCMacro" - self.icon = "" # If set, should just be fake filename, doesn't have to exist - self.xpm = "" - self.code = "" - self.raw_code_url = "" - self.other_files = [] # If set, should be fake names, don't have to exist - self.details_filled_from_file = False - self.details_filled_from_code = False - self.parsed_wiki_page = False - self.on_git = False - self.on_wiki = True - - def install(self, location: os.PathLike): - """Installer function for the mock macro object: creates a file with the src_filename - attribute, and optionally an icon, xpm, and other_files. The data contained in these files - is not usable and serves only as a placeholder for the existence of the files. - """ - - with open( - os.path.join(location, self.filename), - "w", - encoding="utf-8", - ) as f: - f.write("Test file for macro installation unit tests") - if self.icon: - with open(os.path.join(location, self.icon), "wb") as f: - f.write(b"Fake icon data - nothing to see here\n") - if self.xpm: - with open(os.path.join(location, "MockMacro_icon.xpm"), "w", encoding="utf-8") as f: - f.write(self.xpm) - for name in self.other_files: - if "/" in name: - new_location = os.path.dirname(os.path.join(location, name)) - os.makedirs(new_location, exist_ok=True) - with open(os.path.join(location, name), "w", encoding="utf-8") as f: - f.write("# Fake macro data for unit testing\n") - return True, [] - - def fill_details_from_file(self, _): - """Tracks that this function was called, but otherwise does nothing""" - self.details_filled_from_file = True - - def fill_details_from_code(self, _): - self.details_filled_from_code = True - - def parse_wiki_page(self, _): - self.parsed_wiki_page = True - - -class SignalCatcher: - """Object to track signals that it has caught. - - Usage: - catcher = SignalCatcher() - my_signal.connect(catcher.catch_signal) - do_things_that_emit_the_signal() - self.assertTrue(catcher.caught) - """ - - def __init__(self): - self.caught = False - self.killed = False - self.args = None - - def catch_signal(self, *args): - self.caught = True - self.args = args - - def die(self): - self.killed = True - - -class AddonSignalCatcher: - """Signal catcher specifically designed for catching emitted addons.""" - - def __init__(self): - self.addons = [] - - def catch_signal(self, addon): - self.addons.append(addon) - - -class CallCatcher: - """Generic call monitor -- use to override functions that are not themselves under - test so that you can detect when the function has been called, and how many times. - """ - - def __init__(self): - self.called = False - self.call_count = 0 - self.args = None - - def catch_call(self, *args): - self.called = True - self.call_count += 1 - self.args = args - - -class MockGitManager: - """A mock git manager: does NOT require a git installation. Takes no actions, only records - which functions are called for instrumentation purposes. Can be forced to appear to fail as - needed. Various member variables can be set to emulate necessary return responses. - """ - - def __init__(self): - self.called_methods = [] - self.update_available_response = False - self.current_tag_response = "main" - self.current_branch_response = "main" - self.get_remote_response = "No remote set" - self.get_branches_response = ["main"] - self.get_last_committers_response = {"John Doe": {"email": "jdoe@freecad.org", "count": 1}} - self.get_last_authors_response = {"Jane Doe": {"email": "jdoe@freecad.org", "count": 1}} - self.should_fail = False - self.fail_once = False # Switch back to success after the simulated failure - - def _check_for_failure(self): - if self.should_fail: - if self.fail_once: - self.should_fail = False - raise GitFailed("Unit test forced failure") - - def clone(self, _remote, _local_path, _args: List[str] = None): - self.called_methods.append("clone") - self._check_for_failure() - - def async_clone(self, _remote, _local_path, _progress_monitor, _args: List[str] = None): - self.called_methods.append("async_clone") - self._check_for_failure() - - def checkout(self, _local_path, _spec, _args: List[str] = None): - self.called_methods.append("checkout") - self._check_for_failure() - - def update(self, _local_path): - self.called_methods.append("update") - self._check_for_failure() - - def status(self, _local_path) -> str: - self.called_methods.append("status") - self._check_for_failure() - return "Up-to-date" - - def reset(self, _local_path, _args: List[str] = None): - self.called_methods.append("reset") - self._check_for_failure() - - def async_fetch_and_update(self, _local_path, _progress_monitor, _args=None): - self.called_methods.append("async_fetch_and_update") - self._check_for_failure() - - def update_available(self, _local_path) -> bool: - self.called_methods.append("update_available") - self._check_for_failure() - return self.update_available_response - - def current_tag(self, _local_path) -> str: - self.called_methods.append("current_tag") - self._check_for_failure() - return self.current_tag_response - - def current_branch(self, _local_path) -> str: - self.called_methods.append("current_branch") - self._check_for_failure() - return self.current_branch_response - - def repair(self, _remote, _local_path): - self.called_methods.append("repair") - self._check_for_failure() - - def get_remote(self, _local_path) -> str: - self.called_methods.append("get_remote") - self._check_for_failure() - return self.get_remote_response - - def get_branches(self, _local_path) -> List[str]: - self.called_methods.append("get_branches") - self._check_for_failure() - return self.get_branches_response - - def get_last_committers(self, _local_path, _n=10): - self.called_methods.append("get_last_committers") - self._check_for_failure() - return self.get_last_committers_response - - def get_last_authors(self, _local_path, _n=10): - self.called_methods.append("get_last_authors") - self._check_for_failure() - return self.get_last_authors_response - - -class MockSignal: - """A purely synchronous signal, instrumented and intended only for use in unit testing. - emit() is semi-functional, but does not use queued slots so cannot be used across - threads.""" - - def __init__(self, *args): - self.expected_types = args - self.connections = [] - self.disconnections = [] - self.emitted = False - - def connect(self, func): - self.connections.append(func) - - def disconnect(self, func): - if func in self.connections: - self.connections.remove(func) - self.disconnections.append(func) - - def emit(self, *args): - self.emitted = True - for connection in self.connections: - connection(args) - - -class MockNetworkManager: - """Instrumented mock for the NetworkManager. Does no network access, is not asynchronous, and - does not require a running event loop. No submitted requests ever complete.""" - - def __init__(self): - self.urls = [] - self.aborted = [] - self.data = MockByteArray() - self.called_methods = [] - - self.completed = MockSignal(int, int, MockByteArray) - self.progress_made = MockSignal(int, int, int) - self.progress_complete = MockSignal(int, int, os.PathLike) - - def submit_unmonitored_get(self, url: str) -> int: - self.urls.append(url) - self.called_methods.append("submit_unmonitored_get") - return len(self.urls) - 1 - - def submit_monitored_get(self, url: str) -> int: - self.urls.append(url) - self.called_methods.append("submit_monitored_get") - return len(self.urls) - 1 - - def blocking_get(self, url: str): - self.urls.append(url) - self.called_methods.append("blocking_get") - return self.data - - def abort_all(self): - self.called_methods.append("abort_all") - for url in self.urls: - self.aborted.append(url) - - def abort(self, index: int): - self.called_methods.append("abort") - self.aborted.append(self.urls[index]) - - -class MockByteArray: - """Mock for QByteArray. Only provides the data() access member.""" - - def __init__(self, data_to_wrap="data".encode("utf-8")): - self.wrapped = data_to_wrap - - def data(self) -> bytes: - return self.wrapped - - -class MockThread: - """Mock for QThread for use when threading is not being used, but interruption - needs to be tested. Set interrupt_after_n_calls to the call number to stop at.""" - - def __init__(self): - self.interrupt_after_n_calls = 0 - self.interrupt_check_counter = 0 - - def isInterruptionRequested(self): - self.interrupt_check_counter += 1 - if ( - self.interrupt_after_n_calls - and self.interrupt_check_counter >= self.interrupt_after_n_calls - ): - return True - return False - - -class MockPref: - def __init__(self): - self.prefs = {} - self.pref_set_counter = {} - self.pref_get_counter = {} - - def set_prefs(self, pref_dict: dict) -> None: - self.prefs = pref_dict - - def GetInt(self, key: str, default: int) -> int: - return self.Get(key, default) - - def GetString(self, key: str, default: str) -> str: - return self.Get(key, default) - - def GetBool(self, key: str, default: bool) -> bool: - return self.Get(key, default) - - def Get(self, key: str, default): - if key not in self.pref_set_counter: - self.pref_get_counter[key] = 1 - else: - self.pref_get_counter[key] += 1 - if key in self.prefs: - return self.prefs[key] - raise ValueError(f"Expected key not in mock preferences: {key}") - - def SetInt(self, key: str, value: int) -> None: - return self.Set(key, value) - - def SetString(self, key: str, value: str) -> None: - return self.Set(key, value) - - def SetBool(self, key: str, value: bool) -> None: - return self.Set(key, value) - - def Set(self, key: str, value): - if key not in self.pref_set_counter: - self.pref_set_counter[key] = 1 - else: - self.pref_set_counter[key] += 1 - self.prefs[key] = value - - -class MockExists: - def __init__(self, files: List[str] = None): - """Returns True for all files in files, and False for all others""" - self.files = files - self.files_checked = [] - - def exists(self, check_file: str): - self.files_checked.append(check_file) - if not self.files: - return False - for file in self.files: - if check_file.endswith(file): - return True - return False diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_addon.py b/src/Mod/AddonManager/AddonManagerTest/app/test_addon.py deleted file mode 100644 index 3872364739..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_addon.py +++ /dev/null @@ -1,407 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** -import tempfile -import unittest -import os -import sys - -sys.path.append("../../") - -from Addon import Addon, INTERNAL_WORKBENCHES -from addonmanager_macro import Macro - - -class TestAddon(unittest.TestCase): - MODULE = "test_addon" # file name without extension - - def setUp(self): - self.test_dir = os.path.join(os.path.dirname(__file__), "..", "data") - - def test_display_name(self): - # Case 1: No display name set elsewhere: name == display_name - addon = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - self.assertEqual(addon.name, "FreeCAD") - self.assertEqual(addon.display_name, "FreeCAD") - - # Case 2: Package.xml metadata file sets a display name: - addon.load_metadata_file(os.path.join(self.test_dir, "good_package.xml")) - self.assertEqual(addon.name, "FreeCAD") - self.assertEqual(addon.display_name, "Test Workbench") - - def test_git_url_cleanup(self): - base_url = "https://github.com/FreeCAD/FreeCAD" - test_urls = [f" {base_url} ", f"{base_url}.git", f" {base_url}.git "] - for url in test_urls: - addon = Addon("FreeCAD", url, Addon.Status.NOT_INSTALLED, "master") - self.assertEqual(addon.url, base_url) - - def test_tag_extraction(self): - addon = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon.load_metadata_file(os.path.join(self.test_dir, "good_package.xml")) - - tags = addon.tags - self.assertEqual(len(tags), 5) - expected_tags = set() - expected_tags.add("Tag0") - expected_tags.add("Tag1") - expected_tags.add("TagA") - expected_tags.add("TagB") - expected_tags.add("TagC") - self.assertEqual(expected_tags, tags) - - def test_contains_functions(self): - # Test package.xml combinations: - - # Workbenches - addon_with_workbench = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon_with_workbench.load_metadata_file(os.path.join(self.test_dir, "workbench_only.xml")) - self.assertTrue(addon_with_workbench.contains_workbench()) - self.assertFalse(addon_with_workbench.contains_macro()) - self.assertFalse(addon_with_workbench.contains_preference_pack()) - self.assertFalse(addon_with_workbench.contains_bundle()) - self.assertFalse(addon_with_workbench.contains_other()) - - # Macros - addon_with_macro = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon_with_macro.load_metadata_file(os.path.join(self.test_dir, "macro_only.xml")) - self.assertFalse(addon_with_macro.contains_workbench()) - self.assertTrue(addon_with_macro.contains_macro()) - self.assertFalse(addon_with_macro.contains_preference_pack()) - self.assertFalse(addon_with_workbench.contains_bundle()) - self.assertFalse(addon_with_workbench.contains_other()) - - # Preference Packs - addon_with_prefpack = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon_with_prefpack.load_metadata_file(os.path.join(self.test_dir, "prefpack_only.xml")) - self.assertFalse(addon_with_prefpack.contains_workbench()) - self.assertFalse(addon_with_prefpack.contains_macro()) - self.assertTrue(addon_with_prefpack.contains_preference_pack()) - self.assertFalse(addon_with_workbench.contains_bundle()) - self.assertFalse(addon_with_workbench.contains_other()) - - # Combination - addon_with_all = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon_with_all.load_metadata_file(os.path.join(self.test_dir, "combination.xml")) - self.assertTrue(addon_with_all.contains_workbench()) - self.assertTrue(addon_with_all.contains_macro()) - self.assertTrue(addon_with_all.contains_preference_pack()) - self.assertTrue(addon_with_all.contains_bundle()) - self.assertTrue(addon_with_all.contains_other()) - - # Now do the simple, explicitly-set cases - addon_wb = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon_wb.repo_type = Addon.Kind.WORKBENCH - self.assertTrue(addon_wb.contains_workbench()) - self.assertFalse(addon_wb.contains_macro()) - self.assertFalse(addon_wb.contains_preference_pack()) - - addon_m = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon_m.repo_type = Addon.Kind.MACRO - self.assertFalse(addon_m.contains_workbench()) - self.assertTrue(addon_m.contains_macro()) - self.assertFalse(addon_m.contains_preference_pack()) - - # There is no equivalent for preference packs, they are always accompanied by a - # metadata file - - def test_create_from_macro(self): - macro_file = os.path.join(self.test_dir, "DoNothing.FCMacro") - macro = Macro("DoNothing") - macro.fill_details_from_file(macro_file) - addon = Addon.from_macro(macro) - - self.assertEqual(addon.repo_type, Addon.Kind.MACRO) - self.assertEqual(addon.name, "DoNothing") - self.assertEqual( - addon.macro.comment, - "Do absolutely nothing. For Addon Manager integration tests.", - ) - self.assertEqual(addon.url, "https://github.com/FreeCAD/FreeCAD") - self.assertEqual(addon.macro.version, "1.0") - self.assertEqual(len(addon.macro.other_files), 3) - self.assertEqual(addon.macro.author, "Chris Hennes") - self.assertEqual(addon.macro.date, "2022-02-28") - self.assertEqual(addon.macro.icon, "not_real.png") - self.assertNotEqual(addon.macro.xpm, "") - - def test_cache(self): - addon = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - cache_data = addon.to_cache() - second_addon = Addon.from_cache(cache_data) - - self.assertTrue(addon.__dict__, second_addon.__dict__) - - def test_dependency_resolution(self): - addonA = Addon( - "AddonA", - "https://github.com/FreeCAD/FakeAddonA", - Addon.Status.NOT_INSTALLED, - "master", - ) - addonB = Addon( - "AddonB", - "https://github.com/FreeCAD/FakeAddonB", - Addon.Status.NOT_INSTALLED, - "master", - ) - addonC = Addon( - "AddonC", - "https://github.com/FreeCAD/FakeAddonC", - Addon.Status.NOT_INSTALLED, - "master", - ) - addonD = Addon( - "AddonD", - "https://github.com/FreeCAD/FakeAddonD", - Addon.Status.NOT_INSTALLED, - "master", - ) - - addonA.requires.add("AddonB") - addonB.requires.add("AddonC") - addonB.requires.add("AddonD") - addonD.requires.add("CAM") - - all_addons = { - addonA.name: addonA, - addonB.name: addonB, - addonC.name: addonC, - addonD.name: addonD, - } - - deps = Addon.Dependencies() - addonA.walk_dependency_tree(all_addons, deps) - - self.assertEqual(len(deps.required_external_addons), 3) - addon_strings = [addon.name for addon in deps.required_external_addons] - self.assertTrue( - "AddonB" in addon_strings, - "AddonB not in required dependencies, and it should be.", - ) - self.assertTrue( - "AddonC" in addon_strings, - "AddonC not in required dependencies, and it should be.", - ) - self.assertTrue( - "AddonD" in addon_strings, - "AddonD not in required dependencies, and it should be.", - ) - self.assertTrue( - "CAM" in deps.internal_workbenches, - "CAM not in workbench dependencies, and it should be.", - ) - - def test_internal_workbench_list(self): - addon = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon.load_metadata_file(os.path.join(self.test_dir, "depends_on_all_workbenches.xml")) - deps = Addon.Dependencies() - addon.walk_dependency_tree({}, deps) - self.assertEqual(len(deps.internal_workbenches), len(INTERNAL_WORKBENCHES)) - - def test_version_check(self): - addon = Addon( - "FreeCAD", - "https://github.com/FreeCAD/FreeCAD", - Addon.Status.NOT_INSTALLED, - "master", - ) - addon.load_metadata_file(os.path.join(self.test_dir, "test_version_detection.xml")) - - self.assertEqual( - len(addon.tags), - 1, - "Wrong number of tags found: version requirements should have restricted to only one", - ) - self.assertFalse( - "TagA" in addon.tags, - "Found 'TagA' in tags, it should have been excluded by version requirement", - ) - self.assertTrue( - "TagB" in addon.tags, - "Failed to find 'TagB' in tags, it should have been included", - ) - self.assertFalse( - "TagC" in addon.tags, - "Found 'TagA' in tags, it should have been excluded by version requirement", - ) - - def test_try_find_wbname_in_files_empty_dir(self): - with tempfile.TemporaryDirectory() as mod_dir: - # Arrange - test_addon = Addon("test") - test_addon.mod_directory = mod_dir - os.mkdir(os.path.join(mod_dir, test_addon.name)) - - # Act - wb_name = test_addon.try_find_wbname_in_files() - - # Assert - self.assertEqual(wb_name, "") - - def test_try_find_wbname_in_files_non_python_ignored(self): - with tempfile.TemporaryDirectory() as mod_dir: - # Arrange - test_addon = Addon("test") - test_addon.mod_directory = mod_dir - base_path = os.path.join(mod_dir, test_addon.name) - os.mkdir(base_path) - file_path = os.path.join(base_path, "test.txt") - with open(file_path, "w", encoding="utf-8") as f: - f.write("Gui.addWorkbench(TestWorkbench())") - - # Act - wb_name = test_addon.try_find_wbname_in_files() - - # Assert - self.assertEqual(wb_name, "") - - def test_try_find_wbname_in_files_simple(self): - with tempfile.TemporaryDirectory() as mod_dir: - # Arrange - test_addon = Addon("test") - test_addon.mod_directory = mod_dir - base_path = os.path.join(mod_dir, test_addon.name) - os.mkdir(base_path) - file_path = os.path.join(base_path, "test.py") - with open(file_path, "w", encoding="utf-8") as f: - f.write("Gui.addWorkbench(TestWorkbench())") - - # Act - wb_name = test_addon.try_find_wbname_in_files() - - # Assert - self.assertEqual(wb_name, "TestWorkbench") - - def test_try_find_wbname_in_files_subdir(self): - with tempfile.TemporaryDirectory() as mod_dir: - # Arrange - test_addon = Addon("test") - test_addon.mod_directory = mod_dir - base_path = os.path.join(mod_dir, test_addon.name) - os.mkdir(base_path) - subdir = os.path.join(base_path, "subdirectory") - os.mkdir(subdir) - file_path = os.path.join(subdir, "test.py") - with open(file_path, "w", encoding="utf-8") as f: - f.write("Gui.addWorkbench(TestWorkbench())") - - # Act - wb_name = test_addon.try_find_wbname_in_files() - - # Assert - self.assertEqual(wb_name, "TestWorkbench") - - def test_try_find_wbname_in_files_variable_used(self): - with tempfile.TemporaryDirectory() as mod_dir: - # Arrange - test_addon = Addon("test") - test_addon.mod_directory = mod_dir - base_path = os.path.join(mod_dir, test_addon.name) - os.mkdir(base_path) - file_path = os.path.join(base_path, "test.py") - with open(file_path, "w", encoding="utf-8") as f: - f.write("Gui.addWorkbench(wb)") - - # Act - wb_name = test_addon.try_find_wbname_in_files() - - # Assert - self.assertEqual(wb_name, "") - - def test_try_find_wbname_in_files_variants(self): - variants = [ - "Gui.addWorkbench(TestWorkbench())", - "Gui.addWorkbench (TestWorkbench())", - "Gui.addWorkbench( TestWorkbench() )", - "Gui.addWorkbench(TestWorkbench( ))", - "Gui.addWorkbench( TestWorkbench( ) )", - "Gui.addWorkbench( TestWorkbench ( ) )", - "Gui.addWorkbench ( TestWorkbench ( ) )", - ] - for variant in variants: - with self.subTest(variant=variant): - with tempfile.TemporaryDirectory() as mod_dir: - # Arrange - test_addon = Addon("test") - test_addon.mod_directory = mod_dir - base_path = os.path.join(mod_dir, test_addon.name) - os.mkdir(base_path) - file_path = os.path.join(base_path, "test.py") - with open(file_path, "w", encoding="utf-8") as f: - f.write(variant) - - # Act - wb_name = test_addon.try_find_wbname_in_files() - - # Assert - self.assertEqual(wb_name, "TestWorkbench") diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_addoncatalog.py b/src/Mod/AddonManager/AddonManagerTest/app/test_addoncatalog.py deleted file mode 100644 index 5b058c53c2..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_addoncatalog.py +++ /dev/null @@ -1,213 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later - -# pylint: disable=global-at-module-level,global-statement,import-outside-toplevel, - -"""Tests for the AddonCatalog and AddonCatalogEntry classes.""" - -import unittest -from unittest import mock -from unittest.mock import patch - -global AddonCatalogEntry -global AddonCatalog -global Version - - -class TestAddonCatalogEntry(unittest.TestCase): - """Tests for the AddonCatalogEntry class.""" - - def setUp(self): - """Start mock for addonmanager_licenses class.""" - global AddonCatalogEntry - global AddonCatalog - global Version - self.addon_patch = mock.patch.dict("sys.modules", {"addonmanager_licenses": mock.Mock()}) - self.mock_addon_module = self.addon_patch.start() - from AddonCatalog import AddonCatalogEntry, AddonCatalog - from addonmanager_metadata import Version - - def tearDown(self): - """Stop patching the addonmanager_licenses class""" - self.addon_patch.stop() - - def test_version_match_without_restrictions(self): - """Given an AddonCatalogEntry that has no version restrictions, a fixed version matches.""" - with patch("addonmanager_freecad_interface.Version") as mock_freecad: - mock_freecad.Version = lambda: (1, 2, 3, "dev") - ac = AddonCatalogEntry({}) - self.assertTrue(ac.is_compatible()) - - def test_version_match_with_min_no_max_good_match(self): - """Given an AddonCatalogEntry with a minimum FreeCAD version, a version smaller than that - does not match.""" - with patch("addonmanager_freecad_interface.Version", return_value=(1, 2, 3, "dev")): - ac = AddonCatalogEntry({"freecad_min": Version(from_string="1.2")}) - self.assertTrue(ac.is_compatible()) - - def test_version_match_with_max_no_min_good_match(self): - """Given an AddonCatalogEntry with a maximum FreeCAD version, a version larger than that - does not match.""" - with patch("addonmanager_freecad_interface.Version", return_value=(1, 2, 3, "dev")): - ac = AddonCatalogEntry({"freecad_max": Version(from_string="1.3")}) - self.assertTrue(ac.is_compatible()) - - def test_version_match_with_min_and_max_good_match(self): - """Given an AddonCatalogEntry with both a minimum and maximum FreeCAD version, a version - between the two matches.""" - with patch("addonmanager_freecad_interface.Version", return_value=(1, 2, 3, "dev")): - ac = AddonCatalogEntry( - { - "freecad_min": Version(from_string="1.1"), - "freecad_max": Version(from_string="1.3"), - } - ) - self.assertTrue(ac.is_compatible()) - - def test_version_match_with_min_and_max_bad_match_high(self): - """Given an AddonCatalogEntry with both a minimum and maximum FreeCAD version, a version - higher than the maximum does not match.""" - with patch("addonmanager_freecad_interface.Version", return_value=(1, 3, 3, "dev")): - ac = AddonCatalogEntry( - { - "freecad_min": Version(from_string="1.1"), - "freecad_max": Version(from_string="1.3"), - } - ) - self.assertFalse(ac.is_compatible()) - - def test_version_match_with_min_and_max_bad_match_low(self): - """Given an AddonCatalogEntry with both a minimum and maximum FreeCAD version, a version - lower than the minimum does not match.""" - with patch("addonmanager_freecad_interface.Version", return_value=(1, 0, 3, "dev")): - ac = AddonCatalogEntry( - { - "freecad_min": Version(from_string="1.1"), - "freecad_max": Version(from_string="1.3"), - } - ) - self.assertFalse(ac.is_compatible()) - - -class TestAddonCatalog(unittest.TestCase): - """Tests for the AddonCatalog class.""" - - def setUp(self): - """Start mock for addonmanager_licenses class.""" - global AddonCatalog - global Version - self.addon_patch = mock.patch.dict("sys.modules", {"addonmanager_licenses": mock.Mock()}) - self.mock_addon_module = self.addon_patch.start() - from AddonCatalog import AddonCatalog - from addonmanager_metadata import Version - - def tearDown(self): - """Stop patching the addonmanager_licenses class""" - self.addon_patch.stop() - - def test_single_addon_simple_entry(self): - """Test that an addon entry for an addon with only a git ref is accepted and added, and - appears as an available addon.""" - data = {"AnAddon": [{"git_ref": "main"}]} - catalog = AddonCatalog(data) - ids = catalog.get_available_addon_ids() - self.assertEqual(len(ids), 1) - self.assertIn("AnAddon", ids) - - def test_single_addon_max_single_entry(self): - """Test that an addon with the maximum possible data load is accepted.""" - data = { - "AnAddon": [ - { - "freecad_min": "0.21.0", - "freecad_max": "1.99.99", - "repository": "https://github.com/FreeCAD/FreeCAD", - "git_ref": "main", - "zip_url": "https://github.com/FreeCAD/FreeCAD/archive/main.zip", - "note": "This is a fake repo, don't use it", - "branch_display_name": "main", - } - ] - } - catalog = AddonCatalog(data) - ids = catalog.get_available_addon_ids() - self.assertEqual(len(ids), 1) - self.assertIn("AnAddon", ids) - - def test_single_addon_multiple_entries(self): - """Test that an addon with multiple entries is accepted and only appears as a single - addon.""" - data = { - "AnAddon": [ - { - "freecad_min": "1.0.0", - "repository": "https://github.com/FreeCAD/FreeCAD", - "git_ref": "main", - }, - { - "freecad_min": "0.21.0", - "freecad_max": "0.21.99", - "repository": "https://github.com/FreeCAD/FreeCAD", - "git_ref": "0_21_compatibility_branch", - "branch_display_name": "FreeCAD 0.21 Compatibility Branch", - }, - ] - } - catalog = AddonCatalog(data) - ids = catalog.get_available_addon_ids() - self.assertEqual(len(ids), 1) - self.assertIn("AnAddon", ids) - - def test_multiple_addon_entries(self): - """Test that multiple distinct addon entries are added as distinct addons""" - data = { - "AnAddon": [{"git_ref": "main"}], - "AnotherAddon": [{"git_ref": "main"}], - "YetAnotherAddon": [{"git_ref": "main"}], - } - catalog = AddonCatalog(data) - ids = catalog.get_available_addon_ids() - self.assertEqual(len(ids), 3) - self.assertIn("AnAddon", ids) - self.assertIn("AnotherAddon", ids) - self.assertIn("YetAnotherAddon", ids) - - def test_multiple_branches_single_match(self): - """Test that an addon with multiple branches representing different configurations of - min and max FreeCAD versions returns only the appropriate match.""" - data = { - "AnAddon": [ - { - "freecad_min": "1.0.0", - "repository": "https://github.com/FreeCAD/FreeCAD", - "git_ref": "main", - }, - { - "freecad_min": "0.21.0", - "freecad_max": "0.21.99", - "repository": "https://github.com/FreeCAD/FreeCAD", - "git_ref": "0_21_compatibility_branch", - "branch_display_name": "FreeCAD 0.21 Compatibility Branch", - }, - { - "freecad_min": "0.19.0", - "freecad_max": "0.20.99", - "repository": "https://github.com/FreeCAD/FreeCAD", - "git_ref": "0_19_compatibility_branch", - "branch_display_name": "FreeCAD 0.19 Compatibility Branch", - }, - ] - } - with patch("addonmanager_freecad_interface.Version", return_value=(1, 0, 3, "dev")): - catalog = AddonCatalog(data) - branches = catalog.get_available_branches("AnAddon") - self.assertEqual(len(branches), 1) - - def test_load_metadata_cache(self): - """Test that an addon with a known hash is correctly loaded (e.g. no exception is raised)""" - data = {"AnAddon": [{"git_ref": "main"}]} - catalog = AddonCatalog(data) - sha = "cbce6737d7d058dca2b5ae3f2fdb8cc45b0c02bf711e75bdf5f12fb71ce87790" - cache = {sha: "CacheData"} - with patch("addonmanager_freecad_interface.Version", return_value=cache): - with patch("Addon.Addon") as addon_mock: - catalog.load_metadata_cache(cache) diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_cache.py b/src/Mod/AddonManager/AddonManagerTest/app/test_cache.py deleted file mode 100644 index 098f1b3a01..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_cache.py +++ /dev/null @@ -1,126 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** -import datetime -import sys -import unittest -from datetime import date -from unittest import TestCase -from unittest.mock import MagicMock, patch - -sys.path.append("../..") - -import addonmanager_cache as cache -from AddonManagerTest.app.mocks import MockPref, MockExists - - -class TestCache(TestCase): - @patch("addonmanager_freecad_interface.getUserCachePath") - @patch("addonmanager_freecad_interface.ParamGet") - @patch("os.remove", MagicMock()) - @patch("os.makedirs", MagicMock()) - def test_local_cache_needs_update(self, param_mock: MagicMock, cache_mock: MagicMock): - cache_mock.return_value = "" - param_mock.return_value = MockPref() - default_prefs = { - "UpdateFrequencyComboEntry": 0, - "LastCacheUpdate": "2000-01-01", - "CustomRepoHash": "", - "CustomRepositories": "", - } - today = date.today().isoformat() - yesterday = (date.today() - datetime.timedelta(1)).isoformat() - - # Organize these as subtests because of all the patching that has to be done: once we are in this function, - # the patch is complete, and we can just modify the return values of the fakes one by one - tests = ( - { - "case": "No existing cache", - "files_that_exist": [], - "prefs_to_set": {}, - "expect": True, - }, - { - "case": "Last cache update was interrupted", - "files_that_exist": ["CACHE_UPDATE_INTERRUPTED"], - "prefs_to_set": {}, - "expect": True, - }, - { - "case": "Cache exists and updating is blocked", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {}, - "expect": False, - }, - { - "case": "Daily updates set and last update was long ago", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {"UpdateFrequencyComboEntry": 1}, - "expect": True, - }, - { - "case": "Daily updates set and last update was today", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {"UpdateFrequencyComboEntry": 1, "LastCacheUpdate": today}, - "expect": False, - }, - { - "case": "Daily updates set and last update was yesterday", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {"UpdateFrequencyComboEntry": 1, "LastCacheUpdate": yesterday}, - "expect": True, - }, - { - "case": "Weekly updates set and last update was long ago", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {"UpdateFrequencyComboEntry": 1}, - "expect": True, - }, - { - "case": "Weekly updates set and last update was yesterday", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {"UpdateFrequencyComboEntry": 2, "LastCacheUpdate": yesterday}, - "expect": False, - }, - { - "case": "Custom repo list changed", - "files_that_exist": ["AddonManager"], - "prefs_to_set": {"CustomRepositories": "NewRepo"}, - "expect": True, - }, - ) - for test_case in tests: - with self.subTest(test_case["case"]): - case_prefs = default_prefs - for pref, setting in test_case["prefs_to_set"].items(): - case_prefs[pref] = setting - param_mock.return_value.set_prefs(case_prefs) - exists_mock = MockExists(test_case["files_that_exist"]) - with patch("os.path.exists", exists_mock.exists): - if test_case["expect"]: - self.assertTrue(cache.local_cache_needs_update()) - else: - self.assertFalse(cache.local_cache_needs_update()) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py b/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py deleted file mode 100644 index c70e08491c..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py +++ /dev/null @@ -1,195 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import functools -import os -import subprocess -import tempfile -from time import sleep -import unittest - -from addonmanager_dependency_installer import DependencyInstaller - - -class CompleteProcessMock(subprocess.CompletedProcess): - def __init__(self): - super().__init__(["fake_arg"], 0) - self.stdout = "Mock subprocess call stdout result" - - -class SubprocessMock: - def __init__(self): - self.arg_log = [] - self.called = False - self.call_count = 0 - self.delay = 0 - self.succeed = True - - def subprocess_interceptor(self, args): - self.arg_log.append(args) - self.called = True - self.call_count += 1 - sleep(self.delay) - if self.succeed: - return CompleteProcessMock() - raise subprocess.CalledProcessError(1, " ".join(args), "Unit test mock output") - - -class FakeFunction: - def __init__(self): - self.called = False - self.call_count = 0 - self.return_value = None - self.arg_log = [] - - def func_call(self, *args): - self.arg_log.append(args) - self.called = True - self.call_count += 1 - return self.return_value - - -class TestDependencyInstaller(unittest.TestCase): - """Test the dependency installation class""" - - def setUp(self): - self.subprocess_mock = SubprocessMock() - self.test_object = DependencyInstaller([], ["required_py_package"], ["optional_py_package"]) - self.test_object._subprocess_wrapper = self.subprocess_mock.subprocess_interceptor - self.signals_caught = [] - self.test_object.failure.connect(functools.partial(self.catch_signal, "failure")) - self.test_object.finished.connect(functools.partial(self.catch_signal, "finished")) - self.test_object.no_pip.connect(functools.partial(self.catch_signal, "no_pip")) - self.test_object.no_python_exe.connect( - functools.partial(self.catch_signal, "no_python_exe") - ) - - def tearDown(self): - pass - - def catch_signal(self, signal_name, *_): - self.signals_caught.append(signal_name) - - def test_run_no_pip(self): - self.test_object._verify_pip = lambda: False - self.test_object.run() - self.assertIn("finished", self.signals_caught) - - def test_run_with_pip(self): - ff = FakeFunction() - self.test_object._verify_pip = lambda: True - self.test_object._install_python_packages = ff.func_call - self.test_object.run() - self.assertIn("finished", self.signals_caught) - self.assertTrue(ff.called) - - def test_run_with_no_packages(self): - ff = FakeFunction() - self.test_object._verify_pip = lambda: True - self.test_object._install_python_packages = ff.func_call - self.test_object.python_requires = [] - self.test_object.python_optional = [] - self.test_object.run() - self.assertIn("finished", self.signals_caught) - self.assertFalse(ff.called) - - def test_install_python_packages_new_location(self): - ff_required = FakeFunction() - ff_optional = FakeFunction() - self.test_object._install_required = ff_required.func_call - self.test_object._install_optional = ff_optional.func_call - with tempfile.TemporaryDirectory() as td: - self.test_object.location = os.path.join(td, "UnitTestLocation") - self.test_object._install_python_packages() - self.assertTrue(ff_required.called) - self.assertTrue(ff_optional.called) - self.assertTrue(os.path.exists(self.test_object.location)) - - def test_install_python_packages_existing_location(self): - ff_required = FakeFunction() - ff_optional = FakeFunction() - self.test_object._install_required = ff_required.func_call - self.test_object._install_optional = ff_optional.func_call - with tempfile.TemporaryDirectory() as td: - self.test_object.location = td - self.test_object._install_python_packages() - self.assertTrue(ff_required.called) - self.assertTrue(ff_optional.called) - - def test_verify_pip_no_pip(self): - sm = SubprocessMock() - sm.succeed = False - self.test_object._subprocess_wrapper = sm.subprocess_interceptor - self.test_object._get_python = lambda: "fake_python" - result = self.test_object._verify_pip() - self.assertFalse(result) - self.assertIn("no_pip", self.signals_caught) - - def test_verify_pip_with_pip(self): - sm = SubprocessMock() - sm.succeed = True - self.test_object._subprocess_wrapper = sm.subprocess_interceptor - self.test_object._get_python = lambda: "fake_python" - result = self.test_object._verify_pip() - self.assertTrue(result) - self.assertNotIn("no_pip", self.signals_caught) - - def test_install_required_loops(self): - sm = SubprocessMock() - sm.succeed = True - self.test_object._subprocess_wrapper = sm.subprocess_interceptor - self.test_object._get_python = lambda: "fake_python" - self.test_object.python_requires = ["test1", "test2", "test3"] - self.test_object._install_required("vendor_path") - self.assertEqual(sm.call_count, 3) - - def test_install_required_failure(self): - sm = SubprocessMock() - sm.succeed = False - self.test_object._subprocess_wrapper = sm.subprocess_interceptor - self.test_object._get_python = lambda: "fake_python" - self.test_object.python_requires = ["test1", "test2", "test3"] - self.test_object._install_required("vendor_path") - self.assertEqual(sm.call_count, 1) - self.assertIn("failure", self.signals_caught) - - def test_install_optional_loops(self): - sm = SubprocessMock() - sm.succeed = True - self.test_object._subprocess_wrapper = sm.subprocess_interceptor - self.test_object._get_python = lambda: "fake_python" - self.test_object.python_optional = ["test1", "test2", "test3"] - self.test_object._install_optional("vendor_path") - self.assertEqual(sm.call_count, 3) - - def test_install_optional_failure(self): - sm = SubprocessMock() - sm.succeed = False - self.test_object._subprocess_wrapper = sm.subprocess_interceptor - self.test_object._get_python = lambda: "fake_python" - self.test_object.python_optional = ["test1", "test2", "test3"] - self.test_object._install_optional("vendor_path") - self.assertEqual(sm.call_count, 3) - - def test_run_pip(self): - pass diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_freecad_interface.py b/src/Mod/AddonManager/AddonManagerTest/app/test_freecad_interface.py deleted file mode 100644 index 07da9f5301..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_freecad_interface.py +++ /dev/null @@ -1,299 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Tests for the Addon Manager's FreeCAD interface classes.""" - -import json -import os -import sys -import tempfile -import unittest -from unittest.mock import patch, MagicMock - -# pylint: disable=protected-access,import-outside-toplevel - - -class TestConsole(unittest.TestCase): - """Tests for the Console""" - - def setUp(self) -> None: - self.saved_freecad = None - if "FreeCAD" in sys.modules: - self.saved_freecad = sys.modules["FreeCAD"] - sys.modules.pop("FreeCAD") - if "addonmanager_freecad_interface" in sys.modules: - sys.modules.pop("addonmanager_freecad_interface") - sys.path.append("../../") - - def tearDown(self) -> None: - if "FreeCAD" in sys.modules: - sys.modules.pop("FreeCAD") - if self.saved_freecad is not None: - sys.modules["FreeCAD"] = self.saved_freecad - - def test_log_with_freecad(self): - """Ensure that if FreeCAD exists, the appropriate function is called""" - sys.modules["FreeCAD"] = unittest.mock.MagicMock() - import addonmanager_freecad_interface as fc - - fc.Console.PrintLog("Test output") - self.assertTrue(isinstance(fc.Console, unittest.mock.MagicMock)) - self.assertTrue(fc.Console.PrintLog.called) - - def test_log_no_freecad(self): - """Test that if the FreeCAD import fails, the logger is set up correctly, and - implements PrintLog""" - sys.modules["FreeCAD"] = None - with patch("addonmanager_freecad_interface.logging", new=MagicMock()) as mock_logging: - import addonmanager_freecad_interface as fc - - fc.Console.PrintLog("Test output") - self.assertTrue(isinstance(fc.Console, fc.ConsoleReplacement)) - self.assertTrue(mock_logging.log.called) - - def test_message_no_freecad(self): - """Test that if the FreeCAD import fails the logger implements PrintMessage""" - sys.modules["FreeCAD"] = None - with patch("addonmanager_freecad_interface.logging", new=MagicMock()) as mock_logging: - import addonmanager_freecad_interface as fc - - fc.Console.PrintMessage("Test output") - self.assertTrue(mock_logging.info.called) - - def test_warning_no_freecad(self): - """Test that if the FreeCAD import fails the logger implements PrintWarning""" - sys.modules["FreeCAD"] = None - with patch("addonmanager_freecad_interface.logging", new=MagicMock()) as mock_logging: - import addonmanager_freecad_interface as fc - - fc.Console.PrintWarning("Test output") - self.assertTrue(mock_logging.warning.called) - - def test_error_no_freecad(self): - """Test that if the FreeCAD import fails the logger implements PrintError""" - sys.modules["FreeCAD"] = None - with patch("addonmanager_freecad_interface.logging", new=MagicMock()) as mock_logging: - import addonmanager_freecad_interface as fc - - fc.Console.PrintError("Test output") - self.assertTrue(mock_logging.error.called) - - -class TestParameters(unittest.TestCase): - """Tests for the Parameters""" - - def setUp(self) -> None: - self.saved_freecad = None - if "FreeCAD" in sys.modules: - self.saved_freecad = sys.modules["FreeCAD"] - sys.modules.pop("FreeCAD") - if "addonmanager_freecad_interface" in sys.modules: - sys.modules.pop("addonmanager_freecad_interface") - sys.path.append("../../") - - def tearDown(self) -> None: - if "FreeCAD" in sys.modules: - sys.modules.pop("FreeCAD") - if self.saved_freecad is not None: - sys.modules["FreeCAD"] = self.saved_freecad - - def test_param_get_with_freecad(self): - """Ensure that if FreeCAD exists, the built-in FreeCAD function is called""" - sys.modules["FreeCAD"] = unittest.mock.MagicMock() - import addonmanager_freecad_interface as fc - - prefs = fc.ParamGet("some/fake/path") - self.assertTrue(isinstance(prefs, unittest.mock.MagicMock)) - - def test_param_get_no_freecad(self): - """Test that if the FreeCAD import fails, param_get returns a ParametersReplacement""" - sys.modules["FreeCAD"] = None - import addonmanager_freecad_interface as fc - - prefs = fc.ParamGet("some/fake/path") - self.assertTrue(isinstance(prefs, fc.ParametersReplacement)) - - def test_replacement_getters_and_setters(self): - """Test that ParameterReplacement's getters, setters, and deleters work""" - sys.modules["FreeCAD"] = None - import addonmanager_freecad_interface as fc - - prf = fc.ParamGet("some/fake/path") - gs_types = [ - ("Bool", prf.GetBool, prf.SetBool, prf.RemBool, True, False), - ("Int", prf.GetInt, prf.SetInt, prf.RemInt, 42, 0), - ("Float", prf.GetFloat, prf.SetFloat, prf.RemFloat, 1.2, 3.4), - ("String", prf.GetString, prf.SetString, prf.RemString, "test", "other"), - ] - for gs_type in gs_types: - with self.subTest(msg=f"Testing {gs_type[0]}", gs_type=gs_type): - getter = gs_type[1] - setter = gs_type[2] - deleter = gs_type[3] - value_1 = gs_type[4] - value_2 = gs_type[5] - self.assertEqual(getter("test", value_1), value_1) - self.assertEqual(getter("test", value_2), value_2) - self.assertNotIn("test", prf.parameters) - setter("test", value_1) - self.assertIn("test", prf.parameters) - self.assertEqual(getter("test", value_2), value_1) - deleter("test") - self.assertNotIn("test", prf.parameters) - - -class TestDataPaths(unittest.TestCase): - """Tests for the data paths""" - - def setUp(self) -> None: - self.saved_freecad = None - if "FreeCAD" in sys.modules: - self.saved_freecad = sys.modules["FreeCAD"] - sys.modules.pop("FreeCAD") - if "addonmanager_freecad_interface" in sys.modules: - sys.modules.pop("addonmanager_freecad_interface") - sys.path.append("../../") - - def tearDown(self) -> None: - if "FreeCAD" in sys.modules: - sys.modules.pop("FreeCAD") - if self.saved_freecad is not None: - sys.modules["FreeCAD"] = self.saved_freecad - - def test_init_with_freecad(self): - """Ensure that if FreeCAD exists, the appropriate functions are called""" - sys.modules["FreeCAD"] = unittest.mock.MagicMock() - import addonmanager_freecad_interface as fc - - data_paths = fc.DataPaths() - self.assertTrue(sys.modules["FreeCAD"].getUserAppDataDir.called) - self.assertTrue(sys.modules["FreeCAD"].getUserMacroDir.called) - self.assertTrue(sys.modules["FreeCAD"].getUserCachePath.called) - self.assertIsNotNone(data_paths.mod_dir) - self.assertIsNotNone(data_paths.cache_dir) - self.assertIsNotNone(data_paths.macro_dir) - - def test_init_without_freecad(self): - """Ensure that if FreeCAD does not exist, the appropriate functions are called""" - sys.modules["FreeCAD"] = None - import addonmanager_freecad_interface as fc - - data_paths = fc.DataPaths() - self.assertIsNotNone(data_paths.mod_dir) - self.assertIsNotNone(data_paths.cache_dir) - self.assertIsNotNone(data_paths.macro_dir) - self.assertNotEqual(data_paths.mod_dir, data_paths.cache_dir) - self.assertNotEqual(data_paths.mod_dir, data_paths.macro_dir) - self.assertNotEqual(data_paths.cache_dir, data_paths.macro_dir) - - -class TestPreferences(unittest.TestCase): - """Tests for the preferences wrapper""" - - def setUp(self) -> None: - sys.path.append("../../") - import addonmanager_freecad_interface as fc - - self.fc = fc - - def tearDown(self) -> None: - pass - - def test_load_preferences_defaults(self): - """Preferences are loaded from a given file""" - defaults = self.given_defaults() - with tempfile.TemporaryDirectory() as temp_dir: - json_file = os.path.join(temp_dir, "defaults.json") - with open(json_file, "w", encoding="utf-8") as f: - f.write(json.dumps(defaults)) - self.fc.Preferences._load_preferences_defaults(json_file) - self.assertDictEqual(defaults, self.fc.Preferences.preferences_defaults) - - def test_in_memory_defaults(self): - """Preferences are loaded from memory""" - defaults = self.given_defaults() - prefs = self.fc.Preferences(defaults) - self.assertDictEqual(defaults, prefs.preferences_defaults) - - def test_get_good(self): - """Get returns results when matching an existing preference""" - defaults = self.given_defaults() - prefs = self.fc.Preferences(defaults) - self.assertEqual(prefs.get("TestBool"), defaults["TestBool"]) - self.assertEqual(prefs.get("TestInt"), defaults["TestInt"]) - self.assertEqual(prefs.get("TestFloat"), defaults["TestFloat"]) - self.assertEqual(prefs.get("TestString"), defaults["TestString"]) - - def test_get_nonexistent(self): - """Get raises an exception when asked for a non-existent preference""" - defaults = self.given_defaults() - prefs = self.fc.Preferences(defaults) - with self.assertRaises(RuntimeError): - prefs.get("No_such_thing") - - def test_get_bad_type(self): - """Get raises an exception when getting an unsupported type""" - defaults = self.given_defaults() - defaults["TestArray"] = ["This", "Is", "Legal", "JSON"] - prefs = self.fc.Preferences(defaults) - with self.assertRaises(RuntimeError): - prefs.get("TestArray") - - def test_set_good(self): - """Set works when matching an existing preference""" - defaults = self.given_defaults() - prefs = self.fc.Preferences(defaults) - prefs.set("TestBool", False) - self.assertEqual(prefs.get("TestBool"), False) - prefs.set("TestInt", 4321) - self.assertEqual(prefs.get("TestInt"), 4321) - prefs.set("TestFloat", 3.14159) - self.assertEqual(prefs.get("TestFloat"), 3.14159) - prefs.set("TestString", "Forty two") - self.assertEqual(prefs.get("TestString"), "Forty two") - - def test_set_nonexistent(self): - """Set raises an exception when asked for a non-existent preference""" - defaults = self.given_defaults() - prefs = self.fc.Preferences(defaults) - with self.assertRaises(RuntimeError): - prefs.get("No_such_thing") - - def test_set_bad_type(self): - """Set raises an exception when setting an unsupported type""" - defaults = self.given_defaults() - defaults["TestArray"] = ["This", "Is", "Legal", "JSON"] - prefs = self.fc.Preferences(defaults) - with self.assertRaises(RuntimeError): - prefs.get("TestArray") - - @staticmethod - def given_defaults(): - """Get a dictionary of fake defaults for testing""" - defaults = { - "TestBool": True, - "TestInt": 42, - "TestFloat": 1.2, - "TestString": "Test", - } - return defaults diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_git.py b/src/Mod/AddonManager/AddonManagerTest/app/test_git.py deleted file mode 100644 index e9a9aaaf64..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_git.py +++ /dev/null @@ -1,177 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - - -import unittest -import os -import shutil -import stat -import tempfile -import time -from zipfile import ZipFile -import FreeCAD - -from addonmanager_git import GitManager, NoGitFound, GitFailed - -try: - git_manager = GitManager() -except NoGitFound: - git_manager = None - - -@unittest.skipIf(git_manager is None, "No git executable -- not running git-based tests") -class TestGit(unittest.TestCase): - - MODULE = "test_git" # file name without extension - - def setUp(self): - """Set up the test case: called by the unit test system""" - self.cwd = os.getcwd() - test_data_dir = os.path.join( - FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data" - ) - git_repo_zip = os.path.join(test_data_dir, "test_repo.zip") - self.test_dir = os.path.join( - tempfile.gettempdir(), "FreeCADTesting", "AddonManagerTests", "Git" - ) - os.makedirs(self.test_dir, exist_ok=True) - self.test_repo_remote = os.path.join(self.test_dir, "TEST_REPO_REMOTE") - if os.path.exists(self.test_repo_remote): - # Make sure any old copy that got left around is deleted - self._rmdir(self.test_repo_remote) - - if not os.path.exists(git_repo_zip): - self.skipTest("Can't find test repo") - return - - with ZipFile(git_repo_zip, "r") as zip_repo: - zip_repo.extractall(self.test_repo_remote) - self.test_repo_remote = os.path.join(self.test_repo_remote, "test_repo") - - self.git = git_manager - - def tearDown(self): - """Clean up after the test""" - os.chdir(self.cwd) - # self._rmdir(self.test_dir) - os.rename(self.test_dir, self.test_dir + ".old." + str(time.time())) - - def test_clone(self): - """Test git clone""" - checkout_dir = self._clone_test_repo() - self.assertTrue(os.path.exists(checkout_dir)) - self.assertTrue(os.path.exists(os.path.join(checkout_dir, ".git"))) - self.assertEqual(os.getcwd(), self.cwd, "We should be left in the same CWD we started") - - def test_checkout(self): - """Test git checkout""" - checkout_dir = self._clone_test_repo() - - self.git.checkout(checkout_dir, "HEAD~1") - status = self.git.status(checkout_dir).strip() - expected_status = "## HEAD (no branch)" - self.assertEqual(status, expected_status) - - self.assertEqual(os.getcwd(), self.cwd, "We should be left in the same CWD we started") - - def test_update(self): - """Test using git to update the local repo""" - checkout_dir = self._clone_test_repo() - - self.git.reset(checkout_dir, ["--hard", "HEAD~1"]) - self.assertTrue(self.git.update_available(checkout_dir)) - self.git.update(checkout_dir) - self.assertFalse(self.git.update_available(checkout_dir)) - self.assertEqual(os.getcwd(), self.cwd, "We should be left in the same CWD we started") - - def test_tag_and_branch(self): - """Test checking the currently checked-out tag""" - checkout_dir = self._clone_test_repo() - - expected_tag = "TestTag" - self.git.checkout(checkout_dir, expected_tag) - found_tag = self.git.current_tag(checkout_dir) - self.assertEqual(found_tag, expected_tag) - self.assertFalse(self.git.update_available(checkout_dir)) - - expected_branch = "TestBranch" - self.git.checkout(checkout_dir, expected_branch) - found_branch = self.git.current_branch(checkout_dir) - self.assertEqual(found_branch, expected_branch) - self.assertFalse(self.git.update_available(checkout_dir)) - - expected_branch = "main" - self.git.checkout(checkout_dir, expected_branch) - found_branch = self.git.current_branch(checkout_dir) - self.assertEqual(found_branch, expected_branch) - self.assertFalse(self.git.update_available(checkout_dir)) - - self.assertEqual(os.getcwd(), self.cwd, "We should be left in the same CWD we started") - - def test_get_remote(self): - """Test getting the remote location""" - checkout_dir = self._clone_test_repo() - expected_remote = self.test_repo_remote - returned_remote = self.git.get_remote(checkout_dir) - self.assertEqual(expected_remote, returned_remote) - self.assertEqual(os.getcwd(), self.cwd, "We should be left in the same CWD we started") - - def test_repair(self): - """Test the repair feature (and some exception throwing)""" - checkout_dir = self._clone_test_repo() - remote = self.git.get_remote(checkout_dir) - git_dir = os.path.join(checkout_dir, ".git") - self.assertTrue(os.path.exists(git_dir)) - self._rmdir(git_dir) - - # Make sure that we've truly broken the install - with self.assertRaises(GitFailed): - self.git.status(checkout_dir) - - self.git.repair(remote, checkout_dir) - status = self.git.status(checkout_dir) - self.assertEqual(status, "## main...origin/main\n") - self.assertEqual(os.getcwd(), self.cwd, "We should be left in the same CWD we started") - - def _rmdir(self, path): - try: - shutil.rmtree(path, onerror=self._remove_readonly) - except Exception as e: - print(e) - - def _remove_readonly(self, func, path, _) -> None: - """Remove a read-only file.""" - - os.chmod(path, stat.S_IWRITE) - func(path) - - def _clone_test_repo(self) -> str: - checkout_dir = os.path.join(self.test_dir, "test_repo") - try: - # Git won't clone to an existing directory, so make sure to remove it first - if os.path.exists(checkout_dir): - self._rmdir(checkout_dir) - self.git.clone(self.test_repo_remote, checkout_dir) - except GitFailed as e: - self.fail(str(e)) - return checkout_dir diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_installer.py b/src/Mod/AddonManager/AddonManagerTest/app/test_installer.py deleted file mode 100644 index fa57af41a0..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_installer.py +++ /dev/null @@ -1,412 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains the unit test class for addonmanager_installer.py non-GUI functionality.""" - -import unittest -from unittest.mock import Mock -import os -import shutil -import tempfile -from zipfile import ZipFile -import sys - -sys.path.append("../../") # So the IDE can find the imports below - -import FreeCAD -from addonmanager_installer import InstallationMethod, AddonInstaller, MacroInstaller -from addonmanager_git import GitManager, initialize_git -from addonmanager_metadata import MetadataReader -from Addon import Addon -from AddonManagerTest.app.mocks import MockAddon, MockMacro - - -class TestAddonInstaller(unittest.TestCase): - """Test class for addonmanager_installer.py non-GUI functionality""" - - MODULE = "test_installer" # file name without extension - - def setUp(self): - """Initialize data needed for all tests""" - # self.start_time = time.perf_counter() - self.test_data_dir = os.path.join( - FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data" - ) - self.real_addon = Addon( - "TestAddon", - "https://github.com/FreeCAD/FreeCAD-addons", - Addon.Status.NOT_INSTALLED, - "master", - ) - self.mock_addon = MockAddon() - - def tearDown(self): - """Finalize the test.""" - # end_time = time.perf_counter() - # print(f"Test '{self.id()}' ran in {end_time-self.start_time:.4f} seconds") - - def test_validate_object(self): - """An object is valid if it has a name, url, and branch attribute.""" - - AddonInstaller._validate_object(self.real_addon) # Won't raise - AddonInstaller._validate_object(self.mock_addon) # Won't raise - - class NoName: - def __init__(self): - self.url = "https://github.com/FreeCAD/FreeCAD-addons" - self.branch = "master" - - no_name = NoName() - with self.assertRaises(RuntimeError): - AddonInstaller._validate_object(no_name) - - class NoUrl: - def __init__(self): - self.name = "TestAddon" - self.branch = "master" - - no_url = NoUrl() - with self.assertRaises(RuntimeError): - AddonInstaller._validate_object(no_url) - - class NoBranch: - def __init__(self): - self.name = "TestAddon" - self.url = "https://github.com/FreeCAD/FreeCAD-addons" - - no_branch = NoBranch() - with self.assertRaises(RuntimeError): - AddonInstaller._validate_object(no_branch) - - def test_update_metadata(self): - """If a metadata file exists in the installation location, it should be - loaded.""" - addon = Mock() - addon.name = "MockAddon" - installer = AddonInstaller(addon, []) - installer._update_metadata() # Does nothing, but should not crash - - installer = AddonInstaller(self.real_addon, []) - with tempfile.TemporaryDirectory() as temp_dir: - installer.installation_path = temp_dir - installer._update_metadata() - addon_dir = os.path.join(temp_dir, self.real_addon.name) - os.mkdir(addon_dir) - shutil.copy( - os.path.join(self.test_data_dir, "good_package.xml"), - os.path.join(addon_dir, "package.xml"), - ) - good_metadata = MetadataReader.from_file(os.path.join(addon_dir, "package.xml")) - installer._update_metadata() - self.assertEqual(self.real_addon.installed_version, good_metadata.version) - - def test_finalize_zip_installation_non_github(self): - """Ensure that zip files are correctly extracted.""" - with tempfile.TemporaryDirectory() as temp_dir: - test_simple_repo = os.path.join(self.test_data_dir, "test_simple_repo.zip") - non_gh_mock = MockAddon() - non_gh_mock.url = test_simple_repo[:-4] - non_gh_mock.name = "NonGitHubMock" - installer = AddonInstaller(non_gh_mock, []) - installer.installation_path = temp_dir - installer._finalize_zip_installation(test_simple_repo) - expected_location = os.path.join(temp_dir, non_gh_mock.name, "README") - self.assertTrue(os.path.isfile(expected_location), "Non-GitHub zip extraction failed") - - def test_finalize_zip_installation_github(self): - with tempfile.TemporaryDirectory() as temp_dir: - test_github_style_repo = os.path.join(self.test_data_dir, "test_github_style_repo.zip") - self.mock_addon.url = "https://github.com/something/test_github_style_repo" - self.mock_addon.branch = "master" - installer = AddonInstaller(self.mock_addon, []) - installer.installation_path = temp_dir - installer._finalize_zip_installation(test_github_style_repo) - expected_location = os.path.join(temp_dir, self.mock_addon.name, "README") - self.assertTrue(os.path.isfile(expected_location), "GitHub zip extraction failed") - - def test_code_in_branch_subdirectory_true(self): - """When there is a subdirectory with the branch name in it, find it""" - self.mock_addon.url = "https://something.com/something_else/something" - installer = AddonInstaller(self.mock_addon, []) - with tempfile.TemporaryDirectory() as temp_dir: - os.mkdir(os.path.join(temp_dir, f"something-{self.mock_addon.branch}")) - result = installer._code_in_branch_subdirectory(temp_dir) - self.assertTrue(result, "Failed to find ZIP subdirectory") - - def test_code_in_branch_subdirectory_false(self): - """When there is not a subdirectory with the branch name in it, don't find - one""" - installer = AddonInstaller(self.mock_addon, []) - with tempfile.TemporaryDirectory() as temp_dir: - result = installer._code_in_branch_subdirectory(temp_dir) - self.assertFalse(result, "Found ZIP subdirectory when there was none") - - def test_code_in_branch_subdirectory_more_than_one(self): - """When there are multiple subdirectories, never find a branch subdirectory""" - installer = AddonInstaller(self.mock_addon, []) - with tempfile.TemporaryDirectory() as temp_dir: - os.mkdir(os.path.join(temp_dir, f"{self.mock_addon.name}-{self.mock_addon.branch}")) - os.mkdir(os.path.join(temp_dir, "AnotherSubdir")) - result = installer._code_in_branch_subdirectory(temp_dir) - self.assertFalse(result, "Found ZIP subdirectory when there were multiple subdirs") - - def test_move_code_out_of_subdirectory(self): - """All files are moved out and the subdirectory is deleted""" - self.mock_addon.url = "https://something.com/something_else/something" - installer = AddonInstaller(self.mock_addon, []) - with tempfile.TemporaryDirectory() as temp_dir: - subdir = os.path.join(temp_dir, f"something-{self.mock_addon.branch}") - os.mkdir(subdir) - with open(os.path.join(subdir, "README.txt"), "w", encoding="utf-8") as f: - f.write("# Test file for unit testing") - with open(os.path.join(subdir, "AnotherFile.txt"), "w", encoding="utf-8") as f: - f.write("# Test file for unit testing") - installer._move_code_out_of_subdirectory(temp_dir) - self.assertTrue(os.path.isfile(os.path.join(temp_dir, "README.txt"))) - self.assertTrue(os.path.isfile(os.path.join(temp_dir, "AnotherFile.txt"))) - self.assertFalse(os.path.isdir(subdir)) - - def test_install_by_git(self): - """Test using git to install. Depends on there being a local git - installation: the test is skipped if there is no local git.""" - git_manager = initialize_git() - if not git_manager: - self.skipTest("git not found, skipping git installer tests") - return - - # Our test git repo has to be in a zipfile, otherwise it cannot itself be - # stored in git, since it has a .git subdirectory. - with tempfile.TemporaryDirectory() as temp_dir: - git_repo_zip = os.path.join(self.test_data_dir, "test_repo.zip") - with ZipFile(git_repo_zip, "r") as zip_repo: - zip_repo.extractall(temp_dir) - - mock_addon = MockAddon() - mock_addon.url = os.path.join(temp_dir, "test_repo") - mock_addon.branch = "main" - installer = AddonInstaller(mock_addon, []) - installer.installation_path = os.path.join(temp_dir, "installed_addon") - installer._install_by_git() - - self.assertTrue(os.path.exists(installer.installation_path)) - addon_name_dir = os.path.join(installer.installation_path, mock_addon.name) - self.assertTrue(os.path.exists(addon_name_dir)) - readme = os.path.join(addon_name_dir, "README.md") - self.assertTrue(os.path.exists(readme)) - - def test_install_by_copy(self): - """Test using a simple filesystem copy to install an addon.""" - with tempfile.TemporaryDirectory() as temp_dir: - git_repo_zip = os.path.join(self.test_data_dir, "test_repo.zip") - with ZipFile(git_repo_zip, "r") as zip_repo: - zip_repo.extractall(temp_dir) - - mock_addon = MockAddon() - mock_addon.url = os.path.join(temp_dir, "test_repo") - mock_addon.branch = "main" - installer = AddonInstaller(mock_addon, []) - installer.addon_to_install = mock_addon - installer.installation_path = os.path.join(temp_dir, "installed_addon") - installer._install_by_copy() - - self.assertTrue(os.path.exists(installer.installation_path)) - addon_name_dir = os.path.join(installer.installation_path, mock_addon.name) - self.assertTrue(os.path.exists(addon_name_dir)) - readme = os.path.join(addon_name_dir, "README.md") - self.assertTrue(os.path.exists(readme)) - - def test_determine_install_method_local_path(self): - """Test which install methods are accepted for a local path""" - - with tempfile.TemporaryDirectory() as temp_dir: - installer = AddonInstaller(self.mock_addon, []) - method = installer._determine_install_method(temp_dir, InstallationMethod.COPY) - self.assertEqual(method, InstallationMethod.COPY) - git_manager = initialize_git() - if git_manager: - method = installer._determine_install_method(temp_dir, InstallationMethod.GIT) - self.assertEqual(method, InstallationMethod.GIT) - method = installer._determine_install_method(temp_dir, InstallationMethod.ZIP) - self.assertIsNone(method) - method = installer._determine_install_method(temp_dir, InstallationMethod.ANY) - self.assertEqual(method, InstallationMethod.COPY) - - def test_determine_install_method_file_url(self): - """Test which install methods are accepted for a file:// url""" - - with tempfile.TemporaryDirectory() as temp_dir: - installer = AddonInstaller(self.mock_addon, []) - temp_dir = "file://" + temp_dir.replace(os.path.sep, "/") - method = installer._determine_install_method(temp_dir, InstallationMethod.COPY) - self.assertEqual(method, InstallationMethod.COPY) - git_manager = initialize_git() - if git_manager: - method = installer._determine_install_method(temp_dir, InstallationMethod.GIT) - self.assertEqual(method, InstallationMethod.GIT) - method = installer._determine_install_method(temp_dir, InstallationMethod.ZIP) - self.assertIsNone(method) - method = installer._determine_install_method(temp_dir, InstallationMethod.ANY) - self.assertEqual(method, InstallationMethod.COPY) - - def test_determine_install_method_local_zip(self): - """Test which install methods are accepted for a local path to a zipfile""" - - with tempfile.TemporaryDirectory() as temp_dir: - installer = AddonInstaller(self.mock_addon, []) - temp_file = os.path.join(temp_dir, "dummy.zip") - method = installer._determine_install_method(temp_file, InstallationMethod.COPY) - self.assertEqual(method, InstallationMethod.ZIP) - method = installer._determine_install_method(temp_file, InstallationMethod.GIT) - self.assertIsNone(method) - method = installer._determine_install_method(temp_file, InstallationMethod.ZIP) - self.assertEqual(method, InstallationMethod.ZIP) - method = installer._determine_install_method(temp_file, InstallationMethod.ANY) - self.assertEqual(method, InstallationMethod.ZIP) - - def test_determine_install_method_remote_zip(self): - """Test which install methods are accepted for a remote path to a zipfile""" - - installer = AddonInstaller(self.mock_addon, []) - - temp_file = "https://freecad.org/dummy.zip" # Doesn't have to actually exist! - - method = installer._determine_install_method(temp_file, InstallationMethod.COPY) - self.assertIsNone(method) - method = installer._determine_install_method(temp_file, InstallationMethod.GIT) - self.assertIsNone(method) - method = installer._determine_install_method(temp_file, InstallationMethod.ZIP) - self.assertEqual(method, InstallationMethod.ZIP) - method = installer._determine_install_method(temp_file, InstallationMethod.ANY) - self.assertEqual(method, InstallationMethod.ZIP) - - def test_determine_install_method_https_known_sites_copy(self): - """Test which install methods are accepted for an https GitHub URL""" - - installer = AddonInstaller(self.mock_addon, []) - installer.git_manager = True - - for site in ["github.org", "gitlab.org", "framagit.org", "salsa.debian.org"]: - with self.subTest(site=site): - temp_file = f"https://{site}/dummy/dummy" # Doesn't have to actually exist! - method = installer._determine_install_method(temp_file, InstallationMethod.COPY) - self.assertIsNone(method, f"Allowed copying from {site} URL") - - def test_determine_install_method_https_known_sites_git(self): - """Test which install methods are accepted for an https GitHub URL""" - - installer = AddonInstaller(self.mock_addon, []) - installer.git_manager = True - - for site in ["github.org", "gitlab.org", "framagit.org", "salsa.debian.org"]: - with self.subTest(site=site): - temp_file = f"https://{site}/dummy/dummy" # Doesn't have to actually exist! - method = installer._determine_install_method(temp_file, InstallationMethod.GIT) - self.assertEqual( - method, - InstallationMethod.GIT, - f"Failed to allow git access to {site} URL", - ) - - def test_determine_install_method_https_known_sites_zip(self): - """Test which install methods are accepted for an https GitHub URL""" - - installer = AddonInstaller(self.mock_addon, []) - installer.git_manager = True - - for site in ["github.org", "gitlab.org", "framagit.org", "salsa.debian.org"]: - with self.subTest(site=site): - temp_file = f"https://{site}/dummy/dummy" # Doesn't have to actually exist! - method = installer._determine_install_method(temp_file, InstallationMethod.ZIP) - self.assertEqual( - method, - InstallationMethod.ZIP, - f"Failed to allow zip access to {site} URL", - ) - - def test_determine_install_method_https_known_sites_any_gm(self): - """Test which install methods are accepted for an https GitHub URL""" - - installer = AddonInstaller(self.mock_addon, []) - installer.git_manager = True - - for site in ["github.org", "gitlab.org", "framagit.org", "salsa.debian.org"]: - with self.subTest(site=site): - temp_file = f"https://{site}/dummy/dummy" # Doesn't have to actually exist! - method = installer._determine_install_method(temp_file, InstallationMethod.ANY) - self.assertEqual( - method, - InstallationMethod.GIT, - f"Failed to allow git access to {site} URL", - ) - - def test_determine_install_method_https_known_sites_any_no_gm(self): - """Test which install methods are accepted for an https GitHub URL""" - - installer = AddonInstaller(self.mock_addon, []) - installer.git_manager = None - - for site in ["github.org", "gitlab.org", "framagit.org", "salsa.debian.org"]: - with self.subTest(site=site): - temp_file = f"https://{site}/dummy/dummy" # Doesn't have to actually exist! - method = installer._determine_install_method(temp_file, InstallationMethod.ANY) - self.assertEqual( - method, - InstallationMethod.ZIP, - f"Failed to allow zip access to {site} URL", - ) - - def test_fcmacro_copying(self): - with tempfile.TemporaryDirectory() as temp_dir: - mock_addon = MockAddon() - mock_addon.url = os.path.join(self.test_data_dir, "test_addon_with_fcmacro.zip") - installer = AddonInstaller(mock_addon, []) - installer.installation_path = temp_dir - installer.macro_installation_path = os.path.join(temp_dir, "Macros") - installer.run() - self.assertTrue( - os.path.exists(os.path.join(temp_dir, "Macros", "TestMacro.FCMacro")), - "FCMacro file was not copied to macro installation location", - ) - - -class TestMacroInstaller(unittest.TestCase): - MODULE = "test_installer" # file name without extension - - def setUp(self): - """Set up the mock objects""" - - self.mock = MockAddon() - self.mock.macro = MockMacro() - - def test_installation(self): - """Test the wrapper around the macro installer""" - - # Note that this doesn't test the underlying Macro object's install function, - # it only tests whether that function is called appropriately by the - # MacroInstaller wrapper. - with tempfile.TemporaryDirectory() as temp_dir: - installer = MacroInstaller(self.mock) - installer.installation_path = temp_dir - installation_succeeded = installer.run() - self.assertTrue(installation_succeeded) - self.assertTrue(os.path.exists(os.path.join(temp_dir, self.mock.macro.filename))) diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_macro.py b/src/Mod/AddonManager/AddonManagerTest/app/test_macro.py deleted file mode 100644 index 20960e3c6e..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_macro.py +++ /dev/null @@ -1,213 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import os -import sys -import tempfile -from typing import Dict -import unittest -from unittest.mock import MagicMock - -sys.path.append("../../") # So the IDE can find the - -import FreeCAD - -from addonmanager_macro import Macro - - -class TestMacro(unittest.TestCase): - MODULE = "test_macro" # file name without extension - - def setUp(self): - self.test_dir = os.path.join( - FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data" - ) - - def test_basic_metadata(self): - replacements = { - "COMMENT": "test comment", - "WEB": "https://test.url", - "VERSION": "1.2.3", - "AUTHOR": "Test Author", - "DATE": "2022-03-09", - "ICON": "testicon.svg", - } - m = self.generate_macro(replacements) - self.assertEqual(m.comment, replacements["COMMENT"]) - self.assertEqual(m.url, replacements["WEB"]) - self.assertEqual(m.version, replacements["VERSION"]) - self.assertEqual(m.author, replacements["AUTHOR"]) - self.assertEqual(m.date, replacements["DATE"]) - self.assertEqual(m.icon, replacements["ICON"]) - - def test_other_files(self): - replacements = { - "FILES": "file_a,file_b,file_c", - } - m = self.generate_macro(replacements) - self.assertEqual(len(m.other_files), 3) - self.assertEqual(m.other_files[0], "file_a") - self.assertEqual(m.other_files[1], "file_b") - self.assertEqual(m.other_files[2], "file_c") - - replacements = { - "FILES": "file_a, file_b, file_c", - } - m = self.generate_macro(replacements) - self.assertEqual(len(m.other_files), 3) - self.assertEqual(m.other_files[0], "file_a") - self.assertEqual(m.other_files[1], "file_b") - self.assertEqual(m.other_files[2], "file_c") - - replacements = { - "FILES": "file_a file_b file_c", - } - m = self.generate_macro(replacements) - self.assertEqual(len(m.other_files), 1) - self.assertEqual(m.other_files[0], "file_a file_b file_c") - - def test_version_from_string(self): - replacements = { - "VERSION": "1.2.3", - } - m = self.generate_macro(replacements) - self.assertEqual(m.version, "1.2.3") - - def test_version_from_date(self): - replacements = { - "DATE": "2022-03-09", - } - outfile = self.generate_macro_file(replacements) - with open(outfile) as f: - lines = f.readlines() - output_lines = [] - for line in lines: - if "VERSION" in line: - line = "__Version__ = __Date__" - output_lines.append(line) - with open(outfile, "w") as f: - f.write("\n".join(output_lines)) - m = Macro("Unit Test Macro") - m.fill_details_from_file(outfile) - self.assertEqual(m.version, "2022-03-09") - - def test_version_from_float(self): - outfile = self.generate_macro_file() - with open(outfile) as f: - lines = f.readlines() - output_lines = [] - for line in lines: - if "VERSION" in line: - line = "__Version__ = 1.23" - output_lines.append(line) - with open(outfile, "w") as f: - f.write("\n".join(output_lines)) - m = Macro("Unit Test Macro") - m.fill_details_from_file(outfile) - self.assertEqual(m.version, "1.23") - - def test_version_from_int(self): - outfile = self.generate_macro_file() - with open(outfile) as f: - lines = f.readlines() - output_lines = [] - for line in lines: - if "VERSION" in line: - line = "__Version__ = 1" - output_lines.append(line) - with open(outfile, "w") as f: - f.write("\n".join(output_lines)) - m = Macro("Unit Test Macro") - m.fill_details_from_file(outfile) - self.assertEqual(m.version, "1") - - def test_xpm(self): - outfile = self.generate_macro_file() - xpm_data = """/* XPM */ -static char * blarg_xpm[] = { -"16 7 2 1", -"* c #000000", -". c #ffffff", -"**..*...........", -"*.*.*...........", -"**..*..**.**..**", -"*.*.*.*.*.*..*.*", -"**..*..**.*...**", -"...............*", -".............**." -};""" - with open(outfile) as f: - contents = f.read() - contents += f'\n__xpm__ = """{xpm_data}"""\n' - - with open(outfile, "w") as f: - f.write(contents) - m = Macro("Unit Test Macro") - m.fill_details_from_file(outfile) - self.assertEqual(m.xpm, xpm_data) - - def generate_macro_file(self, replacements: Dict[str, str] = {}) -> os.PathLike: - with open(os.path.join(self.test_dir, "macro_template.FCStd")) as f: - lines = f.readlines() - outfile = tempfile.NamedTemporaryFile(mode="wt", delete=False) - for line in lines: - for key, value in replacements.items(): - line = line.replace(key, value) - - outfile.write(line) - outfile.close() - return outfile.name - - def generate_macro(self, replacements: Dict[str, str] = {}) -> Macro: - outfile = self.generate_macro_file(replacements) - m = Macro("Unit Test Macro") - m.fill_details_from_file(outfile) - os.unlink(outfile) - return m - - def test_fetch_raw_code_no_data(self): - m = Macro("Unit Test Macro") - Macro.blocking_get = MagicMock(return_value=None) - returned_data = m._fetch_raw_code( - 'rawcodeurl Totally fake' - ) - self.assertIsNone(returned_data) - m.blocking_get.assert_called_with("https://fake_url.com") - Macro.blocking_get = None - - def test_fetch_raw_code_no_url(self): - m = Macro("Unit Test Macro") - Macro.blocking_get = MagicMock(return_value=None) - returned_data = m._fetch_raw_code("Fake pagedata with no URL at all.") - self.assertIsNone(returned_data) - m.blocking_get.assert_not_called() - Macro.blocking_get = None - - def test_fetch_raw_code_with_data(self): - m = Macro("Unit Test Macro") - Macro.blocking_get = MagicMock(return_value=b"Data returned to _fetch_raw_code") - returned_data = m._fetch_raw_code( - 'rawcodeurl Totally fake' - ) - self.assertEqual(returned_data, "Data returned to _fetch_raw_code") - Macro.blocking_get = None diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_macro_parser.py b/src/Mod/AddonManager/AddonManagerTest/app/test_macro_parser.py deleted file mode 100644 index 5e89bc0945..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_macro_parser.py +++ /dev/null @@ -1,344 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Tests for the MacroParser class""" - -import io -import os -import sys -import unittest - -sys.path.append("../../") # So the IDE can find the classes to run with - -from addonmanager_macro_parser import MacroParser -from AddonManagerTest.app.mocks import MockConsole, CallCatcher, MockThread - - -# pylint: disable=protected-access, too-many-public-methods - - -class TestMacroParser(unittest.TestCase): - """Test the MacroParser class""" - - def setUp(self) -> None: - self.test_object = MacroParser("UnitTestMacro") - self.test_object.console = MockConsole() - self.test_object.current_thread = MockThread() - - def tearDown(self) -> None: - pass - - def test_fill_details_from_code_normal(self): - """Test to make sure _process_line gets called as expected""" - catcher = CallCatcher() - self.test_object._process_line = catcher.catch_call - fake_macro_data = self.given_some_lines(20, 10) - self.test_object.fill_details_from_code(fake_macro_data) - self.assertEqual(catcher.call_count, 10) - - def test_fill_details_from_code_too_many_lines(self): - """Test to make sure _process_line gets limited as expected""" - catcher = CallCatcher() - self.test_object._process_line = catcher.catch_call - self.test_object.MAX_LINES_TO_SEARCH = 5 - fake_macro_data = self.given_some_lines(20, 10) - self.test_object.fill_details_from_code(fake_macro_data) - self.assertEqual(catcher.call_count, 5) - - def test_fill_details_from_code_thread_interrupted(self): - """Test to make sure _process_line gets stopped as expected""" - catcher = CallCatcher() - self.test_object._process_line = catcher.catch_call - self.test_object.current_thread.interrupt_after_n_calls = 6 # Stop on the 6th - fake_macro_data = self.given_some_lines(20, 10) - self.test_object.fill_details_from_code(fake_macro_data) - self.assertEqual(catcher.call_count, 5) - - @staticmethod - def given_some_lines(num_lines, num_dunder_lines) -> str: - """Generate fake macro header data with the given number of lines and number of - lines beginning with a double-underscore.""" - result = "" - for i in range(num_lines): - if i < num_dunder_lines: - result += f"__something_{i}__ = 'Test{i}' # A line to be scanned\n" - else: - result += f"# Nothing to see on line {i}\n" - return result - - def test_process_line_known_lines(self): - """Lines starting with keys are processed""" - test_lines = ["__known_key__ = 'Test'", "__another_known_key__ = 'Test'"] - for line in test_lines: - with self.subTest(line=line): - self.test_object.remaining_item_map = { - "__known_key__": "known_key", - "__another_known_key__": "another_known_key", - } - content_lines = io.StringIO(line) - read_in_line = content_lines.readline() - catcher = CallCatcher() - self.test_object._process_key = catcher.catch_call - self.test_object._process_line(read_in_line, content_lines) - self.assertTrue(catcher.called, "_process_key was not called for a known key") - - def test_process_line_unknown_lines(self): - """Lines starting with non-keys are not processed""" - test_lines = [ - "# Just a line with a comment", - "\n", - "__dont_know_this_one__ = 'Who cares?'", - "# __known_key__ = 'Aha, but it is commented out!'", - ] - for line in test_lines: - with self.subTest(line=line): - self.test_object.remaining_item_map = { - "__known_key__": "known_key", - "__another_known_key__": "another_known_key", - } - content_lines = io.StringIO(line) - read_in_line = content_lines.readline() - catcher = CallCatcher() - self.test_object._process_key = catcher.catch_call - self.test_object._process_line(read_in_line, content_lines) - self.assertFalse(catcher.called, "_process_key was called for an unknown key") - - def test_process_key_standard(self): - """Normal expected data is processed""" - self.test_object._reset_map() - in_memory_data = '__comment__ = "Test"' - content_lines = io.StringIO(in_memory_data) - line = content_lines.readline() - self.test_object._process_key("__comment__", line, content_lines) - self.assertTrue(self.test_object.parse_results["comment"], "Test") - - def test_process_key_special(self): - """Special handling for version = date is processed""" - self.test_object._reset_map() - self.test_object.parse_results["date"] = "2001-01-01" - in_memory_data = "__version__ = __date__" - content_lines = io.StringIO(in_memory_data) - line = content_lines.readline() - self.test_object._process_key("__version__", line, content_lines) - self.assertTrue(self.test_object.parse_results["version"], "2001-01-01") - - def test_handle_backslash_continuation_no_backslashes(self): - """The backslash handling code doesn't change a line with no backslashes""" - in_memory_data = '"Not a backslash in sight"' - content_lines = io.StringIO(in_memory_data) - line = content_lines.readline() - result = self.test_object._handle_backslash_continuation(line, content_lines) - self.assertEqual(result, in_memory_data) - - def test_handle_backslash_continuation(self): - """Lines ending in a backslash get stripped and concatenated""" - in_memory_data = '"Line1\\\nLine2\\\nLine3\\\nLine4"' - content_lines = io.StringIO(in_memory_data) - line = content_lines.readline() - result = self.test_object._handle_backslash_continuation(line, content_lines) - self.assertEqual(result, '"Line1Line2Line3Line4"') - - def test_handle_triple_quoted_string_no_triple_quotes(self): - """The triple-quote handler leaves alone lines without triple-quotes""" - in_memory_data = '"Line1"' - content_lines = io.StringIO(in_memory_data) - line = content_lines.readline() - result, was_triple_quoted = self.test_object._handle_triple_quoted_string( - line, content_lines - ) - self.assertEqual(result, in_memory_data) - self.assertFalse(was_triple_quoted) - - def test_handle_triple_quoted_string(self): - """Data is extracted across multiple lines for a triple-quoted string""" - in_memory_data = '"""Line1\nLine2\nLine3\nLine4"""\nLine5\n' - content_lines = io.StringIO(in_memory_data) - line = content_lines.readline() - result, was_triple_quoted = self.test_object._handle_triple_quoted_string( - line, content_lines - ) - self.assertEqual(result, '"""Line1\nLine2\nLine3\nLine4"""') - self.assertTrue(was_triple_quoted) - - def test_strip_quotes_single(self): - """Single quotes are stripped from the final string""" - expected = "test" - quoted = f"'{expected}'" - actual = self.test_object._strip_quotes(quoted) - self.assertEqual(actual, expected) - - def test_strip_quotes_double(self): - """Double quotes are stripped from the final string""" - expected = "test" - quoted = f'"{expected}"' - actual = self.test_object._strip_quotes(quoted) - self.assertEqual(actual, expected) - - def test_strip_quotes_triple(self): - """Triple quotes are stripped from the final string""" - expected = "test" - quoted = f'"""{expected}"""' - actual = self.test_object._strip_quotes(quoted) - self.assertEqual(actual, expected) - - def test_strip_quotes_unquoted(self): - """Unquoted data results in None""" - unquoted = "This has no quotation marks of any kind" - actual = self.test_object._strip_quotes(unquoted) - self.assertIsNone(actual) - - def test_standard_extraction_string(self): - """String variables are extracted and stored""" - string_keys = [ - "comment", - "url", - "wiki", - "version", - "author", - "date", - "icon", - "xpm", - ] - for key in string_keys: - with self.subTest(key=key): - self.test_object._standard_extraction(key, "test") - self.assertEqual(self.test_object.parse_results[key], "test") - - def test_standard_extraction_list(self): - """List variable is extracted and stored""" - key = "other_files" - self.test_object._standard_extraction(key, "test1, test2, test3") - self.assertIn("test1", self.test_object.parse_results[key]) - self.assertIn("test2", self.test_object.parse_results[key]) - self.assertIn("test3", self.test_object.parse_results[key]) - - def test_apply_special_handling_version(self): - """If the tag is __version__, apply our special handling""" - self.test_object._reset_map() - self.test_object._apply_special_handling("__version__", 42) - self.assertNotIn("__version__", self.test_object.remaining_item_map) - self.assertEqual(self.test_object.parse_results["version"], "42") - - def test_apply_special_handling_not_version(self): - """If the tag is not __version__, raise an error""" - self.test_object._reset_map() - with self.assertRaises(SyntaxError): - self.test_object._apply_special_handling("__not_version__", 42) - self.assertIn("__version__", self.test_object.remaining_item_map) - - def test_process_noncompliant_version_date(self): - """Detect and allow __date__ for the __version__""" - self.test_object.parse_results["date"] = "1/2/3" - self.test_object._process_noncompliant_version("__date__") - self.assertEqual( - self.test_object.parse_results["version"], - self.test_object.parse_results["date"], - ) - - def test_process_noncompliant_version_float(self): - """Detect and allow floats for the __version__""" - self.test_object._process_noncompliant_version(1.2) - self.assertEqual(self.test_object.parse_results["version"], "1.2") - - def test_process_noncompliant_version_int(self): - """Detect and allow integers for the __version__""" - self.test_object._process_noncompliant_version(42) - self.assertEqual(self.test_object.parse_results["version"], "42") - - def test_detect_illegal_content_prefixed_string(self): - """Detect and raise an error for various kinds of prefixed strings""" - illegal_strings = [ - "f'Some fancy {thing}'", - 'f"Some fancy {thing}"', - "r'Some fancy {thing}'", - 'r"Some fancy {thing}"', - "u'Some fancy {thing}'", - 'u"Some fancy {thing}"', - "fr'Some fancy {thing}'", - 'fr"Some fancy {thing}"', - "rf'Some fancy {thing}'", - 'rf"Some fancy {thing}"', - ] - for test_string in illegal_strings: - with self.subTest(test_string=test_string): - with self.assertRaises(SyntaxError): - MacroParser._detect_illegal_content(test_string) - - def test_detect_illegal_content_not_a_string(self): - """Detect and raise an error for (some) non-strings""" - illegal_strings = [ - "no quotes", - "do_stuff()", - 'print("A function call sporting quotes!")', - "__name__", - "__version__", - "1.2.3", - ] - for test_string in illegal_strings: - with self.subTest(test_string=test_string): - with self.assertRaises(SyntaxError): - MacroParser._detect_illegal_content(test_string) - - def test_detect_illegal_content_no_failure(self): - """Recognize strings of various kinds, plus ints, and floats""" - legal_strings = [ - '"Some legal value in double quotes"', - "'Some legal value in single quotes'", - '"""Some legal value in triple quotes"""', - "__date__", - "42", - "4.2", - ] - for test_string in legal_strings: - with self.subTest(test_string=test_string): - MacroParser._detect_illegal_content(test_string) - - ##################### - # INTEGRATION TESTS # - ##################### - - def test_macro_parser(self): - """INTEGRATION TEST: Given "real" data, ensure the parsing yields the expected results.""" - data_dir = os.path.join(os.path.dirname(__file__), "../data") - macro_file = os.path.join(data_dir, "DoNothing.FCMacro") - with open(macro_file, "r", encoding="utf-8") as f: - code = f.read() - self.test_object.fill_details_from_code(code) - self.assertEqual(len(self.test_object.console.errors), 0) - self.assertEqual(len(self.test_object.console.warnings), 0) - self.assertEqual(self.test_object.parse_results["author"], "Chris Hennes") - self.assertEqual(self.test_object.parse_results["version"], "1.0") - self.assertEqual(self.test_object.parse_results["date"], "2022-02-28") - self.assertEqual( - self.test_object.parse_results["comment"], - "Do absolutely nothing. For Addon Manager integration tests.", - ) - self.assertEqual( - self.test_object.parse_results["url"], "https://github.com/FreeCAD/FreeCAD" - ) - self.assertEqual(self.test_object.parse_results["icon"], "not_real.png") - self.assertListEqual( - self.test_object.parse_results["other_files"], - ["file1.py", "file2.py", "file3.py"], - ) - self.assertNotEqual(self.test_object.parse_results["xpm"], "") diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_metadata.py b/src/Mod/AddonManager/AddonManagerTest/app/test_metadata.py deleted file mode 100644 index 9f6f53cecf..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_metadata.py +++ /dev/null @@ -1,649 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** -import os -import sys -import tempfile -import unittest -import unittest.mock - -Mock = unittest.mock.MagicMock - -sys.path.append("../../") - - -class TestVersion(unittest.TestCase): - def setUp(self) -> None: - if "addonmanager_metadata" in sys.modules: - sys.modules.pop("addonmanager_metadata") - self.packaging_version = None - if "packaging.version" in sys.modules: - self.packaging_version = sys.modules["packaging.version"] - sys.modules.pop("packaging.version") - - def tearDown(self) -> None: - if self.packaging_version is not None: - sys.modules["packaging.version"] = self.packaging_version - - def test_init_from_string_manual(self): - import addonmanager_metadata as amm - - version = amm.Version() - version._parse_string_to_tuple = unittest.mock.MagicMock() - version._init_from_string("1.2.3beta") - self.assertTrue(version._parse_string_to_tuple.called) - - def test_init_from_list_good(self): - """Initialization from a list works for good input""" - import addonmanager_metadata as amm - - test_cases = [ - {"input": (1,), "output": [1, 0, 0, ""]}, - {"input": (1, 2), "output": [1, 2, 0, ""]}, - {"input": (1, 2, 3), "output": [1, 2, 3, ""]}, - {"input": (1, 2, 3, "b1"), "output": [1, 2, 3, "b1"]}, - ] - for test_case in test_cases: - with self.subTest(test_case=test_case): - v = amm.Version(from_list=test_case["input"]) - self.assertListEqual(test_case["output"], v.version_as_list) - - def test_parse_string_to_tuple_normal(self): - """Parsing of complete version string works for normal cases""" - import addonmanager_metadata as amm - - cases = { - "1": [1, 0, 0, ""], - "1.2": [1, 2, 0, ""], - "1.2.3": [1, 2, 3, ""], - "1.2.3beta": [1, 2, 3, "beta"], - "12_345.6_7.8pre-alpha": [12345, 67, 8, "pre-alpha"], - # The above test is mostly to point out that Python gets permits underscore - # characters in a number. - } - for inp, output in cases.items(): - with self.subTest(inp=inp, output=output): - version = amm.Version() - version._parse_string_to_tuple(inp) - self.assertListEqual(version.version_as_list, output) - - def test_parse_string_to_tuple_invalid(self): - """Parsing of invalid version string raises an exception""" - import addonmanager_metadata as amm - - cases = {"One", "1,2,3", "1-2-3", "1/2/3"} - for inp in cases: - with self.subTest(inp=inp): - with self.assertRaises(ValueError): - version = amm.Version() - version._parse_string_to_tuple(inp) - - def test_parse_final_entry_normal(self): - """Parsing of the final entry works for normal cases""" - import addonmanager_metadata as amm - - cases = { - "3beta": (3, "beta"), - "42.alpha": (42, ".alpha"), - "123.45.6": (123, ".45.6"), - "98_delta": (98, "_delta"), - "1 and some words": (1, " and some words"), - } - for inp, output in cases.items(): - with self.subTest(inp=inp, output=output): - number, text = amm.Version._parse_final_entry(inp) - self.assertEqual(number, output[0]) - self.assertEqual(text, output[1]) - - def test_parse_final_entry_invalid(self): - """Invalid input raises an exception""" - import addonmanager_metadata as amm - - cases = ["beta", "", ["a", "b"]] - for case in cases: - with self.subTest(case=case): - with self.assertRaises(ValueError): - amm.Version._parse_final_entry(case) - - def test_operators_internal(self): - """Test internal (non-package) comparison operators""" - sys.modules["packaging.version"] = None - import addonmanager_metadata as amm - - cases = self.given_comparison_cases() - for case in cases: - with self.subTest(case=case): - first = amm.Version(case[0]) - second = amm.Version(case[1]) - self.assertEqual(first < second, case[0] < case[1]) - self.assertEqual(first > second, case[0] > case[1]) - self.assertEqual(first <= second, case[0] <= case[1]) - self.assertEqual(first >= second, case[0] >= case[1]) - self.assertEqual(first == second, case[0] == case[1]) - - @staticmethod - def given_comparison_cases(): - return [ - ("0.0.0alpha", "1.0.0alpha"), - ("0.0.0alpha", "0.1.0alpha"), - ("0.0.0alpha", "0.0.1alpha"), - ("0.0.0alpha", "0.0.0beta"), - ("0.0.0alpha", "0.0.0alpha"), - ("1.0.0alpha", "0.0.0alpha"), - ("0.1.0alpha", "0.0.0alpha"), - ("0.0.1alpha", "0.0.0alpha"), - ("0.0.0beta", "0.0.0alpha"), - ] - - -class TestDependencyType(unittest.TestCase): - """Ensure that the DependencyType dataclass converts to the correct strings""" - - def setUp(self) -> None: - from addonmanager_metadata import DependencyType - - self.DependencyType = DependencyType - - def test_string_conversion_automatic(self): - self.assertEqual(str(self.DependencyType.automatic), "automatic") - - def test_string_conversion_internal(self): - self.assertEqual(str(self.DependencyType.internal), "internal") - - def test_string_conversion_addon(self): - self.assertEqual(str(self.DependencyType.addon), "addon") - - def test_string_conversion_python(self): - self.assertEqual(str(self.DependencyType.python), "python") - - -class TestUrlType(unittest.TestCase): - """Ensure that the UrlType dataclass converts to the correct strings""" - - def setUp(self) -> None: - from addonmanager_metadata import UrlType - - self.UrlType = UrlType - - def test_string_conversion_website(self): - self.assertEqual(str(self.UrlType.website), "website") - - def test_string_conversion_repository(self): - self.assertEqual(str(self.UrlType.repository), "repository") - - def test_string_conversion_bugtracker(self): - self.assertEqual(str(self.UrlType.bugtracker), "bugtracker") - - def test_string_conversion_readme(self): - self.assertEqual(str(self.UrlType.readme), "readme") - - def test_string_conversion_documentation(self): - self.assertEqual(str(self.UrlType.documentation), "documentation") - - def test_string_conversion_discussion(self): - self.assertEqual(str(self.UrlType.discussion), "discussion") - - -class TestMetadataAuxiliaryFunctions(unittest.TestCase): - def test_get_first_supported_freecad_version_simple(self): - from addonmanager_metadata import ( - Metadata, - Version, - get_first_supported_freecad_version, - ) - - expected_result = Version(from_string="0.20.2beta") - metadata = self.given_metadata_with_freecadmin_set(expected_result) - first_version = get_first_supported_freecad_version(metadata) - self.assertEqual(expected_result, first_version) - - @staticmethod - def given_metadata_with_freecadmin_set(min_version): - from addonmanager_metadata import Metadata - - metadata = Metadata() - metadata.freecadmin = min_version - return metadata - - def test_get_first_supported_freecad_version_with_content(self): - from addonmanager_metadata import ( - Metadata, - Version, - get_first_supported_freecad_version, - ) - - expected_result = Version(from_string="0.20.2beta") - metadata = self.given_metadata_with_freecadmin_in_content(expected_result) - first_version = get_first_supported_freecad_version(metadata) - self.assertEqual(expected_result, first_version) - - @staticmethod - def given_metadata_with_freecadmin_in_content(min_version): - from addonmanager_metadata import Metadata, Version - - v_list = min_version.version_as_list - metadata = Metadata() - wb1 = Metadata() - wb1.freecadmin = Version(from_list=[v_list[0] + 1, v_list[1], v_list[2], v_list[3]]) - wb2 = Metadata() - wb2.freecadmin = Version(from_list=[v_list[0], v_list[1] + 1, v_list[2], v_list[3]]) - wb3 = Metadata() - wb3.freecadmin = Version(from_list=[v_list[0], v_list[1], v_list[2] + 1, v_list[3]]) - m1 = Metadata() - m1.freecadmin = min_version - metadata.content = {"workbench": [wb1, wb2, wb3], "macro": [m1]} - return metadata - - -class TestMetadataReader(unittest.TestCase): - """Test reading metadata from XML""" - - def setUp(self) -> None: - if "xml.etree.ElementTree" in sys.modules: - sys.modules.pop("xml.etree.ElementTree") - if "addonmanager_metadata" in sys.modules: - sys.modules.pop("addonmanager_metadata") - - def tearDown(self) -> None: - if "xml.etree.ElementTree" in sys.modules: - sys.modules.pop("xml.etree.ElementTree") - if "addonmanager_metadata" in sys.modules: - sys.modules.pop("addonmanager_metadata") - - def test_from_file(self): - from addonmanager_metadata import MetadataReader - - MetadataReader.from_bytes = Mock() - with tempfile.NamedTemporaryFile(delete=False) as temp: - temp.write(b"Some data") - temp.close() - MetadataReader.from_file(temp.name) - self.assertTrue(MetadataReader.from_bytes.called) - MetadataReader.from_bytes.assert_called_once_with(b"Some data") - os.unlink(temp.name) - - @unittest.skip("Breaks other tests, needs to be fixed") - def test_from_bytes(self): - import xml.etree.ElementTree - - with unittest.mock.patch("xml.etree.ElementTree") as element_tree_mock: - from addonmanager_metadata import MetadataReader - - MetadataReader._process_element_tree = Mock() - MetadataReader.from_bytes(b"Some data") - element_tree_mock.parse.assert_called_once_with(b"Some data") - - def test_process_element_tree(self): - from addonmanager_metadata import MetadataReader - - MetadataReader._determine_namespace = Mock(return_value="") - element_tree_mock = Mock() - MetadataReader._create_node = Mock() - MetadataReader._process_element_tree(element_tree_mock) - MetadataReader._create_node.assert_called_once() - - def test_determine_namespace_found_full(self): - from addonmanager_metadata import MetadataReader - - root = Mock() - root.tag = "{https://wiki.freecad.org/Package_Metadata}package" - found_ns = MetadataReader._determine_namespace(root) - self.assertEqual(found_ns, "{https://wiki.freecad.org/Package_Metadata}") - - def test_determine_namespace_found_empty(self): - from addonmanager_metadata import MetadataReader - - root = Mock() - root.tag = "package" - found_ns = MetadataReader._determine_namespace(root) - self.assertEqual(found_ns, "") - - def test_determine_namespace_not_found(self): - from addonmanager_metadata import MetadataReader - - root = Mock() - root.find = Mock(return_value=False) - with self.assertRaises(RuntimeError): - MetadataReader._determine_namespace(root) - - def test_parse_child_element_simple_strings(self): - from addonmanager_metadata import Metadata, MetadataReader - - tags = ["name", "date", "description", "icon", "classname", "subdirectory"] - for tag in tags: - with self.subTest(tag=tag): - text = f"Test Data for {tag}" - child = self.given_mock_tree_node(tag, text) - mock_metadata = Metadata() - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(mock_metadata.__dict__[tag], text) - - def test_parse_child_element_version(self): - from addonmanager_metadata import Metadata, Version, MetadataReader - - mock_metadata = Metadata() - child = self.given_mock_tree_node("version", "1.2.3") - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(Version("1.2.3"), mock_metadata.version) - - def test_parse_child_element_version_bad(self): - from addonmanager_metadata import Metadata, Version, MetadataReader - - mock_metadata = Metadata() - child = self.given_mock_tree_node("version", "1-2-3") - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(Version("0.0.0"), mock_metadata.version) - - def test_parse_child_element_lists_of_strings(self): - from addonmanager_metadata import Metadata, MetadataReader - - tags = ["file", "tag"] - for tag in tags: - with self.subTest(tag=tag): - mock_metadata = Metadata() - expected_results = [] - for i in range(10): - text = f"Test {i} for {tag}" - expected_results.append(text) - child = self.given_mock_tree_node(tag, text) - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(len(mock_metadata.__dict__[tag]), 10) - self.assertListEqual(mock_metadata.__dict__[tag], expected_results) - - def test_parse_child_element_lists_of_contacts(self): - from addonmanager_metadata import Metadata, Contact, MetadataReader - - tags = ["maintainer", "author"] - for tag in tags: - with self.subTest(tag=tag): - mock_metadata = Metadata() - expected_results = [] - for i in range(10): - text = f"Test {i} for {tag}" - email = f"Email {i} for {tag}" if i % 2 == 0 else None - expected_results.append(Contact(name=text, email=email)) - child = self.given_mock_tree_node(tag, text, {"email": email}) - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(len(mock_metadata.__dict__[tag]), 10) - self.assertListEqual(mock_metadata.__dict__[tag], expected_results) - - def test_parse_child_element_list_of_licenses(self): - from addonmanager_metadata import Metadata, License, MetadataReader - - mock_metadata = Metadata() - expected_results = [] - tag = "license" - for i in range(10): - text = f"Test {i} for {tag}" - file = f"Filename {i} for {tag}" if i % 2 == 0 else None - expected_results.append(License(name=text, file=file)) - child = self.given_mock_tree_node(tag, text, {"file": file}) - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(len(mock_metadata.__dict__[tag]), 10) - self.assertListEqual(mock_metadata.__dict__[tag], expected_results) - - def test_parse_child_element_list_of_urls(self): - from addonmanager_metadata import Metadata, Url, UrlType, MetadataReader - - mock_metadata = Metadata() - expected_results = [] - tag = "url" - for i in range(10): - text = f"Test {i} for {tag}" - url_type = UrlType(i % len(UrlType)) - type = str(url_type) - branch = "" - if type == "repository": - branch = f"Branch {i} for {tag}" - expected_results.append(Url(location=text, type=url_type, branch=branch)) - child = self.given_mock_tree_node(tag, text, {"type": type, "branch": branch}) - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(len(mock_metadata.__dict__[tag]), 10) - self.assertListEqual(mock_metadata.__dict__[tag], expected_results) - - def test_parse_child_element_lists_of_dependencies(self): - from addonmanager_metadata import ( - Metadata, - Dependency, - DependencyType, - MetadataReader, - ) - - tags = ["depend", "conflict", "replace"] - attributes = { - "version_lt": "1.0.0", - "version_lte": "1.0.0", - "version_eq": "1.0.0", - "version_gte": "1.0.0", - "version_gt": "1.0.0", - "condition": "$BuildVersionMajor<1", - "optional": True, - } - - for tag in tags: - for attribute, attr_value in attributes.items(): - with self.subTest(tag=tag, attribute=attribute): - mock_metadata = Metadata() - expected_results = [] - for i in range(10): - text = f"Test {i} for {tag}" - dependency_type = DependencyType(i % len(DependencyType)) - dependency_type_str = str(dependency_type) - expected = Dependency(package=text, dependency_type=dependency_type) - expected.__dict__[attribute] = attr_value - expected_results.append(expected) - child = self.given_mock_tree_node( - tag, - text, - {"type": dependency_type_str, attribute: str(attr_value)}, - ) - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(len(mock_metadata.__dict__[tag]), 10) - self.assertListEqual(mock_metadata.__dict__[tag], expected_results) - - def test_parse_child_element_ignore_unknown_tag(self): - from addonmanager_metadata import Metadata, MetadataReader - - tag = "invalid_tag" - text = "Shouldn't matter" - child = self.given_mock_tree_node(tag, text) - mock_metadata = Metadata() - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertNotIn(tag, mock_metadata.__dict__) - - def test_parse_child_element_versions(self): - from addonmanager_metadata import Metadata, Version, MetadataReader - - tags = ["version", "freecadmin", "freecadmax", "pythonmin"] - for tag in tags: - with self.subTest(tag=tag): - mock_metadata = Metadata() - text = "3.4.5beta" - child = self.given_mock_tree_node(tag, text) - MetadataReader._parse_child_element("", child, mock_metadata) - self.assertEqual(mock_metadata.__dict__[tag], Version(from_string=text)) - - def given_mock_tree_node(self, tag, text, attributes=None): - class MockTreeNode: - def __init__(self): - self.tag = tag - self.text = text - self.attrib = attributes if attributes is not None else [] - - return MockTreeNode() - - def test_parse_content_valid(self): - from addonmanager_metadata import MetadataReader - - valid_content_items = ["workbench", "macro", "preferencepack"] - MetadataReader._create_node = Mock() - for content_type in valid_content_items: - with self.subTest(content_type=content_type): - tree_mock = [self.given_mock_tree_node(content_type, None)] - metadata_mock = Mock() - MetadataReader._parse_content("", metadata_mock, tree_mock) - MetadataReader._create_node.assert_called_once() - MetadataReader._create_node.reset_mock() - - def test_parse_content_invalid(self): - from addonmanager_metadata import MetadataReader - - MetadataReader._create_node = Mock() - content_item = "no_such_content_type" - tree_mock = [self.given_mock_tree_node(content_item, None)] - metadata_mock = Mock() - MetadataReader._parse_content("", metadata_mock, tree_mock) - MetadataReader._create_node.assert_not_called() - - -class TestMetadataReaderIntegration(unittest.TestCase): - """Full-up tests of the MetadataReader class (no mocking).""" - - def setUp(self) -> None: - self.test_data_dir = os.path.join(os.path.dirname(__file__), "..", "data") - remove_list = [] - for key in sys.modules: - if "addonmanager_metadata" in key: - remove_list.append(key) - for key in remove_list: - print(f"Removing {key}") - sys.modules.pop(key) - - def test_loading_simple_metadata_file(self): - from addonmanager_metadata import ( - Contact, - Dependency, - License, - MetadataReader, - Url, - UrlType, - Version, - ) - - filename = os.path.join(self.test_data_dir, "good_package.xml") - metadata = MetadataReader.from_file(filename) - self.assertEqual("Test Workbench", metadata.name) - self.assertEqual("A package.xml file for unit testing.", metadata.description) - self.assertEqual(Version("1.0.1"), metadata.version) - self.assertEqual("2022-01-07", metadata.date) - self.assertEqual("Resources/icons/PackageIcon.svg", metadata.icon) - self.assertListEqual([License(name="LGPL-2.1", file="LICENSE")], metadata.license) - self.assertListEqual( - [Contact(name="FreeCAD Developer", email="developer@freecad.org")], - metadata.maintainer, - ) - self.assertListEqual( - [ - Url( - location="https://github.com/chennes/FreeCAD-Package", - type=UrlType.repository, - branch="main", - ), - Url( - location="https://github.com/chennes/FreeCAD-Package/blob/main/README.md", - type=UrlType.readme, - ), - ], - metadata.url, - ) - self.assertListEqual(["Tag0", "Tag1"], metadata.tag) - self.assertIn("workbench", metadata.content) - self.assertEqual(len(metadata.content["workbench"]), 1) - wb_metadata = metadata.content["workbench"][0] - self.assertEqual("MyWorkbench", wb_metadata.classname) - self.assertEqual("./", wb_metadata.subdirectory) - self.assertListEqual(["TagA", "TagB", "TagC"], wb_metadata.tag) - - def test_multiple_workbenches(self): - from addonmanager_metadata import MetadataReader - - filename = os.path.join(self.test_data_dir, "workbench_only.xml") - metadata = MetadataReader.from_file(filename) - self.assertIn("workbench", metadata.content) - self.assertEqual(len(metadata.content["workbench"]), 3) - expected_wb_classnames = [ - "MyFirstWorkbench", - "MySecondWorkbench", - "MyThirdWorkbench", - ] - for wb in metadata.content["workbench"]: - self.assertIn(wb.classname, expected_wb_classnames) - expected_wb_classnames.remove(wb.classname) - self.assertEqual(len(expected_wb_classnames), 0) - - def test_multiple_macros(self): - from addonmanager_metadata import MetadataReader - - filename = os.path.join(self.test_data_dir, "macro_only.xml") - metadata = MetadataReader.from_file(filename) - self.assertIn("macro", metadata.content) - self.assertEqual(len(metadata.content["macro"]), 2) - expected_wb_files = ["MyMacro.FCStd", "MyOtherMacro.FCStd"] - for wb in metadata.content["macro"]: - self.assertIn(wb.file[0], expected_wb_files) - expected_wb_files.remove(wb.file[0]) - self.assertEqual(len(expected_wb_files), 0) - - def test_multiple_preference_packs(self): - from addonmanager_metadata import MetadataReader - - filename = os.path.join(self.test_data_dir, "prefpack_only.xml") - metadata = MetadataReader.from_file(filename) - self.assertIn("preferencepack", metadata.content) - self.assertEqual(len(metadata.content["preferencepack"]), 3) - expected_packs = ["MyFirstPack", "MySecondPack", "MyThirdPack"] - for wb in metadata.content["preferencepack"]: - self.assertIn(wb.name, expected_packs) - expected_packs.remove(wb.name) - self.assertEqual(len(expected_packs), 0) - - def test_bundle(self): - from addonmanager_metadata import MetadataReader - - filename = os.path.join(self.test_data_dir, "bundle_only.xml") - metadata = MetadataReader.from_file(filename) - self.assertIn("bundle", metadata.content) - self.assertEqual(len(metadata.content["bundle"]), 1) - - def test_other(self): - from addonmanager_metadata import MetadataReader - - filename = os.path.join(self.test_data_dir, "other_only.xml") - metadata = MetadataReader.from_file(filename) - self.assertIn("other", metadata.content) - self.assertEqual(len(metadata.content["other"]), 1) - - def test_content_combination(self): - from addonmanager_metadata import MetadataReader - - filename = os.path.join(self.test_data_dir, "combination.xml") - metadata = MetadataReader.from_file(filename) - self.assertIn("preferencepack", metadata.content) - self.assertEqual(len(metadata.content["preferencepack"]), 1) - self.assertIn("macro", metadata.content) - self.assertEqual(len(metadata.content["macro"]), 1) - self.assertIn("workbench", metadata.content) - self.assertEqual(len(metadata.content["workbench"]), 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_uninstaller.py b/src/Mod/AddonManager/AddonManagerTest/app/test_uninstaller.py deleted file mode 100644 index 8c82c28421..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_uninstaller.py +++ /dev/null @@ -1,437 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains the unit test class for addonmanager_uninstaller.py non-GUI functionality.""" - -import functools -import os -from stat import S_IREAD, S_IRGRP, S_IROTH, S_IWUSR -import tempfile -import unittest - -import FreeCAD - -from addonmanager_uninstaller import AddonUninstaller, MacroUninstaller - -from Addon import Addon -from AddonManagerTest.app.mocks import MockAddon, MockMacro - - -class TestAddonUninstaller(unittest.TestCase): - """Test class for addonmanager_uninstaller.py non-GUI functionality""" - - MODULE = "test_uninstaller" # file name without extension - - def setUp(self): - """Initialize data needed for all tests""" - self.test_data_dir = os.path.join( - FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data" - ) - self.mock_addon = MockAddon() - self.signals_caught = [] - self.test_object = AddonUninstaller(self.mock_addon) - - self.test_object.finished.connect(functools.partial(self.catch_signal, "finished")) - self.test_object.success.connect(functools.partial(self.catch_signal, "success")) - self.test_object.failure.connect(functools.partial(self.catch_signal, "failure")) - - def tearDown(self): - """Finalize the test.""" - - def catch_signal(self, signal_name, *_): - """Internal use: used to catch and log any emitted signals. Not called directly.""" - self.signals_caught.append(signal_name) - - def setup_dummy_installation(self, temp_dir) -> str: - """Set up a dummy Addon in temp_dir""" - toplevel_path = os.path.join(temp_dir, self.mock_addon.name) - os.makedirs(toplevel_path) - with open(os.path.join(toplevel_path, "README.md"), "w") as f: - f.write("## Mock Addon ##\n\nFile created by the unit test code.") - self.test_object.installation_path = temp_dir - return toplevel_path - - def create_fake_macro(self, macro_directory, fake_macro_name, digest): - """Create an FCMacro file and matching digest entry for later removal""" - os.makedirs(macro_directory, exist_ok=True) - fake_file_installed = os.path.join(macro_directory, fake_macro_name) - with open(digest, "a", encoding="utf-8") as f: - f.write("# The following files were created outside this installation:\n") - f.write(fake_file_installed + "\n") - with open(fake_file_installed, "w", encoding="utf-8") as f: - f.write("# Fake macro data for unit testing") - - def test_uninstall_normal(self): - """Test the integrated uninstall function under normal circumstances""" - - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - self.test_object.run() - self.assertTrue(os.path.exists(temp_dir)) - self.assertFalse(os.path.exists(toplevel_path)) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_uninstall_no_name(self): - """Test the integrated uninstall function for an addon without a name""" - - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - self.mock_addon.name = None - result = self.test_object.run() - self.assertTrue(os.path.exists(temp_dir)) - self.assertIn("failure", self.signals_caught) - self.assertNotIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_uninstall_dangerous_name(self): - """Test the integrated uninstall function for an addon with a dangerous name""" - - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - self.mock_addon.name = "./" - result = self.test_object.run() - self.assertTrue(os.path.exists(temp_dir)) - self.assertIn("failure", self.signals_caught) - self.assertNotIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_uninstall_unmatching_name(self): - """Test the integrated uninstall function for an addon with a name that isn't installed""" - - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - self.mock_addon.name += "Nonexistent" - result = self.test_object.run() - self.assertTrue(os.path.exists(temp_dir)) - self.assertIn("failure", self.signals_caught) - self.assertNotIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_uninstall_addon_with_macros(self): - """Tests that the uninstaller removes the macro files""" - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - macro_directory = os.path.join(temp_dir, "Macros") - self.create_fake_macro( - macro_directory, - "FakeMacro.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - result = self.test_object.run() - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - self.assertFalse(os.path.exists(os.path.join(macro_directory, "FakeMacro.FCMacro"))) - self.assertTrue(os.path.exists(macro_directory)) - - def test_uninstall_calls_script(self): - """Tests that the main uninstaller run function calls the uninstall.py script""" - - class Interceptor: - def __init__(self): - self.called = False - self.args = [] - - def func(self, *args): - self.called = True - self.args = args - - interceptor = Interceptor() - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - self.test_object.run_uninstall_script = interceptor.func - result = self.test_object.run() - self.assertTrue(interceptor.called, "Failed to call uninstall script") - - def test_remove_extra_files_no_digest(self): - """Tests that a lack of digest file is not an error, and nothing gets removed""" - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.remove_extra_files(temp_dir) # Shouldn't throw - self.assertTrue(os.path.exists(temp_dir)) - - def test_remove_extra_files_empty_digest(self): - """Test that an empty digest file is not an error, and nothing gets removed""" - with tempfile.TemporaryDirectory() as temp_dir: - with open("AM_INSTALLATION_DIGEST.txt", "w", encoding="utf-8") as f: - f.write("") - self.test_object.remove_extra_files(temp_dir) # Shouldn't throw - self.assertTrue(os.path.exists(temp_dir)) - - def test_remove_extra_files_comment_only_digest(self): - """Test that a digest file that contains only comment lines is not an error, and nothing - gets removed""" - with tempfile.TemporaryDirectory() as temp_dir: - with open("AM_INSTALLATION_DIGEST.txt", "w", encoding="utf-8") as f: - f.write("# Fake digest file for unit testing") - self.test_object.remove_extra_files(temp_dir) # Shouldn't throw - self.assertTrue(os.path.exists(temp_dir)) - - def test_remove_extra_files_repeated_files(self): - """Test that a digest with the same file repeated removes it once, but doesn't error on - later requests to remove it.""" - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - macro_directory = os.path.join(temp_dir, "Macros") - self.create_fake_macro( - macro_directory, - "FakeMacro.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - self.create_fake_macro( - macro_directory, - "FakeMacro.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - self.create_fake_macro( - macro_directory, - "FakeMacro.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - self.test_object.remove_extra_files(toplevel_path) # Shouldn't throw - self.assertFalse(os.path.exists(os.path.join(macro_directory, "FakeMacro.FCMacro"))) - - def test_remove_extra_files_normal_case(self): - """Test that a digest that is a "normal" case removes the requested files""" - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - macro_directory = os.path.join(temp_dir, "Macros") - self.create_fake_macro( - macro_directory, - "FakeMacro1.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - self.create_fake_macro( - macro_directory, - "FakeMacro2.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - self.create_fake_macro( - macro_directory, - "FakeMacro3.FCMacro", - os.path.join(toplevel_path, "AM_INSTALLATION_DIGEST.txt"), - ) - - # Make sure the setup worked as expected, otherwise the test is meaningless - self.assertTrue(os.path.exists(os.path.join(macro_directory, "FakeMacro1.FCMacro"))) - self.assertTrue(os.path.exists(os.path.join(macro_directory, "FakeMacro2.FCMacro"))) - self.assertTrue(os.path.exists(os.path.join(macro_directory, "FakeMacro3.FCMacro"))) - - self.test_object.remove_extra_files(toplevel_path) # Shouldn't throw - - self.assertFalse(os.path.exists(os.path.join(macro_directory, "FakeMacro1.FCMacro"))) - self.assertFalse(os.path.exists(os.path.join(macro_directory, "FakeMacro2.FCMacro"))) - self.assertFalse(os.path.exists(os.path.join(macro_directory, "FakeMacro3.FCMacro"))) - - def test_runs_uninstaller_script_successful(self): - """Tests that the uninstall.py script is called""" - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - with open(os.path.join(toplevel_path, "uninstall.py"), "w", encoding="utf-8") as f: - double_escaped = temp_dir.replace("\\", "\\\\") - f.write( - f"""# Mock uninstaller script -import os -path = '{double_escaped}' -with open(os.path.join(path,"RAN_UNINSTALLER.txt"),"w",encoding="utf-8") as f: - f.write("File created by uninstall.py from unit tests") -""" - ) - self.test_object.run_uninstall_script(toplevel_path) # The exception does not leak out - self.assertTrue(os.path.exists(os.path.join(temp_dir, "RAN_UNINSTALLER.txt"))) - - def test_runs_uninstaller_script_failure(self): - """Tests that exceptions in the uninstall.py script do not leak out""" - with tempfile.TemporaryDirectory() as temp_dir: - toplevel_path = self.setup_dummy_installation(temp_dir) - with open(os.path.join(toplevel_path, "uninstall.py"), "w", encoding="utf-8") as f: - f.write( - f"""# Mock uninstaller script -raise RuntimeError("Fake exception for unit testing") -""" - ) - self.test_object.run_uninstall_script(toplevel_path) # The exception does not leak out - - -class TestMacroUninstaller(unittest.TestCase): - """Test class for addonmanager_uninstaller.py non-GUI functionality""" - - MODULE = "test_uninstaller" # file name without extension - - def setUp(self): - self.mock_addon = MockAddon() - self.mock_addon.macro = MockMacro() - self.test_object = MacroUninstaller(self.mock_addon) - self.signals_caught = [] - - self.test_object.finished.connect(functools.partial(self.catch_signal, "finished")) - self.test_object.success.connect(functools.partial(self.catch_signal, "success")) - self.test_object.failure.connect(functools.partial(self.catch_signal, "failure")) - - def tearDown(self): - pass - - def catch_signal(self, signal_name, *_): - """Internal use: used to catch and log any emitted signals. Not called directly.""" - self.signals_caught.append(signal_name) - - def test_remove_simple_macro(self): - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.installation_location = temp_dir - self.mock_addon.macro.install(temp_dir) - # Make sure the setup worked, otherwise the test is meaningless - self.assertTrue(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.test_object.run() - self.assertFalse(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_remove_macro_with_icon(self): - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.installation_location = temp_dir - self.mock_addon.macro.icon = "mock_icon_test.svg" - self.mock_addon.macro.install(temp_dir) - # Make sure the setup worked, otherwise the test is meaningless - self.assertTrue(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.assertTrue(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.icon))) - self.test_object.run() - self.assertFalse(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.assertFalse(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.icon))) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_remove_macro_with_xpm_data(self): - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.installation_location = temp_dir - self.mock_addon.macro.xpm = "/*Fake XPM data*/" - self.mock_addon.macro.install(temp_dir) - # Make sure the setup worked, otherwise the test is meaningless - self.assertTrue(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.assertTrue(os.path.exists(os.path.join(temp_dir, "MockMacro_icon.xpm"))) - self.test_object.run() - self.assertFalse(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.assertFalse(os.path.exists(os.path.join(temp_dir, "MockMacro_icon.xpm"))) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_remove_macro_with_files(self): - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.installation_location = temp_dir - self.mock_addon.macro.other_files = [ - "test_file_1.txt", - "test_file_2.FCMacro", - "subdir/test_file_3.txt", - ] - self.mock_addon.macro.install(temp_dir) - # Make sure the setup worked, otherwise the test is meaningless - for f in self.mock_addon.macro.other_files: - self.assertTrue( - os.path.exists(os.path.join(temp_dir, f)), - f"Expected {f} to exist, and it does not", - ) - self.test_object.run() - for f in self.mock_addon.macro.other_files: - self.assertFalse( - os.path.exists(os.path.join(temp_dir, f)), - f"Expected {f} to be removed, and it was not", - ) - self.assertFalse( - os.path.exists(os.path.join(temp_dir, "subdir")), - "Failed to remove empty subdirectory", - ) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_remove_nonexistent_macro(self): - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.installation_location = temp_dir - # Don't run the installer: - - self.assertFalse(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.test_object.run() # Should not raise an exception - self.assertFalse(os.path.exists(os.path.join(temp_dir, self.mock_addon.macro.filename))) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("success", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_remove_write_protected_macro(self): - with tempfile.TemporaryDirectory() as temp_dir: - self.test_object.installation_location = temp_dir - self.mock_addon.macro.install(temp_dir) - # Make sure the setup worked, otherwise the test is meaningless - f = os.path.join(temp_dir, self.mock_addon.macro.filename) - self.assertTrue(os.path.exists(f)) - os.chmod(f, S_IREAD | S_IRGRP | S_IROTH) - self.test_object.run() - - if os.path.exists(f): - os.chmod(f, S_IWUSR | S_IREAD) - self.assertNotIn("success", self.signals_caught) - self.assertIn("failure", self.signals_caught) - else: - # In some cases we managed to delete it anyway: - self.assertIn("success", self.signals_caught) - self.assertNotIn("failure", self.signals_caught) - self.assertIn("finished", self.signals_caught) - - def test_cleanup_directories_multiple_empty(self): - with tempfile.TemporaryDirectory() as temp_dir: - empty_directories = set(["empty1", "empty2", "empty3"]) - full_paths = set() - for directory in empty_directories: - full_path = os.path.join(temp_dir, directory) - os.mkdir(full_path) - full_paths.add(full_path) - - for directory in full_paths: - self.assertTrue(directory, "Test code failed to create {directory}") - self.test_object._cleanup_directories(full_paths) - for directory in full_paths: - self.assertFalse(os.path.exists(directory)) - - def test_cleanup_directories_none(self): - with tempfile.TemporaryDirectory() as temp_dir: - full_paths = set() - self.test_object._cleanup_directories(full_paths) # Shouldn't throw - - def test_cleanup_directories_not_empty(self): - with tempfile.TemporaryDirectory() as temp_dir: - empty_directories = set(["empty1", "empty2", "empty3"]) - full_paths = set() - for directory in empty_directories: - full_path = os.path.join(temp_dir, directory) - os.mkdir(full_path) - full_paths.add(full_path) - with open(os.path.join(full_path, "test.txt"), "w", encoding="utf-8") as f: - f.write("Unit test dummy data\n") - - for directory in full_paths: - self.assertTrue(directory, "Test code failed to create {directory}") - self.test_object._cleanup_directories(full_paths) - for directory in full_paths: - self.assertTrue(os.path.exists(directory)) diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_utilities.py b/src/Mod/AddonManager/AddonManagerTest/app/test_utilities.py deleted file mode 100644 index 66035acc74..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_utilities.py +++ /dev/null @@ -1,287 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -from datetime import datetime -import unittest -from unittest.mock import MagicMock, patch, mock_open -import os -import sys -import subprocess - -try: - import FreeCAD -except ImportError: - FreeCAD = None - -sys.path.append("../..") - -from AddonManagerTest.app.mocks import MockAddon as Addon - -from addonmanager_utilities import ( - get_assigned_string_literal, - get_macro_version_from_file, - get_readme_url, - process_date_string_to_python_datetime, - recognized_git_location, - run_interruptable_subprocess, -) - - -class TestUtilities(unittest.TestCase): - - MODULE = "test_utilities" # file name without extension - - @classmethod - def tearDownClass(cls): - try: - os.remove("AM_INSTALLATION_DIGEST.txt") - except FileNotFoundError: - pass - - def test_recognized_git_location(self): - recognized_urls = [ - "https://github.com/FreeCAD/FreeCAD", - "https://gitlab.com/freecad/FreeCAD", - "https://framagit.org/freecad/FreeCAD", - "https://salsa.debian.org/science-team/freecad", - ] - for url in recognized_urls: - repo = Addon("Test Repo", url, "Addon.Status.NOT_INSTALLED", "branch") - self.assertTrue(recognized_git_location(repo), f"{url} was unexpectedly not recognized") - - unrecognized_urls = [ - "https://google.com", - "https://freecad.org", - "https://not.quite.github.com/FreeCAD/FreeCAD", - "https://github.com.malware.com/", - ] - for url in unrecognized_urls: - repo = Addon("Test Repo", url, "Addon.Status.NOT_INSTALLED", "branch") - self.assertFalse(recognized_git_location(repo), f"{url} was unexpectedly recognized") - - def test_get_readme_url(self): - github_urls = [ - "https://github.com/FreeCAD/FreeCAD", - ] - gitlab_urls = [ - "https://gitlab.com/freecad/FreeCAD", - "https://framagit.org/freecad/FreeCAD", - "https://salsa.debian.org/science-team/freecad", - "https://unknown.location/and/path", - ] - - # GitHub and Gitlab have two different schemes for file URLs: unrecognized URLs are - # presumed to be local instances of a GitLab server. Note that in neither case does this - # take into account the redirects that are used to actually fetch the data. - - for url in github_urls: - branch = "branchname" - expected_result = f"{url}/raw/{branch}/README.md" - repo = Addon("Test Repo", url, "Addon.Status.NOT_INSTALLED", branch) - actual_result = get_readme_url(repo) - self.assertEqual(actual_result, expected_result) - - for url in gitlab_urls: - branch = "branchname" - expected_result = f"{url}/-/raw/{branch}/README.md" - repo = Addon("Test Repo", url, "Addon.Status.NOT_INSTALLED", branch) - actual_result = get_readme_url(repo) - self.assertEqual(actual_result, expected_result) - - def test_get_assigned_string_literal(self): - good_lines = [ - ["my_var = 'Single-quoted literal'", "Single-quoted literal"], - ['my_var = "Double-quoted literal"', "Double-quoted literal"], - ["my_var = \t 'Extra whitespace'", "Extra whitespace"], - ["my_var = 42", "42"], - ["my_var = 1.23", "1.23"], - ] - for line in good_lines: - result = get_assigned_string_literal(line[0]) - self.assertEqual(result, line[1]) - - bad_lines = [ - "my_var = __date__", - "my_var 'No equals sign'", - "my_var = 'Unmatched quotes\"", - "my_var = No quotes at all", - "my_var = 1.2.3", - ] - for line in bad_lines: - result = get_assigned_string_literal(line) - self.assertIsNone(result) - - def test_get_macro_version_from_file_good_metadata(self): - good_metadata = """__Version__ = "1.2.3" """ - with patch("builtins.open", new_callable=mock_open, read_data=good_metadata): - version = get_macro_version_from_file("mocked_file.FCStd") - self.assertEqual(version, "1.2.3") - - def test_get_macro_version_from_file_missing_quotes(self): - bad_metadata = """__Version__ = 1.2.3 """ # No quotes - with patch("builtins.open", new_callable=mock_open, read_data=bad_metadata): - version = get_macro_version_from_file("mocked_file.FCStd") - self.assertEqual(version, "", "Bad version did not yield empty string") - - def test_get_macro_version_from_file_no_version(self): - good_metadata = "" - with patch("builtins.open", new_callable=mock_open, read_data=good_metadata): - version = get_macro_version_from_file("mocked_file.FCStd") - self.assertEqual(version, "", "Missing version did not yield empty string") - - @patch("subprocess.Popen") - def test_run_interruptable_subprocess_success_instant_return(self, mock_popen): - mock_process = MagicMock() - mock_process.communicate.return_value = ("Mocked stdout", "Mocked stderr") - mock_process.returncode = 0 - mock_popen.return_value = mock_process - - completed_process = run_interruptable_subprocess(["arg0", "arg1"]) - - self.assertEqual(completed_process.returncode, 0) - self.assertEqual(completed_process.stdout, "Mocked stdout") - self.assertEqual(completed_process.stderr, "Mocked stderr") - - @patch("subprocess.Popen") - def test_run_interruptable_subprocess_returns_nonzero(self, mock_popen): - mock_process = MagicMock() - mock_process.communicate.return_value = ("Mocked stdout", "Mocked stderr") - mock_process.returncode = 1 - mock_popen.return_value = mock_process - - with self.assertRaises(subprocess.CalledProcessError): - run_interruptable_subprocess(["arg0", "arg1"]) - - @patch("subprocess.Popen") - def test_run_interruptable_subprocess_timeout_five_times(self, mock_popen): - """Five times is below the limit for an error to be raised""" - - def raises_first_five_times(timeout): - raises_first_five_times.counter += 1 - if raises_first_five_times.counter <= 5: - raise subprocess.TimeoutExpired("Test", timeout) - return "Mocked stdout", None - - raises_first_five_times.counter = 0 - - mock_process = MagicMock() - mock_process.communicate = raises_first_five_times - mock_process.returncode = 0 - mock_popen.return_value = mock_process - - result = run_interruptable_subprocess(["arg0", "arg1"], 10) - - self.assertEqual(result.returncode, 0) - - @patch("subprocess.Popen") - def test_run_interruptable_subprocess_timeout_exceeded(self, mock_popen): - """Exceeding the set timeout gives a CalledProcessError exception""" - - def raises_one_time(timeout=0): - if not raises_one_time.raised: - raises_one_time.raised = True - raise subprocess.TimeoutExpired("Test", timeout) - return "Mocked stdout", None - - raises_one_time.raised = False - - def fake_time(): - """Time that advances by one second every time it is called""" - fake_time.time += 1.0 - return fake_time.time - - fake_time.time = 0.0 - - mock_process = MagicMock() - mock_process.communicate = raises_one_time - raises_one_time.mock_access = mock_process - mock_process.returncode = None - mock_popen.return_value = mock_process - - with self.assertRaises(subprocess.CalledProcessError): - with patch("time.time", fake_time): - run_interruptable_subprocess(["arg0", "arg1"], 0.1) - - def test_process_date_string_to_python_datetime_non_numeric(self): - with self.assertRaises(ValueError): - process_date_string_to_python_datetime("TwentyTwentyFour-January-ThirtyFirst") - - def test_process_date_string_to_python_datetime_year_first(self): - result = process_date_string_to_python_datetime("2024-01-31") - expected_result = datetime(2024, 1, 31, 0, 0) - self.assertEqual(result, expected_result) - - def test_process_date_string_to_python_datetime_day_first(self): - result = process_date_string_to_python_datetime("31-01-2024") - expected_result = datetime(2024, 1, 31, 0, 0) - self.assertEqual(result, expected_result) - - def test_process_date_string_to_python_datetime_month_first(self): - result = process_date_string_to_python_datetime("01-31-2024") - expected_result = datetime(2024, 1, 31, 0, 0) - self.assertEqual(result, expected_result) - - def test_process_date_string_to_python_datetime_ambiguous(self): - """In the ambiguous case, the code should assume that the date is in the DD-MM-YYYY format.""" - result = process_date_string_to_python_datetime("01-12-2024") - expected_result = datetime(2024, 12, 1, 0, 0) - self.assertEqual(result, expected_result) - - def test_process_date_string_to_python_datetime_invalid_date(self): - with self.assertRaises(ValueError): - process_date_string_to_python_datetime("13-31-2024") - - def test_process_date_string_to_python_datetime_too_many_components(self): - with self.assertRaises(ValueError): - process_date_string_to_python_datetime("01-01-31-2024") - - def test_process_date_string_to_python_datetime_too_few_components(self): - """Month-Year-only dates are not supported""" - with self.assertRaises(ValueError): - process_date_string_to_python_datetime("01-2024") - - def test_process_date_string_to_python_datetime_unrecognizable(self): - """Two-digit years are not supported""" - with self.assertRaises(ValueError): - process_date_string_to_python_datetime("01-02-24") - - def test_process_date_string_to_python_datetime_valid_separators(self): - """Four individual separators are supported, plus any combination of multiple of those separators""" - valid_separators = [" ", ".", "/", "-", " - ", " / ", "--"] - for separator in valid_separators: - with self.subTest(separator=separator): - result = process_date_string_to_python_datetime(f"2024{separator}01{separator}31") - expected_result = datetime(2024, 1, 31, 0, 0) - self.assertEqual(result, expected_result) - - def test_process_date_string_to_python_datetime_invalid_separators(self): - """Only the four separators [ ./-] are supported: ensure others fail""" - invalid_separators = ["a", "\\", "|", "'", ";", "*", " \\ "] - for separator in invalid_separators: - with self.subTest(separator=separator): - with self.assertRaises(ValueError): - process_date_string_to_python_datetime(f"2024{separator}01{separator}31") - - -if __name__ == "__main__": - unittest.main() diff --git a/src/Mod/AddonManager/AddonManagerTest/data/DoNothing.FCMacro b/src/Mod/AddonManager/AddonManagerTest/data/DoNothing.FCMacro deleted file mode 100644 index b20265d396..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/DoNothing.FCMacro +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- - -__Title__ = 'Do Nothing' -__Author__ = 'Chris Hennes' -__Version__ = '1.0' -__Date__ = '2022-02-28' -__Comment__ = 'Do absolutely nothing. For Addon Manager integration tests.' -__Web__ = 'https://github.com/FreeCAD/FreeCAD' -__Wiki__ = '' -__Icon__ = 'not_real.png' -__Help__ = 'Not much to help with' -__Status__ = 'Very Stable' -__Requires__ = '' -__Communication__ = 'Shout into the void' -__Files__ = 'file1.py, file2.py, file3.py' -__Xpm__ = """/* XPM */ -static char * blarg_xpm[] = { -"16 7 2 1", -"* c #000000", -". c #ffffff", -"**..*...........", -"*.*.*...........", -"**..*..**.**..**", -"*.*.*.*.*.*..*.*", -"**..*..**.*...**", -"...............*", -".............**." -};""" - -print("Well, not quite *nothing*... it does print this line out.") diff --git a/src/Mod/AddonManager/AddonManagerTest/data/MacrosRecipesWikiPage.zip b/src/Mod/AddonManager/AddonManagerTest/data/MacrosRecipesWikiPage.zip deleted file mode 100644 index bbd30539542a5556d388877b22892998af41f6dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30203 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 diff --git a/src/Mod/AddonManager/AddonManagerTest/data/TestWorkbench.zip b/src/Mod/AddonManager/AddonManagerTest/data/TestWorkbench.zip deleted file mode 100644 index 187c9b6c34ce610c7802c155071ddb80f280484f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25149 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 - - Test Bundle - A package.xml file for unit testing. - 1.0.0 - 2025-02-22 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - - - - A bunch of great addons you should install - TestAddon1 - TestAddon2 - TestAddon3 - TestAddon4 - TestAddon5 - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/combination.xml b/src/Mod/AddonManager/AddonManagerTest/data/combination.xml deleted file mode 100644 index bc72470a0e..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/combination.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - Combination Test - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - Resources/icons/PackageIcon.svg - Tag0 - Tag1 - - - - MyFirstWorkbench - Resources/icons/PackageIcon.svg - - - MyMacro.FCStd - - - MyFirstPack - - - A bundle that bundles nothing - - - Mysterious Object - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/corrupted_metadata.zip b/src/Mod/AddonManager/AddonManagerTest/data/corrupted_metadata.zip deleted file mode 100644 index e2f001fb8f23642903f4309e1c931b9bb4108104..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9300 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 Wdg#}@dF*8V>B$xU&(ZmjH~$0lJZEPB diff --git a/src/Mod/AddonManager/AddonManagerTest/data/depends_on_all_workbenches.xml b/src/Mod/AddonManager/AddonManagerTest/data/depends_on_all_workbenches.xml deleted file mode 100644 index 945134bb5e..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/depends_on_all_workbenches.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - Test Workbenches - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - - - - MyFirstWorkbench - Resources/icons/PackageIcon.svg - BIM - Assembly - DraftWB - FEM WB - MeshWorkbench - OpenSCAD Workbench - Part WORKBENCH - PartDesign WB - CAM - Plot - POINTS - ROBOTWB - Sketcher workbench - Spreadsheet - TechDraw - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/git_submodules.txt b/src/Mod/AddonManager/AddonManagerTest/data/git_submodules.txt deleted file mode 100644 index 2a447c61b6..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/git_submodules.txt +++ /dev/null @@ -1,23 +0,0 @@ -[submodule "3DfindIT"] - path = 3DfindIT - url = https://github.com/cadenasgmbh/3dfindit-freecad-integration -[submodule "A2plus"] - path = A2plus - url = https://github.com/kbwbe/A2plus -[submodule "Behave-Dark-Colors"] - path = Behave-Dark-Colors - url = https://github.com/Chrismettal/FreeCAD-Behave-Dark-Preference-Pack - branch = main -[submodule "Beltrami"] - path = Beltrami - url = https://github.com/Simturb/Beltrami - branch = main -[submodule "CurvedShapes"] - path = CurvedShapes - url = https://github.com/chbergmann/CurvedShapesWorkbench.git -[submodule "Curves"] - path = Curves - url = https://github.com/tomate44/CurvesWB.git -[submodule "Defeaturing"] - path = Defeaturing - url = https://github.com/easyw/Defeaturing_WB.git diff --git a/src/Mod/AddonManager/AddonManagerTest/data/good_package.xml b/src/Mod/AddonManager/AddonManagerTest/data/good_package.xml deleted file mode 100644 index 3be6edb282..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/good_package.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - Test Workbench - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - Resources/icons/PackageIcon.svg - Tag0 - Tag1 - - - - MyWorkbench - ./ - TagA - TagB - TagC - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip b/src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip deleted file mode 100644 index 766c988fcdbe284d8c08ac3f45350ddf6b034dfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9447 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 F{U1BmPwD^w diff --git a/src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip.sha1 b/src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip.sha1 deleted file mode 100644 index 2d0b37ee0d..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/icon_cache.zip.sha1 +++ /dev/null @@ -1 +0,0 @@ -67b372f9a5ac11e5377a4075537f31dfebf61753 *icon_cache.zip diff --git a/src/Mod/AddonManager/AddonManagerTest/data/macro_only.xml b/src/Mod/AddonManager/AddonManagerTest/data/macro_only.xml deleted file mode 100644 index b20295cc9f..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/macro_only.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - Test Macros - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - Resources/icons/PackageIcon.svg - - - - MyMacro.FCStd - - - MyOtherMacro.FCStd - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/macro_template.FCStd b/src/Mod/AddonManager/AddonManagerTest/data/macro_template.FCStd deleted file mode 100644 index 9cc885bd8d..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/macro_template.FCStd +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- - -# *************************************************************************** -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of the FreeCAD CAx development system. * -# * * -# * This library is free software; you can redistribute it and/or * -# * modify it under the terms of the GNU Lesser General Public * -# * License as published by the Free Software Foundation; either * -# * version 2.1 of the License, or (at your option) any later version. * -# * * -# * This library is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with this library; if not, write to the Free Software * -# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * -# * 02110-1301 USA * -# * * -# *************************************************************************** - -__Title__ = "TITLE" -__Author__ = "AUTHOR" -__Date__ = "DATE" -__Version__ = "VERSION" -__Comment__ = "COMMENT" -__Web__ = "WEB" -__Wiki__ = "WIKI" -__Icon__ = "ICON" -__Help__ = "HELP" -__Status__ = "STATUS" -__Requires__ = "REQUIRES" -__Communication__ = "COMMUNICATION" -__Files__ = "FILES" diff --git a/src/Mod/AddonManager/AddonManagerTest/data/metadata.zip b/src/Mod/AddonManager/AddonManagerTest/data/metadata.zip deleted file mode 100644 index 2f30f1b8ae166134005957ec24babfa18839db4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9325 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 - - Test Other - A package.xml file for unit testing. - 1.0.0 - 2025-02-22 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - - - - A thing that's not a workbench, macro, preference pack, or bundle - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/prefpack_only.xml b/src/Mod/AddonManager/AddonManagerTest/data/prefpack_only.xml deleted file mode 100644 index 8e8dc5c741..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/prefpack_only.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - Test Preference Packs - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - - - - MyFirstPack - - - MySecondPack - - - MyThirdPack - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/test_addon_with_fcmacro.zip b/src/Mod/AddonManager/AddonManagerTest/data/test_addon_with_fcmacro.zip deleted file mode 100644 index 46dce11c5b372f4ee9e07a8d183ad6d22b2a85b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202 zcmWIWW@Zs#00H&2#i3p6qgT5D*&r+k#38B0CBBKtMfrMe&R|+uAtWQSSOJI<6-t1T z3b`Oz9fiyig_Qi%Vuif?l8nr}bUj|Kf}+g45)GyB)STq}+*E~no69BtZX3Vj6fI!q@BQe0V@(ARR910 diff --git a/src/Mod/AddonManager/AddonManagerTest/data/test_repo.zip b/src/Mod/AddonManager/AddonManagerTest/data/test_repo.zip deleted file mode 100644 index 6449777ab5191a7658e2be93225ad50a2bd45ff4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23052 zcmb7s1z1(f_cq;9(jg(8hwg5WlE0)#TS z!%OG=a|5ufKe%E48v|r#YieO8A1Q+53qXMx+NbyQCpn^AA=^>+w|Fdrebv$u@+cVp zm4k98R=~2-X0a=E-IG&)9;@x3@@TRu(%mr0(DxXfPtG2XM2e$q^Q#vhnHHzZe@zeU zKQQRivFHpWvO9se(`e2MU5zUoo?=re;A?;WUO&(fZO))-`z?}h=@CynDUZ>Kb)A&O@PKu%r-y^+rP~T0dcE5Sn%)b zC+0M_v$Jyg`z|870h$Hn#iA2ZTsa+j9(IMav^_jijBQJ5;l2C?h z-at?fq0%NX{j!5~vb+J4R8X0qDsmveC(V=0T#6sUs0ia~Sh^HSl_}Yg&SuFpq0=n~ zDuaz<7d)=j*r z4UJdJf;hpcY!P-u#seO)4^NdhQIcDB4)m$~FW9@(MFFpQOg^P!ntPpb4hN`5yf;M6 zYC;z6bfk^${N6V0B_y~5LCZ1FX)fS@q=l-Vh!xZ z09aj_sfrHL^rPzXxt~L7Wdq2kk>fPa#kbd}xI*jR4_XHw7kIjr6BlDs9b-yNoqrz` z=y}xk0aeB1O;q;?UJ}xYe65~XVO?wRK;#}#nxy_yZ#0dEj`MFuvq!MCtJPI&*Lv%7 zEDGC~`BuUdgJ0uCk4_ASkv^HI&zmC$#G4~FqTJ+Lhd`F&pw?Ax5>N|PmMIcWG}<98 z#70BwS|ofY&BX_%+qVSL5aUZ*Jujj|fE{s>bdyAqqNXrLR7CI7vK!)^e`fL;Wo9!a zHd#KGR2MY4jSV*Qi(tjTA{takzr+}T3igiK zL2-GfbXkjDqfk@E38OIf0MeejV`JbnHN1Cx@k|4F^xg8g+q0%?`|Irk%P$A3I8vGi zirAQ``)*_Fo-L`2n{j*0gcVgfCVH$O-7b1kugZ|~hmt)Z)FpU5k7+7+inHJ72UibS z?h0h+TQL!}DTU`85+r{M_s&RM4y|k6&HQ1*7O%McBGPWgVuK&H_s#9ebbX@%US&AqjTuV|BMhG0>Tv&0)pvR zkB+I6jh(H9vz;TO+wJtU0owjGJIgd?Z3%fWy%Jk6!hwvD)$YKGwxoWp%z(`Gi3_i+pE{tf|!_ILQG;HHd*k1P2(&ag=w>!pxEJmB&{5Hu{TtBtIAT zcdga+8-`_&&o)ImH!F^3vJvWTIS&t!;3<6J)Ih(atz8fiq_3|-U&lOkR60Z@yUd@$ zj8Mdt6l*vbp@(!RGnUONAvUBnGu~R<0y1oEXP%=1e1nrlj|{0sscdI{5ggc%2uNsX zf!&WERE9r3C@HXKx_Z}9?fPio38khMQboB%W_}sVqmL0j6%j2I_6xGT2EVz$!Viuh7!w@=NykKb)fo3Zrj02>yAf5ARN@E)o;qC( z^*L`OO48dgC<(H$?o^9iGi9{uid8&hWAR0m@W$lNtlaeC4$SoS{x;k8wpMU!jv?t4 zy)3+`kM__e**EOhot;hR%s$V);lvIivP<KFfai=FEufi(Hgu;e%2IIf-diNu2@L zB|yIFBd&e*YzhjJ+LDq!O(e@B%T0ie)p%p1pKaKt=!`AocRBAal`JB8SdsR=-oV$1 zvSabfHZxc$s6n=(+iCVpia@4LE?EU6ljqkCF*T#J90x*?iw0>UaXXHJw*6Mhn3nVv zmL`-}yYs12xg$Ock+WrGSaehayczSN^n_Uusi1)`Uz#|Eh7dU(8H8zXhRehm2W{=p z&S_KkzZlO7HMM#7k|Gi(Q2%ZEp@1Uv5L;HVqy8o<(yQ~gGnwq+i)Ij3grMS1OZ3OH+aI1iAy9*-z8n~ zjGtaHlc`Sk%7S+L3t5V<_YM*5UU+nyFl>Yzh{8MTlF<0~M{yvUgAn+Z27=GOy~)Wp zH*Sj2O&ew^H}Z0Zi~mrG`KD8OmCAY+r7D@q4X>-uTq^L{smm@UO!8W#dz>|q&ZdUn zYh*f)(hZu@7|9|HRMj`cW0wj|5bAQ9Bu86V3N$#=D0LG}RCpO=#Arh_q@6XQ8+Zi^ zIL~jUrOMxR_aJ4bJ6dL*GG#P>-8^KbCR+OXZDJSFxjqA}t=+zGpi&gUdw#!ON0n{O z8894-&nM(Rn7cLWmh7u?Ez2ekYxtQy#q9~xQ>_&2Qe)iNr`%Lt#VSU&Qe%c(Rt<(Y zqC@p;8?SJIVKs8AM9Eq;YtTg=BSu=%;YuWN7(_VaJ&A>~>p1+6;4p;u-M6x|-%(S% zGGKH#ASFKuw?%4@;Vk`_KRETFA@HhCupe`iJ8Ls=rKo^KDym1$A5_JlD{7RlJqk;T zhu9+C&!3Sq)Tmp)esIcCs5dwKs&*@zjIU;9ytJ zQ92K;CMaR~b$CNyx%@(H4gl}%fRasztB=0F}&swFr z*0%P=EPi2$MBJXa=<|NQ1r^){K;L8}{!-xcPL!Y+OcWxU^!rB(GO)=F{DL_=DIqUe zYgqX0wwA1&ZYrlQVI#}Z4Hlh?F|LCQ2F|Lio^TI5cn$*-%1b*;e%8iW^=vfQ0ex(j z6G3&b_v^O;nn*6R3EgNZK4dih+Q|=kwnCRaB4<5a@@GOyS9)Aw`;?>*Hl{*m`r6^o z_yZe)-H`M@y`PMpDre&c7Kg1o7sB|=TCzGnqx4z+88P$j_QN!k4=<#n-90Yz6r&#+ zEr!sCM|7B>1dlhIf1Fd&a~qhO6?3CyI!|HP@^U&7Tq^efcw*SCt&as$!zUadp6rVv zR|`3F7(Sp&C3!m}5aMpDw`J=_?(H)tslB|a7*Aj2S|xLq5kU1MJ-PbpXOy&klwB$1 zg?uv$@?(Lj?ziEusthY%T=Dv8(QbI=zPpe<)p!MH~r$9 zp|`D@e#3Ird5c0R6$8QxaVB!h4_v;%2GsME553BM_^45;*?sFB+B5VALi3|jWm5)D z67xEiA=}Yh?*-=bb()y2E~wd&FFaaR8VQR`7AI*vRWI#^By$(@e5&Y-s!=JvL)q1Y zhwqU;*8k+oP&I1D4YeE?;?bjB%S*66vSu3HjAm~)a|8R&*K7*Pd3zZ6_1Xe%)W3So z+S@rfGrHIt1D#F&dcQIbC}aAA7bU|t8AgEyer)dW%;=;EsH4uYOH2D@Tbl=i%{I)P zuRa^fnTv(%z>(A@P=heEfN`%^>_wEB@=!#xE!Ocl!YOgR9)}rm1vP8ZvmVYOX!NOz z&tE=mMdlvU1RBJqU)B*MzwvoE=Jt?1;nbFyjfcw%!Sm>al;c(LpysZ8l4JZ4O*l^8Xvz?t45A; zY_IC}SLVllYkFTEp#{Y4a7&y;zJgGa^2{WnG%UQGN=}?ECnc{sJnK#usbTjoN z-%ckLGnI$6)OoBj`_%6>VQP01?Y>QM@3T?hSpA+#+Czb<9=f_i!hoJDe`-+S(?xFg zFqwi!r^W9f13`B4LA8(PT{_%4cHWOWMtF1@)33##5WvFdK55NWB_SJR>oHT@J0ZY& z`hd#cP!h6j=2+2WeQ>N6xl|JBOHL&=Vs1O%#5Q_zJb}c;HSmId-hgmHuc_5yYyP^+ z#;>~k)mG#irq_Wlu;#>>sLW2btg9RGmFHhpsY!tH>{s8&!OQw3UtN+gjYacs+QEvI zfy#pDRV+gI6WZwLbbL2K67Y*=EH55huAFO4t@lilSiK8|qy?5GeAte)d16$P`kQoExU#|+g_%7}fMYp{-BOJoqg?SuW zFwb=tKzqtP^|M;O+{N(43w}U?oK{d4u`Vn;oFV=Jt!v|pOiSV;l*Dmigm{Nao9akE z>&iarl#Dh^V_7>Kc5JPJlRze>_Xs4OD^D$UmT3(}2$Jg=umcWX>gD1-#yUY*RdHIv zZ>ig6mBm~}^EP-cZDR@pTl57I#TwKlnIU)ymmcZ-+zEfXF`6ve6G?+DY%<|fT=MLc zKD;1QI|_9}Zg*Zb#Hi|$*yOrW=ZGy)&=AV-Mi)#+C|tO)7`@s~wWP1gDE+#gQ+xd! zEj#)OV`5(G$i>LTVmRW+*v{el*q9MzUP5-iV&3=b&lel9tz)eeYWkrOT&vCrN(a~9 zhR}Sj)cId5brLgH1wd@RdVx_tgQpT&i~=-+_-d=}V2GW^otgXgo2iKE%Q zS?v|AsQ3ba-gS75r3iSA+3=h#w8t|}D&ShKX0fD6fFV0|JOk+c1EJg9F0 z$pWq>U3#_dO=ZwfeuHgNxG z$o+?$fGsEph;i88tWUv?(H{7>bNqqg2vi+WnFXMG+P1FPv%ZM=z_hQE>>Q*b%l1?@ zIL{8>-zXD=t>Z|EkJQ<7PQhc5mCP9jFLidXzi&G?FPA7v^?J*hPmlYhZ=1VX5<;L# zy`c)DC9=9mS=9zX2M$6}F&!{lmA-Houl3!l%7SJFmVk9=ar#EWM`26))9-RAD$rFA zDx8#g>1?x?y3^5HO>FR`VoIu2&;3S#tSFW*Vy#jj$gGif2m!?-wA~OjcBAM zC2x+YO@Owpz8Z;nN4ZgK6Vn6#WPFr&H9gekVVZH+qo)fEYvw7UkH3{`a0ChC<@V+& zZy(KGSvSxEW}SPlw1QElKE0mh@26pS6_)TmqKMyYyh=ryq=#*}HJ3I?98^jpr?Q4D zPA2vtxHaV+JxPdtK9*J@S;1EYW@aX;ny#)B&tr?v>(+C8+9dMKZ3gM19jSvSUwTIx z&fkp55aeFpR7&bWJv@$GgnBG+tsR#-EG;`rq}uCp)%GNg`*lxai}7%9;kl^9nq>m- z*9~IW-{LdOsZ4oYz z#8LA&{jR;XF38b>0gpO&^;VX@PRsKVy+CH?clq{&St#N;yzLV4l)XX-L|VEYBNfR| z>)=x8&J!q#6M07gp%ApiA^2k;^D}i{H-M1rPOHwe1L7w0H5+41iau1K4BNxlmyEQd zCeLMAExc>{cgl4J$vH9wT2J_p4p9%!gg(xHj&C^g7ek&JU$!@E*7G2A_J;oFoIyiF zx@ZB<8GZ1aq4=Hiv3GGY|0|RTR9&>11E6>d-e7AVOxF$T`ZSl-1}fvxN3eGHJ?iF6 z6Ax|Sbv5Oa=R50BtafUd#oJrv)=Cugx}-3>SZNqNpkBZ7TQ2wIk&oh`1;u3Qe>A%&mD8 z+06(x3(#3Z7$u~)am+Z?^;Gh6f1qs{Teo}~uQc=XJe+sWWOdR-wcasawAX#}iXn&_ zbs5|gjnE+ju@90LWH{{12fN)w=bP`u*|A<1Y96s1h0f&d3^?hnL&oQr135KIw|)k004*VU!le#m&X8Gg~u)l~GNIY8uXs1$pZen1cW4s(e_-{Ev_ zkLp|lst1aQYiLHa-_fXexFXjfGWV;rHnZ0OZs`T>ossBoznfI?GQQt>fNvIv-Yk|> z62N3vMyGd5yemD1Tt(&^z6wVYwJ$At_6)#n55nnBa>F?B<_P#*<39A z^eIPSvzKzyI#z>Sfq}gYD+r-$ho{k3j+ZqT?4lLval$E^DKCn|1A<)R_&1IGs4D9M zrhzwpRj_37I%!#-M<;h^T0B!&hUKQi`bC^)s|5K3*V5%M-pvnxXudi@7hAi&ARJbC z=>u^vZNur4Q?H%(sNw?D!3WFUhVRc*%@Q5_CWl=WPZs%#)uIx*v`yt*3igtA*K!6O zmU=1cyH+esdUy@yp)B`R$=N;ZwLmQawBryV+F3WPyeF66+bv87+D^PBK4*m7qcmUa zX)3RPDNS;4isP4T_-!ohXkr9(`rlG3UDL{LRubo$;d_{lL{nn5$MmI=^D1u;2;S!G zB}CDP5eDB`2!U*=462(co4kHFa~6-YdFz)rY&B6C5<^?M z2|DTJlZipcAsfNLi_sT{XeZId(%9)^L*%%DjgHDFMWaTrWVEd}^wbQtg0KuYB8sy-+04D*DVaVY-U z>Da3@?eC2;j2~Z%V#f*PsWZ%~o6cxz5MqTh#K}n=tWnYRj|Wl4i-zlJ7Y!iyaB%1J zz8_J|uhI^io5w49YGM8u#r-t>gi1acsL#ewOS8h^Y5I0ymhwRYRdSN6TxuP|70COr zxun)qQDC)@lkkk-WfFdE`9ybn=mV{ZZixg7B6q`BJ!Cm35ghzdJzFyJBoEk$B_5hJ zv*$`W8#xWJlddR4oeP?(K^J1uD#-YRY9?~%$#gaGt|(}hg{3%JmXpKK0cE4J7FdC1 z)TJCo$NI-IKKA3$qc2Kfs4fG{ym+&py+FrO9(wCEI>pLT!$Fby$#5as*wpy?AaMlr z=0eoO0;QDlZI1xI*>EiNKEMxPbOKqb}mk_!cPiFwC*8Gj^tOlobzalN39?+%P~CC!8O z$(j97ItnPV?ObZBCyh4tEEmvdB)vQEA+={7ROMUO-9(QI6T7UEOB9JpEmq|}81DJ* zw?|F+`mAd|aD**_?L+bERUnq+ZOuJ#mLi0{!rGSkKr>SumOEgCPl)_!1@-c=n(-{5 zX#>v;qQb-QXcuod15reQVF7Wg=d-{}pTL&uJ)m7lIS78r;Jl+b${E3@;DErU?4|y` z&G>B6TLKaNg@y46;ygN@csXD`b2RUE%MCqHV3Aeyt)u|Oun=NURqi5;8MQB?@bj8J zbFRm7MQkb3yuKNpgnh78L}@KI+f!)4Q$5SiY}JXDH#xcpKmk(tLya@vaGofb%wy~8 zVqcS*eocznevI%@qIZ3EcR&zTh)Cf(6IJi&q9i-$asfSVca4%b^6P=$ljM9??j}0Z zRl|jmy61t%64tpNjTJg2*P=cypIn$P!JZ4c_XfQEVpp+uacaJ{4)L(_P?wOEeQWxr zi#DxUJpK_>QSQ3t#CeO#Ukt3r^ZhA;6m=@9(o4uc7NX%#NxgtHrd|UiNfAYb~F~2@CduE_GVl8M? zez9>A)Qr$rBQ;MO`iXwyt~l{h7}E=-*Sf;BPwFBVXJ|-Y;+ztn#Z+wDT-rw92{Tlf>OF{LDJ9quZWC88 z)m6}|SyRxGj=q#g$SIvoPWo&L-H}pe=uPXK=r{$N_&%L|8oi_WnUQjYhd-P?G7poj zlmpb9^OJP@@7jd$Pjz|q&fC*!d0j+kj2R*^Ja)C89Fdw0TuJ0)cjCQrr#9)$*z!0g zi(>_NPJ4?jI(6pkmh8qNI6?$$Mor~tvKYp@g>p>N5PYkwo_~f=CRIv}(9Tk&Aa@Xg zs;Zg3ZU#TXa#WC1r5%Kwtxjm9ZnzxD4b3WjDloB$Jn}U@>|^veUq;pknU{Gbvf;49 z(Mcmq1zbs7xONLeSA^4jt$A?Y>`zh+s>q6hPNxIk9mWwZ<7hV0kHZ~3dK78Sn~q7) zfjZg%Y6Li9xOn7q;n7~9A(?lP&6WuXiZ*;^dqX#70-YI!tqr&$c1n{O24M!q$s%B{ zY@<;mwz-DSD7s^D?yDy0z>uW+L9ki-mR+*9J1IP~e<_Vgn$EVVC0B$eAzl%K(lxQk zHtHOsK$;H0nU6}ti$piQPdH-#-Avg9a(+G|Wyap0`6BOK<20f{J45o;A`!VSaVqSI z>Fn{~!D_=f7ALB-9*JM64I6v_ydYsY#ZH!0^4oVCP!>3P?n+3zqI)U$NZ}>DRrM|C zI$ARpTr&CTmr9PS=$|U-;nwH)dBcM6&a9ME&W1z2GwU5k#PFp>yz@h<;79c;u@J+* zmYabV!yiHhdMUp^f<1dKa8%f9{CR-hcfsM~2cMlA#a1?KA@rp+D-pBjp{9I8XT#1J zpRvWXokmIu;%f#cyvsAtUAJ)t-+z&c_p^QDRF_#I-0jnb-Q43>y6K6P9=Qyq@%1fV zfq*S}YeME*j}BXDnM-_m!FY-rICQ!myUJ{8o(zpBY8hmWD*n?wjbf&wNwHLU#Q9g( zD>~oFx)MSTCr&9`JO1q8Y@Y)v2z%Ed^<@@zL#x3^!*F+ic>YNlDDF2#~{Ub^MnOL~~ zFHCSz>R0Flp!4?_ury$J3G4K|q>~PTJ{eUfZy{5&ZG0*JkS}Z=Ui6C3wJ#UJ;nReN zSvT7(FJXE7Bkf-8(m=ikydl+e2&1naSgV)xb>PPviA`(!_bS_zy(mg!ok8WNPdJgU z>8saJqI#eelJhk%DDGVcuQK0WLYz7LlB{uR-hSW<{oL2MeRF6NC3}<>Llj4=v6+^l zpO&ly%%Sq&^1Av69Y&c&L*$r?BrYyuODfrx)a0*ISXKB|pu1I3r6#j0I#z>a8q=6F z9wpU0<4u-NILfqq5 zPrf35X@GQ~AvQOF-*LGfk64l)uzJdA#uGY<7HWsy#(`O;|9Q~ixi|5v)vAgf=tl{t zeLyVlO7buAlnw>C_I}FsgbY?jZ;eR)xnvoGLpa)ifq+;<`W;^aUal}Y+cAR7O+Z$5 zF3x`~T_V-xoxm)pfK(gQOM$X^mUV|Hg}A8I#yFx&mNGsYMFMo)utFK%j$q@uv73c@ z2=TE<)6qCa$8+G~Y&~*Db8~6k+mm@C2XfnpEGeD{fzZJj_~nE#5PC-#Hz#XMjHpZA zqrxKV_fAq2r5$6Ds74X3I*bYsPKy?qkVhJ+WfJ~{=R|5eDtYy)ktzaddg%?Lv+%w8mUg=pGshyW*EnuP4PQiSY)9Ui)!e)?L7|`E9puUCVQQMM;HLsrxT&T6B^EH_zI;-2yDba=XAd`lbyhNJ zPTZpoZt;2v<`G`Lysc1rhz;umVmM-bvkObY#-TK3IDFO7bHrL--J_b8m?)%+pmoJ# z+L>Wg6*iD}ZVxrxTjr9@4H4T16q&%i#I!N_1CTNX1c!@biH&o`%lgMK>+cxIt#hmeR;3>FKDp=3~5IqjqRmUB_hRjQQw*=bCXvM$x76VR^dyMlxYQz*UcwI_t^91 zTpI1+=b=B56X0eJz?2iFjt@rExK4#foNSzg^?ZR=P2|skx2BEYm@rslzc{xvX5Kw{_{x*rMDxG zMz~MII}&0sr@k?LGK@vX*&I@XGwTB+dFL-tn zQOib;^H9NcJz&#+@cl>P@2HOP`L8~v&kkS-q*^lTvRm8$131*kpGqh{Sh=1bsE^sQ zOvV$L2#U0TeNeTz!c&kBn3agglgGE7#?!NISFf6fh^6DVo6 zd3$UQ{bHp0(5b$KC`6gN1DYtom;Oe!pUlR+oS{u_p*J=s*q+069(qKRm%^jOSm?B2 z*nM&pX7Whicox|F;W(_XS;Z;SRb3t^mH#$aOe37t{#hZ%(5@k|+N7Gm2ZvOwMcL7> zf_5e!BIU=<;hpAQmqEOG^Xe*2B4$B2fY~edEz+Bmap`oaAkOA|c`aX}H>j@j!_%_@ zl6jF-brBMUxd&B>Oq){+vLK}y!V#D^PE!>9GJ;8|>4~afnb0)5G z+KS_Hc?rCM$YUZohvtxS9wbag( zP7`ZhJrH^*HxV*n+3OvaLBhQf1z{PVy{eE?oz!dfjI)IQ%Y>A&ng^(%L~v459wWVr zje$d|VNAJ5t9ePU_R3{#Bk#F@i*zk!hIL}N`q0v+r)ni^eLaN^93(D+w&zF~R&{lIM_CP+C*Tv#>Ut*@j$>46Qi{N6Vec2L{08}g1o!eW70TI9o~ zzDXbd;KDv?9kmNz&d>_#v@efy5~7~u&=!3i6@0xwOY*gio&WWc^PW%r|!;Q}Cn+epH4mF(@L(qC6H}TZSs1_2UsfKIc?Cj-`k$ zfj$CHboO%4IuB|AWuOzVa0wANnqRwmjV!MYfL~?Qsx2&@xyqhk-63PP$F6emk(t7P z58#HB@(D}x2~{mLdr(N6Jzr6!S=hS?M>uKV-h12lCtXD0AG|6nV|n2Kb++8T&^df1 zX2q(5$rJ;TuU)$3yTkP~rpSjZ`g*rJUdI3;OB574l4Ox{!&s><>+XFR2(KKFH7^Dni;?13QjLBFAefeo`6o=id58%ZR58wo^=Eq=A3-RY z&WpYzvseHdCv&EIer@wTh3u7s7VpVWfXY!ID?c-R^f}O9QrV%u(*p|g<5I=vcd=7( zI4JrIuhNv6DA0-t-XeV~0QwTpetkS?2J~e;-pzcceZ-vT2NTPH-)K1NYmY{Jot2gIcv}&CM;`N5<4`8e4VTLKfA^?o;k0l;+jRgEe;Y>-G&aj>fM zVZBmTB3f^~oyKUY?J>jlz^fKYnbIi3TsI7>x9YvaG44@nOgDQkA|0w0VnHK`QNc8)j_!kS0gR`FDP#x`}qDXa4w#g zsVPF_NYI2de8?jSc#fDBqD%~B^X}zMIr8jZ-x@m!htxOHv7Vw&WaO*T+X@N@+G5Lj zzE8=X9$)Jao|}vtLp#KEzoL-U7{)Q;s*sOQow3W#TLpa{dMCw?i2R~v150l#aocRF zXYw**{9U97BdagHxqS_$oqBd;)VcAV8~iFP3-_yH6r3iaibrUv2;%`3I+0nj(}!=2 z-IhbI=Eo~g)U~)#Zr*O41Il*a52AP=F6tv!_&B(%+8|w}O$)Z2A@9+@CVo40RF``i zoc8Eh^Pw>!eqn7oK?S1?2G%S5fop@kc}XWnA^*860jZnkF_w(;p5zI!H-W~fm^rnK zylD-D`>qEgHtjBOi_ggd2amd4a25P-ekd!rtqjjMVz2fBd$Uk*yR8?$S0-#>Yi#1~ zbd2I?YG`N(Wz?M~^aS#93YAFua`QS!zTW{3nuwiAq!QoOy3M+cSL^7^tfV>=r~YkA z8#AuY@hd;J4-+F@Q);A}3j=W4}cr4_-#hWYg2MPqR`RJPgX2RUoG zFWrzxPD@;;P(8|fP^%6C*y&lHv1cFjtCzE14$%Hx4tKYfp1{8++H=D zdR%LZxsBz++=lMA5YU}h8$u9DX5urbD0YN<=A9gtlla{)9d==)&FW6(v?wXH&S{Mu zqgjlorr!8u&ItyxkiWLsij`?XXi) z*BYO#0zc*Oy11}7;bB`*Xe`osj-Se}w=A3@-JDROai;3mpj`^AhEYVA3TsGaCJ7KE zCG|)-uAn#^Kb-9N-iGW`vWk6oZ*DF9_l*Jnf&U9j|55(`YcZ1FiT$~2;D5q@?!RDb ze1|*;79s#IwIBcA!na!v(xU`yI{_$xn;Td}v)K=9`YsW}a?BI;18|Zxg(+}jljd3_ zXR|*=*gt#!_~I*>Exo;iIHy$|rvf7vi8L0MGE{*f1A*d7Z z#>`e(53%dSUo2d>@Z(i@)k?lP(bo>Buf4(JYFlV_N6Rf(fV~7=73!`y`xXb*^c5Gp z$&An6XRC0-PP~|WVsifA&K$Q}T4=~tnhU{ZPzFEnwEwp`RKeS0L>+;)AoKJnd9X`B z51cx~a)LA&&Fd8xkEc5!U`d|#x1rpAUC)Iz7jE~(8!rg$n9EO?Dm+Rwz#IyGQbm?R ztmA2Jh*gD}eQfsrSWNb+#R>}bqTTZ6M;oC$EkRO_76VrL?))FOpTT8wSjNiYPlKMd z(&NS*Mh{cDBEyGRJj!k|u$ve{$%#m*3U$FEcaNAU_Eo^Bs>$gdjo@JU{y@$^Qz&}1 z5^H)uME&ojJp{zFtn8*dKo&M*6BZ607I#Rs zC>C2N5fq81L$rc3u5}XcVQHQUW02)%%yaNb@^KQRBG{4y(1aMjJ@UEqUM+qsSU($G z-ud$5u{^H)w&pZ?98i~;9te~QN1(Pjg3!WoC)?Z5g8jzuESqzwU%9$tD@j|Qfv z+i%PXmgDB)Gy!m!vYN867=r+&oILEt03bUzw+WDkg%tq)kBf)P)YKiaOtrVXL>>KO zN`+yxKKDn`bqOF`YKI{ph**#aj*#t}(bvn(IhrPhu@d#V#^OA6j=jtw(+*msqc+Be zqTFi`2CNV)(lov?PXkFeK1PZn`1><8_yYrTvZjd$KO?$i%KM5Vt{HVel42DK^LGM- zvED<45z&(qe71hchR|;yH?P>BtvC>&Q@A@EaRa$~xKWY4&G+Kx~dj9n4KCL;;VWQtGy<|YtDHQiq#m zpbX>NYzf>w!&3z5lKuXJb9mraS>91*((?X%+$}_YF$9CN{x`)^i=eNO959&sT!Lhg zxeIU?sblsTU0`-Xj%Mj1NT(H6BHOW17xj(+e+`;jQWpmsVXy7cFz z7H+xAk(SY&tu%C9>%9Oo=c%KpZL!n2nY|%WbsN;qnk4jjYcWQdG1jK=wmK1`7v9hm z+$5}Ar{%D+Im6m~nq4CxXML$?ib+hF3E!7h;^A+p zh38n_+j%xVbr;SpsM(s=?~gKb!vxK~4h9`q+$7*Vx!x=SOfxTm4C3!5G(LD@Mq)TE z3V3K;O`A$?nfYcEKeZ(M>%Pv+gaa(Oli+^6vMPbuxc9Lzt z0pdGrG~SrzM|(I{3>iX^K@$qHj}EE+ovgx|Ovnt5N_}ik9&Cp+B}+boQ*r2AjaZey z?-xx(BFA~(>p81q#^qON^tf$y3nc~Lt-2vJCqTX_BcS0# zMg__be?j~8OK1(=3f$Db`HOf%19joz#I77&bj*O+a1$39#{!&fzNnljTHdxy&fRpQ zYkmPgiw>UM{GK;PiY=aG-G)U@)G`8XDI?#IRzH~u5V2CZbMYmR&@`rV6d+cEX5W6U zw6T3bOG5IHy+ul4Bw0R~Ur5#MAuJBs*mIXLf`L&@a=#nXAMM6qvgja2$-l&uV`q_-^ar6soV= ze;5Y%lxUMYee9@15> zmIRcax{l2vhvlHoaXXqHxQx-{XJTDHeYOF4>SlT({H@}>(vFZ~;N`=0AHBaz{UIRW zy#E>R{N`QD4*KC;dn*Um&OaCn4q0y7Z>BU@jtj^NjzBnAO^jGr*?CNO*o=T|>?UmN zAY)FjD+GbV5q7W>{8()DR1@ggBv7?7*2M$%wfMIX3I7D39dPMn_u;q^u6fNBE`nMZg|XfUg8_c z&H868%|;7Ts{wCP2^F1jA=dbk40-N zJFt^CXyR7}RPR|7z+AF@yNo#~Qt#mv;D<$d!49qX=s3f8^fAc+(_=eYjK@_nE3t75ic`1hErel2H^+B|X`Ltifxg z@-%ez0)d`!IK^RTtNDAS*mWtEX?J_ZFlBzDqzj?v=<=8p#cpoNKK15!(L-vpkK{~M z4sjvol41=ZKu^jDdhNPYV>L7!=&!-r+Q%KLkn6{i@8zv46Gholo1QFm=DY9&G}4Rd zeWGq6EbshC##s6BYpy|UZI(5PuB_Sfe(HIxELZx&5(*pKNQ`j4{cl~TsHvqH0$k0t zt4dV3QAo75dJ~`b`4dO`_aUHrhM#M3EiB8}wr;_?nb3=xoCE_jhns_~tWsVN)vW}f zz7NMJWnaHib@=)PmMf&51-OK@!onm;{egr{uD1cx_B~r#b1Js|=xoVO`eauV=GA=J zEBSz$qANbQ*4;z+sOu*D3H9$*EU&JQN{@~PZ<&Myp7&yTW z?Y8}9vV!Hn%PkW&E@SXSW#Q!DGG#LY@Nl!5aC38Va&fb>8F85cc)%+PcSw3#S$Q=8 zrx}190AOQLMsRd-K6aVtmj@mdji$uSV?Am(4VwuK^z!qXg7G|ufB-C`eY_jX!~Z@O zBd#CDax2H-J@Tv+JdWG;o3Vi9jM>;sfkvEc;I)vEDH|J*i<5_ijoa7=V8m`@$_3+oZH>SbyjakIN z`d)X}qLk50chvG=F|3u~6Q~0pnIBGoxWArs!KIJW|2p|e?feg&-0^ZO;04uxVLyK8iu~S__Y*4i zkFK17KXB#XR4-WUM>CNA!VG_i-72UGH2eQH1OfyP*xF4^yfhhL_-Sza=UFi-U?N^# zg2~4CulRD7{uE78tK_@iOGr4?(2JQz17waxjvA`oij8DikF5J$5%8vo-1MDhYX{J~ zltchByQx(nxvCF`beA~j8rvVQ@(*b_Q0529MTb9*?fBXmxPXVejrFPVje~Y6^mYVo z0fnuAtrq^pvl9vmsG$(-~lNQ=O*&{1+w-C{* zaZVv6IY=n1Khj7)KXwQ_F7O3D_TrE0-ci4{K*Jz_k{m>DA66% z&rc%)%l`%C@NcL;&nEg2;%CPP-9bQuIpurW{BW4i9nR0s1G>ZU_&3gN{^du2`;#C0 zR{D<%9sJq;Z-Dp?3Z6b+-)lUVXN1jYJcM1KNIH;R|ULqxM!n3 zRr}WoIrlN|AC_{583|5Y{S@<;N2lD!zQ05K4*LY<7uf&aFMc2N{yyzH(9Q?H0tJ^m z-Wm9>61)4j_qQwG;bMVL^!lkG{a))RLep~($@gJL6?ql9BcD=(4BL6Ms zkEO5oLGRaW-hpC)-<&^J^yd|v_mS^cH{BtNgWt_RMgB*v(~o#Rt1Gz0gMc6fHv;gP zNB8jls4}=i_;-ACo6`RCx^;BDKSTH4nfYIX`776cr^?T=?RTm?1pFM~zVH88Cizc|ZcXCF@^h3wBAOqEb06k5v;60E z3sd_$nE&OO|2eYzndV!tKaG6+e}mmdjd$81{E@u8pR2tCgkby4Apg`(_3zB>9qhmJ zakn|qKd;+CAO0Kmf62}tL4KAay#t|O|Cet61NkFk`ah%nJZJhR4jK5D?r(AaTL$$< zt$((5ywlo=8L*z5R?r zzO&IH|1W#{gHXP+(a$L5JFRgAeuwkl2<9KPzVDcB*L8nhw+}VE;4gdogWkQ<`WELt z!TTr9?ei$~Tb%z!_x`B$&zP+{t!qVosr4T`*PYfsW4i9N-uo@if8)J=)cR)})}7YA zqQBJo4@T=w>z{F2cUm|67U#b)Tt904`?>#4?3Y^q!6MyheT#FSN4nGc^0zqujaB+l z>z^@1ceaia|E1P{@I`l8|BNxZ)4Kb&IRA}5`cdoqOS4-p=+EnRHfl@!QtQ8%p*y{Q zj}-rFq`#P=UnBi9bQ%0N(*GGP{L{xkNd9Y7Kae#)TIXk6(yev=3>3J3i}TMI;m?=( zeah$#EB&`vKMxOn#thveLO|T!I|QkpkMb{`=+4|fV~TD;{v4#x?_h5A0`o?9Ci^)d gbcgo(A83EmLrQY6aJOIL0{{47KtQ-i-~RXi0I8)q#{d8T diff --git a/src/Mod/AddonManager/AddonManagerTest/data/test_simple_repo.zip b/src/Mod/AddonManager/AddonManagerTest/data/test_simple_repo.zip deleted file mode 100644 index 9ce0ee9ac3f6964b481a299e77a4bd1b49169d92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110 zcmWIWW@Zs#00I8|qEIjcO0WUxAXi5hU)KO{MkWyk+^QfN6rlQGdRRdQFfan436NF+ G%K`ut#R!i8 diff --git a/src/Mod/AddonManager/AddonManagerTest/data/test_version_detection.xml b/src/Mod/AddonManager/AddonManagerTest/data/test_version_detection.xml deleted file mode 100644 index 0856dac73d..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/test_version_detection.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - Test Workbenches - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - - - - MacroA - TagA - 0.1 - 0.10 - - - MacroB - TagB - 0.20 - 9999.98 - - - MacroC - TagC - 9999.99 - 99999.99 - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/data/workbench_only.xml b/src/Mod/AddonManager/AddonManagerTest/data/workbench_only.xml deleted file mode 100644 index 719e117611..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/data/workbench_only.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - Test Workbenches - A package.xml file for unit testing. - 1.0.1 - 2022-01-07 - FreeCAD Developer - LGPL-2.1 - https://github.com/chennes/FreeCAD-Package - https://github.com/chennes/FreeCAD-Package/blob/main/README.md - - - - MyFirstWorkbench - Resources/icons/PackageIcon.svg - - - MySecondWorkbench - Resources/icons/PackageIcon.svg - - - MyThirdWorkbench - Resources/icons/PackageIcon.svg - - - - diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/__init__.py b/src/Mod/AddonManager/AddonManagerTest/gui/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/gui_mocks.py b/src/Mod/AddonManager/AddonManagerTest/gui/gui_mocks.py deleted file mode 100644 index fde8d9e896..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/gui_mocks.py +++ /dev/null @@ -1,157 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import sys - -try: - from PySide import QtCore, QtWidgets -except ImportError: - try: - from PySide6 import QtCore, QtWidgets - except ImportError: - from PySide2 import QtCore, QtWidgets - -sys.path.append("../../") # For running in standalone mode during testing - -from AddonManagerTest.app.mocks import SignalCatcher - - -class DialogInteractor(QtCore.QObject): - """Takes the title of the dialog and a callable. The callable is passed the widget - we found and can do whatever it wants to it. Whatever it does should eventually - close the dialog, however.""" - - def __init__(self, dialog_to_watch_for, interaction): - super().__init__() - - # Status variables for tests to check: - self.dialog_found = False - self.has_run = False - self.button_found = False - self.interaction = interaction - - self.dialog_to_watch_for = dialog_to_watch_for - - self.execution_counter = 0 - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.run) - self.timer.start( - 1 - ) # At 10 this occasionally left open dialogs; less than 1 produced failed tests - - def run(self): - widget = QtWidgets.QApplication.activeModalWidget() - if widget and self._dialog_matches(widget): - # Found the dialog we are looking for: now try to run the interaction - if self.interaction is not None and callable(self.interaction): - self.interaction(widget) - self.dialog_found = True - self.timer.stop() - - self.has_run = True - self.execution_counter += 1 - if self.execution_counter > 100: - print("Stopped timer after 100 iterations") - self.timer.stop() - - def _dialog_matches(self, widget) -> bool: - # Is this the widget we are looking for? Only applies on Linux and Windows: macOS - # doesn't set the title of a modal dialog: - os = QtCore.QSysInfo.productType() # Qt5 gives "osx", Qt6 gives "macos" - if os in ["osx", "macos"] or ( - hasattr(widget, "windowTitle") - and callable(widget.windowTitle) - and widget.windowTitle() == self.dialog_to_watch_for - ): - return True - return False - - -class DialogWatcher(DialogInteractor): - """Examine the running GUI and look for a modal dialog with a given title, containing a button - with a role. Click that button, which is expected to close the dialog. Generally run on - a one-shot QTimer to allow the dialog time to open up. If the specified dialog is found, but - it does not contain the expected button, button_found will be false, and the dialog will be - closed with a reject() slot.""" - - def __init__(self, dialog_to_watch_for, button=QtWidgets.QDialogButtonBox.NoButton): - super().__init__(dialog_to_watch_for, self.click_button) - if button != QtWidgets.QDialogButtonBox.NoButton: - self.button = button - else: - self.button = QtWidgets.QDialogButtonBox.Cancel - - def click_button(self, widget): - button_boxes = widget.findChildren(QtWidgets.QDialogButtonBox) - if len(button_boxes) == 1: # There should be one, and only one - button_to_click = button_boxes[0].button(self.button) - if button_to_click: - self.button_found = True - button_to_click.click() - else: - widget.reject() - else: - widget.reject() - - -class FakeWorker: - def __init__(self): - self.called = False - self.should_continue = True - - def work(self): - while self.should_continue: - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) - - def stop(self): - self.should_continue = False - - -class MockThread: - def wait(self): - pass - - def isRunning(self): - return False - - -class AsynchronousMonitor: - """Watch for a signal to be emitted for at most some given number of milliseconds""" - - def __init__(self, signal): - self.signal = signal - self.signal_catcher = SignalCatcher() - self.signal.connect(self.signal_catcher.catch_signal) - self.kill_timer = QtCore.QTimer() - self.kill_timer.setSingleShot(True) - self.kill_timer.timeout.connect(self.signal_catcher.die) - - def wait_for_at_most(self, max_wait_millis) -> None: - self.kill_timer.setInterval(max_wait_millis) - self.kill_timer.start() - while not self.signal_catcher.caught and not self.signal_catcher.killed: - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 10) - self.kill_timer.stop() - - def good(self) -> bool: - return self.signal_catcher.caught and not self.signal_catcher.killed diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py deleted file mode 100644 index b70689d0c4..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py +++ /dev/null @@ -1,234 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2025 The FreeCAD Project Association AISBL * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Test the Change Branch GUI code""" - -# pylint: disable=wrong-import-position, deprecated-module, too-many-return-statements - -import sys -import unittest -from unittest.mock import patch, Mock, MagicMock - -# So that when run standalone, the Addon Manager classes imported below are available -sys.path.append("../..") - -from AddonManagerTest.gui.gui_mocks import DialogWatcher, AsynchronousMonitor - -from change_branch import ChangeBranchDialog - -from addonmanager_freecad_interface import translate -from addonmanager_git import GitFailed - -try: - from PySide import QtCore, QtWidgets -except ImportError: - try: - from PySide6 import QtCore, QtWidgets - except ImportError: - from PySide2 import QtCore, QtWidgets - - -class MockFilter(QtCore.QSortFilterProxyModel): - """Replaces a filter with a non-filter that simply always returns whatever it's given""" - - def mapToSource(self, something): - return something - - -class MockChangeBranchDialogModel(QtCore.QAbstractTableModel): - """Replace a data-connected model with a static one for testing""" - - branches = [ - {"ref_name": "ref1", "upstream": "us1"}, - {"ref_name": "ref2", "upstream": "us2"}, - {"ref_name": "ref3", "upstream": "us3"}, - ] - current_branch = "ref1" - DataSortRole = QtCore.Qt.UserRole - RefAccessRole = QtCore.Qt.UserRole + 1 - - def __init__(self, _: str, parent=None) -> None: - super().__init__(parent) - - def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: - """Number of rows: should always return 3""" - if parent.isValid(): - return 0 - return len(self.branches) - - def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: - """Number of columns (identical to non-mocked version)""" - if parent.isValid(): - return 0 - return 3 # Local name, remote name, date - - def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole): - """Mock returns static untranslated strings for DisplayRole, no tooltips at all, and - otherwise matches the non-mock version""" - if not index.isValid(): - return None - row = index.row() - column = index.column() - if role == QtCore.Qt.DisplayRole: - if column == 2: - return "date" - if column == 0: - return "ref_name" - if column == 1: - return "upstream" - return None - if role == MockChangeBranchDialogModel.DataSortRole: - return None - if role == MockChangeBranchDialogModel.RefAccessRole: - return self.branches[row] - return None - - def headerData( - self, - section: int, - orientation: QtCore.Qt.Orientation, - role: int = QtCore.Qt.DisplayRole, - ): - """Mock returns untranslated strings for DisplayRole, and no tooltips at all""" - if orientation == QtCore.Qt.Vertical: - return None - if role != QtCore.Qt.DisplayRole: - return None - if section == 0: - return "Local" - if section == 1: - return "Remote tracking" - if section == 2: - return "Last Updated" - return None - - def currentBranch(self) -> str: - """Mock returns a static string stored in the class: that string could be modified to - return something else by tests that require it.""" - return self.current_branch - - -class TestChangeBranchGui(unittest.TestCase): - """Tests for the ChangeBranch GUI code""" - - MODULE = "test_change_branch" # file name without extension - - def setUp(self): - pass - - def tearDown(self): - pass - - @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) - @patch("change_branch.initialize_git", new=Mock(return_value=None)) - def test_no_git(self): - """If git is not present, a dialog saying so is presented""" - # Arrange - gui = ChangeBranchDialog("/some/path") - ref = {"ref_name": "foo/bar", "upstream": "us1"} - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Cannot find git"), - QtWidgets.QDialogButtonBox.Ok, - ) - - # Act - gui.change_branch("/foo/bar/baz", ref) - - # Assert - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - - @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) - @patch("change_branch.initialize_git") - def test_git_failed(self, init_git: MagicMock): - """If git fails when attempting to change branches, a dialog saying so is presented""" - # Arrange - git_manager = MagicMock() - git_manager.checkout = MagicMock() - git_manager.checkout.side_effect = GitFailed() - init_git.return_value = git_manager - gui = ChangeBranchDialog("/some/path") - ref = {"ref_name": "foo/bar", "upstream": "us1"} - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "git operation failed"), - QtWidgets.QDialogButtonBox.Ok, - ) - - # Act - gui.change_branch("/foo/bar/baz", ref) - - # Assert - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - - @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) - @patch("change_branch.initialize_git", new=MagicMock) - def test_branch_change_succeeded(self): - """If nothing gets thrown, then the process is assumed to have worked, and the appropriate - signal is emitted.""" - - # Arrange - gui = ChangeBranchDialog("/some/path") - ref = {"ref_name": "foo/bar", "upstream": "us1"} - monitor = AsynchronousMonitor(gui.branch_changed) - - # Act - gui.change_branch("/foo/bar/baz", ref) - - # Assert - monitor.wait_for_at_most(10) # Should be effectively instantaneous - self.assertTrue(monitor.good()) - - @patch("change_branch.ChangeBranchDialogFilter", new=MockFilter) - @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) - @patch("change_branch.initialize_git", new=MagicMock) - def test_warning_is_shown_when_dialog_is_accepted(self): - """If the dialog is accepted (e.g. a branch change is requested) then a warning dialog is - displayed, and gives the opportunity to cancel. If cancelled, no signal is emitted.""" - # Arrange - gui = ChangeBranchDialog("/some/path") - gui.ui.exec = MagicMock() - gui.ui.exec.return_value = QtWidgets.QDialog.Accepted - gui.ui.tableView.selectedIndexes = MagicMock() - gui.ui.tableView.selectedIndexes.return_value = [MagicMock()] - gui.ui.tableView.selectedIndexes.return_value[0].isValid = MagicMock() - gui.ui.tableView.selectedIndexes.return_value[0].isValid.return_value = True - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "DANGER: Developer feature"), - QtWidgets.QDialogButtonBox.Cancel, - ) - monitor = AsynchronousMonitor(gui.branch_changed) - - # Act - gui.exec() - - # Assert - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertFalse(monitor.good()) # The watcher cancelled the op, so no signal is emitted - - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - QtCore.QTimer.singleShot(0, unittest.main) - if hasattr(app, "exec"): - app.exec() # PySide6 - else: - app.exec_() # PySide2 diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_gui.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_gui.py deleted file mode 100644 index 1af1592057..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_gui.py +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import unittest -import FreeCAD - - -class TestGui(unittest.TestCase): - - MODULE = "test_gui" # file name without extension - - def setUp(self): - pass diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_installer_gui.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_installer_gui.py deleted file mode 100644 index 6523f2ccdc..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_installer_gui.py +++ /dev/null @@ -1,650 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import os -import tempfile -import unittest -import FreeCAD - -from PySide import QtCore, QtWidgets - -from addonmanager_installer_gui import AddonInstallerGUI, MacroInstallerGUI - -from AddonManagerTest.gui.gui_mocks import DialogWatcher, DialogInteractor -from AddonManagerTest.app.mocks import MockAddon - -translate = FreeCAD.Qt.translate - - -class TestInstallerGui(unittest.TestCase): - - MODULE = "test_installer_gui" # file name without extension - - def setUp(self): - self.addon_to_install = MockAddon() - self.installer_gui = AddonInstallerGUI(self.addon_to_install) - self.finalized_thread = False - - def tearDown(self): - pass - - def test_success_dialog(self): - # Pop the modal dialog and verify that it opens, and responds to an OK click - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Success"), - QtWidgets.QDialogButtonBox.Ok, - ) - self.installer_gui._installation_succeeded() - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_failure_dialog(self): - # Pop the modal dialog and verify that it opens, and responds to a Cancel click - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Installation Failed"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.installer_gui._installation_failed( - self.addon_to_install, "Test of installation failure" - ) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_no_python_dialog(self): - # Pop the modal dialog and verify that it opens, and responds to a No click - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Cannot execute Python"), - QtWidgets.QDialogButtonBox.No, - ) - self.installer_gui._report_no_python_exe() - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_no_pip_dialog(self): - # Pop the modal dialog and verify that it opens, and responds to a No click - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Cannot execute pip"), - QtWidgets.QDialogButtonBox.No, - ) - self.installer_gui._report_no_pip("pip not actually run, this was a test") - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_dependency_failure_dialog(self): - # Pop the modal dialog and verify that it opens, and responds to a No click - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Package installation failed"), - QtWidgets.QDialogButtonBox.No, - ) - self.installer_gui._report_dependency_failure( - "Unit test", "Nothing really failed, this is a test of the dialog box" - ) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_install(self): - # Run the installation code and make sure it puts the directory in place - with tempfile.TemporaryDirectory() as temp_dir: - self.installer_gui.installer.installation_path = temp_dir - self.installer_gui.install() # This does not block - self.installer_gui.installer.success.disconnect( - self.installer_gui._installation_succeeded - ) - self.installer_gui.installer.failure.disconnect(self.installer_gui._installation_failed) - while not self.installer_gui.worker_thread.isFinished(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) - self.assertTrue( - os.path.exists(os.path.join(temp_dir, "MockAddon")), - "Installed directory not found", - ) - - def test_handle_disallowed_python(self): - disallowed_packages = ["disallowed_package_name"] - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Missing Requirement"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.installer_gui._handle_disallowed_python(disallowed_packages) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_handle_disallowed_python_long_list(self): - """A separate test for when there are MANY packages, which takes a separate code path.""" - disallowed_packages = [] - for i in range(50): - disallowed_packages.append(f"disallowed_package_name_{i}") - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Missing Requirement"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.installer_gui._handle_disallowed_python(disallowed_packages) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_report_missing_workbenches_single(self): - """Test only missing one workbench""" - wbs = ["OneMissingWorkbench"] - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Missing Requirement"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.installer_gui._report_missing_workbenches(wbs) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_report_missing_workbenches_multiple(self): - """Test only missing one workbench""" - wbs = ["FirstMissingWorkbench", "SecondMissingWorkbench"] - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Missing Requirement"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.installer_gui._report_missing_workbenches(wbs) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_resolve_dependencies_then_install(self): - class MissingDependenciesMock: - def __init__(self): - self.external_addons = ["addon_1", "addon_2"] - self.python_requires = ["py_req_1", "py_req_2"] - self.python_optional = ["py_opt_1", "py_opt_2"] - - missing = MissingDependenciesMock() - dialog_watcher = DialogWatcher( - translate("DependencyResolutionDialog", "Resolve Dependencies"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.installer_gui._resolve_dependencies_then_install(missing) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_check_python_version_bad(self): - class MissingDependenciesMock: - def __init__(self): - self.python_min_version = {"major": 3, "minor": 9999} - - missing = MissingDependenciesMock() - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Incompatible Python version"), - QtWidgets.QDialogButtonBox.Cancel, - ) - stop_installing = self.installer_gui._check_python_version(missing) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - self.assertTrue(stop_installing, "Failed to halt installation on bad Python version") - - def test_check_python_version_good(self): - class MissingDependenciesMock: - def __init__(self): - self.python_min_version = {"major": 3, "minor": 0} - - missing = MissingDependenciesMock() - stop_installing = self.installer_gui._check_python_version(missing) - self.assertFalse(stop_installing, "Failed to continue installation on good Python version") - - def test_clean_up_optional(self): - class MissingDependenciesMock: - def __init__(self): - self.python_optional = [ - "allowed_packages_1", - "allowed_packages_2", - "disallowed_package", - ] - - allowed_packages = ["allowed_packages_1", "allowed_packages_2"] - missing = MissingDependenciesMock() - self.installer_gui.installer.allowed_packages = set(allowed_packages) - self.installer_gui._clean_up_optional(missing) - self.assertTrue("allowed_packages_1" in missing.python_optional) - self.assertTrue("allowed_packages_2" in missing.python_optional) - self.assertFalse("disallowed_package" in missing.python_optional) - - def intercept_run_dependency_installer(self, addons, python_requires, python_optional): - self.assertEqual(python_requires, ["py_req_1", "py_req_2"]) - self.assertEqual(python_optional, ["py_opt_1", "py_opt_2"]) - self.assertEqual(addons[0].name, "addon_1") - self.assertEqual(addons[1].name, "addon_2") - - def test_dependency_dialog_yes_clicked(self): - class DialogMock: - class ListWidgetMock: - class ListWidgetItemMock: - def __init__(self, name): - self.name = name - - def text(self): - return self.name - - def checkState(self): - return QtCore.Qt.Checked - - def __init__(self, items): - self.list = [] - for item in items: - self.list.append(DialogMock.ListWidgetMock.ListWidgetItemMock(item)) - - def count(self): - return len(self.list) - - def item(self, i): - return self.list[i] - - def __init__(self): - self.listWidgetAddons = DialogMock.ListWidgetMock(["addon_1", "addon_2"]) - self.listWidgetPythonRequired = DialogMock.ListWidgetMock(["py_req_1", "py_req_2"]) - self.listWidgetPythonOptional = DialogMock.ListWidgetMock(["py_opt_1", "py_opt_2"]) - - class AddonMock: - def __init__(self, name): - self.name = name - - self.installer_gui.dependency_dialog = DialogMock() - self.installer_gui.addons = [AddonMock("addon_1"), AddonMock("addon_2")] - self.installer_gui._run_dependency_installer = self.intercept_run_dependency_installer - self.installer_gui._dependency_dialog_yes_clicked() - - -class TestMacroInstallerGui(unittest.TestCase): - class MockMacroAddon: - class MockMacro: - def __init__(self): - self.install_called = False - self.install_result = ( - True # External code can change to False to test failed install - ) - self.name = "MockMacro" - self.filename = "mock_macro_no_real_file.FCMacro" - self.comment = "This is a mock macro for unit testing" - self.icon = None - self.xpm = None - - def install(self): - self.install_called = True - return self.install_result - - def __init__(self): - self.macro = TestMacroInstallerGui.MockMacroAddon.MockMacro() - self.name = self.macro.name - self.display_name = self.macro.name - - class MockParameter: - """Mock the parameter group to allow simplified behavior and introspection.""" - - def __init__(self): - self.params = {} - self.groups = {} - self.accessed_parameters = {} # Dict is param name: default value - - types = ["Bool", "String", "Int", "UInt", "Float"] - for t in types: - setattr(self, f"Get{t}", self.get) - setattr(self, f"Set{t}", self.set) - setattr(self, f"Rem{t}", self.rem) - - def get(self, p, default=None): - self.accessed_parameters[p] = default - if p in self.params: - return self.params[p] - else: - return default - - def set(self, p, value): - self.params[p] = value - - def rem(self, p): - if p in self.params: - self.params.erase(p) - - def GetGroup(self, name): - if name not in self.groups: - self.groups[name] = TestMacroInstallerGui.MockParameter() - return self.groups[name] - - def GetGroups(self): - return self.groups.keys() - - class ToolbarIntercepter: - def __init__(self): - self.ask_for_toolbar_called = False - self.install_macro_to_toolbar_called = False - self.tb = None - self.custom_group = TestMacroInstallerGui.MockParameter() - self.custom_group.set("Name", "MockCustomToolbar") - - def _ask_for_toolbar(self, _): - self.ask_for_toolbar_called = True - return self.custom_group - - def _install_macro_to_toolbar(self, tb): - self.install_macro_to_toolbar_called = True - self.tb = tb - - class InstallerInterceptor: - def __init__(self): - self.ccc_called = False - - def _create_custom_command( - self, - toolbar, - filename, - menuText, - tooltipText, - whatsThisText, - statustipText, - pixmapText, - ): - self.ccc_called = True - self.toolbar = toolbar - self.filename = filename - self.menuText = menuText - self.tooltipText = tooltipText - self.whatsThisText = whatsThisText - self.statustipText = statustipText - self.pixmapText = pixmapText - - def setUp(self): - self.mock_macro = TestMacroInstallerGui.MockMacroAddon() - self.installer = MacroInstallerGUI(self.mock_macro) - self.installer.addon_params = TestMacroInstallerGui.MockParameter() - self.installer.toolbar_params = TestMacroInstallerGui.MockParameter() - - def tearDown(self): - pass - - def test_class_is_initialized(self): - """Connecting to a signal does not throw""" - self.installer.finished.connect(lambda: None) - - def test_ask_for_toolbar_no_dialog_default_exists(self): - self.installer.addon_params.set("alwaysAskForToolbar", False) - self.installer.addon_params.set("CustomToolbarName", "UnitTestCustomToolbar") - utct = self.installer.toolbar_params.GetGroup("UnitTestCustomToolbar") - utct.set("Name", "UnitTestCustomToolbar") - utct.set("Active", True) - result = self.installer._ask_for_toolbar([]) - self.assertIsNotNone(result) - self.assertTrue(hasattr(result, "get")) - name = result.get("Name") - self.assertEqual(name, "UnitTestCustomToolbar") - - def test_ask_for_toolbar_with_dialog_cancelled(self): - - # First test: the user cancels the dialog - self.installer.addon_params.set("alwaysAskForToolbar", True) - dialog_watcher = DialogWatcher( - translate("select_toolbar_dialog", "Select Toolbar"), - QtWidgets.QDialogButtonBox.Cancel, - ) - result = self.installer._ask_for_toolbar([]) - self.assertIsNone(result) - - def test_ask_for_toolbar_with_dialog_defaults(self): - - # Second test: the user leaves the dialog at all default values, so: - # - The checkbox "Ask every time" is unchecked - # - The selected toolbar option is "Create new toolbar", which triggers a search for - # a new custom toolbar name by calling _create_new_custom_toolbar, which we mock. - fake_custom_toolbar_group = TestMacroInstallerGui.MockParameter() - fake_custom_toolbar_group.set("Name", "UnitTestCustomToolbar") - self.installer._create_new_custom_toolbar = lambda: fake_custom_toolbar_group - dialog_watcher = DialogWatcher( - translate("select_toolbar_dialog", "Select Toolbar"), - QtWidgets.QDialogButtonBox.Ok, - ) - result = self.installer._ask_for_toolbar([]) - self.assertIsNotNone(result) - self.assertTrue(hasattr(result, "get")) - name = result.get("Name") - self.assertEqual(name, "UnitTestCustomToolbar") - self.assertIn("alwaysAskForToolbar", self.installer.addon_params.params) - self.assertFalse(self.installer.addon_params.get("alwaysAskForToolbar", True)) - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_ask_for_toolbar_with_dialog_selection(self): - - # Third test: the user selects a custom toolbar in the dialog, and checks the box to always - # ask. - dialog_interactor = DialogInteractor( - translate("select_toolbar_dialog", "Select Toolbar"), - self.interactor_selection_option_and_checkbox, - ) - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_2 = self.installer.toolbar_params.GetGroup("UT_TB_2") - ut_tb_3 = self.installer.toolbar_params.GetGroup("UT_TB_3") - ut_tb_1.set("Name", "UT_TB_1") - ut_tb_2.set("Name", "UT_TB_2") - ut_tb_3.set("Name", "UT_TB_3") - result = self.installer._ask_for_toolbar(["UT_TB_1", "UT_TB_2", "UT_TB_3"]) - self.assertIsNotNone(result) - self.assertTrue(hasattr(result, "get")) - name = result.get("Name") - self.assertEqual(name, "UT_TB_3") - self.assertIn("alwaysAskForToolbar", self.installer.addon_params.params) - self.assertTrue(self.installer.addon_params.get("alwaysAskForToolbar", False)) - - def interactor_selection_option_and_checkbox(self, parent): - - boxes = parent.findChildren(QtWidgets.QComboBox) - self.assertEqual(len(boxes), 1) # Just to make sure... - box = boxes[0] - box.setCurrentIndex(box.count() - 2) # Select the last thing but one - - checkboxes = parent.findChildren(QtWidgets.QCheckBox) - self.assertEqual(len(checkboxes), 1) # Just to make sure... - checkbox = checkboxes[0] - checkbox.setChecked(True) - - parent.accept() - - def test_macro_button_exists_no_command(self): - # Test 1: No command for this macro - self.installer._find_custom_command = lambda _: None - button_exists = self.installer._macro_button_exists() - self.assertFalse(button_exists) - - def test_macro_button_exists_true(self): - # Test 2: Macro is in the list of buttons - ut_tb_1 = self.installer.toolbar_params.GetGroup("UnitTestCommand") - ut_tb_1.set("UnitTestCommand", "FreeCAD") # This is what the real thing looks like... - self.installer._find_custom_command = lambda _: "UnitTestCommand" - self.assertTrue(self.installer._macro_button_exists()) - - def test_macro_button_exists_false(self): - # Test 3: Macro is not in the list of buttons - self.installer._find_custom_command = lambda _: "UnitTestCommand" - self.assertFalse(self.installer._macro_button_exists()) - - def test_ask_to_install_toolbar_button_disabled(self): - self.installer.addon_params.SetBool("dontShowAddMacroButtonDialog", True) - self.installer._ask_to_install_toolbar_button() - # This should NOT block when dontShowAddMacroButtonDialog is True - - def test_ask_to_install_toolbar_button_enabled_no(self): - self.installer.addon_params.SetBool("dontShowAddMacroButtonDialog", False) - dialog_watcher = DialogWatcher( - translate("toolbar_button", "Add button?"), - QtWidgets.QDialogButtonBox.No, - ) - # Note: that dialog does not use a QButtonBox, so we can really only test its - # reject() signal, which is triggered by the DialogWatcher when it cannot find - # the button. In this case, failure to find that button is NOT an error. - self.installer._ask_to_install_toolbar_button() # Blocks until killed by watcher - self.assertTrue(dialog_watcher.dialog_found) - - def test_get_toolbar_with_name_found(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UnitTestToolbar") - ut_tb_1.set("Name", "Unit Test Toolbar") - ut_tb_1.set("UnitTestParam", True) - tb = self.installer._get_toolbar_with_name("Unit Test Toolbar") - self.assertIsNotNone(tb) - self.assertTrue(tb.get("UnitTestParam", False)) - - def test_get_toolbar_with_name_not_found(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UnitTestToolbar") - ut_tb_1.set("Name", "Not the Unit Test Toolbar") - tb = self.installer._get_toolbar_with_name("Unit Test Toolbar") - self.assertIsNone(tb) - - def test_create_new_custom_toolbar_no_existing(self): - tb = self.installer._create_new_custom_toolbar() - self.assertEqual(tb.get("Name", ""), "Auto-Created Macro Toolbar") - self.assertTrue(tb.get("Active", False), True) - - def test_create_new_custom_toolbar_one_existing(self): - _ = self.installer._create_new_custom_toolbar() - tb = self.installer._create_new_custom_toolbar() - self.assertEqual(tb.get("Name", ""), "Auto-Created Macro Toolbar (2)") - self.assertTrue(tb.get("Active", False), True) - - def test_check_for_toolbar_true(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - self.assertTrue(self.installer._check_for_toolbar("UT_TB_1")) - - def test_check_for_toolbar_false(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - self.assertFalse(self.installer._check_for_toolbar("Not UT_TB_1")) - - def test_install_toolbar_button_first_custom_toolbar(self): - tbi = TestMacroInstallerGui.ToolbarIntercepter() - self.installer._ask_for_toolbar = tbi._ask_for_toolbar - self.installer._install_macro_to_toolbar = tbi._install_macro_to_toolbar - self.installer._install_toolbar_button() - self.assertTrue(tbi.install_macro_to_toolbar_called) - self.assertFalse(tbi.ask_for_toolbar_called) - self.assertTrue("Custom_1" in self.installer.toolbar_params.GetGroups()) - - def test_install_toolbar_button_existing_custom_toolbar_1(self): - # There is an existing custom toolbar, and we should use it - tbi = TestMacroInstallerGui.ToolbarIntercepter() - self.installer._ask_for_toolbar = tbi._ask_for_toolbar - self.installer._install_macro_to_toolbar = tbi._install_macro_to_toolbar - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - self.installer.addon_params.set("CustomToolbarName", "UT_TB_1") - self.installer._install_toolbar_button() - self.assertTrue(tbi.install_macro_to_toolbar_called) - self.assertFalse(tbi.ask_for_toolbar_called) - self.assertEqual(tbi.tb.get("Name", ""), "UT_TB_1") - - def test_install_toolbar_button_existing_custom_toolbar_2(self): - # There are multiple existing custom toolbars, and we should use one of them - tbi = TestMacroInstallerGui.ToolbarIntercepter() - self.installer._ask_for_toolbar = tbi._ask_for_toolbar - self.installer._install_macro_to_toolbar = tbi._install_macro_to_toolbar - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_2 = self.installer.toolbar_params.GetGroup("UT_TB_2") - ut_tb_3 = self.installer.toolbar_params.GetGroup("UT_TB_3") - ut_tb_1.set("Name", "UT_TB_1") - ut_tb_2.set("Name", "UT_TB_2") - ut_tb_3.set("Name", "UT_TB_3") - self.installer.addon_params.set("CustomToolbarName", "UT_TB_3") - self.installer._install_toolbar_button() - self.assertTrue(tbi.install_macro_to_toolbar_called) - self.assertFalse(tbi.ask_for_toolbar_called) - self.assertEqual(tbi.tb.get("Name", ""), "UT_TB_3") - - def test_install_toolbar_button_existing_custom_toolbar_3(self): - # There are multiple existing custom toolbars, but none of them match - tbi = TestMacroInstallerGui.ToolbarIntercepter() - self.installer._ask_for_toolbar = tbi._ask_for_toolbar - self.installer._install_macro_to_toolbar = tbi._install_macro_to_toolbar - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_2 = self.installer.toolbar_params.GetGroup("UT_TB_2") - ut_tb_3 = self.installer.toolbar_params.GetGroup("UT_TB_3") - ut_tb_1.set("Name", "UT_TB_1") - ut_tb_2.set("Name", "UT_TB_2") - ut_tb_3.set("Name", "UT_TB_3") - self.installer.addon_params.set("CustomToolbarName", "UT_TB_4") - self.installer._install_toolbar_button() - self.assertTrue(tbi.install_macro_to_toolbar_called) - self.assertTrue(tbi.ask_for_toolbar_called) - self.assertEqual(tbi.tb.get("Name", ""), "MockCustomToolbar") - - def test_install_toolbar_button_existing_custom_toolbar_4(self): - # There are multiple existing custom toolbars, one of them matches, but we have set - # "alwaysAskForToolbar" to True - tbi = TestMacroInstallerGui.ToolbarIntercepter() - self.installer._ask_for_toolbar = tbi._ask_for_toolbar - self.installer._install_macro_to_toolbar = tbi._install_macro_to_toolbar - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_2 = self.installer.toolbar_params.GetGroup("UT_TB_2") - ut_tb_3 = self.installer.toolbar_params.GetGroup("UT_TB_3") - ut_tb_1.set("Name", "UT_TB_1") - ut_tb_2.set("Name", "UT_TB_2") - ut_tb_3.set("Name", "UT_TB_3") - self.installer.addon_params.set("CustomToolbarName", "UT_TB_3") - self.installer.addon_params.set("alwaysAskForToolbar", True) - self.installer._install_toolbar_button() - self.assertTrue(tbi.install_macro_to_toolbar_called) - self.assertTrue(tbi.ask_for_toolbar_called) - self.assertEqual(tbi.tb.get("Name", ""), "MockCustomToolbar") - - def test_install_macro_to_toolbar_icon_abspath(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - ii = TestMacroInstallerGui.InstallerInterceptor() - self.installer._create_custom_command = ii._create_custom_command - with tempfile.NamedTemporaryFile() as ntf: - self.mock_macro.macro.icon = ntf.name - self.installer._install_macro_to_toolbar(ut_tb_1) - self.assertTrue(ii.ccc_called) - self.assertEqual(ii.pixmapText, ntf.name) - - def test_install_macro_to_toolbar_icon_relpath(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - ii = TestMacroInstallerGui.InstallerInterceptor() - self.installer._create_custom_command = ii._create_custom_command - with tempfile.TemporaryDirectory() as td: - self.installer.macro_dir = td - self.mock_macro.macro.icon = "RelativeIconPath.png" - self.installer._install_macro_to_toolbar(ut_tb_1) - self.assertTrue(ii.ccc_called) - self.assertEqual(ii.pixmapText, os.path.join(td, "RelativeIconPath.png")) - - def test_install_macro_to_toolbar_xpm(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - ii = TestMacroInstallerGui.InstallerInterceptor() - self.installer._create_custom_command = ii._create_custom_command - with tempfile.TemporaryDirectory() as td: - self.installer.macro_dir = td - self.mock_macro.macro.xpm = "Not really xpm data, don't try to use it!" - self.installer._install_macro_to_toolbar(ut_tb_1) - self.assertTrue(ii.ccc_called) - self.assertEqual(ii.pixmapText, os.path.join(td, "MockMacro_icon.xpm")) - self.assertTrue(os.path.exists(os.path.join(td, "MockMacro_icon.xpm"))) - - def test_install_macro_to_toolbar_no_icon(self): - ut_tb_1 = self.installer.toolbar_params.GetGroup("UT_TB_1") - ut_tb_1.set("Name", "UT_TB_1") - ii = TestMacroInstallerGui.InstallerInterceptor() - self.installer._create_custom_command = ii._create_custom_command - with tempfile.TemporaryDirectory() as td: - self.installer.macro_dir = td - self.installer._install_macro_to_toolbar(ut_tb_1) - self.assertTrue(ii.ccc_called) - self.assertIsNone(ii.pixmapText) diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_python_deps_gui.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_python_deps_gui.py deleted file mode 100644 index be08fa37e6..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_python_deps_gui.py +++ /dev/null @@ -1,139 +0,0 @@ -import logging -import subprocess -import sys -import unittest -from unittest.mock import MagicMock, patch - -try: - import FreeCAD - import FreeCADGui -except ImportError: - try: - from PySide6 import QtCore, QtWidgets - except ImportError: - from PySide2 import QtCore, QtWidgets - -sys.path.append( - "../.." -) # So that when run standalone, the Addon Manager classes imported below are available - -from addonmanager_python_deps_gui import ( - PythonPackageManager, - call_pip, - PipFailed, - python_package_updates_are_available, - parse_pip_list_output, -) -from AddonManagerTest.gui.gui_mocks import DialogInteractor, DialogWatcher - - -class TestPythonPackageManager(unittest.TestCase): - - def setUp(self) -> None: - self.manager = PythonPackageManager([]) - - def tearDown(self) -> None: - if self.manager.worker_thread: - self.manager.worker_thread.terminate() - self.manager.worker_thread.wait() - - @patch("addonmanager_python_deps_gui.PythonPackageManager._create_list_from_pip") - def test_show(self, patched_create_list_from_pip): - dialog_watcher = DialogWatcher("Manage Python Dependencies") - self.manager.show() - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - - -class TestPythonDepsStandaloneFunctions(unittest.TestCase): - - @patch("addonmanager_utilities.run_interruptable_subprocess") - def test_call_pip(self, mock_run_subprocess: MagicMock): - call_pip(["arg1", "arg2", "arg3"]) - mock_run_subprocess.assert_called() - args = mock_run_subprocess.call_args[0][0] - self.assertTrue("pip" in args) - - @patch("addonmanager_python_deps_gui.get_python_exe") - def test_call_pip_no_python(self, mock_get_python_exe: MagicMock): - mock_get_python_exe.return_value = None - with self.assertRaises(PipFailed): - call_pip(["arg1", "arg2", "arg3"]) - - @patch("addonmanager_utilities.run_interruptable_subprocess") - def test_call_pip_exception_raised(self, mock_run_subprocess: MagicMock): - mock_run_subprocess.side_effect = subprocess.CalledProcessError( - -1, "dummy_command", "Fake contents of stdout", "Fake contents of stderr" - ) - with self.assertRaises(PipFailed): - call_pip(["arg1", "arg2", "arg3"]) - - @patch("addonmanager_utilities.run_interruptable_subprocess") - def test_call_pip_splits_results(self, mock_run_subprocess: MagicMock): - result_mock = MagicMock() - result_mock.stdout = "\n".join(["Value 1", "Value 2", "Value 3"]) - mock_run_subprocess.return_value = result_mock - result = call_pip(["arg1", "arg2", "arg3"]) - self.assertEqual(len(result), 3) - - @patch("addonmanager_python_deps_gui.call_pip") - def test_python_package_updates_are_available(self, mock_call_pip: MagicMock): - mock_call_pip.return_value = "Some result" - result = python_package_updates_are_available() - self.assertEqual(result, True) - - @patch("addonmanager_python_deps_gui.call_pip") - def test_python_package_updates_are_available_no_results(self, mock_call_pip: MagicMock): - """An empty string is an indication that no updates are available""" - mock_call_pip.return_value = "" - result = python_package_updates_are_available() - self.assertEqual(result, False) - - @patch("addonmanager_python_deps_gui.call_pip") - def test_python_package_updates_are_available_pip_failure(self, mock_call_pip: MagicMock): - logging.disable() - mock_call_pip.side_effect = PipFailed("Test error message") - logging.disable() # A logging error message is expected here, but not desirable during test runs - result = python_package_updates_are_available() - self.assertEqual(result, False) - logging.disable(logging.NOTSET) - - def test_parse_pip_list_output_no_input(self): - results_dict = parse_pip_list_output("", "") - self.assertEqual(len(results_dict), 0) - - def test_parse_pip_list_output_all_packages_no_updates(self): - results_dict = parse_pip_list_output( - ["Package Version", "---------- -------", "gitdb 4.0.9", "setuptools 41.2.0"], - [], - ) - self.assertEqual(len(results_dict), 2) - self.assertTrue("gitdb" in results_dict) - self.assertTrue("setuptools" in results_dict) - self.assertEqual(results_dict["gitdb"]["installed_version"], "4.0.9") - self.assertEqual(results_dict["gitdb"]["available_version"], "") - self.assertEqual(results_dict["setuptools"]["installed_version"], "41.2.0") - self.assertEqual(results_dict["setuptools"]["available_version"], "") - - def test_parse_pip_list_output_all_packages_with_updates(self): - results_dict = parse_pip_list_output( - [], - [ - "Package Version Latest Type", - "---------- ------- ------ -----", - "pip 21.0.1 22.1.2 wheel", - "setuptools 41.2.0 63.2.0 wheel", - ], - ) - self.assertEqual(len(results_dict), 2) - self.assertTrue("pip" in results_dict) - self.assertTrue("setuptools" in results_dict) - self.assertEqual(results_dict["pip"]["installed_version"], "21.0.1") - self.assertEqual(results_dict["pip"]["available_version"], "22.1.2") - self.assertEqual(results_dict["setuptools"]["installed_version"], "41.2.0") - self.assertEqual(results_dict["setuptools"]["available_version"], "63.2.0") - - -if __name__ == "__main__": - app = QtWidgets.QApplication(sys.argv) - QtCore.QTimer.singleShot(0, unittest.main) - app.exec() diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_uninstaller_gui.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_uninstaller_gui.py deleted file mode 100644 index 538c8daac9..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_uninstaller_gui.py +++ /dev/null @@ -1,131 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import functools -import unittest - -from PySide import QtCore, QtWidgets - -import FreeCAD - -from AddonManagerTest.gui.gui_mocks import ( - DialogWatcher, - FakeWorker, - MockThread, -) -from AddonManagerTest.app.mocks import MockAddon - -from addonmanager_uninstaller_gui import AddonUninstallerGUI - -translate = FreeCAD.Qt.translate - - -class TestUninstallerGUI(unittest.TestCase): - - MODULE = "test_uninstaller_gui" # file name without extension - - def setUp(self): - self.addon_to_remove = MockAddon() - self.uninstaller_gui = AddonUninstallerGUI(self.addon_to_remove) - self.finalized_thread = False - self.signals_caught = [] - - def tearDown(self): - pass - - def catch_signal(self, signal_name, *_): - self.signals_caught.append(signal_name) - - def test_confirmation_dialog_yes(self): - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Confirm remove"), - QtWidgets.QDialogButtonBox.Yes, - ) - answer = self.uninstaller_gui._confirm_uninstallation() - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - self.assertTrue(answer, "Expected a 'Yes' click to return True, but got False") - - def test_confirmation_dialog_cancel(self): - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Confirm remove"), - QtWidgets.QDialogButtonBox.Cancel, - ) - answer = self.uninstaller_gui._confirm_uninstallation() - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - self.assertFalse(answer, "Expected a 'Cancel' click to return False, but got True") - - def test_progress_dialog(self): - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Removing Addon"), - QtWidgets.QDialogButtonBox.Cancel, - ) - self.uninstaller_gui._show_progress_dialog() - # That call isn't modal, so spin our own event loop: - while self.uninstaller_gui.progress_dialog.isVisible(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_timer_launches_progress_dialog(self): - worker = FakeWorker() - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Removing Addon"), - QtWidgets.QDialogButtonBox.Cancel, - ) - QtCore.QTimer.singleShot(1000, worker.stop) # If the test fails, this kills the "worker" - self.uninstaller_gui._confirm_uninstallation = lambda: True - self.uninstaller_gui._run_uninstaller = worker.work - self.uninstaller_gui._finalize = lambda: None - self.uninstaller_gui.dialog_timer.setInterval(1) # To speed up the test, only wait 1ms - self.uninstaller_gui.run() # Blocks once it hits the fake worker - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - worker.stop() - - def test_success_dialog(self): - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Uninstall complete"), - QtWidgets.QDialogButtonBox.Ok, - ) - self.uninstaller_gui._succeeded(self.addon_to_remove) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_failure_dialog(self): - dialog_watcher = DialogWatcher( - translate("AddonsInstaller", "Uninstall failed"), - QtWidgets.QDialogButtonBox.Ok, - ) - self.uninstaller_gui._failed( - self.addon_to_remove, "Some failure message\nAnother failure message" - ) - self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") - self.assertTrue(dialog_watcher.button_found, "Failed to find the expected button") - - def test_finalize(self): - self.uninstaller_gui.finished.connect(functools.partial(self.catch_signal, "finished")) - self.uninstaller_gui.worker_thread = MockThread() - self.uninstaller_gui._finalize() - self.assertIn("finished", self.signals_caught) diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_update_all_gui.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_update_all_gui.py deleted file mode 100644 index 8cea9f327b..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_update_all_gui.py +++ /dev/null @@ -1,260 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2025 FreeCAD project association AISBL * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -from time import sleep -import unittest -import FreeCAD - -from Addon import Addon - -from PySide import QtCore, QtWidgets - -from addonmanager_update_all_gui import UpdateAllGUI, AddonStatus - - -class MockUpdater(QtCore.QObject): - success = QtCore.Signal(object) - failure = QtCore.Signal(object) - finished = QtCore.Signal() - - def __init__(self, addon, addons=[]): - super().__init__() - self.addon_to_install = addon - self.addons = addons - self.has_run = False - self.emit_success = True - self.work_function = None # Set to some kind of callable to make this function take time - - def run(self): - self.has_run = True - if self.work_function is not None and callable(self.work_function): - self.work_function() - if self.emit_success: - self.success.emit(self.addon_to_install) - else: - self.failure.emit(self.addon_to_install) - self.finished.emit() - - -class MockUpdaterFactory: - def __init__(self, addons): - self.addons = addons - self.work_function = None - self.updater = None - - def get_updater(self, addon): - self.updater = MockUpdater(addon, self.addons) - self.updater.work_function = self.work_function - return self.updater - - -class MockAddon: - def __init__(self, name): - self.display_name = name - self.name = name - self.macro = None - self.metadata = None - self.installed_metadata = None - - def status(self): - return Addon.Status.UPDATE_AVAILABLE - - -class CallInterceptor: - def __init__(self): - self.called = False - self.args = None - - def intercept(self, *args): - self.called = True - self.args = args - - -class TestUpdateAllGui(unittest.TestCase): - def setUp(self): - self.addons = [] - for i in range(3): - self.addons.append(MockAddon(f"Mock Addon {i}")) - self.factory = MockUpdaterFactory(self.addons) - self.test_object = UpdateAllGUI(self.addons) - self.test_object.updater_factory = self.factory - - def tearDown(self): - pass - - def test_run(self): - self.factory.work_function = lambda: sleep(0.1) - self.test_object.run() - while self.test_object.is_running(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) - self.test_object.dialog.accept() - - def test_setup_dialog(self): - self.test_object._setup_dialog() - self.assertIsNotNone( - self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel) - ) - self.assertEqual(self.test_object.dialog.tableWidget.rowCount(), 3) - - def test_cancelling_installation(self): - class Worker: - def __init__(self): - self.counter = 0 - self.LIMIT = 100 - self.limit_reached = False - - def run(self): - while self.counter < self.LIMIT: - if QtCore.QThread.currentThread().isInterruptionRequested(): - return - self.counter += 1 - sleep(0.01) - self.limit_reached = True - - worker = Worker() - self.factory.work_function = worker.run - self.test_object.run() - cancel_timer = QtCore.QTimer() - cancel_timer.timeout.connect( - self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel).click - ) - cancel_timer.start(90) - while self.test_object.is_running(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 10) - self.assertGreater(len(self.test_object.addons_with_update), 0) - - def test_add_addon_to_table(self): - mock_addon = MockAddon("MockAddon") - self.test_object.dialog.tableWidget.clear() - self.test_object._add_addon_to_table(mock_addon, 1) - self.assertEqual(self.test_object.dialog.tableWidget.rowCount(), 1) - - def test_update_addon_status(self): - self.test_object._setup_dialog() - self.test_object._update_addon_status(0, AddonStatus.WAITING) - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.WAITING.ui_string(), - ) - self.test_object._update_addon_status(0, AddonStatus.INSTALLING) - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.INSTALLING.ui_string(), - ) - self.test_object._update_addon_status(0, AddonStatus.SUCCEEDED) - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.SUCCEEDED.ui_string(), - ) - self.test_object._update_addon_status(0, AddonStatus.FAILED) - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.FAILED.ui_string(), - ) - - def test_process_next_update(self): - self.test_object._setup_dialog() - self.test_object._launch_active_installer = lambda: None - self.test_object._process_next_update() - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.INSTALLING.ui_string(), - ) - - self.test_object._process_next_update() - self.assertEqual( - self.test_object.dialog.tableWidget.item(1, 2).text(), - AddonStatus.INSTALLING.ui_string(), - ) - - self.test_object._process_next_update() - self.assertEqual( - self.test_object.dialog.tableWidget.item(2, 2).text(), - AddonStatus.INSTALLING.ui_string(), - ) - - self.test_object._process_next_update() - - def test_launch_active_installer(self): - self.test_object.active_installer = self.factory.get_updater(self.addons[0]) - self.test_object._update_succeeded = lambda _: None - self.test_object._update_failed = lambda _: None - self.test_object.process_next_update = lambda: None - self.test_object._launch_active_installer() - # The above call does not block, so spin until it has completed (basically instantly in testing) - while self.test_object.worker_thread.isRunning(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) - self.test_object.dialog.accept() - - def test_update_succeeded(self): - self.test_object._setup_dialog() - self.test_object._update_succeeded(self.addons[0]) - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.SUCCEEDED.ui_string(), - ) - - def test_update_failed(self): - self.test_object._setup_dialog() - self.test_object._update_failed(self.addons[0]) - self.assertEqual( - self.test_object.dialog.tableWidget.item(0, 2).text(), - AddonStatus.FAILED.ui_string(), - ) - - def test_update_finished(self): - self.test_object._setup_dialog() - call_interceptor = CallInterceptor() - self.test_object.worker_thread = QtCore.QThread() - self.test_object.worker_thread.start() - self.test_object._process_next_update = call_interceptor.intercept - self.test_object.active_installer = self.factory.get_updater(self.addons[0]) - self.test_object._update_finished() - self.assertFalse(self.test_object.worker_thread.isRunning()) - self.test_object.worker_thread.quit() - self.assertTrue(call_interceptor.called) - self.test_object.worker_thread.wait() - - def test_finalize(self): - self.test_object._setup_dialog() - self.test_object.worker_thread = QtCore.QThread() - self.test_object.worker_thread.start() - self.test_object._finalize() - self.assertFalse(self.test_object.worker_thread.isRunning()) - self.test_object.worker_thread.quit() - self.test_object.worker_thread.wait() - self.assertFalse(self.test_object.running) - self.assertIsNotNone( - self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Close) - ) - self.assertIsNone( - self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel) - ) - - def test_is_running(self): - self.assertFalse(self.test_object.is_running()) - self.test_object.run() - self.assertTrue(self.test_object.is_running()) - while self.test_object.is_running(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100) - self.test_object.dialog.accept() diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_widget_progress_bar.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_widget_progress_bar.py deleted file mode 100644 index 1e6dca06a6..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_widget_progress_bar.py +++ /dev/null @@ -1,145 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import sys -import unittest - -sys.path.append("../..") - -from Widgets.addonmanager_widget_progress_bar import Progress - - -class TestProgress(unittest.TestCase): - - def test_default_construction(self): - """Given no parameters, a single-task Progress object is initialized with zero progress""" - progress = Progress() - self.assertEqual(progress.status_text, "") - self.assertEqual(progress.number_of_tasks, 1) - self.assertEqual(progress.current_task, 0) - self.assertEqual(progress.current_task_progress, 0.0) - - def test_good_parameters(self): - """Given good parameters, no exception is raised""" - _ = Progress( - status_text="Some text", number_of_tasks=1, current_task=0, current_task_progress=0.0 - ) - - def test_zero_task_count(self): - with self.assertRaises(ValueError): - _ = Progress(number_of_tasks=0) - - def test_negative_task_count(self): - with self.assertRaises(ValueError): - _ = Progress(number_of_tasks=-1) - - def test_setting_status_post_creation(self): - progress = Progress() - self.assertEqual(progress.status_text, "") - progress.status_text = "Some status" - self.assertEqual(progress.status_text, "Some status") - - def test_setting_task_count(self): - progress = Progress() - progress.number_of_tasks = 10 - self.assertEqual(progress.number_of_tasks, 10) - - def test_setting_negative_task_count(self): - progress = Progress() - with self.assertRaises(ValueError): - progress.number_of_tasks = -1 - - def test_setting_invalid_task_count(self): - progress = Progress() - with self.assertRaises(TypeError): - progress.number_of_tasks = 3.14159 - - def test_setting_current_task(self): - progress = Progress(number_of_tasks=10) - progress.number_of_tasks = 5 - self.assertEqual(progress.number_of_tasks, 5) - - def test_setting_current_task_greater_than_task_count(self): - progress = Progress() - progress.number_of_tasks = 10 - with self.assertRaises(ValueError): - progress.current_task = 11 - - def test_setting_current_task_equal_to_task_count(self): - """current_task is zero-indexed, so this is too high""" - progress = Progress() - progress.number_of_tasks = 10 - with self.assertRaises(ValueError): - progress.current_task = 10 - - def test_setting_current_task_negative(self): - progress = Progress() - with self.assertRaises(ValueError): - progress.current_task = -1 - - def test_setting_current_task_invalid(self): - progress = Progress() - with self.assertRaises(TypeError): - progress.current_task = 2.718281 - - def test_setting_current_task_progress(self): - progress = Progress() - progress.current_task_progress = 50.0 - self.assertEqual(progress.current_task_progress, 50.0) - - def test_setting_current_task_progress_too_low(self): - progress = Progress() - progress.current_task_progress = -0.01 - self.assertEqual(progress.current_task_progress, 0.0) - - def test_setting_current_task_progress_too_high(self): - progress = Progress() - progress.current_task_progress = 100.001 - self.assertEqual(progress.current_task_progress, 100.0) - - def test_incrementing_task(self): - progress = Progress(number_of_tasks=10, current_task_progress=100.0) - progress.next_task() - self.assertEqual(progress.current_task, 1) - self.assertEqual(progress.current_task_progress, 0.0) - - def test_incrementing_task_too_high(self): - progress = Progress(number_of_tasks=10, current_task=9, current_task_progress=100.0) - with self.assertRaises(ValueError): - progress.next_task() - - def test_overall_progress_simple(self): - progress = Progress() - self.assertEqual(progress.overall_progress(), 0.0) - - def test_overall_progress_with_ranges(self): - progress = Progress(number_of_tasks=2, current_task=1, current_task_progress=0.0) - self.assertAlmostEqual(progress.overall_progress(), 0.5) - - def test_overall_progress_with_ranges_and_progress(self): - progress = Progress(number_of_tasks=10, current_task=5, current_task_progress=50.0) - self.assertAlmostEqual(progress.overall_progress(), 0.55) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py deleted file mode 100644 index c3dda4b72a..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py +++ /dev/null @@ -1,200 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import json -import unittest -import os -import tempfile - -import FreeCAD - -from PySide import QtCore - -import NetworkManager -from Addon import Addon -from addonmanager_workers_startup import ( - CreateAddonListWorker, - LoadPackagesFromCacheWorker, - LoadMacrosFromCacheWorker, -) - -run_slow_tests = False - - -class TestWorkersStartup(unittest.TestCase): - - MODULE = "test_workers_startup" # file name without extension - - @unittest.skipUnless(run_slow_tests, "This integration test is slow and uses the network") - def setUp(self): - """Set up the test""" - self.test_dir = os.path.join( - FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data" - ) - - self.saved_mod_directory = Addon.mod_directory - self.saved_cache_directory = Addon.cache_directory - Addon.mod_directory = os.path.join(tempfile.gettempdir(), "FreeCADTesting", "Mod") - Addon.cache_directory = os.path.join(tempfile.gettempdir(), "FreeCADTesting", "Cache") - - os.makedirs(Addon.mod_directory, mode=0o777, exist_ok=True) - os.makedirs(Addon.cache_directory, mode=0o777, exist_ok=True) - - url = "https://api.github.com/zen" - NetworkManager.InitializeNetworkManager() - result = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url) - if result is None: - self.skipTest("No active internet connection detected") - - self.addon_list = [] - self.macro_counter = 0 - self.workbench_counter = 0 - self.prefpack_counter = 0 - self.addon_from_cache_counter = 0 - self.macro_from_cache_counter = 0 - - self.package_cache = {} - self.macro_cache = [] - - self.package_cache_filename = os.path.join(Addon.cache_directory, "packages.json") - self.macro_cache_filename = os.path.join(Addon.cache_directory, "macros.json") - - # Store the user's preference for whether git is enabled or disabled - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - self.saved_git_disabled_status = pref.GetBool("disableGit", False) - - def tearDown(self): - """Tear down the test""" - Addon.mod_directory = self.saved_mod_directory - Addon.cache_directory = self.saved_cache_directory - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - pref.SetBool("disableGit", self.saved_git_disabled_status) - - def test_create_addon_list_worker(self): - """Test whether any addons are added: runs the full query, so this potentially is a SLOW - test.""" - worker = CreateAddonListWorker() - worker.addon_repo.connect(self._addon_added) - worker.start() - while worker.isRunning(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - - self.assertGreater(self.macro_counter, 0, "No macros returned") - self.assertGreater(self.workbench_counter, 0, "No workbenches returned") - - # Make sure there are no duplicates: - addon_name_set = set() - for addon in self.addon_list: - addon_name_set.add(addon.name) - self.assertEqual( - len(addon_name_set), len(self.addon_list), "Duplicate names are not allowed" - ) - - # Write the cache data - if hasattr(self, "package_cache"): - with open(self.package_cache_filename, "w", encoding="utf-8") as f: - f.write(json.dumps(self.package_cache, indent=" ")) - if hasattr(self, "macro_cache"): - with open(self.macro_cache_filename, "w", encoding="utf-8") as f: - f.write(json.dumps(self.macro_cache, indent=" ")) - - original_macro_counter = self.macro_counter - original_addon_list = self.addon_list.copy() - self.macro_counter = 0 - self.workbench_counter = 0 - self.addon_list.clear() - - # Now try loading the same data from the cache we just created - worker = LoadPackagesFromCacheWorker(self.package_cache_filename) - worker.override_metadata_cache_path(os.path.join(Addon.cache_directory, "PackageMetadata")) - worker.addon_repo.connect(self._addon_added) - - worker.start() - while worker.isRunning(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - - worker = LoadMacrosFromCacheWorker(self.macro_cache_filename) - worker.add_macro_signal.connect(self._addon_added) - - worker.start() - while worker.isRunning(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - - # Make sure that every addon in the original list is also in the new list - fail_counter = 0 - for original_addon in original_addon_list: - found = False - for addon in self.addon_list: - if addon.name == original_addon.name: - found = True - break - if not found: - print(f"Failed to load {addon.name} from cache") - fail_counter += 1 - self.assertEqual(fail_counter, 0) - - # Make sure there are no duplicates: - addon_name_set.clear() - for addon in self.addon_list: - addon_name_set.add(addon.name) - - self.assertEqual(len(addon_name_set), len(self.addon_list)) - self.assertEqual(len(original_addon_list), len(self.addon_list)) - - self.assertEqual( - original_macro_counter, - self.macro_counter, - "Cache loaded a different number of macros", - ) - # We can't check workbench and preference pack counting at this point, because that relies - # on the package.xml metadata file, which this test does not download. - - def test_create_addon_list_git_disabled(self): - """If the user has git enabled, also test the addon manager with git disabled""" - if self.saved_git_disabled_status: - self.skipTest("Git is disabled, this test is redundant") - - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - pref.SetBool("disableGit", True) - - self.test_create_addon_list_worker() - - def _addon_added(self, addon: Addon): - """Callback for adding an Addon: tracks the list, and counts the various types""" - print(f"Addon added: {addon.name}") - self.addon_list.append(addon) - if addon.contains_workbench(): - self.workbench_counter += 1 - if addon.contains_macro(): - self.macro_counter += 1 - if addon.contains_preference_pack(): - self.prefpack_counter += 1 - - # Also record the information for cache purposes - if addon.macro is None: - self.package_cache[addon.name] = addon.to_cache() - else: - self.macro_cache.append(addon.macro.to_cache()) diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_utility.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_utility.py deleted file mode 100644 index cea77491aa..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_utility.py +++ /dev/null @@ -1,78 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import unittest -import os -import FreeCAD -from addonmanager_workers_utility import ConnectionChecker -from PySide import QtCore - -import NetworkManager - - -class TestWorkersUtility(unittest.TestCase): - - MODULE = "test_workers_utility" # file name without extension - - @unittest.skip("Test is slow and uses the network: refactor!") - def setUp(self): - self.test_dir = os.path.join( - FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data" - ) - self.last_result = None - - url = "https://api.github.com/zen" - NetworkManager.InitializeNetworkManager() - result = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url) - if result is None: - self.skipTest("No active internet connection detected") - - def test_connection_checker_basic(self): - """Tests the connection checking worker's basic operation: does not exit until worker thread completes""" - worker = ConnectionChecker() - worker.success.connect(self.connection_succeeded) - worker.failure.connect(self.connection_failed) - self.last_result = None - worker.start() - while worker.isRunning(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - self.assertEqual(self.last_result, "SUCCESS") - - def test_connection_checker_thread_interrupt(self): - worker = ConnectionChecker() - worker.success.connect(self.connection_succeeded) - worker.failure.connect(self.connection_failed) - self.last_result = None - worker.start() - worker.requestInterruption() - while worker.isRunning(): - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - self.assertIsNone(self.last_result, "Requesting interruption of thread failed to interrupt") - - def connection_succeeded(self): - self.last_result = "SUCCESS" - - def connection_failed(self): - self.last_result = "FAILURE" diff --git a/src/Mod/AddonManager/AddonManagerTest/test_information.md b/src/Mod/AddonManager/AddonManagerTest/test_information.md deleted file mode 100644 index 5df8cbc554..0000000000 --- a/src/Mod/AddonManager/AddonManagerTest/test_information.md +++ /dev/null @@ -1,3 +0,0 @@ -## Unit tests for the Addon Manager - -Data files are located in the `data/` subdirectory. diff --git a/src/Mod/AddonManager/AddonStats.py b/src/Mod/AddonManager/AddonStats.py deleted file mode 100644 index 4cf7b319ac..0000000000 --- a/src/Mod/AddonManager/AddonStats.py +++ /dev/null @@ -1,81 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Classes and structures related to Addon sidecar information""" -from __future__ import annotations - -from dataclasses import dataclass -from datetime import datetime -from typing import Optional - -import addonmanager_freecad_interface as fci - - -def to_int_or_zero(inp: [str | int | None]): - try: - return int(inp) - except TypeError: - return 0 - - -def time_string_to_datetime(inp: str) -> Optional[datetime]: - try: - return datetime.fromisoformat(inp) - except ValueError: - try: - # Support for the trailing "Z" was added in Python 3.11 -- strip it and see if it works now - return datetime.fromisoformat(inp[:-1]) - except ValueError: - fci.Console.PrintWarning(f"Unable to parse '{str}' as a Python datetime") - return None - - -@dataclass -class AddonStats: - """Statistics about an addon: not all stats apply to all addon types""" - - last_update_time: datetime | None = None - date_created: datetime | None = None - stars: int = 0 - open_issues: int = 0 - forks: int = 0 - license: str = "" - page_views_last_month: int = 0 - - @classmethod - def from_json(cls, json_dict: dict): - new_stats = AddonStats() - if "pushed_at" in json_dict: - new_stats.last_update_time = time_string_to_datetime(json_dict["pushed_at"]) - if "created_at" in json_dict: - new_stats.date_created = time_string_to_datetime(json_dict["created_at"]) - if "stargazers_count" in json_dict: - new_stats.stars = to_int_or_zero(json_dict["stargazers_count"]) - if "forks_count" in json_dict: - new_stats.forks = to_int_or_zero(json_dict["forks_count"]) - if "open_issues_count" in json_dict: - new_stats.open_issues = to_int_or_zero(json_dict["open_issues_count"]) - if "license" in json_dict: - if json_dict["license"] != "NOASSERTION" and json_dict["license"] != "None": - new_stats.license = json_dict["license"] # Might be None or "NOASSERTION" - return new_stats diff --git a/src/Mod/AddonManager/CMakeLists.txt b/src/Mod/AddonManager/CMakeLists.txt deleted file mode 100644 index 895b5e3bd2..0000000000 --- a/src/Mod/AddonManager/CMakeLists.txt +++ /dev/null @@ -1,189 +0,0 @@ -IF (BUILD_GUI) - PYSIDE_WRAP_RC(AddonManager_QRC_SRCS Resources/AddonManager.qrc) - add_subdirectory(Widgets) -ENDIF (BUILD_GUI) - -SET(AddonManager_SRCS - ALLOWED_PYTHON_PACKAGES.txt - Addon.py - AddonManager.py - AddonManager.ui - AddonManagerOptions.py - AddonManagerOptions.ui - AddonManagerOptions_AddCustomRepository.ui - AddonStats.py - Init.py - InitGui.py - NetworkManager.py - PythonDependencyUpdateDialog.ui - TestAddonManagerApp.py - add_toolbar_button_dialog.ui - addonmanager_cache.py - addonmanager_connection_checker.py - addonmanager_dependency_installer.py - addonmanager_devmode.py - addonmanager_devmode_add_content.py - addonmanager_devmode_license_selector.py - addonmanager_devmode_licenses_table.py - addonmanager_devmode_metadata_checker.py - addonmanager_devmode_people_table.py - addonmanager_devmode_person_editor.py - addonmanager_devmode_predictor.py - addonmanager_devmode_validators.py - addonmanager_firstrun.py - addonmanager_freecad_interface.py - addonmanager_git.py - addonmanager_installer.py - addonmanager_installer_gui.py - addonmanager_licenses.py - addonmanager_macro.py - addonmanager_macro_parser.py - addonmanager_metadata.py - addonmanager_package_details_controller.py - addonmanager_preferences_defaults.json - addonmanager_pyside_interface.py - addonmanager_python_deps_gui.py - addonmanager_readme_controller.py - addonmanager_uninstaller.py - addonmanager_uninstaller_gui.py - addonmanager_update_all_gui.py - addonmanager_utilities.py - addonmanager_workers_installation.py - addonmanager_workers_startup.py - addonmanager_workers_utility.py - change_branch.py - change_branch.ui - compact_view.py - composite_view.py - dependency_resolution_dialog.ui - developer_mode.ui - developer_mode_add_content.ui - developer_mode_advanced_freecad_versions.ui - developer_mode_copyright_info.ui - developer_mode_dependencies.ui - developer_mode_edit_dependency.ui - developer_mode_freecad_versions.ui - developer_mode_license.ui - developer_mode_licenses_table.ui - developer_mode_people.ui - developer_mode_people_table.ui - developer_mode_select_from_list.ui - developer_mode_tags.ui - expanded_view.py - first_run.ui - install_to_toolbar.py - loading.html - package_list.py - select_toolbar_dialog.ui - update_all.ui -) -IF (BUILD_GUI) - LIST(APPEND AddonManager_SRCS TestAddonManagerGui.py) -ENDIF (BUILD_GUI) - -SOURCE_GROUP("" FILES ${AddonManager_SRCS}) - -SET(AddonManagerTests_SRCS - AddonManagerTest/__init__.py - AddonManagerTest/test_information.md -) - -SET(AddonManagerTestsApp_SRCS - AddonManagerTest/app/__init__.py - AddonManagerTest/app/mocks.py - AddonManagerTest/app/test_addon.py - AddonManagerTest/app/test_addoncatalog.py - AddonManagerTest/app/test_cache.py - AddonManagerTest/app/test_dependency_installer.py - AddonManagerTest/app/test_freecad_interface.py - AddonManagerTest/app/test_git.py - AddonManagerTest/app/test_installer.py - AddonManagerTest/app/test_macro.py - AddonManagerTest/app/test_macro_parser.py - AddonManagerTest/app/test_metadata.py - AddonManagerTest/app/test_uninstaller.py - AddonManagerTest/app/test_utilities.py -) - -SET(AddonManagerTestsGui_SRCS - AddonManagerTest/gui/__init__.py - AddonManagerTest/gui/gui_mocks.py - AddonManagerTest/gui/test_gui.py - AddonManagerTest/gui/test_installer_gui.py - AddonManagerTest/gui/test_python_deps_gui.py - AddonManagerTest/gui/test_uninstaller_gui.py - AddonManagerTest/gui/test_update_all_gui.py - AddonManagerTest/gui/test_widget_progress_bar.py - AddonManagerTest/gui/test_workers_startup.py - AddonManagerTest/gui/test_workers_utility.py -) - -SET(AddonManagerTestsFiles_SRCS - AddonManagerTest/data/__init__.py - AddonManagerTest/data/addon_update_stats.json - AddonManagerTest/data/bundle_only.xml - AddonManagerTest/data/combination.xml - AddonManagerTest/data/corrupted_metadata.zip - AddonManagerTest/data/depends_on_all_workbenches.xml - AddonManagerTest/data/DoNothing.FCMacro - AddonManagerTest/data/git_submodules.txt - AddonManagerTest/data/good_package.xml - AddonManagerTest/data/icon_cache.zip - AddonManagerTest/data/icon_cache.zip.sha1 - AddonManagerTest/data/macro_only.xml - AddonManagerTest/data/macro_template.FCStd - AddonManagerTest/data/MacrosRecipesWikiPage.zip - AddonManagerTest/data/metadata.zip - AddonManagerTest/data/missing_macro_metadata.FCStd - AddonManagerTest/data/other_only.xml - AddonManagerTest/data/prefpack_only.xml - AddonManagerTest/data/test_addon_with_fcmacro.zip - AddonManagerTest/data/test_github_style_repo.zip - AddonManagerTest/data/test_repo.zip - AddonManagerTest/data/test_simple_repo.zip - AddonManagerTest/data/test_version_detection.xml - AddonManagerTest/data/TestWorkbench.zip - AddonManagerTest/data/workbench_only.xml -) - -SET(AddonManagerTests_ALL - ${AddonManagerTests_SRCS} - ${AddonManagerTestsApp_SRCS} - ${AddonManagerTestsFiles_SRCS} - ) - -IF (BUILD_GUI) - LIST(APPEND AddonManagerTests_ALL ${AddonManagerTestsGui_SRCS}) -ENDIF (BUILD_GUI) - -ADD_CUSTOM_TARGET(AddonManager ALL - SOURCES ${AddonManager_SRCS} ${AddonManager_QRC_SRCS} -) - -ADD_CUSTOM_TARGET(AddonManagerTests ALL - SOURCES ${AddonManagerTests_ALL} -) - -fc_copy_sources(AddonManager "${CMAKE_BINARY_DIR}/Mod/AddonManager" ${AddonManager_SRCS}) - -fc_copy_sources(AddonManagerTests "${CMAKE_BINARY_DIR}/Mod/AddonManager" ${AddonManagerTests_ALL}) - -IF (BUILD_GUI) - fc_target_copy_resource(AddonManager - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_BINARY_DIR}/Mod/AddonManager - AddonManager_rc.py) -ENDIF (BUILD_GUI) - -INSTALL( - FILES - ${AddonManager_SRCS} - ${AddonManager_QRC_SRCS} - DESTINATION - Mod/AddonManager -) - -INSTALL(FILES ${AddonManagerTests_SRCS} DESTINATION Mod/AddonManager/AddonManagerTest) -INSTALL(FILES ${AddonManagerTestsApp_SRCS} DESTINATION Mod/AddonManager/AddonManagerTest/app) -INSTALL(FILES ${AddonManagerTestsGui_SRCS} DESTINATION Mod/AddonManager/AddonManagerTest/gui) -INSTALL(FILES ${AddonManagerTestsFiles_SRCS} DESTINATION Mod/AddonManager/AddonManagerTest/data) diff --git a/src/Mod/AddonManager/Init.py b/src/Mod/AddonManager/Init.py deleted file mode 100644 index a09c412a0b..0000000000 --- a/src/Mod/AddonManager/Init.py +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# FreeCAD init script of the AddonManager module -# (c) 2001 Juergen Riegel -# License LGPL - -import FreeCAD - -FreeCAD.__unit_test__ += ["TestAddonManagerApp"] diff --git a/src/Mod/AddonManager/InitGui.py b/src/Mod/AddonManager/InitGui.py deleted file mode 100644 index 3173fd107d..0000000000 --- a/src/Mod/AddonManager/InitGui.py +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# AddonManager gui init module -# (c) 2001 Juergen Riegel -# License LGPL - -import AddonManager - -FreeCADGui.addLanguagePath(":/translations") -FreeCADGui.addCommand("Std_AddonMgr", AddonManager.CommandAddonManager()) - -import FreeCAD - -FreeCAD.__unit_test__ += ["TestAddonManagerGui"] diff --git a/src/Mod/AddonManager/NetworkManager.py b/src/Mod/AddonManager/NetworkManager.py deleted file mode 100644 index 34b91d7f88..0000000000 --- a/src/Mod/AddonManager/NetworkManager.py +++ /dev/null @@ -1,714 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -""" -############################################################################# -# -# ABOUT NETWORK MANAGER -# -# A wrapper around QNetworkAccessManager providing proxy-handling -# capabilities, and simplified access to submitting requests from any -# application thread. -# -# -# USAGE -# -# Once imported, this file provides access to a global object called -# AM_NETWORK_MANAGER. This is a QObject running on the main thread, but -# designed to be interacted with from any other application thread. It -# provides two principal methods: submit_unmonitored_get() and -# submit_monitored_get(). Use the unmonitored version for small amounts of -# data (suitable for caching in RAM, and without a need to show a progress -# bar during download), and the monitored version for larger amounts of data. -# Both functions take a URL, and return an integer index. That index allows -# tracking of the completed request by attaching to the signals completed(), -# progress_made(), and progress_complete(). All three provide, as the first -# argument to the signal, the index of the request the signal refers to. -# Code attached to those signals should filter them to look for the indices -# of the requests they care about. Requests may complete in any order. -# -# A secondary blocking interface is also provided, for very short network -# accesses: the blocking_get() function blocks until the network transmission -# is complete, directly returning a QByteArray object with the received data. -# Do not run on the main GUI thread! -""" - -import threading -import os -import queue -import itertools -import tempfile -import sys -from typing import Dict, List, Optional -from urllib.parse import urlparse - -try: - import FreeCAD - - if FreeCAD.GuiUp: - import FreeCADGui - - HAVE_FREECAD = True - translate = FreeCAD.Qt.translate -except ImportError: - # For standalone testing support working without the FreeCAD import - HAVE_FREECAD = False - -from PySide import QtCore - -if FreeCAD.GuiUp: - from PySide import QtWidgets - - -# This is the global instance of the NetworkManager that outside code -# should access -AM_NETWORK_MANAGER = None - -HAVE_QTNETWORK = True -try: - from PySide import QtNetwork -except ImportError: - if HAVE_FREECAD: - FreeCAD.Console.PrintError( - translate( - "AddonsInstaller", - 'Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork")', - ) - + "\n" - ) - else: - print("Could not import QtNetwork, unable to test this file.") - sys.exit(1) - HAVE_QTNETWORK = False - -if HAVE_QTNETWORK: - - # Added in Qt 5.15 - if hasattr(QtNetwork.QNetworkRequest, "DefaultTransferTimeoutConstant"): - timeoutConstant = QtNetwork.QNetworkRequest.DefaultTransferTimeoutConstant - if hasattr(timeoutConstant, "value"): - # Qt 6 changed the timeout constant to have a 'value' attribute. - # The function setTransferTimeout does not accept - # DefaultTransferTimeoutConstant of type - # QtNetwork.QNetworkRequest.TransferTimeoutConstant any - # longer but only an int. - default_timeout = timeoutConstant.value - else: - # In Qt 5.15 we can use the timeoutConstant as is. - default_timeout = timeoutConstant - else: - default_timeout = 30000 - - class QueueItem: - """A container for information about an item in the network queue.""" - - def __init__(self, index: int, request: QtNetwork.QNetworkRequest, track_progress: bool): - self.index = index - self.request = request - self.original_url = request.url() - self.track_progress = track_progress - - class NetworkManager(QtCore.QObject): - """A single global instance of NetworkManager is instantiated and stored as - AM_NETWORK_MANAGER. Outside threads should send GET requests to this class by - calling the submit_unmonitored_request() or submit_monitored_request() function, - as needed. See the documentation of those functions for details.""" - - # Connect to complete for requests with no progress monitoring (e.g. small amounts of data) - completed = QtCore.Signal( - int, int, QtCore.QByteArray - ) # Index, http response code, received data (if any) - - # Connect to progress_made and progress_complete for large amounts of data, which get buffered into a temp file - # That temp file should be deleted when your code is done with it - progress_made = QtCore.Signal(int, int, int) # Index, bytes read, total bytes (may be None) - - progress_complete = QtCore.Signal( - int, int, os.PathLike - ) # Index, http response code, filename - - __request_queued = QtCore.Signal() - - def __init__(self): - super().__init__() - - self.counting_iterator = itertools.count() - self.queue = queue.Queue() - self.__last_started_index = 0 - self.__abort_when_found: List[int] = [] - self.replies: Dict[int, QtNetwork.QNetworkReply] = {} - self.file_buffers = {} - - # We support an arbitrary number of threads using synchronous GET calls: - self.synchronous_lock = threading.Lock() - self.synchronous_complete: Dict[int, bool] = {} - self.synchronous_result_data: Dict[int, QtCore.QByteArray] = {} - - # Make sure we exit nicely on quit - if QtCore.QCoreApplication.instance() is not None: - QtCore.QCoreApplication.instance().aboutToQuit.connect(self.__aboutToQuit) - - # Create the QNAM on this thread: - self.QNAM = QtNetwork.QNetworkAccessManager() - self.QNAM.proxyAuthenticationRequired.connect(self.__authenticate_proxy) - self.QNAM.authenticationRequired.connect(self.__authenticate_resource) - self.QNAM.setRedirectPolicy(QtNetwork.QNetworkRequest.ManualRedirectPolicy) - - qnam_cache = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.CacheLocation) - os.makedirs(qnam_cache, exist_ok=True) - self.diskCache = QtNetwork.QNetworkDiskCache() - self.diskCache.setCacheDirectory(qnam_cache) - self.QNAM.setCache(self.diskCache) - - self.monitored_connections: List[int] = [] - self._setup_proxy() - - # A helper connection for our blocking interface - self.completed.connect(self.__synchronous_process_completion) - - # Set up our worker connection - self.__request_queued.connect(self.__setup_network_request) - - def _setup_proxy(self): - """Set up the proxy based on user preferences or prompts on command line""" - - # Set up the proxy, if necessary: - if HAVE_FREECAD: - ( - noProxyCheck, - systemProxyCheck, - userProxyCheck, - proxy_string, - ) = self._setup_proxy_freecad() - else: - ( - noProxyCheck, - systemProxyCheck, - userProxyCheck, - proxy_string, - ) = self._setup_proxy_standalone() - - if noProxyCheck: - pass - elif systemProxyCheck: - query = QtNetwork.QNetworkProxyQuery( - QtCore.QUrl("https://github.com/FreeCAD/FreeCAD") - ) - proxy = QtNetwork.QNetworkProxyFactory.systemProxyForQuery(query) - if proxy and proxy[0]: - self.QNAM.setProxy(proxy[0]) # This may still be QNetworkProxy.NoProxy - elif userProxyCheck: - try: - parsed_url = urlparse(proxy_string) - host = parsed_url.hostname - port = parsed_url.port - scheme = ( - "http" if parsed_url.scheme == "https" else parsed_url.scheme - ) # There seems no https type: doc.qt.io/qt-6/qnetworkproxy.html#ProxyType-enum - except ValueError: - FreeCAD.Console.PrintError( - translate( - "AddonsInstaller", - "Failed to parse proxy URL '{}'", - ).format(proxy_string) - + "\n" - ) - return - - FreeCAD.Console.PrintMessage(f"Using proxy {scheme}://{host}:{port} \n") - if scheme == "http": - _scheme = QtNetwork.QNetworkProxy.HttpProxy - elif scheme == "socks5": - _scheme = QtNetwork.QNetworkProxy.Socks5Proxy - else: - FreeCAD.Console.PrintWarning(f"Unknown proxy scheme '{scheme}', using http. \n") - _scheme = QtNetwork.QNetworkProxy.HttpProxy - proxy = QtNetwork.QNetworkProxy(_scheme, host, port) - self.QNAM.setProxy(proxy) - - def _setup_proxy_freecad(self): - """If we are running within FreeCAD, this uses the config data to set up the proxy""" - noProxyCheck = True - systemProxyCheck = False - userProxyCheck = False - proxy_string = "" - pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - noProxyCheck = pref.GetBool("NoProxyCheck", noProxyCheck) - systemProxyCheck = pref.GetBool("SystemProxyCheck", systemProxyCheck) - userProxyCheck = pref.GetBool("UserProxyCheck", userProxyCheck) - proxy_string = pref.GetString("ProxyUrl", "") - - # Add some error checking to the proxy setup, since for historical reasons they - # are independent booleans, rather than an enumeration: - option_count = [noProxyCheck, systemProxyCheck, userProxyCheck].count(True) - if option_count != 1: - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "Parameter error: mutually exclusive proxy options set. Resetting to default.", - ) - + "\n" - ) - noProxyCheck = True - systemProxyCheck = False - userProxyCheck = False - pref.SetBool("NoProxyCheck", noProxyCheck) - pref.SetBool("SystemProxyCheck", systemProxyCheck) - pref.SetBool("UserProxyCheck", userProxyCheck) - - if userProxyCheck and not proxy_string: - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "Parameter error: user proxy indicated, but no proxy provided. Resetting to default.", - ) - + "\n" - ) - noProxyCheck = True - userProxyCheck = False - pref.SetBool("NoProxyCheck", noProxyCheck) - pref.SetBool("UserProxyCheck", userProxyCheck) - return noProxyCheck, systemProxyCheck, userProxyCheck, proxy_string - - def _setup_proxy_standalone(self): - """If we are NOT running inside FreeCAD, prompt the user for proxy information""" - noProxyCheck = True - systemProxyCheck = False - userProxyCheck = False - proxy_string = "" - print("Please select a proxy type:") - print("1) No proxy") - print("2) Use system proxy settings") - print("3) Custom proxy settings") - result = input("Choice: ") - if result == "1": - pass - elif result == "2": - noProxyCheck = False - systemProxyCheck = True - elif result == "3": - noProxyCheck = False - userProxyCheck = True - proxy_string = input("Enter your proxy server (host:port): ") - else: - print(f"Got {result}, expected 1, 2, or 3.") - app.quit() - return noProxyCheck, systemProxyCheck, userProxyCheck, proxy_string - - def __aboutToQuit(self): - """Called when the application is about to quit. Not currently used.""" - - def __setup_network_request(self): - """Get the next request off the queue and launch it.""" - try: - item = self.queue.get_nowait() - if item: - if item.index in self.__abort_when_found: - self.__abort_when_found.remove(item.index) - return # Do not do anything with this item, it's been aborted... - if item.track_progress: - self.monitored_connections.append(item.index) - self.__launch_request(item.index, item.request) - except queue.Empty: - pass - - def __launch_request(self, index: int, request: QtNetwork.QNetworkRequest) -> None: - """Given a network request, ask the QNetworkAccessManager to begin processing it.""" - reply = self.QNAM.get(request) - self.replies[index] = reply - - self.__last_started_index = index - reply.finished.connect(self.__reply_finished) - reply.sslErrors.connect(self.__on_ssl_error) - if index in self.monitored_connections: - reply.readyRead.connect(self.__ready_to_read) - reply.downloadProgress.connect(self.__download_progress) - - def submit_unmonitored_get( - self, - url: str, - timeout_ms: int = default_timeout, - ) -> int: - """Adds this request to the queue, and returns an index that can be used by calling code - in conjunction with the completed() signal to handle the results of the call. All data is - kept in memory, and the completed() call includes a direct handle to the bytes returned. It - is not called until the data transfer has finished and the connection is closed.""" - - current_index = next(self.counting_iterator) # A thread-safe counter - # Use a queue because we can only put things on the QNAM from the main event loop thread - self.queue.put( - QueueItem( - current_index, self.__create_get_request(url, timeout_ms), track_progress=False - ) - ) - self.__request_queued.emit() - return current_index - - def submit_monitored_get( - self, - url: str, - timeout_ms: int = default_timeout, - ) -> int: - """Adds this request to the queue, and returns an index that can be used by calling code - in conjunction with the progress_made() and progress_completed() signals to handle the - results of the call. All data is cached to disk, and progress is reported periodically - as the underlying QNetworkReply reports its progress. The progress_completed() signal - contains a path to a temporary file with the stored data. Calling code should delete this - file when done with it (or move it into its final place, etc.).""" - - current_index = next(self.counting_iterator) # A thread-safe counter - # Use a queue because we can only put things on the QNAM from the main event loop thread - self.queue.put( - QueueItem( - current_index, self.__create_get_request(url, timeout_ms), track_progress=True - ) - ) - self.__request_queued.emit() - return current_index - - def blocking_get( - self, - url: str, - timeout_ms: int = default_timeout, - ) -> Optional[QtCore.QByteArray]: - """Submits a GET request to the QNetworkAccessManager and block until it is complete""" - - current_index = next(self.counting_iterator) # A thread-safe counter - with self.synchronous_lock: - self.synchronous_complete[current_index] = False - - self.queue.put( - QueueItem( - current_index, self.__create_get_request(url, timeout_ms), track_progress=False - ) - ) - self.__request_queued.emit() - while True: - if QtCore.QThread.currentThread().isInterruptionRequested(): - return None - QtCore.QCoreApplication.processEvents() - with self.synchronous_lock: - if self.synchronous_complete[current_index]: - break - - with self.synchronous_lock: - self.synchronous_complete.pop(current_index) - if current_index in self.synchronous_result_data: - return self.synchronous_result_data.pop(current_index) - return None - - def __synchronous_process_completion( - self, index: int, code: int, data: QtCore.QByteArray - ) -> None: - """Check the return status of a completed process, and handle its returned data (if - any).""" - with self.synchronous_lock: - if index in self.synchronous_complete: - if code == 200: - self.synchronous_result_data[index] = data - else: - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "Addon Manager: Unexpected {} response from server", - ).format(code) - + "\n" - ) - self.synchronous_complete[index] = True - - @staticmethod - def __create_get_request(url: str, timeout_ms: int) -> QtNetwork.QNetworkRequest: - """Construct a network request to a given URL""" - request = QtNetwork.QNetworkRequest(QtCore.QUrl(url)) - request.setAttribute( - QtNetwork.QNetworkRequest.RedirectPolicyAttribute, - QtNetwork.QNetworkRequest.ManualRedirectPolicy, - ) - request.setAttribute(QtNetwork.QNetworkRequest.CacheSaveControlAttribute, True) - request.setAttribute( - QtNetwork.QNetworkRequest.CacheLoadControlAttribute, - QtNetwork.QNetworkRequest.PreferNetwork, - ) - if hasattr(request, "setTransferTimeout"): - # Added in Qt 5.15 - # In Qt 5, the function setTransferTimeout seems to accept - # DefaultTransferTimeoutConstant of type - # PySide2.QtNetwork.QNetworkRequest.TransferTimeoutConstant, - # whereas in Qt 6, the function seems to only accept an - # integer. - request.setTransferTimeout(timeout_ms) - return request - - def abort_all(self): - """Abort ALL network calls in progress, including clearing the queue""" - for reply in self.replies.values(): - if reply.abort().isRunning(): - reply.abort() - while True: - try: - self.queue.get() - self.queue.task_done() - except queue.Empty: - break - - def abort(self, index: int): - """Abort a specific request""" - if index in self.replies and self.replies[index].isRunning(): - self.replies[index].abort() - elif index < self.__last_started_index: - # It's still in the queue. Mark it for later destruction. - self.__abort_when_found.append(index) - - def __authenticate_proxy( - self, - reply: QtNetwork.QNetworkProxy, - authenticator: QtNetwork.QAuthenticator, - ): - """If proxy authentication is required, attempt to authenticate. If the GUI is running this displays - a window asking for credentials. If the GUI is not running, it prompts on the command line. - """ - if HAVE_FREECAD and FreeCAD.GuiUp: - proxy_authentication = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "proxy_authentication.ui") - ) - # Show the right labels, etc. - proxy_authentication.labelProxyAddress.setText(f"{reply.hostName()}:{reply.port()}") - if authenticator.realm(): - proxy_authentication.labelProxyRealm.setText(authenticator.realm()) - else: - proxy_authentication.labelProxyRealm.hide() - proxy_authentication.labelRealmCaption.hide() - result = proxy_authentication.exec() - if result == QtWidgets.QDialogButtonBox.Ok: - authenticator.setUser(proxy_authentication.lineEditUsername.text()) - authenticator.setPassword(proxy_authentication.lineEditPassword.text()) - else: - username = input("Proxy username: ") - import getpass - - password = getpass.getpass() - authenticator.setUser(username) - authenticator.setPassword(password) - - def __authenticate_resource( - self, - _reply: QtNetwork.QNetworkReply, - _authenticator: QtNetwork.QAuthenticator, - ): - """Unused.""" - - def __on_ssl_error(self, reply: str, errors: List[str] = None): - """Called when an SSL error occurs: prints the error information.""" - if HAVE_FREECAD: - FreeCAD.Console.PrintWarning( - translate("AddonsInstaller", "Error with encrypted connection") + "\n:" - ) - FreeCAD.Console.PrintWarning(reply) - if errors is not None: - for error in errors: - FreeCAD.Console.PrintWarning(error) - else: - print("Error with encrypted connection") - if errors is not None: - for error in errors: - print(error) - - def __download_progress(self, bytesReceived: int, bytesTotal: int) -> None: - """Monitors download progress and emits a progress_made signal""" - sender = self.sender() - if not sender: - return - for index, reply in self.replies.items(): - if reply == sender: - self.progress_made.emit(index, bytesReceived, bytesTotal) - return - - def __ready_to_read(self) -> None: - """Called when data is available, this reads that data.""" - sender = self.sender() - if not sender: - return - - for index, reply in self.replies.items(): - if reply == sender: - self.__data_incoming(index, reply) - return - - def __data_incoming(self, index: int, reply: QtNetwork.QNetworkReply) -> None: - """Read incoming data and attach it to a data object""" - if not index in self.replies: - # We already finished this reply, this is a vestigial signal - return - buffer = reply.readAll() - if not index in self.file_buffers: - f = tempfile.NamedTemporaryFile("wb", delete=False) - self.file_buffers[index] = f - else: - f = self.file_buffers[index] - try: - f.write(buffer.data()) - except OSError as e: - if HAVE_FREECAD: - FreeCAD.Console.PrintError(f"Network Manager internal error: {str(e)}") - else: - print(f"Network Manager internal error: {str(e)}") - - def __reply_finished(self) -> None: - """Called when a reply has been completed: this makes sure the data has been read and - any notifications have been called.""" - reply = self.sender() - if not reply: - # This can happen during a cancellation operation: silently do nothing - return - - index = None - for key, value in self.replies.items(): - if reply == value: - index = key - break - if index is None: - return - - response_code = reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute) - redirect_codes = [301, 302, 303, 305, 307, 308] - if response_code in redirect_codes: # This is a redirect - timeout_ms = default_timeout - if hasattr(reply, "request"): - request = reply.request() - if hasattr(request, "transferTimeout"): - timeout_ms = request.transferTimeout() - new_url = reply.attribute(QtNetwork.QNetworkRequest.RedirectionTargetAttribute) - self.__launch_request(index, self.__create_get_request(new_url, timeout_ms)) - return # The task is not done, so get out of this method now - if reply.error() != QtNetwork.QNetworkReply.NetworkError.OperationCanceledError: - # It this was not a timeout, make sure we mark the queue task done - self.queue.task_done() - if reply.error() == QtNetwork.QNetworkReply.NetworkError.NoError: - if index in self.monitored_connections: - # Make sure to read any remaining data - self.__data_incoming(index, reply) - self.monitored_connections.remove(index) - f = self.file_buffers[index] - f.close() - self.progress_complete.emit(index, response_code, f.name) - else: - data = reply.readAll() - self.completed.emit(index, response_code, data) - else: - FreeCAD.Console.PrintWarning(f"Request failed: {reply.error()} \n") - if index in self.monitored_connections: - self.progress_complete.emit(index, response_code, "") - else: - self.completed.emit(index, response_code, None) - self.replies.pop(index) - -else: # HAVE_QTNETWORK is false: - - class NetworkManager(QtCore.QObject): - """A dummy class to enable an offline mode when the QtNetwork package is not yet installed""" - - completed = QtCore.Signal( - int, int, bytes - ) # Emitted as soon as the request is made, with a connection failed error - progress_made = QtCore.Signal(int, int, int) # Never emitted, no progress is made here - progress_complete = QtCore.Signal( - int, int, os.PathLike - ) # Emitted as soon as the request is made, with a connection failed error - - def __init__(self): - super().__init__() - self.monitored_queue = queue.Queue() - self.unmonitored_queue = queue.Queue() - - def submit_unmonitored_request(self, _) -> int: - """Returns a fake index that can be used for testing -- nothing is actually queued""" - current_index = next(itertools.count()) - self.unmonitored_queue.put(current_index) - return current_index - - def submit_monitored_request(self, _) -> int: - """Returns a fake index that can be used for testing -- nothing is actually queued""" - current_index = next(itertools.count()) - self.monitored_queue.put(current_index) - return current_index - - def blocking_get(self, _: str) -> QtCore.QByteArray: - """No operation - returns None immediately""" - return None - - def abort_all( - self, - ): - """There is nothing to abort in this case""" - - def abort(self, _): - """There is nothing to abort in this case""" - - -def InitializeNetworkManager(): - """Called once at the beginning of program execution to create the appropriate manager object""" - global AM_NETWORK_MANAGER - if AM_NETWORK_MANAGER is None: - AM_NETWORK_MANAGER = NetworkManager() - - -if __name__ == "__main__": - app = QtCore.QCoreApplication() - - InitializeNetworkManager() - - count = 0 - - # For testing, create several network requests and send them off in quick succession: - # (Choose small downloads, no need for significant data) - urls = [ - "https://api.github.com/zen", - "http://climate.ok.gov/index.php/climate/rainfall_table/local_data", - "https://tigerweb.geo.census.gov/arcgis/rest/services/TIGERweb/AIANNHA/MapServer", - ] - - def handle_completion(index: int, code: int, data): - """Attached to the completion signal, prints diagnostic information about the network access""" - global count - if code == 200: - print(f"For request {index+1}, response was {data.size()} bytes.", flush=True) - else: - print( - f"For request {index+1}, request failed with HTTP result code {code}", - flush=True, - ) - - count += 1 - if count >= len(urls): - print("Shutting down...", flush=True) - AM_NETWORK_MANAGER.requestInterruption() - AM_NETWORK_MANAGER.wait(5000) - app.quit() - - AM_NETWORK_MANAGER.completed.connect(handle_completion) - for test_url in urls: - AM_NETWORK_MANAGER.submit_unmonitored_get(test_url) - - app.exec_() - - print("Done with all requests.") diff --git a/src/Mod/AddonManager/PythonDependencyUpdateDialog.ui b/src/Mod/AddonManager/PythonDependencyUpdateDialog.ui deleted file mode 100644 index af32fadc5e..0000000000 --- a/src/Mod/AddonManager/PythonDependencyUpdateDialog.ui +++ /dev/null @@ -1,109 +0,0 @@ - - - PythonDependencyUpdateDialog - - - - 0 - 0 - 528 - 300 - - - - Manage Python Dependencies - - - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - true - - - - - - - placeholder for path - - - Qt::TextSelectableByMouse - - - - - - - true - - - QAbstractItemView::SelectRows - - - true - - - 5 - - - true - - - false - - - - Package name - - - - - Installed version - - - - - Available version - - - - - Used by - - - - - - - - - - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - true - - - - - - - - - Update all available - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/AddonManager.qrc b/src/Mod/AddonManager/Resources/AddonManager.qrc deleted file mode 100644 index e8b651c079..0000000000 --- a/src/Mod/AddonManager/Resources/AddonManager.qrc +++ /dev/null @@ -1,127 +0,0 @@ - - - icons/preferences-addon_manager.svg - icons/3D_Printing_Tools_workbench_icon.svg - icons/AddonMgrWithWarning.svg - icons/A2plus_workbench_icon.svg - icons/AirPlaneDesign_workbench_icon.svg - icons/ArchTextures_workbench_icon.svg - icons/Assembly4_workbench_icon.svg - icons/BCFPlugin_workbench_icon.svg - icons/BIMBots_workbench_icon.svg - icons/BIM_workbench_icon.svg - icons/BOLTSFC_workbench_icon.svg - icons/CADExchanger_workbench_icon.svg - icons/cadquery_module_workbench_icon.svg - icons/Cfd_workbench_icon.svg - icons/CfdOF_workbench_icon.svg - icons/CurvedShapes_workbench_icon.svg - icons/Curves_workbench_icon.svg - icons/Defeaturing_workbench_icon.svg - icons/DesignSPHysics_workbench_icon.svg - icons/dodo_workbench_icon.svg - icons/DynamicData_workbench_icon.svg - icons/EM_workbench_icon.svg - icons/ExplodedAssembly_workbench_icon.svg - icons/ExtMan_workbench_icon.svg - icons/fasteners_workbench_icon.svg - icons/flamingo_workbench_icon.svg - icons/FEM_FrontISTR_workbench_icon.svg - icons/GDML_workbench_icon.svg - icons/GDT_workbench_icon.svg - icons/FCGear_workbench_icon.svg - icons/Geomatics_workbench_icon.svg - icons/ImportNURBS_workbench_icon.svg - icons/InventorLoader_workbench_icon.svg - icons/kicadStepUpMod_workbench_icon.svg - icons/lattice2_workbench_icon.svg - icons/LCInterlocking_workbench_icon.svg - icons/Lithophane_workbench_icon.svg - icons/Maker_workbench_icon.svg - icons/Manipulator_workbench_icon.svg - icons/Marz_workbench_icon.svg - icons/MeshRemodel_workbench_icon.svg - icons/ModernUI_workbench_icon.svg - icons/MOOC_workbench_icon.svg - icons/MnesarcoUtils_workbench_icon.svg - icons/OSE3dPrinter_workbench_icon.svg - icons/Part-o-magic_workbench_icon.svg - icons/Plot_workbench_icon.svg - icons/POV-Ray-Rendering_workbench_icon.svg - icons/Pyramids-and-Polyhedrons_workbench_icon.svg - icons/pyrate_workbench_icon.svg - icons/Reinforcement_workbench_icon.svg - icons/Reporting_workbench_icon.svg - icons/Render_workbench_icon.svg - icons/Rocket_workbench_icon.svg - icons/sheetmetal_workbench_icon.svg - icons/slic3r-tools_workbench_icon.svg - icons/Ship_workbench_icon.svg - icons/Silk_workbench_icon.svg - icons/TaackPLM_workbench_icon.svg - icons/timber_workbench_icon.svg - icons/ThreadProfile_workbench_icon.svg - icons/WebTools_workbench_icon.svg - icons/workfeature_workbench_icon.svg - icons/yaml-workspace_workbench_icon.svg - icons/compact_view.svg - icons/composite_view.svg - icons/expanded_view.svg - icons/sort_ascending.svg - icons/sort_descending.svg - licenses/Apache-2.0.txt - licenses/BSD-2-Clause.txt - licenses/BSD-3-Clause.txt - licenses/CC0-1.0.txt - licenses/GPL-2.0-or-later.txt - licenses/GPL-3.0-or-later.txt - licenses/LGPL-2.1-or-later.txt - licenses/LGPL-3.0-or-later.txt - licenses/MIT.txt - licenses/MPL-2.0.txt - licenses/spdx.json - translations/AddonManager_af.qm - translations/AddonManager_ar.qm - translations/AddonManager_ca.qm - translations/AddonManager_cs.qm - translations/AddonManager_de.qm - translations/AddonManager_el.qm - translations/AddonManager_es-ES.qm - translations/AddonManager_eu.qm - translations/AddonManager_fi.qm - translations/AddonManager_fil.qm - translations/AddonManager_fr.qm - translations/AddonManager_gl.qm - translations/AddonManager_hr.qm - translations/AddonManager_hu.qm - translations/AddonManager_id.qm - translations/AddonManager_it.qm - translations/AddonManager_ja.qm - translations/AddonManager_kab.qm - translations/AddonManager_ko.qm - translations/AddonManager_lt.qm - translations/AddonManager_nl.qm - translations/AddonManager_no.qm - translations/AddonManager_pl.qm - translations/AddonManager_pt-BR.qm - translations/AddonManager_pt-PT.qm - translations/AddonManager_ro.qm - translations/AddonManager_ru.qm - translations/AddonManager_sk.qm - translations/AddonManager_sl.qm - translations/AddonManager_sr.qm - translations/AddonManager_sv-SE.qm - translations/AddonManager_tr.qm - translations/AddonManager_uk.qm - translations/AddonManager_val-ES.qm - translations/AddonManager_vi.qm - translations/AddonManager_zh-CN.qm - translations/AddonManager_zh-TW.qm - translations/AddonManager_es-AR.qm - translations/AddonManager_bg.qm - translations/AddonManager_ka.qm - translations/AddonManager_sr-CS.qm - translations/AddonManager_be.qm - translations/AddonManager_da.qm - - diff --git a/src/Mod/AddonManager/Resources/icons/3D_Printing_Tools_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/3D_Printing_Tools_workbench_icon.svg deleted file mode 100644 index 4c3cfa8827..0000000000 --- a/src/Mod/AddonManager/Resources/icons/3D_Printing_Tools_workbench_icon.svg +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/A2plus_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/A2plus_workbench_icon.svg deleted file mode 100644 index 5e5162a293..0000000000 --- a/src/Mod/AddonManager/Resources/icons/A2plus_workbench_icon.svg +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - Path-Stock - 2015-07-04 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-Stock.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/AddonMgrWithWarning.svg b/src/Mod/AddonManager/Resources/icons/AddonMgrWithWarning.svg deleted file mode 100644 index 8bcf1cfa9d..0000000000 --- a/src/Mod/AddonManager/Resources/icons/AddonMgrWithWarning.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/AirPlaneDesign_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/AirPlaneDesign_workbench_icon.svg deleted file mode 100644 index 03f4896f8e..0000000000 --- a/src/Mod/AddonManager/Resources/icons/AirPlaneDesign_workbench_icon.svg +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/ArchTextures_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/ArchTextures_workbench_icon.svg deleted file mode 100644 index 3acdd00c6b..0000000000 --- a/src/Mod/AddonManager/Resources/icons/ArchTextures_workbench_icon.svg +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Assembly4_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Assembly4_workbench_icon.svg deleted file mode 100644 index 36005737ed..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Assembly4_workbench_icon.svg +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - Path-Stock - 2015-07-04 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-Stock.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/BCFPlugin_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/BCFPlugin_workbench_icon.svg deleted file mode 100644 index ccf9f03b06..0000000000 --- a/src/Mod/AddonManager/Resources/icons/BCFPlugin_workbench_icon.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/Mod/AddonManager/Resources/icons/BIMBots_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/BIMBots_workbench_icon.svg deleted file mode 100644 index 59cf6d7395..0000000000 --- a/src/Mod/AddonManager/Resources/icons/BIMBots_workbench_icon.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/BIM_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/BIM_workbench_icon.svg deleted file mode 100644 index 73a41130b7..0000000000 --- a/src/Mod/AddonManager/Resources/icons/BIM_workbench_icon.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/BOLTSFC_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/BOLTSFC_workbench_icon.svg deleted file mode 100644 index ce124ff301..0000000000 --- a/src/Mod/AddonManager/Resources/icons/BOLTSFC_workbench_icon.svg +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/CADExchanger_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/CADExchanger_workbench_icon.svg deleted file mode 100644 index 49ff8dfa50..0000000000 --- a/src/Mod/AddonManager/Resources/icons/CADExchanger_workbench_icon.svg +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/CfdOF_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/CfdOF_workbench_icon.svg deleted file mode 100644 index 9db1fd2cbf..0000000000 --- a/src/Mod/AddonManager/Resources/icons/CfdOF_workbench_icon.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Cfd_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Cfd_workbench_icon.svg deleted file mode 100644 index 1652933f31..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Cfd_workbench_icon.svg +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/CurvedShapes_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/CurvedShapes_workbench_icon.svg deleted file mode 100644 index 9473fea256..0000000000 --- a/src/Mod/AddonManager/Resources/icons/CurvedShapes_workbench_icon.svg +++ /dev/null @@ -1,744 +0,0 @@ - - - - - - image/svg+xml - - FreeCAD SVG Export - - - - - FreeCAD SVG Export - Drawing page: Page exported from FreeCAD document: horten_wing - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Curves_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Curves_workbench_icon.svg deleted file mode 100644 index 7986716229..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Curves_workbench_icon.svg +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Defeaturing_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Defeaturing_workbench_icon.svg deleted file mode 100644 index ab9980ced3..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Defeaturing_workbench_icon.svg +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [Yorik van Havre] - - - Arch_Pipe_Tree - 2016-08-24 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Arch/Resources/icons/Arch_Pipe_Tree.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/DesignSPHysics_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/DesignSPHysics_workbench_icon.svg deleted file mode 100644 index de9106a89e..0000000000 --- a/src/Mod/AddonManager/Resources/icons/DesignSPHysics_workbench_icon.svg +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/DynamicData_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/DynamicData_workbench_icon.svg deleted file mode 100644 index c46277fd3f..0000000000 --- a/src/Mod/AddonManager/Resources/icons/DynamicData_workbench_icon.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/EM_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/EM_workbench_icon.svg deleted file mode 100644 index 66486fc6e1..0000000000 --- a/src/Mod/AddonManager/Resources/icons/EM_workbench_icon.svg +++ /dev/null @@ -1,602 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [triplus] - - - ArchWorkbench - 2016-02-26 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Arch/Resources/icons/ArchWorkbench.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/ExplodedAssembly_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/ExplodedAssembly_workbench_icon.svg deleted file mode 100644 index 6879a75884..0000000000 --- a/src/Mod/AddonManager/Resources/icons/ExplodedAssembly_workbench_icon.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/ExtMan_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/ExtMan_workbench_icon.svg deleted file mode 100644 index ae29e44317..0000000000 --- a/src/Mod/AddonManager/Resources/icons/ExtMan_workbench_icon.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/FCGear_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/FCGear_workbench_icon.svg deleted file mode 100644 index 3579612b1a..0000000000 --- a/src/Mod/AddonManager/Resources/icons/FCGear_workbench_icon.svg +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/FEM_FrontISTR_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/FEM_FrontISTR_workbench_icon.svg deleted file mode 100644 index 4c3fe05d44..0000000000 --- a/src/Mod/AddonManager/Resources/icons/FEM_FrontISTR_workbench_icon.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/GDML_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/GDML_workbench_icon.svg deleted file mode 100644 index acdf4bd819..0000000000 --- a/src/Mod/AddonManager/Resources/icons/GDML_workbench_icon.svg +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [triplus] - - - OpenSCADWorkbench - 2016-02-26 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/OpenSCAD/Resources/icons/OpenSCADWorkbench.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/GDT_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/GDT_workbench_icon.svg deleted file mode 100644 index ea4ef88e68..0000000000 --- a/src/Mod/AddonManager/Resources/icons/GDT_workbench_icon.svg +++ /dev/null @@ -1,420 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Geomatics_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Geomatics_workbench_icon.svg deleted file mode 100644 index e39563c820..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Geomatics_workbench_icon.svg +++ /dev/null @@ -1 +0,0 @@ -Layer 1 diff --git a/src/Mod/AddonManager/Resources/icons/ImportNURBS_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/ImportNURBS_workbench_icon.svg deleted file mode 100644 index 7446dd70dd..0000000000 --- a/src/Mod/AddonManager/Resources/icons/ImportNURBS_workbench_icon.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/InventorLoader_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/InventorLoader_workbench_icon.svg deleted file mode 100644 index c1292a311d..0000000000 --- a/src/Mod/AddonManager/Resources/icons/InventorLoader_workbench_icon.svg +++ /dev/null @@ -1,329 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/LCInterlocking_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/LCInterlocking_workbench_icon.svg deleted file mode 100644 index c3957ff9f5..0000000000 --- a/src/Mod/AddonManager/Resources/icons/LCInterlocking_workbench_icon.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Lithophane_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Lithophane_workbench_icon.svg deleted file mode 100644 index 1101468760..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Lithophane_workbench_icon.svg +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/MOOC_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/MOOC_workbench_icon.svg deleted file mode 100644 index f79589f108..0000000000 --- a/src/Mod/AddonManager/Resources/icons/MOOC_workbench_icon.svg +++ /dev/null @@ -1,1175 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Maker_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Maker_workbench_icon.svg deleted file mode 100644 index f1e2c9143e..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Maker_workbench_icon.svg +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Manipulator_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Manipulator_workbench_icon.svg deleted file mode 100644 index 80cb90ea8f..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Manipulator_workbench_icon.svg +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - Mon Oct 10 13:44:52 2011 +0000 - - - [wmayer] - - - - - FreeCAD LGPL2+ - - - - - FreeCAD - - - FreeCAD/src/Mod/Draft/Resources/icons/Draft_Move.svg - https://www.freecad.org/wiki/index.php?title=Artwork - - - [agryson] Alexander Gryson - - - - - arrow - move - arrows - compass - cross - - - Four equally sized arrow heads at 90° to each other, all joined at the tail - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Marz_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Marz_workbench_icon.svg deleted file mode 100644 index 7e76002095..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Marz_workbench_icon.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/MeshRemodel_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/MeshRemodel_workbench_icon.svg deleted file mode 100644 index 44a68477de..0000000000 --- a/src/Mod/AddonManager/Resources/icons/MeshRemodel_workbench_icon.svg +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/MnesarcoUtils_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/MnesarcoUtils_workbench_icon.svg deleted file mode 100644 index 55097cf050..0000000000 --- a/src/Mod/AddonManager/Resources/icons/MnesarcoUtils_workbench_icon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/ModernUI_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/ModernUI_workbench_icon.svg deleted file mode 100644 index e0b3a738b1..0000000000 --- a/src/Mod/AddonManager/Resources/icons/ModernUI_workbench_icon.svg +++ /dev/null @@ -1,259 +0,0 @@ - - - Modern UI Logo - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - Modern UI Logo - - - [bitacovir] - - - - - - CC BY - - - 04-20-2020 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/OSE3dPrinter_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/OSE3dPrinter_workbench_icon.svg deleted file mode 100644 index fdacc3d703..0000000000 --- a/src/Mod/AddonManager/Resources/icons/OSE3dPrinter_workbench_icon.svg +++ /dev/null @@ -1,3 +0,0 @@ - -image/svg+xml - diff --git a/src/Mod/AddonManager/Resources/icons/POV-Ray-Rendering_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/POV-Ray-Rendering_workbench_icon.svg deleted file mode 100644 index 6931e1e02a..0000000000 --- a/src/Mod/AddonManager/Resources/icons/POV-Ray-Rendering_workbench_icon.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Part-o-magic_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Part-o-magic_workbench_icon.svg deleted file mode 100644 index 1b4675d0fc..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Part-o-magic_workbench_icon.svg +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Plot_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Plot_workbench_icon.svg deleted file mode 100644 index 1bb0f53a02..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Plot_workbench_icon.svg +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [triplus] - - - PlotWorkbench - 2016-02-26 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Plot/resources/icons/PlotWorkbench.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Pyramids-and-Polyhedrons_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Pyramids-and-Polyhedrons_workbench_icon.svg deleted file mode 100644 index 55c0ccd4b9..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Pyramids-and-Polyhedrons_workbench_icon.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Reinforcement_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Reinforcement_workbench_icon.svg deleted file mode 100644 index e1aa380dd3..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Reinforcement_workbench_icon.svg +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [Yorik van Havre] - - - Arch_Rebar - 2013-10-07 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Arch/Resources/icons/Arch_Rebar.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Render_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Render_workbench_icon.svg deleted file mode 100644 index 8ce9fbfdc6..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Render_workbench_icon.svg +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Reporting_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Reporting_workbench_icon.svg deleted file mode 100644 index d9a0fdd1ac..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Reporting_workbench_icon.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Rocket_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Rocket_workbench_icon.svg deleted file mode 100644 index 8e96d0b952..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Rocket_workbench_icon.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Ship_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Ship_workbench_icon.svg deleted file mode 100644 index 60fd9d3bf0..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Ship_workbench_icon.svg +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [triplus] - - - ShipWorkbench - 2016-02-26 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Ship/resources/icons/ShipWorkbench.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [agryson] Alexander Gryson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/Silk_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/Silk_workbench_icon.svg deleted file mode 100644 index 7885882baf..0000000000 --- a/src/Mod/AddonManager/Resources/icons/Silk_workbench_icon.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/TaackPLM_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/TaackPLM_workbench_icon.svg deleted file mode 100644 index 39e96c180d..0000000000 --- a/src/Mod/AddonManager/Resources/icons/TaackPLM_workbench_icon.svg +++ /dev/null @@ -1,40 +0,0 @@ - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/ThreadProfile_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/ThreadProfile_workbench_icon.svg deleted file mode 100644 index c730b07e22..0000000000 --- a/src/Mod/AddonManager/Resources/icons/ThreadProfile_workbench_icon.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/WebTools_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/WebTools_workbench_icon.svg deleted file mode 100644 index dcc27e5f7e..0000000000 --- a/src/Mod/AddonManager/Resources/icons/WebTools_workbench_icon.svg +++ /dev/null @@ -1,277 +0,0 @@ - - - - - WebTool Addon Logo - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - WebTool Addon Logo - - - [bitacovir] - - - Part_Box - 2019-10-16 - https://forum.freecad.org/viewtopic.php?f=34&t=40130&p=341411#p341411 - - - FreeCAD - - - - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/cadquery_module_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/cadquery_module_workbench_icon.svg deleted file mode 100644 index c716c26200..0000000000 --- a/src/Mod/AddonManager/Resources/icons/cadquery_module_workbench_icon.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/compact_view.svg b/src/Mod/AddonManager/Resources/icons/compact_view.svg deleted file mode 100644 index 93ad359ef6..0000000000 --- a/src/Mod/AddonManager/Resources/icons/compact_view.svg +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/composite_view.svg b/src/Mod/AddonManager/Resources/icons/composite_view.svg deleted file mode 100644 index 10a62d0a9b..0000000000 --- a/src/Mod/AddonManager/Resources/icons/composite_view.svg +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/dodo_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/dodo_workbench_icon.svg deleted file mode 100644 index fff4d48dce..0000000000 --- a/src/Mod/AddonManager/Resources/icons/dodo_workbench_icon.svg +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/expanded_view.svg b/src/Mod/AddonManager/Resources/icons/expanded_view.svg deleted file mode 100644 index 40c94243a0..0000000000 --- a/src/Mod/AddonManager/Resources/icons/expanded_view.svg +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/fasteners_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/fasteners_workbench_icon.svg deleted file mode 100644 index 8710de1d64..0000000000 --- a/src/Mod/AddonManager/Resources/icons/fasteners_workbench_icon.svg +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/flamingo_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/flamingo_workbench_icon.svg deleted file mode 100644 index a709f5b55f..0000000000 --- a/src/Mod/AddonManager/Resources/icons/flamingo_workbench_icon.svg +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/kicadStepUpMod_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/kicadStepUpMod_workbench_icon.svg deleted file mode 100644 index 3b9262de23..0000000000 --- a/src/Mod/AddonManager/Resources/icons/kicadStepUpMod_workbench_icon.svg +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/lattice2_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/lattice2_workbench_icon.svg deleted file mode 100644 index afc3f68588..0000000000 --- a/src/Mod/AddonManager/Resources/icons/lattice2_workbench_icon.svg +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/preferences-addon_manager.svg b/src/Mod/AddonManager/Resources/icons/preferences-addon_manager.svg deleted file mode 100644 index bc1330a0d7..0000000000 --- a/src/Mod/AddonManager/Resources/icons/preferences-addon_manager.svg +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/pyrate_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/pyrate_workbench_icon.svg deleted file mode 100644 index 3652724320..0000000000 --- a/src/Mod/AddonManager/Resources/icons/pyrate_workbench_icon.svg +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/sheetmetal_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/sheetmetal_workbench_icon.svg deleted file mode 100644 index ebb90f1bdd..0000000000 --- a/src/Mod/AddonManager/Resources/icons/sheetmetal_workbench_icon.svg +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg - - - FreeCAD LGPL2+ - - - 2023-12-19 - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/slic3r-tools_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/slic3r-tools_workbench_icon.svg deleted file mode 100644 index fe806c21c9..0000000000 --- a/src/Mod/AddonManager/Resources/icons/slic3r-tools_workbench_icon.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/sort_ascending.svg b/src/Mod/AddonManager/Resources/icons/sort_ascending.svg deleted file mode 100644 index c7d42ad5cb..0000000000 --- a/src/Mod/AddonManager/Resources/icons/sort_ascending.svg +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/sort_descending.svg b/src/Mod/AddonManager/Resources/icons/sort_descending.svg deleted file mode 100644 index 08566e8d87..0000000000 --- a/src/Mod/AddonManager/Resources/icons/sort_descending.svg +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - [maxwxyz] - - - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - FreeCAD/src/ - - - FreeCAD LGPL2+ - - - 2024 - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/timber_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/timber_workbench_icon.svg deleted file mode 100644 index 61dfbf8d4b..0000000000 --- a/src/Mod/AddonManager/Resources/icons/timber_workbench_icon.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/icons/workfeature_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/workfeature_workbench_icon.svg deleted file mode 100644 index c3edfe078f..0000000000 --- a/src/Mod/AddonManager/Resources/icons/workfeature_workbench_icon.svg +++ /dev/null @@ -1,452 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - W - p - - diff --git a/src/Mod/AddonManager/Resources/icons/yaml-workspace_workbench_icon.svg b/src/Mod/AddonManager/Resources/icons/yaml-workspace_workbench_icon.svg deleted file mode 100644 index e8662f1427..0000000000 --- a/src/Mod/AddonManager/Resources/icons/yaml-workspace_workbench_icon.svg +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - [wmayer] - - - Part_Box - 2011-10-10 - https://www.freecad.org/wiki/index.php?title=Artwork - - - FreeCAD - - - Resources/icons/YAML_workbench_icon.svg - - - FreeCAD LGPL2+ - - - https://www.gnu.org/copyleft/lesser.html - - - [bitacovir] - - - - - - - - - - - - - - diff --git a/src/Mod/AddonManager/Resources/licenses/Apache-2.0.txt b/src/Mod/AddonManager/Resources/licenses/Apache-2.0.txt deleted file mode 100644 index d645695673..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/Apache-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/Mod/AddonManager/Resources/licenses/BSD-2-Clause.txt b/src/Mod/AddonManager/Resources/licenses/BSD-2-Clause.txt deleted file mode 100644 index b6e0e031a3..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/BSD-2-Clause.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright <%%YEAR%%> <%%COPYRIGHT HOLDER%%> - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions -and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of -conditions and the following disclaimer in the documentation and/or other materials provided with -the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/Mod/AddonManager/Resources/licenses/BSD-3-Clause.txt b/src/Mod/AddonManager/Resources/licenses/BSD-3-Clause.txt deleted file mode 100644 index fe112b08ea..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/BSD-3-Clause.txt +++ /dev/null @@ -1,23 +0,0 @@ -Copyright <%%YEAR%%> <%%COPYRIGHT HOLDER%%> - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions -and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of -conditions and the following disclaimer in the documentation and/or other materials provided with -the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to -endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/Mod/AddonManager/Resources/licenses/CC0-1.0.txt b/src/Mod/AddonManager/Resources/licenses/CC0-1.0.txt deleted file mode 100644 index ae39b2e3cd..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/CC0-1.0.txt +++ /dev/null @@ -1,97 +0,0 @@ -CC0 1.0 Universal - -CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF -THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS -INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS -DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES -RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and -Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") -of an original work of authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the purpose of -contributing to a commons of creative, cultural and scientific works ("Commons") that the public -can reliably and without fear of later claims of infringement build upon, modify, incorporate in -other works, reuse and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may contribute to the -Commons to promote the ideal of a free culture and the further production of creative, cultural -and scientific works, or to gain reputation or greater distribution for their Work in part through -the use and efforts of others. - -For these and/or other purposes and motivations, and without any expectation of additional -consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the -extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects -to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or -her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on -those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and -related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights -include, but are not limited to, the following: - -the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; -moral rights retained by the original author(s) and/or performer(s); -publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; -rights protecting against unfair competition in regards to a Work, subject to the limitations in -paragraph 4(a), below; -rights protecting the extraction, dissemination, use and reuse of data in a Work; -database rights (such as those arising under Directive 96/9/EC of the European Parliament and of -the Council of 11 March 1996 on the legal protection of databases, and under any national -implementation thereof, including any amended or successor version of such directive); and -other similar, equivalent or corresponding rights throughout the world based on applicable -law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, -Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, -and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as future claims and causes -of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided -by applicable law or treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the -Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's -heirs and successors, fully intending that such Waiver shall not be subject to revocation, -rescission, cancellation, termination, or any other legal or equitable action to disrupt the -quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of -Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be judged legally -invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum -extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, -non-transferable, non sublicensable, non exclusive, irrevocable and unconditional license to -exercise Affirmer's Copyright and Related Rights in the Work -(i) in all territories worldwide, -(ii) for the maximum duration provided by applicable law or treaty (including future time -extensions), -(iii) in any current or future medium and for any number of copies, and -(iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional -purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by -Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or -ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate -the remainder of the License, and in such case Affirmer hereby affirms that he or she will not -(i) exercise any of his or her remaining Copyright and Related Rights in the Work or -(ii) assert any associated claims and causes of action with respect to the Work, in either case -contrary to Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - -No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or -otherwise affected by this document. - -Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning -the Work, express, implied, statutory or otherwise, including without limitation warranties of -title, merchantability, fitness for a particular purpose, non infringement, or the absence of -latent or other defects, accuracy, or the present or absence of errors, whether or not -discoverable, all to the greatest extent permissible under applicable law. - -Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work -or any use thereof, including without limitation any person's Copyright and Related Rights in the -Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions -or other rights required for any use of the Work. - -Affirmer understands and acknowledges that Creative Commons is not a party to this document and has -no duty or obligation with respect to this CC0 or use of the Work. diff --git a/src/Mod/AddonManager/Resources/licenses/GPL-2.0-or-later.txt b/src/Mod/AddonManager/Resources/licenses/GPL-2.0-or-later.txt deleted file mode 100644 index 0503436feb..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/GPL-2.0-or-later.txt +++ /dev/null @@ -1,265 +0,0 @@ -GNU GENERAL PUBLIC LICENSE Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA - -Everyone is permitted to copy and distribute verbatim copies of this license document, but changing -it is not allowed. - -Preamble - -The licenses for most software are designed to take away your freedom to share and change it. By -contrast, the GNU General Public License is intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. This General Public License -applies to most of the Free Software Foundation's software and to any other program whose authors -commit to using it. (Some other Free Software Foundation software is covered by the GNU Library -General Public License instead.) You can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our General Public Licenses -are designed to make sure that you have the freedom to distribute copies of free software (and -charge for this service if you wish), that you receive source code or can get it if you want it, -that you can change the software or use pieces of it in new free programs; and that you know you can -do these things. - -To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or -to ask you to surrender the rights. These restrictions translate to certain responsibilities for you -if you distribute copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must give -the recipients all the rights that you have. You must make sure that they, too, receive or can get -the source code. And you must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) offer you this license -which gives you legal permission to copy, distribute and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that everyone understands that -there is no warranty for this free software. If the software is modified by someone else and passed -on, we want its recipients to know that what they have is not the original, so that any problems -introduced by others will not reflect on the original authors' reputations. - -Finally, any free program is threatened constantly by software patents. We wish to avoid the danger -that redistributors of a free program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any patent must be licensed for -everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice placed by the copyright -holder saying it may be distributed under the terms of this General Public License. The "Program", -below, refers to any such program or work, and a "work based on the Program" means either the -Program or any derivative work under copyright law: that is to say, a work containing the Program or -a portion of it, either verbatim or with modifications and/or translated into another language. -(Hereinafter, translation is included without limitation in the term "modification".) Each licensee -is addressed as "you". - -Activities other than copying, distribution and modification are not covered by this License; they -are outside its scope. The act of running the Program is not restricted, and the output from the -Program is covered only if its contents constitute a work based on the Program (independent of -having been made by running the Program). Whether that is true depends on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in -any medium, provided that you conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License -and to the absence of any warranty; and give any other recipients of the Program a copy of this -License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and you may at your option offer -warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based -on the Program, and copy and distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - -a) You must cause the modified files to carry prominent notices stating that you changed the files -and the date of any change. - -b) You must cause any work that you distribute or publish, that in whole or in part contains or is -derived from the Program or any part thereof, to be licensed as a whole at no charge to all third -parties under the terms of this License. - -c) If the modified program normally reads commands interactively when run, you must cause it, when -started running for such interactive use in the most ordinary way, to print or display an -announcement including an appropriate copyright notice and a notice that there is no warranty (or -else, saying that you provide a warranty) and that users may redistribute the program under these -conditions, and telling the user how to view a copy of this License. (Exception: if the Program -itself is interactive but does not normally print such an announcement, your work based on the -Program is not required to print an announcement.) These requirements apply to the modified work as -a whole. If identifiable sections of that work are not derived from the Program, and can be -reasonably considered independent and separate works in themselves, then this License, and its -terms, do not apply to those sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based on the Program, the -distribution of the whole must be on the terms of this License, whose permissions for other -licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest your rights to work written -entirely by you; rather, the intent is to exercise the right to control the distribution of -derivative or collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program with the Program (or with a -work based on the Program) on a volume of a storage or distribution medium does not bring the other -work under the scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code -or executable form under the terms of Sections 1 and 2 above provided that you also do one of the -following: - -a) Accompany it with the complete corresponding machine-readable source code, which must be -distributed under the terms of Sections 1 and 2 above on a medium customarily used for software -interchange; or, - -b) Accompany it with a written offer, valid for at least three years, to give any third party, for a -charge no more than your cost of physically performing source distribution, a complete -machine-readable copy of the corresponding source code, to be distributed under the terms of -Sections 1 and 2 above on a medium customarily used for software interchange; or, - -c) Accompany it with the information you received as to the offer to distribute corresponding source -code. (This alternative is allowed only for noncommercial distribution and only if you received the -program in object code or executable form with such an offer, in accord with Subsection b above.) -The source code for a work means the preferred form of the work for making modifications to it. For -an executable work, complete source code means all the source code for all modules it contains, plus -any associated interface definition files, plus the scripts used to control compilation and -installation of the executable. However, as a special exception, the source code distributed need -not include anything that is normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on which the executable runs, -unless that component itself accompanies the executable. - -If distribution of executable or object code is made by offering access to copy from a designated -place, then offering equivalent access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not compelled to copy the source -along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided -under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. However, parties who have -received copies, or rights, from you under this License will not have their licenses terminated so -long as such parties remain in full compliance. - -5. You are not required to accept this License, since you have not signed it. However, nothing else -grants you permission to modify or distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by modifying or distributing the -Program (or any work based on the Program), you indicate your acceptance of this License to do so, -and all its terms and conditions for copying, distributing or modifying the Program or works based -on it. - -6. Each time you redistribute the Program (or any work based on the Program), the recipient -automatically receives a license from the original licensor to copy, distribute or modify the -Program subject to these terms and conditions. You may not impose any further restrictions on the -recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance -by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent infringement or for any other -reason (not limited to patent issues), conditions are imposed on you (whether by court order, -agreement or otherwise) that contradict the conditions of this License, they do not excuse you from -the conditions of this License. If you cannot distribute so as to satisfy simultaneously your -obligations under this License and any other pertinent obligations, then as a consequence you may -not distribute the Program at all. For example, if a patent license would not permit royalty-free -redistribution of the Program by all those who receive copies directly or indirectly through you, -then the only way you could satisfy both it and this License would be to refrain entirely from -distribution of the Program. - -If any portion of this section is held invalid or unenforceable under any particular circumstance, -the balance of the section is intended to apply and the section as a whole is intended to apply in -other circumstances. - -It is not the purpose of this section to induce you to infringe any patents or other property right -claims or to contest validity of any such claims; this section has the sole purpose of protecting -the integrity of the free software distribution system, which is implemented by public license -practices. Many people have made generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that system; it is up to the -author/donor to decide if he or she is willing to distribute software through any other system and a -licensee cannot impose that choice. - -This section is intended to make thoroughly clear what is believed to be a consequence of the rest -of this License. - -8. If the distribution and/or use of the Program is restricted in certain countries either by -patents or by copyrighted interfaces, the original copyright holder who places the Program under -this License may add an explicit geographical distribution limitation excluding those countries, so -that distribution is permitted only in or among countries not thus excluded. In such case, this -License incorporates the limitation as if written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of the General Public -License from time to time. Such new versions will be similar in spirit to the present version, but -may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies a version number of -this License which applies to it and "any later version", you have the option of following the terms -and conditions either of that version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of this License, you may choose any -version ever published by the Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs whose distribution -conditions are different, write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing and reuse of software -generally. - -NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE -EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS -AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR -IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. -SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, -OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO -YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF -THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO -OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest possible use to the public, the -best way to achieve this is to make it free software which everyone can redistribute and change -under these terms. - -To do so, attach the following notices to the program. It is safest to attach them to the start of -each source file to most effectively convey the exclusion of warranty; and each file should have at -least the "copyright" line and a pointer to where the full notice is found. - -One line to give the program's name and a brief idea of what it does. Copyright (C) - -This program is free software; you can redistribute it and/or modify it under the terms of the GNU -General Public License as published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -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 -General Public License for more details. - -You should have received a copy of the GNU 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 -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this when it starts in an -interactive mode: - -Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO -WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it -under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' -should show the appropriate parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be mouse-clicks or menu -items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your school, if any, to sign a -"copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: - -Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes -passes at compilers) written by James Hacker. - -signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not -permit incorporating your program into proprietary programs. If your program is a subroutine -library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General Public License instead of this -License. diff --git a/src/Mod/AddonManager/Resources/licenses/GPL-3.0-or-later.txt b/src/Mod/AddonManager/Resources/licenses/GPL-3.0-or-later.txt deleted file mode 100644 index f288702d2f..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/GPL-3.0-or-later.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/src/Mod/AddonManager/Resources/licenses/LGPL-2.1-or-later.txt b/src/Mod/AddonManager/Resources/licenses/LGPL-2.1-or-later.txt deleted file mode 100644 index e5ab03e123..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/LGPL-2.1-or-later.txt +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/src/Mod/AddonManager/Resources/licenses/LGPL-3.0-or-later.txt b/src/Mod/AddonManager/Resources/licenses/LGPL-3.0-or-later.txt deleted file mode 100644 index 0a041280bd..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/LGPL-3.0-or-later.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/src/Mod/AddonManager/Resources/licenses/MIT.txt b/src/Mod/AddonManager/Resources/licenses/MIT.txt deleted file mode 100644 index 2b6d1ad269..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/MIT.txt +++ /dev/null @@ -1,16 +0,0 @@ -Copyright © <%%YEAR%%> <%%COPYRIGHT HOLDER%%> - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the “Softwareâ€), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES -OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/Mod/AddonManager/Resources/licenses/MPL-2.0.txt b/src/Mod/AddonManager/Resources/licenses/MPL-2.0.txt deleted file mode 100644 index 3585607237..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/MPL-2.0.txt +++ /dev/null @@ -1,258 +0,0 @@ -Mozilla Public License 2.0 (MPL-2.0) - -1. Definitions -1.1. “Contributor†-means each individual or legal entity that creates, contributes to the creation of, or owns Covered -Software. - -1.2. “Contributor Version†-means the combination of the Contributions of others (if any) used by a Contributor and that -particular Contributor’s Contribution. - -1.3. “Contribution†-means Covered Software of a particular Contributor. - -1.4. “Covered Software†-means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the -Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case -including portions thereof. - -1.5. “Incompatible With Secondary Licenses†-means that the initial Contributor has attached the notice described in Exhibit B to the Covered -Software; or -that the Covered Software was made available under the terms of version 1.1 or earlier of the -License, but not also under the terms of a Secondary License. - -1.6. “Executable Form†-means any form of the work other than Source Code Form. - -1.7. “Larger Work†-means a work that combines Covered Software with other material, in a separate file or files, that -is not Covered Software. - -1.8. “License†-means this document. - -1.9. “Licensable†-means having the right to grant, to the maximum extent possible, whether at the time of the initial -grant or subsequently, any and all of the rights conveyed by this License. - -1.10. “Modifications†-means any of the following: - -any file in Source Code Form that results from an addition to, deletion from, or modification of the -contents of Covered Software; or - -any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims†of a Contributor -means any patent claim(s), including without limitation, method, process, and apparatus claims, in -any patent Licensable by such Contributor that would be infringed, but for the grant of the License, -by the making, using, selling, offering for sale, having made, import, or transfer of either its -Contributions or its Contributor Version. - -1.12. “Secondary License†-means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, -Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those -licenses. - -1.13. “Source Code Form†-means the form of the work preferred for making modifications. - -1.14. “You†(or “Yourâ€) -means an individual or a legal entity exercising rights under this License. For legal entities, -“You†includes any entity that controls, is controlled by, or is under common control with You. For -purposes of this definition, “control†means (a) the power, direct or indirect, to cause the -direction or management of such entity, whether by contract or otherwise, or (b) ownership of more -than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. - -2. License Grants and Conditions -2.1. Grants -Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: - -under intellectual property rights (other than patent or trademark) Licensable by such Contributor -to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its -Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and - -under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and -otherwise transfer either its Contributions or its Contributor Version. - -2.2. Effective Date -The licenses granted in Section 2.1 with respect to any Contribution become effective for each -Contribution on the date the Contributor first distributes such Contribution. - -2.3. Limitations on Grant Scope -The licenses granted in this Section 2 are the only rights granted under this License. No additional -rights or licenses will be implied from the distribution or licensing of Covered Software under this -License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: - -for any code that a Contributor has removed from Covered Software; or - -for infringements caused by: (i) Your and any other third party’s modifications of Covered Software, -or (ii) the combination of its Contributions with other software (except as part of its Contributor -Version); or - -under Patent Claims infringed by Covered Software in the absence of its Contributions. - -This License does not grant any rights in the trademarks, service marks, or logos of any Contributor -(except as may be necessary to comply with the notice requirements in Section 3.4). - -2.4. Subsequent Licenses -No Contributor makes additional grants as a result of Your choice to distribute the Covered Software -under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary -License (if permitted under the terms of Section 3.3). - -2.5. Representation -Each Contributor represents that the Contributor believes its Contributions are its original -creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this -License. - -2.6. Fair Use -This License is not intended to limit any rights You have under applicable copyright doctrines of -fair use, fair dealing, or other equivalents. - -2.7. Conditions -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. - -3. Responsibilities -3.1. Distribution of Source Form -All distribution of Covered Software in Source Code Form, including any Modifications that You -create or to which You contribute, must be under the terms of this License. You must inform -recipients that the Source Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not attempt to alter or restrict -the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form -If You distribute Covered Software in Executable Form then: - -such Covered Software must also be made available in Source Code Form, as described in Section 3.1, -and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code -Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to -the recipient; and - -You may distribute such Executable Form under the terms of this License, or sublicense it under -different terms, provided that the license for the Executable Form does not attempt to limit or -alter the recipients’ rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work -You may create and distribute a Larger Work under terms of Your choice, provided that You also -comply with the requirements of this License for the Covered Software. If the Larger Work is a -combination of Covered Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this License permits You to -additionally distribute such Covered Software under the terms of such Secondary License(s), so that -the recipient of the Larger Work may, at their option, further distribute the Covered Software under -the terms of either this License or such Secondary License(s). - -3.4. Notices -You may not remove or alter the substance of any license notices (including copyright notices, -patent notices, disclaimers of warranty, or limitations of liability) contained within the Source -Code Form of the Covered Software, except that You may alter any license notices to the extent -required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms -You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability -obligations to one or more recipients of Covered Software. However, You may do so only on Your own -behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such -warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree -to indemnify every Contributor for any liability incurred by such Contributor as a result of -warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of -warranty and limitations of liability specific to any jurisdiction. - -4. Inability to Comply Due to Statute or Regulation -If it is impossible for You to comply with any of the terms of this License with respect to some or -all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply -with the terms of this License to the maximum extent possible; and (b) describe the limitations and -the code they affect. Such description must be placed in a text file included with all distributions -of the Covered Software under this License. Except to the extent prohibited by statute or -regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be -able to understand it. - -5. Termination -5.1. The rights granted under this License will terminate automatically if You fail to comply with -any of its terms. However, if You become compliant, then the rights granted under this License from -a particular Contributor are reinstated (a) provisionally, unless and until such Contributor -explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor -fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an -ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this -is the first time You have received notice of non-compliance with this License from such -Contributor, and You become compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent infringement claim -(excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a -Contributor Version directly or indirectly infringes any patent, then the rights granted to You by -any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements -(excluding distributors and resellers) which have been validly granted by You or Your distributors -under this License prior to termination shall survive termination. - -6. Disclaimer of Warranty -Covered Software is provided under this License on an “as is†basis, without warranty of any kind, -either expressed, implied, or statutory, including, without limitation, warranties that the Covered -Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The -entire risk as to the quality and performance of the Covered Software is with You. Should any -Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any -necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential -part of this License. No use of any Covered Software is authorized under this License except under -this disclaimer. - -7. Limitation of Liability -Under no circumstances and under no legal theory, whether tort (including negligence), contract, or -otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be -liable to You for any direct, indirect, special, incidental, or consequential damages of any -character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, -computer failure or malfunction, or any and all other commercial damages or losses, even if such -party shall have been informed of the possibility of such damages. This limitation of liability -shall not apply to liability for death or personal injury resulting from such party’s negligence to -the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion -or limitation of incidental or consequential damages, so this exclusion and limitation may not apply -to You. - -8. Litigation -Any litigation relating to this License may be brought only in the courts of a jurisdiction where -the defendant maintains its principal place of business and such litigation shall be governed by -laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this -Section shall prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous -This License represents the complete agreement concerning the subject matter hereof. If any -provision of this License is held to be unenforceable, such provision shall be reformed only to the -extent necessary to make it enforceable. Any law or regulation which provides that the language of a -contract shall be construed against the drafter shall not be used to construe this License against a -Contributor. - -10. Versions of the License -10.1. New Versions -Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the -license steward has the right to modify or publish new versions of this License. Each version will -be given a distinguishing version number. - -10.2. Effect of New Versions -You may distribute the Covered Software under the terms of the version of the License under which -You originally received the Covered Software, or under the terms of any subsequent version published -by the license steward. - -10.3. Modified Versions -If you create software not governed by this License, and you want to create a new license for such -software, you may create and use a modified version of this License if you rename the license and -remove any references to the name of the license steward (except to note that such modified license -differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses -If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the -terms of this version of the License, the notice described in Exhibit B of this License must be -attached. - -Exhibit A - Source Code Form License Notice -This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -If it is not possible or desirable to put the notice in a particular file, then You may include the -notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be -likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses†Notice -This Source Code Form is “Incompatible With Secondary Licensesâ€, as defined by the Mozilla Public -License, v. 2.0. diff --git a/src/Mod/AddonManager/Resources/licenses/spdx.json b/src/Mod/AddonManager/Resources/licenses/spdx.json deleted file mode 100644 index a66972e749..0000000000 --- a/src/Mod/AddonManager/Resources/licenses/spdx.json +++ /dev/null @@ -1,7835 +0,0 @@ -{ - "licenseListVersion": "83c9f84", - "licenses": [ - { - "reference": "https://spdx.org/licenses/0BSD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/0BSD.json", - "referenceNumber": 530, - "name": "BSD Zero Clause License", - "licenseId": "0BSD", - "seeAlso": [ - "http://landley.net/toybox/license.html", - "https://opensource.org/licenses/0BSD" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/AAL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AAL.json", - "referenceNumber": 121, - "name": "Attribution Assurance License", - "licenseId": "AAL", - "seeAlso": [ - "https://opensource.org/licenses/attribution" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Abstyles.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Abstyles.json", - "referenceNumber": 499, - "name": "Abstyles License", - "licenseId": "Abstyles", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Abstyles" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AdaCore-doc.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AdaCore-doc.json", - "referenceNumber": 103, - "name": "AdaCore Doc License", - "licenseId": "AdaCore-doc", - "seeAlso": [ - "https://github.com/AdaCore/xmlada/blob/master/docs/index.rst", - "https://github.com/AdaCore/gnatcoll-core/blob/master/docs/index.rst", - "https://github.com/AdaCore/gnatcoll-db/blob/master/docs/index.rst" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Adobe-2006.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Adobe-2006.json", - "referenceNumber": 471, - "name": "Adobe Systems Incorporated Source Code License Agreement", - "licenseId": "Adobe-2006", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AdobeLicense" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Adobe-Display-PostScript.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Adobe-Display-PostScript.json", - "referenceNumber": 556, - "name": "Adobe Display PostScript License", - "licenseId": "Adobe-Display-PostScript", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type\u003dheads#L752" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Adobe-Glyph.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Adobe-Glyph.json", - "referenceNumber": 585, - "name": "Adobe Glyph List License", - "licenseId": "Adobe-Glyph", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Adobe-Utopia.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Adobe-Utopia.json", - "referenceNumber": 89, - "name": "Adobe Utopia Font License", - "licenseId": "Adobe-Utopia", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/font/adobe-utopia-100dpi/-/blob/master/COPYING?ref_type\u003dheads" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ADSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ADSL.json", - "referenceNumber": 535, - "name": "Amazon Digital Services License", - "licenseId": "ADSL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AFL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AFL-1.1.json", - "referenceNumber": 174, - "name": "Academic Free License v1.1", - "licenseId": "AFL-1.1", - "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-1.1.txt", - "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AFL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AFL-1.2.json", - "referenceNumber": 606, - "name": "Academic Free License v1.2", - "licenseId": "AFL-1.2", - "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-1.2.txt", - "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AFL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AFL-2.0.json", - "referenceNumber": 219, - "name": "Academic Free License v2.0", - "licenseId": "AFL-2.0", - "seeAlso": [ - "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AFL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AFL-2.1.json", - "referenceNumber": 426, - "name": "Academic Free License v2.1", - "licenseId": "AFL-2.1", - "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-2.1.txt" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AFL-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AFL-3.0.json", - "referenceNumber": 37, - "name": "Academic Free License v3.0", - "licenseId": "AFL-3.0", - "seeAlso": [ - "http://www.rosenlaw.com/AFL3.0.htm", - "https://opensource.org/licenses/afl-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Afmparse.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Afmparse.json", - "referenceNumber": 227, - "name": "Afmparse License", - "licenseId": "Afmparse", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Afmparse" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AGPL-1.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/AGPL-1.0.json", - "referenceNumber": 327, - "name": "Affero General Public License v1.0", - "licenseId": "AGPL-1.0", - "seeAlso": [ - "http://www.affero.org/oagpl.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AGPL-1.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AGPL-1.0-only.json", - "referenceNumber": 75, - "name": "Affero General Public License v1.0 only", - "licenseId": "AGPL-1.0-only", - "seeAlso": [ - "http://www.affero.org/oagpl.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AGPL-1.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AGPL-1.0-or-later.json", - "referenceNumber": 421, - "name": "Affero General Public License v1.0 or later", - "licenseId": "AGPL-1.0-or-later", - "seeAlso": [ - "http://www.affero.org/oagpl.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AGPL-3.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/AGPL-3.0.json", - "referenceNumber": 500, - "name": "GNU Affero General Public License v3.0", - "licenseId": "AGPL-3.0", - "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AGPL-3.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AGPL-3.0-only.json", - "referenceNumber": 291, - "name": "GNU Affero General Public License v3.0 only", - "licenseId": "AGPL-3.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/AGPL-3.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AGPL-3.0-or-later.json", - "referenceNumber": 398, - "name": "GNU Affero General Public License v3.0 or later", - "licenseId": "AGPL-3.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Aladdin.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Aladdin.json", - "referenceNumber": 441, - "name": "Aladdin Free Public License", - "licenseId": "Aladdin", - "seeAlso": [ - "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/AMDPLPA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AMDPLPA.json", - "referenceNumber": 423, - "name": "AMD\u0027s plpa_map.c License", - "licenseId": "AMDPLPA", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AML.json", - "referenceNumber": 17, - "name": "Apple MIT License", - "licenseId": "AML", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AML-glslang.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AML-glslang.json", - "referenceNumber": 254, - "name": "AML glslang variant License", - "licenseId": "AML-glslang", - "seeAlso": [ - "https://github.com/KhronosGroup/glslang/blob/main/LICENSE.txt#L949", - "https://docs.omniverse.nvidia.com/install-guide/latest/common/licenses.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/AMPAS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/AMPAS.json", - "referenceNumber": 487, - "name": "Academy of Motion Picture Arts and Sciences BSD", - "licenseId": "AMPAS", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ANTLR-PD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ANTLR-PD.json", - "referenceNumber": 129, - "name": "ANTLR Software Rights Notice", - "licenseId": "ANTLR-PD", - "seeAlso": [ - "http://www.antlr2.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ANTLR-PD-fallback.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ANTLR-PD-fallback.json", - "referenceNumber": 171, - "name": "ANTLR Software Rights Notice with license fallback", - "licenseId": "ANTLR-PD-fallback", - "seeAlso": [ - "http://www.antlr2.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Apache-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Apache-1.0.json", - "referenceNumber": 97, - "name": "Apache License 1.0", - "licenseId": "Apache-1.0", - "seeAlso": [ - "http://www.apache.org/licenses/LICENSE-1.0" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Apache-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Apache-1.1.json", - "referenceNumber": 442, - "name": "Apache License 1.1", - "licenseId": "Apache-1.1", - "seeAlso": [ - "http://apache.org/licenses/LICENSE-1.1", - "https://opensource.org/licenses/Apache-1.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Apache-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Apache-2.0.json", - "referenceNumber": 300, - "name": "Apache License 2.0", - "licenseId": "Apache-2.0", - "seeAlso": [ - "https://www.apache.org/licenses/LICENSE-2.0", - "https://opensource.org/licenses/Apache-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/APAFML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/APAFML.json", - "referenceNumber": 513, - "name": "Adobe Postscript AFM License", - "licenseId": "APAFML", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/APL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/APL-1.0.json", - "referenceNumber": 605, - "name": "Adaptive Public License 1.0", - "licenseId": "APL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/APL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/App-s2p.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/App-s2p.json", - "referenceNumber": 336, - "name": "App::s2p License", - "licenseId": "App-s2p", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/App-s2p" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/APSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/APSL-1.0.json", - "referenceNumber": 164, - "name": "Apple Public Source License 1.0", - "licenseId": "APSL-1.0", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0" - ], - "isOsiApproved": true, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/APSL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/APSL-1.1.json", - "referenceNumber": 154, - "name": "Apple Public Source License 1.1", - "licenseId": "APSL-1.1", - "seeAlso": [ - "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/APSL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/APSL-1.2.json", - "referenceNumber": 163, - "name": "Apple Public Source License 1.2", - "licenseId": "APSL-1.2", - "seeAlso": [ - "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/APSL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/APSL-2.0.json", - "referenceNumber": 59, - "name": "Apple Public Source License 2.0", - "licenseId": "APSL-2.0", - "seeAlso": [ - "http://www.opensource.apple.com/license/apsl/" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Arphic-1999.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Arphic-1999.json", - "referenceNumber": 446, - "name": "Arphic Public License", - "licenseId": "Arphic-1999", - "seeAlso": [ - "http://ftp.gnu.org/gnu/non-gnu/chinese-fonts-truetype/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Artistic-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Artistic-1.0.json", - "referenceNumber": 108, - "name": "Artistic License 1.0", - "licenseId": "Artistic-1.0", - "seeAlso": [ - "https://opensource.org/licenses/Artistic-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/Artistic-1.0-cl8.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Artistic-1.0-cl8.json", - "referenceNumber": 405, - "name": "Artistic License 1.0 w/clause 8", - "licenseId": "Artistic-1.0-cl8", - "seeAlso": [ - "https://opensource.org/licenses/Artistic-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Artistic-1.0-Perl.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Artistic-1.0-Perl.json", - "referenceNumber": 558, - "name": "Artistic License 1.0 (Perl)", - "licenseId": "Artistic-1.0-Perl", - "seeAlso": [ - "http://dev.perl.org/licenses/artistic.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Artistic-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Artistic-2.0.json", - "referenceNumber": 152, - "name": "Artistic License 2.0", - "licenseId": "Artistic-2.0", - "seeAlso": [ - "http://www.perlfoundation.org/artistic_license_2_0", - "https://www.perlfoundation.org/artistic-license-20.html", - "https://opensource.org/licenses/artistic-license-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ASWF-Digital-Assets-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ASWF-Digital-Assets-1.0.json", - "referenceNumber": 217, - "name": "ASWF Digital Assets License version 1.0", - "licenseId": "ASWF-Digital-Assets-1.0", - "seeAlso": [ - "https://github.com/AcademySoftwareFoundation/foundation/blob/main/digital_assets/aswf_digital_assets_license_v1.0.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ASWF-Digital-Assets-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ASWF-Digital-Assets-1.1.json", - "referenceNumber": 145, - "name": "ASWF Digital Assets License 1.1", - "licenseId": "ASWF-Digital-Assets-1.1", - "seeAlso": [ - "https://github.com/AcademySoftwareFoundation/foundation/blob/main/digital_assets/aswf_digital_assets_license_v1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Baekmuk.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Baekmuk.json", - "referenceNumber": 524, - "name": "Baekmuk License", - "licenseId": "Baekmuk", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:Baekmuk?rd\u003dLicensing/Baekmuk" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Bahyph.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Bahyph.json", - "referenceNumber": 247, - "name": "Bahyph License", - "licenseId": "Bahyph", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Bahyph" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Barr.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Barr.json", - "referenceNumber": 465, - "name": "Barr License", - "licenseId": "Barr", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Barr" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Beerware.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Beerware.json", - "referenceNumber": 432, - "name": "Beerware License", - "licenseId": "Beerware", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Beerware", - "https://people.freebsd.org/~phk/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Bitstream-Charter.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Bitstream-Charter.json", - "referenceNumber": 369, - "name": "Bitstream Charter Font License", - "licenseId": "Bitstream-Charter", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Charter#License_Text", - "https://raw.githubusercontent.com/blackhole89/notekit/master/data/fonts/Charter%20license.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Bitstream-Vera.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Bitstream-Vera.json", - "referenceNumber": 245, - "name": "Bitstream Vera Font License", - "licenseId": "Bitstream-Vera", - "seeAlso": [ - "https://web.archive.org/web/20080207013128/http://www.gnome.org/fonts/", - "https://docubrain.com/sites/default/files/licenses/bitstream-vera.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BitTorrent-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BitTorrent-1.0.json", - "referenceNumber": 425, - "name": "BitTorrent Open Source License v1.0", - "licenseId": "BitTorrent-1.0", - "seeAlso": [ - "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BitTorrent-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BitTorrent-1.1.json", - "referenceNumber": 315, - "name": "BitTorrent Open Source License v1.1", - "licenseId": "BitTorrent-1.1", - "seeAlso": [ - "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/blessing.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/blessing.json", - "referenceNumber": 545, - "name": "SQLite Blessing", - "licenseId": "blessing", - "seeAlso": [ - "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln\u003d4-9", - "https://sqlite.org/src/artifact/df5091916dbb40e6" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BlueOak-1.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BlueOak-1.0.0.json", - "referenceNumber": 274, - "name": "Blue Oak Model License 1.0.0", - "licenseId": "BlueOak-1.0.0", - "seeAlso": [ - "https://blueoakcouncil.org/license/1.0.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Boehm-GC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Boehm-GC.json", - "referenceNumber": 458, - "name": "Boehm-Demers-Weiser GC License", - "licenseId": "Boehm-GC", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:MIT#Another_Minimal_variant_(found_in_libatomic_ops)", - "https://github.com/uim/libgcroots/blob/master/COPYING", - "https://github.com/ivmai/libatomic_ops/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Borceux.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Borceux.json", - "referenceNumber": 18, - "name": "Borceux license", - "licenseId": "Borceux", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Borceux" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Brian-Gladman-3-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Brian-Gladman-3-Clause.json", - "referenceNumber": 511, - "name": "Brian Gladman 3-Clause License", - "licenseId": "Brian-Gladman-3-Clause", - "seeAlso": [ - "https://github.com/SWI-Prolog/packages-clib/blob/master/sha1/brg_endian.h" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-1-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-1-Clause.json", - "referenceNumber": 564, - "name": "BSD 1-Clause License", - "licenseId": "BSD-1-Clause", - "seeAlso": [ - "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/BSD-2-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause.json", - "referenceNumber": 13, - "name": "BSD 2-Clause \"Simplified\" License", - "licenseId": "BSD-2-Clause", - "seeAlso": [ - "https://opensource.org/licenses/BSD-2-Clause" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.json", - "referenceNumber": 262, - "name": "BSD 2-Clause FreeBSD License", - "licenseId": "BSD-2-Clause-FreeBSD", - "seeAlso": [ - "http://www.freebsd.org/copyright/freebsd-license.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.json", - "referenceNumber": 476, - "name": "BSD 2-Clause NetBSD License", - "licenseId": "BSD-2-Clause-NetBSD", - "seeAlso": [ - "http://www.netbsd.org/about/redistribution.html#default" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BSD-2-Clause-Patent.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Patent.json", - "referenceNumber": 363, - "name": "BSD-2-Clause Plus Patent License", - "licenseId": "BSD-2-Clause-Patent", - "seeAlso": [ - "https://opensource.org/licenses/BSDplusPatent" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/BSD-2-Clause-Views.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Views.json", - "referenceNumber": 82, - "name": "BSD 2-Clause with views sentence", - "licenseId": "BSD-2-Clause-Views", - "seeAlso": [ - "http://www.freebsd.org/copyright/freebsd-license.html", - "https://people.freebsd.org/~ivoras/wine/patch-wine-nvidia.sh", - "https://github.com/protegeproject/protege/blob/master/license.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause.json", - "referenceNumber": 355, - "name": "BSD 3-Clause \"New\" or \"Revised\" License", - "licenseId": "BSD-3-Clause", - "seeAlso": [ - "https://opensource.org/licenses/BSD-3-Clause", - "https://www.eclipse.org/org/documents/edl-v10.php" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-acpica.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-acpica.json", - "referenceNumber": 506, - "name": "BSD 3-Clause acpica variant", - "licenseId": "BSD-3-Clause-acpica", - "seeAlso": [ - "https://github.com/acpica/acpica/blob/master/source/common/acfileio.c#L119" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Attribution.json", - "referenceNumber": 387, - "name": "BSD with attribution", - "licenseId": "BSD-3-Clause-Attribution", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-Clear.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Clear.json", - "referenceNumber": 102, - "name": "BSD 3-Clause Clear License", - "licenseId": "BSD-3-Clause-Clear", - "seeAlso": [ - "http://labs.metacarta.com/license-explanation.html#license" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-flex.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-flex.json", - "referenceNumber": 188, - "name": "BSD 3-Clause Flex variant", - "licenseId": "BSD-3-Clause-flex", - "seeAlso": [ - "https://github.com/westes/flex/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-HP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-HP.json", - "referenceNumber": 609, - "name": "Hewlett-Packard BSD variant license", - "licenseId": "BSD-3-Clause-HP", - "seeAlso": [ - "https://github.com/zdohnal/hplip/blob/master/COPYING#L939" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-LBNL.json", - "referenceNumber": 303, - "name": "Lawrence Berkeley National Labs BSD variant license", - "licenseId": "BSD-3-Clause-LBNL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/LBNLBSD" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-Modification.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Modification.json", - "referenceNumber": 475, - "name": "BSD 3-Clause Modification", - "licenseId": "BSD-3-Clause-Modification", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:BSD#Modification_Variant" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.json", - "referenceNumber": 308, - "name": "BSD 3-Clause No Military License", - "licenseId": "BSD-3-Clause-No-Military-License", - "seeAlso": [ - "https://gitlab.syncad.com/hive/dhive/-/blob/master/LICENSE", - "https://github.com/greymass/swift-eosio/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json", - "referenceNumber": 541, - "name": "BSD 3-Clause No Nuclear License", - "licenseId": "BSD-3-Clause-No-Nuclear-License", - "seeAlso": [ - "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json", - "referenceNumber": 486, - "name": "BSD 3-Clause No Nuclear License 2014", - "licenseId": "BSD-3-Clause-No-Nuclear-License-2014", - "seeAlso": [ - "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json", - "referenceNumber": 559, - "name": "BSD 3-Clause No Nuclear Warranty", - "licenseId": "BSD-3-Clause-No-Nuclear-Warranty", - "seeAlso": [ - "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.json", - "referenceNumber": 46, - "name": "BSD 3-Clause Open MPI variant", - "licenseId": "BSD-3-Clause-Open-MPI", - "seeAlso": [ - "https://www.open-mpi.org/community/license.php", - "http://www.netlib.org/lapack/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-3-Clause-Sun.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Sun.json", - "referenceNumber": 228, - "name": "BSD 3-Clause Sun Microsystems", - "licenseId": "BSD-3-Clause-Sun", - "seeAlso": [ - "https://github.com/xmlark/msv/blob/b9316e2f2270bc1606952ea4939ec87fbba157f3/xsdlib/src/main/java/com/sun/msv/datatype/regexp/InternalImpl.java" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-4-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause.json", - "referenceNumber": 619, - "name": "BSD 4-Clause \"Original\" or \"Old\" License", - "licenseId": "BSD-4-Clause", - "seeAlso": [ - "http://directory.fsf.org/wiki/License:BSD_4Clause" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BSD-4-Clause-Shortened.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause-Shortened.json", - "referenceNumber": 194, - "name": "BSD 4 Clause Shortened", - "licenseId": "BSD-4-Clause-Shortened", - "seeAlso": [ - "https://metadata.ftp-master.debian.org/changelogs//main/a/arpwatch/arpwatch_2.1a15-7_copyright" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-4-Clause-UC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause-UC.json", - "referenceNumber": 332, - "name": "BSD-4-Clause (University of California-Specific)", - "licenseId": "BSD-4-Clause-UC", - "seeAlso": [ - "http://www.freebsd.org/copyright/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-4.3RENO.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-4.3RENO.json", - "referenceNumber": 85, - "name": "BSD 4.3 RENO License", - "licenseId": "BSD-4.3RENO", - "seeAlso": [ - "https://sourceware.org/git/?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dlibiberty/strcasecmp.c;h\u003d131d81c2ce7881fa48c363dc5bf5fb302c61ce0b;hb\u003dHEAD", - "https://git.openldap.org/openldap/openldap/-/blob/master/COPYRIGHT#L55-63" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-4.3TAHOE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-4.3TAHOE.json", - "referenceNumber": 354, - "name": "BSD 4.3 TAHOE License", - "licenseId": "BSD-4.3TAHOE", - "seeAlso": [ - "https://github.com/389ds/389-ds-base/blob/main/ldap/include/sysexits-compat.h#L15", - "https://git.savannah.gnu.org/cgit/indent.git/tree/doc/indent.texi?id\u003da74c6b4ee49397cf330b333da1042bffa60ed14f#n1788" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Advertising-Acknowledgement.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Advertising-Acknowledgement.json", - "referenceNumber": 200, - "name": "BSD Advertising Acknowledgement License", - "licenseId": "BSD-Advertising-Acknowledgement", - "seeAlso": [ - "https://github.com/python-excel/xlrd/blob/master/LICENSE#L33" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Attribution-HPND-disclaimer.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Attribution-HPND-disclaimer.json", - "referenceNumber": 427, - "name": "BSD with Attribution and HPND disclaimer", - "licenseId": "BSD-Attribution-HPND-disclaimer", - "seeAlso": [ - "https://github.com/cyrusimap/cyrus-sasl/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Inferno-Nettverk.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Inferno-Nettverk.json", - "referenceNumber": 151, - "name": "BSD-Inferno-Nettverk", - "licenseId": "BSD-Inferno-Nettverk", - "seeAlso": [ - "https://www.inet.no/dante/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Protection.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Protection.json", - "referenceNumber": 592, - "name": "BSD Protection License", - "licenseId": "BSD-Protection", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Source-beginning-file.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Source-beginning-file.json", - "referenceNumber": 137, - "name": "BSD Source Code Attribution - beginning of file variant", - "licenseId": "BSD-Source-beginning-file", - "seeAlso": [ - "https://github.com/lattera/freebsd/blob/master/sys/cam/cam.c#L4" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Source-Code.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Source-Code.json", - "referenceNumber": 433, - "name": "BSD Source Code Attribution", - "licenseId": "BSD-Source-Code", - "seeAlso": [ - "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Systemics.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Systemics.json", - "referenceNumber": 325, - "name": "Systemics BSD variant license", - "licenseId": "BSD-Systemics", - "seeAlso": [ - "https://metacpan.org/release/DPARIS/Crypt-DES-2.07/source/COPYRIGHT" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSD-Systemics-W3Works.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSD-Systemics-W3Works.json", - "referenceNumber": 340, - "name": "Systemics W3Works BSD variant license", - "licenseId": "BSD-Systemics-W3Works", - "seeAlso": [ - "https://metacpan.org/release/DPARIS/Crypt-Blowfish-2.14/source/COPYRIGHT#L7" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/BSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BSL-1.0.json", - "referenceNumber": 73, - "name": "Boost Software License 1.0", - "licenseId": "BSL-1.0", - "seeAlso": [ - "http://www.boost.org/LICENSE_1_0.txt", - "https://opensource.org/licenses/BSL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/BUSL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/BUSL-1.1.json", - "referenceNumber": 525, - "name": "Business Source License 1.1", - "licenseId": "BUSL-1.1", - "seeAlso": [ - "https://mariadb.com/bsl11/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/bzip2-1.0.5.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/bzip2-1.0.5.json", - "referenceNumber": 438, - "name": "bzip2 and libbzip2 License v1.0.5", - "licenseId": "bzip2-1.0.5", - "seeAlso": [ - "https://sourceware.org/bzip2/1.0.5/bzip2-manual-1.0.5.html", - "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/bzip2-1.0.6.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/bzip2-1.0.6.json", - "referenceNumber": 252, - "name": "bzip2 and libbzip2 License v1.0.6", - "licenseId": "bzip2-1.0.6", - "seeAlso": [ - "https://sourceware.org/git/?p\u003dbzip2.git;a\u003dblob;f\u003dLICENSE;hb\u003dbzip2-1.0.6", - "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/C-UDA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/C-UDA-1.0.json", - "referenceNumber": 472, - "name": "Computational Use of Data Agreement v1.0", - "licenseId": "C-UDA-1.0", - "seeAlso": [ - "https://github.com/microsoft/Computational-Use-of-Data-Agreement/blob/master/C-UDA-1.0.md", - "https://cdla.dev/computational-use-of-data-agreement-v1-0/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CAL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CAL-1.0.json", - "referenceNumber": 618, - "name": "Cryptographic Autonomy License 1.0", - "licenseId": "CAL-1.0", - "seeAlso": [ - "http://cryptographicautonomylicense.com/license-text.html", - "https://opensource.org/licenses/CAL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.json", - "referenceNumber": 384, - "name": "Cryptographic Autonomy License 1.0 (Combined Work Exception)", - "licenseId": "CAL-1.0-Combined-Work-Exception", - "seeAlso": [ - "http://cryptographicautonomylicense.com/license-text.html", - "https://opensource.org/licenses/CAL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Caldera.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Caldera.json", - "referenceNumber": 319, - "name": "Caldera License", - "licenseId": "Caldera", - "seeAlso": [ - "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Caldera-no-preamble.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Caldera-no-preamble.json", - "referenceNumber": 51, - "name": "Caldera License (without preamble)", - "licenseId": "Caldera-no-preamble", - "seeAlso": [ - "https://github.com/apache/apr/blob/trunk/LICENSE#L298C6-L298C29" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CATOSL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CATOSL-1.1.json", - "referenceNumber": 437, - "name": "Computer Associates Trusted Open Source License 1.1", - "licenseId": "CATOSL-1.1", - "seeAlso": [ - "https://opensource.org/licenses/CATOSL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CC-BY-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-1.0.json", - "referenceNumber": 226, - "name": "Creative Commons Attribution 1.0 Generic", - "licenseId": "CC-BY-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-2.0.json", - "referenceNumber": 259, - "name": "Creative Commons Attribution 2.0 Generic", - "licenseId": "CC-BY-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-2.5.json", - "referenceNumber": 165, - "name": "Creative Commons Attribution 2.5 Generic", - "licenseId": "CC-BY-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-2.5-AU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-2.5-AU.json", - "referenceNumber": 518, - "name": "Creative Commons Attribution 2.5 Australia", - "licenseId": "CC-BY-2.5-AU", - "seeAlso": [ - "https://creativecommons.org/licenses/by/2.5/au/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0.json", - "referenceNumber": 370, - "name": "Creative Commons Attribution 3.0 Unported", - "licenseId": "CC-BY-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0-AT.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-AT.json", - "referenceNumber": 101, - "name": "Creative Commons Attribution 3.0 Austria", - "licenseId": "CC-BY-3.0-AT", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/at/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0-AU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-AU.json", - "referenceNumber": 156, - "name": "Creative Commons Attribution 3.0 Australia", - "licenseId": "CC-BY-3.0-AU", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/au/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-DE.json", - "referenceNumber": 9, - "name": "Creative Commons Attribution 3.0 Germany", - "licenseId": "CC-BY-3.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0-IGO.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-IGO.json", - "referenceNumber": 211, - "name": "Creative Commons Attribution 3.0 IGO", - "licenseId": "CC-BY-3.0-IGO", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/igo/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0-NL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-NL.json", - "referenceNumber": 445, - "name": "Creative Commons Attribution 3.0 Netherlands", - "licenseId": "CC-BY-3.0-NL", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/nl/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-3.0-US.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-US.json", - "referenceNumber": 529, - "name": "Creative Commons Attribution 3.0 United States", - "licenseId": "CC-BY-3.0-US", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/us/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-4.0.json", - "referenceNumber": 40, - "name": "Creative Commons Attribution 4.0 International", - "licenseId": "CC-BY-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/4.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-1.0.json", - "referenceNumber": 94, - "name": "Creative Commons Attribution Non Commercial 1.0 Generic", - "licenseId": "CC-BY-NC-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/1.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-2.0.json", - "referenceNumber": 246, - "name": "Creative Commons Attribution Non Commercial 2.0 Generic", - "licenseId": "CC-BY-NC-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/2.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-2.5.json", - "referenceNumber": 498, - "name": "Creative Commons Attribution Non Commercial 2.5 Generic", - "licenseId": "CC-BY-NC-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/2.5/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-3.0.json", - "referenceNumber": 469, - "name": "Creative Commons Attribution Non Commercial 3.0 Unported", - "licenseId": "CC-BY-NC-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/3.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-3.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-3.0-DE.json", - "referenceNumber": 112, - "name": "Creative Commons Attribution Non Commercial 3.0 Germany", - "licenseId": "CC-BY-NC-3.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/3.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-4.0.json", - "referenceNumber": 70, - "name": "Creative Commons Attribution Non Commercial 4.0 International", - "licenseId": "CC-BY-NC-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/4.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.json", - "referenceNumber": 360, - "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic", - "licenseId": "CC-BY-NC-ND-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.json", - "referenceNumber": 395, - "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic", - "licenseId": "CC-BY-NC-ND-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.json", - "referenceNumber": 172, - "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic", - "licenseId": "CC-BY-NC-ND-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.json", - "referenceNumber": 358, - "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported", - "licenseId": "CC-BY-NC-ND-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.json", - "referenceNumber": 139, - "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Germany", - "licenseId": "CC-BY-NC-ND-3.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/3.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.json", - "referenceNumber": 253, - "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO", - "licenseId": "CC-BY-NC-ND-3.0-IGO", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/3.0/igo/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.json", - "referenceNumber": 8, - "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International", - "licenseId": "CC-BY-NC-ND-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.json", - "referenceNumber": 587, - "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic", - "licenseId": "CC-BY-NC-SA-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.json", - "referenceNumber": 181, - "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic", - "licenseId": "CC-BY-NC-SA-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-DE.json", - "referenceNumber": 474, - "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Germany", - "licenseId": "CC-BY-NC-SA-2.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.json", - "referenceNumber": 196, - "name": "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 France", - "licenseId": "CC-BY-NC-SA-2.0-FR", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.0/fr/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.json", - "referenceNumber": 420, - "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 England and Wales", - "licenseId": "CC-BY-NC-SA-2.0-UK", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.0/uk/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.json", - "referenceNumber": 521, - "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic", - "licenseId": "CC-BY-NC-SA-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.json", - "referenceNumber": 379, - "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported", - "licenseId": "CC-BY-NC-SA-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.json", - "referenceNumber": 278, - "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Germany", - "licenseId": "CC-BY-NC-SA-3.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.json", - "referenceNumber": 44, - "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 IGO", - "licenseId": "CC-BY-NC-SA-3.0-IGO", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/3.0/igo/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.json", - "referenceNumber": 195, - "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International", - "licenseId": "CC-BY-NC-SA-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-ND-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-1.0.json", - "referenceNumber": 331, - "name": "Creative Commons Attribution No Derivatives 1.0 Generic", - "licenseId": "CC-BY-ND-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/1.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-ND-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-2.0.json", - "referenceNumber": 610, - "name": "Creative Commons Attribution No Derivatives 2.0 Generic", - "licenseId": "CC-BY-ND-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/2.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-ND-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-2.5.json", - "referenceNumber": 91, - "name": "Creative Commons Attribution No Derivatives 2.5 Generic", - "licenseId": "CC-BY-ND-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/2.5/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-ND-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-3.0.json", - "referenceNumber": 485, - "name": "Creative Commons Attribution No Derivatives 3.0 Unported", - "licenseId": "CC-BY-ND-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/3.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-ND-3.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-3.0-DE.json", - "referenceNumber": 538, - "name": "Creative Commons Attribution No Derivatives 3.0 Germany", - "licenseId": "CC-BY-ND-3.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/3.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-ND-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-4.0.json", - "referenceNumber": 134, - "name": "Creative Commons Attribution No Derivatives 4.0 International", - "licenseId": "CC-BY-ND-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/4.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-1.0.json", - "referenceNumber": 526, - "name": "Creative Commons Attribution Share Alike 1.0 Generic", - "licenseId": "CC-BY-SA-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.0.json", - "referenceNumber": 30, - "name": "Creative Commons Attribution Share Alike 2.0 Generic", - "licenseId": "CC-BY-SA-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-2.0-UK.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.0-UK.json", - "referenceNumber": 222, - "name": "Creative Commons Attribution Share Alike 2.0 England and Wales", - "licenseId": "CC-BY-SA-2.0-UK", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.0/uk/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-2.1-JP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.1-JP.json", - "referenceNumber": 251, - "name": "Creative Commons Attribution Share Alike 2.1 Japan", - "licenseId": "CC-BY-SA-2.1-JP", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.5.json", - "referenceNumber": 47, - "name": "Creative Commons Attribution Share Alike 2.5 Generic", - "licenseId": "CC-BY-SA-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0.json", - "referenceNumber": 293, - "name": "Creative Commons Attribution Share Alike 3.0 Unported", - "licenseId": "CC-BY-SA-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-AT.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-AT.json", - "referenceNumber": 15, - "name": "Creative Commons Attribution Share Alike 3.0 Austria", - "licenseId": "CC-BY-SA-3.0-AT", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/3.0/at/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-DE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-DE.json", - "referenceNumber": 586, - "name": "Creative Commons Attribution Share Alike 3.0 Germany", - "licenseId": "CC-BY-SA-3.0-DE", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/3.0/de/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-IGO.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-IGO.json", - "referenceNumber": 109, - "name": "Creative Commons Attribution-ShareAlike 3.0 IGO", - "licenseId": "CC-BY-SA-3.0-IGO", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/3.0/igo/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC-BY-SA-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-4.0.json", - "referenceNumber": 86, - "name": "Creative Commons Attribution Share Alike 4.0 International", - "licenseId": "CC-BY-SA-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/4.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CC-PDDC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC-PDDC.json", - "referenceNumber": 573, - "name": "Creative Commons Public Domain Dedication and Certification", - "licenseId": "CC-PDDC", - "seeAlso": [ - "https://creativecommons.org/licenses/publicdomain/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CC0-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CC0-1.0.json", - "referenceNumber": 392, - "name": "Creative Commons Zero v1.0 Universal", - "licenseId": "CC0-1.0", - "seeAlso": [ - "https://creativecommons.org/publicdomain/zero/1.0/legalcode" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CDDL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CDDL-1.0.json", - "referenceNumber": 572, - "name": "Common Development and Distribution License 1.0", - "licenseId": "CDDL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/cddl1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CDDL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CDDL-1.1.json", - "referenceNumber": 367, - "name": "Common Development and Distribution License 1.1", - "licenseId": "CDDL-1.1", - "seeAlso": [ - "http://glassfish.java.net/public/CDDL+GPL_1_1.html", - "https://javaee.github.io/glassfish/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CDL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CDL-1.0.json", - "referenceNumber": 491, - "name": "Common Documentation License 1.0", - "licenseId": "CDL-1.0", - "seeAlso": [ - "http://www.opensource.apple.com/cdl/", - "https://fedoraproject.org/wiki/Licensing/Common_Documentation_License", - "https://www.gnu.org/licenses/license-list.html#ACDL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CDLA-Permissive-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CDLA-Permissive-1.0.json", - "referenceNumber": 159, - "name": "Community Data License Agreement Permissive 1.0", - "licenseId": "CDLA-Permissive-1.0", - "seeAlso": [ - "https://cdla.io/permissive-1-0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CDLA-Permissive-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CDLA-Permissive-2.0.json", - "referenceNumber": 175, - "name": "Community Data License Agreement Permissive 2.0", - "licenseId": "CDLA-Permissive-2.0", - "seeAlso": [ - "https://cdla.dev/permissive-2-0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CDLA-Sharing-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CDLA-Sharing-1.0.json", - "referenceNumber": 221, - "name": "Community Data License Agreement Sharing 1.0", - "licenseId": "CDLA-Sharing-1.0", - "seeAlso": [ - "https://cdla.io/sharing-1-0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CECILL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CECILL-1.0.json", - "referenceNumber": 272, - "name": "CeCILL Free Software License Agreement v1.0", - "licenseId": "CECILL-1.0", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CECILL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CECILL-1.1.json", - "referenceNumber": 571, - "name": "CeCILL Free Software License Agreement v1.1", - "licenseId": "CECILL-1.1", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CECILL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CECILL-2.0.json", - "referenceNumber": 269, - "name": "CeCILL Free Software License Agreement v2.0", - "licenseId": "CECILL-2.0", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CECILL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CECILL-2.1.json", - "referenceNumber": 569, - "name": "CeCILL Free Software License Agreement v2.1", - "licenseId": "CECILL-2.1", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CECILL-B.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CECILL-B.json", - "referenceNumber": 501, - "name": "CeCILL-B Free Software License Agreement", - "licenseId": "CECILL-B", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CECILL-C.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CECILL-C.json", - "referenceNumber": 503, - "name": "CeCILL-C Free Software License Agreement", - "licenseId": "CECILL-C", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CERN-OHL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CERN-OHL-1.1.json", - "referenceNumber": 502, - "name": "CERN Open Hardware Licence v1.1", - "licenseId": "CERN-OHL-1.1", - "seeAlso": [ - "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CERN-OHL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CERN-OHL-1.2.json", - "referenceNumber": 614, - "name": "CERN Open Hardware Licence v1.2", - "licenseId": "CERN-OHL-1.2", - "seeAlso": [ - "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CERN-OHL-P-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CERN-OHL-P-2.0.json", - "referenceNumber": 324, - "name": "CERN Open Hardware Licence Version 2 - Permissive", - "licenseId": "CERN-OHL-P-2.0", - "seeAlso": [ - "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CERN-OHL-S-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CERN-OHL-S-2.0.json", - "referenceNumber": 41, - "name": "CERN Open Hardware Licence Version 2 - Strongly Reciprocal", - "licenseId": "CERN-OHL-S-2.0", - "seeAlso": [ - "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CERN-OHL-W-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CERN-OHL-W-2.0.json", - "referenceNumber": 162, - "name": "CERN Open Hardware Licence Version 2 - Weakly Reciprocal", - "licenseId": "CERN-OHL-W-2.0", - "seeAlso": [ - "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CFITSIO.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CFITSIO.json", - "referenceNumber": 209, - "name": "CFITSIO License", - "licenseId": "CFITSIO", - "seeAlso": [ - "https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/f_user/node9.html", - "https://heasarc.gsfc.nasa.gov/docs/software/ftools/fv/doc/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/check-cvs.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/check-cvs.json", - "referenceNumber": 611, - "name": "check-cvs License", - "licenseId": "check-cvs", - "seeAlso": [ - "http://cvs.savannah.gnu.org/viewvc/cvs/ccvs/contrib/check_cvs.in?revision\u003d1.1.4.3\u0026view\u003dmarkup\u0026pathrev\u003dcvs1-11-23#l2" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/checkmk.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/checkmk.json", - "referenceNumber": 148, - "name": "Checkmk License", - "licenseId": "checkmk", - "seeAlso": [ - "https://github.com/libcheck/check/blob/master/checkmk/checkmk.in" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ClArtistic.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ClArtistic.json", - "referenceNumber": 202, - "name": "Clarified Artistic License", - "licenseId": "ClArtistic", - "seeAlso": [ - "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/", - "http://www.ncftp.com/ncftp/doc/LICENSE.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Clips.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Clips.json", - "referenceNumber": 419, - "name": "Clips License", - "licenseId": "Clips", - "seeAlso": [ - "https://github.com/DrItanium/maya/blob/master/LICENSE.CLIPS" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CMU-Mach.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CMU-Mach.json", - "referenceNumber": 212, - "name": "CMU Mach License", - "licenseId": "CMU-Mach", - "seeAlso": [ - "https://www.cs.cmu.edu/~410/licenses.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CNRI-Jython.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CNRI-Jython.json", - "referenceNumber": 515, - "name": "CNRI Jython License", - "licenseId": "CNRI-Jython", - "seeAlso": [ - "http://www.jython.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CNRI-Python.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CNRI-Python.json", - "referenceNumber": 124, - "name": "CNRI Python License", - "licenseId": "CNRI-Python", - "seeAlso": [ - "https://opensource.org/licenses/CNRI-Python" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.json", - "referenceNumber": 533, - "name": "CNRI Python Open Source GPL Compatible License Agreement", - "licenseId": "CNRI-Python-GPL-Compatible", - "seeAlso": [ - "http://www.python.org/download/releases/1.6.1/download_win/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/COIL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/COIL-1.0.json", - "referenceNumber": 265, - "name": "Copyfree Open Innovation License", - "licenseId": "COIL-1.0", - "seeAlso": [ - "https://coil.apotheon.org/plaintext/01.0.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Community-Spec-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Community-Spec-1.0.json", - "referenceNumber": 616, - "name": "Community Specification License 1.0", - "licenseId": "Community-Spec-1.0", - "seeAlso": [ - "https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Condor-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Condor-1.1.json", - "referenceNumber": 141, - "name": "Condor Public License v1.1", - "licenseId": "Condor-1.1", - "seeAlso": [ - "http://research.cs.wisc.edu/condor/license.html#condor", - "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/copyleft-next-0.3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/copyleft-next-0.3.0.json", - "referenceNumber": 110, - "name": "copyleft-next 0.3.0", - "licenseId": "copyleft-next-0.3.0", - "seeAlso": [ - "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/copyleft-next-0.3.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/copyleft-next-0.3.1.json", - "referenceNumber": 296, - "name": "copyleft-next 0.3.1", - "licenseId": "copyleft-next-0.3.1", - "seeAlso": [ - "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Cornell-Lossless-JPEG.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Cornell-Lossless-JPEG.json", - "referenceNumber": 271, - "name": "Cornell Lossless JPEG License", - "licenseId": "Cornell-Lossless-JPEG", - "seeAlso": [ - "https://android.googlesource.com/platform/external/dng_sdk/+/refs/heads/master/source/dng_lossless_jpeg.cpp#16", - "https://www.mssl.ucl.ac.uk/~mcrw/src/20050920/proto.h", - "https://gitlab.freedesktop.org/libopenraw/libopenraw/blob/master/lib/ljpegdecompressor.cpp#L32" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CPAL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CPAL-1.0.json", - "referenceNumber": 383, - "name": "Common Public Attribution License 1.0", - "licenseId": "CPAL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/CPAL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CPL-1.0.json", - "referenceNumber": 310, - "name": "Common Public License 1.0", - "licenseId": "CPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/CPL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/CPOL-1.02.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CPOL-1.02.json", - "referenceNumber": 78, - "name": "Code Project Open License 1.02", - "licenseId": "CPOL-1.02", - "seeAlso": [ - "http://www.codeproject.com/info/cpol10.aspx" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/Cronyx.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Cronyx.json", - "referenceNumber": 104, - "name": "Cronyx License", - "licenseId": "Cronyx", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/font/alias/-/blob/master/COPYING", - "https://gitlab.freedesktop.org/xorg/font/cronyx-cyrillic/-/blob/master/COPYING", - "https://gitlab.freedesktop.org/xorg/font/misc-cyrillic/-/blob/master/COPYING", - "https://gitlab.freedesktop.org/xorg/font/screen-cyrillic/-/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Crossword.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Crossword.json", - "referenceNumber": 88, - "name": "Crossword License", - "licenseId": "Crossword", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Crossword" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CrystalStacker.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CrystalStacker.json", - "referenceNumber": 608, - "name": "CrystalStacker License", - "licenseId": "CrystalStacker", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/CUA-OPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/CUA-OPL-1.0.json", - "referenceNumber": 364, - "name": "CUA Office Public License v1.0", - "licenseId": "CUA-OPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/CUA-OPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Cube.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Cube.json", - "referenceNumber": 385, - "name": "Cube License", - "licenseId": "Cube", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Cube" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/curl.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/curl.json", - "referenceNumber": 243, - "name": "curl License", - "licenseId": "curl", - "seeAlso": [ - "https://github.com/bagder/curl/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/D-FSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/D-FSL-1.0.json", - "referenceNumber": 302, - "name": "Deutsche Freie Software Lizenz", - "licenseId": "D-FSL-1.0", - "seeAlso": [ - "http://www.dipp.nrw.de/d-fsl/lizenzen/", - "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt", - "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DEC-3-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DEC-3-Clause.json", - "referenceNumber": 453, - "name": "DEC 3-Clause License", - "licenseId": "DEC-3-Clause", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type\u003dheads#L239" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/diffmark.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/diffmark.json", - "referenceNumber": 350, - "name": "diffmark license", - "licenseId": "diffmark", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/diffmark" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DL-DE-BY-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DL-DE-BY-2.0.json", - "referenceNumber": 266, - "name": "Data licence Germany – attribution – version 2.0", - "licenseId": "DL-DE-BY-2.0", - "seeAlso": [ - "https://www.govdata.de/dl-de/by-2-0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DL-DE-ZERO-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DL-DE-ZERO-2.0.json", - "referenceNumber": 540, - "name": "Data licence Germany – zero – version 2.0", - "licenseId": "DL-DE-ZERO-2.0", - "seeAlso": [ - "https://www.govdata.de/dl-de/zero-2-0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DOC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DOC.json", - "referenceNumber": 496, - "name": "DOC License", - "licenseId": "DOC", - "seeAlso": [ - "http://www.cs.wustl.edu/~schmidt/ACE-copying.html", - "https://www.dre.vanderbilt.edu/~schmidt/ACE-copying.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Dotseqn.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Dotseqn.json", - "referenceNumber": 229, - "name": "Dotseqn License", - "licenseId": "Dotseqn", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Dotseqn" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DRL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DRL-1.0.json", - "referenceNumber": 365, - "name": "Detection Rule License 1.0", - "licenseId": "DRL-1.0", - "seeAlso": [ - "https://github.com/Neo23x0/sigma/blob/master/LICENSE.Detection.Rules.md" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DRL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DRL-1.1.json", - "referenceNumber": 130, - "name": "Detection Rule License 1.1", - "licenseId": "DRL-1.1", - "seeAlso": [ - "https://github.com/SigmaHQ/Detection-Rule-License/blob/6ec7fbde6101d101b5b5d1fcb8f9b69fbc76c04a/LICENSE.Detection.Rules.md" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/DSDP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/DSDP.json", - "referenceNumber": 123, - "name": "DSDP License", - "licenseId": "DSDP", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/DSDP" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/dtoa.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/dtoa.json", - "referenceNumber": 410, - "name": "David M. Gay dtoa License", - "licenseId": "dtoa", - "seeAlso": [ - "https://github.com/SWI-Prolog/swipl-devel/blob/master/src/os/dtoa.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/dvipdfm.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/dvipdfm.json", - "referenceNumber": 198, - "name": "dvipdfm License", - "licenseId": "dvipdfm", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/dvipdfm" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ECL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ECL-1.0.json", - "referenceNumber": 373, - "name": "Educational Community License v1.0", - "licenseId": "ECL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/ECL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/ECL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ECL-2.0.json", - "referenceNumber": 158, - "name": "Educational Community License v2.0", - "licenseId": "ECL-2.0", - "seeAlso": [ - "https://opensource.org/licenses/ECL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/eCos-2.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/eCos-2.0.json", - "referenceNumber": 344, - "name": "eCos license version 2.0", - "licenseId": "eCos-2.0", - "seeAlso": [ - "https://www.gnu.org/licenses/ecos-license.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/EFL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EFL-1.0.json", - "referenceNumber": 69, - "name": "Eiffel Forum License v1.0", - "licenseId": "EFL-1.0", - "seeAlso": [ - "http://www.eiffel-nice.org/license/forum.txt", - "https://opensource.org/licenses/EFL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/EFL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EFL-2.0.json", - "referenceNumber": 409, - "name": "Eiffel Forum License v2.0", - "licenseId": "EFL-2.0", - "seeAlso": [ - "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html", - "https://opensource.org/licenses/EFL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/eGenix.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/eGenix.json", - "referenceNumber": 216, - "name": "eGenix.com Public License 1.1.0", - "licenseId": "eGenix", - "seeAlso": [ - "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf", - "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Elastic-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Elastic-2.0.json", - "referenceNumber": 389, - "name": "Elastic License 2.0", - "licenseId": "Elastic-2.0", - "seeAlso": [ - "https://www.elastic.co/licensing/elastic-license", - "https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE-2.0.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Entessa.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Entessa.json", - "referenceNumber": 29, - "name": "Entessa Public License v1.0", - "licenseId": "Entessa", - "seeAlso": [ - "https://opensource.org/licenses/Entessa" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/EPICS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EPICS.json", - "referenceNumber": 31, - "name": "EPICS Open License", - "licenseId": "EPICS", - "seeAlso": [ - "https://epics.anl.gov/license/open.php" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/EPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EPL-1.0.json", - "referenceNumber": 92, - "name": "Eclipse Public License 1.0", - "licenseId": "EPL-1.0", - "seeAlso": [ - "http://www.eclipse.org/legal/epl-v10.html", - "https://opensource.org/licenses/EPL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/EPL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EPL-2.0.json", - "referenceNumber": 593, - "name": "Eclipse Public License 2.0", - "licenseId": "EPL-2.0", - "seeAlso": [ - "https://www.eclipse.org/legal/epl-2.0", - "https://www.opensource.org/licenses/EPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ErlPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ErlPL-1.1.json", - "referenceNumber": 167, - "name": "Erlang Public License v1.1", - "licenseId": "ErlPL-1.1", - "seeAlso": [ - "http://www.erlang.org/EPLICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/etalab-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/etalab-2.0.json", - "referenceNumber": 478, - "name": "Etalab Open License 2.0", - "licenseId": "etalab-2.0", - "seeAlso": [ - "https://github.com/DISIC/politique-de-contribution-open-source/blob/master/LICENSE.pdf", - "https://raw.githubusercontent.com/DISIC/politique-de-contribution-open-source/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/EUDatagrid.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EUDatagrid.json", - "referenceNumber": 48, - "name": "EU DataGrid Software License", - "licenseId": "EUDatagrid", - "seeAlso": [ - "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html", - "https://opensource.org/licenses/EUDatagrid" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/EUPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EUPL-1.0.json", - "referenceNumber": 270, - "name": "European Union Public License 1.0", - "licenseId": "EUPL-1.0", - "seeAlso": [ - "http://ec.europa.eu/idabc/en/document/7330.html", - "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/EUPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EUPL-1.1.json", - "referenceNumber": 20, - "name": "European Union Public License 1.1", - "licenseId": "EUPL-1.1", - "seeAlso": [ - "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf", - "https://opensource.org/licenses/EUPL-1.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/EUPL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/EUPL-1.2.json", - "referenceNumber": 62, - "name": "European Union Public License 1.2", - "licenseId": "EUPL-1.2", - "seeAlso": [ - "https://joinup.ec.europa.eu/page/eupl-text-11-12", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/2020-03/EUPL-1.2%20EN.txt", - "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt", - "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863", - "https://opensource.org/licenses/EUPL-1.2" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Eurosym.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Eurosym.json", - "referenceNumber": 464, - "name": "Eurosym License", - "licenseId": "Eurosym", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Eurosym" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Fair.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Fair.json", - "referenceNumber": 557, - "name": "Fair License", - "licenseId": "Fair", - "seeAlso": [ - "https://web.archive.org/web/20150926120323/http://fairlicense.org/", - "https://opensource.org/licenses/Fair" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/FBM.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FBM.json", - "referenceNumber": 115, - "name": "Fuzzy Bitmap License", - "licenseId": "FBM", - "seeAlso": [ - "https://github.com/SWI-Prolog/packages-xpce/blob/161a40cd82004f731ba48024f9d30af388a7edf5/src/img/gifwrite.c#L21-L26" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FDK-AAC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FDK-AAC.json", - "referenceNumber": 168, - "name": "Fraunhofer FDK AAC Codec Library", - "licenseId": "FDK-AAC", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FDK-AAC", - "https://directory.fsf.org/wiki/License:Fdk" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Ferguson-Twofish.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Ferguson-Twofish.json", - "referenceNumber": 414, - "name": "Ferguson Twofish License", - "licenseId": "Ferguson-Twofish", - "seeAlso": [ - "https://github.com/wernerd/ZRTPCPP/blob/6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03/cryptcommon/twofish.c#L113C3-L127" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Frameworx-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Frameworx-1.0.json", - "referenceNumber": 287, - "name": "Frameworx Open License 1.0", - "licenseId": "Frameworx-1.0", - "seeAlso": [ - "https://opensource.org/licenses/Frameworx-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/FreeBSD-DOC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FreeBSD-DOC.json", - "referenceNumber": 257, - "name": "FreeBSD Documentation License", - "licenseId": "FreeBSD-DOC", - "seeAlso": [ - "https://www.freebsd.org/copyright/freebsd-doc-license/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FreeImage.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FreeImage.json", - "referenceNumber": 144, - "name": "FreeImage Public License v1.0", - "licenseId": "FreeImage", - "seeAlso": [ - "http://freeimage.sourceforge.net/freeimage-license.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FSFAP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FSFAP.json", - "referenceNumber": 1, - "name": "FSF All Permissive License", - "licenseId": "FSFAP", - "seeAlso": [ - "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/FSFAP-no-warranty-disclaimer.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FSFAP-no-warranty-disclaimer.json", - "referenceNumber": 313, - "name": "FSF All Permissive License (without Warranty)", - "licenseId": "FSFAP-no-warranty-disclaimer", - "seeAlso": [ - "https://git.savannah.gnu.org/cgit/wget.git/tree/util/trunc.c?h\u003dv1.21.3\u0026id\u003d40747a11e44ced5a8ac628a41f879ced3e2ebce9#n6" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FSFUL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FSFUL.json", - "referenceNumber": 5, - "name": "FSF Unlimited License", - "licenseId": "FSFUL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FSFULLR.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FSFULLR.json", - "referenceNumber": 603, - "name": "FSF Unlimited License (with License Retention)", - "licenseId": "FSFULLR", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FSFULLRWD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FSFULLRWD.json", - "referenceNumber": 406, - "name": "FSF Unlimited License (With License Retention and Warranty Disclaimer)", - "licenseId": "FSFULLRWD", - "seeAlso": [ - "https://lists.gnu.org/archive/html/autoconf/2012-04/msg00061.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/FTL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/FTL.json", - "referenceNumber": 562, - "name": "Freetype Project License", - "licenseId": "FTL", - "seeAlso": [ - "http://freetype.fis.uniroma2.it/FTL.TXT", - "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT", - "http://gitlab.freedesktop.org/freetype/freetype/-/raw/master/docs/FTL.TXT" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Furuseth.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Furuseth.json", - "referenceNumber": 27, - "name": "Furuseth License", - "licenseId": "Furuseth", - "seeAlso": [ - "https://git.openldap.org/openldap/openldap/-/blob/master/COPYRIGHT?ref_type\u003dheads#L39-51" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/fwlw.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/fwlw.json", - "referenceNumber": 402, - "name": "fwlw License", - "licenseId": "fwlw", - "seeAlso": [ - "https://mirrors.nic.cz/tex-archive/macros/latex/contrib/fwlw/README" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GCR-docs.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GCR-docs.json", - "referenceNumber": 98, - "name": "Gnome GCR Documentation License", - "licenseId": "GCR-docs", - "seeAlso": [ - "https://github.com/GNOME/gcr/blob/master/docs/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GD.json", - "referenceNumber": 326, - "name": "GD License", - "licenseId": "GD", - "seeAlso": [ - "https://libgd.github.io/manuals/2.3.0/files/license-txt.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1.json", - "referenceNumber": 90, - "name": "GNU Free Documentation License v1.1", - "licenseId": "GFDL-1.1", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1-invariants-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-invariants-only.json", - "referenceNumber": 514, - "name": "GNU Free Documentation License v1.1 only - invariants", - "licenseId": "GFDL-1.1-invariants-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.json", - "referenceNumber": 381, - "name": "GNU Free Documentation License v1.1 or later - invariants", - "licenseId": "GFDL-1.1-invariants-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.json", - "referenceNumber": 173, - "name": "GNU Free Documentation License v1.1 only - no invariants", - "licenseId": "GFDL-1.1-no-invariants-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.json", - "referenceNumber": 301, - "name": "GNU Free Documentation License v1.1 or later - no invariants", - "licenseId": "GFDL-1.1-no-invariants-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-only.json", - "referenceNumber": 309, - "name": "GNU Free Documentation License v1.1 only", - "licenseId": "GFDL-1.1-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.1-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-or-later.json", - "referenceNumber": 351, - "name": "GNU Free Documentation License v1.1 or later", - "licenseId": "GFDL-1.1-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2.json", - "referenceNumber": 239, - "name": "GNU Free Documentation License v1.2", - "licenseId": "GFDL-1.2", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2-invariants-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-invariants-only.json", - "referenceNumber": 615, - "name": "GNU Free Documentation License v1.2 only - invariants", - "licenseId": "GFDL-1.2-invariants-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.json", - "referenceNumber": 42, - "name": "GNU Free Documentation License v1.2 or later - invariants", - "licenseId": "GFDL-1.2-invariants-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.json", - "referenceNumber": 179, - "name": "GNU Free Documentation License v1.2 only - no invariants", - "licenseId": "GFDL-1.2-no-invariants-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.json", - "referenceNumber": 595, - "name": "GNU Free Documentation License v1.2 or later - no invariants", - "licenseId": "GFDL-1.2-no-invariants-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-only.json", - "referenceNumber": 224, - "name": "GNU Free Documentation License v1.2 only", - "licenseId": "GFDL-1.2-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.2-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-or-later.json", - "referenceNumber": 72, - "name": "GNU Free Documentation License v1.2 or later", - "licenseId": "GFDL-1.2-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3.json", - "referenceNumber": 345, - "name": "GNU Free Documentation License v1.3", - "licenseId": "GFDL-1.3", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3-invariants-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-invariants-only.json", - "referenceNumber": 61, - "name": "GNU Free Documentation License v1.3 only - invariants", - "licenseId": "GFDL-1.3-invariants-only", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.json", - "referenceNumber": 258, - "name": "GNU Free Documentation License v1.3 or later - invariants", - "licenseId": "GFDL-1.3-invariants-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.json", - "referenceNumber": 22, - "name": "GNU Free Documentation License v1.3 only - no invariants", - "licenseId": "GFDL-1.3-no-invariants-only", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.json", - "referenceNumber": 374, - "name": "GNU Free Documentation License v1.3 or later - no invariants", - "licenseId": "GFDL-1.3-no-invariants-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-only.json", - "referenceNumber": 323, - "name": "GNU Free Documentation License v1.3 only", - "licenseId": "GFDL-1.3-only", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GFDL-1.3-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-or-later.json", - "referenceNumber": 449, - "name": "GNU Free Documentation License v1.3 or later", - "licenseId": "GFDL-1.3-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Giftware.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Giftware.json", - "referenceNumber": 311, - "name": "Giftware License", - "licenseId": "Giftware", - "seeAlso": [ - "http://liballeg.org/license.html#allegro-4-the-giftware-license" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GL2PS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GL2PS.json", - "referenceNumber": 87, - "name": "GL2PS License", - "licenseId": "GL2PS", - "seeAlso": [ - "http://www.geuz.org/gl2ps/COPYING.GL2PS" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Glide.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Glide.json", - "referenceNumber": 566, - "name": "3dfx Glide License", - "licenseId": "Glide", - "seeAlso": [ - "http://www.users.on.net/~triforce/glidexp/COPYING.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Glulxe.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Glulxe.json", - "referenceNumber": 3, - "name": "Glulxe License", - "licenseId": "Glulxe", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Glulxe" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GLWTPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GLWTPL.json", - "referenceNumber": 454, - "name": "Good Luck With That Public License", - "licenseId": "GLWTPL", - "seeAlso": [ - "https://github.com/me-shaon/GLWTPL/commit/da5f6bc734095efbacb442c0b31e33a65b9d6e85" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/gnuplot.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/gnuplot.json", - "referenceNumber": 177, - "name": "gnuplot License", - "licenseId": "gnuplot", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Gnuplot" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-1.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-1.0.json", - "referenceNumber": 452, - "name": "GNU General Public License v1.0 only", - "licenseId": "GPL-1.0", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-1.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-1.0+.json", - "referenceNumber": 448, - "name": "GNU General Public License v1.0 or later", - "licenseId": "GPL-1.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-1.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GPL-1.0-only.json", - "referenceNumber": 305, - "name": "GNU General Public License v1.0 only", - "licenseId": "GPL-1.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-1.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GPL-1.0-or-later.json", - "referenceNumber": 230, - "name": "GNU General Public License v1.0 or later", - "licenseId": "GPL-1.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0.json", - "referenceNumber": 264, - "name": "GNU General Public License v2.0 only", - "licenseId": "GPL-2.0", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0+.json", - "referenceNumber": 77, - "name": "GNU General Public License v2.0 or later", - "licenseId": "GPL-2.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-only.json", - "referenceNumber": 600, - "name": "GNU General Public License v2.0 only", - "licenseId": "GPL-2.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-or-later.json", - "referenceNumber": 54, - "name": "GNU General Public License v2.0 or later", - "licenseId": "GPL-2.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json", - "referenceNumber": 393, - "name": "GNU General Public License v2.0 w/Autoconf exception", - "licenseId": "GPL-2.0-with-autoconf-exception", - "seeAlso": [ - "http://ac-archive.sourceforge.net/doc/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.json", - "referenceNumber": 361, - "name": "GNU General Public License v2.0 w/Bison exception", - "licenseId": "GPL-2.0-with-bison-exception", - "seeAlso": [ - "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.json", - "referenceNumber": 527, - "name": "GNU General Public License v2.0 w/Classpath exception", - "licenseId": "GPL-2.0-with-classpath-exception", - "seeAlso": [ - "https://www.gnu.org/software/classpath/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-font-exception.json", - "referenceNumber": 400, - "name": "GNU General Public License v2.0 w/Font exception", - "licenseId": "GPL-2.0-with-font-exception", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-faq.html#FontException" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.json", - "referenceNumber": 343, - "name": "GNU General Public License v2.0 w/GCC Runtime Library exception", - "licenseId": "GPL-2.0-with-GCC-exception", - "seeAlso": [ - "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-3.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-3.0.json", - "referenceNumber": 488, - "name": "GNU General Public License v3.0 only", - "licenseId": "GPL-3.0", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-3.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-3.0+.json", - "referenceNumber": 283, - "name": "GNU General Public License v3.0 or later", - "licenseId": "GPL-3.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-3.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GPL-3.0-only.json", - "referenceNumber": 495, - "name": "GNU General Public License v3.0 only", - "licenseId": "GPL-3.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-3.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/GPL-3.0-or-later.json", - "referenceNumber": 372, - "name": "GNU General Public License v3.0 or later", - "licenseId": "GPL-3.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json", - "referenceNumber": 489, - "name": "GNU General Public License v3.0 w/Autoconf exception", - "licenseId": "GPL-3.0-with-autoconf-exception", - "seeAlso": [ - "https://www.gnu.org/licenses/autoconf-exception-3.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.json", - "referenceNumber": 352, - "name": "GNU General Public License v3.0 w/GCC Runtime Library exception", - "licenseId": "GPL-3.0-with-GCC-exception", - "seeAlso": [ - "https://www.gnu.org/licenses/gcc-exception-3.1.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Graphics-Gems.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Graphics-Gems.json", - "referenceNumber": 275, - "name": "Graphics Gems License", - "licenseId": "Graphics-Gems", - "seeAlso": [ - "https://github.com/erich666/GraphicsGems/blob/master/LICENSE.md" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/gSOAP-1.3b.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/gSOAP-1.3b.json", - "referenceNumber": 346, - "name": "gSOAP Public License v1.3b", - "licenseId": "gSOAP-1.3b", - "seeAlso": [ - "http://www.cs.fsu.edu/~engelen/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HaskellReport.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HaskellReport.json", - "referenceNumber": 560, - "name": "Haskell Language Report License", - "licenseId": "HaskellReport", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/hdparm.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/hdparm.json", - "referenceNumber": 249, - "name": "hdparm License", - "licenseId": "hdparm", - "seeAlso": [ - "https://github.com/Distrotech/hdparm/blob/4517550db29a91420fb2b020349523b1b4512df2/LICENSE.TXT" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Hippocratic-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Hippocratic-2.1.json", - "referenceNumber": 10, - "name": "Hippocratic License 2.1", - "licenseId": "Hippocratic-2.1", - "seeAlso": [ - "https://firstdonoharm.dev/version/2/1/license.html", - "https://github.com/EthicalSource/hippocratic-license/blob/58c0e646d64ff6fbee275bfe2b9492f914e3ab2a/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HP-1986.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HP-1986.json", - "referenceNumber": 11, - "name": "Hewlett-Packard 1986 License", - "licenseId": "HP-1986", - "seeAlso": [ - "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/machine/hppa/memchr.S;h\u003d1cca3e5e8867aa4bffef1f75a5c1bba25c0c441e;hb\u003dHEAD#l2" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HP-1989.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HP-1989.json", - "referenceNumber": 418, - "name": "Hewlett-Packard 1989 License", - "licenseId": "HP-1989", - "seeAlso": [ - "https://github.com/bleargh45/Data-UUID/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND.json", - "referenceNumber": 416, - "name": "Historical Permission Notice and Disclaimer", - "licenseId": "HPND", - "seeAlso": [ - "https://opensource.org/licenses/HPND", - "http://lists.opensource.org/pipermail/license-discuss_lists.opensource.org/2002-November/006304.html" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/HPND-DEC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-DEC.json", - "referenceNumber": 206, - "name": "Historical Permission Notice and Disclaimer - DEC variant", - "licenseId": "HPND-DEC", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/app/xkbcomp/-/blob/master/COPYING?ref_type\u003dheads#L69" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-doc.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-doc.json", - "referenceNumber": 450, - "name": "Historical Permission Notice and Disclaimer - documentation variant", - "licenseId": "HPND-doc", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/lib/libxext/-/blob/master/COPYING?ref_type\u003dheads#L185-197", - "https://gitlab.freedesktop.org/xorg/lib/libxtst/-/blob/master/COPYING?ref_type\u003dheads#L70-77" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-doc-sell.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-doc-sell.json", - "referenceNumber": 113, - "name": "Historical Permission Notice and Disclaimer - documentation sell variant", - "licenseId": "HPND-doc-sell", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/lib/libxtst/-/blob/master/COPYING?ref_type\u003dheads#L108-117", - "https://gitlab.freedesktop.org/xorg/lib/libxext/-/blob/master/COPYING?ref_type\u003dheads#L153-162" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-export-US.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-export-US.json", - "referenceNumber": 329, - "name": "HPND with US Government export control warning", - "licenseId": "HPND-export-US", - "seeAlso": [ - "https://www.kermitproject.org/ck90.html#source" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-export-US-modify.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-export-US-modify.json", - "referenceNumber": 304, - "name": "HPND with US Government export control warning and modification rqmt", - "licenseId": "HPND-export-US-modify", - "seeAlso": [ - "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L1157-L1182", - "https://github.com/pythongssapi/k5test/blob/v0.10.3/K5TEST-LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-Kevlin-Henney.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-Kevlin-Henney.json", - "referenceNumber": 553, - "name": "Historical Permission Notice and Disclaimer - Kevlin Henney variant", - "licenseId": "HPND-Kevlin-Henney", - "seeAlso": [ - "https://github.com/mruby/mruby/blob/83d12f8d52522cdb7c8cc46fad34821359f453e6/mrbgems/mruby-dir/src/Win/dirent.c#L127-L140" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-Markus-Kuhn.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-Markus-Kuhn.json", - "referenceNumber": 223, - "name": "Historical Permission Notice and Disclaimer - Markus Kuhn variant", - "licenseId": "HPND-Markus-Kuhn", - "seeAlso": [ - "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c", - "https://sourceware.org/git/?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dreadline/readline/support/wcwidth.c;h\u003d0f5ec995796f4813abbcf4972aec0378ab74722a;hb\u003dHEAD#l55" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-MIT-disclaimer.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-MIT-disclaimer.json", - "referenceNumber": 100, - "name": "Historical Permission Notice and Disclaimer with MIT disclaimer", - "licenseId": "HPND-MIT-disclaimer", - "seeAlso": [ - "https://metacpan.org/release/NLNETLABS/Net-DNS-SEC-1.22/source/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-Pbmplus.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-Pbmplus.json", - "referenceNumber": 260, - "name": "Historical Permission Notice and Disclaimer - Pbmplus variant", - "licenseId": "HPND-Pbmplus", - "seeAlso": [ - "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/netpbm.c#l8" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-sell-MIT-disclaimer-xserver.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-sell-MIT-disclaimer-xserver.json", - "referenceNumber": 170, - "name": - "Historical Permission Notice and Disclaimer - sell xserver variant with MIT disclaimer", - "licenseId": "HPND-sell-MIT-disclaimer-xserver", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type\u003dheads#L1781" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-sell-regexpr.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-sell-regexpr.json", - "referenceNumber": 580, - "name": "Historical Permission Notice and Disclaimer - sell regexpr variant", - "licenseId": "HPND-sell-regexpr", - "seeAlso": [ - "https://gitlab.com/bacula-org/bacula/-/blob/Branch-11.0/bacula/LICENSE-FOSS?ref_type\u003dheads#L245" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-sell-variant.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant.json", - "referenceNumber": 79, - "name": "Historical Permission Notice and Disclaimer - sell variant", - "licenseId": "HPND-sell-variant", - "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h\u003dv4.19" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer.json", - "referenceNumber": 318, - "name": "HPND sell variant with MIT disclaimer", - "licenseId": "HPND-sell-variant-MIT-disclaimer", - "seeAlso": [ - "https://github.com/sigmavirus24/x11-ssh-askpass/blob/master/README" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HPND-UC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HPND-UC.json", - "referenceNumber": 531, - "name": - "Historical Permission Notice and Disclaimer - University of California variant", - "licenseId": "HPND-UC", - "seeAlso": [ - "https://core.tcl-lang.org/tk/file?name\u003dcompat/unistd.h" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/HTMLTIDY.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/HTMLTIDY.json", - "referenceNumber": 120, - "name": "HTML Tidy License", - "licenseId": "HTMLTIDY", - "seeAlso": [ - "https://github.com/htacg/tidy-html5/blob/next/README/LICENSE.md" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/IBM-pibs.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/IBM-pibs.json", - "referenceNumber": 596, - "name": "IBM PowerPC Initialization and Boot Software", - "licenseId": "IBM-pibs", - "seeAlso": [ - "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ICU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ICU.json", - "referenceNumber": 330, - "name": "ICU License", - "licenseId": "ICU", - "seeAlso": [ - "http://source.icu-project.org/repos/icu/icu/trunk/license.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/IEC-Code-Components-EULA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/IEC-Code-Components-EULA.json", - "referenceNumber": 356, - "name": "IEC Code Components End-user licence agreement", - "licenseId": "IEC-Code-Components-EULA", - "seeAlso": [ - "https://www.iec.ch/webstore/custserv/pdf/CC-EULA.pdf", - "https://www.iec.ch/CCv1", - "https://www.iec.ch/copyright" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/IJG.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/IJG.json", - "referenceNumber": 314, - "name": "Independent JPEG Group License", - "licenseId": "IJG", - "seeAlso": [ - "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/IJG-short.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/IJG-short.json", - "referenceNumber": 316, - "name": "Independent JPEG Group License - short", - "licenseId": "IJG-short", - "seeAlso": [ - "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/ljpg/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ImageMagick.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ImageMagick.json", - "referenceNumber": 391, - "name": "ImageMagick License", - "licenseId": "ImageMagick", - "seeAlso": [ - "http://www.imagemagick.org/script/license.php" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/iMatix.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/iMatix.json", - "referenceNumber": 295, - "name": "iMatix Standard Function Library Agreement", - "licenseId": "iMatix", - "seeAlso": [ - "http://legacy.imatix.com/html/sfl/sfl4.htm#license" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Imlib2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Imlib2.json", - "referenceNumber": 547, - "name": "Imlib2 License", - "licenseId": "Imlib2", - "seeAlso": [ - "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING", - "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Info-ZIP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Info-ZIP.json", - "referenceNumber": 490, - "name": "Info-ZIP License", - "licenseId": "Info-ZIP", - "seeAlso": [ - "http://www.info-zip.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Inner-Net-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Inner-Net-2.0.json", - "referenceNumber": 435, - "name": "Inner Net License v2.0", - "licenseId": "Inner-Net-2.0", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Inner_Net_License", - "https://sourceware.org/git/?p\u003dglibc.git;a\u003dblob;f\u003dLICENSES;h\u003d530893b1dc9ea00755603c68fb36bd4fc38a7be8;hb\u003dHEAD#l207" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Intel.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Intel.json", - "referenceNumber": 399, - "name": "Intel Open Source License", - "licenseId": "Intel", - "seeAlso": [ - "https://opensource.org/licenses/Intel" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Intel-ACPI.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Intel-ACPI.json", - "referenceNumber": 306, - "name": "Intel ACPI Software License Agreement", - "licenseId": "Intel-ACPI", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Interbase-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Interbase-1.0.json", - "referenceNumber": 237, - "name": "Interbase Public License v1.0", - "licenseId": "Interbase-1.0", - "seeAlso": [ - "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/IPA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/IPA.json", - "referenceNumber": 561, - "name": "IPA Font License", - "licenseId": "IPA", - "seeAlso": [ - "https://opensource.org/licenses/IPA" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/IPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/IPL-1.0.json", - "referenceNumber": 53, - "name": "IBM Public License v1.0", - "licenseId": "IPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/IPL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ISC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ISC.json", - "referenceNumber": 322, - "name": "ISC License", - "licenseId": "ISC", - "seeAlso": [ - "https://www.isc.org/licenses/", - "https://www.isc.org/downloads/software-support-policy/isc-license/", - "https://opensource.org/licenses/ISC" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ISC-Veillard.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ISC-Veillard.json", - "referenceNumber": 284, - "name": "ISC Veillard variant", - "licenseId": "ISC-Veillard", - "seeAlso": [ - "https://raw.githubusercontent.com/GNOME/libxml2/4c2e7c651f6c2f0d1a74f350cbda95f7df3e7017/hash.c", - "https://github.com/GNOME/libxml2/blob/master/dict.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Jam.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Jam.json", - "referenceNumber": 505, - "name": "Jam License", - "licenseId": "Jam", - "seeAlso": [ - "https://www.boost.org/doc/libs/1_35_0/doc/html/jam.html", - "https://web.archive.org/web/20160330173339/https://swarm.workshop.perforce.com/files/guest/perforce_software/jam/src/README" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/JasPer-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/JasPer-2.0.json", - "referenceNumber": 60, - "name": "JasPer License", - "licenseId": "JasPer-2.0", - "seeAlso": [ - "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/JPL-image.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/JPL-image.json", - "referenceNumber": 509, - "name": "JPL Image Use Policy", - "licenseId": "JPL-image", - "seeAlso": [ - "https://www.jpl.nasa.gov/jpl-image-use-policy" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/JPNIC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/JPNIC.json", - "referenceNumber": 579, - "name": "Japan Network Information Center License", - "licenseId": "JPNIC", - "seeAlso": [ - "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/JSON.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/JSON.json", - "referenceNumber": 155, - "name": "JSON License", - "licenseId": "JSON", - "seeAlso": [ - "http://www.json.org/license.html" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/Kastrup.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Kastrup.json", - "referenceNumber": 570, - "name": "Kastrup License", - "licenseId": "Kastrup", - "seeAlso": [ - "https://ctan.math.utah.edu/ctan/tex-archive/macros/generic/kastrup/binhex.dtx" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Kazlib.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Kazlib.json", - "referenceNumber": 551, - "name": "Kazlib License", - "licenseId": "Kazlib", - "seeAlso": [ - "http://git.savannah.gnu.org/cgit/kazlib.git/tree/except.c?id\u003d0062df360c2d17d57f6af19b0e444c51feb99036" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Knuth-CTAN.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Knuth-CTAN.json", - "referenceNumber": 504, - "name": "Knuth CTAN License", - "licenseId": "Knuth-CTAN", - "seeAlso": [ - "https://ctan.org/license/knuth" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LAL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LAL-1.2.json", - "referenceNumber": 468, - "name": "Licence Art Libre 1.2", - "licenseId": "LAL-1.2", - "seeAlso": [ - "http://artlibre.org/licence/lal/licence-art-libre-12/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LAL-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LAL-1.3.json", - "referenceNumber": 118, - "name": "Licence Art Libre 1.3", - "licenseId": "LAL-1.3", - "seeAlso": [ - "https://artlibre.org/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Latex2e.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Latex2e.json", - "referenceNumber": 597, - "name": "Latex2e License", - "licenseId": "Latex2e", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Latex2e" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Latex2e-translated-notice.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Latex2e-translated-notice.json", - "referenceNumber": 276, - "name": "Latex2e with translated notice permission", - "licenseId": "Latex2e-translated-notice", - "seeAlso": [ - "https://git.savannah.gnu.org/cgit/indent.git/tree/doc/indent.texi?id\u003da74c6b4ee49397cf330b333da1042bffa60ed14f#n74" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Leptonica.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Leptonica.json", - "referenceNumber": 192, - "name": "Leptonica License", - "licenseId": "Leptonica", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Leptonica" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.0.json", - "referenceNumber": 68, - "name": "GNU Library General Public License v2 only", - "licenseId": "LGPL-2.0", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.0+.json", - "referenceNumber": 492, - "name": "GNU Library General Public License v2 or later", - "licenseId": "LGPL-2.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.0-only.json", - "referenceNumber": 434, - "name": "GNU Library General Public License v2 only", - "licenseId": "LGPL-2.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.0-or-later.json", - "referenceNumber": 157, - "name": "GNU Library General Public License v2 or later", - "licenseId": "LGPL-2.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.1.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.1.json", - "referenceNumber": 623, - "name": "GNU Lesser General Public License v2.1 only", - "licenseId": "LGPL-2.1", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.1+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.1+.json", - "referenceNumber": 357, - "name": "GNU Lesser General Public License v2.1 or later", - "licenseId": "LGPL-2.1+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.1-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.1-only.json", - "referenceNumber": 35, - "name": "GNU Lesser General Public License v2.1 only", - "licenseId": "LGPL-2.1-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-2.1-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPL-2.1-or-later.json", - "referenceNumber": 349, - "name": "GNU Lesser General Public License v2.1 or later", - "licenseId": "LGPL-2.1-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-3.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/LGPL-3.0.json", - "referenceNumber": 617, - "name": "GNU Lesser General Public License v3.0 only", - "licenseId": "LGPL-3.0", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-3.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/LGPL-3.0+.json", - "referenceNumber": 52, - "name": "GNU Lesser General Public License v3.0 or later", - "licenseId": "LGPL-3.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-3.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-only.json", - "referenceNumber": 307, - "name": "GNU Lesser General Public License v3.0 only", - "licenseId": "LGPL-3.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPL-3.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-or-later.json", - "referenceNumber": 64, - "name": "GNU Lesser General Public License v3.0 or later", - "licenseId": "LGPL-3.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LGPLLR.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LGPLLR.json", - "referenceNumber": 268, - "name": "Lesser General Public License For Linguistic Resources", - "licenseId": "LGPLLR", - "seeAlso": [ - "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Libpng.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Libpng.json", - "referenceNumber": 484, - "name": "libpng License", - "licenseId": "Libpng", - "seeAlso": [ - "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/libpng-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/libpng-2.0.json", - "referenceNumber": 16, - "name": "PNG Reference Library version 2", - "licenseId": "libpng-2.0", - "seeAlso": [ - "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/libselinux-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/libselinux-1.0.json", - "referenceNumber": 67, - "name": "libselinux public domain notice", - "licenseId": "libselinux-1.0", - "seeAlso": [ - "https://github.com/SELinuxProject/selinux/blob/master/libselinux/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/libtiff.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/libtiff.json", - "referenceNumber": 466, - "name": "libtiff License", - "licenseId": "libtiff", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/libtiff" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/libutil-David-Nugent.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/libutil-David-Nugent.json", - "referenceNumber": 66, - "name": "libutil David Nugent License", - "licenseId": "libutil-David-Nugent", - "seeAlso": [ - "http://web.mit.edu/freebsd/head/lib/libutil/login_ok.3", - "https://cgit.freedesktop.org/libbsd/tree/man/setproctitle.3bsd" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LiLiQ-P-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LiLiQ-P-1.1.json", - "referenceNumber": 248, - "name": "Licence Libre du Québec – Permissive version 1.1", - "licenseId": "LiLiQ-P-1.1", - "seeAlso": [ - "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/", - "http://opensource.org/licenses/LiLiQ-P-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LiLiQ-R-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LiLiQ-R-1.1.json", - "referenceNumber": 71, - "name": "Licence Libre du Québec – Réciprocité version 1.1", - "licenseId": "LiLiQ-R-1.1", - "seeAlso": [ - "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/", - "http://opensource.org/licenses/LiLiQ-R-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.json", - "referenceNumber": 143, - "name": "Licence Libre du Québec – Réciprocité forte version 1.1", - "licenseId": "LiLiQ-Rplus-1.1", - "seeAlso": [ - "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/", - "http://opensource.org/licenses/LiLiQ-Rplus-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Linux-man-pages-1-para.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-1-para.json", - "referenceNumber": 279, - "name": "Linux man-pages - 1 paragraph", - "licenseId": "Linux-man-pages-1-para", - "seeAlso": [ - "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/getcpu.2#n4" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft.json", - "referenceNumber": 286, - "name": "Linux man-pages Copyleft", - "licenseId": "Linux-man-pages-copyleft", - "seeAlso": [ - "https://www.kernel.org/doc/man-pages/licenses.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft-2-para.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft-2-para.json", - "referenceNumber": 136, - "name": "Linux man-pages Copyleft - 2 paragraphs", - "licenseId": "Linux-man-pages-copyleft-2-para", - "seeAlso": [ - "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/move_pages.2#n5", - "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/migrate_pages.2#n8" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft-var.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft-var.json", - "referenceNumber": 21, - "name": "Linux man-pages Copyleft Variant", - "licenseId": "Linux-man-pages-copyleft-var", - "seeAlso": [ - "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/set_mempolicy.2#n5" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Linux-OpenIB.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Linux-OpenIB.json", - "referenceNumber": 161, - "name": "Linux Kernel Variant of OpenIB.org license", - "licenseId": "Linux-OpenIB", - "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LOOP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LOOP.json", - "referenceNumber": 233, - "name": "Common Lisp LOOP License", - "licenseId": "LOOP", - "seeAlso": [ - "https://gitlab.com/embeddable-common-lisp/ecl/-/blob/develop/src/lsp/loop.lsp", - "http://git.savannah.gnu.org/cgit/gcl.git/tree/gcl/lsp/gcl_loop.lsp?h\u003dVersion_2_6_13pre", - "https://sourceforge.net/p/sbcl/sbcl/ci/master/tree/src/code/loop.lisp", - "https://github.com/cl-adams/adams/blob/master/LICENSE.md", - "https://github.com/blakemcbride/eclipse-lisp/blob/master/lisp/loop.lisp", - "https://gitlab.common-lisp.net/cmucl/cmucl/-/blob/master/src/code/loop.lisp" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LPD-document.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPD-document.json", - "referenceNumber": 294, - "name": "LPD Documentation License", - "licenseId": "LPD-document", - "seeAlso": [ - "https://github.com/Cyan4973/xxHash/blob/dev/doc/xxhash_spec.md", - "https://www.ietf.org/rfc/rfc1952.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPL-1.0.json", - "referenceNumber": 390, - "name": "Lucent Public License Version 1.0", - "licenseId": "LPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/LPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/LPL-1.02.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPL-1.02.json", - "referenceNumber": 459, - "name": "Lucent Public License v1.02", - "licenseId": "LPL-1.02", - "seeAlso": [ - "http://plan9.bell-labs.com/plan9/license.html", - "https://opensource.org/licenses/LPL-1.02" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LPPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPPL-1.0.json", - "referenceNumber": 183, - "name": "LaTeX Project Public License v1.0", - "licenseId": "LPPL-1.0", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-0.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LPPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPPL-1.1.json", - "referenceNumber": 408, - "name": "LaTeX Project Public License v1.1", - "licenseId": "LPPL-1.1", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LPPL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPPL-1.2.json", - "referenceNumber": 24, - "name": "LaTeX Project Public License v1.2", - "licenseId": "LPPL-1.2", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-2.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LPPL-1.3a.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPPL-1.3a.json", - "referenceNumber": 366, - "name": "LaTeX Project Public License v1.3a", - "licenseId": "LPPL-1.3a", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-3a.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/LPPL-1.3c.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LPPL-1.3c.json", - "referenceNumber": 396, - "name": "LaTeX Project Public License v1.3c", - "licenseId": "LPPL-1.3c", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-3c.txt", - "https://opensource.org/licenses/LPPL-1.3c" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/lsof.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/lsof.json", - "referenceNumber": 403, - "name": "lsof License", - "licenseId": "lsof", - "seeAlso": [ - "https://github.com/lsof-org/lsof/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Lucida-Bitmap-Fonts.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Lucida-Bitmap-Fonts.json", - "referenceNumber": 588, - "name": "Lucida Bitmap Fonts License", - "licenseId": "Lucida-Bitmap-Fonts", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/font/bh-100dpi/-/blob/master/COPYING?ref_type\u003dheads" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LZMA-SDK-9.11-to-9.20.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LZMA-SDK-9.11-to-9.20.json", - "referenceNumber": 539, - "name": "LZMA SDK License (versions 9.11 to 9.20)", - "licenseId": "LZMA-SDK-9.11-to-9.20", - "seeAlso": [ - "https://www.7-zip.org/sdk.html", - "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/LZMA-SDK-9.22.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/LZMA-SDK-9.22.json", - "referenceNumber": 497, - "name": "LZMA SDK License (versions 9.22 and beyond)", - "licenseId": "LZMA-SDK-9.22", - "seeAlso": [ - "https://www.7-zip.org/sdk.html", - "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/magaz.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/magaz.json", - "referenceNumber": 380, - "name": "magaz License", - "licenseId": "magaz", - "seeAlso": [ - "https://mirrors.nic.cz/tex-archive/macros/latex/contrib/magaz/magaz.tex" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/mailprio.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/mailprio.json", - "referenceNumber": 339, - "name": "mailprio License", - "licenseId": "mailprio", - "seeAlso": [ - "https://fossies.org/linux/sendmail/contrib/mailprio" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MakeIndex.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MakeIndex.json", - "referenceNumber": 404, - "name": "MakeIndex License", - "licenseId": "MakeIndex", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MakeIndex" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Martin-Birgmeier.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Martin-Birgmeier.json", - "referenceNumber": 2, - "name": "Martin Birgmeier License", - "licenseId": "Martin-Birgmeier", - "seeAlso": [ - "https://github.com/Perl/perl5/blob/blead/util.c#L6136" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/McPhee-slideshow.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/McPhee-slideshow.json", - "referenceNumber": 107, - "name": "McPhee Slideshow License", - "licenseId": "McPhee-slideshow", - "seeAlso": [ - "https://mirror.las.iastate.edu/tex-archive/graphics/metapost/contrib/macros/slideshow/slideshow.mp" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/metamail.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/metamail.json", - "referenceNumber": 519, - "name": "metamail License", - "licenseId": "metamail", - "seeAlso": [ - "https://github.com/Dual-Life/mime-base64/blob/master/Base64.xs#L12" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Minpack.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Minpack.json", - "referenceNumber": 621, - "name": "Minpack License", - "licenseId": "Minpack", - "seeAlso": [ - "http://www.netlib.org/minpack/disclaimer", - "https://gitlab.com/libeigen/eigen/-/blob/master/COPYING.MINPACK" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MirOS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MirOS.json", - "referenceNumber": 516, - "name": "The MirOS Licence", - "licenseId": "MirOS", - "seeAlso": [ - "https://opensource.org/licenses/MirOS" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/MIT.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT.json", - "referenceNumber": 292, - "name": "MIT License", - "licenseId": "MIT", - "seeAlso": [ - "https://opensource.org/license/mit/" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/MIT-0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-0.json", - "referenceNumber": 83, - "name": "MIT No Attribution", - "licenseId": "MIT-0", - "seeAlso": [ - "https://github.com/aws/mit-0", - "https://romanrm.net/mit-zero", - "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/MIT-advertising.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-advertising.json", - "referenceNumber": 317, - "name": "Enlightenment License (e16)", - "licenseId": "MIT-advertising", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-CMU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-CMU.json", - "referenceNumber": 382, - "name": "CMU License", - "licenseId": "MIT-CMU", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style", - "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-enna.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-enna.json", - "referenceNumber": 256, - "name": "enna License", - "licenseId": "MIT-enna", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#enna" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-feh.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-feh.json", - "referenceNumber": 231, - "name": "feh License", - "licenseId": "MIT-feh", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#feh" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-Festival.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-Festival.json", - "referenceNumber": 235, - "name": "MIT Festival Variant", - "licenseId": "MIT-Festival", - "seeAlso": [ - "https://github.com/festvox/flite/blob/master/COPYING", - "https://github.com/festvox/speech_tools/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-Modern-Variant.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-Modern-Variant.json", - "referenceNumber": 34, - "name": "MIT License Modern Variant", - "licenseId": "MIT-Modern-Variant", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:MIT#Modern_Variants", - "https://ptolemy.berkeley.edu/copyright.htm", - "https://pirlwww.lpl.arizona.edu/resources/guide/software/PerlTk/Tixlic.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/MIT-open-group.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-open-group.json", - "referenceNumber": 460, - "name": "MIT Open Group variant", - "licenseId": "MIT-open-group", - "seeAlso": [ - "https://gitlab.freedesktop.org/xorg/app/iceauth/-/blob/master/COPYING", - "https://gitlab.freedesktop.org/xorg/app/xvinfo/-/blob/master/COPYING", - "https://gitlab.freedesktop.org/xorg/app/xsetroot/-/blob/master/COPYING", - "https://gitlab.freedesktop.org/xorg/app/xauth/-/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-testregex.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-testregex.json", - "referenceNumber": 32, - "name": "MIT testregex Variant", - "licenseId": "MIT-testregex", - "seeAlso": [ - "https://github.com/dotnet/runtime/blob/55e1ac7c07df62c4108d4acedf78f77574470ce5/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/AttRegexTests.cs#L12-L28" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MIT-Wu.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MIT-Wu.json", - "referenceNumber": 320, - "name": "MIT Tom Wu Variant", - "licenseId": "MIT-Wu", - "seeAlso": [ - "https://github.com/chromium/octane/blob/master/crypto.js" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MITNFA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MITNFA.json", - "referenceNumber": 534, - "name": "MIT +no-false-attribs license", - "licenseId": "MITNFA", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MITNFA" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MMIXware.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MMIXware.json", - "referenceNumber": 197, - "name": "MMIXware License", - "licenseId": "MMIXware", - "seeAlso": [ - "https://gitlab.lrz.de/mmix/mmixware/-/blob/master/boilerplate.w" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Motosoto.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Motosoto.json", - "referenceNumber": 439, - "name": "Motosoto License", - "licenseId": "Motosoto", - "seeAlso": [ - "https://opensource.org/licenses/Motosoto" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/MPEG-SSG.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MPEG-SSG.json", - "referenceNumber": 169, - "name": "MPEG Software Simulation", - "licenseId": "MPEG-SSG", - "seeAlso": [ - "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/ppm/ppmtompeg/jrevdct.c#l1189" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/mpi-permissive.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/mpi-permissive.json", - "referenceNumber": 65, - "name": "mpi Permissive License", - "licenseId": "mpi-permissive", - "seeAlso": [ - "https://sources.debian.org/src/openmpi/4.1.0-10/ompi/debuggers/msgq_interface.h/?hl\u003d19#L19" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/mpich2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/mpich2.json", - "referenceNumber": 189, - "name": "mpich2 License", - "licenseId": "mpich2", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MPL-1.0.json", - "referenceNumber": 127, - "name": "Mozilla Public License 1.0", - "licenseId": "MPL-1.0", - "seeAlso": [ - "http://www.mozilla.org/MPL/MPL-1.0.html", - "https://opensource.org/licenses/MPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/MPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MPL-1.1.json", - "referenceNumber": 482, - "name": "Mozilla Public License 1.1", - "licenseId": "MPL-1.1", - "seeAlso": [ - "http://www.mozilla.org/MPL/MPL-1.1.html", - "https://opensource.org/licenses/MPL-1.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/MPL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MPL-2.0.json", - "referenceNumber": 342, - "name": "Mozilla Public License 2.0", - "licenseId": "MPL-2.0", - "seeAlso": [ - "https://www.mozilla.org/MPL/2.0/", - "https://opensource.org/licenses/MPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json", - "referenceNumber": 463, - "name": "Mozilla Public License 2.0 (no copyleft exception)", - "licenseId": "MPL-2.0-no-copyleft-exception", - "seeAlso": [ - "https://www.mozilla.org/MPL/2.0/", - "https://opensource.org/licenses/MPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/mplus.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/mplus.json", - "referenceNumber": 436, - "name": "mplus Font License", - "licenseId": "mplus", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:Mplus?rd\u003dLicensing/mplus" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MS-LPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MS-LPL.json", - "referenceNumber": 550, - "name": "Microsoft Limited Public License", - "licenseId": "MS-LPL", - "seeAlso": [ - "https://www.openhub.net/licenses/mslpl", - "https://github.com/gabegundy/atlserver/blob/master/License.txt", - "https://en.wikipedia.org/wiki/Shared_Source_Initiative#Microsoft_Limited_Public_License_(Ms-LPL)" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MS-PL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MS-PL.json", - "referenceNumber": 215, - "name": "Microsoft Public License", - "licenseId": "MS-PL", - "seeAlso": [ - "http://www.microsoft.com/opensource/licenses.mspx", - "https://opensource.org/licenses/MS-PL" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/MS-RL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MS-RL.json", - "referenceNumber": 190, - "name": "Microsoft Reciprocal License", - "licenseId": "MS-RL", - "seeAlso": [ - "http://www.microsoft.com/opensource/licenses.mspx", - "https://opensource.org/licenses/MS-RL" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/MTLL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MTLL.json", - "referenceNumber": 26, - "name": "Matrix Template Library License", - "licenseId": "MTLL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MulanPSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MulanPSL-1.0.json", - "referenceNumber": 555, - "name": "Mulan Permissive Software License, Version 1", - "licenseId": "MulanPSL-1.0", - "seeAlso": [ - "https://license.coscl.org.cn/MulanPSL/", - "https://github.com/yuwenlong/longphp/blob/25dfb70cc2a466dc4bb55ba30901cbce08d164b5/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/MulanPSL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/MulanPSL-2.0.json", - "referenceNumber": 376, - "name": "Mulan Permissive Software License, Version 2", - "licenseId": "MulanPSL-2.0", - "seeAlso": [ - "https://license.coscl.org.cn/MulanPSL2" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Multics.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Multics.json", - "referenceNumber": 613, - "name": "Multics License", - "licenseId": "Multics", - "seeAlso": [ - "https://opensource.org/licenses/Multics" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Mup.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Mup.json", - "referenceNumber": 184, - "name": "Mup License", - "licenseId": "Mup", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Mup" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NAIST-2003.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NAIST-2003.json", - "referenceNumber": 473, - "name": "Nara Institute of Science and Technology License (2003)", - "licenseId": "NAIST-2003", - "seeAlso": [ - "https://enterprise.dejacode.com/licenses/public/naist-2003/#license-text", - "https://github.com/nodejs/node/blob/4a19cc8947b1bba2b2d27816ec3d0edf9b28e503/LICENSE#L343" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NASA-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NASA-1.3.json", - "referenceNumber": 328, - "name": "NASA Open Source Agreement 1.3", - "licenseId": "NASA-1.3", - "seeAlso": [ - "http://ti.arc.nasa.gov/opensource/nosa/", - "https://opensource.org/licenses/NASA-1.3" - ], - "isOsiApproved": true, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/Naumen.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Naumen.json", - "referenceNumber": 232, - "name": "Naumen Public License", - "licenseId": "Naumen", - "seeAlso": [ - "https://opensource.org/licenses/Naumen" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/NBPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NBPL-1.0.json", - "referenceNumber": 321, - "name": "Net Boolean Public License v1", - "licenseId": "NBPL-1.0", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NCGL-UK-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NCGL-UK-2.0.json", - "referenceNumber": 80, - "name": "Non-Commercial Government Licence", - "licenseId": "NCGL-UK-2.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/non-commercial-government-licence/version/2/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NCSA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NCSA.json", - "referenceNumber": 7, - "name": "University of Illinois/NCSA Open Source License", - "licenseId": "NCSA", - "seeAlso": [ - "http://otm.illinois.edu/uiuc_openSource", - "https://opensource.org/licenses/NCSA" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Net-SNMP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Net-SNMP.json", - "referenceNumber": 456, - "name": "Net-SNMP License", - "licenseId": "Net-SNMP", - "seeAlso": [ - "http://net-snmp.sourceforge.net/about/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NetCDF.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NetCDF.json", - "referenceNumber": 282, - "name": "NetCDF license", - "licenseId": "NetCDF", - "seeAlso": [ - "http://www.unidata.ucar.edu/software/netcdf/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Newsletr.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Newsletr.json", - "referenceNumber": 236, - "name": "Newsletr License", - "licenseId": "Newsletr", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Newsletr" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NGPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NGPL.json", - "referenceNumber": 536, - "name": "Nethack General Public License", - "licenseId": "NGPL", - "seeAlso": [ - "https://opensource.org/licenses/NGPL" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/NICTA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NICTA-1.0.json", - "referenceNumber": 444, - "name": "NICTA Public Software License, Version 1.0", - "licenseId": "NICTA-1.0", - "seeAlso": [ - "https://opensource.apple.com/source/mDNSResponder/mDNSResponder-320.10/mDNSPosix/nss_ReadMe.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NIST-PD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NIST-PD.json", - "referenceNumber": 250, - "name": "NIST Public Domain Notice", - "licenseId": "NIST-PD", - "seeAlso": [ - "https://github.com/tcheneau/simpleRPL/blob/e645e69e38dd4e3ccfeceb2db8cba05b7c2e0cd3/LICENSE.txt", - "https://github.com/tcheneau/Routing/blob/f09f46fcfe636107f22f2c98348188a65a135d98/README.md" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NIST-PD-fallback.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NIST-PD-fallback.json", - "referenceNumber": 186, - "name": "NIST Public Domain Notice with license fallback", - "licenseId": "NIST-PD-fallback", - "seeAlso": [ - "https://github.com/usnistgov/jsip/blob/59700e6926cbe96c5cdae897d9a7d2656b42abe3/LICENSE", - "https://github.com/usnistgov/fipy/blob/86aaa5c2ba2c6f1be19593c5986071cf6568cc34/LICENSE.rst" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NIST-Software.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NIST-Software.json", - "referenceNumber": 33, - "name": "NIST Software License", - "licenseId": "NIST-Software", - "seeAlso": [ - "https://github.com/open-quantum-safe/liboqs/blob/40b01fdbb270f8614fde30e65d30e9da18c02393/src/common/rand/rand_nist.c#L1-L15" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NLOD-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NLOD-1.0.json", - "referenceNumber": 119, - "name": "Norwegian Licence for Open Government Data (NLOD) 1.0", - "licenseId": "NLOD-1.0", - "seeAlso": [ - "http://data.norge.no/nlod/en/1.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NLOD-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NLOD-2.0.json", - "referenceNumber": 601, - "name": "Norwegian Licence for Open Government Data (NLOD) 2.0", - "licenseId": "NLOD-2.0", - "seeAlso": [ - "http://data.norge.no/nlod/en/2.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NLPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NLPL.json", - "referenceNumber": 594, - "name": "No Limit Public License", - "licenseId": "NLPL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/NLPL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Nokia.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Nokia.json", - "referenceNumber": 574, - "name": "Nokia Open Source License", - "licenseId": "Nokia", - "seeAlso": [ - "https://opensource.org/licenses/nokia" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/NOSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NOSL.json", - "referenceNumber": 160, - "name": "Netizen Open Source License", - "licenseId": "NOSL", - "seeAlso": [ - "http://bits.netizen.com.au/licenses/NOSL/nosl.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Noweb.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Noweb.json", - "referenceNumber": 180, - "name": "Noweb License", - "licenseId": "Noweb", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Noweb" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NPL-1.0.json", - "referenceNumber": 388, - "name": "Netscape Public License v1.0", - "licenseId": "NPL-1.0", - "seeAlso": [ - "http://www.mozilla.org/MPL/NPL/1.0/" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/NPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NPL-1.1.json", - "referenceNumber": 598, - "name": "Netscape Public License v1.1", - "licenseId": "NPL-1.1", - "seeAlso": [ - "http://www.mozilla.org/MPL/NPL/1.1/" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/NPOSL-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NPOSL-3.0.json", - "referenceNumber": 620, - "name": "Non-Profit Open Software License 3.0", - "licenseId": "NPOSL-3.0", - "seeAlso": [ - "https://opensource.org/licenses/NOSL3.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/NRL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NRL.json", - "referenceNumber": 55, - "name": "NRL License", - "licenseId": "NRL", - "seeAlso": [ - "http://web.mit.edu/network/isakmp/nrllicense.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/NTP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NTP.json", - "referenceNumber": 19, - "name": "NTP License", - "licenseId": "NTP", - "seeAlso": [ - "https://opensource.org/licenses/NTP" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/NTP-0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/NTP-0.json", - "referenceNumber": 25, - "name": "NTP No Attribution", - "licenseId": "NTP-0", - "seeAlso": [ - "https://github.com/tytso/e2fsprogs/blob/master/lib/et/et_name.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Nunit.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/Nunit.json", - "referenceNumber": 589, - "name": "Nunit License", - "licenseId": "Nunit", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Nunit" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/O-UDA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/O-UDA-1.0.json", - "referenceNumber": 238, - "name": "Open Use of Data Agreement v1.0", - "licenseId": "O-UDA-1.0", - "seeAlso": [ - "https://github.com/microsoft/Open-Use-of-Data-Agreement/blob/v1.0/O-UDA-1.0.md", - "https://cdla.dev/open-use-of-data-agreement-v1-0/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OCCT-PL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OCCT-PL.json", - "referenceNumber": 149, - "name": "Open CASCADE Technology Public License", - "licenseId": "OCCT-PL", - "seeAlso": [ - "http://www.opencascade.com/content/occt-public-license" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OCLC-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OCLC-2.0.json", - "referenceNumber": 417, - "name": "OCLC Research Public License 2.0", - "licenseId": "OCLC-2.0", - "seeAlso": [ - "http://www.oclc.org/research/activities/software/license/v2final.htm", - "https://opensource.org/licenses/OCLC-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/ODbL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ODbL-1.0.json", - "referenceNumber": 105, - "name": "Open Data Commons Open Database License v1.0", - "licenseId": "ODbL-1.0", - "seeAlso": [ - "http://www.opendatacommons.org/licenses/odbl/1.0/", - "https://opendatacommons.org/licenses/odbl/1-0/" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ODC-By-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ODC-By-1.0.json", - "referenceNumber": 493, - "name": "Open Data Commons Attribution License v1.0", - "licenseId": "ODC-By-1.0", - "seeAlso": [ - "https://opendatacommons.org/licenses/by/1.0/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OFFIS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFFIS.json", - "referenceNumber": 84, - "name": "OFFIS License", - "licenseId": "OFFIS", - "seeAlso": [ - "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/dicom/README" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OFL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFL-1.0.json", - "referenceNumber": 56, - "name": "SIL Open Font License 1.0", - "licenseId": "OFL-1.0", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OFL-1.0-no-RFN.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFL-1.0-no-RFN.json", - "referenceNumber": 394, - "name": "SIL Open Font License 1.0 with no Reserved Font Name", - "licenseId": "OFL-1.0-no-RFN", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OFL-1.0-RFN.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFL-1.0-RFN.json", - "referenceNumber": 532, - "name": "SIL Open Font License 1.0 with Reserved Font Name", - "licenseId": "OFL-1.0-RFN", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OFL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFL-1.1.json", - "referenceNumber": 337, - "name": "SIL Open Font License 1.1", - "licenseId": "OFL-1.1", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", - "https://opensource.org/licenses/OFL-1.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OFL-1.1-no-RFN.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFL-1.1-no-RFN.json", - "referenceNumber": 507, - "name": "SIL Open Font License 1.1 with no Reserved Font Name", - "licenseId": "OFL-1.1-no-RFN", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", - "https://opensource.org/licenses/OFL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/OFL-1.1-RFN.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OFL-1.1-RFN.json", - "referenceNumber": 578, - "name": "SIL Open Font License 1.1 with Reserved Font Name", - "licenseId": "OFL-1.1-RFN", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", - "https://opensource.org/licenses/OFL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/OGC-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGC-1.0.json", - "referenceNumber": 543, - "name": "OGC Software License, Version 1.0", - "licenseId": "OGC-1.0", - "seeAlso": [ - "https://www.ogc.org/ogc/software/1.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OGDL-Taiwan-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGDL-Taiwan-1.0.json", - "referenceNumber": 23, - "name": "Taiwan Open Government Data License, version 1.0", - "licenseId": "OGDL-Taiwan-1.0", - "seeAlso": [ - "https://data.gov.tw/license" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OGL-Canada-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGL-Canada-2.0.json", - "referenceNumber": 210, - "name": "Open Government Licence - Canada", - "licenseId": "OGL-Canada-2.0", - "seeAlso": [ - "https://open.canada.ca/en/open-government-licence-canada" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OGL-UK-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGL-UK-1.0.json", - "referenceNumber": 205, - "name": "Open Government Licence v1.0", - "licenseId": "OGL-UK-1.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OGL-UK-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGL-UK-2.0.json", - "referenceNumber": 386, - "name": "Open Government Licence v2.0", - "licenseId": "OGL-UK-2.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OGL-UK-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGL-UK-3.0.json", - "referenceNumber": 415, - "name": "Open Government Licence v3.0", - "licenseId": "OGL-UK-3.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OGTSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OGTSL.json", - "referenceNumber": 544, - "name": "Open Group Test Suite License", - "licenseId": "OGTSL", - "seeAlso": [ - "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt", - "https://opensource.org/licenses/OGTSL" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/OLDAP-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-1.1.json", - "referenceNumber": 377, - "name": "Open LDAP Public License v1.1", - "licenseId": "OLDAP-1.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-1.2.json", - "referenceNumber": 548, - "name": "Open LDAP Public License v1.2", - "licenseId": "OLDAP-1.2", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d42b0383c50c299977b5893ee695cf4e486fb0dc7" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-1.3.json", - "referenceNumber": 455, - "name": "Open LDAP Public License v1.3", - "licenseId": "OLDAP-1.3", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-1.4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-1.4.json", - "referenceNumber": 38, - "name": "Open LDAP Public License v1.4", - "licenseId": "OLDAP-1.4", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.0.json", - "referenceNumber": 234, - "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", - "licenseId": "OLDAP-2.0", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.0.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.0.1.json", - "referenceNumber": 397, - "name": "Open LDAP Public License v2.0.1", - "licenseId": "OLDAP-2.0.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.1.json", - "referenceNumber": 39, - "name": "Open LDAP Public License v2.1", - "licenseId": "OLDAP-2.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.json", - "referenceNumber": 142, - "name": "Open LDAP Public License v2.2", - "licenseId": "OLDAP-2.2", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.1.json", - "referenceNumber": 583, - "name": "Open LDAP Public License v2.2.1", - "licenseId": "OLDAP-2.2.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.2.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.2.json", - "referenceNumber": 153, - "name": "Open LDAP Public License 2.2.2", - "licenseId": "OLDAP-2.2.2", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.3.json", - "referenceNumber": 590, - "name": "Open LDAP Public License v2.3", - "licenseId": "OLDAP-2.3", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.4.json", - "referenceNumber": 584, - "name": "Open LDAP Public License v2.4", - "licenseId": "OLDAP-2.4", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.5.json", - "referenceNumber": 204, - "name": "Open LDAP Public License v2.5", - "licenseId": "OLDAP-2.5", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.6.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.6.json", - "referenceNumber": 604, - "name": "Open LDAP Public License v2.6", - "licenseId": "OLDAP-2.6", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.7.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.7.json", - "referenceNumber": 125, - "name": "Open LDAP Public License v2.7", - "licenseId": "OLDAP-2.7", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OLDAP-2.8.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLDAP-2.8.json", - "referenceNumber": 528, - "name": "Open LDAP Public License v2.8", - "licenseId": "OLDAP-2.8", - "seeAlso": [ - "http://www.openldap.org/software/release/license.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/OLFL-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OLFL-1.3.json", - "referenceNumber": 63, - "name": "Open Logistics Foundation License Version 1.3", - "licenseId": "OLFL-1.3", - "seeAlso": [ - "https://openlogisticsfoundation.org/licenses/", - "https://opensource.org/license/olfl-1-3/" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/OML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OML.json", - "referenceNumber": 199, - "name": "Open Market License", - "licenseId": "OML", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Open_Market_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OpenPBS-2.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OpenPBS-2.3.json", - "referenceNumber": 45, - "name": "OpenPBS v2.3 Software License", - "licenseId": "OpenPBS-2.3", - "seeAlso": [ - "https://github.com/adaptivecomputing/torque/blob/master/PBS_License.txt", - "https://www.mcs.anl.gov/research/projects/openpbs/PBS_License.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OpenSSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OpenSSL.json", - "referenceNumber": 508, - "name": "OpenSSL License", - "licenseId": "OpenSSL", - "seeAlso": [ - "http://www.openssl.org/source/license.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OpenSSL-standalone.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OpenSSL-standalone.json", - "referenceNumber": 542, - "name": "OpenSSL License - standalone", - "licenseId": "OpenSSL-standalone", - "seeAlso": [ - "https://library.netapp.com/ecm/ecm_download_file/ECMP1196395", - "https://hstechdocs.helpsystems.com/manuals/globalscape/archive/cuteftp6/open_ssl_license_agreement.htm" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OPL-1.0.json", - "referenceNumber": 411, - "name": "Open Public License v1.0", - "licenseId": "OPL-1.0", - "seeAlso": [ - "http://old.koalateam.com/jackaroo/OPL_1_0.TXT", - "https://fedoraproject.org/wiki/Licensing/Open_Public_License" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/OPL-UK-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OPL-UK-3.0.json", - "referenceNumber": 378, - "name": "United Kingdom Open Parliament Licence v3.0", - "licenseId": "OPL-UK-3.0", - "seeAlso": [ - "https://www.parliament.uk/site-information/copyright-parliament/open-parliament-licence/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OPUBL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OPUBL-1.0.json", - "referenceNumber": 479, - "name": "Open Publication License v1.0", - "licenseId": "OPUBL-1.0", - "seeAlso": [ - "http://opencontent.org/openpub/", - "https://www.debian.org/opl", - "https://www.ctan.org/license/opl" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/OSET-PL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OSET-PL-2.1.json", - "referenceNumber": 244, - "name": "OSET Public License version 2.1", - "licenseId": "OSET-PL-2.1", - "seeAlso": [ - "http://www.osetfoundation.org/public-license", - "https://opensource.org/licenses/OPL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/OSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OSL-1.0.json", - "referenceNumber": 281, - "name": "Open Software License 1.0", - "licenseId": "OSL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/OSL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OSL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OSL-1.1.json", - "referenceNumber": 146, - "name": "Open Software License 1.1", - "licenseId": "OSL-1.1", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/OSL1.1" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OSL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OSL-2.0.json", - "referenceNumber": 290, - "name": "Open Software License 2.0", - "licenseId": "OSL-2.0", - "seeAlso": [ - "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OSL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OSL-2.1.json", - "referenceNumber": 375, - "name": "Open Software License 2.1", - "licenseId": "OSL-2.1", - "seeAlso": [ - "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm", - "https://opensource.org/licenses/OSL-2.1" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/OSL-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/OSL-3.0.json", - "referenceNumber": 122, - "name": "Open Software License 3.0", - "licenseId": "OSL-3.0", - "seeAlso": [ - "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm", - "https://opensource.org/licenses/OSL-3.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/PADL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PADL.json", - "referenceNumber": 347, - "name": "PADL License", - "licenseId": "PADL", - "seeAlso": [ - "https://git.openldap.org/openldap/openldap/-/blob/master/libraries/libldap/os-local.c?ref_type\u003dheads#L19-23" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Parity-6.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Parity-6.0.0.json", - "referenceNumber": 241, - "name": "The Parity Public License 6.0.0", - "licenseId": "Parity-6.0.0", - "seeAlso": [ - "https://paritylicense.com/versions/6.0.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Parity-7.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Parity-7.0.0.json", - "referenceNumber": 440, - "name": "The Parity Public License 7.0.0", - "licenseId": "Parity-7.0.0", - "seeAlso": [ - "https://paritylicense.com/versions/7.0.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/PDDL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PDDL-1.0.json", - "referenceNumber": 208, - "name": "Open Data Commons Public Domain Dedication \u0026 License 1.0", - "licenseId": "PDDL-1.0", - "seeAlso": [ - "http://opendatacommons.org/licenses/pddl/1.0/", - "https://opendatacommons.org/licenses/pddl/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/PHP-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PHP-3.0.json", - "referenceNumber": 334, - "name": "PHP License v3.0", - "licenseId": "PHP-3.0", - "seeAlso": [ - "http://www.php.net/license/3_0.txt", - "https://opensource.org/licenses/PHP-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/PHP-3.01.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PHP-3.01.json", - "referenceNumber": 447, - "name": "PHP License v3.01", - "licenseId": "PHP-3.01", - "seeAlso": [ - "http://www.php.net/license/3_01.txt" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Pixar.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Pixar.json", - "referenceNumber": 520, - "name": "Pixar License", - "licenseId": "Pixar", - "seeAlso": [ - "https://github.com/PixarAnimationStudios/OpenSubdiv/raw/v3_5_0/LICENSE.txt", - "https://graphics.pixar.com/opensubdiv/docs/license.html", - "https://github.com/PixarAnimationStudios/OpenSubdiv/blob/v3_5_0/opensubdiv/version.cpp#L2-L22" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Plexus.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Plexus.json", - "referenceNumber": 135, - "name": "Plexus Classworlds License", - "licenseId": "Plexus", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/pnmstitch.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/pnmstitch.json", - "referenceNumber": 563, - "name": "pnmstitch License", - "licenseId": "pnmstitch", - "seeAlso": [ - "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/editor/pnmstitch.c#l2" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.json", - "referenceNumber": 297, - "name": "PolyForm Noncommercial License 1.0.0", - "licenseId": "PolyForm-Noncommercial-1.0.0", - "seeAlso": [ - "https://polyformproject.org/licenses/noncommercial/1.0.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.json", - "referenceNumber": 576, - "name": "PolyForm Small Business License 1.0.0", - "licenseId": "PolyForm-Small-Business-1.0.0", - "seeAlso": [ - "https://polyformproject.org/licenses/small-business/1.0.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/PostgreSQL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PostgreSQL.json", - "referenceNumber": 443, - "name": "PostgreSQL License", - "licenseId": "PostgreSQL", - "seeAlso": [ - "http://www.postgresql.org/about/licence", - "https://opensource.org/licenses/PostgreSQL" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/PSF-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/PSF-2.0.json", - "referenceNumber": 510, - "name": "Python Software Foundation License 2.0", - "licenseId": "PSF-2.0", - "seeAlso": [ - "https://opensource.org/licenses/Python-2.0" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/psfrag.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/psfrag.json", - "referenceNumber": 99, - "name": "psfrag License", - "licenseId": "psfrag", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/psfrag" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/psutils.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/psutils.json", - "referenceNumber": 242, - "name": "psutils License", - "licenseId": "psutils", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/psutils" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Python-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Python-2.0.json", - "referenceNumber": 57, - "name": "Python License 2.0", - "licenseId": "Python-2.0", - "seeAlso": [ - "https://opensource.org/licenses/Python-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Python-2.0.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Python-2.0.1.json", - "referenceNumber": 298, - "name": "Python License 2.0.1", - "licenseId": "Python-2.0.1", - "seeAlso": [ - "https://www.python.org/download/releases/2.0.1/license/", - "https://docs.python.org/3/license.html", - "https://github.com/python/cpython/blob/main/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/python-ldap.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/python-ldap.json", - "referenceNumber": 193, - "name": "Python ldap License", - "licenseId": "python-ldap", - "seeAlso": [ - "https://github.com/python-ldap/python-ldap/blob/main/LICENCE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Qhull.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Qhull.json", - "referenceNumber": 577, - "name": "Qhull License", - "licenseId": "Qhull", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Qhull" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/QPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/QPL-1.0.json", - "referenceNumber": 240, - "name": "Q Public License 1.0", - "licenseId": "QPL-1.0", - "seeAlso": [ - "http://doc.qt.nokia.com/3.3/license.html", - "https://opensource.org/licenses/QPL-1.0", - "https://doc.qt.io/archives/3.3/license.html" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/QPL-1.0-INRIA-2004.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/QPL-1.0-INRIA-2004.json", - "referenceNumber": 431, - "name": "Q Public License 1.0 - INRIA 2004 variant", - "licenseId": "QPL-1.0-INRIA-2004", - "seeAlso": [ - "https://github.com/maranget/hevea/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/radvd.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/radvd.json", - "referenceNumber": 255, - "name": "radvd License", - "licenseId": "radvd", - "seeAlso": [ - "https://github.com/radvd-project/radvd/blob/master/COPYRIGHT" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Rdisc.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Rdisc.json", - "referenceNumber": 348, - "name": "Rdisc License", - "licenseId": "Rdisc", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Rdisc_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/RHeCos-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/RHeCos-1.1.json", - "referenceNumber": 470, - "name": "Red Hat eCos Public License v1.1", - "licenseId": "RHeCos-1.1", - "seeAlso": [ - "http://ecos.sourceware.org/old-license.html" - ], - "isOsiApproved": false, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/RPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/RPL-1.1.json", - "referenceNumber": 312, - "name": "Reciprocal Public License 1.1", - "licenseId": "RPL-1.1", - "seeAlso": [ - "https://opensource.org/licenses/RPL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/RPL-1.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/RPL-1.5.json", - "referenceNumber": 117, - "name": "Reciprocal Public License 1.5", - "licenseId": "RPL-1.5", - "seeAlso": [ - "https://opensource.org/licenses/RPL-1.5" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/RPSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/RPSL-1.0.json", - "referenceNumber": 512, - "name": "RealNetworks Public Source License v1.0", - "licenseId": "RPSL-1.0", - "seeAlso": [ - "https://helixcommunity.org/content/rpsl", - "https://opensource.org/licenses/RPSL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/RSA-MD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/RSA-MD.json", - "referenceNumber": 96, - "name": "RSA Message-Digest License", - "licenseId": "RSA-MD", - "seeAlso": [ - "http://www.faqs.org/rfcs/rfc1321.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/RSCPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/RSCPL.json", - "referenceNumber": 341, - "name": "Ricoh Source Code Public License", - "licenseId": "RSCPL", - "seeAlso": [ - "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml", - "https://opensource.org/licenses/RSCPL" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Ruby.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Ruby.json", - "referenceNumber": 602, - "name": "Ruby License", - "licenseId": "Ruby", - "seeAlso": [ - "https://www.ruby-lang.org/en/about/license.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/SAX-PD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SAX-PD.json", - "referenceNumber": 178, - "name": "Sax Public Domain Notice", - "licenseId": "SAX-PD", - "seeAlso": [ - "http://www.saxproject.org/copying.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SAX-PD-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SAX-PD-2.0.json", - "referenceNumber": 567, - "name": "Sax Public Domain Notice 2.0", - "licenseId": "SAX-PD-2.0", - "seeAlso": [ - "http://www.saxproject.org/copying.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Saxpath.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Saxpath.json", - "referenceNumber": 14, - "name": "Saxpath License", - "licenseId": "Saxpath", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Saxpath_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SCEA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SCEA.json", - "referenceNumber": 429, - "name": "SCEA Shared Source License", - "licenseId": "SCEA", - "seeAlso": [ - "http://research.scea.com/scea_shared_source_license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SchemeReport.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SchemeReport.json", - "referenceNumber": 263, - "name": "Scheme Language Report License", - "licenseId": "SchemeReport", - "seeAlso": [], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Sendmail.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Sendmail.json", - "referenceNumber": 581, - "name": "Sendmail License", - "licenseId": "Sendmail", - "seeAlso": [ - "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf", - "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Sendmail-8.23.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Sendmail-8.23.json", - "referenceNumber": 133, - "name": "Sendmail License 8.23", - "licenseId": "Sendmail-8.23", - "seeAlso": [ - "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf", - "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SGI-B-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SGI-B-1.0.json", - "referenceNumber": 187, - "name": "SGI Free Software License B v1.0", - "licenseId": "SGI-B-1.0", - "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SGI-B-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SGI-B-1.1.json", - "referenceNumber": 147, - "name": "SGI Free Software License B v1.1", - "licenseId": "SGI-B-1.1", - "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SGI-B-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SGI-B-2.0.json", - "referenceNumber": 285, - "name": "SGI Free Software License B v2.0", - "licenseId": "SGI-B-2.0", - "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/SGI-OpenGL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SGI-OpenGL.json", - "referenceNumber": 207, - "name": "SGI OpenGL License", - "licenseId": "SGI-OpenGL", - "seeAlso": [ - "https://gitlab.freedesktop.org/mesa/glw/-/blob/master/README?ref_type\u003dheads" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SGP4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SGP4.json", - "referenceNumber": 467, - "name": "SGP4 Permission Notice", - "licenseId": "SGP4", - "seeAlso": [ - "https://celestrak.org/publications/AIAA/2006-6753/faq.php" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SHL-0.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SHL-0.5.json", - "referenceNumber": 568, - "name": "Solderpad Hardware License v0.5", - "licenseId": "SHL-0.5", - "seeAlso": [ - "https://solderpad.org/licenses/SHL-0.5/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SHL-0.51.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SHL-0.51.json", - "referenceNumber": 150, - "name": "Solderpad Hardware License, Version 0.51", - "licenseId": "SHL-0.51", - "seeAlso": [ - "https://solderpad.org/licenses/SHL-0.51/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SimPL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SimPL-2.0.json", - "referenceNumber": 412, - "name": "Simple Public License 2.0", - "licenseId": "SimPL-2.0", - "seeAlso": [ - "https://opensource.org/licenses/SimPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/SISSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SISSL.json", - "referenceNumber": 201, - "name": "Sun Industry Standards Source License v1.1", - "licenseId": "SISSL", - "seeAlso": [ - "http://www.openoffice.org/licenses/sissl_license.html", - "https://opensource.org/licenses/SISSL" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/SISSL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SISSL-1.2.json", - "referenceNumber": 546, - "name": "Sun Industry Standards Source License v1.2", - "licenseId": "SISSL-1.2", - "seeAlso": [ - "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SL.json", - "referenceNumber": 131, - "name": "SL License", - "licenseId": "SL", - "seeAlso": [ - "https://github.com/mtoyoda/sl/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Sleepycat.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Sleepycat.json", - "referenceNumber": 333, - "name": "Sleepycat License", - "licenseId": "Sleepycat", - "seeAlso": [ - "https://opensource.org/licenses/Sleepycat" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/SMLNJ.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SMLNJ.json", - "referenceNumber": 95, - "name": "Standard ML of New Jersey License", - "licenseId": "SMLNJ", - "seeAlso": [ - "https://www.smlnj.org/license.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/SMPPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SMPPL.json", - "referenceNumber": 517, - "name": "Secure Messaging Protocol Public License", - "licenseId": "SMPPL", - "seeAlso": [ - "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SNIA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SNIA.json", - "referenceNumber": 480, - "name": "SNIA Public License 1.1", - "licenseId": "SNIA", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/snprintf.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/snprintf.json", - "referenceNumber": 43, - "name": "snprintf License", - "licenseId": "snprintf", - "seeAlso": [ - "https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bsd-snprintf.c#L2" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Soundex.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Soundex.json", - "referenceNumber": 338, - "name": "Soundex License", - "licenseId": "Soundex", - "seeAlso": [ - "https://metacpan.org/release/RJBS/Text-Soundex-3.05/source/Soundex.pm#L3-11" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Spencer-86.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Spencer-86.json", - "referenceNumber": 461, - "name": "Spencer License 86", - "licenseId": "Spencer-86", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Spencer-94.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Spencer-94.json", - "referenceNumber": 413, - "name": "Spencer License 94", - "licenseId": "Spencer-94", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License", - "https://metacpan.org/release/KNOK/File-MMagic-1.30/source/COPYING#L28" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Spencer-99.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Spencer-99.json", - "referenceNumber": 582, - "name": "Spencer License 99", - "licenseId": "Spencer-99", - "seeAlso": [ - "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SPL-1.0.json", - "referenceNumber": 359, - "name": "Sun Public License v1.0", - "licenseId": "SPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/SPL-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ssh-keyscan.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ssh-keyscan.json", - "referenceNumber": 483, - "name": "ssh-keyscan License", - "licenseId": "ssh-keyscan", - "seeAlso": [ - "https://github.com/openssh/openssh-portable/blob/master/LICENCE#L82" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SSH-OpenSSH.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SSH-OpenSSH.json", - "referenceNumber": 537, - "name": "SSH OpenSSH license", - "licenseId": "SSH-OpenSSH", - "seeAlso": [ - "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/LICENCE#L10" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SSH-short.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SSH-short.json", - "referenceNumber": 451, - "name": "SSH short notice", - "licenseId": "SSH-short", - "seeAlso": [ - "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/pathnames.h", - "http://web.mit.edu/kolya/.f/root/athena.mit.edu/sipb.mit.edu/project/openssh/OldFiles/src/openssh-2.9.9p2/ssh-add.1", - "https://joinup.ec.europa.eu/svn/lesoll/trunk/italc/lib/src/dsa_key.cpp" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SSLeay-standalone.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SSLeay-standalone.json", - "referenceNumber": 607, - "name": "SSLeay License - standalone", - "licenseId": "SSLeay-standalone", - "seeAlso": [ - "https://www.tq-group.com/filedownloads/files/software-license-conditions/OriginalSSLeay/OriginalSSLeay.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SSPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SSPL-1.0.json", - "referenceNumber": 599, - "name": "Server Side Public License, v 1", - "licenseId": "SSPL-1.0", - "seeAlso": [ - "https://www.mongodb.com/licensing/server-side-public-license" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/StandardML-NJ.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/StandardML-NJ.json", - "referenceNumber": 622, - "name": "Standard ML of New Jersey License", - "licenseId": "StandardML-NJ", - "seeAlso": [ - "https://www.smlnj.org/license.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/SugarCRM-1.1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SugarCRM-1.1.3.json", - "referenceNumber": 280, - "name": "SugarCRM Public License v1.1.3", - "licenseId": "SugarCRM-1.1.3", - "seeAlso": [ - "http://www.sugarcrm.com/crm/SPL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SunPro.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SunPro.json", - "referenceNumber": 49, - "name": "SunPro License", - "licenseId": "SunPro", - "seeAlso": [ - "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_acosh.c", - "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_lgammal.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/SWL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/SWL.json", - "referenceNumber": 407, - "name": "Scheme Widget Library (SWL) Software License Agreement", - "licenseId": "SWL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/SWL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/swrule.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/swrule.json", - "referenceNumber": 220, - "name": "swrule License", - "licenseId": "swrule", - "seeAlso": [ - "https://ctan.math.utah.edu/ctan/tex-archive/macros/generic/misc/swrule.sty" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Symlinks.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Symlinks.json", - "referenceNumber": 213, - "name": "Symlinks License", - "licenseId": "Symlinks", - "seeAlso": [ - "https://www.mail-archive.com/debian-bugs-rc@lists.debian.org/msg11494.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TAPR-OHL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TAPR-OHL-1.0.json", - "referenceNumber": 401, - "name": "TAPR Open Hardware License v1.0", - "licenseId": "TAPR-OHL-1.0", - "seeAlso": [ - "https://www.tapr.org/OHL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TCL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TCL.json", - "referenceNumber": 166, - "name": "TCL/TK License", - "licenseId": "TCL", - "seeAlso": [ - "http://www.tcl.tk/software/tcltk/license.html", - "https://fedoraproject.org/wiki/Licensing/TCL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TCP-wrappers.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TCP-wrappers.json", - "referenceNumber": 0, - "name": "TCP Wrappers License", - "licenseId": "TCP-wrappers", - "seeAlso": [ - "http://rc.quest.com/topics/openssh/license.php#tcpwrappers" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TermReadKey.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TermReadKey.json", - "referenceNumber": 214, - "name": "TermReadKey License", - "licenseId": "TermReadKey", - "seeAlso": [ - "https://github.com/jonathanstowe/TermReadKey/blob/master/README#L9-L10" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TGPPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TGPPL-1.0.json", - "referenceNumber": 185, - "name": "Transitive Grace Period Public Licence 1.0", - "licenseId": "TGPPL-1.0", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TGPPL", - "https://tahoe-lafs.org/trac/tahoe-lafs/browser/trunk/COPYING.TGPPL.rst" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TMate.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TMate.json", - "referenceNumber": 591, - "name": "TMate Open Source License", - "licenseId": "TMate", - "seeAlso": [ - "http://svnkit.com/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TORQUE-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TORQUE-1.1.json", - "referenceNumber": 422, - "name": "TORQUE v2.5+ Software License v1.1", - "licenseId": "TORQUE-1.1", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TOSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TOSL.json", - "referenceNumber": 12, - "name": "Trusster Open Source License", - "licenseId": "TOSL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TOSL" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TPDL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TPDL.json", - "referenceNumber": 575, - "name": "Time::ParseDate License", - "licenseId": "TPDL", - "seeAlso": [ - "https://metacpan.org/pod/Time::ParseDate#LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TPL-1.0.json", - "referenceNumber": 565, - "name": "THOR Public License 1.0", - "licenseId": "TPL-1.0", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:ThorPublicLicense" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TTWL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TTWL.json", - "referenceNumber": 111, - "name": "Text-Tabs+Wrap License", - "licenseId": "TTWL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TTWL", - "https://github.com/ap/Text-Tabs/blob/master/lib.modern/Text/Tabs.pm#L148" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TTYP0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TTYP0.json", - "referenceNumber": 225, - "name": "TTYP0 License", - "licenseId": "TTYP0", - "seeAlso": [ - "https://people.mpi-inf.mpg.de/~uwe/misc/uw-ttyp0/" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TU-Berlin-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TU-Berlin-1.0.json", - "referenceNumber": 362, - "name": "Technische Universitaet Berlin License 1.0", - "licenseId": "TU-Berlin-1.0", - "seeAlso": [ - "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/TU-Berlin-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/TU-Berlin-2.0.json", - "referenceNumber": 261, - "name": "Technische Universitaet Berlin License 2.0", - "licenseId": "TU-Berlin-2.0", - "seeAlso": [ - "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/UCAR.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/UCAR.json", - "referenceNumber": 93, - "name": "UCAR License", - "licenseId": "UCAR", - "seeAlso": [ - "https://github.com/Unidata/UDUNITS-2/blob/master/COPYRIGHT" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/UCL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/UCL-1.0.json", - "referenceNumber": 612, - "name": "Upstream Compatibility License v1.0", - "licenseId": "UCL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/UCL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/ulem.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ulem.json", - "referenceNumber": 481, - "name": "ulem License", - "licenseId": "ulem", - "seeAlso": [ - "https://mirrors.ctan.org/macros/latex/contrib/ulem/README" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Unicode-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Unicode-3.0.json", - "referenceNumber": 203, - "name": "Unicode License v3", - "licenseId": "Unicode-3.0", - "seeAlso": [ - "https://www.unicode.org/license.txt" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Unicode-DFS-2015.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Unicode-DFS-2015.json", - "referenceNumber": 273, - "name": "Unicode License Agreement - Data Files and Software (2015)", - "licenseId": "Unicode-DFS-2015", - "seeAlso": [ - "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Unicode-DFS-2016.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Unicode-DFS-2016.json", - "referenceNumber": 477, - "name": "Unicode License Agreement - Data Files and Software (2016)", - "licenseId": "Unicode-DFS-2016", - "seeAlso": [ - "https://www.unicode.org/license.txt", - "http://web.archive.org/web/20160823201924/http://www.unicode.org/copyright.html#License", - "http://www.unicode.org/copyright.html" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/Unicode-TOU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Unicode-TOU.json", - "referenceNumber": 36, - "name": "Unicode Terms of Use", - "licenseId": "Unicode-TOU", - "seeAlso": [ - "http://web.archive.org/web/20140704074106/http://www.unicode.org/copyright.html", - "http://www.unicode.org/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/UnixCrypt.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/UnixCrypt.json", - "referenceNumber": 353, - "name": "UnixCrypt License", - "licenseId": "UnixCrypt", - "seeAlso": [ - "https://foss.heptapod.net/python-libs/passlib/-/blob/branch/stable/LICENSE#L70", - "https://opensource.apple.com/source/JBoss/JBoss-737/jboss-all/jetty/src/main/org/mortbay/util/UnixCrypt.java.auto.html", - "https://archive.eclipse.org/jetty/8.0.1.v20110908/xref/org/eclipse/jetty/http/security/UnixCrypt.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Unlicense.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Unlicense.json", - "referenceNumber": 50, - "name": "The Unlicense", - "licenseId": "Unlicense", - "seeAlso": [ - "https://unlicense.org/" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/UPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/UPL-1.0.json", - "referenceNumber": 28, - "name": "Universal Permissive License v1.0", - "licenseId": "UPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/UPL" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/URT-RLE.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/URT-RLE.json", - "referenceNumber": 549, - "name": "Utah Raster Toolkit Run Length Encoded License", - "licenseId": "URT-RLE", - "seeAlso": [ - "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/other/pnmtorle.c", - "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/other/rletopnm.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Vim.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Vim.json", - "referenceNumber": 554, - "name": "Vim License", - "licenseId": "Vim", - "seeAlso": [ - "http://vimdoc.sourceforge.net/htmldoc/uganda.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/VOSTROM.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/VOSTROM.json", - "referenceNumber": 106, - "name": "VOSTROM Public License for Open Source", - "licenseId": "VOSTROM", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/VOSTROM" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/VSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/VSL-1.0.json", - "referenceNumber": 128, - "name": "Vovida Software License v1.0", - "licenseId": "VSL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/VSL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/W3C.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/W3C.json", - "referenceNumber": 522, - "name": "W3C Software Notice and License (2002-12-31)", - "licenseId": "W3C", - "seeAlso": [ - "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html", - "https://opensource.org/licenses/W3C" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/W3C-19980720.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/W3C-19980720.json", - "referenceNumber": 126, - "name": "W3C Software Notice and License (1998-07-20)", - "licenseId": "W3C-19980720", - "seeAlso": [ - "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/W3C-20150513.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/W3C-20150513.json", - "referenceNumber": 368, - "name": "W3C Software Notice and Document License (2015-05-13)", - "licenseId": "W3C-20150513", - "seeAlso": [ - "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/w3m.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/w3m.json", - "referenceNumber": 277, - "name": "w3m License", - "licenseId": "w3m", - "seeAlso": [ - "https://github.com/tats/w3m/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Watcom-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Watcom-1.0.json", - "referenceNumber": 430, - "name": "Sybase Open Watcom Public License 1.0", - "licenseId": "Watcom-1.0", - "seeAlso": [ - "https://opensource.org/licenses/Watcom-1.0" - ], - "isOsiApproved": true, - "isFsfLibre": false - }, - { - "reference": "https://spdx.org/licenses/Widget-Workshop.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Widget-Workshop.json", - "referenceNumber": 371, - "name": "Widget Workshop License", - "licenseId": "Widget-Workshop", - "seeAlso": [ - "https://github.com/novnc/noVNC/blob/master/core/crypto/des.js#L24" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Wsuipa.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Wsuipa.json", - "referenceNumber": 81, - "name": "Wsuipa License", - "licenseId": "Wsuipa", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Wsuipa" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/WTFPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/WTFPL.json", - "referenceNumber": 74, - "name": "Do What The F*ck You Want To Public License", - "licenseId": "WTFPL", - "seeAlso": [ - "http://www.wtfpl.net/about/", - "http://sam.zoy.org/wtfpl/COPYING" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/wxWindows.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "https://spdx.org/licenses/wxWindows.json", - "referenceNumber": 288, - "name": "wxWindows Library License", - "licenseId": "wxWindows", - "seeAlso": [ - "https://opensource.org/licenses/WXwindows" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/X11.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/X11.json", - "referenceNumber": 424, - "name": "X11 License", - "licenseId": "X11", - "seeAlso": [ - "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/X11-distribute-modifications-variant.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/X11-distribute-modifications-variant.json", - "referenceNumber": 494, - "name": "X11 License Distribution Modification Variant", - "licenseId": "X11-distribute-modifications-variant", - "seeAlso": [ - "https://github.com/mirror/ncurses/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Xdebug-1.03.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Xdebug-1.03.json", - "referenceNumber": 58, - "name": "Xdebug License v 1.03", - "licenseId": "Xdebug-1.03", - "seeAlso": [ - "https://github.com/xdebug/xdebug/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Xerox.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Xerox.json", - "referenceNumber": 428, - "name": "Xerox License", - "licenseId": "Xerox", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Xerox" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Xfig.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Xfig.json", - "referenceNumber": 289, - "name": "Xfig License", - "licenseId": "Xfig", - "seeAlso": [ - "https://github.com/Distrotech/transfig/blob/master/transfig/transfig.c", - "https://fedoraproject.org/wiki/Licensing:MIT#Xfig_Variant", - "https://sourceforge.net/p/mcj/xfig/ci/master/tree/src/Makefile.am" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/XFree86-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/XFree86-1.1.json", - "referenceNumber": 218, - "name": "XFree86 License 1.1", - "licenseId": "XFree86-1.1", - "seeAlso": [ - "http://www.xfree86.org/current/LICENSE4.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/xinetd.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/xinetd.json", - "referenceNumber": 138, - "name": "xinetd License", - "licenseId": "xinetd", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Xinetd_License" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/xkeyboard-config-Zinoviev.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/xkeyboard-config-Zinoviev.json", - "referenceNumber": 462, - "name": "xkeyboard-config Zinoviev License", - "licenseId": "xkeyboard-config-Zinoviev", - "seeAlso": [ - "https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/COPYING?ref_type\u003dheads#L178" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/xlock.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/xlock.json", - "referenceNumber": 299, - "name": "xlock License", - "licenseId": "xlock", - "seeAlso": [ - "https://fossies.org/linux/tiff/contrib/ras/ras2tif.c" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Xnet.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Xnet.json", - "referenceNumber": 523, - "name": "X.Net License", - "licenseId": "Xnet", - "seeAlso": [ - "https://opensource.org/licenses/Xnet" - ], - "isOsiApproved": true - }, - { - "reference": "https://spdx.org/licenses/xpp.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/xpp.json", - "referenceNumber": 457, - "name": "XPP License", - "licenseId": "xpp", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/xpp" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/XSkat.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/XSkat.json", - "referenceNumber": 267, - "name": "XSkat License", - "licenseId": "XSkat", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/XSkat_License" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/YPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/YPL-1.0.json", - "referenceNumber": 191, - "name": "Yahoo! Public License v1.0", - "licenseId": "YPL-1.0", - "seeAlso": [ - "http://www.zimbra.com/license/yahoo_public_license_1.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/YPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/YPL-1.1.json", - "referenceNumber": 114, - "name": "Yahoo! Public License v1.1", - "licenseId": "YPL-1.1", - "seeAlso": [ - "http://www.zimbra.com/license/yahoo_public_license_1.1.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Zed.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Zed.json", - "referenceNumber": 182, - "name": "Zed License", - "licenseId": "Zed", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Zed" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Zeeff.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Zeeff.json", - "referenceNumber": 4, - "name": "Zeeff License", - "licenseId": "Zeeff", - "seeAlso": [ - "ftp://ftp.tin.org/pub/news/utils/newsx/newsx-1.6.tar.gz" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Zend-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Zend-2.0.json", - "referenceNumber": 140, - "name": "Zend License v2.0", - "licenseId": "Zend-2.0", - "seeAlso": [ - "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Zimbra-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Zimbra-1.3.json", - "referenceNumber": 116, - "name": "Zimbra Public License v1.3", - "licenseId": "Zimbra-1.3", - "seeAlso": [ - "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html" - ], - "isOsiApproved": false, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/Zimbra-1.4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Zimbra-1.4.json", - "referenceNumber": 6, - "name": "Zimbra Public License v1.4", - "licenseId": "Zimbra-1.4", - "seeAlso": [ - "http://www.zimbra.com/legal/zimbra-public-license-1-4" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/Zlib.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/Zlib.json", - "referenceNumber": 132, - "name": "zlib License", - "licenseId": "Zlib", - "seeAlso": [ - "http://www.zlib.net/zlib_license.html", - "https://opensource.org/licenses/Zlib" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/zlib-acknowledgement.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/zlib-acknowledgement.json", - "referenceNumber": 76, - "name": "zlib/libpng License with Acknowledgement", - "licenseId": "zlib-acknowledgement", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ZPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ZPL-1.1.json", - "referenceNumber": 176, - "name": "Zope Public License 1.1", - "licenseId": "ZPL-1.1", - "seeAlso": [ - "http://old.zope.org/Resources/License/ZPL-1.1" - ], - "isOsiApproved": false - }, - { - "reference": "https://spdx.org/licenses/ZPL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ZPL-2.0.json", - "referenceNumber": 552, - "name": "Zope Public License 2.0", - "licenseId": "ZPL-2.0", - "seeAlso": [ - "http://old.zope.org/Resources/License/ZPL-2.0", - "https://opensource.org/licenses/ZPL-2.0" - ], - "isOsiApproved": true, - "isFsfLibre": true - }, - { - "reference": "https://spdx.org/licenses/ZPL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "https://spdx.org/licenses/ZPL-2.1.json", - "referenceNumber": 335, - "name": "Zope Public License 2.1", - "licenseId": "ZPL-2.1", - "seeAlso": [ - "http://old.zope.org/Resources/ZPL/" - ], - "isOsiApproved": true, - "isFsfLibre": true - } - ], - "releaseDate": "2024-02-03" -} diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager.ts b/src/Mod/AddonManager/Resources/translations/AddonManager.ts deleted file mode 100644 index c4d0a408c5..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager.ts +++ /dev/null @@ -1,2473 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - - - - - Repository URL - - - - - Branch - - - - - CompactView - - - - Icon - - - - - - <b>Package Name</b> - - - - - - Version - - - - - - Description - - - - - Update Available - - - - - UpdateAvailable - - - - - DependencyDialog - - - Dependencies - - - - - Dependency type - - - - - Name - - - - - Optional? - - - - - DependencyResolutionDialog - - - - Resolve Dependencies - - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - - FreeCAD Addons - - - - - Required Python modules - - - - - Optional Python modules - - - - - DeveloperModeDialog - - - Addon Developer Tools - - - - - Path to Addon - - - - - - Browse... - - - - - Metadata - - - - - Primary branch - - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - - Description - - - - - Discussion URL - - - - - Icon - - - - - Bugtracker URL - - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - - Set to today (CalVer style) - - - - - - - - (Optional) - - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - - README URL - - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - - Repository URL - - - - - Website URL - - - - - Documentation URL - - - - - Addon Name - - - - - Version - - - - - (Recommended) - - - - - Minimum Python - - - - - (Optional, only 3.x version supported) - - - - - Detect... - - - - - Addon Contents - - - - - Dialog - - - Addon Manager - - - - - Edit Tags - - - - - Comma-separated list of tags describing this item: - - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - - Add-on Manager: Warning! - - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - - Continue - - - - - Cancel - - - - - EditDependencyDialog - - - Edit Dependency - - - - - Dependency Type - - - - - Dependency - - - - - Package name, if "Other..." - - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - - Optional - - - - - ExpandedView - - - - Icon - - - - - - <h1>Package Name</h1> - - - - - - Version - - - - - - (tags) - - - - - - Description - - - - - - Maintainer - - - - - Update Available - - - - - labelSort - - - - - UpdateAvailable - - - - - Form - - - Licenses - - - - - License - - - - - License file - - - - - People - - - - - Kind - - - - - Name - - - - - Email - - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - - FreeCAD Version - - - - - Best-available branch, tag, or commit - - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - - - - - Minimum FreeCAD Version Supported - - - - - - Optional - - - - - Maximum FreeCAD Version Supported - - - - - Advanced version mapping... - - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - - Automatically check for updates at start (requires Git) - - - - - Download Macro metadata (approximately 10MB) - - - - - Cache update frequency - - - - - Manual (no automatic updates) - - - - - Daily - - - - - Weekly - - - - - Hide Addons without a license - - - - - Hide Addons with non-FSF Free/Libre license - - - - - Hide Addons with non-OSI-approved license - - - - - Hide Addons marked Python 2 Only - - - - - Hide Addons marked Obsolete - - - - - Hide Addons that require a newer version of FreeCAD - - - - - Custom repositories - - - - - Proxy - - - - - No proxy - - - - - User system proxy - - - - - User-defined proxy: - - - - - Score source URL - - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - - Path to Git executable (optional): - - - - - The path to the Git executable. Autodetected if needed and not specified. - - - - - Show option to change branches (requires Git) - - - - - Disable Git (fall back to ZIP downloads only) - - - - - Advanced Options - - - - - Activate Addon Manager options intended for developers of new Addons. - - - - - Addon developer mode - - - - - PackageDetails - - - Uninstalls a selected macro or workbench - - - - - Install - - - - - Uninstall - - - - - Update - - - - - Run Macro - - - - - Change branch - - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - - Package name - - - - - Installed version - - - - - Available version - - - - - Used by - - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - - Update all available - - - - - SelectFromList - - - Dialog - - - - - TextLabel - - - - - UpdateAllDialog - - - Updating Addons - - - - - Updating out-of-date addons... - - - - - addContentDialog - - - Content Item - - - - - Content type: - - - - - Macro - - - - - Preference Pack - - - - - Workbench - - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - - This is the only item in the Addon - - - - - Main macro file - - - - - The file with the macro's metadata in it - - - - - - - Browse... - - - - - Preference Pack Name - - - - - Workbench class name - - - - - Class that defines "Icon" data member - - - - - Subdirectory - - - - - Optional, defaults to name of content item - - - - - Icon - - - - - Optional, defaults to inheriting from top-level Addon - - - - - Tags... - - - - - Dependencies... - - - - - FreeCAD Versions... - - - - - Other Metadata - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - - Version - - - - - Description - - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - - Set to today (CalVer style) - - - - - Display Name - - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - - add_toolbar_button_dialog - - - Add button? - - - - - Add a toolbar button for this macro? - - - - - Yes - - - - - No - - - - - Never - - - - - change_branch - - - Change Branch - - - - - Change to branch: - - - - - copyrightInformationDialog - - - Copyright Information - - - - - Copyright holder: - - - - - Copyright year: - - - - - personDialog - - - Add Person - - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - - Name: - - - - - Email: - - - - - Email is required for maintainers, and optional for authors. - - - - - proxy_authentication - - - Proxy login required - - - - - Proxy requires authentication - - - - - Proxy: - - - - - Placeholder for proxy address - - - - - Realm: - - - - - Placeholder for proxy realm - - - - - Username - - - - - Password - - - - - selectLicenseDialog - - - Select a license - - - - - About... - - - - - License name: - - - - - Path to license file: - - - - - (if required by license) - - - - - Browse... - - - - - Create... - - - - - select_toolbar_dialog - - - - - - Select Toolbar - - - - - Select a toolbar to add this macro to: - - - - - Ask every time - - - - - toolbar_button - - - - Add button? - - - - - Add a toolbar button for this macro? - - - - - Yes - - - - - No - - - - - Never - - - - - AddonsInstaller - - - Starting up... - - - - - Worker process {} is taking a long time to stop... - - - - - Previous cache process was interrupted, restarting... - - - - - - Custom repo list changed, forcing recache... - - - - - - Addon manager - - - - - You must restart FreeCAD for changes to take effect. - - - - - Restart now - - - - - Restart later - - - - - - Refresh local cache - - - - - Creating addon list - - - - - Loading addon list - - - - - Creating macro list - - - - - Updating cache... - - - - - - Checking for updates... - - - - - Temporary installation of macro failed. - - - - - - Close - - - - - Update all addons - - - - - Check for updates - - - - - Python dependencies... - - - - - Developer tools... - - - - - Apply %n available update(s) - - - - - No updates available - - - - - - - Cannot launch a new installer until the previous one has finished. - - - - - - - - Maintainer - - - - - - - - Author - - - - - New Python Version Detected - - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - - Processing, please wait... - - - - - - Update - - - - - Updating... - - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - - Failed to convert the specified proxy port '{}' to a port number - - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - - Addon Manager: Unexpected {} response from server - - - - - Error with encrypted connection - - - - - - - Confirm remove - - - - - Are you sure you want to uninstall {}? - - - - - - - Removing Addon - - - - - Removing {} - - - - - - Uninstall complete - - - - - - Uninstall failed - - - - - Version {version} installed on {date} - - - - - Version {version} installed - - - - - Installed on {date} - - - - - - - - Installed - - - - - Currently on branch {}, name changed to {} - - - - - Git tag '{}' checked out, no updates possible - - - - - Update check in progress - - - - - Installation location - - - - - Repository URL - - - - - Changed to branch '{}' -- please restart to use Addon. - - - - - This Addon has been updated. Restart FreeCAD to see changes. - - - - - Disabled - - - - - Currently on branch {}, update available to version {} - - - - - Update available to version {} - - - - - This is the latest version available - - - - - WARNING: This addon is obsolete - - - - - WARNING: This addon is Python 2 only - - - - - WARNING: This addon requires FreeCAD {} - - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - - This Addon will be enabled next time you restart FreeCAD. - - - - - This Addon will be disabled next time you restart FreeCAD. - - - - - - - Success - - - - - Install - - - - - Uninstall - - - - - Enable - - - - - Disable - - - - - - Check for update - - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - - Run - - - - - Change branch... - - - - - Return to package list - - - - - Checking connection - - - - - Checking for connection to GitHub... - - - - - Connection failed - - - - - Missing dependency - - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - - Other... - For providing a license other than one listed - - - - - Select the corresponding license file in your Addon - - - - - Location for new license file - - - - - Received {} response code from server - - - - - Failed to install macro {} - - - - - Failed to create installation manifest file: - - - - - - Unrecognized content kind '{}' - - - - - Unable to locate icon at {} - - - - - Select an icon file for this content item - - - - - - - {} is not a subdirectory of {} - - - - - Select the subdirectory for this content item - - - - - Automatic - - - - - - Workbench - - - - - Addon - - - - - Python - - - - - Yes - - - - - Internal Workbench - - - - - External Addon - - - - - Python Package - - - - - - Other... - - - - - Too many to list - - - - - - - - - - Missing Requirement - - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - - Press OK to install anyway. - - - - - - Incompatible Python version - - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - - Optional dependency on {} ignored because it is not in the allow-list - - - - - - Installing dependencies - - - - - - Cannot execute Python - - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - - Cannot execute pip - - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - - Continue with installation of {} anyway? - - - - - - Package installation failed - - - - - See Report View for detailed failure log. - - - - - Installing Addon - - - - - Installing FreeCAD Addon '{}' - - - - - Cancelling - - - - - Cancelling installation of '{}' - - - - - {} was installed successfully - - - - - - Installation Failed - - - - - Failed to install {} - - - - - - Create new toolbar - - - - - - A macro installed with the FreeCAD Addon Manager - - - - - - Run - Indicates a macro that can be 'run' - - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - - XML failure while reading metadata from file {} - - - - - Invalid metadata in file {} - - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - - Name - - - - - Class - - - - - Description - - - - - Subdirectory - - - - - Files - - - - - Select the folder containing your Addon - - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - - - - - Scanning Addon for Python version compatibility - - - - - Minimum Python Version Detected - - - - - Vermin auto-detected a required version of Python 3.{} - - - - - Install Vermin? - - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - - Attempting to install Vermin from PyPi - - - - - - Installation failed - - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - - - - - Select an icon file for this package - - - - - Filter is valid - - - - - Filter regular expression is invalid - - - - - Search... - - - - - Click for details about package {} - - - - - Click for details about workbench {} - - - - - Click for details about macro {} - - - - - Maintainers: - - - - - Tags - - - - - {} ★ on GitHub - - - - - No ★, or not on GitHub - - - - - Created - - - - - Updated - - - - - Score: - - - - - - Up-to-date - - - - - - - - - Update available - - - - - - Pending restart - - - - - - DISABLED - - - - - Installed version - - - - - Unknown version - - - - - Installed on - - - - - Available version - - - - - Filter by... - - - - - Addon Type - - - - - - Any - - - - - Macro - - - - - Preference Pack - - - - - Installation Status - - - - - Not installed - - - - - Filter - - - - - DANGER: Developer feature - - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - - There are local changes - - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - - Local - Table header for local git ref name - - - - - Remote tracking - Table header for git remote tracking branch name - - - - - Last Updated - Table header for git update date - - - - - Installation of Python package {} failed - - - - - Installation of optional package failed - - - - - Installing required dependency {} - - - - - Installation of Addon {} failed - - - - - Downloaded {} for {} - - - - - Failed to decode {} file for Addon '{}' - - - - - Any dependency information in this file will be ignored - - - - - Unable to open macro wiki page at {} - - - - - Unable to fetch the code of this macro. - - - - - Unable to retrieve a description from the wiki for macro {} - - - - - Unable to open macro code URL {} - - - - - Unable to fetch macro-specified file {} from {} - - - - - Could not locate macro-specified file {} (expected at {}) - - - - - {}: Unrecognized internal workbench '{}' - - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - - Got an error when trying to import {} - - - - - An unknown error occurred - - - - - Could not find addon {} to remove it. - - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - - Removed extra installed file {} - - - - - Error while trying to remove extra installed file {} - - - - - Error while trying to remove macro file {}: - - - - - Failed to connect to GitHub. Check your connection and proxy settings. - - - - - WARNING: Duplicate addon {} ignored - - - - - Git is disabled, skipping Git macros - - - - - Attempting to change non-Git Macro setup to use Git - - - - - - An error occurred updating macros from GitHub, trying clean checkout... - - - - - Attempting to do a clean checkout... - - - - - Clean checkout succeeded - - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - - Checking {} for update - - - - - Unable to fetch Git updates for workbench {} - - - - - Git status failed for {} - - - - - Caching {} macro - - - - - Caching macros - - - - - Failed to read metadata from {name} - - - - - Failed to fetch code for macro '{name}' - - - - - Addon Manager: a worker process failed to complete while fetching {name} - - - - - Out of {num_macros} macros, {num_failed} timed out while processing - - - - - Addon Manager: a worker process failed to halt ({name}) - - - - - Timeout while fetching metadata for macro {} - - - - - Failed to kill process for macro {}! - - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - - Repository URL - Preferences header for custom repositories - - - - - Branch name - Preferences header for custom repositories - - - - - Basic Git update failed with the following message: - - - - - Backing up the original directory and re-cloning - - - - - Failed to clone {} into {} using Git - - - - - Git branch rename failed with the following message: - - - - - Installing - - - - - Succeeded - - - - - Failed - - - - - Update was cancelled - - - - - some addons may have been updated - - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - - Loading page for {} from {}... - - - - - Failed to download data from {} -- received response code {}. - - - - - Composite view - - - - - Expanded view - - - - - Compact view - - - - - Alphabetical - Sort order - - - - - Last Updated - Sort order - - - - - Date Created - Sort order - - - - - GitHub Stars - Sort order - - - - - Score - Sort order - - - - - Std_AddonMgr - - - &Addon manager - - - - - Manage external workbenches, macros, and preference packs - - - - - AddonInstaller - - - Finished removing {} - - - - - Failed to remove some files - - - - - Addons installer - - - Finished updating the following addons - - - - - Workbench - - - Auto-Created Macro Toolbar - - - - - QObject - - - Addon Manager - - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_af.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_af.qm deleted file mode 100644 index 4ca66c9a3b07d30ca0b7e6031cd8c4918997da07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13491 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 tU6SE(a!Ffq5*(9c*YQ_SM)F8p$B-zpNp8gGj diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_af.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_af.ts deleted file mode 100644 index d8b56b375f..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_af.ts +++ /dev/null @@ -1,427 +0,0 @@ - - - - - AddonInstaller - - - Installed location - Installed location - - - - AddonsInstaller - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description for this macro. - Unable to retrieve a description for this macro. - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - - - - Checking for updates... - Checking for updates... - - - - Apply - Pas toe - - - - update(s) - update(s) - - - - No update available - No update available - - - - Macro successfully installed. The macro is now available from the Macros dialog. - Macro successfully installed. The macro is now available from the Macros dialog. - - - - Unable to install - Unable to install - - - - Addon successfully removed. Please restart FreeCAD - Addon successfully removed. Please restart FreeCAD - - - - Unable to remove this addon - Unable to remove this addon - - - - Macro successfully removed. - Macro successfully removed. - - - - Macro could not be removed. - Macro could not be removed. - - - - Unable to download addon list. - Unable to download addon list. - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Outdated GitPython detected, consider upgrading with pip. - Outdated GitPython detected, consider upgrading with pip. - - - - List of macros successfully retrieved. - List of macros successfully retrieved. - - - - Retrieving description... - Retrieving description... - - - - Retrieving info from - Retrieving info from - - - - An update is available for this addon. - An update is available for this addon. - - - - This addon is already installed. - This addon is already installed. - - - - Retrieving info from git - Retrieving info from git - - - - Retrieving info from wiki - Retrieving info from wiki - - - - GitPython not found. Using standard download instead. - GitPython not found. Using standard download instead. - - - - Your version of python doesn't appear to support ZIP files. Unable to proceed. - Your version of python doesn't appear to support ZIP files. Unable to proceed. - - - - Workbench successfully installed. Please restart FreeCAD to apply the changes. - Workbench successfully installed. Please restart FreeCAD to apply the changes. - - - - Missing workbench - Missing workbench - - - - Missing python module - Missing python module - - - - Missing optional python module (doesn't prevent installing) - Missing optional python module (doesn't prevent installing) - - - - Some errors were found that prevent to install this workbench - Some errors were found that prevent to install this workbench - - - - Please install the missing components first. - Please install the missing components first. - - - - Error: Unable to download - Error: Unable to download - - - - Successfully installed - Successfully installed - - - - GitPython not installed! Cannot retrieve macros from git - GitPython not installed! Cannot retrieve macros from git - - - - Installed - Installed - - - - Update available - Update available - - - - Restart required - Restart required - - - - This macro is already installed. - This macro is already installed. - - - - A macro has been installed and is available under Macro -> Macros menu - A macro has been installed and is available under Macro -> Macros menu - - - - This addon is marked as obsolete - This addon is marked as obsolete - - - - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - - - - Error: Unable to locate zip from - Error: Unable to locate zip from - - - - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - - - - This addon is marked as Python 2 Only - This addon is marked as Python 2 Only - - - - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - - - - User requested updating a Python 2 workbench on a system running Python 3 - - User requested updating a Python 2 workbench on a system running Python 3 - - - - - Workbench successfully updated. Please restart FreeCAD to apply the changes. - Workbench successfully updated. Please restart FreeCAD to apply the changes. - - - - User requested installing a Python 2 workbench on a system running Python 3 - - User requested installing a Python 2 workbench on a system running Python 3 - - - - - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - - - - Raw markdown displayed - Raw markdown displayed - - - - Python Markdown library is missing. - Python Markdown library is missing. - - - - Dialog - - - Workbenches - Workbenches - - - - Macros - Makros - - - - Execute - Voer uit - - - - Downloading info... - Downloading info... - - - - Update all - Update all - - - - Executes the selected macro, if installed - Executes the selected macro, if installed - - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Installs or updates the selected macro or workbench - Installs or updates the selected macro or workbench - - - - Download and apply all available updates - Download and apply all available updates - - - - Custom repositories (one per line): - Custom repositories (one per line): - - - - Sets configuration options for the Addon Manager - Sets configuration options for the Addon Manager - - - - Configure... - Configure... - - - - Addon manager options - Addon manager options - - - - Uninstall selected - Uninstall selected - - - - Install/update selected - Install/update selected - - - - Close - Maak toe - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires GitPython) - Automatically check for updates at start (requires GitPython) - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User defined proxy : - User defined proxy : - - - - Addon Manager - Addon Manager - - - - Close the Addon Manager - Close the Addon Manager - - - - You can use this window to specify additional addon repositories -to be scanned for available addons - You can use this window to specify additional addon repositories -to be scanned for available addons - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches and macros - Manage external workbenches and macros - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ar.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ar.qm deleted file mode 100644 index 0e993ebe56a92e1c7e9965f45996d8f3d34f8c85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13452 zcmcgzYiu0Xb-t9uk+_mfS+->PnV}x!idvF-G`7juZYYv^RS!lI>&R#w4|itCDQ9O^ zGqYS$EsCJY4>vYipiWvFP?|ao&;*Gc2Zo!}fYBfZ`onOOq6um=aE-o;)28zak z)$hA^p1V7gj23|)?e0A8J@-7m^PO|A9{85I>$P{Te(o;^?)vk`o_*!-{zM3|&hU@o z-^ayB^*qVlDl|9bexLfrc5xA9S~orQkPtf`UH6&yo)_Yd zkFEQg-4jBLzP^6P_x}*%eRKV;pJBYdZ?1pgllKU*>+<@)AHnl??OuQFNAs9}Zo}{1 z`I|zNH*a|7?!Ojd?<@HHi4Z;KHoWtp?Lr*<&)zs|F;!2LIR|KQwrg&26H_m6&On-F*J?EUt8zbC}V zhTb2Y_%uGhu5J3K&qDs+&~6W~{_+#reJ_7Xh@lm2_L=*IIPj8o@$nxBvHhy{`H#FM z#2$0w$!}r)(%{Bl|8}1cV|zAz@rzGlolk9g?m@`0;q6U7{qOJN`sKdfH$N`K=12P; zdf}1~JC66wzCJ31KGC1KSM9|(sQr>82bOm z(pzui_kp?1Uw`jitZV1ym-qL={Fk;o-Nf~t-{10sPdzV0?^|2`wg>YM9NqHv*Zu|T z{>0YG{h!D6N47rr1jZc|TmQ6*@i4;W^KS}q=daxKjUPge9Y5?J{2BDH!RbGF7VmG_ z-hak|9mbyPf9#DJ*z-I6kN<~@>;KUIlx+*Kf1v-_cVC0t@AkjB|7qCgO8-y)_`4YI z&v5h5_ts;Az2c;BMIb_92nT;GVG13eo~YtVC~SOlH&GM~f484>gV1ms%hVmOYJ|4u zZp7uACQZ|G<9mJ&2YymaVxT$(sR|#1=wcDy1ANY75(|^+7`$_81J@{mEuS^SGTyQw zkb(Coo-Ug52@9j@;!I}z5%Ey&3g@cJnVQK0j!o)yqw0J5q7mrxmgVYpvLeGZbvw|F zWy5xidB@V5u4(!D8TtIkL+VSQ*DbfnMfb}^2l-X+)Mm6X?UZ&%=-QArjbGE+h;}rY zf2({6GPuTqc-a7+i_Ln=xf( z?DFB`b~w8lE_$v`FROWg(NTRaprwEzu4(vYqCE+}mSGlKt+D13VjZ+;;}uPXjncqYL8Cfpd|iRXw+S@g-;Yw$E<-m57D2=ulzpfF+$1KpcT!bDEa zOP`6cPoXSjsN*itFFXI8D#2F0rejKv0hqU1E84F4rwRw zyE8#%?;^bdWG0hLt>8!j&YvUMW1kVh~XHMYzn1rD?v&S=~kTk27lG9+~HlzAQ zV6k)+CNbA*WvB+DSYovtA<#|RaJ+@$s5r>=7Z8M4uABxEKa13zlkvLhUWSe7c_~78 zK&prxBK{p%yOF~fTH2JJKx8Z9yC?n96+_a08`3A~3$FZ~4`hWy`xBu*at67L0OB>s zISof|D1@ndW)n=UY+_9*_B_x9Ehy}^bUpU3?jwxEu zgAd-om~auRi^kfwc!+G4E(8 zovY(c*1@@yI)r1&R8FdLg^k4!g43w4L=-uSbQ#9=$X}~oz2Uj=NMr}w55i(OkF_Of zRyK5$IPtP5v*9*Wr7uBU(dE3{sZ@KS9DK&`m&jFg$Da2Mf0fu1NmndPMV!YpEvSnb zCNBo<7(g*B$yTA7w2s($-e>{fqWMfaXgJ2IRh-Xs%)(s7+SA9sDoabc;zHs9M|prlUCgiE+3Iw{Oz zZ-hjzeGE&i;LWN8^t9GdYKiF?6_>u*KrmvI#Igoegc_S*%goyHy%={{TLPz}4oT#1 zhEvfS9o;@tej znWD+zeFKFC{HVCtrFoP#og74)DpDCC9gdU92mBJ<9Bd^>gkT-Ilf0(oG}}^dbPHkS>AK zC7#iymQ)aLKJXmSvl}uEXN+6H3V;Y>AIvmK^<><*X?~J1O%v;DLXNmDW_y@jIvRv9 z96Jr6QFXxy(u&DaemW1?3O{K~f-v8wS*baWN6ti!&u?VCY+#e=$HtGlo5~dx@G5Pa@v7_*HhgaxT%1sW05L2G?bxV!LZfI)N_1Hiv4z6|sU@*X?QBq5mQ1WvQYQadX~cwe zz+kID;MjaX=+uJJfGK9u)-aqABgPRuSPep}4r1mw%Emx?mIh0f?D+>xN2cb85dny0 z*T31&(PC{a+9{y{Z4>J=UsK)F*=UWtklt53`%$^o!QGdm zNTy@5b2E-adlFYF_$=e|5RxSD7D@J?OpR)vChnS~dLK$!6&yGfK^RetyB&UARy@=?o>;axb<=`~jY z<^zSYF-G=rLi@0WZ9l9nFGiBuCseh9b1NpcDK!`Eu`!B zK(1m;1|b8KNY0v6RjLZbyMs(8urRH61GyB4^04DeOm}5|A#8QR)QHfN^_-mxfZr^M zQ5^%OGl8Fk{Nc1*QBV*efZudoa{7o%9MMPgLJxTQI@%zdscumWw?A)9oNm*E+zsOL z{$KTQ6?=Yd-8fwqQ?}+l2-<@D$J?F)Ua?F}gkd0kx5O$7Ev^Twj~BA(%+_oB$Dq=Bn6|A{Hg_>AIn)3m_6H35LRSP+lO4hd{?~TkFpcM zJOa38E*u6>mvMAJ?PUy0h{ve~jKQ506t*ZH56aP0cAUicC|G5&IfPPqLc0&o#hG;m z_xJ|4a9K)UPZs8WH8XZyWHG!)?%3?Z+Y=aRAiBE;nVR`6Kc-5Z$)N_^#UTjf`(Hvf zPqX*sODG}hO>Awo9bJ%#rK-GJ?vS$twQ4mqnQ__y4+r|WCEjR%55;MPJP5mgRm;gf z;h<&h7e~rfaS2h}l-Yzk9&8}Xb2ab`wU3wIcxc}%QPIyzh51M!0#S#UKs=&{J%X*p zS$x(oGVuk7fM4CHn5r#UkH|PoeDEw3=IhIrAArP@;zU~<@zx5U0mluv?4a3bcqsWF zIXR22wgZsJ?2Dr?s9HEUQslJa9ynjLs}Bj;jmYltr+Yqq%Kghh@ea-%ID?R~$TJcS z4OOru%Zg6ioJmjIXw!0YO`cL3&W*szf@cEak}tc-6(l3>n3UyEbcQF|k_x!q?8sLz zGPhA!6q5hjND^t`N$_T0Zb_OL? zS^rgeU_!dTQY~5?5y98XQDZ$wH(sRLvnwhgvL|G;rRSM?ryMVk^?&xsQS89;XoK2u ziA&e(+v+wsnoK`R#|2i~h4D$D=?vYdvMJkJg>`dFj0_TMiilF9Z=0cNm&>sx4i+M$P2HGy8nwvXNb zKXXu8@1JOQk6FNR?x+dIjynn2Y_D8~_qrW~i+LBMO{6JLM<-KM8%`#4m_M`G99h3z zq`?l6Vmil9w&L?Tz9pWBM2k)TE~+jeypJI>oYKY;0XNRbZg7X!oX3Hgv|FtV5c>{2 ziLe%LHfE1LunA*BK2>`wG8G+VOy=Al%^CG8EJtoBssgT}+qIZGtDU8cv-H#etQ?z? zs5VU&6*wmyrCmPC#LAu>e>#l;hm+gA(tSwnz_(n|n+6m)P0G61b*{o>hFRRG2M&Qp|es zWK>+Mt$y~Zg2-GIv>`I+Qc75^Y8PO)hOG`XNhJ88NaA6!qyUVM zjg`u>(o8@w+P8>`qlQsk!g0;iM_5UrL+wZHln$gEZ9C^Ph83rw+TksUm)>?#b(+Ui zgeD7bk5u|(_T()6pnDF9ZPxCe+4zay?I=_exsF6~1*AW5?vRbYTp-CNQCxhq%X|ko zV!;WTWFAeOerbPon>dT*(aG2qUCA6c+=PP-ARH_5%wZ;K#TJmE=;2Jktj+RSS?FdT zehm9e?08d+>I6fYSXAm(uA2>fJ{yNttmMK_P8N9Zf`yX+IL9D!lRQ5i^M|P4(dN+Y zs@N+j9q~9tg<^l&K8G4#9@s8)rP(e6a&4^O|8GuHP9_J>Nak0NyQZhy3X!tWB2!?Z z!qQyS#BrQ<<&^OvWhUHlzn@lAefo^=;9i=!Zkkdw?-$z&y6g$2)lWU1G49^CyzsG^p}Q=AizT3!(W5 zdG*YK`Y#Trak?ul7=hLXWuC({rt7-L<{zOV@@s|1W)6)3*Qs diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ar.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_ar.ts deleted file mode 100644 index e0f6ddd45b..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_ar.ts +++ /dev/null @@ -1,427 +0,0 @@ - - - - - AddonInstaller - - - Installed location - Installed location - - - - AddonsInstaller - - - Unable to fetch the code of this macro. - غير قادر على جلب رمز هذا الماكرو. - - - - Unable to retrieve a description for this macro. - غير قادر على استرداد وص٠لهذا الماكرو. - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - Ø§Ù„Ø¥Ø¶Ø§ÙØ§Øª التي يمكن تثبيتها هنا ليست رسميا جزءا من FreeCADØŒ ولا يتم مراجعتها من قبل ÙØ±ÙŠÙ‚ FreeCAD. تأكد من Ù…Ø¹Ø±ÙØ© ما تقوم بتثبيته! - - - - Addon manager - مدير الملحق - - - - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - يجب إعادة تشغيل FreeCAD حتى تصبح التغييرات Ù†Ø§ÙØ°Ø© Ø§Ù„Ù…ÙØ¹ÙˆÙ„. اضغط على مواÙÙ‚ لإعادة تشغيل FreeCad الآن، أو إلغاء الأمر لإعادة التشغيل لاحقًا. - - - - Checking for updates... - يتم الآن التحقق من وجود تحديثات... - - - - Apply - Apply - - - - update(s) - تحديث (تحديثات) - - - - No update available - لا يوجد تحديث Ù…ØªÙˆÙØ± - - - - Macro successfully installed. The macro is now available from the Macros dialog. - تم تثبيت الماكرو بنجاح. الماكرو Ù…ØªÙˆÙØ± الآن من مربع حوار وحدات الماكرو. - - - - Unable to install - غير قادر على التثبيت - - - - Addon successfully removed. Please restart FreeCAD - تمت إزالة الملحق بنجاح. الرجاء إعادة تشغيل FreeCad - - - - Unable to remove this addon - تعذر إزالة هذا الملحق - - - - Macro successfully removed. - تمت إزالة الماكرو بنجاح. - - - - Macro could not be removed. - Macro could not be removed. - - - - Unable to download addon list. - Unable to download addon list. - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Outdated GitPython detected, consider upgrading with pip. - Outdated GitPython detected, consider upgrading with pip. - - - - List of macros successfully retrieved. - List of macros successfully retrieved. - - - - Retrieving description... - Retrieving description... - - - - Retrieving info from - Retrieving info from - - - - An update is available for this addon. - An update is available for this addon. - - - - This addon is already installed. - This addon is already installed. - - - - Retrieving info from git - Retrieving info from git - - - - Retrieving info from wiki - Retrieving info from wiki - - - - GitPython not found. Using standard download instead. - GitPython not found. Using standard download instead. - - - - Your version of python doesn't appear to support ZIP files. Unable to proceed. - Your version of python doesn't appear to support ZIP files. Unable to proceed. - - - - Workbench successfully installed. Please restart FreeCAD to apply the changes. - Workbench successfully installed. Please restart FreeCAD to apply the changes. - - - - Missing workbench - Missing workbench - - - - Missing python module - Missing python module - - - - Missing optional python module (doesn't prevent installing) - Missing optional python module (doesn't prevent installing) - - - - Some errors were found that prevent to install this workbench - Some errors were found that prevent to install this workbench - - - - Please install the missing components first. - Please install the missing components first. - - - - Error: Unable to download - Error: Unable to download - - - - Successfully installed - Successfully installed - - - - GitPython not installed! Cannot retrieve macros from git - GitPython not installed! Cannot retrieve macros from git - - - - Installed - Installed - - - - Update available - Update available - - - - Restart required - Restart required - - - - This macro is already installed. - This macro is already installed. - - - - A macro has been installed and is available under Macro -> Macros menu - A macro has been installed and is available under Macro -> Macros menu - - - - This addon is marked as obsolete - This addon is marked as obsolete - - - - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - - - - Error: Unable to locate zip from - Error: Unable to locate zip from - - - - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - - - - This addon is marked as Python 2 Only - This addon is marked as Python 2 Only - - - - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - - - - User requested updating a Python 2 workbench on a system running Python 3 - - User requested updating a Python 2 workbench on a system running Python 3 - - - - - Workbench successfully updated. Please restart FreeCAD to apply the changes. - Workbench successfully updated. Please restart FreeCAD to apply the changes. - - - - User requested installing a Python 2 workbench on a system running Python 3 - - User requested installing a Python 2 workbench on a system running Python 3 - - - - - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - - - - Raw markdown displayed - Raw markdown displayed - - - - Python Markdown library is missing. - Python Markdown library is missing. - - - - Dialog - - - Workbenches - Workbenches - - - - Macros - وحدات الماكرو - - - - Execute - تنÙيد - - - - Downloading info... - Downloading info... - - - - Update all - Update all - - - - Executes the selected macro, if installed - Executes the selected macro, if installed - - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Installs or updates the selected macro or workbench - Installs or updates the selected macro or workbench - - - - Download and apply all available updates - Download and apply all available updates - - - - Custom repositories (one per line): - Custom repositories (one per line): - - - - Sets configuration options for the Addon Manager - Sets configuration options for the Addon Manager - - - - Configure... - Configure... - - - - Addon manager options - Addon manager options - - - - Uninstall selected - Uninstall selected - - - - Install/update selected - Install/update selected - - - - Close - إغلاق - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires GitPython) - Automatically check for updates at start (requires GitPython) - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User defined proxy : - User defined proxy : - - - - Addon Manager - Addon Manager - - - - Close the Addon Manager - Close the Addon Manager - - - - You can use this window to specify additional addon repositories -to be scanned for available addons - You can use this window to specify additional addon repositories -to be scanned for available addons - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches and macros - Manage external workbenches and macros - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_be.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_be.qm deleted file mode 100644 index 94de11a6d2f0b41dfb5625d24ed2d423899560d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71050 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%0DGoNhwm{-1#8 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 BIJ^J= diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_be.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_be.ts deleted file mode 100644 index 32a40e0ed5..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_be.ts +++ /dev/null @@ -1,2493 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - КарыÑтальніцкае Ñховішча - - - - Repository URL - URL-Ð°Ð´Ñ€Ð°Ñ Ñховішча - - - - Branch - Галіна - - - - CompactView - - - - Icon - Гузік - - - - - <b>Package Name</b> - <b>Ðазва пакета</b> - - - - - Version - ВерÑÑ–Ñ - - - - - Description - ÐпіÑанне - - - - Update Available - Ðбнаўленне даÑтупнае - - - - UpdateAvailable - ДаÑтупна абнаўленне - - - - DependencyDialog - - - Dependencies - ЗалежнаÑці - - - - Dependency type - Тып залежнаÑці - - - - Name - Ðазва - - - - Optional? - ÐеабавÑзковы? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Дазволіць залежнаÑці - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Дадатак мае наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð°Ð±Ð°Ð²ÑÐ·ÐºÐ¾Ð²Ñ‹Ñ Ñ– неабавÑÐ·ÐºÐ¾Ð²Ñ‹Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð°Ñці. Ð’Ñ‹ павінны ÑžÑталÑваць Ñ–Ñ…, перш чым гÑты Дадатак можна будзе ўжываць. - -Ð’Ñ‹ жадаеце, каб Кіраванне дадаткамі ÑžÑталёўвала Ñ–Ñ… аўтаматычна? ÐбÑрыце "ПрапуÑціць", каб уÑталÑваць Дадатак без уÑтаноўкі залежнаÑцÑÑž. - - - - FreeCAD Addons - Дадаткі FreeCAD - - - - Required Python modules - ÐÐµÐ°Ð±Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ– Python - - - - Optional Python modules - ÐеабавÑÐ·ÐºÐ¾Ð²Ñ‹Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ– Python - - - - DeveloperModeDialog - - - Addon Developer Tools - ІнÑтрумент раÑпрацоўкі дадаткаў - - - - Path to Addon - ШлÑÑ… да дадаткаў - - - - - Browse... - ÐглÑд... - - - - Metadata - ÐœÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ - - - - Primary branch - ПершаÑÐ½Ð°Ñ Ð³Ð°Ð»Ñ–Ð½Ð° - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - ТлумачÑнне таго, што дае Дадатак. ÐдлюÑтроўваецца Ñž Кіраванні дадаткамі. Ð”Ð»Ñ Ð³Ñтага не абавÑзкова паказваць, што гÑта дадатак Ð´Ð»Ñ FreeCAD. - - - - Description - ÐпіÑанне - - - - Discussion URL - URL-Ð°Ð´Ñ€Ð°Ñ Ð°Ð±Ð¼ÐµÑ€ÐºÐ°Ð²Ð°Ð½Ð½Ñ - - - - Icon - Гузік - - - - Bugtracker URL - URL-Ð°Ð´Ñ€Ð°Ñ Ñ€ÑгіÑтрацыі памылак (bugtracker) - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Падтрымліваюцца Ñтылі Semantic (1.2.3-бÑта-верÑÑ–Ñ) ці CalVer (2022.08.30) - - - - Set to today (CalVer style) - Задаць на ÑÑ‘Ð½Ð½Ñ (Ñтыль CalVer) - - - - - - - (Optional) - (ÐеабавÑзковы) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - ÐдлюÑтроўваецца Ñž ÑпіÑе Дадаткаў ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ–'s. Ðе павінна ўтрымліваць Ñловы "FreeCAD" Ñ– павінна быць дапушчальным іменем каталога ва ÑžÑÑ–Ñ… падтрыманых аперацыйных ÑÑ–ÑÑ‚Ñмах. - - - - README URL - URL-Ð°Ð´Ñ€Ð°Ñ README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - Парада: Паколькі гÑтае адлюÑтроўваецца Ñž FreeCAD, у Кіраванні дадаткамі, нÑма неабходнаÑці займаць меÑца, кажучы нешта накшталт "ГÑта дадатак FreeCAD..."- проÑта Ñкажы, што ён робіць. - - - - Repository URL - URL-Ð°Ð´Ñ€Ð°Ñ Ñховішча - - - - Website URL - URL-Ð°Ð´Ñ€Ð°Ñ Ð½Ð° інтÑрнет-Ñайт - - - - Documentation URL - URL-Ð°Ð´Ñ€Ð°Ñ Ð½Ð° дакументацыю - - - - Addon Name - Ðазва дадатка - - - - Version - ВерÑÑ–Ñ - - - - (Recommended) - (Прапанаваны) - - - - Minimum Python - ÐÐ°Ð¹Ð¼ÐµÐ½ÑˆÐ°Ñ Ð²ÐµÑ€ÑÑ–Ñ Python - - - - (Optional, only 3.x version supported) - (ÐеабавÑзкова, падтрымліваецца толькі верÑÑ–Ñ 3.x) - - - - Detect... - Ð’Ñ‹Ñвіць... - - - - Addon Contents - ЗмеÑÑ‚ дадатку - - - - Dialog - - - Addon Manager - Кіраванне дадаткамі - - - - Edit Tags - ЗмÑніць меткі - - - - Comma-separated list of tags describing this item: - Ð¡Ð¿Ñ–Ñ Ð¼ÐµÑ‚Ð°Ðº, Ð¿Ð°Ð´Ð·ÐµÐ»ÐµÐ½Ñ‹Ñ ÐºÐ¾Ñкамі, ÑÐºÑ–Ñ Ð°Ð¿Ñ–Ñваюць Ñлемент: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - Падказка: Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ñ‹Ñ Ð¼ÐµÑ‚ÐºÑ– ўключаюць "Assemply (Зборка)", "FEM (Метад канчатковых Ñлементаў)", "Mesh (Паліганальную Ñетку)", "NURBS (Ðеаднародны рацыÑнальны B-Ñплайн)" Ñ– гÑтак далей. - - - - Add-on Manager: Warning! - Кіраўнік дадаткаў: Увага! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Кіраўнік дадаткаў дае доÑтуп да шырокай бібліÑÑ‚Ñцы карыÑных пашырÑннÑÑž FreeCAD. -Мы не даем ніÑкіх гарантый адноÑна Ñ–Ñ… бÑÑпекі ці функцыÑнальнаÑці. - - - - Continue - ПрацÑгнуць - - - - Cancel - СкаÑаваць - - - - EditDependencyDialog - - - Edit Dependency - ЗмÑніць залежнаÑць - - - - Dependency Type - Тып залежнаÑці - - - - Dependency - ЗалежнаÑць - - - - Package name, if "Other..." - Ðазва пакета, калі "Іншы..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - Заўвага: Калі абрана "Іншы...", пакет адÑутнічае Ñž файле ALLOWED_PYTHON_PACKAGES.txt, Ñ– не будзе аўтаматычна ÑžÑталÑваны Кіраваннем дадаткамі. Ðдпраўце PR на <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> каб запытаць даданне пакета. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Калі ÑуÑтракаецца неабавÑÐ·ÐºÐ¾Ð²Ð°Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð°Ñць, Кіраванне дадаткамі прапануе ÑžÑталÑваць Ñе (калі гÑта магчыма), але не будзе блакаваць уÑтаноўку, калі карыÑтальнік вырашыць не ÑžÑталёўваць пакет ці не зможа Ñго ÑžÑталÑваць. - - - - Optional - ÐеабавÑзковы - - - - ExpandedView - - - - Icon - Гузік - - - - - <h1>Package Name</h1> - <h1>Ðазва пакета</h1> - - - - - Version - ВерÑÑ–Ñ - - - - - (tags) - (меткі) - - - - - Description - ÐпіÑанне - - - - - Maintainer - Суправаджальнік - - - - Update Available - Ðбнаўленне даÑтупнае - - - - labelSort - Парадкаваць надпіÑÑ‹ - - - - UpdateAvailable - ДаÑтупна абнаўленне - - - - Form - - - Licenses - ЛіцÑнзіі - - - - License - ЛіцÑÐ½Ð·Ñ–Ñ - - - - License file - Файл ліцÑнзіі - - - - People - Стваральнікі - - - - Kind - Тып - - - - Name - Ðазва - - - - Email - Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾ÑˆÑ‚Ð° - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Пашыранае ÑупаÑтаўленне верÑій - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Ð‘ÑƒÐ´ÑƒÑ‡Ñ‹Ñ Ð²ÐµÑ€ÑÑ–Ñ– ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ– FreeCAD будуць падтрымліваць уÑтаноўку раÑпрацаўнікамі пÑўнай галіны ці меткі Ð´Ð»Ñ ÑžÐ¶Ñ‹Ð²Ð°Ð½Ð½Ñ Ð· пÑўнай верÑÑ–Ñй FreeCAD (напрыклад, уÑтаноўка пÑўнай меткі Ñž ÑкаÑці апошнÑй верÑÑ–Ñ– вашага дадатку Ð´Ð»Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼ÐºÑ– верÑÑ–Ñ– 0.19 Ñ– гÑтак далей) - - - - FreeCAD Version - ВерÑÑ–Ñ FreeCAD - - - - Best-available branch, tag, or commit - ÐÐ°Ð¹Ð»ÐµÐ¿ÑˆÐ°Ñ Ð´Ð°ÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð³Ð°Ð»Ñ–Ð½Ð°, метка ці фікÑÐ°Ñ†Ñ‹Ñ - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - ÐŸÐ°Ð´Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½Ñ‹Ñ Ð²ÐµÑ€ÑÑ–Ñ– FreeCAD - - - - Minimum FreeCAD Version Supported - ÐÐ°Ð¹Ð¼ÐµÐ½ÑˆÐ°Ñ Ð¿Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ FreeCAD - - - - - Optional - ÐеабавÑзковы - - - - Maximum FreeCAD Version Supported - ÐÐ°Ð¹Ð±Ð¾Ð»ÑŒÑˆÐ°Ñ Ð¿Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ FreeCAD - - - - Advanced version mapping... - Пашыранае ÑупаÑтаўленне верÑій... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Ðалады ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ– - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Калі щключана, то пры запуÑку варштату ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ– ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑ– будуць правÑрацца на наÑўнаÑць даÑтупных абнаўленнÑÑž - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Спампаваць Ð¼ÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ð¼Ð°ÐºÑ€Ð°Ñаў (прыкладна 10 Мб) - - - - Cache update frequency - ЧаÑтата Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ ÐºÑшу - - - - Manual (no automatic updates) - Уручную (без аўтаматычных абнаўленнÑÑž) - - - - Daily - Штодзень - - - - Weekly - Штотыдзень - - - - Hide Addons without a license - Схаваць дадаткі без ліцÑнзіі - - - - Hide Addons with non-FSF Free/Libre license - Схаваць дадаткі без ліцÑнзіі FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Схаваць дадаткі без ліцÑнзіі, ÑÐºÐ°Ñ Ð½Ðµ Ð°Ð´Ð¾Ð±Ñ€Ð°Ð½Ð°Ñ OSI - - - - Hide Addons marked Python 2 Only - Схаваць дадаткі, Ð°Ð´Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ Ñк толькі Ð´Ð»Ñ Python 2 - - - - Hide Addons marked Obsolete - Схаваць дадаткі, Ð°Ð´Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ Ñк ÑаÑтарÑÐ»Ñ‹Ñ - - - - Hide Addons that require a newer version of FreeCAD - Схаваць дадаткі, ÑÐºÑ–Ñ Ð¿Ð°Ñ‚Ñ€Ð°Ð±ÑƒÑŽÑ†ÑŒ больш новую верÑÑ–ÑŽ FreeCAD - - - - Custom repositories - КарыÑÑ‚Ð°Ð»ÑŒÐ½Ñ–Ñ†ÐºÑ–Ñ Ñховішча - - - - Proxy - ПрокÑÑ– - - - - No proxy - Без прокÑÑ– - - - - User system proxy - СіÑÑ‚Ñмны прокÑÑ– карыÑтальніка - - - - User-defined proxy: - КарыÑтальніцкі прокÑÑ–: - - - - Score source URL - URL-Ð°Ð´Ñ€Ð°Ñ ÐºÑ€Ñ‹Ð½Ñ–Ñ†Ñ‹ ацÑнкі - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - URL-Ð°Ð´Ñ€Ð°Ñ Ð´Ð»Ñ Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ… ацÑнкі дапаўненнÑÑž (падрабÑзнаÑці аб фарматаванні Ñ– размÑшчÑнні глÑдзіце Ñž вікі-Ñтаронкі ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ–). - - - - Path to Git executable (optional): - ШлÑÑ… да двайковага файла Git (неабавÑзкова): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ - - - - Activate Addon Manager options intended for developers of new Addons. - Задзейнічаць налады ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ–, ÑÐºÑ–Ñ Ð¿Ñ€Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ Ð´Ð»Ñ Ñ€Ð°Ñпрацоўкі новых дадаткаў. - - - - Addon developer mode - РÑжым раÑпрацоўкі дадаткаў - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Выдаліць абраны Ð¼Ð°ÐºÑ€Ð°Ñ Ñ†Ñ– варштат - - - - Install - УÑталÑваць - - - - Uninstall - Выдаліць - - - - Update - Ðбнавіць - - - - Run Macro - Выканаць Ð¼Ð°ÐºÑ€Ð°Ñ - - - - Change branch - ЗмÑніць галіну - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Кіраваць залежнаÑцÑмі Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð¿Ð°ÐºÐµÑ‚Ñ‹ Python былі ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð»Ð°ÐºÐ°Ð»ÑŒÐ½Ð° Кіраваннем дадаткамі Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð²Ð°Ð»ÑŒÐ½ÐµÐ½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð°ÑцÑÑž дадаткаў. МеÑца ÑžÑтаноўкі: - - - - Package name - Ðазва пакета - - - - Installed version - УÑталÑÐ²Ð°Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ - - - - Available version - ДаÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ - - - - Used by - Ужываецца Ñž - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Зорачка (*) Ñž Ñлупку "Ужываецца Ñž" паказвае на неабавÑзковую залежнаÑць. ЗвÑрніце ўвагу, што ўжываецца толькі Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñаў прамога Ñ–Ð¼Ð¿Ð°Ñ€Ñ‚Ð°Ð²Ð°Ð½Ð½Ñ Ñž дадатку. Магчыма, такÑама былі ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ñ–Ð½ÑˆÑ‹Ñ Ð¿Ð°ÐºÐµÑ‚Ñ‹ Python, ад Ñкіх залежаць гÑÑ‚Ñ‹Ñ Ð¿Ð°ÐºÐµÑ‚Ñ‹. - - - - Update all available - УÑе даÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ– - - - - SelectFromList - - - Dialog - ДыÑлогавае акно - - - - TextLabel - ТÑкÑтавы Ð½Ð°Ð´Ð¿Ñ–Ñ - - - - UpdateAllDialog - - - Updating Addons - Ðбнавіць дадаткі - - - - Updating out-of-date addons... - Ðбнавіць ÑаÑтарÑÐ»Ñ‹Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑ–... - - - - addContentDialog - - - Content Item - ЗмеÑÑ‚ Ñлемента - - - - Content type: - Тып змеÑту: - - - - Macro - ÐœÐ°ÐºÑ€Ð°Ñ - - - - Preference Pack - Пакет перавагі - - - - Workbench - Варштат - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Калі гÑта адзінае, што Ñ‘Ñць у дадатку, уÑе аÑÑ‚Ð°Ñ‚Ð½Ñ–Ñ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ быць уÑÐ¿Ð°Ð´ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ð°Ð´ верхнÑга ўзроўню, Ñ– Ñ–Ñ… не трÑба паказваць тут. - - - - This is the only item in the Addon - ГÑта адзіны Ñлемент у дадатку - - - - Main macro file - Файл галоўнага макраÑу - - - - The file with the macro's metadata in it - Файл з метададзенымі макраÑа - - - - - - Browse... - ÐглÑд... - - - - Preference Pack Name - Ðазва Пакета перавагі - - - - Workbench class name - Ðазва клаÑа варштату - - - - Class that defines "Icon" data member - КлаÑ, Ñкі вызначае Ñлемент дадзеных "Гузік" - - - - Subdirectory - Укладзены каталог - - - - Optional, defaults to name of content item - ÐеабавÑзкова, першапачаткова ўжываецца назва Ñлемента змеÑту - - - - Icon - Гузік - - - - Optional, defaults to inheriting from top-level Addon - ÐеабавÑзкова, першапачаткова ÑžÑпадкавана ад дадатку верхнÑга ўзроўню - - - - Tags... - Меткі... - - - - Dependencies... - ЗалежнаÑці... - - - - FreeCAD Versions... - ВерÑÑ–Ñ– FreeCAD... - - - - Other Metadata - Ð†Ð½ÑˆÑ‹Ñ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - ÐдлюÑтроўваецца Ñž ÑпіÑе дадаткаў ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ–. Ðе варта ўключаць Ñлова "FreeCAD". - - - - Version - ВерÑÑ–Ñ - - - - Description - ÐпіÑанне - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Падтрымліваюцца Ñтылі Semantic (1.2.3-бÑта-верÑÑ–Ñ) ці CalVer (2022.08.30) - - - - Set to today (CalVer style) - Задаць на ÑÑ‘Ð½Ð½Ñ (Ñтыль CalVer) - - - - Display Name - ÐдлюÑтраваць назву - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Ð›ÑŽÐ±Ñ‹Ñ Ð¿Ð°Ð»Ñ–, ÑÐºÑ–Ñ Ð¿Ð°ÐºÑ–Ð½ÑƒÑ‚Ñ‹Ñ Ð¿ÑƒÑтымі, уÑпадкоўваюцца з метададзеных дадаткаў верхнÑга ўзроўню, таму Ñ‚Ñхнічна Ñны ÑžÑе неабавÑзковыÑ. Ð”Ð»Ñ Ð´Ð°Ð´Ð°Ð´Ñ‚ÐºÐ°Ñž з некалькімі Ñлементамі змеÑту, кожны Ñлемент павінен утрымліваць унікальнае ÐдлюÑтроўванае Ñ–Ð¼Ñ Ñ– ÐпіÑанне. - - - - add_toolbar_button_dialog - - - Add button? - Дадаць кнопку? - - - - Add a toolbar button for this macro? - Дадаць кнопку на панÑль інÑтрументаў Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð°Ñа? - - - - Yes - Так - - - - No - Ðе - - - - Never - Ðіколі - - - - change_branch - - - Change Branch - ЗмÑніць галіну - - - - Change to branch: - ЗмÑніць на галіну: - - - - copyrightInformationDialog - - - Copyright Information - Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð°Ð± аўтарÑкіх правах - - - - Copyright holder: - Уладальнік аўтарÑкіх праў: - - - - Copyright year: - Год аўтарÑкіх праў: - - - - personDialog - - - Add Person - Дадаць аÑобу - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Суправаджальнік - той, у каго Ñ‘Ñць бÑгучы доÑтуп да фікÑацыі Ñž гÑтым праекце. -Ðўтар - любы іншы чалавек, Ñкога вы жадаеце ўключыць. - - - - Name: - Ðазва: - - - - Email: - Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾ÑˆÑ‚Ð°: - - - - Email is required for maintainers, and optional for authors. - Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾ÑˆÑ‚Ð° Ð½ÐµÐ°Ð±Ñ…Ð¾Ð´Ð½Ð°Ñ Ð´Ð»Ñ Ñуправаджальнікаў, Ñ– неабавÑÐ·ÐºÐ¾Ð²Ð°Ñ Ð´Ð»Ñ Ð°ÑžÑ‚Ð°Ñ€Ð°Ñž. - - - - proxy_authentication - - - Proxy login required - ПатрÑбна Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка прокÑÑ– - - - - Proxy requires authentication - ПрокÑÑ– патрабуе аўтÑнтыфікацыі - - - - Proxy: - ПрокÑÑ–: - - - - Placeholder for proxy address - ЗапаўнÑльнік Ð´Ð»Ñ Ð°Ð´Ñ€Ð°Ñа прокÑÑ– - - - - Realm: - ВоблаÑць: - - - - Placeholder for proxy realm - ЗапаўнÑльнік Ð´Ð»Ñ Ð²Ð¾Ð±Ð»Ð°Ñці прокÑÑ– - - - - Username - Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка - - - - Password - Пароль - - - - selectLicenseDialog - - - Select a license - Ðбраць ліцÑнзію - - - - About... - Пра праграму... - - - - License name: - Ðазва ліцÑнзіі: - - - - Path to license file: - ШлÑÑ… да файла ліцÑнзіі: - - - - (if required by license) - (калі патрабуецца ліцÑнзіÑ) - - - - Browse... - ÐглÑд... - - - - Create... - Стварыць... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Ðбраць ПанÑль інÑтрументаў - - - - Select a toolbar to add this macro to: - Ðбраць панÑль інÑтрументаў, каб дадаць макраÑ: - - - - Ask every time - Спытаць кожны раз - - - - toolbar_button - - - - Add button? - Дадаць кнопку? - - - - Add a toolbar button for this macro? - Дадаць кнопку на панÑль інÑтрументаў Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð°Ñа? - - - - Yes - Так - - - - No - Ðе - - - - Never - Ðіколі - - - - AddonsInstaller - - - Starting up... - ЗапуÑк... - - - - Worker process {} is taking a long time to stop... - Працоўнаму працÑÑу {} патрабуецца шмат чаÑу, каб Ñпыніцца... - - - - Previous cache process was interrupted, restarting... - - ПапÑÑ€Ñдні працÑÑ ÐºÑшу быў перапынены, перазапуÑк... - - - - - Custom repo list changed, forcing recache... - - КарыÑтальніцкі ÑÐ¿Ñ–Ñ Ñховішча зменены, паўторнае абнаўленне кÑшу... - - - - - Addon manager - Кіраванне дадаткамі - - - - You must restart FreeCAD for changes to take effect. - Ð’Ñ‹ павінны перазапуÑціць FreeCAD, каб змены былі ўжытыÑ. - - - - Restart now - ПеразапуÑціць зараз - - - - Restart later - ПеразапуÑціць пазней - - - - - Refresh local cache - Ðбнавіць лакальны кÑш - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Ðбнаўленне кÑшу... - - - - - Checking for updates... - Праверыць наÑўнаÑць абнаўленнÑÑž... - - - - Temporary installation of macro failed. - ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° чаÑовага ÑžÑталÑÐ²Ð°Ð½Ð½Ñ Ð¼Ð°ÐºÑ€Ð°Ñа. - - - - - Close - Зачыніць - - - - Update all addons - Ðбнавіць уÑе дадаткі - - - - Check for updates - Праверыць наÑўнаÑць абнаўленнÑÑž - - - - Python dependencies... - ЗалежнаÑці аÑÑÑ€Ð¾Ð´Ð´Ð·Ñ Python... - - - - Developer tools... - ІнÑтрумент раÑпрацоўкі... - - - - Apply %n available update(s) - ПрымÑніць %n даÑтупных абнаўленнÑÑž - - - - No updates available - ДаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ– адÑутнічаюць - - - - - - Cannot launch a new installer until the previous one has finished. - Ðе атрымалаÑÑ Ð·Ð°Ð¿ÑƒÑціць новы ÑžÑтаноўшчык, каб Ñкончыць працу папÑÑ€ÑднÑга. - - - - - - - Maintainer - Суправаджальнік - - - - - - - Author - Ðўтар - - - - New Python Version Detected - Ð’Ñ‹Ñўлена Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Падобна на тое, што гÑта першы раз, калі гÑÑ‚Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Python ужываецца з Кіраваннем дадаткамі. Ці жадаеце вы ÑžÑталÑваць Ð´Ð»Ñ Ñго Ñ‚Ñ‹Ñ Ð¶ аўтаматычна ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð°Ñці? - - - - Processing, please wait... - Ðпрацоўка, калі лаÑка, пачакайце... - - - - - Update - Ðбнавіць - - - - Updating... - Ðбнаўленне... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Ðе атрымалаÑÑ Ñ–Ð¼Ð¿Ð°Ñ€Ñ‚Ð°Ð²Ð°Ñ†ÑŒ QtNetwork - падобна на тое, што ён не ÑžÑталÑваны Ñž вашай ÑÑ–ÑÑ‚Ñме. Ваш паÑтаўшчык можа мець пакет Ð´Ð»Ñ Ð³Ñтай залежнаÑці (чаÑта названы Ñк "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Ðе атрымалаÑÑ Ð¿ÐµÑ€Ð°ÑžÑ‚Ð²Ð°Ñ€Ñ‹Ñ†ÑŒ паказаны порт прокÑÑ– '{}' у нумар порта - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Памылка налады: уÑталÑваны ÑžÐ·Ð°ÐµÐ¼Ð°Ð²Ñ‹ÐºÐ»ÑŽÑ‡Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ прокÑÑ–. Скінуць да першапачатковага значÑннÑ. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Памылка налады: паказаны карыÑтальніцкі прокÑÑ–, але прокÑÑ– не прадÑтаўлены. Скінуць да першапачатковага значÑннÑ. - - - - Addon Manager: Unexpected {} response from server - Кіраванне дадаткамі: Ðечаканы адказ {} ад Ñервера - - - - Error with encrypted connection - Памылка з зашыфраваным злучÑннем - - - - - - Confirm remove - Пацвердзіць выдаленне - - - - Are you sure you want to uninstall {}? - Ð’Ñ‹ ўпÑўненыÑ, што жадаеце выдаліць {}? - - - - - - Removing Addon - Выдаленне Дадатку - - - - Removing {} - Выдаленне {} - - - - - Uninstall complete - Выдаленне завершана - - - - - Uninstall failed - Ðе атрымалаÑÑ Ð²Ñ‹Ð´Ð°Ð»Ñ–Ñ†ÑŒ - - - - Version {version} installed on {date} - ВерÑÑ–Ñ {version} уÑталÑÐ²Ð°Ð½Ð°Ñ {date} - - - - Version {version} installed - ВерÑÑ–Ñ {version} уÑталÑÐ²Ð°Ð½Ð°Ñ - - - - Installed on {date} - Дата ÑžÑталÑÐ²Ð°Ð½Ð½Ñ {date} - - - - - - - Installed - УÑталÑвана - - - - Currently on branch {}, name changed to {} - У бÑгучы Ñ‡Ð°Ñ Ð·Ð½Ð°Ñ…Ð¾Ð´Ð·Ñ–Ñ†Ñ†Ð° Ñž галіне {}, назва Ð·Ð¼ÐµÐ½ÐµÐ½Ð°Ñ Ð½Ð° {} - - - - Git tag '{}' checked out, no updates possible - Метка Git'{}' праверана, абнаўленнÑÑž нÑма - - - - Update check in progress - Выконваецца праверка абнаўленнÑÑž - - - - Installation location - МеÑцазнаходжанне ÑžÑтаноўкі - - - - Repository URL - URL-Ð°Ð´Ñ€Ð°Ñ Ñховішча - - - - Changed to branch '{}' -- please restart to use Addon. - Зменены на галіну '{}' -- калі лаÑка, перазапуÑціце, каб ужыць Дадатак. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Дадатак быў абноўлены. -ЗапуÑціце FreeCAD нанова, каб убачыць змены. - - - - Disabled - Ðдключана - - - - Currently on branch {}, update available to version {} - У бÑгучы Ñ‡Ð°Ñ Ñƒ галіне {}, даÑтупна абнаўленне да верÑÑ–Ñ– {} - - - - Update available to version {} - ДаÑтупна абнаўленне да верÑÑ–Ñ– {} - - - - This is the latest version available - ГÑта апошнÑÑ Ð´Ð°ÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ - - - - WARNING: This addon is obsolete - УВÐГÐ: ГÑты дадатак ÑаÑтарÑлы - - - - WARNING: This addon is Python 2 only - УВÐГÐ: гÑты дадатак прызначаны толькі Ð´Ð»Ñ Python 2 - - - - WARNING: This addon requires FreeCAD {} - УВÐГÐ: гÑты дадатак патрабуе FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - УВÐГÐ: ГÑты дадатак у бÑгучы Ñ‡Ð°Ñ ÑƒÑталÑваны, але адключаны. ÐаціÑнуць кнопку 'Уключыць', каб зноў уключыць Ñго. - - - - This Addon will be enabled next time you restart FreeCAD. - ГÑты Дадатак будзе ўключаны пры наÑтупным перазапуÑку FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - ГÑты Дадатак будзе адключаны пры наÑтупным перазапуÑку FreeCAD. - - - - - - Success - ПаÑпÑхова завершана - - - - Install - УÑталÑваць - - - - Uninstall - Выдаліць - - - - Enable - Уключыць - - - - Disable - Ðдключыць - - - - - Check for update - Праверыць абнаўленне - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Праца - - - - Change branch... - ЗмÑніць галіну... - - - - Return to package list - Ð’Ñрнуцца да ÑпіÑу пакетаў - - - - Checking connection - Праверка злучÑÐ½Ð½Ñ - - - - Checking for connection to GitHub... - Праверка злучÑÐ½Ð½Ñ Ð· GitHub... - - - - Connection failed - Ðе атрымалаÑÑ Ð·Ð»ÑƒÑ‡Ñ‹Ñ†Ñ†Ð° - - - - Missing dependency - ЗалежнаÑці адÑутнічаюць - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Ðе атрымалаÑÑ Ñ–Ð¼Ð¿Ð°Ñ€Ñ‚Ð°Ð²Ð°Ñ†ÑŒ QtNetwork -- падрабÑзнаÑці глÑдзіце Ñž ПраглÑдзе Ñправаздачы. -Кіраванне дадаткамі недаÑтупнае. - - - - Other... - For providing a license other than one listed - Іншы... - - - - Select the corresponding license file in your Addon - ÐбÑрыце адпаведны файл ліцÑнзіі Ñž вашым Дадатку - - - - Location for new license file - МеÑцазнаходжанне новага файла ліцÑнзіі - - - - Received {} response code from server - Ðтрыманы {} код адказу Ñервера - - - - Failed to install macro {} - Ðе атрымалаÑÑ ÑžÑталÑваць Ð¼Ð°ÐºÑ€Ð°Ñ {} - - - - Failed to create installation manifest file: - - Ðе атрымалаÑÑ Ñтварыць файл маніфеÑту ÑžÑтаноўкі: - - - - - Unrecognized content kind '{}' - Ðепрызнаны тып змеÑту '{}' - - - - Unable to locate icon at {} - Ðемагчыма знайÑці гузік у {} - - - - Select an icon file for this content item - Ðбраць файл гузіку Ð´Ð»Ñ Ð³Ñтага Ñлемента змеÑту - - - - - - {} is not a subdirectory of {} - {} не з'ÑўлÑецца ўкладзеным каталогам {} - - - - Select the subdirectory for this content item - Ðбраць укладзены каталог Ð´Ð»Ñ Ð³Ñтага Ñлемента змеÑту - - - - Automatic - Ðўтаматычна - - - - - Workbench - Варштат - - - - Addon - Дадатак - - - - Python - Python - - - - Yes - Так - - - - Internal Workbench - Унутраны варштат - - - - External Addon - Вонкавы Дадатак - - - - Python Package - Пакет Python - - - - - Other... - Іншы... - - - - Too many to list - Ð¡Ð¿Ñ–Ñ Ð·Ð°ÑˆÐ¼Ð°Ñ‚ доўгі Ð´Ð»Ñ Ð°Ð´Ð»ÑŽÑÑ‚Ñ€Ð°Ð²Ð°Ð½Ð½Ñ - - - - - - - - - Missing Requirement - ÐдÑутнічаюць патрабаванні - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Дадатак '{}' патрабуе '{}', ÑÐºÑ–Ñ Ð½ÐµÐ´Ð°ÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñž вашай копіі FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Дадатак '{}' патрабуе наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð²Ð°Ñ€ÑˆÑ‚Ð°Ñ‚Ñ‹, ÑÐºÑ–Ñ Ð½ÐµÐ´Ð°ÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñž вашай копіі FreeCAD: - - - - Press OK to install anyway. - ÐаціÑніце ОК, каб уÑталÑваць у любым выпадку. - - - - - Incompatible Python version - ÐеÑумÑÑˆÑ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Ð”Ð»Ñ Ð³Ñтага дадатку патрабуюцца пакеты Python, ÑÐºÑ–Ñ Ð½Ðµ ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ñ– не могуць быць уÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð°ÑžÑ‚Ð°Ð¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ð°. -Каб ужыць гÑты дадатак, вы павінны ÑžÑталÑваць наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð¿Ð°ÐºÐµÑ‚Ñ‹ Python уручную: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Дадатак (ці адна з Ñго залежнаÑці) патрабуе Python {}.{}, Ñ– Ð²Ð°ÑˆÐ°Ñ ÑÑ–ÑÑ‚Ñма Ð·Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð½Ð°Ñ {}.{}. УÑтаноўка адменена. - - - - Optional dependency on {} ignored because it is not in the allow-list - ÐеабавÑÐ·ÐºÐ¾Ð²Ð°Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð°Ñць ад {} прапуÑкаецца, паколькі Ñе нÑма Ñž ÑпіÑе дазволеных - - - - - Installing dependencies - УÑтаноўка залежнаÑці - - - - - Cannot execute Python - Ðе атрымалаÑÑ Ð²Ñ‹ÐºÐ°Ð½Ð°Ñ†ÑŒ Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Ðе атрымалаÑÑ Ð°ÑžÑ‚Ð°Ð¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ð° знайÑці ваш выконваемы файл Python, альбо шлÑÑ… зададзены нÑправільна. Калі лаÑка, праверце налады Перавагі ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ– Ð´Ð»Ñ Ð¿Ð°ÐºÐ°Ð·Ð°Ð½Ð°Ð³Ð° шлÑху да Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Ðе атрымалаÑÑ ÑžÑталÑваць залежнаÑці. Ці працÑгнуць уÑтаноўку Ñž любым выпадку {}? - - - - - Cannot execute pip - Ðе атрымалаÑÑ Ð²Ñ‹ÐºÐ°Ð½Ð°Ñ†ÑŒ праграму pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Ðе атрымалаÑÑ Ð²Ñ‹ÐºÐ°Ð½Ð°Ñ†ÑŒ каманду pip, ÑÐºÐ°Ñ Ð¼Ð¾Ð¶Ð° адÑутнічаць у вашым уÑталÑваным Python. -Калі лаÑка, пераканайцеÑÑ, што Ñž вашай ÑÑ–ÑÑ‚Ñме ÑžÑталÑваны pip, Ñ– паўтарыце Ñпробу. -ÐÑÑžÐ´Ð°Ð»Ð°Ñ ÐºÐ°Ð¼Ð°Ð½Ð´Ð° была: - - - - - Continue with installation of {} anyway? - Ці працÑгнуць уÑтаноўку Ñž любым выпадку {}? - - - - - Package installation failed - Ðе атрымалаÑÑ ÑžÑталÑваць пакет - - - - See Report View for detailed failure log. - ПадрабÑзны чаÑÐ¾Ð¿Ñ–Ñ Ð·Ð±Ð¾ÑÑž глÑдзіце Ñž ПраглÑдзе Ñправаздачы. - - - - Installing Addon - УÑтаноўка дадатку - - - - Installing FreeCAD Addon '{}' - ÐŽÑтаноўка дадаткаў FreeCAD '{}' - - - - Cancelling - СкаÑаванне - - - - Cancelling installation of '{}' - СкаÑаванне ÑžÑтаноўкі '{}' - - - - {} was installed successfully - {} быў паÑпÑхова ÑžÑталÑваны - - - - - Installation Failed - УÑталÑваць не атрымалаÑÑ - - - - Failed to install {} - Ðе атрымалаÑÑ ÑžÑталÑваць {} - - - - - Create new toolbar - Стварыць новую панÑль інÑтрументаў - - - - - A macro installed with the FreeCAD Addon Manager - МакраÑÑ‹, Ñкі ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð· дапамогай ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ– FreeCAD - - - - - Run - Indicates a macro that can be 'run' - Выканаць - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Ðемагчыма прачытаць Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ð· GitHub: праверце Ñваё інтÑрнÑÑ‚-злучÑнне Ñ– налады прокÑÑ–, Ñ– паўтарыце Ñпробу. - - - - XML failure while reading metadata from file {} - Ðе атрымалаÑÑ Ð¿Ñ€Ð°Ñ‡Ñ‹Ñ‚Ð°Ñ†ÑŒ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ð· файла XML {} - - - - Invalid metadata in file {} - Ð¥Ñ–Ð±Ð½Ñ‹Ñ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ñž файле {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - УВÐГÐ: шлÑÑ…, Ñкі паказаны Ñž метададзеных package.xml, не адпавÑдае бÑгучай праверанай галіны. - - - - Name - Ðазва - - - - Class - ÐšÐ»Ð°Ñ - - - - Description - ÐпіÑанне - - - - Subdirectory - Укладзены каталог - - - - Files - Файлы - - - - Select the folder containing your Addon - Ðбраць каталог, Ñкі змÑшчае ваш Дадатак - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Vermin адÑутнічае, ÑкаÑаванне аперацыі. - - - - Scanning Addon for Python version compatibility - Сканаванне Дадатку на ÑумÑшчальнаÑць з верÑÑ–Ñй Python - - - - Minimum Python Version Detected - Ð’Ñ‹Ñўлена Ð½Ð°Ð¹Ð¼ÐµÐ½ÑˆÐ°Ñ Ð²ÐµÑ€ÑÑ–Ñ Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin аўтаматычна выÑвіў патрÑбную верÑÑ–ÑŽ Python 3.{} - - - - Install Vermin? - УÑталÑваць Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Ð”Ð»Ñ Ð°ÑžÑ‚Ð°Ð¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ð°Ð³Ð° вызначÑÐ½Ð½Ñ Ð¿Ð°Ñ‚Ñ€Ñбнай верÑÑ–Ñ– Python Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑƒ патрабуецца Vermin (https://pypi.org/project/vermin/). ОК, каб уÑталÑваць? - - - - Attempting to install Vermin from PyPi - Спроба ÑžÑталÑваць Vermin з PyPi - - - - - Installation failed - УÑталÑваць не атрымалаÑÑ - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Ðе атрымалаÑÑ ÑžÑталÑваць Vermin -- праверце ПраглÑд Ñправаздачы, каб атрымаць падрабÑзную інфармацыю. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Ðе атрымалаÑÑ Ñ–Ð¼Ð¿Ð°Ñ€Ñ‚Ð°Ð²Ð°Ñ†ÑŒ vermin паÑÐ»Ñ ÑžÑтаноўкі -- не атрымалаÑÑ Ð¿Ñ€Ð°Ñканаваць Дадатак. - - - - Select an icon file for this package - Ðбраць файл гузіку Ð´Ð»Ñ Ð³Ñтага пакету - - - - Filter is valid - Фільтр дапушчальны - - - - Filter regular expression is invalid - Хібны Ñ€ÑгулÑрны выраз фільтра - - - - Search... - Пошук... - - - - Click for details about package {} - ÐаціÑніце, каб атрымаць падрабÑзную інфармацыю пра пакет {} - - - - Click for details about workbench {} - ÐаціÑніце, каб атрымаць падрабÑзную інфармацыю пра варштат {} - - - - Click for details about macro {} - ÐаціÑніце, каб атрымаць падрабÑзную інфармацыю пра Ð¼Ð°ÐºÑ€Ð°Ñ {} - - - - Maintainers: - Суправаджальнікі: - - - - Tags - Меткі - - - - {} ★ on GitHub - {} ★ на GitHub - - - - No ★, or not on GitHub - Без ★, альбо не на GitHub - - - - Created - Створана - - - - Updated - Ðбноўлена - - - - Score: - ÐцÑнкі: - - - - - Up-to-date - ÐÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ - - - - - - - - Update available - ДаÑтупна абнаўленне - - - - - Pending restart - У чаканні перазапуÑку - - - - - DISABLED - ВЫКЛЮЧÐÐЫ - - - - Installed version - УÑталÑÐ²Ð°Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ - - - - Unknown version - ÐевÑÐ´Ð¾Ð¼Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ - - - - Installed on - УÑталÑваны на - - - - Available version - ДаÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ - - - - Filter by... - Фільтраваць па... - - - - Addon Type - Тып дадатку - - - - - Any - Любы - - - - Macro - ÐœÐ°ÐºÑ€Ð°Ñ - - - - Preference Pack - Пакет перавагі - - - - Installation Status - Стан уÑтаноўкі - - - - Not installed - Ðе ÑžÑталÑваны - - - - Filter - Фільтр - - - - DANGER: Developer feature - ÐЕБЯСПЕКÐ: Ñ„ÑƒÐ½ÐºÑ†Ñ‹Ñ Ñ€Ð°Ñпрацоўкі - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - ÐЕБЯСПЕКÐ: ПераключÑнне галін прызначана Ð´Ð»Ñ Ñ€Ð°Ñпрацоўкі Ñ– бÑта-Ñ‚ÑÑтараў, Ñ– можа прывеÑці да Ð¿Ð°ÑˆÐºÐ¾Ð´Ð¶Ð°Ð½Ð½Ñ Ð´Ð°ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñž, ÑÐºÑ–Ñ Ð½Ðµ ÑумÑÑˆÑ‡Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð· зваротнай ÑувÑззю, неÑтабільнаÑці, збоÑÑž Ñ–/ці заўчаÑнай цеплавой Ñмерці ÑуÑвету. Ð’Ñ‹ жадаеце працÑгнуць? - - - - There are local changes - ÐÑць Ð»Ð°ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð¼ÐµÐ½Ñ‹ - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - УВÐГÐ: у Ñховішчы Ñ‘Ñць незафікÑÐ°Ð²Ð°Ð½Ñ‹Ñ Ð»Ð°ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð¼ÐµÐ½Ñ‹. Ð’Ñ‹ ўпÑўненыÑ, што жадаеце змÑніць галіну (Ñ– прынеÑці змены з Ñабою)? - - - - Local - Table header for local git ref name - Лакальны - - - - Remote tracking - Table header for git remote tracking branch name - Падаленае адÑочванне - - - - Last Updated - Table header for git update date - ÐпошнÑе абнаўленне - - - - Installation of Python package {} failed - Ðе атрымалаÑÑ ÑžÑталÑваць пакет Python {} - - - - Installation of optional package failed - Ðе атрымалаÑÑ ÑžÑталÑваць неабавÑзковы пакет - - - - Installing required dependency {} - ÐŽÑтаноўка неабходнай залежнаÑці {} - - - - Installation of Addon {} failed - Ðе атрымалаÑÑ ÑžÑталÑваць дадатак {} - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Ðе атрымалаÑÑ Ð´Ñкадаваць файл {} Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑƒ '{}' - - - - Any dependency information in this file will be ignored - Ð›ÑŽÐ±Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° залежнаÑці Ñž файле будзе Ð¿Ñ€Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð½Ð°Ñ - - - - Unable to open macro wiki page at {} - Ðемагчыма адчыніць вікі-Ñтаронку макраÑу Ñž {} - - - - Unable to fetch the code of this macro. - Ðемагчыма вынÑць код макраÑа. - - - - Unable to retrieve a description from the wiki for macro {} - Ðемагчыма атрымаць апіÑанне з вікі-Ñтаронкі Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð°Ñа {} - - - - Unable to open macro code URL {} - Ðемагчыма адчыніць URL-Ð°Ð´Ñ€Ð°Ñ {} коду макраÑа - - - - Unable to fetch macro-specified file {} from {} - Ðемагчыма вынÑць паказаны файл макраÑа {} з {} - - - - Could not locate macro-specified file {} (expected at {}) - Ðе атрымалаÑÑ Ð·Ð½Ð°Ð¹Ñці паказаны файл макраÑа {} (чакаецца Ñž {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Ðепрызнаны ўнутраны варштат '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - ПапÑÑ€Ñджанне раÑпрацоўкі дадатку: URL-Ð°Ð´Ñ€Ð°Ñ Ñховішча, Ñкі ÑžÑталÑваны Ñž файле package.xml Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑƒ {} ({}) не адпавÑдае ÑпаÑылку, з Ñкога ён быў вынÑты ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - ПапÑÑ€Ñджанне раÑпрацоўкі дадатку: галіна Ñховішча, ÑÐºÐ°Ñ ÑžÑталÑвана Ñž файле package.xml Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑƒ {} ({}) не адпавÑдае галіне, з Ñкой Ñна была вынÑта ({}) - - - - - Got an error when trying to import {} - ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры Ñпробе імпартаваць {} - - - - An unknown error occurred - ÐдбылаÑÑ Ð½ÐµÐ²ÑÐ´Ð¾Ð¼Ð°Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° - - - - Could not find addon {} to remove it. - Ðе атрымалаÑÑ Ð·Ð½Ð°Ð¹Ñці дадатак {} каб выдаліць. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Ðе атрымалаÑÑ Ð²Ñ‹ÐºÐ°Ð½Ð°Ñ†ÑŒ ÑцÑнар uninstall.py дадатку. ПрыÑтупаем да выдаленнÑ... - - - - Removed extra installed file {} - Выдалены дадаткова ÑžÑталÑваны файл {} - - - - Error while trying to remove extra installed file {} - Памылка пры Ñпробе выдаліць дадаткова ÑžÑталÑваны файл {} - - - - Error while trying to remove macro file {}: - Памылка пры Ñпробе выдаліць файл макраÑа {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Ðе атрымалаÑÑ Ð¿Ð°Ð´Ð»ÑƒÑ‡Ñ‹Ñ†Ñ†Ð° да GitHub. Калі лаÑка, праверце вашае падключÑнне Ñ– налады прокÑÑ–. - - - - WARNING: Duplicate addon {} ignored - УВÐГÐ: Паўторны дадатак {} прапушчаны - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры абнаўленні макраÑаў з GitHub, Ñпроба зрабіць clean checkout... - - - - Attempting to do a clean checkout... - Спроба выканаць clean checkout... - - - - Clean checkout succeeded - ПаÑпÑховы clean checkout - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Ðе атрымалаÑÑ Ð°Ð±Ð½Ð°Ð²Ñ–Ñ†ÑŒ макраÑÑ‹ з GitHub -- паÑпрабуйце ачыÑціць кÑш ÐšÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ°Ð¼Ñ–. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Памылка злучÑÐ½Ð½Ñ Ð· Wiki, FreeCAD Ñž бÑгучы Ñ‡Ð°Ñ Ð½Ðµ можа атрымаць ÑÐ¿Ñ–Ñ Ð¼Ð°ÐºÑ€Ð°Ñаў Wiki - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Ðе атрымалаÑÑ Ð¿Ñ€Ð°Ñ‡Ñ‹Ñ‚Ð°Ñ†ÑŒ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ð· {name} - - - - Failed to fetch code for macro '{name}' - Ðе атрымалаÑÑ Ð²Ñ‹Ð½Ñць код Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð°Ñа '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Кіраванне дадаткамі: працоўнаму працÑÑу не атрымалаÑÑ Ð²Ñ‹Ð½Ñць {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Ð”Ð»Ñ {num_macros} макраÑаў ÑкончыўÑÑ Ñ‡Ð°Ñ Ñ‡Ð°ÐºÐ°Ð½Ð½Ñ {num_failed} Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð°Ð¿Ñ€Ð°Ñ†Ð¾ÑžÐºÑ– - - - - Addon Manager: a worker process failed to halt ({name}) - Кіраванне дадаткамі: не атрымалаÑÑ Ñпыніць працоўны працÑÑ ({name}) - - - - Timeout while fetching metadata for macro {} - Выйшаў Ñ‡Ð°Ñ Ñ‡Ð°ÐºÐ°Ð½Ð½Ñ Ð¿Ñ€Ñ‹ выманні метададзеных з макраÑу {} - - - - Failed to kill process for macro {}! - - Ðе атрымалаÑÑ Ð·Ð°Ð²Ñршыць працÑÑ Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð°Ñа {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Ðе атрымалаÑÑ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ñ†ÑŒ ÑтатыÑтыку па дадатку з {} -- дакладнай будзе толькі ўпарадкаванне па алфавіце - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Ðе атрымалаÑÑ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ñ†ÑŒ ацÑнкі дадаткаў з '{}' -- упарадкаванне па ацÑнках завÑршылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ°Ð¹ - - - - - Repository URL - Preferences header for custom repositories - URL-Ð°Ð´Ñ€Ð°Ñ Ñховішча - - - - Branch name - Preferences header for custom repositories - Ðазва галіны - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - РÑзервовае капіраванне зыходнага каталога Ñ– паўторнае кланаванне - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Ðе атрымалаÑÑ Ð¿ÐµÑ€Ð°Ð½Ð°Ð·Ð²Ð°Ñ†ÑŒ галіну Git з наÑтупным паведамленнем: - - - - Installing - УÑталÑванне - - - - Succeeded - ПаÑпÑхова - - - - Failed - Ðе атрымалаÑÑ - - - - Update was cancelled - Ðбнаўленне было ÑкаÑавана - - - - some addons may have been updated - магчыма, Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÑ– былі Ð°Ð±Ð½Ð¾ÑžÐ»ÐµÐ½Ñ‹Ñ - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Загрузка інфармацыі Ð´Ð»Ñ {} з вікі-Ñтаронкі ÑÑ–ÑÑ‚Ñмы макраÑаў FreeCAD... - - - - Loading page for {} from {}... - Загрузка Ñтаронкі {} з {}... - - - - Failed to download data from {} -- received response code {}. - Ðе атрымалаÑÑ Ñпампаваць Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ð· {} - атрыманы код адказу {}. - - - - Composite view - Складовы выглÑд - - - - Expanded view - Пашыраны выглÑд - - - - Compact view - Кампактны выглÑд - - - - Alphabetical - Sort order - Па алфавіце - - - - Last Updated - Sort order - ÐпошнÑе абнаўленне - - - - Date Created - Sort order - Дата ÑтварÑÐ½Ð½Ñ - - - - GitHub Stars - Sort order - Зоркі на GitHub - - - - Score - Sort order - ÐцÑнкі - - - - Std_AddonMgr - - - &Addon manager - &Кіраванне дадаткамі - - - - Manage external workbenches, macros, and preference packs - Кіраваць вонкавымі варштатамі, макраÑамі Ñ– пакетамі пераваг - - - - AddonInstaller - - - Finished removing {} - Скончана выдаленне {} - - - - Failed to remove some files - Ðе атрымалаÑÑ Ð²Ñ‹Ð´Ð°Ð»Ñ–Ñ†ÑŒ Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ - - - - Addons installer - - - Finished updating the following addons - Скончана абнаўленне наÑтупных дадаткаў - - - - Workbench - - - Auto-Created Macro Toolbar - ПанÑль інÑтрументаў макраÑаў, ÑÐºÑ–Ñ Ñтвараюцца аўтаматычна - - - - QObject - - - Addon Manager - Кіраванне дадаткамі - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_bg.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_bg.qm deleted file mode 100644 index b952efbc82a1cc68980a43b113b7e105e888a78d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14373 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_bg.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_bg.ts deleted file mode 100644 index 2f157dd6cf..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_bg.ts +++ /dev/null @@ -1,424 +0,0 @@ - - - - - AddonInstaller - - - Installed location - ИнÑталационна папка - - - - AddonsInstaller - - - Unable to fetch the code of this macro. - Кодът на макроÑа не може да Ñе извлече. - - - - Unable to retrieve a description for this macro. - ОпиÑанието на макроÑа не може да Ñе извлече. - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - Добавките, които могат да бъдат инÑталирани тук, официално не Ñе ÑвÑват чаÑÑ‚ от FreeCAD и не Ñа проверÑвани от екипа на FreeCAD. Уверете Ñе, че знаете какво точно инÑталирате! - - - - Addon manager - Управител на добавките - - - - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - ТрÑбва да реÑтартирате FreeCAD, за да имат ефект извършените промени. ÐатиÑнете Ок, за да реÑтартирате Ñега FreeCAD, или Отказ, за да реÑтартирате по-къÑно. - - - - Checking for updates... - Проверка за обновÑване... - - - - Apply - Прилагане - - - - update(s) - обновÑÐ²Ð°Ð½Ð¸Ñ - - - - No update available - ÐÑма обновÑване на разположение - - - - Macro successfully installed. The macro is now available from the Macros dialog. - УÑпешно инÑталиран макроÑ. МакроÑÑŠÑ‚ Ñега е наличен от Ð´Ð¸Ð°Ð»Ð¾Ð³Ð¾Ð²Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ† Ñ Ð¼Ð°ÐºÑ€Ð¾Ñи. - - - - Unable to install - Ðе може да Ñе инÑталира - - - - Addon successfully removed. Please restart FreeCAD - Добавката е премахната уÑпешно. РеÑтартирайте FreeCAD - - - - Unable to remove this addon - Добавката не може да Ñе премахне - - - - Macro successfully removed. - УÑпешно премахнат макроÑ. - - - - Macro could not be removed. - МакроÑÑŠÑ‚ не може да Ñе премахне. - - - - Unable to download addon list. - СпиÑъкът Ñ Ð´Ð¾Ð±Ð°Ð²ÐºÐ¸ не може да Ñе изтегли. - - - - Workbenches list was updated. - СпиÑъкът Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð½Ð¸ Ñреди бе обновен. - - - - Outdated GitPython detected, consider upgrading with pip. - ЗаÑечен е оÑтарÑл GitPython, обмиÑлете да го надградите Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ñ‚Ð° на pip. - - - - List of macros successfully retrieved. - УÑпешно извлечен е ÑпиÑъкът Ñ Ð¼Ð°ÐºÑ€Ð¾Ñи. - - - - Retrieving description... - Извлича Ñе опиÑание... - - - - Retrieving info from - Извличане на данни от - - - - An update is available for this addon. - Има обновÑване за тази добавка. - - - - This addon is already installed. - Добавката вече Ñ Ð¸Ð¼Ð°. - - - - Retrieving info from git - Извличане на данни от git - - - - Retrieving info from wiki - Извличане на данни от уики - - - - GitPython not found. Using standard download instead. - ÐÑма открит GitPython. ВмеÑто това използвайте Ñтандартно изтеглÑне. - - - - Your version of python doesn't appear to support ZIP files. Unable to proceed. - Вашата верÑÐ¸Ñ Ð½Ð° python не поддържа ZIP файлове. Продължаването невъзможно. - - - - Workbench successfully installed. Please restart FreeCAD to apply the changes. - Работната Ñреда бе обновена. ÐœÐ¾Ð»Ñ Ñ€ÐµÑтартирайте FreeCAD за прилагане на промените. - - - - Missing workbench - Работната Ñреда не е налична - - - - Missing python module - ЛипÑва модул на python - - - - Missing optional python module (doesn't prevent installing) - ЛипÑва допълнителен модул на python (не предотвратÑва инÑталирането) - - - - Some errors were found that prevent to install this workbench - Открити бÑха грешки, които предотвратÑват инÑталирането на работната Ñреда - - - - Please install the missing components first. - Първо инÑталирайте липÑващите компоненти. - - - - Error: Unable to download - Грешка: Ðе може да Ñе изтегли - - - - Successfully installed - УÑпешно инÑталирано - - - - GitPython not installed! Cannot retrieve macros from git - Ðе е инÑталиран GitPython! Ðе може да извлечете данни за макроÑа от git - - - - Installed - ИнÑталирано - - - - Update available - Има налично обновление - - - - Restart required - ИзиÑква Ñе повторно пуÑкане - - - - This macro is already installed. - МакроÑÑŠÑ‚ вече е инÑталиран. - - - - A macro has been installed and is available under Macro -> Macros menu - МакроÑÑŠÑ‚ е инÑталиран и наличен под менюто МакроÑи -> Ð¼Ð°ÐºÑ€Ð¾Ñ - - - - This addon is marked as obsolete - Добавката е отбелÑзана като оÑтарÑла - - - - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - Това обикновено означава, че Ñ‚Ñ Ð²ÐµÑ‡Ðµ не Ñе поддържа, и нÑÐºÐ¾Ñ Ð¿Ð¾-напреднала добавка в този ÑпиÑък предлага Ñъщата функционалноÑÑ‚. - - - - Error: Unable to locate zip from - Грешка: Ðе може да Ñе намери zip от - - - - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - Получи Ñе проблем при извличането на макроÑа от Git, вероÑтно изпълнимиÑÑ‚ файл Git.exe не е доÑтъпен през променливата на Ñредата PATH - - - - This addon is marked as Python 2 Only - Тази добавка е отбелÑзана като ÑъвмеÑтима Ñамо Ñ Python 2 - - - - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - Тази работна Ñреда вероÑтно вече не Ñе поддържа и инÑталирането и в ÑиÑтема Ñ Python 3 вероÑтно ще доведе до грешки по време на Ñтартиране или употреба. - - - - User requested updating a Python 2 workbench on a system running Python 3 - - ПотребителÑÑ‚ пожела обновÑване на Python 2 работна Ñреда в ÑиÑтема използваща Python 3 - - - - - Workbench successfully updated. Please restart FreeCAD to apply the changes. - Работната Ñреда бе обновена. ÐœÐ¾Ð»Ñ Ñ€ÐµÑтартирайте FreeCAD за прилагане на промените. - - - - User requested installing a Python 2 workbench on a system running Python 3 - - ПотребителÑÑ‚ пожела инÑталиране на Python 2 работна Ñреда в ÑиÑтема използваща Python 3 - - - - - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - Изглежда има проблем при Ñвързване Ñ Wiki, ÑвалÑнето на ÑпиÑъка Ñ Ð¼Ð°ÐºÑ€Ð¾Ñи от Wiki не е възможно в момента - - - - Raw markdown displayed - Показан е ÑÑƒÑ€Ð¾Ð²Ð¸Ñ Ð¸Ð·Ñ…Ð¾Ð´Ð½Ð¸Ñ ÐºÐ¾Ð´ - - - - Python Markdown library is missing. - ЛипÑва библиотеката Python Markdown. - - - - Dialog - - - Workbenches - Workbenches - - - - Macros - МакроÑи - - - - Execute - Изпълнение - - - - Downloading info... - Данни за изтеглÑнето... - - - - Update all - ОбновÑване на вÑичко - - - - Executes the selected macro, if installed - Ðко е инÑталиран, Ñтартирай Ð¸Ð·Ð±Ñ€Ð°Ð½Ð¸Ñ Ð¼Ð°ÐºÑ€Ð¾Ñ - - - - Uninstalls a selected macro or workbench - Премахни Ð¸Ð·Ð±Ñ€Ð°Ð½Ð¸Ñ Ð¼Ð°ÐºÑ€Ð¾Ñ Ð¸Ð»Ð¸ работна Ñреда - - - - Installs or updates the selected macro or workbench - ИнÑталира или обновÑва Ð¸Ð·Ð±Ñ€Ð°Ð½Ð¸Ñ Ð¼Ð°ÐºÑ€Ð¾Ñ Ð¸Ð»Ð¸ работна Ñреда - - - - Download and apply all available updates - ИзтеглÑне и прилагане на вÑички налични Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - - - - Custom repositories (one per line): - Допълнителни източници (по един на ред): - - - - Sets configuration options for the Addon Manager - ÐаÑтройва конфигурационни параметри на Мениджъра на добавки - - - - Configure... - Конфигуриране... - - - - Addon manager options - Опции на ÑƒÐ¿Ñ€Ð°Ð²Ð¸Ñ‚ÐµÐ»Ñ Ð½Ð° добавки - - - - Uninstall selected - ДеинÑталиране на избраното - - - - Install/update selected - ИнÑталиране/обновÑване на избраното - - - - Close - ЗатварÑне - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - Ðко тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ избрана, при Ñтартирането на Мениджъра на добавки, ще Ñе извърши проверка за наличие на Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° инÑталираните добавки (това изиÑква в ÑиÑтемата да има инÑталиран GitPython) - - - - Automatically check for updates at start (requires GitPython) - Ðвтоматична проверка за Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¸ Ñтартиране (изиÑква GitPython) - - - - Proxy - ПрокÑи - - - - No proxy - Без прокÑи - - - - User system proxy - СиÑтемно прокÑи - - - - User defined proxy : - ПотребителÑко прокÑи: - - - - Addon Manager - Управление на добавките - - - - Close the Addon Manager - Затворете управлението на добавките - - - - You can use this window to specify additional addon repositories -to be scanned for available addons - Използвайте този прозорец за да добавите допълнителни хранилища за Ñканиране за добавки - - - - Std_AddonMgr - - - &Addon manager - &Управител на добавките - - - - Manage external workbenches and macros - Управление на външни workbench и макроÑи - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ca.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ca.qm deleted file mode 100644 index cbd42912d5eb4bd3056adc64b0835751c625eb50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75103 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 T4u3Gr>n(lq3J`NmEcSl^dc5Y$ diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ca.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_ca.ts deleted file mode 100644 index 5851ce38cc..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_ca.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Personalitza el repositori - - - - Repository URL - URL del repositori - - - - Branch - Branca - - - - CompactView - - - - Icon - Icona - - - - - <b>Package Name</b> - <b>Nom del paquet</b> - - - - - Version - Versió - - - - - Description - Descripció - - - - Update Available - Actualització disponible - - - - UpdateAvailable - Actualització disponible - - - - DependencyDialog - - - Dependencies - Dependències - - - - Dependency type - Tipus de dependència - - - - Name - Nom - - - - Optional? - Opcional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resol les dependències - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Aquest complement té les dependències requerides i opcionals següents. Les heu d'instal·lar abans que es pugui utilitzar el complement. - -Voleu que el gestor de complements les instal·li automàticament? Trieu "Ignora" per a instal·lar el complement sense instal·lar les dependències. - - - - FreeCAD Addons - Complements del FreeCAD - - - - Required Python modules - Mòduls Python necessaris - - - - Optional Python modules - Mòduls Python opcionals - - - - DeveloperModeDialog - - - Addon Developer Tools - Eines per a desenvolupadors del complement - - - - Path to Addon - Ruta cap al Complement - - - - - Browse... - Navega... - - - - Metadata - Metadades - - - - Primary branch - Branca primària - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explicació del que proporciona aquest complement. Es mostra al gestor de complements. Pot ser que no hi digui que es tracta d'un complement del FreeCAD. - - - - Description - Descripció - - - - Discussion URL - URL de discussió - - - - Icon - Icona - - - - Bugtracker URL - URL del rastrejador d'errors - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estils semàntics (1.2.3-beta) o CalVer (2022.08.30) compatibles - - - - Set to today (CalVer style) - Estableix a avui (estil CalVer) - - - - - - - (Optional) - (Opcional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Es mostra a la llista de complements del gestor de complements. No hauria d'incloure la paraula "FreeCAD", i ha de ser un nom de directori vàlid en tots els sistemes operatius compatibles. - - - - README URL - Adreça web al README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - PISTA: Donat que això es mostra a FreeCAD, en el Gestor de Complements, no cal ocupar espai dient coses com "Aquest és un complement de FreeCAD..." -- només digues què fa. - - - - Repository URL - URL del repositori - - - - Website URL - Adreça de la pàgina web - - - - Documentation URL - Adreça web a la documentació - - - - Addon Name - Nom del Complement - - - - Version - Versió - - - - (Recommended) - (Recomanat) - - - - Minimum Python - Versió mínima de Python - - - - (Optional, only 3.x version supported) - (Opcional, només està suportada la versió 3.x) - - - - Detect... - Detecta... - - - - Addon Contents - Contingut del Complement - - - - Dialog - - - Addon Manager - Gestor de complements - - - - Edit Tags - Edita les etiquetes - - - - Comma-separated list of tags describing this item: - Llista d'etiquetes separades per comes que descriuen aquest element: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - PISTA: Les etiquetes comunes inclouen "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Gestor de Complements: Advertència! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - El Gestor de Complements proporciona accés a una àmplia biblioteca d'extensions útils de FreeCAD de tercers. No es poden fer garanties quant a la seva seguretat o funcionalitat. - - - - Continue - Continua - - - - Cancel - Cancel·la - - - - EditDependencyDialog - - - Edit Dependency - Modificar dependències - - - - Dependency Type - Tipus de dependència - - - - Dependency - Dependència - - - - Package name, if "Other..." - Nom del paquet, si "Altre..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTA: Si "Altre..." està seleccionat, el paquet no està inclòs al fitxer ALLOWED_PYTHON_PACKAGES.txt, i no serà instal·lat automàticament del Gestor de complements. Envieu un PR a <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> per sol·licitar l'addició d'un paquet. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Si aquesta és una dependència opcional, el Gestor de complements l'oferirà per a instal·lar (quan sigui possible), però no bloquejarà la instal·lació si l'usuari decideix, o no pot, instal·lar el paquet. - - - - Optional - Opcional - - - - ExpandedView - - - - Icon - Icona - - - - - <h1>Package Name</h1> - <h1>Nom del paquet</h1> - - - - - Version - Versió - - - - - (tags) - (etiquetes) - - - - - Description - Descripció - - - - - Maintainer - Mantenidor - - - - Update Available - Actualització disponible - - - - labelSort - ordenació per etiquetes - - - - UpdateAvailable - Actualització disponible - - - - Form - - - Licenses - Llicències - - - - License - Llicència - - - - License file - Fitxer de llicència - - - - People - Gent - - - - Kind - Tipus - - - - Name - Nom - - - - Email - Correu electrònic - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Mapatge avançat de versions - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Les pròximes versions del Gestor de complements de FreeCAD donaran suport als desenvolupadors a establir una branca o etiqueta específica per utilitzar-la amb una versió específica de FreeCAD (p. ex., establir una etiqueta específica com a darrera versió del vostre complement per admetre la v0.19, etc.) - - - - FreeCAD Version - Versió del FreeCAD - - - - Best-available branch, tag, or commit - Millor branca, etiqueta o publicació disponible - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versions del FreeCAD admeses - - - - Minimum FreeCAD Version Supported - Versió mínima de FreeCAD admesa - - - - - Optional - Opcional - - - - Maximum FreeCAD Version Supported - Versió màxima del FreeCAD admesa - - - - Advanced version mapping... - Mapatge avançat de versions... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opcions del Gestor de complements - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Si seleccioneu aquesta opció, en iniciar el Gestor de complements, -es comprovarà si hi ha actualitzacions disponibles als complements instal·lats - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Descarrega les metadades de la Macro (aproximadament 10MB) - - - - Cache update frequency - Freqüència d'actualització de la memòria cau - - - - Manual (no automatic updates) - Manual (sense actualitzacions automàtiques) - - - - Daily - Diàriament - - - - Weekly - Setmanalment - - - - Hide Addons without a license - Oculta Complements sense llicència - - - - Hide Addons with non-FSF Free/Libre license - Oculta Complements sense llicència non-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Oculta Complements sense llicència non-OSI-approved - - - - Hide Addons marked Python 2 Only - Oculta Complements marcats com a Només Python 2 - - - - Hide Addons marked Obsolete - Ocultar Complements marcats com a Obsolets - - - - Hide Addons that require a newer version of FreeCAD - Oculta Complements que requereixen una nova versió de FreeCAD - - - - Custom repositories - Repositoris personalitzats - - - - Proxy - Servidor intermediari - - - - No proxy - Sense servidor intermediari - - - - User system proxy - Servidor intermediari del sistema de l'usuari - - - - User-defined proxy: - Servidor intermediari definit per l'usuari: - - - - Score source URL - Font URL de la puntuació - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - L'URL per les dades de puntuació del complement (vegeu pàgina de la wiki Addon Manager pel format i els detalls de l'allotjament). - - - - Path to Git executable (optional): - Ruta de l'executable Git (opcional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opcions avançades - - - - Activate Addon Manager options intended for developers of new Addons. - Habiliteu les opcions del Gestor de complements destinades als desenvolupadors de nous Complements. - - - - Addon developer mode - Mode de desenvolupament del complement - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Desinstal·la la macro seleccionada o el banc de treball - - - - Install - Instal·la - - - - Uninstall - Desinstal·la - - - - Update - Actualitza - - - - Run Macro - Executa la macro - - - - Change branch - Canvia de branca - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Administreu les dependències de Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Els paquets de Python següents han sigut instal·lats localment pel Gestor de complements per a satisfer dependències de complements. Ubicació d'instal·lació: - - - - Package name - Nom del paquet - - - - Installed version - Versió instal·lada - - - - Available version - Versió disponible - - - - Used by - Utilitzat per - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Un asterisc (*) a la columna "Utilitzat per" indica una dependència opcional. Tingueu en compte que Utilitzat per només registra les importacions directes al complement. També s'han instal·lat altres paquets Python dels quals depenen aquests paquets. - - - - Update all available - Actualitza tots els disponibles - - - - SelectFromList - - - Dialog - Diàleg - - - - TextLabel - Etiqueta de text - - - - UpdateAllDialog - - - Updating Addons - Actualitza els complements - - - - Updating out-of-date addons... - Actualitzant complements obsolets... - - - - addContentDialog - - - Content Item - Elements de contingut - - - - Content type: - Tipus de contingut: - - - - Macro - Macro - - - - Preference Pack - Paquets de preferències - - - - Workbench - Banc de treball - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Si això és l'únic que hi ha al complement, totes les altres metadades es poden heretar del nivell superior i no cal que les especifiqueu aquí. - - - - This is the only item in the Addon - Aquest és l'únic element en el complement - - - - Main macro file - Fitxer de macro principal - - - - The file with the macro's metadata in it - El fitxer amb les metadades de la macro - - - - - - Browse... - Navega... - - - - Preference Pack Name - Nom del paquet de preferències - - - - Workbench class name - Nom de la classe del banc de treball - - - - Class that defines "Icon" data member - Classe que defineix un membre de dades "Icona" - - - - Subdirectory - Subdirectori - - - - Optional, defaults to name of content item - Opcional, el valor predeterminat és el nom de l'element del contingut - - - - Icon - Icona - - - - Optional, defaults to inheriting from top-level Addon - Opcional, el valor predeterminat és heretat del nivell superior del complement - - - - Tags... - Etiquetes... - - - - Dependencies... - Dependències... - - - - FreeCAD Versions... - Versions del FreeCAD... - - - - Other Metadata - Altres metadades - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Mostrat a la llista de complements del Gestor de complements. No hauria d'incloure la paraula "FreeCAD". - - - - Version - Versió - - - - Description - Descripció - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estils semàntics (1.2.3-beta) o CalVer (2022.08.30) compatibles - - - - Set to today (CalVer style) - Estableix a avui (estil CalVer) - - - - Display Name - Nom a mostrar - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Tots els camps deixats en blanc s'hereten de les metadades del complement de nivell superior, de manera que tècnicament són tots opcionals. Per als complements amb diversos elements de contingut, cada element hauria de proporcionar un nom a mostrar i una descripció única. - - - - add_toolbar_button_dialog - - - Add button? - Afegir botó? - - - - Add a toolbar button for this macro? - Voleu afegir un botó a la barra d'eines per a aquesta macro? - - - - Yes - Sí - - - - No - No - - - - Never - Mai - - - - change_branch - - - Change Branch - Canvia la branca - - - - Change to branch: - Canvia a la branca: - - - - copyrightInformationDialog - - - Copyright Information - Informació dels drets d'autor - - - - Copyright holder: - Titular dels drets d'autor: - - - - Copyright year: - Any dels drets d'autor: - - - - personDialog - - - Add Person - Afegeix una persona - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Un mantenidor és algú amb accés actual de commit en aquest projecte. Un autor és qualsevol altra persona a qui t'agradaria donar-li crèdit. - - - - Name: - Nom: - - - - Email: - Correu electrònic: - - - - Email is required for maintainers, and optional for authors. - El correu electrònic és obligatori per als mantenidors i opcional per als autors. - - - - proxy_authentication - - - Proxy login required - Cal iniciar sessió al servidor intermediari - - - - Proxy requires authentication - El servidor intermediari requereix autenticació - - - - Proxy: - Servidor intermediari: - - - - Placeholder for proxy address - Marcador de posició per a l'adreça del servidor intermediari - - - - Realm: - Domini: - - - - Placeholder for proxy realm - Marcador de posició pel domini del servidor intermediari - - - - Username - Nom d'usuari - - - - Password - Contrasenya - - - - selectLicenseDialog - - - Select a license - Selecciona una llicència - - - - About... - Quant a... - - - - License name: - Nom de la llicència: - - - - Path to license file: - Ruta de l'arxiu de la llicència: - - - - (if required by license) - (si és requerit per la llicència) - - - - Browse... - Navega... - - - - Create... - Crea... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Seleccionar Barra d'eines - - - - Select a toolbar to add this macro to: - Seleccioneu una barra d'eines per afegir aquesta macro a: - - - - Ask every time - Demana-m'ho sempre - - - - toolbar_button - - - - Add button? - Afegir botó? - - - - Add a toolbar button for this macro? - Voleu afegir un botó a la barra d'eines per a aquesta macro? - - - - Yes - Sí - - - - No - No - - - - Never - Mai - - - - AddonsInstaller - - - Starting up... - S’està iniciant... - - - - Worker process {} is taking a long time to stop... - El procés de treball {} està trigant molta estona a aturar-se... - - - - Previous cache process was interrupted, restarting... - - El procés de memòria cau anterior ha sigut interromput, s'està reiniciant... - - - - - Custom repo list changed, forcing recache... - - S'ha canviat la llista de repositoris personalitzats, forçant la càrrega a memòria cau... - - - - - Addon manager - Gestor de complements - - - - You must restart FreeCAD for changes to take effect. - Has de reiniciar FreeCAD perquè els canvis tinguin efecte. - - - - Restart now - Reinicia ara - - - - Restart later - Reinicia més tard - - - - - Refresh local cache - Refrescar memòria cau local - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - S'està actualitzant la memòria cau... - - - - - Checking for updates... - S'estan comprovant les actualitzacions... - - - - Temporary installation of macro failed. - La instal·lació temporal de la macro ha fallat. - - - - - Close - Tanca - - - - Update all addons - Actualitza tots els complements - - - - Check for updates - Comprovar actualitzacions - - - - Python dependencies... - Dependències de Python... - - - - Developer tools... - Eines per a desenvolupadors... - - - - Apply %n available update(s) - Aplicar %n actualitzacions disponibles - - - - No updates available - No hi ha actualitzacions disponibles - - - - - - Cannot launch a new installer until the previous one has finished. - No es pot iniciar un nou instal·lador fins que s'hagi acabat l'anterior. - - - - - - - Maintainer - Mantenidor - - - - - - - Author - Autor - - - - New Python Version Detected - S'ha detectat una nova versió de Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Sembla que és la primera vegada que s'utilitza aquesta versió de Python amb el Gestor de complements. Voleu instal·lar-hi les mateixes dependències instal·lades automàticament? - - - - Processing, please wait... - Processant, si us plau, espereu... - - - - - Update - Actualitza - - - - Updating... - S'està actualitzant... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - No s'ha pogut importar QtNetwork -- no pareix com a instal·lat al teu sistema. El vostre proveïdor pot tenir un paquet per a aquesta dependència (sovint anomenat "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - No s'ha pogut convertir el port '{}' del servidor intermediari especificat "{}" a un número de port - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Error de paràmetre: s'han establert opcions de servidor intermediari mútuament excloents. S'està restablint al valor predeterminat. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Error de paràmetre: s'ha indicat el servidor intermediari d'usuari, però no s'ha proporcionat cap servidor intermediari. S'està restablint al valor predeterminat. - - - - Addon Manager: Unexpected {} response from server - Gestor de complements: Resposta {} inesperada del servidor - - - - Error with encrypted connection - Error amb la connexió encriptada - - - - - - Confirm remove - Confirma l'eliminació - - - - Are you sure you want to uninstall {}? - Estàs segur que vols desinstal·lar {}? - - - - - - Removing Addon - Eliminant complement - - - - Removing {} - Eliminant {} - - - - - Uninstall complete - Desinstal·lació completa - - - - - Uninstall failed - Desinstal·lació fallida - - - - Version {version} installed on {date} - Versió {version} instal·lada el dia {date} - - - - Version {version} installed - Versió {version} instal·lada - - - - Installed on {date} - Instal·lat el {date} - - - - - - - Installed - Instal·lat - - - - Currently on branch {}, name changed to {} - Actualment a la branca {}, el nom ha canviat a {} - - - - Git tag '{}' checked out, no updates possible - Etiqueta Git '{}' comprovada, no hi ha actualitzacions possibles - - - - Update check in progress - Comprovació d'actualitzacions en curs - - - - Installation location - Localització de la instal·lació - - - - Repository URL - URL del repositori - - - - Changed to branch '{}' -- please restart to use Addon. - Canviat a la branca '{}' -- si us plau, reinicieu per utilitzar el complement. - - - - This Addon has been updated. Restart FreeCAD to see changes. - S'ha actualitzat aquest complement. Reinicia FreeCAD per veure els canvis. - - - - Disabled - Deshabilitat - - - - Currently on branch {}, update available to version {} - Actualment a la branca {}, hi ha una actualització disponible a la versió {} - - - - Update available to version {} - Actualització disponible a la versió {} - - - - This is the latest version available - Aquesta és l'última versió disponible - - - - WARNING: This addon is obsolete - ADVERTÈNCIA: Aquest complement està obsolet - - - - WARNING: This addon is Python 2 only - ADVERTÈNCIA: Aquest complement només és per a Python 2 - - - - WARNING: This addon requires FreeCAD {} - ADVERTÈNCIA: Aquest complement necessita FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ADVERTÈNCIA: Aquest complement ja està instal·lat, però està deshabilitat. Prem el botó 'habilitar' per tornar-lo a habilitar. - - - - This Addon will be enabled next time you restart FreeCAD. - Aquest complement serà habilitat la pròxima vegada que reiniciïs FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Aquest complement serà deshabilitat la pròxima vegada que reiniciïs FreeCAD. - - - - - - Success - Èxit - - - - Install - Instal·la - - - - Uninstall - Desinstal·la - - - - Enable - Habilita - - - - Disable - Desactiva - - - - - Check for update - Cerca actualitzacions - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - executa - - - - Change branch... - Canvia de branca... - - - - Return to package list - Torna al llistat de paquets - - - - Checking connection - S’està comprovant la connexió - - - - Checking for connection to GitHub... - S'està comprovant la connexió a GitHub... - - - - Connection failed - La connexió ha fallat - - - - Missing dependency - Dependències faltant - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - No s'ha pogut importar QtNetwork -- vegeu Visualització d'informes per obtenir més informació. El Gestor de complements no està disponible. - - - - Other... - For providing a license other than one listed - Altres... - - - - Select the corresponding license file in your Addon - Selecciona el fitxer de llicència corresponent pel teu complement - - - - Location for new license file - Localització per un nou fitxer de llicència - - - - Received {} response code from server - S'ha rebut el codi de resposta {} del servidor - - - - Failed to install macro {} - No s'ha pogut instal·lar la macro {} - - - - Failed to create installation manifest file: - - No s'ha pogut crear el fitxer de manifest d'instal·lació: - - - - - Unrecognized content kind '{}' - No s'ha pogut reconèixer el tipus de contingut '{}' - - - - Unable to locate icon at {} - No s'ha pogut localitzar la icona a {} - - - - Select an icon file for this content item - Selecciona una icona per aquest element de contingut - - - - - - {} is not a subdirectory of {} - {} no és un subdirectori de {} - - - - Select the subdirectory for this content item - Selecciona el subdirectori per aquest element de contingut - - - - Automatic - Automàtica - - - - - Workbench - Banc de treball - - - - Addon - Complement - - - - Python - Python - - - - Yes - Sí - - - - Internal Workbench - Banc de treball intern - - - - External Addon - Complement extern - - - - Python Package - Paquet de Python - - - - - Other... - Altres... - - - - Too many to list - Masses per llistar - - - - - - - - - Missing Requirement - Falten requisits - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - El complement '{}' requereix '{}', que no està disponible per a la teva còpia de FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - El complement '{}' requereix els següents bancs de treball, que no estan disponibles per a la teva còpia de FreeCAD: - - - - Press OK to install anyway. - Premeu OK per instal·lar-lo de totes maneres. - - - - - Incompatible Python version - Versió incompatible de Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Aquest complement requereix paquets de Python que no estan instal·lats i que no es poden instal·lar automàticament. Per a utilitzar aquest complement, heu d'instal·lar manualment els següents paquets de Python: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Aquest complement (o una de les seves dependències) requereix Python {}.{}, i el vostre sistema està executant {}.{}. S'ha cancel·lat la instal·lació. - - - - Optional dependency on {} ignored because it is not in the allow-list - La dependència opcional {} s'ha ignorat perquè no està en la llista permesa - - - - - Installing dependencies - Instal·lant dependències - - - - - Cannot execute Python - No s’ha pogut executar Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - No s'ha pogut localitzar automàticament l'executable de Python o el camí s'ha definit incorrectament. Si us plau, comproveu la configuració de preferències del Gestor de complements per al camí de Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - No s'han pogut instal·lar les dependències. Voleu continuar amb la instal·lació de {} de totes maneres? - - - - - Cannot execute pip - No s’ha pogut executar pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - No s'ha pogut executar pip, que pot ser absent a la instal·lació de Python. Assegureu-vos que el vostre sistema tingui pip instal·lat i torneu-ho a provar. La comanda que ha fallat és: - - - - - Continue with installation of {} anyway? - Voleu continuar amb la instal·lació de {} de totes maneres? - - - - - Package installation failed - La instal·lació del paquet ha fallat - - - - See Report View for detailed failure log. - Consulteu Visualització d'informes per obtenir un registre d'errors detallat. - - - - Installing Addon - Instal·lant el complement - - - - Installing FreeCAD Addon '{}' - Instal·lant el complement de FreeCAD '{}' - - - - Cancelling - Cancel·lant - - - - Cancelling installation of '{}' - Cancel·lant la instal·lació de '{}' - - - - {} was installed successfully - {} s'ha instal·lat correctament - - - - - Installation Failed - La instal·lació ha fallat - - - - Failed to install {} - No s'ha pogut instal·lar {} - - - - - Create new toolbar - Crea una nova barra d'eines - - - - - A macro installed with the FreeCAD Addon Manager - Una macro instal·lada amb el Gestor de complements de FreeCAD - - - - - Run - Indicates a macro that can be 'run' - executa - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - No es poden llegir dades de GitHub: comproveu la vostra connexió a Internet i la configuració del servidor intermediari i torneu-ho a provar. - - - - XML failure while reading metadata from file {} - Error XML durant la lectura de metadades del fitxer {} - - - - Invalid metadata in file {} - Fitxer invàlid de metadades {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ADVERTÈNCIA: El camí especificat a les metadades package.xml no coincideix amb la branca descarregada actualment. - - - - Name - Nom - - - - Class - Classe - - - - Description - Descripció - - - - Subdirectory - Subdirectori - - - - Files - Fitxers - - - - Select the folder containing your Addon - Selecciona la carpeta que conté el teu complement - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No hi ha Vermin, cancel·lant l'operació. - - - - Scanning Addon for Python version compatibility - Escanejant el complement per a la compatibilitat de la versió de Python - - - - Minimum Python Version Detected - S'ha detectat la versió mínima de Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin ha detectat automàticament una versió requerida de Python 3.{} - - - - Install Vermin? - Instal·lar Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - La detecció automàtica de la versió necessària de Python per a aquest complement requereix Vermin (https://pypi.org/project/vermin/). El vols instal·lar? - - - - Attempting to install Vermin from PyPi - Intentant la instal·lació de Vermin des de PyPi - - - - - Installation failed - La instal·lació ha fallat - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - La instal·lació de Vermin ha fallat -- consulteu la Visualització d'informes per obtenir més informació. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - No s'ha pogut importar vermin després de la instal·lació -- no es pot escanejar el complement. - - - - Select an icon file for this package - Selecciona una icona per aquest paquet - - - - Filter is valid - El filtre és vàlid - - - - Filter regular expression is invalid - L'expressió regular de filtre és invàlida - - - - Search... - Cerca... - - - - Click for details about package {} - Fes clic per veure els detalls sobre el paquet {} - - - - Click for details about workbench {} - Fes clic per veure els detalls sobre el banc de treball {} - - - - Click for details about macro {} - Fes clic per veure els detalls sobre la macro {} - - - - Maintainers: - Mantenidors: - - - - Tags - Etiquetes - - - - {} ★ on GitHub - {} ★ a GitHub - - - - No ★, or not on GitHub - Sense ★, o no hi és a GitHub - - - - Created - Creat - - - - Updated - Actualitzat - - - - Score: - Puntuació: - - - - - Up-to-date - Actualitzat - - - - - - - - Update available - Hi ha una actualització disponible - - - - - Pending restart - Pendent de reinici - - - - - DISABLED - DESHABILITAT - - - - Installed version - Versió instal·lada - - - - Unknown version - Versió desconeguda - - - - Installed on - Instal·lat el - - - - Available version - Versió disponible - - - - Filter by... - Filtra per... - - - - Addon Type - Tipus del Complement - - - - - Any - Qualsevol - - - - Macro - Macro - - - - Preference Pack - Paquets de preferències - - - - Installation Status - Estat de la instal·lació - - - - Not installed - No instal·lat - - - - Filter - Filtre - - - - DANGER: Developer feature - PERILL: Característica de desenvolupador - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - PERILL: El canvi de branques està pensat per a desenvolupadors i beta testers, i pot provocar documents trencats i no compatibles amb versions anteriors, inestabilitat, bloquejos i/o la mort prematura per calor de l'univers. Esteu segur que voleu continuar? - - - - There are local changes - Hi ha canvis locals - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ADVERTÈNCIA: Aquest repositori té canvis locals no confirmats. Esteu segur que voleu canviar de branca (portar els canvis amb vosaltres)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Seguiment remot - - - - Last Updated - Table header for git update date - Darrera actualització - - - - Installation of Python package {} failed - La instal·lació del paquet de Python {} ha fallat - - - - Installation of optional package failed - La instal·lació del paquet opcional ha fallat - - - - Installing required dependency {} - S'està instal·lant la dependència necessària {} - - - - Installation of Addon {} failed - La instal·lació del complement {} ha fallat - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - La descodificació del fitxer {} pel complement '{}' ha fallat - - - - Any dependency information in this file will be ignored - Qualsevol informació de dependències en aquest fitxer serà ignorada - - - - Unable to open macro wiki page at {} - No s'ha pogut obrir la pàgina de wiki de la macro a {} - - - - Unable to fetch the code of this macro. - No es pot obtenir el codi d'aquesta macro. - - - - Unable to retrieve a description from the wiki for macro {} - No es pot recuperar una descripció de la wiki per la macro {} - - - - Unable to open macro code URL {} - No es pot obrir l'URL del codi de la macro {} - - - - Unable to fetch macro-specified file {} from {} - No es pot obtenir el fitxer especificat per la macro {} de {} - - - - Could not locate macro-specified file {} (expected at {}) - No s'ha pogut localitzar el fitxer especificat per la macro {} (s'esperava {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Banc de treball intern no reconegut '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Advertiment per a desenvolupadors de complements: L'URL del repositori establert al fitxer package.xml pel complement {} ({}) no coincideix amb l'URL del qual s'ha obtingut ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Advertiment per a desenvolupadors de complements: La branca del repositori establerta al fitxer package.xml pel complement {} ({}) no coincideix amb la branca de la qual s'ha obtingut ({}) - - - - - Got an error when trying to import {} - S'ha produït un error en importar {} - - - - An unknown error occurred - S'ha produït un error desconegut - - - - Could not find addon {} to remove it. - No s'ha pogut trobar el complement {} per eliminar-lo. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - L'execució de l'script uninstall.py del complement ha fallat. Continuant amb la desinstal·lació... - - - - Removed extra installed file {} - S'ha eliminat el fitxer instal·lat addicional {} - - - - Error while trying to remove extra installed file {} - S'ha produït un error durant l'eliminació del fitxer instal·lat addicional {} - - - - Error while trying to remove macro file {}: - S'ha produït un error durant l'eliminació del fitxer de la macro {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - No s'ha pogut connectar amb GitHub: Comprova la teva connexió i la configuració del servidor intermediari. - - - - WARNING: Duplicate addon {} ignored - ADVERTÈNCIA: El complement {} duplicat s'ignora - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - S'ha produït un error en actualitzar les macros de GitHub, s'està intentant netejar el checkout... - - - - Attempting to do a clean checkout... - S'està intentant fer un checkout net... - - - - Clean checkout succeeded - Checkout net exitós - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Error en actualitzar les macros de GitHub -- intenti netejar la memòria cau del Gestor de complements. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error en connectar a la Wiki, FreeCAD no pot recuperar la llista de macros de la wiki en aquest moment - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - La lectura de metadades de {name} ha fallat - - - - Failed to fetch code for macro '{name}' - No s'ha pogut obtenir el codi per la macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Gestor de complements: no s'ha pogut completar un procés de treball mentre s'obté {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - De {num_macros} macros, {num_failed} s'han bloquejat durant el processament - - - - Addon Manager: a worker process failed to halt ({name}) - Gestor de complements: no s'ha pogut aturar un procés de treball ({name}) - - - - Timeout while fetching metadata for macro {} - S'ha esgotat el temps durant l'obtenció de metadades per a la macro {} - - - - Failed to kill process for macro {}! - - No s'ha pogut matar el procés per a la macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - No s'han pogut obtenir les estadístiques del complement de {} -- només l'ordenació alfabètica serà precisa - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - No s'ha pogut obtenir la puntuació del complement de '{}' l'ordenació per puntuació fallarà - - - - - Repository URL - Preferences header for custom repositories - URL del repositori - - - - Branch name - Preferences header for custom repositories - Nom de la branca - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Fent còpia de seguretat del directori original i tornant a clonar - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Error en el canvi de nom de la branca de git amb el missatge següent: - - - - Installing - Instal·lant - - - - Succeeded - Amb èxit - - - - Failed - Ha fallat - - - - Update was cancelled - S'ha cancel·lat l'actualització - - - - some addons may have been updated - alguns complements poden haver estat actualitzats - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - S'està carregant informació per a {} del wiki de FreeCAD Macro Recipies... - - - - Loading page for {} from {}... - Carregant pàgina per {} de {}... - - - - Failed to download data from {} -- received response code {}. - No s'han pogut baixar les dades de {} -- s'ha rebut el codi de resposta {}. - - - - Composite view - Vista composta - - - - Expanded view - Vista estesa - - - - Compact view - Vista compacta - - - - Alphabetical - Sort order - Alfabètic - - - - Last Updated - Sort order - Darrera actualització - - - - Date Created - Sort order - Data de creació - - - - GitHub Stars - Sort order - Estrelles de GitHub - - - - Score - Sort order - Puntuació - - - - Std_AddonMgr - - - &Addon manager - &Gestor de complements - - - - Manage external workbenches, macros, and preference packs - Administra bancs de treball externs, macros, i paquets de preferències - - - - AddonInstaller - - - Finished removing {} - S'ha completat l'eliminació de {} - - - - Failed to remove some files - No s'ha pogut esborrar alguns fitxers - - - - Addons installer - - - Finished updating the following addons - L'actualització dels següents complements s'ha completat - - - - Workbench - - - Auto-Created Macro Toolbar - Barra d'eines de macro creada automàticament - - - - QObject - - - Addon Manager - Gestor de complements - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_cs.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_cs.qm deleted file mode 100644 index d57db4fa15ec104bf95758f724dfd18acea4be5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68683 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_cs.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_cs.ts deleted file mode 100644 index deeacd2daf..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_cs.ts +++ /dev/null @@ -1,2484 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Vlastní repozitář - - - - Repository URL - URL adresa repozitáře - - - - Branch - VÄ›tev - - - - CompactView - - - - Icon - Ikona - - - - - <b>Package Name</b> - <b>Název balíÄku</b> - - - - - Version - Verze - - - - - Description - Popis - - - - Update Available - Je dostupná aktualizace - - - - UpdateAvailable - Aktualizace k dispozici - - - - DependencyDialog - - - Dependencies - Závislosti - - - - Dependency type - Typ závislosti - - - - Name - Název - - - - Optional? - Volitelné? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - VyÅ™eÅ¡it závislosti - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Tento doplnÄ›k má následující povinné a volitelné závislosti. PÅ™ed použitím tohoto doplňku je musíte nainstalovat. - -PÅ™ejete si, aby je správce doplňků automaticky nainstaloval? Vyberte "Ignorovat" pro instalaci doplňku bez instalace závislostí. - - - - FreeCAD Addons - Doplňky pro FreeCAD - - - - Required Python modules - Požadované Python moduly - - - - Optional Python modules - Volitelné Python moduly - - - - DeveloperModeDialog - - - Addon Developer Tools - Nástroje pro vývoj doplňků - - - - Path to Addon - Cesta k doplňku - - - - - Browse... - Procházet... - - - - Metadata - Metadata - - - - Primary branch - Hlavní vÄ›tev - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - VysvÄ›tlení, co tento doplnÄ›k poskytuje, zobrazené ve správci doplňků. Není nutné uvádÄ›t, že se jedná o doplnÄ›k pro FreeCAD. - - - - Description - Popis - - - - Discussion URL - URL adresa diskuze - - - - Icon - Ikona - - - - Bugtracker URL - URL adresa pro sledování chyb - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) nebo CalVer (2022.08.30) styly podporovány - - - - Set to today (CalVer style) - Nastavit na dneÅ¡ek (CalVer styl) - - - - - - - (Optional) - (Volitelné) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Zobrazeno v seznamu doplňků správce doplňků. NemÄ›lo by obsahovat slovo "FreeCAD" a musí být platný název adresáře na vÅ¡ech podporovaných operaÄních systémech. - - - - README URL - URL adresa README souboru - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Protože je tento text zobrazen ve správci doplňků programu FreeCAD, není nutné plýtvat místem vÄ›tami jako "Toto je doplnÄ›k pro FreeCAD..." -- Jen Å™eknÄ›te, co dÄ›lá. - - - - Repository URL - URL adresa repozitáře - - - - Website URL - URL adresa webové stránky - - - - Documentation URL - URL adresa dokumentace - - - - Addon Name - Název doplňku - - - - Version - Verze - - - - (Recommended) - (DoporuÄené) - - - - Minimum Python - Minimální verze Pythonu - - - - (Optional, only 3.x version supported) - (Volitelné, podporována pouze verze 3.x) - - - - Detect... - Detekovat... - - - - Addon Contents - Obsah doplňků - - - - Dialog - - - Addon Manager - Správce rozšíření - - - - Edit Tags - Upravit tagy - - - - Comma-separated list of tags describing this item: - Seznam Å¡títků oddÄ›lených Äárkami popisujících tuto položku: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - TIP: Běžné tagy zahrnují "ShromáždÄ›ní", "MKP", "Síť", "NURBS", atd. - - - - Add-on Manager: Warning! - Správce doplňků: Varování! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Správce doplňků poskytuje přístup k rozsáhlé knihovnÄ› užiteÄných rozšíření FreeCADu tÅ™etích stran. Nelze poskytnout žádné záruky týkající se jejich bezpeÄnosti nebo funkÄnosti. - - - - Continue - PokraÄovat - - - - Cancel - ZruÅ¡it - - - - EditDependencyDialog - - - Edit Dependency - Upravit závislost - - - - Dependency Type - Typ závislosti - - - - Dependency - Závislost - - - - Package name, if "Other..." - Název balíÄku, pokud "ostatní..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - POZNÃMKA: Pokud je vybrána "další...", balíÄek není v ALLOWED_PYTHON_PACKAGES. xt soubor a nebude automaticky nainstalován Správcem doplňků. PoÅ¡lete PR na <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> a požádejte o pÅ™idání balíÄku. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Pokud se jedná o volitelnou závislost, správce doplňků nabídne instalaci (je-li to možné), ale nebude blokovat instalaci, pokud se uživatel rozhodne, že balíÄek nenainstaluje nebo nemůže. - - - - Optional - Volitelné - - - - ExpandedView - - - - Icon - Ikona - - - - - <h1>Package Name</h1> - <h1>Název balíÄku</h1> - - - - - Version - Verze - - - - - (tags) - (Å¡títky) - - - - - Description - Popis - - - - - Maintainer - Správce - - - - Update Available - Je dostupná aktualizace - - - - labelSort - Třídit Å¡títky - - - - UpdateAvailable - Aktualizace k dispozici - - - - Form - - - Licenses - Licence - - - - License - Licence - - - - License file - LicenÄní soubory - - - - People - Lidé - - - - Kind - Druh - - - - Name - Název - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - PokroÄilé mapování verze - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Nadcházející verze FreeCAD Addon Manageru budou podporovat vývojáře'apos; nastavení konkrétní vÄ›tve nebo tagu pro použití s konkrétní verzí FreeCADu (napÅ™. nastavení konkrétního tagu jako poslední verze vaÅ¡eho Addonu pro podporu v0.19 atd.) - - - - FreeCAD Version - FreeCAD verze - - - - Best-available branch, tag, or commit - Nejlépe dostupná vÄ›tev, znaÄka nebo potvrzení - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Podporované verze FreeCAD - - - - Minimum FreeCAD Version Supported - Minimální verze FreeCAD je podporována - - - - - Optional - Volitelné - - - - Maximum FreeCAD Version Supported - Maximální poÄet podporovaných verzí FreeCAD - - - - Advanced version mapping... - Rozšířené mapování verze... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Možnosti správce doplňků - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Pokud je tato možnost vybrána, pÅ™i spuÅ¡tÄ›ní Správce doplňků, -nainstalované doplňky zkontrolovány, zda jsou k dispozici aktualizace - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Stáhnout metadata pro makra (pÅ™ibližnÄ› 10MB) - - - - Cache update frequency - ÄŒetnost aktualizace mezipamÄ›ti - - - - Manual (no automatic updates) - RuÄní (bez automatických aktualizací) - - - - Daily - DennÄ› - - - - Weekly - TýdnÄ› - - - - Hide Addons without a license - Skrýt doplňky bez licence - - - - Hide Addons with non-FSF Free/Libre license - Skrýt doplňky s licencí non-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Skrytí doplňků s licencí neschválenou spoleÄností OSI - - - - Hide Addons marked Python 2 Only - Skrýt doplňky oznaÄené pouze Python 2 - - - - Hide Addons marked Obsolete - Skrýt Zastaralé doplňky - - - - Hide Addons that require a newer version of FreeCAD - Skrýt doplňky, které vyžadují novÄ›jší verzi FreeCADu - - - - Custom repositories - Vlastní repozitáře - - - - Proxy - Proxy - - - - No proxy - Nepoužívat proxy - - - - User system proxy - Proxy uživatelského systému - - - - User-defined proxy: - Uživatelem definované proxy: - - - - Score source URL - Zdrojová adresa URL skóre - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Adresa URL pro data Addon Score (podrobnosti o formátování a hostování naleznete na wiki stránce Addon Manager). - - - - Path to Git executable (optional): - Cesta pro spuÅ¡tÄ›ní Gitu (volitelné): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - PokroÄilá nastavení - - - - Activate Addon Manager options intended for developers of new Addons. - Aktivujte možnosti doplňků správce obsahu urÄené pro vývojáře nových doplňků. - - - - Addon developer mode - Režim pro vývojáře - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Odinstaluje vybrané makro nebo pracovní stůl - - - - Install - Instalovat - - - - Uninstall - Odinstalovat - - - - Update - Aktualizovat - - - - Run Macro - Spustit makro - - - - Change branch - ZmÄ›nit vÄ›tev - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Spravovat závislosti Pythonu - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Následující balíky Pythonu byly lokálnÄ› nainstalovány Správcem doplňků pro uspokojení závislostí doplňků. UmístÄ›ní instalace: - - - - Package name - Název balíÄku - - - - Installed version - Nainstalovaná verze - - - - Available version - Dostupná verze - - - - Used by - Použito - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - HvÄ›zdiÄka (*) v "používaném ve sloupci" oznaÄuje volitelnou závislost. VÅ¡imnÄ›te si, že používají pouze přímé importy v doplňku. Ostatní balíky v Pythonu, na kterých závisí, mohou být také nainstalovány. - - - - Update all available - Aktualizovat vÅ¡echny dostupné - - - - SelectFromList - - - Dialog - Dialogové okno - - - - TextLabel - Textový popisek - - - - UpdateAllDialog - - - Updating Addons - Aktualizace doplňků - - - - Updating out-of-date addons... - Aktualizace zastaralých doplňků... - - - - addContentDialog - - - Content Item - Položka obsahu - - - - Content type: - Typ obsahu: - - - - Macro - Makro - - - - Preference Pack - PÅ™edvolby balíÄku - - - - Workbench - Pracovní prostÅ™edí - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Pokud je to jediná vÄ›c v Addon, lze vÅ¡echna ostatní metadata zdÄ›dit z nejvyšší úrovnÄ›, a zde není tÅ™eba uvádÄ›t. - - - - This is the only item in the Addon - Toto je jediná položka v doplňku - - - - Main macro file - Hlavní makro soubor - - - - The file with the macro's metadata in it - Soubor s makro's metadaty v nÄ›m - - - - - - Browse... - Procházet... - - - - Preference Pack Name - Název balíÄku pÅ™edvoleb - - - - Workbench class name - Název třídy pracovního stolu - - - - Class that defines "Icon" data member - Třída definovaná "Ikona" datovým Älenem - - - - Subdirectory - Podadresář - - - - Optional, defaults to name of content item - Nepovinné, výchozí hodnota názvu položky obsahu - - - - Icon - Ikona - - - - Optional, defaults to inheriting from top-level Addon - Volitelné, výchozí zdÄ›dÄ›ní z nejvyšší úrovnÄ› - - - - Tags... - Tagy... - - - - Dependencies... - Závislosti... - - - - FreeCAD Versions... - FreeCAD verze... - - - - Other Metadata - Další metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Zobrazeno ve správci doplňků's seznamu doplňků. NemÄ›lo by obsahovat slovo "FreeCAD". - - - - Version - Verze - - - - Description - Popis - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) nebo CalVer (2022.08.30) styly podporovány - - - - Set to today (CalVer style) - Nastavit na dneÅ¡ek (CalVer styl) - - - - Display Name - Zobrazit název - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - VÅ¡echna pole, která zůstávají prázdná, jsou zdÄ›dÄ›na z metadat nejvyšší úrovnÄ›, takže jsou technicky nepovinná. Pro doplňky s více položkami obsahu by každá položka mÄ›la poskytnout jedineÄný zobrazovaný název a popis. - - - - add_toolbar_button_dialog - - - Add button? - PÅ™idat tlaÄítko? - - - - Add a toolbar button for this macro? - PÅ™idat pro toto makro tlaÄítko panelu nástrojů? - - - - Yes - Ano - - - - No - Ne - - - - Never - Nikdy - - - - change_branch - - - Change Branch - ZmÄ›nit vÄ›tev - - - - Change to branch: - ZmÄ›na vÄ›tve: - - - - copyrightInformationDialog - - - Copyright Information - Informace o autorských právech - - - - Copyright holder: - Držitel autorských práv: - - - - Copyright year: - Autorská práva rok: - - - - personDialog - - - Add Person - PÅ™idat osobu - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Správce je nÄ›kdo s aktuálním přístupem k commitu na tento projekt. Autor je kdokoliv jiný,'byste rádi udÄ›lili kredit. - - - - Name: - Název: - - - - Email: - E-mail: - - - - Email is required for maintainers, and optional for authors. - E-mail je vyžadován pro správce a pro autory je volitelný. - - - - proxy_authentication - - - Proxy login required - Je vyžadováno pÅ™ihlášení pÅ™es proxy - - - - Proxy requires authentication - Proxy vyžaduje autentizaci - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Zástupný symbol pro adresu proxy - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Zástupný symbol pro proxy říši - - - - Username - Jméno uživatele - - - - Password - Heslo - - - - selectLicenseDialog - - - Select a license - Vyberte licenci - - - - About... - O aplikaci... - - - - License name: - Název licence: - - - - Path to license file: - Cesta k licenÄnímu souboru: - - - - (if required by license) - (vyžaduje-li to licence) - - - - Browse... - Procházet... - - - - Create... - VytvoÅ™it... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Vybrat nástrojovou liÅ¡tu - - - - Select a toolbar to add this macro to: - Vyberte nástrojovou liÅ¡tu pro pÅ™idání tohoto makra do: - - - - Ask every time - Pokaždé se zeptat - - - - toolbar_button - - - - Add button? - PÅ™idat tlaÄítko? - - - - Add a toolbar button for this macro? - PÅ™idat pro toto makro tlaÄítko panelu nástrojů? - - - - Yes - Ano - - - - No - Ne - - - - Never - Nikdy - - - - AddonsInstaller - - - Starting up... - Zahájení... - - - - Worker process {} is taking a long time to stop... - Pracovní proces {} trvá dlouho, než se zastaví... - - - - Previous cache process was interrupted, restarting... - - PÅ™edchozí proces mezipamÄ›ti byl pÅ™eruÅ¡en, restartuji... - - - - - Custom repo list changed, forcing recache... - - Seznam vlastních repozitářů byl zmÄ›nÄ›n, vynucování recache... - - - - - Addon manager - Správce rozšíření - - - - You must restart FreeCAD for changes to take effect. - Aby se zmÄ›ny projevily, musíte FreeCAD restartovat. - - - - Restart now - Restartovat nyní - - - - Restart later - Restartovat pozdÄ›ji - - - - - Refresh local cache - Aktualizovat lokální mezipaměť - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Aktualizuji mezipaměť... - - - - - Checking for updates... - Hledání aktualizací... - - - - Temporary installation of macro failed. - DoÄasná instalace makra selhala. - - - - - Close - Zavřít - - - - Update all addons - Aktualizace vÅ¡ech doplňků - - - - Check for updates - Zkontrolujte aktualizace - - - - Python dependencies... - Závislosti jazyka Python... - - - - Developer tools... - Nástroje pro vývojáře... - - - - Apply %n available update(s) - Použít %n dostupných aktualizací - - - - No updates available - Žádné dostupné aktualizace - - - - - - Cannot launch a new installer until the previous one has finished. - Nelze spustit nový instalaÄní program, dokud nebude ukonÄena pÅ™edchozí instalace. - - - - - - - Maintainer - Správce - - - - - - - Author - Autor - - - - New Python Version Detected - Byla zjiÅ¡tÄ›na nová verze Pythonu - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Zdá se, že tato verze Pythonu byla poprvé použita spolu se Správcem doplňků. PÅ™ejete si nainstalovat stejné automaticky nainstalované závislosti? - - - - Processing, please wait... - Zpracovávání, Äekejte prosím... - - - - - Update - Aktualizovat - - - - Updating... - Probíhá aktualizace... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - NepodaÅ™ilo se importovat QtNetwork -- zdá se, že není nainstalován ve vaÅ¡em systému. Váš poskytovatel může mít balíÄek pro tuto závislost (Äasto nazývaný "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - NepodaÅ™ilo se pÅ™evést zadaný port proxy '{}' na Äíslo portu - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Chyba parametru: oboustrannÄ› exkluzivní nastavení proxy možností. Resetování na výchozí. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Chyba parametru: indikován uživatelský proxy server, ale není k dispozici. Resetování na výchozí. - - - - Addon Manager: Unexpected {} response from server - Správce doplňků: NeoÄekávaná {} odpovÄ›Ä od serveru - - - - Error with encrypted connection - Chyba Å¡ifrovaného pÅ™ipojení - - - - - - Confirm remove - Potvrdit odstranÄ›ní - - - - Are you sure you want to uninstall {}? - Opravdu chcete odinstalovat {}? - - - - - - Removing Addon - Odstraňování doplňku - - - - Removing {} - OdstranÄ›ní {} - - - - - Uninstall complete - Odinstalace dokonÄena - - - - - Uninstall failed - Odinstalace se nezdaÅ™ila - - - - Version {version} installed on {date} - Verze {version} nainstalována v {date} - - - - Version {version} installed - Verze {version} nainstalována - - - - Installed on {date} - Nainstalováno na {date} - - - - - - - Installed - Nainstalováno - - - - Currently on branch {}, name changed to {} - AktuálnÄ› na vÄ›tvi {}, název zmÄ›nÄ›n na {} - - - - Git tag '{}' checked out, no updates possible - Git znaÄka '{}' proÅ¡la kontrolou, žádná aktualizace není možná - - - - Update check in progress - Probíhá kontrola aktualizací - - - - Installation location - UmístÄ›ní instalace - - - - Repository URL - URL adresa repozitáře - - - - Changed to branch '{}' -- please restart to use Addon. - ZmÄ›nÄ›no na vÄ›tev '{}' -- restartujte prosím používání doplňku. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Tento doplnÄ›k byl aktualizován. Pro provedení zmÄ›n restartujte FreeCAD. - - - - Disabled - Deaktivovány - - - - Currently on branch {}, update available to version {} - AktuálnÄ› na vÄ›tvi {}, k dispozici aktualizace na verzi {} - - - - Update available to version {} - K dispozici je aktualizace na verzi {} - - - - This is the latest version available - Jedná se o nejnovÄ›jší dostupnou verzi - - - - WARNING: This addon is obsolete - VAROVÃNÃ: Tento doplnÄ›k je zastaralý - - - - WARNING: This addon is Python 2 only - UPOZORNÄšNÃ: Tento doplnÄ›k je urÄen pouze pro Python 2. - - - - WARNING: This addon requires FreeCAD {} - VAROVÃNÃ: Tento doplnÄ›k vyžaduje FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - VAROVÃNÃ: Tento doplnÄ›k je v souÄasné dobÄ› nainstalován, ale je zakázán. Použijte tlaÄítko 'povolit' pro opÄ›tovné povolení. - - - - This Addon will be enabled next time you restart FreeCAD. - Tento doplnÄ›k bude povolen pÅ™i příštím restartu FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Tento doplnÄ›k bude zakázán pÅ™i příštím restartu FreeCAD. - - - - - - Success - ÚspěšnÄ› - - - - Install - Instalovat - - - - Uninstall - Odinstalovat - - - - Enable - Povolit - - - - Disable - Vypnout - - - - - Check for update - Zkontrolujte aktualizaci - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Spustit - - - - Change branch... - ZmÄ›na vÄ›tve... - - - - Return to package list - ZpÄ›t na seznam balíÄků - - - - Checking connection - Ověřování pÅ™ipojení - - - - Checking for connection to GitHub... - Kontrola pÅ™ipojení k GitHubu... - - - - Connection failed - PÅ™ipojení se nezdaÅ™ilo - - - - Missing dependency - ChybÄ›jící závislost - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - NepodaÅ™ilo se importovat QtNetwork -- podrobnosti viz Zobrazení reportu. Správce doplňků není k dispozici. - - - - Other... - For providing a license other than one listed - Ostatní... - - - - Select the corresponding license file in your Addon - Vyberte odpovídající licenÄní soubor ve vaÅ¡em doplňku - - - - Location for new license file - UmístÄ›ní nového licenÄního souboru - - - - Received {} response code from server - Obdržen {} kód odpovÄ›di od serveru - - - - Failed to install macro {} - NepodaÅ™ilo se nainstalovat macro {} - - - - Failed to create installation manifest file: - - NepodaÅ™ilo se vytvoÅ™it instalaÄní soubor: - - - - Unrecognized content kind '{}' - Nerozpoznaný typ obsahu '{}' - - - - Unable to locate icon at {} - Ikonu na {} nelze najít - - - - Select an icon file for this content item - Vyberte soubor ikony pro tuto položku obsahu - - - - - - {} is not a subdirectory of {} - {} není podadresář {} - - - - Select the subdirectory for this content item - Vyberte podadresář pro tuto položku obsahu - - - - Automatic - Automaticky - - - - - Workbench - Pracovní prostÅ™edí - - - - Addon - Doplňek - - - - Python - Python - - - - Yes - Ano - - - - Internal Workbench - Interní pracovní stůl - - - - External Addon - Externí doplnÄ›k - - - - Python Package - Python Package - - - - - Other... - Ostatní... - - - - Too many to list - PříliÅ¡ mnoho k zobrazení seznamu - - - - - - - - - Missing Requirement - ChybÄ›jící požadavek - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - DoplnÄ›k '{}' vyžaduje '{}', což není k dispozici ve vaší kopii FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - DoplnÄ›k '{}' vyžaduje následující pracovní prostÅ™edí, která nejsou dostupná ve vaší kopii FreeCAD: - - - - Press OK to install anyway. - StisknÄ›te OK pro instalaci. - - - - - Incompatible Python version - Nekompatibilní verze Pythonu - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Tento doplnÄ›k vyžaduje balíky Pythonu, které nejsou nainstalovány a nelze je nainstalovat automaticky. Chcete-li použít tento doplnÄ›k, musíte nainstalovat následující balíky Pythonu ruÄnÄ›: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Tento doplnÄ›k (nebo jedna z jeho závislostí) vyžaduje Python {}.{} a váš systém používá {}.{}. Instalace zruÅ¡ena. - - - - Optional dependency on {} ignored because it is not in the allow-list - Volitelná závislost na {} ignorována, protože není v seznamu povolenek - - - - - Installing dependencies - Instalace závislostí - - - - - Cannot execute Python - Python nelze spustit - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - NepodaÅ™ilo se automaticky najít váš spustitelný program Pythonu, nebo je nastavena cesta nesprávnÄ›. Zkontrolujte prosím nastavení nastavení nastavení správce doplňků pro cestu k Pythonu. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Závislosti nelze nainstalovat. Chcete pÅ™esto pokraÄovat s instalací {} {}? - - - - - Cannot execute pip - Nelze spustit pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - NepodaÅ™ilo se spustit funkci pip, která možná chybí v instalaci Pythonu. UjistÄ›te se prosím, že je v systému nainstalován program pip, a zkuste to znovu. Neúspěšný příkaz byl: - - - - - Continue with installation of {} anyway? - Chcete pÅ™esto pokraÄovat s instalací {}? - - - - - Package installation failed - Instalace balíÄku se nezdaÅ™ila - - - - See Report View for detailed failure log. - Detailní protokol selhání, viz Report View. - - - - Installing Addon - Instalovat doplňky - - - - Installing FreeCAD Addon '{}' - Instalace FreeCAD doplňku '{}' - - - - Cancelling - RuÅ¡ení - - - - Cancelling installation of '{}' - Ruší se instalace '{}' - - - - {} was installed successfully - {} byl úspěšnÄ› nainstalován - - - - - Installation Failed - Instalace se nezdaÅ™ila - - - - Failed to install {} - NepodaÅ™ilo se nainstalovat {} - - - - - Create new toolbar - VytvoÅ™it nový panel nástrojů - - - - - A macro installed with the FreeCAD Addon Manager - Makro nainstalované ve správci doplňků FreeCAD - - - - - Run - Indicates a macro that can be 'run' - Spustit - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Nelze Äíst data z GitHubu: zkontrolujte pÅ™ipojení k Internetu a nastavení proxy a zkuste to znovu. - - - - XML failure while reading metadata from file {} - XML selhal pÅ™i Ätení metadat ze souboru {} - - - - Invalid metadata in file {} - Neplatná metadata v souboru {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - VAROVÃNÃ: Cesta zadaná v souboru package.xml metadata neodpovídají aktuálnÄ› kontrolované vÄ›tvi. - - - - Name - Název - - - - Class - Třída - - - - Description - Popis - - - - Subdirectory - Podadresář - - - - Files - Soubory - - - - Select the folder containing your Addon - Vyberte složku obsahující doplnÄ›k - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Žádné Vermin, zruÅ¡ení operace. - - - - Scanning Addon for Python version compatibility - Skenování doplňku pro kompatibilitu verze Pythonu - - - - Minimum Python Version Detected - ZjiÅ¡tÄ›na minimální verze Pythonu - - - - Vermin auto-detected a required version of Python 3.{} - Vermin automaticky detekoval požadovanou verzi Pythonu 3.{} - - - - Install Vermin? - Instalovat Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Automatická detekce požadované verze Pythonu pro tento doplnÄ›k vyžaduje Vermin (https://pypi.org/project/vermin/). Je instalace v pořádku? - - - - Attempting to install Vermin from PyPi - Pokus o instalaci Vermin z PyPi - - - - - Installation failed - Instalace se nezdaÅ™ila - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - NepodaÅ™ilo se nainstalovat Vermin -- Zkontrolujte Report View pro podrobnosti. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - NepodaÅ™ilo se importovat vermin po instalaci -- Nelze skenovat Addon. - - - - Select an icon file for this package - Vyberte soubor ikony pro tento balíÄek - - - - Filter is valid - Filtr je platný - - - - Filter regular expression is invalid - Regulární výraz filtru je neplatný - - - - Search... - Hledat... - - - - Click for details about package {} - KliknÄ›te pro podrobnosti o balíÄku {} - - - - Click for details about workbench {} - KliknÄ›te pro podrobnosti o pracovním prostÅ™edí {} - - - - Click for details about macro {} - KliknÄ›te pro podrobnosti o makro {} - - - - Maintainers: - Správci: - - - - Tags - Å títky - - - - {} ★ on GitHub - {} ★ na GitHubu - - - - No ★, or not on GitHub - Ne ★, nebo není na GitHubu - - - - Created - VytvoÅ™eno - - - - Updated - Aktualizováno - - - - Score: - Skóre: - - - - - Up-to-date - Aktualizováno - - - - - - - - Update available - K dispozici je aktualizace - - - - - Pending restart - ÄŒekající restart - - - - - DISABLED - VYPNOUT - - - - Installed version - Nainstalovaná verze - - - - Unknown version - Neznámá verze - - - - Installed on - Nainstalováno - - - - Available version - Dostupná verze - - - - Filter by... - Filtrovat dle... - - - - Addon Type - Typ doplňku - - - - - Any - Jakýkoli - - - - Macro - Makro - - - - Preference Pack - PÅ™edvolby balíÄku - - - - Installation Status - Stav instalace - - - - Not installed - Není nainstalováno - - - - Filter - Filtr - - - - DANGER: Developer feature - DANGER: Funkce vývojáře - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: PÅ™epínací vÄ›tve jsou urÄeny pro vývojáře a beta testery a mohou mít za následek rozbití, dokumenty, které nejsou zpÄ›tnÄ› sluÄitelné, nestabilita, havárie a/nebo pÅ™edÄasná tepelná smrt vesmíru. Jste si jisti, že chcete pokraÄovat? - - - - There are local changes - Existují lokální zmÄ›ny - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - VAROVÃNÃ: Tento repozitář má neprovedené místní zmÄ›ny. Jste si jisti, že chcete zmÄ›nit vÄ›tve (pÅ™ináší zmÄ›ny s vámi)? - - - - Local - Table header for local git ref name - Místní - - - - Remote tracking - Table header for git remote tracking branch name - Vzdálené sledování - - - - Last Updated - Table header for git update date - Poslední aktualizace - - - - Installation of Python package {} failed - Instalace Pythonu {} selhala - - - - Installation of optional package failed - Instalace volitelného balíÄku selhala - - - - Installing required dependency {} - Instalace požadované závislosti {} - - - - Installation of Addon {} failed - Instalace doplňku {} selhala - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - NepodaÅ™ilo se dekódovat {} soubor pro Addon '{}' - - - - Any dependency information in this file will be ignored - Informace o závislosti v tomto souboru budou ignorovány - - - - Unable to open macro wiki page at {} - Nelze otevřít makro wiki stránku na {} - - - - Unable to fetch the code of this macro. - Nelze naÄíst kód tohoto makra. - - - - Unable to retrieve a description from the wiki for macro {} - Nelze naÄíst popis z wiki pro makro {} - - - - Unable to open macro code URL {} - Nelze otevřít makro kód URL {} - - - - Unable to fetch macro-specified file {} from {} - Nelze naÄíst makrostanovený soubor {} od {} - - - - Could not locate macro-specified file {} (expected at {}) - Nelze najít makrospecifikovaný soubor {} (oÄekáváno v {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Nerozpoznaný interní pracovní stůl '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Varování pro vývojáře doplňku: URL adresa repozitáře nastavená v souboru addon {} ({}) neodpovídá URL adrese, ze které byla naÄtena ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Varování pro vývojáře doplňku: vÄ›tev repozitáře nastavená v souboru package.xml pro addon {} ({}) neodpovídá vÄ›tvi, ze které byla naÄtena ({}) - - - - - Got an error when trying to import {} - DoÅ¡lo k chybÄ› pÅ™i pokusu o import {} - - - - An unknown error occurred - DoÅ¡lo k neznámé chybÄ› - - - - Could not find addon {} to remove it. - DoplnÄ›k {} nelze najít. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Provedení uninstall.py skriptu addon's selhalo. PokraÄujte s odinstalování... - - - - Removed extra installed file {} - OdstranÄ›ný extra nainstalovaný soubor {} - - - - Error while trying to remove extra installed file {} - Chyba pÅ™i pokusu o odstranÄ›ní extra nainstalovaného souboru {} - - - - Error while trying to remove macro file {}: - Chyba pÅ™i pokusu o odstranÄ›ní makrosouboru {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - NepodaÅ™ilo se pÅ™ipojit k GitHubu. Zkontrolujte nastavení pÅ™ipojení a proxy serveru. - - - - WARNING: Duplicate addon {} ignored - VAROVÃNÃ: Duplikovat doplnÄ›k {} ignorován - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - DoÅ¡lo k chybÄ› pÅ™i aktualizaci maker z GitHubu, pokusu o vyÄiÅ¡tÄ›ní pokladny... - - - - Attempting to do a clean checkout... - Pokus o vyÄiÅ¡tÄ›ní pokladny... - - - - Clean checkout succeeded - Vymazání platby bylo úspěšné - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Aktualizace maker z GitHubu se nezdaÅ™ila – zkuste vymazat mezipaměť Správce doplňků. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Chyba pÅ™i pÅ™ipojování k Wiki, FreeCAD momentálnÄ› nemůže naÄíst Wiki makro seznam - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - NepodaÅ™ilo se pÅ™eÄíst metadata z {name} - - - - Failed to fetch code for macro '{name}' - NepodaÅ™ilo se naÄíst kód pro makro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Správce doplňků: pÅ™i naÄítání {name} se nepodaÅ™ilo dokonÄit proces pracovníka - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Z {num_macros} maker vyprÅ¡el Äasový limit {num_failed} pÅ™i zpracování - - - - Addon Manager: a worker process failed to halt ({name}) - Správce doplňků: proces pracovníka se nepodaÅ™ilo zastavit ({name}) - - - - Timeout while fetching metadata for macro {} - ÄŒasový limit pÅ™i naÄítání metadat pro makro {} - - - - Failed to kill process for macro {}! - - NepodaÅ™ilo se ukonÄit proces pro makro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - NepodaÅ™ilo se získat statistiky doplňků z {} -- pÅ™esné bude pouze abecední Å™azení - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - NepodaÅ™ilo se získat hodnocení doplňku z '{}' -- Å™azení podle skóre selže - - - - Repository URL - Preferences header for custom repositories - URL adresa repozitáře - - - - Branch name - Preferences header for custom repositories - Název poboÄky - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Zálohování původního adresáře a opÄ›tovné klonování - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - PÅ™ejmenování vÄ›tve systému Git selhalo s následující zprávou: - - - - Installing - Instalace - - - - Succeeded - ÚspěšnÄ› - - - - Failed - Selhalo - - - - Update was cancelled - Aktualizace byla zruÅ¡ena - - - - some addons may have been updated - nÄ›které doplňky mohly být aktualizovány - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - NaÄítání informací pro {} z wiki FreeCAD Macro Recipes... - - - - Loading page for {} from {}... - NaÄítání stránky pro {} z {}... - - - - Failed to download data from {} -- received response code {}. - NepodaÅ™ilo se stáhnout data z {} -- obdržel kód odpovÄ›di {}. - - - - Composite view - Složené zobrazení - - - - Expanded view - Rozšířené zobrazení - - - - Compact view - Kompaktní zobrazení - - - - Alphabetical - Sort order - Abecední Å™azení - - - - Last Updated - Sort order - Poslední aktualizace - - - - Date Created - Sort order - Datum vytvoÅ™ení - - - - GitHub Stars - Sort order - PříspÄ›vky GitHub - - - - Score - Sort order - Výsledky - - - - Std_AddonMgr - - - &Addon manager - &Správce doplňků - - - - Manage external workbenches, macros, and preference packs - Správa externích pracovních prostÅ™edí, maker a balíÄků preferencí - - - - AddonInstaller - - - Finished removing {} - DokonÄeno odstranÄ›ní {} - - - - Failed to remove some files - NepodaÅ™ilo se odstranit nÄ›které soubory - - - - Addons installer - - - Finished updating the following addons - Aktualizace následujících doplňků dokonÄena - - - - Workbench - - - Auto-Created Macro Toolbar - Automaticky vytvoÅ™ený panel nástrojů makra - - - - QObject - - - Addon Manager - Správce rozšíření - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_da.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_da.qm deleted file mode 100644 index 968611942451ef07dd0aae113bd798155d2775f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68363 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 - - - - AddCustomRepositoryDialog - - - Custom repository - Tilpasset repo - - - - Repository URL - Repo-URL - - - - Branch - Gren - - - - CompactView - - - - Icon - Ikon - - - - - <b>Package Name</b> - <b>Pakkenavn</b> - - - - - Version - Version - - - - - Description - Beskrivelse - - - - Update Available - Opdatering tilgængelig - - - - UpdateAvailable - Opdatering tilgængelig - - - - DependencyDialog - - - Dependencies - Afhængigheder - - - - Dependency type - Afhængighedstype - - - - Name - Navn - - - - Optional? - Valgfri? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Løs afhængigheder - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Denne Tilføjelse har flg. krævede og valgfrie afhængigheder. Disse skal installeres, før denne Tilføjelse kan bruges. - -Skal TilføjelseshÃ¥ndtering installere dem automatisk? Vælg "Ignorér" for at installere Tilføjelse uden at installere afhængighederne. - - - - FreeCAD Addons - FreeCAD-tilføjelser - - - - Required Python modules - Obligatoriske Python-moduler - - - - Optional Python modules - Valgfrie Python-moduler - - - - DeveloperModeDialog - - - Addon Developer Tools - Tilføjelsesudviklerværktøjer - - - - Path to Addon - Sti til Tilføjelse - - - - - Browse... - Gennemse... - - - - Metadata - Metadata - - - - Primary branch - Primære gren - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Forklaring af, hvad denne Tilføjelse leverer. Vil fremgÃ¥ under TilføjelseshÃ¥ndtering. Det er ikke nødvendigt at angive, at dette er en FreeCAD-tilføjelse. - - - - Description - Beskrivelse - - - - Discussion URL - Debat-URL - - - - Icon - Ikon - - - - Bugtracker URL - Bugtracker-URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) eller CalVer (2022.08.30) stilarter understøttes - - - - Set to today (CalVer style) - Sæt til i dag (CalVer-stil) - - - - - - - (Optional) - (Valgfri) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Vist pÃ¥ TilføjelseshÃ¥ndtering-listen over Tilføjelser. Bør ikke omfatte ordet "FreeCAD", og skal være et gyldigt mappenavn pÃ¥ alle understøttende operativsystemer. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Da dette vises i FreeCAD i Addon Manager, er det er ikke nødvendigt at bruge plads pÃ¥ info sÃ¥som "Dette er en FreeCAD Addon." – blot info, hvad den gør. - - - - Repository URL - Repo-URL - - - - Website URL - Websteds-URL - - - - Documentation URL - Dokumentation-URL - - - - Addon Name - Tilføjelsesnavn - - - - Version - Version - - - - (Recommended) - (Anbefalet) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Valgfri, kun version 3.x understøttes) - - - - Detect... - Detektér... - - - - Addon Contents - Tilføjelsesindhold - - - - Dialog - - - Addon Manager - TilføjelseshÃ¥ndtering - - - - Edit Tags - Redigér tag - - - - Comma-separated list of tags describing this item: - Kommasepareret liste over tags, som beskriver dette element: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - TIP: Fælles-tags omfatter "Assembly", "FEM", "Mesh", "NURBS" mv. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Continue - - - - Cancel - Annuller - - - - EditDependencyDialog - - - Edit Dependency - Redigér Afhængighed - - - - Dependency Type - Afhængighedstype - - - - Dependency - Afhængighed - - - - Package name, if "Other..." - Pakkenavn, hvis "Andet..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - BEMÆRK: Hvis "Andet..." er valgt, er pakken ikke i ALLOWED_PYTHON_PAKNINGER.txt-filen og installeres ikke automatisk af TilføjelseshÃ¥ndtering. Indsend en PR pÃ¥ <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> for at anmode om tilføjelse af en pakke. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Er denne en valgfri afhængighed, vil TilføjelseshÃ¥ndtering tilbyde at installere den (nÃ¥r muligt), men vil ikke blokere installationen, hvis brugeren vælger ikke at – eller ikke kan – installere pakken. - - - - Optional - Valgfri - - - - ExpandedView - - - - Icon - Ikon - - - - - <h1>Package Name</h1> - <h1>Pakkenavn</h1> - - - - - Version - Version - - - - - (tags) - (tags) - - - - - Description - Beskrivelse - - - - - Maintainer - Vedligeholder - - - - Update Available - Opdatering tilgængelig - - - - labelSort - etiketsortering - - - - UpdateAvailable - Opdatering tilgængelig - - - - Form - - - Licenses - Licenser - - - - License - Licens - - - - License file - Licensfil - - - - People - Personer - - - - Kind - Art - - - - Name - Navn - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Avanceret versionsassociering - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Kommende versioner af FreeCAD TilføjelseshÃ¥ndtering vil understøtte, at udviklere indstiller en bestemt gren eller tag til brug med en bestemt version af FreeCAD (f. eks. sætte et bestemt tag som den sidste Tilføjelsesversion understøttet af v0.19 mv.) - - - - FreeCAD Version - FreeCAD-version - - - - Best-available branch, tag, or commit - Best-tilgængelig gren, tag eller commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Understøttede FreeCAD-versioner - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD-version understøttet - - - - - Optional - Valgfri - - - - Maximum FreeCAD Version Supported - Minimum FreeCAD-version understøttet - - - - Advanced version mapping... - Avanceret versionsassociering... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - TilføjelseshÃ¥ndteringsindstillinger - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Er denne mulighed markeret, kontrolleres -installerede tilføjelser for opdateringer ifm. start af TilføjelseshÃ¥ndtering - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Download Makro-metadata (ca. 10MB) - - - - Cache update frequency - Cacheopdateringsfrekvens - - - - Manual (no automatic updates) - Manuelt (ingen automatiske opdateringer) - - - - Daily - Dagligt - - - - Weekly - Ugentligt - - - - Hide Addons without a license - Skjul tilføjelser uden en licens - - - - Hide Addons with non-FSF Free/Libre license - Skjul tilføjelser med ikke-FSF Free/Libre licens - - - - Hide Addons with non-OSI-approved license - Skjul tilføjelser med ikke-OSI godkendt licens - - - - Hide Addons marked Python 2 Only - Skjul kun tilføjelser markeret med Python 2 - - - - Hide Addons marked Obsolete - Skjul tilføjelser markeret Forældet - - - - Hide Addons that require a newer version of FreeCAD - Skjul tilføjelser, som kræver en nyere version af FreeCAD - - - - Custom repositories - Tilpasset repos - - - - Proxy - Proxy - - - - No proxy - Ingen proxy - - - - User system proxy - Benyt systemproxy - - - - User-defined proxy: - Brugerdefineret proxy: - - - - Score source URL - Scorekilde-URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - URL til Tilføjelsesscoredata (se TilføjelseshÃ¥ndterings wiki-side for formatering og hosting-detaljer). - - - - Path to Git executable (optional): - Sti til Git eksekverbar (valgfri): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Avancerede indstillinger - - - - Activate Addon Manager options intended for developers of new Addons. - Aktivér TilføjelseshÃ¥ndteringsvalgmuligheder beregnet til udviklere af nye Tilføjelser. - - - - Addon developer mode - Tilføjelsesudviklertilstand - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Afinstallerer en valgt makro eller arbejdsbord - - - - Install - Installation - - - - Uninstall - Afinstallation - - - - Update - Opdatering - - - - Run Macro - Kør makro - - - - Change branch - Skift gren - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - HÃ¥ndtér Python-afhængigheder - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Flg. Python-pakker er blevet installeret lokalt af TilføjelseshÃ¥ndtering for at tilfredsstille Tilføjelsesafhængigheder. Installationsplacering: - - - - Package name - Pakkenavn - - - - Installed version - Installeret version - - - - Available version - Tilgængelig version - - - - Used by - Brugt af - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - En stjerne (*) i "Bruges af"-kolonnen angiver en valgfri afhængighed. Bemærk, at Bruges af kun registrerer direkte import i tilføjelsen. Andre Python-pakker, som disse pakker afhænger af, kan ogsÃ¥ være blevet installeret. - - - - Update all available - Opdatering alle tilgængelige - - - - SelectFromList - - - Dialog - Dialog - - - - TextLabel - Tekstlabel - - - - UpdateAllDialog - - - Updating Addons - Opdaterer Tilføjelser - - - - Updating out-of-date addons... - Opdaterer forældede tilføjelser... - - - - addContentDialog - - - Content Item - Indholdselement - - - - Content type: - Indholdstype: - - - - Macro - Makro - - - - Preference Pack - Præferencepakke - - - - Workbench - Arbejdsbord - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Er dette det eneste i tilføjelsen, kan alle andre metadata arves fra det øverste niveau og behøves ikke specificeres her. - - - - This is the only item in the Addon - Dette er det eneste element i tilføjelsen - - - - Main macro file - Hovedmakrofil - - - - The file with the macro's metadata in it - Filen indeholdende makrometadataene - - - - - - Browse... - Gennemse... - - - - Preference Pack Name - Navn pÃ¥ præference pakke - - - - Workbench class name - Arbejdsbordklassenavn - - - - Class that defines "Icon" data member - Klasse, der definerer "Ikon"-datamedlem - - - - Subdirectory - Undermappe - - - - Optional, defaults to name of content item - Valgfri, standard er navnet pÃ¥ indholdselement - - - - Icon - Ikon - - - - Optional, defaults to inheriting from top-level Addon - Valgfri, standard er arvning fra topniveautilføjelse - - - - Tags... - Tags... - - - - Dependencies... - Afhængigheder... - - - - FreeCAD Versions... - FreeCAD-versioner... - - - - Other Metadata - Andre metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Vist i TilføjelseshÃ¥ndtering-listen over Addons. Bør ikke omfatte ordet "FreeCAD". - - - - Version - Version - - - - Description - Beskrivelse - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) eller CalVer (2022.08.30) stilarter understøttes - - - - Set to today (CalVer style) - Sæt til i dag (CalVer-stil) - - - - Display Name - Visningsnavn - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Evt. felter efterladt blanke arves fra de øverste niveau Tilføjelse-metadata, sÃ¥ teknisk set er de alle valgfrie. For tilføjelser med flere indholdselementer skal hvert element vise et unikt visningsnavn og -beskrivelse. - - - - add_toolbar_button_dialog - - - Add button? - Tilføj knap? - - - - Add a toolbar button for this macro? - Tilføj en værktøjsbjælkeknap for denne makro? - - - - Yes - Ja - - - - No - Nej - - - - Never - Aldrig - - - - change_branch - - - Change Branch - Skift gren - - - - Change to branch: - Skift til gren: - - - - copyrightInformationDialog - - - Copyright Information - Ophavsretsoplysninger - - - - Copyright holder: - Ophavsrettighedsindehaver: - - - - Copyright year: - OphavsrettighedsÃ¥r: - - - - personDialog - - - Add Person - Tilføj person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - En vedligeholder er en person med aktuel commit-rettighed til dette projekt. En forfatter er enhver anden, man gerne vil tildele rettighed. - - - - Name: - Navn: - - - - Email: - E-mail: - - - - Email is required for maintainers, and optional for authors. - E-mail er obligatorisk for vedligeholdere og valgfri for forfattere. - - - - proxy_authentication - - - Proxy login required - Proxylogin er obligatorisk - - - - Proxy requires authentication - Proxy kræver godkendelse - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Variabel til proxyadresse - - - - Realm: - OmrÃ¥de: - - - - Placeholder for proxy realm - Variabel til proxyomrÃ¥de - - - - Username - Brugernavn - - - - Password - Adgangskode - - - - selectLicenseDialog - - - Select a license - Vælg en licens - - - - About... - Om... - - - - License name: - Licensnavn: - - - - Path to license file: - Sti til licensfil: - - - - (if required by license) - (sÃ¥fremt krævet af licens) - - - - Browse... - Gennemse... - - - - Create... - Opret... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Vælg Værktøjsbjælke - - - - Select a toolbar to add this macro to: - Vælg en værktøjsbjælke at føje denne makro til: - - - - Ask every time - Spørg hver gang - - - - toolbar_button - - - - Add button? - Tilføj knap? - - - - Add a toolbar button for this macro? - Tilføj en værktøjsbjælkeknap for denne makro? - - - - Yes - Ja - - - - No - Nej - - - - Never - Aldrig - - - - AddonsInstaller - - - Starting up... - Starter op... - - - - Worker process {} is taking a long time to stop... - Worker-proces {} tager lang tid at stoppe... - - - - Previous cache process was interrupted, restarting... - - Tidligere cacheproces blev afbrudt, genstarter... - - - - - Custom repo list changed, forcing recache... - - Tilpasset repo-liste ændret, gennemtvinger cacheopfriskning... - - - - - Addon manager - TilføjelseshÃ¥ndtering - - - - You must restart FreeCAD for changes to take effect. - FreeCAD skal genstartes for at effektuere ændringerne. - - - - Restart now - Genstart nu - - - - Restart later - Genstart senere - - - - - Refresh local cache - Opfrisk lokal cache - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Updaterer cache… - - - - - Checking for updates... - Søger efter opdateringer... - - - - Temporary installation of macro failed. - Midlertidig installation af makro mislykkedes. - - - - - Close - Luk - - - - Update all addons - Opdatér alle tilføjelser - - - - Check for updates - Søg efter opdateringer - - - - Python dependencies... - Python-afhængigheder... - - - - Developer tools... - Udviklingsværktøjer... - - - - Apply %n available update(s) - Anvend %n tilgængelig(e) opdatering(er) - - - - No updates available - Ingen opdateringer tilgængelige - - - - - - Cannot launch a new installer until the previous one has finished. - Kan ikke starte en ny installer, før den foregÃ¥ende er færdig. - - - - - - - Maintainer - Vedligeholder - - - - - - - Author - Forfatter - - - - New Python Version Detected - Ny Python-version detekteret - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Det lader til at være første gang denne version af Python er blevet brugt sammen med TilføjelseshÃ¥ndtering. Installér de samme autoinstallerede afhængigheder til den? - - - - Processing, please wait... - Behandler, vent venligst... - - - - - Update - Opdatering - - - - Updating... - Opdaterer... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Kunne ikke importere QtNetwork – det synes ikke at være installeret pÃ¥ systemet. Udbyderen kan have en pakke til denne afhængighed (ofte kaldet "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Kunne ikke konvertere den angivne proxyport '{}' til et portnummer - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameterfejl: Gensidig eksklusiv proxyindstillingssæt. Nulstiller til standard. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameterfejl: Brugerproxy indikeret, men ingen proxy angivet. Nulstiller til standard. - - - - Addon Manager: Unexpected {} response from server - TilføjelseshÃ¥ndtering: Uventet {}-svar fra server - - - - Error with encrypted connection - Fejl pÃ¥ krypteret forbindelse - - - - - - Confirm remove - Bekræft fjernelse - - - - Are you sure you want to uninstall {}? - Sikker pÃ¥, at {} skal afinstalleres? - - - - - - Removing Addon - Fjerner tilføjelse - - - - Removing {} - Fjerner {} - - - - - Uninstall complete - Afinstallation er færdig - - - - - Uninstall failed - Afinstallation mislykkedes - - - - Version {version} installed on {date} - Version {version} installeret pr. {date} - - - - Version {version} installed - Version {version} installeret - - - - Installed on {date} - Installeret pr. {date} - - - - - - - Installed - Installeret - - - - Currently on branch {}, name changed to {} - Aktuelt pÃ¥ gren {}, navn ændret til {} - - - - Git tag '{}' checked out, no updates possible - Git-tag '{}' tjekket ud, ingen opdateringer er mulige - - - - Update check in progress - Opdateringstjek i gang - - - - Installation location - Installationsplacering - - - - Repository URL - Repo-URL - - - - Changed to branch '{}' -- please restart to use Addon. - Ændret til gren '{}' – genstart for at anvende tilføjelsen. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Denne tilføjelse er blevet opdateret. Genstart FreeCAD for at se ændringer. - - - - Disabled - Deaktiveret - - - - Currently on branch {}, update available to version {} - Pt. pÃ¥ gren {}, opdatering tilgængelig til version {} - - - - Update available to version {} - Opdatering tilgængelig til version {} - - - - This is the latest version available - Dette er seneste tilgængelige version - - - - WARNING: This addon is obsolete - ADVARSEL: Denne tilføjelse er forældet - - - - WARNING: This addon is Python 2 only - ADVARSEL: Dette er en ren Python 2-tilføjelse - - - - WARNING: This addon requires FreeCAD {} - ADVARSEL: Denne tilføjelse kræver FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ADVARSEL: Denne tilføjelse er p.t. installeret, men deaktiveret. Brug knappen 'Aktivér' for at genaktivere. - - - - This Addon will be enabled next time you restart FreeCAD. - Denne Addon aktiveres ved næste FreeCAD-genstart. - - - - This Addon will be disabled next time you restart FreeCAD. - Denne Addon deaktiveres ved næste FreeCAD-genstart. - - - - - - Success - Succes - - - - Install - Installation - - - - Uninstall - Afinstallation - - - - Enable - Aktivér - - - - Disable - Deaktivér - - - - - Check for update - Tjek for opdateringer - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Kør - - - - Change branch... - Skift gren... - - - - Return to package list - Retur til pakkeliste - - - - Checking connection - Tjekker forbindelse - - - - Checking for connection to GitHub... - Tjekker forbindelse til GitHub... - - - - Connection failed - Forbindelse fejlede - - - - Missing dependency - Manglende afhængighed - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Kunne ikke importere QtNetwork – se Rapportvisning for detaljer. TilføjelseshÃ¥ndtering er utilgængelig. - - - - Other... - For providing a license other than one listed - Andet... - - - - Select the corresponding license file in your Addon - Vælg den modsvarende licensfil i tilføjelsen - - - - Location for new license file - Placering pÃ¥ ny licensfil - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Mislykkedes at installere makroen {} - - - - Failed to create installation manifest file: - - Mislykkedes at oprette installationsmanifestfil: - - - - - Unrecognized content kind '{}' - Ukendt indholdsart '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Vælg en ikonfil til dette indholdsemne - - - - - - {} is not a subdirectory of {} - {} er ikke en undermappe til {} - - - - Select the subdirectory for this content item - Vælg undermappen til dette indholdsemne - - - - Automatic - Automatisk - - - - - Workbench - Arbejdsbord - - - - Addon - Tilføjelse - - - - Python - Python - - - - Yes - Ja - - - - Internal Workbench - Internt Arbejdsbord - - - - External Addon - Ekstern Tilføjelse - - - - Python Package - Python-pakke - - - - - Other... - Andet... - - - - Too many to list - For mange at opliste - - - - - - - - - Missing Requirement - Manglende betingelse - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Tilføjelsen '{}' kræver '{}', der er utilgængelig i denne FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Tilføjelsen '{}' kræver flg. arbejdsborde, som er utilgængelige i denne FreeCAD: - - - - Press OK to install anyway. - Tryk OK for at installere alligevel. - - - - - Incompatible Python version - Inkompatibel Python-version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Denne tilføjelse kræver Python-pakker, som ikke er installeret, og som kan ikke installeres automatisk. For at bruge denne tilføjelse skal du installere følgende Python-pakker manuelt: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installation af afhængigheder - - - - - Cannot execute Python - Kan ikke eksekvere Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Automatisk lokalisering af Python-eksekverbare mislykkedes, eller forkert angivet sti. Tjek TilføjelseshÃ¥ndtering-præferenceindstillingen for stien til Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Afhængigheder kunne ikke installeres. Fortsæt installation af {} alligevel? - - - - - Cannot execute pip - Kan ikke eksekvere pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Mislykkedes at eksekvere pip, der mÃ¥ske mangler i Python-installationen. Tjek, at systemet har pip installeret og forsøg igen. Den fejlede kommando var: - - - - - Continue with installation of {} anyway? - Fortsæt med installation af {} alligevel? - - - - - Package installation failed - Pakkeinstallation mislykkedes - - - - See Report View for detailed failure log. - Se Rapportvisning for detaljeret fejllog. - - - - Installing Addon - Installerer Tilføjelse - - - - Installing FreeCAD Addon '{}' - Installerer FreeCAD-tilføjeelse '{}' - - - - Cancelling - Afbryder - - - - Cancelling installation of '{}' - Afbryder installationen af '{}' - - - - {} was installed successfully - {} er hermed installeret - - - - - Installation Failed - Installation mislykkedes - - - - Failed to install {} - Mislykkedes at installere {} - - - - - Create new toolbar - Opret ny værktøjsbjælke - - - - - A macro installed with the FreeCAD Addon Manager - En makro installeret med FreeCAD TilføjelseshÃ¥ndtering - - - - - Run - Indicates a macro that can be 'run' - Kør - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Kan ikke læse data fra GitHub: Tjek internetforbindelsen og proxyindstillingerne, og forsøg igen. - - - - XML failure while reading metadata from file {} - XML-fejl under metadatalæsning fra filen {} - - - - Invalid metadata in file {} - Ugyldig metadata i filen {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ADVARSEL: Sti angivet i package.xml-metadata matcher ikke p.t. udtjekkede gren. - - - - Name - Navn - - - - Class - Klasse - - - - Description - Beskrivelse - - - - Subdirectory - Undermappe - - - - Files - Filer - - - - Select the folder containing your Addon - Vælg mappen indeholdende tilføjelsen - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Ingen Vermin, afbryder handling. - - - - Scanning Addon for Python version compatibility - Skanner tilføjelse for Python-versionskompatibilitet - - - - Minimum Python Version Detected - Minimum Python-version detekteret - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detekterede en krævet version af Python 3.{} - - - - Install Vermin? - Installér Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detektering af den krævede Python-version til denne tilføjelse kræver Vermin (https://pypi.org/project/vermin/). OK at installere? - - - - Attempting to install Vermin from PyPi - Forsøger at installere Vermin fra PyPi - - - - - Installation failed - Installation mislykkedes - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Mislykkedes at installere Vermin – tjek Rapportvisning for detaljer. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Kunne ikke importere vermin efter installation – kan ikke skanne tilføjelse. - - - - Select an icon file for this package - Vælg en ikonfil til denne pakke - - - - Filter is valid - Filter er gyldigt - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Søg... - - - - Click for details about package {} - Klik for detaljer om pakken {} - - - - Click for details about workbench {} - Klik for detaljer om arbejdsbordet {} - - - - Click for details about macro {} - Klik for detaljer om makroen {} - - - - Maintainers: - Vedligeholdere: - - - - Tags - Tags - - - - {} ★ on GitHub - {} ★ pÃ¥ GitHub - - - - No ★, or not on GitHub - Ingen ★, eller ikke pÃ¥ GitHub - - - - Created - Oprettet - - - - Updated - Opdateret - - - - Score: - Score: - - - - - Up-to-date - Opdateret - - - - - - - - Update available - Opdatering tilgængelig - - - - - Pending restart - Afventer genstart - - - - - DISABLED - DEAKTIVERET - - - - Installed version - Installeret version - - - - Unknown version - Ukendt version - - - - Installed on - Installeret pr. - - - - Available version - Tilgængelig version - - - - Filter by... - Filtrér efter... - - - - Addon Type - Tilføjelsestype - - - - - Any - Enhver - - - - Macro - Makro - - - - Preference Pack - Præferencepakke - - - - Installation Status - Installationsstatus - - - - Not installed - Ikke installeret - - - - Filter - Filter - - - - DANGER: Developer feature - FARE: Udviklerfunktion - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - FARE: Skift af grene er beregnet til udviklere og betatestere, og det kan resultere i ødelagte, ikke-bagudkompatible dokumenter, ustabilitet, nedbrud og/eller for tidlig varmedød for universet. Fortsæt alligevel? - - - - There are local changes - Der er lokale ændringer - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ADVARSEL: Dette repo har ikke-committede lokale ændringer. Sikker pÃ¥, at der skal skiftes grene (medbringende ændringerne)? - - - - Local - Table header for local git ref name - Lokal - - - - Remote tracking - Table header for git remote tracking branch name - Fjernsporing - - - - Last Updated - Table header for git update date - Senest opdateret - - - - Installation of Python package {} failed - Installation af Python-pakken {} mislykkedes - - - - Installation of optional package failed - Installation af den valgfrie pakke {} mislykkedes - - - - Installing required dependency {} - Installerer krævet afhængighed {} - - - - Installation of Addon {} failed - Installation af tilføjelsen {} mislykkedes - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Mislykkedes at afkode {}-filen til tilføjelsen '{}' - - - - Any dependency information in this file will be ignored - Enhver afhængighedsinformation i denne fil ignoreres - - - - Unable to open macro wiki page at {} - Kan ikke Ã¥bne makro wiki-siden pÃ¥ {} - - - - Unable to fetch the code of this macro. - Kan ikke hente denne makros kode. - - - - Unable to retrieve a description from the wiki for macro {} - Kan ikke hente en beskrivelse fra wiki'en til makroen {} - - - - Unable to open macro code URL {} - Kan ikke Ã¥bne makrokode-URL'en {} - - - - Unable to fetch macro-specified file {} from {} - Kan ikke hente makrospecificeret fil {} fra {} - - - - Could not locate macro-specified file {} (expected at {}) - Kunne ikke finde makrospecificeret fil {} (forventet pÃ¥ {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Ukendt internt arbejdsbord '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Tiløjelsesudvikleradvarsel: Repo-URL angivet i package.xml fil til tilføjelsen {} ({}) matcher ikke URL'en, den blev hentet fra ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Tiløjelsesudvikleradvarsel: Repo-grenen angivet i package.xml fil til tilføjelsen {} ({}) matcher ikke grenen, den blev hentet fra ({}) - - - - - Got an error when trying to import {} - Fik en fejl under forsøget pÃ¥ at importere {} - - - - An unknown error occurred - En ukendt fejl opstod - - - - Could not find addon {} to remove it. - Kunne ikke finde tilføjelsen {} for at fjerne den. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Eksekvering af tilføjelsens uninstall.py-script mislykkedes. Fortsætter afinstallationen... - - - - Removed extra installed file {} - Fjernede ekstra installeret fil {} - - - - Error while trying to remove extra installed file {} - Fejl under forsøget pÃ¥ at fjerne ekstra installeret fil {} - - - - Error while trying to remove macro file {}: - Fejl under forsøget pÃ¥ at fjerne makrofilen {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Kunne ikke oprette forbindelse til GitHub. Tjek forbindelsen og proxyindstillingerne. - - - - WARNING: Duplicate addon {} ignored - ADVARSEL: Dublettilføjelsen {} ignoreret - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - En fejl opstod under opdatering af makroer fra GitHub, forsøger ren tjekud... - - - - Attempting to do a clean checkout... - Forsøger at foretage en ren tjekud... - - - - Clean checkout succeeded - Ren tjekud lykkedes - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Mislykkedes at opdatere makroer fra GitHub – prøv at rydde TilføjelseshÃ¥ndtering-cachen. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Fejl ved tilslutning til Wiki. FreeCAD kan ikke p.t. hente Wiki-makrolisten - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Kunne ikke læse metadata fra {name} - - - - Failed to fetch code for macro '{name}' - Kunne ikke hente kode til makroen '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - TilføjelseshÃ¥ndtering: En worker-proces kunne ikke færdiggøres under hentningen af {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Ud af {num_macros} makroer, fik {num_failed} timeout under behandling - - - - Addon Manager: a worker process failed to halt ({name}) - TilføjelseshÃ¥ndtering: En worker-proces kunne ikke standse ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout under hentning af metadata til makroen {} - - - - Failed to kill process for macro {}! - - Mislykkedes at standse processen for makroen {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Kunne ikke hente tilføjelsesstatistik fra {} – kun alfabetisk sortering vil være præcis - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Kunne ikke fÃ¥ tilføjelsesscore fra '{}' – sortering efter score vil mislykkes - - - - - Repository URL - Preferences header for custom repositories - Repo-URL - - - - Branch name - Preferences header for custom repositories - Grennavn - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Sikkerhedskopiering af den oprindelige mappe og genkloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Grenomdøbning mislykkedes med flg. meddelelse: - - - - Installing - Installerer - - - - Succeeded - Gennemført - - - - Failed - Mislykket - - - - Update was cancelled - Opdatering blev afbrudt - - - - some addons may have been updated - nogle tilføjelser kan være blevet opdateret - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Indlæser info for {} fra FreeCAD Makroopskrifter wiki... - - - - Loading page for {} from {}... - Indlæser side til {} fra {}... - - - - Failed to download data from {} -- received response code {}. - Mislykkedes at downloade data fra {} – modtaget svarkode {}. - - - - Composite view - Sammensat visning - - - - Expanded view - Udvidet visning - - - - Compact view - Kompakt visning - - - - Alphabetical - Sort order - Alfabetisk - - - - Last Updated - Sort order - Senest opdateret - - - - Date Created - Sort order - Oprettelsesdato - - - - GitHub Stars - Sort order - GitHub-stjerner - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - TilføjelseshÃ¥ndtering (&A) - - - - Manage external workbenches, macros, and preference packs - HÃ¥bdtér eksterne arbejdsborde, makroer og præferencepakker - - - - AddonInstaller - - - Finished removing {} - Fjernelse af {} udført - - - - Failed to remove some files - Kunne ikke fjerne visse filer - - - - Addons installer - - - Finished updating the following addons - Opdatering af flg. tilføjelser udført - - - - Workbench - - - Auto-Created Macro Toolbar - Autooprettet Makroværktøjsbjælke - - - - QObject - - - Addon Manager - TilføjelseshÃ¥ndtering - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_de.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_de.qm deleted file mode 100644 index a3ff0fcb82ea4f52983e8d628b0d0d97c3479747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73197 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 jpjNccpX(PkdbGb6_H?9^7xr+tXIJ{ - - - - AddCustomRepositoryDialog - - - Custom repository - Eigenes Projektarchiv - - - - Repository URL - URL des Projektarchivs - - - - Branch - Zweig - - - - CompactView - - - - Icon - Symbol - - - - - <b>Package Name</b> - <b>Paketname</b> - - - - - Version - Version - - - - - Description - Beschreibung - - - - Update Available - Aktualisierung verfügbar - - - - UpdateAvailable - Aktualisierung verfügbar - - - - DependencyDialog - - - Dependencies - Abhängigkeiten - - - - Dependency type - Abhängigkeitstyp - - - - Name - Name - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Abhängigkeiten auflösen - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Diese Erweiterung hat die folgenden erforderlichen bzw. optionalen Abhängigkeiten. Sie müssen installiert werden, bevor dieses Addon verwendet werden kann. - -Soll der Addon-Manager sie automatisch installieren? "Ignorieren" wählen, um die Erweiterung zu installieren, ohne die Abhängigkeiten zu installieren. - - - - FreeCAD Addons - FreeCAD-Programmerweiterungen - - - - Required Python modules - Erforderliche Python-Module - - - - Optional Python modules - Optionale Python-Module - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon-Entwicklungswerkzeuge - - - - Path to Addon - Pfad zur Erweiterung - - - - - Browse... - Durchsuchen... - - - - Metadata - Metadaten - - - - Primary branch - Primärer Zweig - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Erläuterung der Eigenschaften dieser Erweiterung. Wird in der Erweiterungsverwaltung angezeigt. Der Hinweis, dass es sich um eine FreeCAD-Erweiterung handelt, ist nicht notwendig. - - - - Description - Beschreibung - - - - Discussion URL - URL der Diskussion - - - - Icon - Symbol - - - - Bugtracker URL - URL der Fehlerverfolgung - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Die Stie Semantic (1.2.3-beta) oder CalVer (2022.08.30) werden unterstützt - - - - Set to today (CalVer style) - Auf heute setzen (CalVer-Stil) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Wird in der Liste der Addons im Addon-Manager angezeigt. Sollte das Wort "FreeCAD"nicht enthalten und muss ein gültiger Verzeichnisname auf allen unterstützten Betriebssystemen sein. - - - - README URL - LIESMICH URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIPP: Da dies in FreeCAD angezeigt wird, im Addon-Manager, ist es unnötig, Platz zu verschwenden, für Aussagen wie "Dies ist ein FreeCAD-Addon..." -- Es reicht zu sagen, was es macht. - - - - Repository URL - URL des Projektarchivs - - - - Website URL - URL der Webseite - - - - Documentation URL - URL der Dokumentation - - - - Addon Name - Addon-Name - - - - Version - Version - - - - (Recommended) - (Empfohlen) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, nur Version 3.x unterstützt) - - - - Detect... - Erkennen... - - - - Addon Contents - Addon-Inhalte - - - - Dialog - - - Addon Manager - Addon-Manager - - - - Edit Tags - Schlagwörter bearbeiten - - - - Comma-separated list of tags describing this item: - Durch Kommas getrennte Liste von Tags, die dieses Element beschreiben: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HInweis: Gängige Tags einschließlich "Assembly", "FEM", "Mesh", "NURBS" usw. - - - - Add-on Manager: Warning! - Addon-Manager: Warnung! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Der Addon-Manager ermöglicht Zugriff auf eine umfangreiche Bibliothek nützlicher FreeCAD-Erweiterungen von Drittanbietern. Es gibt aber keine Garantie für deren Sicherheit oder Funktionalität. - - - - Continue - Fortsetzen - - - - Cancel - Abbrechen - - - - EditDependencyDialog - - - Edit Dependency - Abhängigkeit bearbeiten - - - - Dependency Type - Abhängigkeitstyp - - - - Dependency - Abhängigkeit - - - - Package name, if "Other..." - Paketname, wenn "Andere..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - HINWEIS: Wenn "Andere..." ausgewählt wurde, ist das Paket nicht in der Datei ALLOWED_PYTHON_PACKAGES. txt und wird nicht automatisch vom Addon-Manager installiert. Einen PR senden an <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-Addons</a>, um das Hinzufügen eines Paketes anzufragen. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Wenn dies eine optionale Abhängigkeit ist, wird der Addon-Manager anbieten, diese (wenn möglich) zu installieren, wird aber die Installation nicht blockieren, wenn der Benutzer das Paket nicht installieren möchte oder nicht installieren kann. - - - - Optional - Optional - - - - ExpandedView - - - - Icon - Symbol - - - - - <h1>Package Name</h1> - <h1>Paketname</h1> - - - - - Version - Version - - - - - (tags) - (Tags) - - - - - Description - Beschreibung - - - - - Maintainer - Betreuer - - - - Update Available - Aktualisierung verfügbar - - - - labelSort - labelSort - - - - UpdateAvailable - Aktualisierung verfügbar - - - - Form - - - Licenses - Lizenzen - - - - License - Lizenz - - - - License file - Lizenzdatei - - - - People - Personen - - - - Kind - Typ - - - - Name - Name - - - - Email - E-Mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Erweiterte Versionszuordnung - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Kommende Versionen des FreeCAD-Addon-Managers werden Entwickler dabei unterstützen, einen bestimmten Zweig oder Tag für die Verwendung mit einer bestimmten Version von FreeCAD festzulegen (z.B. durch Setzen eines bestimmten Tags für die letzte Version des Addons, das v0.19 noch unterstützt usw.) - - - - FreeCAD Version - FreeCAD-Version - - - - Best-available branch, tag, or commit - Bester verfügbarer Branch, Tag oder Commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Unterstützte FreeCAD-Versionen - - - - Minimum FreeCAD Version Supported - Unterstützte FreeCAD-Mindestversion - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximal unterstützte FreeCAD-Version - - - - Advanced version mapping... - Erweiterte Versionszuordnung... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon-Manager-Optionen - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Wenn diese Option ausgewählt ist, werden beim Starten des Addon-Managers -installierte Addons auf verfügbare Updates überprüft - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Makro-Metadaten herunterladen (ca. 10 MB) - - - - Cache update frequency - Häufigkeit der Cache-Aktualisierung - - - - Manual (no automatic updates) - Manuell (keine automatischen Aktualisierungen) - - - - Daily - Täglich - - - - Weekly - Wöchentlich - - - - Hide Addons without a license - Addons ohne Lizenz ausblenden - - - - Hide Addons with non-FSF Free/Libre license - Addons mit Nicht-FSF-Free- oder Libre-Lizenz ausblenden - - - - Hide Addons with non-OSI-approved license - Addons mit nicht-OSI-anerkannter Lizenz ausblenden - - - - Hide Addons marked Python 2 Only - Nur für Python 2 markierte Addons ausblenden - - - - Hide Addons marked Obsolete - Veraltete Addons ausblenden - - - - Hide Addons that require a newer version of FreeCAD - Addons ausblenden, die eine neuere Version von FreeCAD voraussetzen - - - - Custom repositories - Eigene Projektarchive - - - - Proxy - Proxy - - - - No proxy - Kein Proxy - - - - User system proxy - Benutzer-System-Proxy - - - - User-defined proxy: - Benutzerdefinierter Proxy: - - - - Score source URL - Bewertung Quellen-URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Die URL für die Bewertungs-Daten von Erweiterungen (siehe Dokumentation für Formatierung und Hosting Details). - - - - Path to Git executable (optional): - Pfad zu Git (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Erweiterte Wahlmöglichkeiten - - - - Activate Addon Manager options intended for developers of new Addons. - Addon-Manager-Optionen für Entwickler neuer Addons aktivieren. - - - - Addon developer mode - Addon-Entwickler-Modus - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Deinstalliert ein ausgewähltes Makro oder einen Arbeitsbereich - - - - Install - Installieren - - - - Uninstall - Deinstallieren - - - - Update - Aktualisierung - - - - Run Macro - Makro ausführen - - - - Change branch - Zweig wechseln - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Python-Abhängigkeiten verwalten - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Die folgenden Python-Pakete wurden lokal vom Addon-Manager installiert, um Addon-Abhängigkeiten zu erfüllen. Installationsort: - - - - Package name - Paketname - - - - Installed version - Installierte Version - - - - Available version - Verfügbare Version - - - - Used by - Verwendet von - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Ein in der "Verwendet von" Spalte eingetragener Stern (*) zeigt eine optionale Abhängigkeit an. Es ist zu beachten, dass Verwendet von nur direkte Importe ins Addon aufzeichnet. Andere Python-Pakete, von denen diese Pakete abhängen, könnten ebenfalls installiert worden sein. - - - - Update all available - Alle verfügbaren aktualisieren - - - - SelectFromList - - - Dialog - Dialog - - - - TextLabel - TextLabel - - - - UpdateAllDialog - - - Updating Addons - Addons aktualisieren - - - - Updating out-of-date addons... - Veraltete Addons werden aktualisiert... - - - - addContentDialog - - - Content Item - Bestandteil - - - - Content type: - Inhaltstyp: - - - - Macro - Makro - - - - Preference Pack - Voreinstellungspaket - - - - Workbench - Arbeitsbereich - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Wenn dies das einzige Element im Addon ist, können alle anderen Metadaten von der obersten Ebene übernommen werden und müssen hier nicht angegeben werden. - - - - This is the only item in the Addon - Dies ist das einzige Element im Addon - - - - Main macro file - Hauptmakrodatei - - - - The file with the macro's metadata in it - Die Datei, die die Metadaten des Makros enthält - - - - - - Browse... - Durchsuchen... - - - - Preference Pack Name - Name des Voreinstellunspakets - - - - Workbench class name - Name der Klasse des Arbeitsbereichs - - - - Class that defines "Icon" data member - Klasse, die das "Symbol" Datenelement definiert - - - - Subdirectory - Unterverzeichnis - - - - Optional, defaults to name of content item - Optional, Standardwert ist der Name des Inhaltselements - - - - Icon - Symbol - - - - Optional, defaults to inheriting from top-level Addon - Optional, erbt standardmäßig vom Top-Level Add-on - - - - Tags... - Schlagwörter... - - - - Dependencies... - Abhängigkeiten... - - - - FreeCAD Versions... - FreeCAD-Versionen... - - - - Other Metadata - Andere Metadaten - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Wird in der Liste der Addons im Addon-Manager angezeigt. Sollte das Wort "FreeCAD"nicht enthalten. - - - - Version - Version - - - - Description - Beschreibung - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Die Stie Semantic (1.2.3-beta) oder CalVer (2022.08.30) werden unterstützt - - - - Set to today (CalVer style) - Auf heute setzen (CalVer-Stil) - - - - Display Name - Angezeigename - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Alle nicht ausgefüllten Felder werden aus den Metadaten der obersten Ebene des Add-ons übernommen und sind daher technisch gesehen alle optional. Bei Add-ons mit mehreren Inhaltselementen sollte jedes Element einen eindeutigen Anzeigenamen und eine Beschreibung enthalten. - - - - add_toolbar_button_dialog - - - Add button? - Schaltfläche hinzufügen? - - - - Add a toolbar button for this macro? - Eine Symbolleistenschaltfläche für dieses Makro hinzufügen? - - - - Yes - Ja - - - - No - Nein - - - - Never - Nie - - - - change_branch - - - Change Branch - Git-Branch wechseln - - - - Change to branch: - Git-Branch wechseln: - - - - copyrightInformationDialog - - - Copyright Information - Copyright-Informationen - - - - Copyright holder: - Urheberrechtsinhaber: - - - - Copyright year: - Urheberrechtsjahr: - - - - personDialog - - - Add Person - Person Hinzufügen - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Ein Maintainer ist jemand mit aktuellem Commit-Zugriff auf dieses Projekt. Ein Autor ist jeder andere, dem man Anerkennung zuteil werden lassen möchte. - - - - Name: - Name: - - - - Email: - E-Mail: - - - - Email is required for maintainers, and optional for authors. - E-Mail ist für Betreuer erforderlich und für Autoren optional. - - - - proxy_authentication - - - Proxy login required - Proxy-Anmeldung erforderlich - - - - Proxy requires authentication - Proxy erfordert Authentifizierung - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Platzhalter für die Proxy-Adresse - - - - Realm: - Bereich: - - - - Placeholder for proxy realm - Platzhalter für Proxy-Realm - - - - Username - Benutzername - - - - Password - Kennwort - - - - selectLicenseDialog - - - Select a license - Eine Lizenz auswählen - - - - About... - Über... - - - - License name: - Lizenzname: - - - - Path to license file: - Pfad zur Lizenzdatei: - - - - (if required by license) - (falls von der Lizenz gefordert) - - - - Browse... - Durchsuchen... - - - - Create... - Erstellen... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Symbolleiste auswählen - - - - Select a toolbar to add this macro to: - Eine Symbolleiste wählen, um dieses Makro hinzuzufügen: - - - - Ask every time - Jedes Mal nachfragen - - - - toolbar_button - - - - Add button? - Schaltfläche hinzufügen? - - - - Add a toolbar button for this macro? - Eine Symbolleistenschaltfläche für dieses Makro hinzufügen? - - - - Yes - Ja - - - - No - Nein - - - - Never - Nie - - - - AddonsInstaller - - - Starting up... - Wird gestartet... - - - - Worker process {} is taking a long time to stop... - Arbeitsprozess {} braucht lange, um beendet zu werden... - - - - Previous cache process was interrupted, restarting... - - Vorheriger Cache-Prozess wurde unterbrochen, wird neu gestartet... - - - - - Custom repo list changed, forcing recache... - - Benutzerdefinierte Repo-Liste geändert, erzwinge den Recache... - - - - - Addon manager - Addon-Manager - - - - You must restart FreeCAD for changes to take effect. - FreeCAD muss neu gestartet werden, damit die Änderungen wirksam werden. - - - - Restart now - Jetzt neu starten - - - - Restart later - Später neu starten - - - - - Refresh local cache - Lokalen Cache aktualisieren - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Cache wird aktualisiert... - - - - - Checking for updates... - Sucht nach Updates... - - - - Temporary installation of macro failed. - Temporäre Installation des Makros fehlgeschlagen. - - - - - Close - Schließen - - - - Update all addons - Alle Erweiterungen aktualisieren - - - - Check for updates - Auf Aktualisierungen prüfen - - - - Python dependencies... - Python-Abhängigkeiten... - - - - Developer tools... - Entwicklerwerkzeuge... - - - - Apply %n available update(s) - %n verfügbare Aktualisierung(en) anwenden - - - - No updates available - Keine Aktualisierungen verfügbar - - - - - - Cannot launch a new installer until the previous one has finished. - Ein neuer Installer kann erst nach Beendigung des Vorherigen gestartet werden. - - - - - - - Maintainer - Betreuer - - - - - - - Author - Autor - - - - New Python Version Detected - Neue Python-Version erkannt - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Dies scheint das erste Mal zu sein, dass diese Version von Python mit dem Addon-Manager verwendet wurde. Sollen die gleichen automatisch installierten Abhängigkeiten für die neue Version installiert werden? - - - - Processing, please wait... - In Bearbeitung, bitte warten... - - - - - Update - Aktualisierung - - - - Updating... - Wird aktualisiert... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - QtNetwork konnte nicht importiert werden - es scheint nicht auf diesem System installiert zu sein. Dein Anbieter könnte ein Paket für diese Abhängigkeit haben (oft "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Konnte den angegebenen Proxy-Port '{}' nicht in eine Portnummer umwandeln - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameterfehler: sich gegenseitig ausschließende Proxy-Optionen eingestellt. Wird auf Standard zurückgesetzt. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameterfehler: Benutzerdefinierter Proxy ausgewählt, aber kein Proxy angegeben. Wird auf Standard zurückgesetzt. - - - - Addon Manager: Unexpected {} response from server - Addon-Manager: Unerwartete {} Antwort vom Server - - - - Error with encrypted connection - Fehler mit verschlüsselter Verbindung - - - - - - Confirm remove - Entfernen bestätigen - - - - Are you sure you want to uninstall {}? - Soll {} wirklich deinstalliert werden? - - - - - - Removing Addon - Addon wird entfernt - - - - Removing {} - {} wird entfernt - - - - - Uninstall complete - Deinstallation abgeschlossen - - - - - Uninstall failed - Deinstallation fehlgeschlagen - - - - Version {version} installed on {date} - Version {version} installiert am {date} - - - - Version {version} installed - Version {version} installiert - - - - Installed on {date} - Installiert am {date} - - - - - - - Installed - Installiert - - - - Currently on branch {}, name changed to {} - Derzeit auf Branch {}, Name geändert zu {} - - - - Git tag '{}' checked out, no updates possible - Git Tag '{}' ausgecheckt, keine Aktualisierungen möglich - - - - Update check in progress - Prüfung der Aktualisierung läuft - - - - Installation location - Speicherort für die Installation - - - - Repository URL - URL des Projektarchivs - - - - Changed to branch '{}' -- please restart to use Addon. - Änderung zu Branch '{}' -- bitte neu starten, um Erweiterung zu verwenden. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Diese Erweiterung wurde aktualisiert. FreeCAD neustarten, um Änderungen zu sehen. - - - - Disabled - Deaktiviert - - - - Currently on branch {}, update available to version {} - Derzeit auf Branch {}, Update verfügbar für Version {} - - - - Update available to version {} - Update verfügbar auf Version {} - - - - This is the latest version available - Dies ist die neueste verfügbare Version - - - - WARNING: This addon is obsolete - WARNUNG: Dieses Addon ist veraltet - - - - WARNING: This addon is Python 2 only - WARNUNG: Diese Erweiterung ist nur für Python 2 - - - - WARNING: This addon requires FreeCAD {} - WARNUNG: Diese Erweiterung benötigt FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNUNG: Dieses Add-on ist derzeit installiert, aber deaktiviert. Die Schaltfläche "Aktivieren" verwenden, um es wieder zu aktivieren. - - - - This Addon will be enabled next time you restart FreeCAD. - Dieses Addon wird beim nächsten Neustart von FreeCAD aktiviert. - - - - This Addon will be disabled next time you restart FreeCAD. - Dieses Addon wird beim nächsten Neustart von FreeCAD deaktiviert. - - - - - - Success - Erfolgreich - - - - Install - Installieren - - - - Uninstall - Deinstallieren - - - - Enable - Aktivieren - - - - Disable - Deaktivieren - - - - - Check for update - Auf Update prüfen - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Ausführen - - - - Change branch... - Git-Branch wechseln... - - - - Return to package list - Zurück zur Paketliste - - - - Checking connection - Verbindung wird überprüft - - - - Checking for connection to GitHub... - Verbindung zu GitHub wird überprüft... - - - - Connection failed - Verbindung fehlgeschlagen - - - - Missing dependency - Fehlende Abhängigkeit - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - QtNetwork konnte nicht importiert werden - Einzelheiten finden sich im Ausgabefenster. Der Addon-Manager ist nicht verfügbar. - - - - Other... - For providing a license other than one listed - Andere... - - - - Select the corresponding license file in your Addon - Die entsprechende Lizenzdatei des Addon auswählen - - - - Location for new license file - Speicherort für neue Lizenzdatei - - - - Received {} response code from server - {} Antwortcode vom Server erhalten - - - - Failed to install macro {} - Installieren des Makros {} fehlgeschlagen - - - - Failed to create installation manifest file: - - Fehler beim Erstellen der Installations-Manifest-Datei: - - - - - Unrecognized content kind '{}' - Unbekannter Inhaltstyp '{}' - - - - Unable to locate icon at {} - Symbol kann nicht gefunden werden bei {} - - - - Select an icon file for this content item - Eine Symboldatei für dieses Inhaltselement auswählen - - - - - - {} is not a subdirectory of {} - {} ist kein Unterverzeichnis von {} - - - - Select the subdirectory for this content item - Das Unterverzeichnis für dieses Inhaltselement auswählen - - - - Automatic - Automatisch - - - - - Workbench - Arbeitsbereich - - - - Addon - Addon - - - - Python - Python - - - - Yes - Ja - - - - Internal Workbench - Interner Arbeitsbereich - - - - External Addon - Externer Arbeitsbereich - - - - Python Package - Python-Paket - - - - - Other... - Andere... - - - - Too many to list - Zu viele zum Auflisten - - - - - - - - - Missing Requirement - Fehlende Voraussetzung - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Add-on '{}' benötigt '{}', was in FreeCAD nicht verfügbar ist. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' benötigt die folgenden Arbeitsbereiche, welche nicht in FreeCAD verfügbar sind: - - - - Press OK to install anyway. - OK drücken, um trotzdem zu installieren. - - - - - Incompatible Python version - Inkompatible Python-Version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Dieses Addon benötigt Python-Pakete, die nicht installiert sind und nicht automatisch installiert werden können. Um diesen Arbeitsbereich nutzen zu können, müssen die folgenden Python-Pakete manuell installiert werden: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Dieses Addon (oder eine seiner Abhängigkeiten) erfordert Python {}.{}, und auf dem System läuft {}.{}. Installation abgebrochen. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optionale Abhängigkeit von {} ignoriert, weil sie nicht in der Erlaubnisliste ist - - - - - Installing dependencies - Abhängigkeiten werden installiert - - - - - Cannot execute Python - Python kann nicht ausgeführt werden - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Konnte die ausführbare Python-Datei nicht automatisch lokalisieren, oder der Pfad ist falsch gesetzt. Bitte den Pfad zu Python in den Einstellungen des Addon-Managers überprüfen. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Abhängigkeiten konnten nicht installiert werden. Trotzdem mit der Installation von {} fortfahren? - - - - - Cannot execute pip - Pip kann nicht ausgeführt werden - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Die Ausführung von pip ist fehlgeschlagen, da sie möglicherweise nicht in der Python-Installation enthalten ist. Bitte sicherstellen, dass das System pip installiert hat und erneut versuchen. Der fehlgeschlagene Befehl war: - - - - - Continue with installation of {} anyway? - Trotzdem mit der Installation von {} fortfahren? - - - - - Package installation failed - Paketinstallation fehlgeschlagen - - - - See Report View for detailed failure log. - Ein detailliertes Fehlerprotokoll findet sich im Ausgabefenster. - - - - Installing Addon - Addon wird installiert - - - - Installing FreeCAD Addon '{}' - FreeCAD-Addon '{}' wird installiert - - - - Cancelling - Abbrechen - - - - Cancelling installation of '{}' - Installation von '{}' abbrechen - - - - {} was installed successfully - {} wurde erfolgreich installiert - - - - - Installation Failed - Installation fehlgeschlagen - - - - Failed to install {} - Installation von {} fehlgeschlagen - - - - - Create new toolbar - Neue Symbolleiste erstellen - - - - - A macro installed with the FreeCAD Addon Manager - Ein Makro, das mit dem FreeCAD Addon-Manager installiert wurde - - - - - Run - Indicates a macro that can be 'run' - Ausführen - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Daten von GitHub konnten nicht gelesen werden: Bitte die Internetverbindung und Proxy-Einstellungen überprüfen und neu versuchen. - - - - XML failure while reading metadata from file {} - XML-Fehler beim Lesen von Metadaten aus der Datei {} - - - - Invalid metadata in file {} - Ungültige Metadaten in Datei {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNUNG: Der in der package.xml Metadaten angegebene Pfad stimmt nicht mit der aktuell ausgecheckten Version überein. - - - - Name - Name - - - - Class - Klasse - - - - Description - Beschreibung - - - - Subdirectory - Unterverzeichnis - - - - Files - Dateien - - - - Select the folder containing your Addon - Den Ordner auswählen, der die Erweiterung enthält - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Kein Vermin, Abbruch der Operation. - - - - Scanning Addon for Python version compatibility - Untersuchen des Addons auf Kompatibilität mit Python-Versionen - - - - Minimum Python Version Detected - Ermittelte minimale Python-Version - - - - Vermin auto-detected a required version of Python 3.{} - Vermin hat automatisch eine erforderliche Version von Python 3.{} erkannt - - - - Install Vermin? - Vermin installieren? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Die automatische Erkennung der erforderlichen Python-Version für dieses Add-on erfordert Vermin (https://pypi.org/project/vermin/). Soll dies Installiert werden? - - - - Attempting to install Vermin from PyPi - Installationsversuch Vermin von PyPi - - - - - Installation failed - Installation fehlgeschlagen - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Vermin konnte nicht installiert werden -- Einzelheiten finden sich im Ausgabefenster. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Fehler beim Importieren von Vermin nach der Installation -- Addon kann nicht gescannt werden. - - - - Select an icon file for this package - Eine Symboldatei für dieses Paket auswählen - - - - Filter is valid - Filter ist gültig - - - - Filter regular expression is invalid - Der Filter regulärer Ausdruck ist ungültig - - - - Search... - Suche... - - - - Click for details about package {} - Klicken für Details zum Paket {} - - - - Click for details about workbench {} - Klicken für Details zum Arbeitsbereich {} - - - - Click for details about macro {} - Klicken für Details zum Makro {} - - - - Maintainers: - Betreuer: - - - - Tags - Schlagwörter - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - Kein ★, oder nicht auf GitHub - - - - Created - Erstellt - - - - Updated - Aktualisiert - - - - Score: - Bewertung: - - - - - Up-to-date - Auf dem neuesten Stand - - - - - - - - Update available - Aktualisierung verfügbar - - - - - Pending restart - Ausstehender Neustart - - - - - DISABLED - DEAKTIVIERT - - - - Installed version - Installierte Version - - - - Unknown version - Unbekannte Version - - - - Installed on - Installiert am - - - - Available version - Verfügbare Version - - - - Filter by... - Filtern nach... - - - - Addon Type - Erweiterungs-Typ - - - - - Any - Alle - - - - Macro - Makro - - - - Preference Pack - Voreinstellungspaket - - - - Installation Status - Installationsstatus - - - - Not installed - Nicht installiert - - - - Filter - Filter - - - - DANGER: Developer feature - VORSICHT: Entwicklerfunktion - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - VORSICHT: Das Wechseln von Branches ist für Entwickler und Beta-Tester gedacht und kann zu Störungen, nicht rückwärtskompatiblen Dokumenten, Instabilität, Abstürze und/oder den vorzeitigen Untergang des Universums erzeugen. Wirklich fortfahren? - - - - There are local changes - Es gibt lokale Änderungen - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNUNG: Dieses Repo hat nicht gespeicherte lokale Änderungen. Wirklich den Branch wechseln (die Änderungen werden mitgenommen)? - - - - Local - Table header for local git ref name - Lokal - - - - Remote tracking - Table header for git remote tracking branch name - Entfernte Nachverfolgung (Remote) - - - - Last Updated - Table header for git update date - Zuletzt aktualisiert - - - - Installation of Python package {} failed - Installation des Python-Pakets {} fehlgeschlagen - - - - Installation of optional package failed - Installation des optionalen Pakets fehlgeschlagen - - - - Installing required dependency {} - Installieren der benötigten Abhängigkeit {} - - - - Installation of Addon {} failed - Installation des Addons {} fehlgeschlagen - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Datei {} für Add-on '{}' konnte nicht dekodiert werden - - - - Any dependency information in this file will be ignored - Alle Abhängigkeitsinformationen in dieser Datei werden ignoriert - - - - Unable to open macro wiki page at {} - Makro-Wiki-Seite unter {} kann nicht geöffnet werden - - - - Unable to fetch the code of this macro. - Der Code dieses Makros konnte nicht abgerufen werden. - - - - Unable to retrieve a description from the wiki for macro {} - Konnte keine Beschreibung aus dem Wiki für Makro {} holen - - - - Unable to open macro code URL {} - Makro-Code kann nicht geöffnet werden URL {} - - - - Unable to fetch macro-specified file {} from {} - Makrospezifizierte Datei {} von {} konnte nicht abgerufen werden - - - - Could not locate macro-specified file {} (expected at {}) - Datei {} konnte nicht gefunden werden (erwartet um {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unbekannter interner Arbeitsbereich '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Add-on Entwickler Warnung: Die in der Datei package.xml für das Add-on {} ({}) angegebene Repository-URL stimmt nicht mit der URL überein, von der es abgerufen wurde ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Add-on Entwickler Warnung: Der in der package.xml-Datei für das Add-on {} ({}) angegebene Repository-Branch stimmt nicht mit dem Branch überein, aus dem es geholt wurde ({}) - - - - - Got an error when trying to import {} - Fehler beim Importieren von {} - - - - An unknown error occurred - Ein unbekannter Fehler ist aufgetreten - - - - Could not find addon {} to remove it. - Addon {} konnte nicht gefunden werden, um es zu entfernen. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Ausführung des Addon's Uninstall.py Skripts fehlgeschlagen. Fortfahren mit der Deinstallation... - - - - Removed extra installed file {} - Zusätzlich installierte Datei {} entfernt - - - - Error while trying to remove extra installed file {} - Fehler beim Versuch, die zusätzlich installierte Datei {} zu entfernen - - - - Error while trying to remove macro file {}: - Fehler beim Entfernen der Makrodatei {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Verbindung zu GitHub fehlgeschlagen. Bitte die Verbindungs- und Proxy-Einstellungen überprüfen. - - - - WARNING: Duplicate addon {} ignored - WARNUNG: Duplizieren des Addons {} wird ignoriert - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Fehler beim Aktualisieren von Makros von GitHub, sauberer Checkout-Versuch wird ausgeführt... - - - - Attempting to do a clean checkout... - Sauberer Checkout-Versuch... - - - - Clean checkout succeeded - Sauberer Checkout war erfolgreich - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Aktualisierung der GitHub Makros fehlgeschlagen -- Löschen des Caches des Addon-Managers versuchen. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Fehler beim Verbinden mit dem Wiki, FreeCAD kann die Wiki-Makroliste zu diesem Zeitpunkt nicht abrufen - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Fehler beim Lesen der Metadaten von {name} - - - - Failed to fetch code for macro '{name}' - Fehler beim Abrufen des Codes für Makro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon-Manager: Ein Arbeitsprozess konnte während des Abrufs von {name} nicht abgeschlossen werden - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Von {num_macros} Makros wurden {num_failed} während der Verarbeitung nicht rechtzeitig beendet - - - - Addon Manager: a worker process failed to halt ({name}) - Addon-Manager: Ein Arbeitsprozess ({name}) konnte nicht angehalten werden - - - - Timeout while fetching metadata for macro {} - Timeout beim Abrufen von Metadaten für Makro {} - - - - Failed to kill process for macro {}! - - Fehler beim Beenden des Prozesses für Makro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Fehler beim Abrufen der Erweiterungs-Statistiken von {} -- nur alphabetisch sortieren wird genau sein - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Fehler beim Abrufen der Erweiterungs-Bewertungen von '{}' -- Sortierung nach Bewertung wird fehlschlagen - - - - - Repository URL - Preferences header for custom repositories - URL des Projektarchivs - - - - Branch name - Preferences header for custom repositories - Zweigname - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Sichern des ursprünglichen Ordners und erneutes Klonen - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Umbenennen des Git Branches mit der folgenden Nachricht fehlgeschlagen: - - - - Installing - Wird installiert - - - - Succeeded - Erfolgreich - - - - Failed - Fehlgeschlagen - - - - Update was cancelled - Aktualisierung wurde abgebrochen - - - - some addons may have been updated - Einige Addons wurden möglicherweise aktualisiert - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Laden der Info für {} aus dem FreeCAD Makro Rezeptenwiki... - - - - Loading page for {} from {}... - Lade Seite für {} von {}... - - - - Failed to download data from {} -- received response code {}. - Fehler beim Herunterladen der Daten von {} -- Empfangener Antwortcode {}. - - - - Composite view - Zusammengesetzte Ansicht - - - - Expanded view - Erweiterte Ansicht - - - - Compact view - Kompakte Ansicht - - - - Alphabetical - Sort order - Alphabetisch - - - - Last Updated - Sort order - Zuletzt aktualisiert - - - - Date Created - Sort order - Erstellungsdatum - - - - GitHub Stars - Sort order - GitHub Sterne - - - - Score - Sort order - Bewertung - - - - Std_AddonMgr - - - &Addon manager - &Addon-Manager - - - - Manage external workbenches, macros, and preference packs - Verwaltet externe Arbeitsbereiche, Makros und Voreinstellungspakete - - - - AddonInstaller - - - Finished removing {} - Entfernen von {} abgeschlossen - - - - Failed to remove some files - Einige Dateien konnten nicht entfernt werden - - - - Addons installer - - - Finished updating the following addons - Aktualisierung der folgenden Addons fertiggestellt - - - - Workbench - - - Auto-Created Macro Toolbar - Automatisch erstellte Makro-Symbolleiste - - - - QObject - - - Addon Manager - Addon-Manager - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_el.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_el.qm deleted file mode 100644 index 3d4cf3d6c95d74b8b189c8a9c0beed6a34c36270..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74781 zcmeIb37A|}nKynqy`;O-=?)MehOG#YbTHisi!3pqSs{>wn1odasP3*#7pbmls;Wtv z2s*BaD@$Y%1w}-eEQWw&0TKvdGoa%z+2XUtnq) z{*S&Mnm6X$OO0v!l`)q-ZcK5eF<0z0=CixywPx(G`g-UcrtXiI8}s=;>+9B6_4U~| z>+7F7OnqvBG0*+GsXzBE#-wl8*L%OBug~9S>hJ%NF+=y7#t$ts=BN*vrdMAxrel(s z{N#6yS$?=V>bOp0`p1}K7h@goe!uBhdzmr+Ho=@cW3@5&eAT>l*D6!f`WAD}-(elK z8_ap__ZpM>ojLEc4aOYzZFAmx&ot)SSC}QI{}0x&$1EL#eJo3xmB(FR%um;wm6yKT zn9IL!R$lu_?CBPLeeGPc>isvGnwAflRr{X=T)wKWhn{UN{`4P=`N7%d(l33`n9|ke zvM=NLRgL=k)3=(-{s(`5>=}Li>ED}l-=L{Ec&*92y3&|kJ*Kq&ZN^MK-CWx<*_gVY zn)UD5Y|OVlWp4X)oiT6urupihnvMCz<7UTaUc@^0o1N2+GiJr7&13c0|I`k%r@h{o z@0@JDd+WQ5*)+|(+=llztu;Scv>)rb*}VGHHe()m%>403_XI?Qi zwZEl?BgZqs!y?e*h{$R+Mmic3jy$JI(EE}`v1DlNb)WKuU-}4Ea|G$h` z{-2MTn(_CKx#+=GWB%~BW7fX~^IrR3V{Sfu3eG<_=JxIQ{ltz%x?Uoz&t^pFnlk2l`=2-F%86tC z^|d>VS(6&`hkg5udA@DTAASS;Xq-FdkJn!cI4mFYm$v{e-)gC?JK}Jh(=)Y4U;U&p z-HU5yzAtOcKVDUP)~~S-^Y+@V_q=4x*WX{;w{Vp)AAfi4RX0pDX2Oix>%VcmF>9yS z?!4d@WB%@_+MS;ReBaho`|KroW3Ky1?Kj@{IB4oKwZFaVm&UByPx9;#~ z-)BtooVw$`fpvfJwYs@KeGt)?E3>huRFi|31cq#qrSd+ZQYWOyll)}|5>;4 z>kEzfm-TgpzuXGA&#U{`mM&u^zPax9#g7`Z^SHX(KX5zNYwGUoYXyCsRQJGQ;Kyax z*KK+K#m4;lD|I_3+-YjYe!gyJ=O2tY@f&q}-}6V{{mQzhhE6c%w0GA%JLVx{=G4`F zb2i|x?9+8W`o_nNc}IWUua5c_@aY@+`s-DA{ZC`Yf2i(P#~f_Te{|N@bbZd4!l&zx ze+%~cvvKt&+=_EJ~qYP`uE<6asKAI`uA?R z+?d>Z>p!p!@c7l*`j5W98Q)u9fAcY)Fy@c{P=8C;T4UyZvwp*OzG%!XOX|PyJ?!U- zZ|Uo^UG-l&3Fr4W$JK9o`aDx}&^zn5O#h=Xog3@-uKor1$l>)*fB8ORKG~+P|NhPT z@7xc*mRVf?FHZu0{_WQKA1?jAF?SwW|GN{hjtie@FfVT~HKx6x=Ijpw5AJNJ`R+dg zKC>I@2Y+MC-*+@Lei?M|>FXK}NrUf9%r;DX9QgOoS2qYgtolO3n?Hp07JD0Jex(e2 zp3-pIgMj;rR~pX$`F|Mmm-P)x-;RA>|Cxs6zkSY_AJ#X#v*u9H>CA@oyko$R7B>vN z^A+&J7aKmG$8nBx8b0&xQ-ELZX}Isle*--IR>PM!-($>80}UJh@yEt| z?!|^pH{v`tjBD6;&t_xFr!{=@6IkyBhc$e=SP%Gqt>I_qeGdEixxW5)jl9-Oc&6cZ ztCj*kZ)x~T+pWf&Jv6py(^JOG*fn<2c&t1B+p)*C{tWxsGj`EHt1&m8GWPNheggbt z&e-l$E%^M)V+U4k1|I%q?6p6c5BSxNUB9Qvn4f%X?2Wa+*D-ZtKl#yl;G;hsd(-*T zz*jCEdwX}*)J&)u`_&8HWXvJ&AN$qxk;Xjzaee*!r^Y_>Pn$sZ&yU^T`AcKI+C27! zTAa&+Pmg`+(c6Gee;WJk!#j=Xnm_j6ullnwPd+^MXNzAnrtjvlzuEZ;_{ram{q4!K zO-=m*+&2UJyraMI#of=~ob!$UGU*)P>x_A5uDsTm zo0=y5@%P4j=4bL+Q}=w+yct-}yZW1!uKu$zr@o}GpMOGMH{PMI&-_APfB$OJWtZ*4 z`5o7E1?AYm|J}6uu)W5-w5DnGx2}cU`EXNi@Oqr*bxno*_0UJAHC?k6{NnuiP49i} zY-5gWYP#XWM;kM5L(|75z6bJnrM^ylwdqsaK4HwtJDP53#^)ctuj!V@v9EW0r|C2Q ziuDhj&~(?5j~nyOe{1^E4WGh!Y;M|l>MO?F_U5KNr{lTlE1I6!J{ElbqfO8JpBIfe z=8UH2=KmIaV|&xr|GdnYZywb2on07rX>HTXQ`(F<%d9+y6p$!8V&;gy7znI8gIG-c>nHk zO+y*r^+(1X^#btr?$zU_uK5Yp{q=G0?D{42tiKueH!lJ%pM7;)_mkj5hbcYqac;M_)c*kR{zGTW#FI`3|M^(UVc!It z7Jjzn$bWqa^mTd5F%MwBzhBgH+_{+l+)XW=-9yIgzO!ZK9VbJdIj3dT=T}3Y>1%o0 zL0IoGx3nz2tp)u1M=i_Rv5ws}Ez3WL^?&mGmX!@y$CBQbi%;n{=A-*tE?tH5e*Vms zcfR*6;4fcqS-t7~#teMCCI4kSzhzs?)m_-TTR!=o4;a(a z(sIW}>?eOv%V&Bq&#!*ha?gWHabCHW`#0SL{&ix@qvW%NS6lY}1oZvIDJ{?4(`w8Y zzOS#_pVimrmdR^P-OVlgpMTMqAFpfqQPWZ2=dX=F=q#Mmx|ij(X3VbfZ~E3pjCuGK zd94}q=JCh8itpXfGk)r4ftNQuG=A#$CPQu>F@9S2Z-DO;$DefZK4Wfwe*By*V}W;n z7=PABCmHkahmSvZP2QOQd};hUj$Qz};ga#`C$X<%r;i_4{AKXu*axxB8};?s z-;clPkQ0r0&&KiJUG-zo%@4-^ItP6GrysRW+=KleU1~jaBj&&6vex4|Fz+cBv`&5b zDPunPbZh&60iO3B+>-};XGuP|oT ziLEQ213x|D{?^PcjQ{G7TXP4^hko+W*1_^bjN8<@whj73-%^{v0Z zx)b>Petms)QrnyE$Nn!~**5imUV%MwY+L(5?=$AVy4q%Z1bC79RNE;#e+YT?Qrj7O zKLI@aT-)qJnvD7WK-*bw|2gpgfwp;PKV-~zZ)scFKO21TzP2mBy%6}ez3s~X#_JbO z)z@b~-`4#*;K{eQwh_+e-+tCs-imeH_rtbp8vkg_q6KY#d)&`JhyT^~@k>@hpT42( z<|*J$zy4v{U5%H3&v&%l^{yWQU)Qxg@`oOr_r$ixKZ^6eWH(=M~fW?mnQ1 zdDGmUp812Na-n}kW}r~YmJ7w91=)12u)2oN&#Jwr_6a<@w{|ODAC=!8t=&}nSnY0; z!h3u0&i2}eYoDs!jL&z}?)GyWq@$*ae%Mh=ccQt_tT0P3^!>Fj%EbHd`%QM5&9yr* z)jlldkFWxM1Ijw+kA-_0ZDyMU~ zOi=)PYVF-PnB5q87v_5c<8Q|+_J>&>k(r*xY+LZj!(5F?nf2y6KjXwj*?hLthdE`! zY<_iW{dGxGT{*&3592f+!B#h6vgdR%fC3woW$dioFALp=1?qdmi2eAUo_iP&Q~k0A z2YS+FF00%JKooMh!dm{7CLjbR69guuR5k*Yn``d^w0RznV)r{S(QfSjF)U{{7O@%c z6XA#xo8%mJ;J1fyVtRU8v8bo;92d4l#vnBDETFf@6io*I=9{@@0p7ip^XM3uWrsY; z@g2Hv#|#1l5A#`bQ~l}gV!}B-+l-$5 z1eqlO;Z{FKy?j0K!HuBj&N0`wsP4FRwhzk%lQ9s#Qq&%@XPkUxQMKP~U^aBw6QAnx>=TC7l+w*I9bDqkq4($|2D(p|X>AeH(}g@K_|p*Lm0+nETMA0Iei zxFOL0li1uIY=zs|3HryG%R3tdtK2up1-9WEd$IMcc!t2-Ex_`?w4fUWIOUrM4$#>i zpjX5JG)ib|3&k~E8SwZ_$w4_?%#04qvy;GFv&@pm!@vtl6vZQ9mjFlwRtlLaIVrY0 zDn$Jhp5^8@o7s3q@Yyqci%Fj0Q?8IX0#_@DemCCLag@{pa5@G}su(b7({0w^=W39C zr&(wEO%Ahe!?R>EdoW5shJ1ollrrt|Ivw9|^g*_=L+0FA`!!Gt=>)<7Ke1*!;l!3> zPg{kWc5=Vjlc*b}A~{Ql(6p#4(WWUIPx( zxvoDaQU)BhsJs;NN(uf7s}bSjcEIFeZxN(%67qlbxP@W*9bo-#od14r$~k zZq|uc4Gm-x$C_~RU%D$(&UUAB zi3@xh8>9|IeTPcl#tLrxG~U_8vj8Y~E{|BHG1+j4)8Cy9B|;FRP;j1OvZid#HG`&0 zw5kXd$Sf4nG(gEbsM#wGs!jNeSc%qNOHK8=K4)$|l_?e>6${D9;Fd&n}MJKBT8r(oVqjUTVN&xdOt$B{gN2?B!|WGWEYhj%Scm%l?=84gjQ zL|E*`vtq9KC7zBYrg}01nS2lQ*CD7oP;Q{aWD9w!KIJ}G3$(0ZeC2YfE*J}|^93Am z;8F_r*3^k>&(&Qpd*wLr2Y9iY=PM^6OnLwqNLzw&r5Z#pa`r_54Ox{LD7624IeZ4dZo2MynIbl>b(eCphCInzI&K7#^i zFr8mbdnMli8ihqo!yDS~;DBrbA|7uyC$4{i)mrxgYGJNH?gI3~$BBO4}eu%p0JkSG?m*@lYn0f>v8h_B0#E$6Cm`Jttd$e_chDS5dLTV zDyK$Q>5loLOtBwyBkXSZ(DG~|%qG^}3+}%S|J1bK1UQ9UhI0qYeT77yM$K$th+8oN z2;WL=Rr($S#y zAyY7Fg;|GL+)QFFnh0c}Q}h8#%fQkS)YzH$HvrfU0PdZbsR%shJH+U#a3bCK=1g-< z=xk=1>G);}v`yu9BiN!Eh|bImn;&lb#e**%Emm z+#$<{a1=OFh&N$}swa5Yiaqi6zH)h>G<)XEfuVtHXQ8-yCRD10o(^Yq?!bms~*^%Hm6 zYvzHWmVk`io^7UtrS{-`vgnlQ#cx@7HZrCMf33yuBoeagKKpqApXPwT{7hLn&4?2I zsc$53E}b$jUCMToy{gItLqRPF@9YfRx&1IO;D<gloo@3ZcK2%ccn)f`K01626hfZ)Mp&rInL74j6fS zYc1Ya3MOF5O#*Izp$12s2r3PBcV{v^nV!z(rEu-{G?SCghV*PM7vyC*lt#!S*q-Hd zQDrRt{KPFhD%C&bZge;74c0n{)64B&Hc(&>6>I)q(|0dTed9-Yu zpYHA>TB;J9I9h7hXzCd2mpL$|A8~>k5$3lHnmA@Fn8;4>c^hQ#BQ(!PEGm=BRU?9v zqtAkWBuY=`@b=>$6O8XToobWdr1U~3E|`-(1n#2V45#zbr>E+f6;5HH{;^G)ma=#JI6)5AEUonU8_#Mq!f znr<9Q<;SpbWr%8%QB&9mCag9(0*uwp1>a)K2AY?QL=%7^3bN!KR?p@qoKZ)AMA)y_ z3qlk+&+a>y9)yP*$`}dF3Nd&-2J_`?P6%+In7Jlf7%Zg<`An*heoq@VOD0EZgS+r= zD`qE5?!@ovsoYng6;7D1I;y(Ysu_#7hQ{0^P_q6@hpXU59r(xD)ImnQ|6$Qts5e!f zh|??7G9XNORuZZaVYI{gOVoZ4JG;_>5rXDvx(^9oT34ZjYC1Yna2Lg}Hc>Z{A=p`a zgPiI%oVMbGTkmkoYDY-J1UzAPi&mqCR3a|F-Wd+6oIxUyu}-h!q0H?9!ft~y=fFtR z+zSTw7`TE2Wj!GtA_J4Jb{Fz_YHx*n;_4SA!Y48~CJP4`!hVtp>%>n^g)mqEH9Pfh zRKv|v6IT;^S`{>Kcw}xpwo2%y@B%KM_e+Hj0s&xSNg2M|5Ho2}*YIIupNZZTlGi*;D`mp6J%uldhzz_}*dElavA4~~AdssXmvijqbR_`OX)z&{j5S+%0<@^5pfaZl#vYOZ~Mm~iK(TC=~ zX7dDM_dy^PLJxkxmiY)9q`S+hYqFWOi2ywsKF~ue>!;p&(`C)+-Dzo>BTKO=z22ap=`W(M^-t{tQz8V~877PG(@;l1QGG#Km6ckN38+^h-dSD=vhG(lF&V8F6)&mt@bAn1kB{+&Z zQ*vQY`aHr!*XYgr{C6i%tpbJk(2}C z*{$HI!_wa5=_moK-%R8A%5ekt-R_X_aAEaxEoCy2!h-X@2;xJ|#HtmY(PTMTZ9e}i zk+4ls2%Cb2QDL<%RMyh%M~#+nDaUe3g?ch^ zN?!UMJinOXqG$`33x!-)I?-8gjvO{`C`-wY*r+4+q!LBmRA}>bx=~wq+I$)up+{V5 zDLCh{bjbM;50MdRC#9JPn#yHMUe`@jhrb_A*9@%Ub0XFB3-l-WqDi#O=dv<=VD+nqR%c5Bv#LmrTCibD4;p2FH z8aTxm6Zs9-^djKN!`({l&otY#0R27_$|Uk65}z7iWnzGcCydCMDoqJ~78nJ;a)_`J zMuEEimH8k$6p0ksJk%k?HmqQ_>8CLHp>rc=D4i-Js)4}c40(r27Q!5ZNS{JPxvN-M zlgWdFAx7VYXxG|wv8M$86RgE@mRa0Ah3>(A@H{*%#zm{a7vTZXN%<~?A`Lp8IdguD44A@O&ohW zMo|xab?eKS8Q~Z*)k{^`n3O|(2iyRtp}8wm{GzsL9O|f>bF?<7#^Y(>1<1B^flJ%T z0=>Gu3CAQIr^k1u-msZ^Fba=@cJPOzt$Er4AJ2$WlPvi!D(fXZS)>d>u8b z--=Jf2K`kh_uE{$P(toDRZ3!&(@H_wV<#%gR6Qf}E1+o|* zBtX=p7|Dq~e&M!QzLC3Lk|{afgO7(o5hQ9``?MKOn=eqT`-OaDx0bRI@( z(3%XOcI!hzacY|fzR$`kFmf5q^KzO!F)Kcj`viQk+p!CpPQ+#v{4}L73*J-J$zwT` zvl!1Ap5y5-QIY;Jr-V6WLM6uV9q3$yoVBvUIV2(P+UJA9;Z5!S1aft&RK|NV@K&IHggLj8 zi>S$lP}DglII+%}?5R5!;x?R=<}!zwghn^9=5wWlW$0(Bb}(DZxsoL2?a}r402s`f z6HgoLmjX4B!4jz#(e5Nrk|3SxT}-(K`L5q@QSYkm(!CgC7;oq zF)-nZ==7%>nmVcrl&Fa3&bH%yGACy~>nGbmPRtwTev|hWE>s4I;ky*CI|Mppb$%3o z>Ti$00Cpht8Wh-jr>kyOLJE?$0tg`nzz9Qru)nKH{Z~)S?jIWNj+Gr%Dglh?G5r&) z!!kgp=!C2?d=jVw9ie@wqc#$tLy=Fm7q+&jGP9E%Mc2kGnv#)Tljj8R%wr9i7P34m zsRh{DzCd&v4Iz5d2j9XGke`L54T!n)x^4im`&Jf zH(4&zYv>44Ca!iZHwg@}QBTd53bw5NetsuZV92rL`$1gstkBY}DU(8@g0!Z`gOMN> z1tyt+!-2`UwwloHF_DmJu8G-Dg}xL%2k1pe;|nYke`17xoHe3mD)k@QAr=%)cHrF@ zVn1#GD2vVD(}?m zwq2yF&PZ1UqmEqFZTPR4tSmaL&^rABNP=%U_eelopAC-HC0rsG(iOhbZ3P!Zf3_r2 zLMkD`k~2(*UN&a(u5_lD(vYJh5MtPn-9csx<0O?{ozCVvQ>(z3dNo-ZZZMEEIz*&P z$=dz9V$dc`2kbgRUJ9;@Z9AnR)&Q|&8dOG3iz8Pl`Gm?3k|n9C5i(6HA(Qi99~xnq z#3hP1O_q{Oe8F~}dWe%)olnWw_p7jpk7`daenRg%3rJl0skJo$fS7skuB#>^&wC0& zNU<~U(9a8SV|Au%*;5J15MaO(K$q)Sg2BUU!h)+bG7XB3S7;Uv zgo}0El<=ykm?%`t7h;erV7XB}!<#8l*w`Jb=@m(375B_dKp|=3f}Ik6+~sbdfw(mA zx8pbzKYNITfOR7;rYMZDFfVir8|jaeKO3RN&Hjf=pFgVsnj>n?LY2wW;Sbu89d(_vVuIGC9G z();?W3(s|HgE>VPbdS8IkuIR6kTdXJNrFHFVvK0vqxyDIsH+}cA9p<02l(~a*x8I! zX-#%uz&e*yVNR|gnB~`_PH~!+V&%5R!Vk9F;uA7VmZ`G)Kn$|ya+Z(#tK#m)j(y(kczIImiWu zDV&a2seyY?oNx|X*166cYx|H^8pNrrDp=+GX4z&*;RF-PfM~i^$aMD;AF((eO0uxt zUnrfV{Y2h*7|}_^Hs|O}0W}IlFOEIehILPBY z)A6f4#15`%wMx3gmCrz86Sb(2#*Beu!4b;Yh)w}C1ZgHt@p@Fm=mbjii4#nb{0$9M zB-j8RIEO}nBawn?n6acP{GFJpFn}nk)E-SZp<^P8Kq8O21(`G;{62A~7maE;doZm{ zc9*4u=wyV2wO2085>QYyG|~#+HOdu|Eg_)`OosL;Ikh$zs91Xf0H;;1vmiMw2==*^ zjsVEXArx2t9J!n{(DSI$WGAW8J!eYtFrXrFWccA){BTHeO+4XQBabL&=-L|uEZ30? zMNU4o9u`2Awq@<1X`QCHVuZ9v zcIGR}#pa7?Vighd$A%W;d$IUc4OLUoPQ|jAQ5=fq%ar#(6!G9ScJ5NqtO@U-aPVT} zW=eGbV%N(x5dh~}Wg;*X=rE4Aw)u$-a{?sJbhG|NKRc8Ru^<9dn>~cIz9DfLQ(;!o z*ThagbUvyzv7yq|_LH7}Vf$m+ z1QX;Q!WtO~w)+aH3fPhS6ITF2?i;w z^>PS_k87JQW}dMl9~(ZxYwx$-ycCfrlx^p$_)!kCxmLjl%(4%nX)VDRRf1O(Fs|r| zjxCO+?dzFuvk|ck+EI8Hu)G1E&_O0d5ROOsbsw`7ojLjk`(1AkD|jyOOQx0;tVxJM0N?m0#je*vOUdz&MLs{CelpHHvx%*LW=Pz-HjUfYK&4wH~{srM_SP79=N!4&@B_ zIVNF_AKv~!$;e_mAgHbC*hrk`M88W4a|T1{NshJo{4C>_Vd$*OuumNNPBB~@d4vrU zZl?mP@s9de13ORqb%rVh@ys4MZluHD`*F@C#{t4w)0!tt->-(1AiVrm7GB`YoPdZ# z*}u;9`9vtcJ3R;{tDZVS6{-n^7&7AuYdfme6t>oW2+Rrnmn)J+8!x~B#cGl!=E;sl zVEc%apaNMG0?+;n91Kf>cZhjvTv4Wn3dzXRY?NSy3dua&hyCV?u%nXQ>0=cDa&V9% zM5}u$>~!Q)bOt_xcrejPR0^OkO;oK*!i=J-pr0Oo8}2L9lV)Q>Eu0Xk=}&F`1!xcg zBY!0BK15MTJqMo4yOCknh>k|=WTdNRFf6o@6W@n4Pr zO$HsD#dGoXm03Yh>BF8e_f7Kz);;-&tfVv1zHQJ#ZXz^k63 zW;3~QtBv_ap}TSzbiu@ge;`*AJuc9n8(d;Wstcq9U%J9sxeIy^9w3nETVU5PvRI}w zJLDp2FflFE;ms3q+j5iwl93^f#7>5Za^!gNx(B@`=&oS!I+8gZ8rEkMr$~K?!=5I? zYTcTohnWk^`8X)2n8(V%kY;hjat6SnElq99lVofxhGb%8!#TyV2*(45?Ut~S^wsp# zxgXf1+8A+-^c4eW6*-}x`)OFPwx^RAs}H*Kf({mD7K?){(U{>51ZM*YRV@mC3-}KY z*x@r*Lb)E@1J|h7PnOBtp%>*Hev4~QnEMhZ(QPQn z)coBC7$~;UMhq}g^9a?#0hIjC+g6~j6AEcj`z5_~6DPXdMtmry+3F`a5CyLaz)=;d zVPO$RK*TqA3>U;q;RCHlJ06gztT!VUjbuyuedB^VOhe8rL6pR8A2xi{$a2T|ajL{6 z|4KLT#io56;MgaEKl(Zpl!dd;4?Qj2a$O;C-`-aUvZQhiFu4m1-93QutME!vg(S3R zy$#2pF5AFgFn)#Y?wf;wauq2-MQ|IP|hQW|H4H2^t_Q`G4PLl!EkwPJ>c|vhU z6{l5^3d2QvTMQ>+k~KxB1c&Angm5UGM@ZioHSSQXhm0&%n#^3u%uG*X zf@hZf+gOnAY#?0>5{Ymk((8w%LwhLJuViX*;=_~T9;P`C2$!-z2r!-l)>$TLw!b8`_)iwNxaCIzF zj3w*u|U z5;36b|Iv~I_7LRT9ba|1mR}^UbY09!6+Bcfct>OaCh9a%fQS6)_{>>rnk6dF;oS;a z$2(GB=fQo7T|a$4AS>u0(1pZ;3H#yc9g=E~>cW#Zvrq>L(4x^upE8Yz0gpYI&nOmJj9;kOv}!Y3?+q6WYE#%VAgAdEd}U&3 za5{9KM>oaBl$z|#UVy<}R~@0nmj=6ny9^Et$(f84u|X?1R4cQ-q!?pxpcj(T^6OxKXEj-!pYl&ONaG;CGChqW*Ok%rQ(LdsIlCEX}rRhv=aL8mE*k zBdImioo71KXL}Q`RdWz%Wj{I=tqB*hMQ<1kikdJd`9^2TCPXL#*bojpREgB}rD5kW zoJR&+G#s;WcO!;fZ^LzVIpd1hcc2t%4nEz8fjXlOfC##UaD7e)g1j@JD}&Td4HT&# zPOkZI5p!tPY;vjhRaL3AW)WQ!D~ChDm1fcXLd#VPdD+}Yu1Et$kb>#FqHD4YDid1Dr!l-;gxJQM!xLm+mqPcOjmmCvw&$)_ZrcM$0 zl%#?Yg6d!QjcAV$>2ZgqYueRCpQgrF?b3=$m3ug`@SRQABUJaqHEACYXT@mrC0wY$ zcLL2Ae}!#Bd?vM|n1}Hiy%L2YBgmB4BuJo{K$ZN|>dz&{0bvqAd}*i>Mn9VmE2pK= zi2!D}L0T%(=>tW@h*HaaLg2(Y6RE5pJ`g90CHNU!%4GSupC5I|62wWYL#_!oLshp_ z*oo|pJ7{&S?mEgJ@FRd}IQP-xquIyLLk2khvRcS6P!C6lkaVOWDbG@_-bz&RhojyR z&UKF*Rk$XKk|VD3T_y5H5k=(#vzXki3Q>gKjqAUH5uya-G7kcsLfVJHv<-6O?^Cpq zKG(nxX>?5^2F>ens=`Ujl;Y0w0QqeXHIPRo@ELz2mx}wPdQog=>SF1NT0*T7%u zZ+H_-DY5E?NY>#~1|q6~_&&1b)Z6sWssQK#i&e$r%+W;WfSE z1uWP%VL?Y5fZ;$ea)QRk#QXlZAY3@ItyT|PmN+ZN+DEcl6{i%6H1dd=beL#_m5Ld8 zU}Y-`=N52&?1&nzDxu%gj8%|}ygsAi&gGzj5jvWx&{dqW?Lckn&dRUoAJ1zv{ zAXZP-Qsp#d9*NIH{OL0*_a)~T(+^zIEUO%E+2{O($!U09mhBCJ<+x2oJ49HnE3P=p zW#hLMakNdV+=lv7&?5qTNBEHJD_N0ap|)Ern;a2Ksm61WwC{q8Rx90XAx}gF-5e1t z%J#Yvj~XOt6*yiQvk>aP^wqJkHy36h2c%ztyk9CiLE9YO1sjV7glOdGaqm1;J)$%+ z*YcKvB?x!niY3+7cv;LEiNw4@Qr0LdWW22+mo}6J6wU^=&a%krj*nd(vw0B(Kz?mi zDAr6IB{nMQ`2ugOIF4CTVfB`HI7d#BJZJ+m&&_#fm9UfgYB|TC%76N4$+Gu}i_0mk z^rR4a$vw9sVO4z7JsDTQ?Hkm1#+nXbE2Zc`8M-F+&9?0h#DdlbRoPHqFpCK@C$phH0cBq@Up+oq>s}YRV-$F{fH1C#p3&=h*PYPjEwzn8RJ9(VEF70VVcI|uig3=Sa33s!G^V#tNd zuFfO3BDpKee~z%g+pr{cRfL-j$C-`c3r-wF2P7?Y4Suc$R6ET&=<7MKNnW$gt4kE# zX_*6vjaP~Lh|JWh*67AmFP9@6{g$>;cRg7sciox-^&zUZ__&D&+`ByBma~6v&^?v> zQWJwZ*Y)RuYEOR~8*b&m70c+{W^XUDJwH0=)37%mClXBW2oS$%#E3}P9`-HoqMk!@ zvft(LewXTClL}4vldSXXWMFY_C~37dNB&h;8z`7j|KRS5baYilhev#@b^}aGq5f*P zZ&Z`p1D`0Z8g|>+BQeTp!aT!Kq%GF9H4WoA!R|b}!)JH#rs4L_6$vm7FvN2*&1H9C zqR!NX;>Jeim&Qq^G1a|{G#Tg$#Y~63ne1h_@~?V4lr$__dj?>sR3wi{*kYlpRH&-( z_q^dH1|krc5AIP}mmhYkO^aKmk3zWkWU@S~>9ote7u@=O$Tn78RFI_H?lyq(XgcvF z8iL=PUx$$7i?G z)<*%)JXGloi_7TI^)*{Y&c4fsmK)+r)h;dy-yx5Z>-Mf9v@B|E;)T=a)zJ@+!t`XP z{Lwhfa9aVTecRJ3q|P>t+)bcQ^c*J&nHXn>0W>OxRXYIhlbW{SQ$md5X;&?sX?iX^ zP1Zs2#5K^eqe8trnTyh5m~Pf^P?{qQkcLr+LVEy{@L+%$tfEvdR80zs>5y$MF-xtp zFG%kQd;Xo>Jd)?1#h}o51nUWc`skDm37}DyYO> z!qr|{r47c7K!LcJD0v-OJX5YTou95n7Zrs;R$=*>9DA^pQC-Mtu=%r9* zvrm>za$+|spRI=PJFj$@zaOns!1!<)SH_33?ckSBX6v}4EYLkF3=mmae45%(m`w|h zY=ByCsV|j!2XWy<;>M5EjZZ~Uv|Q}qqD9i#%|mtq21gk*t%woIpRbbfD2eWp$X25J zNw_yvtKt1sSR5YoR~gQ+Djibo>#v&)hknQ@rG8uFngx-ms(o(S%^WlxJUgiA$NEWi zwnh%|r#WUOzu_Tr$egaTm)nedmi^C}*>yI7JZ`?;w$9sfYijYvfn0VL^Y8{xJXJ&5 z-Q?(jyR2?8TyL>c#`~Uz`AGa;obPFF*!MJSE%Bo|di0J5KWdx$NvaRp5^j3nA02Bg z+1TApgoZIJIPV{ASrAH+;*F(YrDY$(jh;b$-&r-4>h`*I(!v%&8O{dG?!x45NLY zT!zM|X1D!8dS1uuyvzyK82J1?Vg>M|67j;7IuiwcD6sYrwH>cU*yNaerOu8?EBq=E z-Q6WWhV!5lB!Te}_}}ys7b4@xmH6fka~MsD=^CezKpPaIiF(PxDL7FB)yZ_;9u>~^ zipwE$mIO7@>gkr9rWyCHMw5dQlZ!;!MB%DVf7LLm?MStwuqSk@d8;4;1#zg{z)S(L zP>*I!KW&?5fizR_%_uY~g?kuoP$TgD=sNk%Gmw(DfeV!pyiU1;SmJ=q+CtTFF$u5_GHKbq=R=uJbXR(%=BQ_h)*luQJ#%Z3e2q zZXMG-Lm%Ic0%q9Ba_?~U;Z6kjsJ>}b(d9c6eF@e;WWl-Mhi_GUn6JfFBBT<5`u2)( zIPwOJybYk!+(H(@RN{El z1{7GEv4Pmazj?*NT3n;7<@$*O&GNZ1l+e!E6D08jSL|)Xr(qe^I&W~b6lcSfM;c7k z?H`C9NFZM%W#$PTT-YVJkj#oG#Bn2M$=^@-sfHjH&>s-?*=Syvv3H6gd^hVE}YgtE&axiL_7grq4TQKOh(_37lfPWz&?BsmIBL**?yj!20yEg$7SCE z^Xz8)zZV{Z4M03igrF;iwWiy_#~xGbP^sQ8yLrXJxeJyq98r!QU{4K`&?zGcEo#od z${8Y~ClT%=94&Pr%b88PISHhDGX9@}yQY``&R93ACO3nm=HvIAO$tHHCB8Qc|M~4% z<_vjemVB4IeP8V^Axo7G0e5!_tqa=hfYEjzSQRs@RNdVH`5M*@gVB;!E+qlg*Nz=i zKDk657DFRo047A)6Kb?c1jI&%$_x_mabsGl{iM#5J5TB80vS!` z9li6@Ie4m4?I+JV`Q*-7XLO!2YdXRkL-1}m*`etSNrz*WBXZ}G^7IN!_0H1?#rzq5 zhW0&Ja#Z(kj~gI$fxi6`#2( zPlVMx|Jb@}@$%WJm04WktO5qo1fh7V64AtkT4c4F8L=u7-i;Ah#0iFK1_zKulE&br z^pIM}_(`P-pG{ds<2^=vb#_kSol{q_cn!~~EX6F$HmNS#Mt1Zj5=o#>-64oh&cVEM zI>Zr|@emt#ai*(;<{Trk+;c~z)et>N1k`m{A;iWaTF~oKF^=_9Pl9affYxX$xMrs= zP8V5neJsUGL&yye2F zOcQDh6b5|NR_5w!;=+R7Udl}AadZYWiNvKbIU|KR=^McoK+s~=1nfe!J{nVQwk;Tm z=IQQGHRj2Po%E+WN|^!lv6LXZ)$nm)5v$*sf!<|t73hgJEK(8~hVQ|Uc9h7>Vzy}r z9v+SKDP;45;=~U>#G59#hsr*CWPonH0v$h8)50ELz3c7}9&0-ma33_Wo59)d1Ee)8 z<8IN<8OI?%cOF+An>|R?OY7js%fub~vap12Q8z{nUvFxqDW+ZmG55p>T!=Wi{R?=j zjE*Lp`^GX+Qs&{lCTk*^PDqW;+C3r0Gwi8(c8ZmE>%@5&9q zjGD4&;ZnXVMfW(qF1v8Wyp{MRQ|=Z{5CTfgwY7HxT>?{LM9dfDiW)O&6zm08rzS%g zqoPvMPw|)Q$v}f4K->oba5`hD`S9Z6o$@3d&vd)8S)xiI*5m648#%7NTglsTP;}0z zH6J#3oP*ni*wwt@MY>E@QDUIOb{l@T2^2!{48c1Bq@Ao}My-fm0q&E%Yt*VH!BG)V z{WH$ecCi?aM6b_2%n`_w`&X&2HN>WvX^q~;&{lA@E7LY08{n!%@jIH}vsY{`3ndw< zGOQ*zZxKkQBr5iFfIiDZPWZU*Bk11A=HRObLA~gdgki1Yw;!F~;80$jE=mRkjPfk* zWKN@&5JRIS9P(~xoZ(8o@=zu27CWE&^Og9?rs~9dMK*GVk zRW{g{JStnXCUK3(g2OWi-v|~--kdl?%|C&$DPD zKDU`+_zfx{e(K6db~Io9Bf?x^6QM=q> z=kD&CuGyRNZD~<}GR!qDB%;ocET@;a3^REcSW)jrxgh=SLA`j8x}{{4$ah_?aaF_} z^F9cx+aLs)O8yo8Zc`KWs1>|K3;`iToAz{Pn+g7d#*7221Y2+b4+BzRTx=Ga1!%p#+*}HK=3Kn9O#Ye+!|8l{>l}Q(5_6>xLMdZD${Lpn#shc0 zQ+MdDvx`G2q7#wIxvs3L0}jsIAd&&~{r!F?2O|5hDr+Irf+43@udlN>mZS2O(obN7 z#1!PDn?6bO>@{ZrdVSbY8TVzD0QH&pw;H$3l=1E$?E6lXgcnRd-i>;UEC24msLsD# z!kB0OKNyuMHEE1o86f?du##w4RGEomMS&#O90Zc@9zZ-u*YR?%reoO!s}{~qfz+nB zI|8QAv?)oeKlbq;4OqN({ypb$Ub5tZix)1qV)>=3&b?sS70c(&KY#8y3s-iQ(JzOY zf9gyQNDK~Tl&T=(9+eG9x^k2Q7d9@XA4bXWSPym~-4ss3ABaAv}CzWIeXM!oij6iHW>y3yKKyW0kX~|ns)ma>6<8! z%wg6T0?i4-RRuP}3yTiWmL<8UVWM!J)#3 zTYc_{kULK0a+-JGHEC$4zAFxr7PyTO`_A2qbNTHw<KFE-`zgO)x2RC; zmxQ!t2uoXx>%UibK5A+!zxE+fM36q~zczM>-dYv?CM&K3nU(@cQI<)mo`15%J}JyB z`gjY3vOWOY)IZQ@ACSm+c<~s`Or z6Xt<4clcI0Hbemll}5vUrdvyS!l)O1WEdpirxB6wCvCGZaPS%J@MA84i-Rhz+Rnr^ z=fzid2JPvG@E+}HO-K@}v~nRB;Xt$_r~Fq&7#;`o)zWshuljZ4Ge78pVI`He75W-p zgOU=>_olAOxHUCC?u5QNTWEw&d}Il~tFaY0b9lxsTgbr{%)t!2H$>0e#Y%%0EJq6~ReMrpUCEp3AP4kM0Hl-Y!$_C1+vGC5vL zR+w8*RGHp;7i& z3Ngj=VBYBkXEa2Jw)Y87m%oHqf}manbFM^Yzno*2rq{_Gf)3OdS&qHZWv`JpRaw*$ z2+@kr^{ZtAJU~qM zdbqtQO*J)9$pmSPQ6w-omdsbZ-LWhl-@FGSMVf8ky&$f@&nj6PMUG>yY7lBK92c2T z)j(&}OH#F7Gu50|{l&3+FPb?JU}DWus; zpkwq)V%v(!V^a+$lKvwH%q2y@=@()%DG@P8rz*5B7N?eA)#z6;!=ij z4|%j5vXs#s(JTDS6FfIlGxPu_&BHA;2uBIsBW$gZm7Ah+NPrju$LfaZm%-09_`Mh3 zDdKeyP8MwokYUQ7Je9(4Ora>^Cld>bc`>i3j;%^V3+bT`BrP(YKKA z7I*yUmp02Y0TxSPx1cgz9_f`*KG;6w&q=}3f1!4sFZ$V7xonad>SA|)B6YmrNu!@Kmr5n&4Q z_fSYL>OiJin(ga=2dVa6<|=lf7LD$m%N8$3G=6P9hg+_pEg=v501-tm!D8uxXslpR z@l7=8>7-U1Zl0;PSVJ=vSlT;%v4fMKtaF!l`9<H{VQ@Lk09q~5h4tW@Yh4aNY$x16VZt*s2^g%@8r$lornRFFXTHG ztz0C!*~}#f!ZH-w&6~*&YzIAWXa`i|hFiZpCmY*9RAr@E?DsJ}b{`k4T-+fv&3o2f z*DmJ7>>>`|!bMX4H2mt0s$3l_gwUGcb-)#kH#Vq?8W0NV#3@Xpim}sN6lN}n%fG@3 z@@DZ8Y3|xaeCF(LdL3Nbat&TuUqHOS1WytwQDvGQ0=O?_Mi;w^_Osz z8h^3(k;ZR(8i{@$c+afB@-Sgc1$^RRKjv1Re!* z0Daw4?YJz~hmD-lcYrdFErx;$K|PvCn^aE*jmXfTfIUF1=3N%&swHp}U)5*i{h<&; zUi$&i2-J$$5d!={JN_vy)th=vW?iOxuqszW+7%U>=(pGwmejAs8&-OtNTr1k(fEXv# z3SF~r8YiqkV*L?y%cA_HCJQyl(U>6}D4$tt%{3~L+SAP5ebd3!1j`9p?oNvTIX-31itbu;>ltGeK4@c`WTin8E}>l2dLNS(%|e+F3s&h0^NxkuJYPqCz=;2omJ(_krdhcLxZve5DF^pGd6YZc5W z;DxOxah?c88);G8&Rc3C3=z&s*ASZKBK|{ZRyQYVcKZq?`Mn34bv9R;E}`Agquk9% zn~*z_VdK&o?gI$bRN?Ogxg+chQYbPw3fj)j=z-Yr)^ra(WuwAw`PqX{vM_{FK-UcZ z@l(D>^yOQ_L!?qt8y$9RBNk?-hAxwkRhwZ_HXU_**3gNf@oe zB?nC-R$8P8&jy}Ta~tR`&>F7I5Qv@kf8 z<>iUEfzRcI(fsI4Nj{ltEMqgs*hd2nTQs0RG||7OttX(|Bcndrm@H(|lu~Omxtz$P zBh@_w6j9 zOirdn!VK6AGqn{(D8*b-{&M)^se?cP_IsSHp%r%)9&WY;&&ZpdoSc&8Cuy-VMry=I zwX>Q!YkU)lSt`#I1(#JFAa*6ujE)dhK)Mq9fY3j_9#&n1%FF^t^==G_OVwL7H!;*QI;Tx3zEtQ_;_-{q#q?Px zV*|;mqo@akWca8Mrm#d0=QAx6Wc^MN)ii-JmMP6p6%DU?eN6`C1E3QXQ4%N}zTc^_ zG>{BLO~It^PQWIky0pw(E+o5{rZJqjkXb3f3>=8=ijeT;!>;#eGK=0}!Rg`I?I`rh zMIzQy=x#l*EeRv58Nkh!>`%e`0af6_4TN;=1r1GM7>N~$F38i+2s z6Q-~^u1#vf?Ra>G305q}XR;fUH614l0{e(njN&nSt+9)sxT; ze&;BRJUdwxcAAr=>K=xx(;G!qy#>$l8_FA^=x0}kPk9b%KDsh%QGfBQY85&McQgEo z8?Ki%L@+h+Tl6_fQzx;9_vTfI2OU>ziH5+IrV4FiNPdhF^jQhFJK*R(br!!n!oNr0 z9=hczr2M`#7ncI|W-~dcr@2foy7;5J$r`z!G@Hj&+o+30rV5)A(=~!-%N;pp!dVgN z0iSBq&>Q*4()M!CX0uR9%1X56f`DRx(HgkdoX~ zN!#$ivB26wSc!xAEYbp8ca;H*lvRlHGc!!B zct^A@wMZ>HwU#J$D8uNriz2(Q0$7HN#qXF8l_Q)m9|?a}^H;}82`%c-o^?t}e0TjQ zn#~AJ$FFV{toh-k(L`B?2o<+7d7j^50fyc*nSL^j_z9+hcf24p!flav#L+>Zsf~BT zvgfI&O!4DR23|*Xbn1dpz8q9lQY+KmW$~jONcltj2vaPbp?(CEr-ywverIAb3$wy% zNsDdwBM6xcx_=6h?(j}v6j|X;UxD%w))2_FqH#Ix5mu!y7{*OzJIozs8KNFzxLn*} zvaV|r4hO#hXCtZK_&czrFRtG8==Jv5szT9Is->k@AkQHcIhP|L&<0_+6mW^{l4CKa z=2RRrum)fcx)y}xlw%H%zP2>cw+z8E&ecK%El7*gt3sTFQ~5;&StVW|QQ29-rOvBF zBZDH!Xu5=2W|h*Lol@O5qSjwnc2mO8706^9398_4CuP9i@E09Wv=j9b8_IaPrQDqE zu2oVK=|@+@kzNcT(T81N7ln0{I?{iV9ZFV5Tqe*yDO~UkTp8#xer%C=yzGL6gX~hR z)n92tcRr0jM1H+1KZP+fRgms5xV&Oqx1N#Ki~5z!22KuIO9496vsAAjeB-pkuv55g zX&R0ry(5ujgUPde$Xe)?K~icc#4RRU1u2@;R$btXCm1*Y`H91cN}S{;s@o|?r1q+# z?t$o|S3hXR`4-KjOydL~*V2&vIA0bWi=M&bRYfDJWF+tJ@)7q(+|=8BxgTo-VueC? zgfxC99&*(cnp$YxC&sT^oBQ=fbeH7C26f5wm&U5U9(`KX7Z`4^7RzVM@qmEy{1A6k zG$fgHZOc&)YArQ-pOP0lE22k+<`77^S=e<&>eoW%`NWDjs>{Rwzn>T|frR+K*-tDU zwf^^-iN&vHk}X#tNk{I>@Kn=+0%+fQGa0uTGa`j(c{c(csi}U5v8zz9TUD#hUb3P$50 zcMh3a@tb;m7aYZp z6|EqrW+bMa7;Vn+rZR%W%68C|fy{}#v8W3!Fx-tN#v5fr@}{q~jGFEz*F}g?N7cjW z_ThC&K_QAJ1-Z!?Ki*fffaGE#oyS>Iy9$ zwC?NZK*|&pB{5tm@!}wxwLr~P%8bRZju~f>Hb2t*ykD5JtJfla?<39J7VLf~lOEN)H3x@M4QOnW z&C+wq9!HL}gT!C@4r#HG4REDk#6s5EiWt&J7G8NIgCIh zSJ%$%!he`??4*KQw+eYH?(8*^wp86U7Gonh@+de388AYI z76SN#2$IVH>HH9%&*Ts?N2TmE=82;VCFo=|yO4F`Qds1JmJ4FuwXmW$az_mXOC>+! z7HLug_?`^dh(EPlo+j=OALvF&sv!>3W9^efkbTyV{4{iM08AYFuEYwaT&N!z&*OVM z>*2|+!SlpwHfW<2!y9iRan$l0`k^X! z5-`e27(v3-cM{D?UfX#d2Yt~TR;8NnRxnTYo)yCj@ABwr*pkF<#VV54b42`l5H8Az zt2cQyv*QsNu!8#rFmTyygizA#Fbk0-j;kASnWe|Q>IXDW8fC-`D(6o=<7rF4pnT6I z1qpaUhauDZipMBERA0xWIIv<30p>Qy<^*+?f;njvl8+`r4OJvB9Kvq``U)f@}&~_ab!$hiEUXC0Ys- z691Etxkfjasu~+H7e!mtz27*u3-MNKfhCS~pi!K}fhOZ@qmfp|K%+})(va#%Yl`Ol zXlPTi9YcsR-U3B(e&om#S2o9DUARQTu_Bf0Q47=`Qv|sVbtMq?fW(rlKJk$-kJTwi zf4>TF*SsePHc!yh3m6b~WYSRLX3pTfr8sZxVXD3_;u5?yUUo4M6-cH8uYiK9})` diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_el.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_el.ts deleted file mode 100644 index c0e7ed384e..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_el.ts +++ /dev/null @@ -1,2488 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - ΠÏοσαÏμοσμένο αποθετήÏιο - - - - Repository URL - URL ΧώÏου Αποθήκευσης - - - - Branch - Κλάδος - - - - CompactView - - - - Icon - Εικονίδιο - - - - - <b>Package Name</b> - <b>Όνομα πακέτου</b> - - - - - Version - Έκδοση - - - - - Description - ΠεÏιγÏαφή - - - - Update Available - Διαθέσιμη ΕνημέÏωση - - - - UpdateAvailable - Διαθέσιμη ενημέÏωση - - - - DependencyDialog - - - Dependencies - ΕξαÏτήσεις - - - - Dependency type - ΤÏπος εξάÏτησης - - - - Name - Όνομα - - - - Optional? - ΠÏοαιÏετικό; - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Επίλυση ΕξαÏτήσεων - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Αυτό το Ï€Ïόσθετο έχει τις ακόλουθες απαιτοÏμενες και Ï€ÏοαιÏετικές εξαÏτήσεις. ΠÏέπει να τα εγκαταστήσετε για να μποÏέσει να χÏησιμοποιηθεί αυτό το Ï€Ïόσθετο. - -Θέλετε ο ΔιαχειÏιστής Ï€Ïόσθετων να τα εγκαταστήσει αυτόματα; Επιλέξτε "ΠαÏάβλεψη" για να εγκαταστήσετε το Ï€Ïόσθετο χωÏίς να εγκαταστήσετε τις εξαÏτήσεις. - - - - FreeCAD Addons - ΠÏόσθετα FreeCAD - - - - Required Python modules - ΑπαιτοÏμενες ενότητες Python - - - - Optional Python modules - ΠÏοαιÏετικές ενότητες Python - - - - DeveloperModeDialog - - - Addon Developer Tools - ΠÏόσθετα ΕÏγαλεία ΠÏογÏαμματιστή - - - - Path to Addon - ΔιαδÏομή Ï€Ïος το Ï€Ïόσθετο - - - - - Browse... - ΠεÏιήγηση... - - - - Metadata - Μεταδεδομένα - - - - Primary branch - ΚÏÏιος κλάδος - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Επεξήγηση το τι παÏέχει αυτό το ΠÏόσθετο. Εμφανίζεται στη ΔιαχείÏιση ΠÏόσθετου. Δεν είναι απαÏαίτητο να δηλωθεί ότι Ï€Ïόκειται για ένα Ï€Ïόσθετο FreeCAD. - - - - Description - ΠεÏιγÏαφή - - - - Discussion URL - URL Συζήτησης - - - - Icon - Εικονίδιο - - - - Bugtracker URL - URL ÎµÎ½Ï„Î¿Ï€Î¹ÏƒÎ¼Î¿Ï ÏƒÏ†Î±Î»Î¼Î¬Ï„Ï‰Î½ - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Σημασιολογικά (1.2.3-beta) ή CalVer (2022.08.30) στυλ που υποστηÏίζονται -ΥποστηÏιζόμενα στυλ Î£Î·Î¼Î±ÏƒÎ¹Î¿Î»Î¿Î³Î¹ÎºÎ¿Ï (1.2.3-beta) ή με ημεÏομηνία Έκδοσης (30/8/2022) - - - - Set to today (CalVer style) - ΟÏισμός σε σημεÏινή έκδοση (CalVer στυλ) - - - - - - - (Optional) - (ΠÏοαιÏετικό) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Εμφανίζεται στο Addon Manager's λίστα των Addons. Δεν Ï€Ïέπει να συμπεÏιλάβετε τη λέξη "FreeCAD", και Ï€Ïέπει να είναι ένα έγκυÏο όνομα καταλόγου σε όλα τα λειτουÏγικά συστήματα υποστήÏιξης. - - - - README URL - ΔΙΑΒΑΣΤΕ τη διεÏθυνση URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Εφόσον αυτό εμφανίζεται στη ΔιαχείÏιση ΠÏόσθετων του FreeCAD , δεν είναι απαÏαίτητο να καταλαμβάνετε χώÏο λέγοντας Ï€Ïάγματα όπως "Αυτό είναι ένα FreeCAD Addon. ." - απλά πείτε τι κάνει. - - - - Repository URL - URL ΧώÏου Αποθήκευσης - - - - Website URL - URL Ιστοσελίδας - - - - Documentation URL - URL τεκμηÏίωσης - - - - Addon Name - Όνομα ΠÏόσθετου - - - - Version - Έκδοση - - - - (Recommended) - (ΠÏοτείνεται) - - - - Minimum Python - Ελάχιστη Python - - - - (Optional, only 3.x version supported) - (ΠÏοαιÏετικά, υποστηÏίζεται μόνο έκδοση 3.x) - - - - Detect... - Ανίχνευση... - - - - Addon Contents - ΠεÏιεχόμενα ΠÏόσθετου - - - - Dialog - - - Addon Manager - ΔιαχειÏιστής ΠÏόσθετων - - - - Edit Tags - ΕπεξεÏγασία Ετικετών - - - - Comma-separated list of tags describing this item: - Λίστα ετικετών χωÏισμένη με κόμματα που πεÏιγÏάφουν αυτό το αντικείμενο: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - ΣΥΜΒΟΥΛΗ: Οι κοινές ετικέτες πεÏιλαμβάνουν "ΣυναÏμολόγηση", "FEM", "Πλέγμα", "NURBS", κ.λ.Ï€. - - - - Add-on Manager: Warning! - ΔιαχείÏιση ΠÏόσθετων: ΠÏοειδοποίηση! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Ο ΔιαχειÏιστής ΠÏόσθετων παÏέχει Ï€Ïόσβαση σε μια εκτεταμένη βιβλιοθήκη χÏήσιμων επεκτάσεων FreeCAD Ï„Ïίτων. Δεν μποÏοÏν να γίνουν εγγυήσεις σχετικά με την ασφάλεια ή τη λειτουÏγικότητά τους. - - - - Continue - Συνεχίστε - - - - Cancel - ΑκÏÏωση - - - - EditDependencyDialog - - - Edit Dependency - ΕπεξεÏγασία ΕξάÏτησης - - - - Dependency Type - ΤÏπος ΕξάÏτησης - - - - Dependency - ΕξάÏτηση - - - - Package name, if "Other..." - Όνομα πακέτου, εάν "Άλλο..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - ΣΗΜΕΙΩΣΗ: Αν επιλεγεί "Άλλα..." το πακέτο δεν βÏίσκεται στα ALLOWED_PYTHON_PACKAGES. xt αÏχείο, και δεν θα εγκατασταθεί αυτόματα από το ΔιαχειÏιστής ΠÏόσθετων. Υποβάλετε ένα PR στο <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> για να ζητήσετε την Ï€Ïοσθήκη ενός πακέτου. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Αν αυτή είναι μια Ï€ÏοαιÏετική εξάÏτηση, η ΔιαχείÏιση ΠÏόσθετου θα Ï€ÏοσφέÏει τη δυνατότητα να την εγκαταστήσει (όταν είναι δυνατόν), αλλά δε θα μπλοκάÏει την εγκατάσταση αν ο χÏήστης δεν επιλέξει, ή δεν μποÏεί να εγκαταστήσει το πακέτο. - - - - Optional - ΠÏοαιÏετικό - - - - ExpandedView - - - - Icon - Εικονίδιο - - - - - <h1>Package Name</h1> - <h1>Όνομα πακέτου</h1> - - - - - Version - Έκδοση - - - - - (tags) - (ετικέτες) - - - - - Description - ΠεÏιγÏαφή - - - - - Maintainer - ΣυντηÏητής - - - - Update Available - Διαθέσιμη ΕνημέÏωση - - - - labelSort - Ταξινόμηση - - - - UpdateAvailable - Διαθέσιμη ενημέÏωση - - - - Form - - - Licenses - Άδειες - - - - License - Άδεια - - - - License file - ΑÏχείο άδειας - - - - People - ΆνθÏωποι - - - - Kind - Είδος - - - - Name - Όνομα - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - ΠÏοηγμένη Αντιστοίχιση Έκδοσης - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Οι επεÏχόμενες εκδόσεις του FreeCAD ΔιαχειÏιστής ΠÏόσθετων θα υποστηÏίξουν τους Ï€ÏογÏαμματιστές' οÏίζοντας έναν συγκεκÏιμένο κλάδο ή ετικέτα για χÏήση με μια συγκεκÏιμένη έκδοση του FreeCAD (Ï€. χ. οÏίζοντας μια συγκεκÏιμένη ετικέτα ως την τελευταία έκδοση του Ï€Ïόσθετου σας για υποστήÏιξη v0.19 κλπ.) - - - - FreeCAD Version - Έκδοση FreeCAD - - - - Best-available branch, tag, or commit - Ο καλÏτεÏος διαθέσιμος κλάδος, ετικέτα ή υποβολή - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - ΥποστηÏιζόμενες Εκδόσεις FreeCAD - - - - Minimum FreeCAD Version Supported - Ελάχιστη ΥποστηÏιζόμενη Έκδοση FreeCAD - - - - - Optional - ΠÏοαιÏετικό - - - - Maximum FreeCAD Version Supported - Μέγιστη ΥποστηÏιζόμενη Έκδοση FreeCAD - - - - Advanced version mapping... - ΠÏοηγμένη Αντιστοίχιση Έκδοσης... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Επιλογές διαχείÏισης Ï€Ïόσθετων - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Εάν είναι ενεÏγοποιημένη αυτή η επιλογή, κατά την εκκίνηση του ΔιαχειÏιστή ΠÏοσθέτων. Τα εγκατεστημένα ΠÏόσθετα θα ελεγχθοÏν για διαθέσιμες ενημεÏώσεις - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Λήψη μεταδεδομένων μακÏοεντολών (πεÏίπου 10MB) - - - - Cache update frequency - Συχνότητα ενημέÏωσης Ï€ÏοσωÏινής μνήμης - - - - Manual (no automatic updates) - ΧειÏοκίνητη (δεν υπάÏχουν αυτόματες ενημεÏώσεις) - - - - Daily - ΚαθημεÏινά - - - - Weekly - Εβδομαδιαία - - - - Hide Addons without a license - ΑπόκÏυψη ΠÏόσθετων χωÏίς άδεια - - - - Hide Addons with non-FSF Free/Libre license - ΑπόκÏυψη Ï€Ïοσθέτων με άδεια μη-FSF δωÏεάν/Libre - - - - Hide Addons with non-OSI-approved license - ΑπόκÏυψη Ï€Ïοσθέτων με άδεια μη εγκεκÏιμένη από OSI - - - - Hide Addons marked Python 2 Only - ΑπόκÏυψη Ï€Ïοσθέτων που επισημαίνονται μόνο Python 2 - - - - Hide Addons marked Obsolete - ΑπόκÏυψη Ï€Ïοσθέτων που είναι παÏωχημένα - - - - Hide Addons that require a newer version of FreeCAD - ΑπόκÏυψη ΠÏόσθετων που απαιτοÏν μια νεότεÏη έκδοση του FreeCAD - - - - Custom repositories - ΠÏοσαÏμοσμένα αποθετήÏια - - - - Proxy - Διακομιστής - - - - No proxy - ΧωÏίς διακομιστή - - - - User system proxy - Διακομιστής συστήματος χÏήστη - - - - User-defined proxy: - Διακομιστή οÏισμένου ΧÏήστη: - - - - Score source URL - URL πηγής βαθμολογίας - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Η διεÏθυνση URL για τα δεδομένα του Addon Score (δείτε τη σελίδα wiki του Addon Manager για τη μοÏφοποίηση και τις λεπτομέÏειες φιλοξενίας). - - - - Path to Git executable (optional): - ΔιαδÏομή Ï€Ïος το εκτελέσιμο Git (Ï€ÏοαιÏετικό): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - ΠÏοχωÏημένες Ρυθμίσεις - - - - Activate Addon Manager options intended for developers of new Addons. - ΕνεÏγοποιήστε τις επιλογές ΔιαχειÏιστή ΠÏοσθέτων που Ï€ÏοοÏίζονται για Ï€ÏογÏαμματιστές νέων ΠÏόσθετων. - - - - Addon developer mode - ΛειτουÏγία ΠÏόσθετου Ï€ÏογÏαμματιστή - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Απεγκαθιστά μια επιλεγμένη μακÏοεντολή ή πάγκο εÏγασίας - - - - Install - Εγκατάσταση - - - - Uninstall - Απεγκατάσταση - - - - Update - ΕνημέÏωση - - - - Run Macro - Εκτέλεση ΜακÏοεντολής - - - - Change branch - Αλλαγή τοποθεσίας - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - ΔιαχείÏιση ΕξαÏτήσεων Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Τα ακόλουθα πακέτα Python έχουν εγκατασταθεί τοπικά από το ΔιαχειÏιστή ΠÏοσθέτων για να ικανοποιήσουν τις εξαÏτήσεις του ΠÏόσθετο: - - - - Package name - Όνομα πακέτου - - - - Installed version - Εγκατεστημένη έκδοση - - - - Available version - Διαθέσιμη έκδοση - - - - Used by - ΧÏησιμοποιείται από - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Ένας αστεÏίσκος (*) στο "ΧÏησιμοποιείται από τη στήλη" υποδηλώνει μια Ï€ÏοαιÏετική εξάÏτηση. Σημειώστε ότι χÏησιμοποιείται μόνο με τις άμεσες εισαγωγές στο ΠÏόσθετο. ΜποÏεί να έχουν εγκατασταθεί και άλλα πακέτα Python από τα οποία εξαÏτώνται αυτά τα πακέτα. - - - - Update all available - ΕνημέÏωση όλων των διαθέσιμων - - - - SelectFromList - - - Dialog - Διάλογος - - - - TextLabel - Ετικέτα κειμένου - - - - UpdateAllDialog - - - Updating Addons - ΕνημέÏωση ΠÏόσθετων - - - - Updating out-of-date addons... - ΕνημέÏωση μη ενημεÏωμένων Ï€Ïοσθέτων... - - - - addContentDialog - - - Content Item - Αντικείμενα ΠεÏιεχομένου - - - - Content type: - ΤÏπος πεÏιεχομένου: - - - - Macro - ΜακÏοεντολή - - - - Preference Pack - Πακέτο ΠÏοτιμήσεων - - - - Workbench - Πάγκος εÏγασίας - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Εάν αυτό είναι το μόνο Ï€Ïάγμα στο Ï€Ïόσθετο, όλα τα άλλα μεταδιδόμενα μποÏοÏν να κληÏονομηθοÏν από το ανώτεÏο επίπεδο και δε χÏειάζεται να καθοÏιστοÏν εδώ. - - - - This is the only item in the Addon - Αυτό είναι το μόνο αντικείμενο στο ΠÏόσθετο - - - - Main macro file - ΚÏÏιο αÏχείο μακÏοεντολής - - - - The file with the macro's metadata in it - Το αÏχείο με την μακÏοεντολή's μεταδεδομένα σε αυτό - - - - - - Browse... - ΠεÏιήγηση... - - - - Preference Pack Name - Όνομα Πακέτου ΠÏοτίμησης - - - - Workbench class name - Όνομα κλάσης πάγκου εÏγασίας - - - - Class that defines "Icon" data member - Κλάση που οÏίζει το μέλος δεδομένων "Icon" - - - - Subdirectory - Υποκατάλογος - - - - Optional, defaults to name of content item - ΠÏοαιÏετικό, Ï€ÏοκαθοÏισμένο όνομα του στοιχείου - - - - Icon - Εικονίδιο - - - - Optional, defaults to inheriting from top-level Addon - ΠÏοαιÏετικό, Ï€Ïοεπιλογή για εισαγωγή από Ï€Ïόσθετο ανώτατου επιπέδου - - - - Tags... - Ετικέτες… - - - - Dependencies... - ΕξαÏτήσεις... - - - - FreeCAD Versions... - Έκδοση FreeCAD... - - - - Other Metadata - Άλλα Μεταδεδομένα - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Εμφανίζεται στη λίστα ΔιαχείÏιση ΠÏοσθέτων's των Addons. Δε θα Ï€Ïέπει να συμπεÏιλαμβάνει τη λέξη "FreeCAD". - - - - Version - Έκδοση - - - - Description - ΠεÏιγÏαφή - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Σημασιολογικά (1.2.3-beta) ή CalVer (2022.08.30) στυλ που υποστηÏίζονται -ΥποστηÏιζόμενα στυλ Î£Î·Î¼Î±ÏƒÎ¹Î¿Î»Î¿Î³Î¹ÎºÎ¿Ï (1.2.3-beta) ή με ημεÏομηνία Έκδοσης (30/8/2022) - - - - Set to today (CalVer style) - ΟÏισμός σε σημεÏινή έκδοση (CalVer στυλ) - - - - Display Name - Εμφάνιση Ονόματος - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Τυχόν πεδία που παÏαμένουν κενά κληÏονομοÏνται από τα ανώτεÏα μεταδεδομένα του Addon, οπότε τεχνικά είναι όλα Ï€ÏοαιÏετικά. Για τα ΠÏόσθετα με πολλαπλά στοιχεία πεÏιεχομένου, κάθε στοιχείο θα Ï€Ïέπει να παÏέχει ένα μοναδικό Εμφανιζόμενο Όνομα και ΠεÏιγÏαφή. - - - - add_toolbar_button_dialog - - - Add button? - ΠÏοσθήκη κουμπιοÏ? - - - - Add a toolbar button for this macro? - ΠÏοσθήκη ÎºÎ¿Ï…Î¼Ï€Î¹Î¿Ï Î³Ïαμμής εÏγαλείων για αυτή την μακÏοεντολή; - - - - Yes - Îαι - - - - No - Όχι - - - - Never - Ποτέ - - - - change_branch - - - Change Branch - Αλλαγή Κλάδου - - - - Change to branch: - Αλλαγή σε κλάδο: - - - - copyrightInformationDialog - - - Copyright Information - ΠληÏοφοÏίες Πνευματικών Δικαιωμάτων - - - - Copyright holder: - Κάτοχος πνευματικών δικαιωμάτων: - - - - Copyright year: - Έτος πνευματικών δικαιωμάτων: - - - - personDialog - - - Add Person - ΠÏοσθήκη ατόμου - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Ένας συντηÏητής είναι κάποιος με Ï„Ïέχουσα Ï€Ïόσβαση σε αυτό το έÏγο. Συντάκτης είναι οποιοσδήποτε άλλος 'θα θέλατε να αποδώσετε τα εÏσημα. - - - - Name: - Όνομα: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Απαιτείται email για συντηÏητές, και Ï€ÏοαιÏετικό για τους συγγÏαφείς. - - - - proxy_authentication - - - Proxy login required - Απαιτείται σÏνδεση διακομιστή - - - - Proxy requires authentication - Ο διακομιστής απαιτεί ταυτοποίηση - - - - Proxy: - Διακομιστής: - - - - Placeholder for proxy address - Υποκατάσταση θέσης για διεÏθυνση διακομιστή - - - - Realm: - Τομέας: - - - - Placeholder for proxy realm - ΠÏοσωÏινή καταχώÏηση τομέα Διακομιστή - - - - Username - Όνομα χÏήστη - - - - Password - Κωδικός ΠÏόσβασης - - - - selectLicenseDialog - - - Select a license - Επιλέξτε Άδεια - - - - About... - Σχετικά με... - - - - License name: - Όνομα αδείας: - - - - Path to license file: - ΔιαδÏομή για το αÏχείο άδειας: - - - - (if required by license) - (εάν απαιτείται από την άδεια) - - - - Browse... - ΠεÏιήγηση... - - - - Create... - ΔημιουÏγία... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Επιλογή γÏαμμής εÏγαλείων - - - - Select a toolbar to add this macro to: - Επιλέξτε μια γÏαμμή εÏγαλείων για να Ï€Ïοσθέσετε αυτή την μακÏοεντολή: - - - - Ask every time - Îα γίνεται εÏώτηση κάθε φοÏά - - - - toolbar_button - - - - Add button? - ΠÏοσθήκη κουμπιοÏ? - - - - Add a toolbar button for this macro? - ΠÏοσθήκη ÎºÎ¿Ï…Î¼Ï€Î¹Î¿Ï Î³Ïαμμής εÏγαλείων για αυτή την μακÏοεντολή? - - - - Yes - Îαι - - - - No - Όχι - - - - Never - Ποτέ - - - - AddonsInstaller - - - Starting up... - Εκκίνηση... - - - - Worker process {} is taking a long time to stop... - Η διαδικασία εÏγασίας {} αÏγεί Ï€Î¿Î»Ï Î½Î± σταματήσει... - - - - Previous cache process was interrupted, restarting... - - Η Ï€ÏοηγοÏμενη διεÏγασία cache διακόπηκε, επανεκκίνηση... - - - - - Custom repo list changed, forcing recache... - - Η Ï€ÏοσαÏμοσμένη λίστα αποθεμάτων άλλαξε, επιβάλλεται εκ νέου Ï€ÏοσωÏινή αποθήκευση... - - - - - Addon manager - ΔιαχειÏιστής ΠÏόσθετων - - - - You must restart FreeCAD for changes to take effect. - ΠÏέπει να επανεκκινήσετε το FreeCAD για να τεθοÏν σε Î¹ÏƒÏ‡Ï Î¿Î¹ αλλαγές. - - - - Restart now - Επανεκκίνηση τώÏα - - - - Restart later - Επανεκκίνηση αÏγότεÏα - - - - - Refresh local cache - Ανανέωση τοπικής Ï€ÏοσωÏινής μνήμης - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - ΕνημέÏωση Ï€ÏοσωÏινής μνήμης... - - - - - Checking for updates... - Έλεγχος για ενημεÏώσεις... - - - - Temporary installation of macro failed. - Η Ï€ÏοσωÏινή εγκατάσταση της μακÏοεντολής απέτυχε. - - - - - Close - Κλείσιμο - - - - Update all addons - ΕνημέÏωση όλων των Ï€Ïοσθέτων - - - - Check for updates - Έλεγχος για ενημεÏώσεις - - - - Python dependencies... - ΕξαÏτήσεις για Python... - - - - Developer tools... - ΕÏγαλεία για Ï€ÏογÏαμματιστές... - - - - Apply %n available update(s) - ΕφαÏμογή %n διαθέσιμων ενημεÏώσεων(ων) - - - - No updates available - Δεν υπάÏχουν διαθέσιμες ενημεÏώσεις - - - - - - Cannot launch a new installer until the previous one has finished. - Δεν είναι δυνατή η εκκίνηση ενός νέου Ï€ÏογÏάμματος εγκατάστασης μέχÏι να τελειώσει η Ï€ÏοηγοÏμενη. - - - - - - - Maintainer - ΣυντηÏητής - - - - - - - Author - ΣυγγÏαφέας - - - - New Python Version Detected - ΑνιχνεÏθηκε Îέα Έκδοση Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Αυτή φαίνεται να είναι η Ï€Ïώτη φοÏά που αυτή η έκδοση της Python χÏησιμοποιείται με το ΔιαχειÏιστή ΠÏοσθέτων. Θέλετε να εγκαταστήσετε τις ίδιες αυτόματο-εγκατεστημένες εξαÏτήσεις? - - - - Processing, please wait... - Γίνεται επεξεÏγασία, παÏακαλώ πεÏιμένετε... - - - - - Update - ΕνημέÏωση - - - - Updating... - ΕνημέÏωση... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Αδυναμία εισαγωγής του QtNetwork -- δε φαίνεται να είναι εγκατεστημένο στο σÏστημά σας. Ο πάÏοχος σας μποÏεί να έχει ένα πακέτο για αυτή την εξάÏτηση (συχνά ονομάζεται "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Αποτυχία μετατÏοπής της καθοÏισμένης θÏÏας διαμεσολαβητή '{}' σε αÏιθμό θÏÏας - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Σφάλμα παÏαμέτÏου: ΟÏίστηκαν αμοιβαία αποκλειστικές επιλογές διακομιστή μεσολάβησης. ΕπαναφοÏά στην Ï€Ïοεπιλογή. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Σφάλμα παÏαμέτÏων: υποδεικνÏεται ο διαμεσολαβητής χÏήστη, αλλά δεν παÏέχεται διαμεσολαβητής. ΕπαναφοÏά στην Ï€Ïοεπιλογή. - - - - Addon Manager: Unexpected {} response from server - ΔιαχειÏιστής ΠÏόσθετων: Μη αναμενόμενη απάντηση {} από τον διακομιστή - - - - Error with encrypted connection - Σφάλμα με κÏυπτογÏαφημένη σÏνδεση - - - - - - Confirm remove - Επιβεβαίωση διαγÏαφής - - - - Are you sure you want to uninstall {}? - Είστε βέβαιοι ότι θέλετε να απεγκαταστήσετε {}; - - - - - - Removing Addon - ΑφαίÏεση ΠÏόσθετου - - - - Removing {} - ΑφαίÏεση {} - - - - - Uninstall complete - Η απεγκατάσταση ολοκληÏώθηκε - - - - - Uninstall failed - Η απεγκατάσταση έχει αποτÏχει - - - - Version {version} installed on {date} - Η έκδοση {version} εγκαταστάθηκε στο {date} - - - - Version {version} installed - Η έκδοση {version} εγκαταστάθηκε - - - - Installed on {date} - Εγκαταστάθηκε στο {date} - - - - - - - Installed - Εγκαταστάθηκε - - - - Currently on branch {}, name changed to {} - Αυτή τη στιγμή στον κλάδο {}, το όνομα άλλαξε σε {} - - - - Git tag '{}' checked out, no updates possible - Ετικέτα Git '{}' έλεγχος, δεν είναι δυνατή η ενημέÏωση - - - - Update check in progress - Έλεγχος ενημέÏωσης σε εξέλιξη - - - - Installation location - Θέση εγκατάστασης - - - - Repository URL - URL ΧώÏου Αποθήκευσης - - - - Changed to branch '{}' -- please restart to use Addon. - Αλλαγές στο '{}' -- Κάντε επανεκκίνηση για να χÏησιμοποιήσετε το ΠÏόσθετο. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Αυτό το Ï€Ïόσθετο έχει ενημεÏωθεί. Επανεκκίνηση το FreeCAD για να δείτε τις αλλαγές. - - - - Disabled - ΑπενεÏγοποιημένο - - - - Currently on branch {}, update available to version {} - Αυτή τη στιγμή στον κλάδο {}, διαθέσιμη ενημέÏωση για την έκδοση {} - - - - Update available to version {} - Διαθέσιμη ενημέÏωση για την έκδοση {} - - - - This is the latest version available - Αυτή είναι η τελευταία διαθέσιμη έκδοση - - - - WARNING: This addon is obsolete - ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό το Ï€Ïόσθετο είναι παÏωχημένο - - - - WARNING: This addon is Python 2 only - ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό το Ï€Ïόσθετο είναι μόνο Python 2 - - - - WARNING: This addon requires FreeCAD {} - ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό το Ï€Ïόσθετο απαιτεί FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αυτό το Ï€Ïόσθετο είναι εγκατεστημένο, αλλά απενεÏγοποιημένο. ΧÏησιμοποιήστε το κουμπί 'ενεÏγοποίηση' για να ενεÏγοποιηθεί ξανά. - - - - This Addon will be enabled next time you restart FreeCAD. - Αυτό το Ï€Ïόσθετο θα ενεÏγοποιηθεί την επόμενη φοÏά που θα κάνετε επανεκκίνηση του FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Αυτό το Ï€Ïόσθετο θα ενεÏγοποιηθεί την επόμενη φοÏά που θα κάνετε επανεκκίνηση του FreeCAD. - - - - - - Success - Επιτυχώς - - - - Install - Εγκατάσταση - - - - Uninstall - Απεγκατάσταση - - - - Enable - ΕνεÏγοποίηση - - - - Disable - ΑπενεÏγοποίηση - - - - - Check for update - Έλεγχος για ενημεÏώσεις - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Εκτέλεση - - - - Change branch... - Αλλαγή Κλάδου... - - - - Return to package list - ΕπιστÏοφή στη λίστα πακέτων - - - - Checking connection - Ελέγξτε τη σÏνδεση - - - - Checking for connection to GitHub... - Έλεγχος για σÏνδεση με το GitHub... - - - - Connection failed - Αποτυχία σÏνδεσης - - - - Missing dependency - Λείπει εξάÏτηση - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Δεν ήταν δυνατή η εισαγωγή του QtNetwork -- ανατÏέξτε στην ΠÏοβολή αναφοÏάς για λεπτομέÏειες. ΔιαχειÏιστής Ï€Ïόσθετων Μη διαθέσιμο. - - - - Other... - For providing a license other than one listed - Άλλο... - - - - Select the corresponding license file in your Addon - Επιλέξτε το αντίστοιχο αÏχείο άδειας χÏήσης στο Ï€Ïόσθετο σας - - - - Location for new license file - Τοποθεσία για νέο αÏχείο άδειας - - - - Received {} response code from server - Λήφθηκε κωδικός απόκÏισης {} από το διακομιστή - - - - Failed to install macro {} - Αποτυχία εγκατάστασης μακÏοεντολής {} - - - - Failed to create installation manifest file: - - Αποτυχία δημιουÏγίας αÏχείου δήλωσης εγκατάστασης: - - - - Unrecognized content kind '{}' - Μη αναγνωÏισμένο είδος πεÏιεχομένου '{}' - - - - Unable to locate icon at {} - Αδυναμία ÎµÎ½Ï„Î¿Ï€Î¹ÏƒÎ¼Î¿Ï ÎµÎ¹ÎºÎ¿Î½Î¹Î´Î¯Î¿Ï… στο {} - - - - Select an icon file for this content item - Επιλέξτε ένα αÏχείο εικονιδίων για αυτό το στοιχείο - - - - - - {} is not a subdirectory of {} - {} δεν είναι ένας υποκατάλογος του {} - - - - Select the subdirectory for this content item - Επιλέξτε τον υποκατάλογο Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… στοιχείου πεÏιεχομένου - - - - Automatic - Αυτόματη - - - - - Workbench - Πάγκος εÏγασίας - - - - Addon - ΠÏόσθετα - - - - Python - Python - - - - Yes - Îαι - - - - Internal Workbench - ΕσωτεÏικός Πάγκος ΕÏγασίας - - - - External Addon - ΕξωτεÏικό ΠÏόσθετο - - - - Python Package - Πακέτο Python - - - - - Other... - Άλλο... - - - - Too many to list - ΠάÏα πολλά στη λίστα - - - - - - - - - Missing Requirement - Λείπουν Ï€ÏοαπαιτοÏμενα - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Το ΠÏόσθετο '{}' απαιτεί '{}', το οποίο δεν είναι διαθέσιμο στο αντίγÏαφο του FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Το ΠÏόσθετο '{}' απαιτεί τους παÏακάτω πάγκους εÏγασίας, οι οποίοι δεν είναι διαθέσιμοι στο αντίγÏαφο του FreeCAD: - - - - Press OK to install anyway. - Πατήστε OK για εγκατάσταση. - - - - - Incompatible Python version - Μη συμβατή έκδοση Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Αυτό το Ï€Ïόσθετο απαιτεί Python πακέτα που δεν είναι εγκατεστημένα και δεν μποÏοÏν να εγκατασταθοÏν αυτόματα. Για να χÏησιμοποιήσετε αυτό το Ï€Ïόσθετο Ï€Ïέπει να εγκαταστήσετε τα ακόλουθα πακέτα Python χειÏοκίνητα: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Αυτό το ΠÏόσθετο (ή τα εξαÏτήματά του) απαιτεί Python {}.{}, και το σÏστημά σας εκτελείται {}.{}. Η εγκατάσταση ακυÏώθηκε. - - - - Optional dependency on {} ignored because it is not in the allow-list - Η Ï€ÏοαιÏετική εξάÏτηση από {} αγνοήθηκε επειδή δεν είναι στη λίστα επιτÏεπτών - - - - - Installing dependencies - Εγκατάσταση εξαÏτήσεων - - - - - Cannot execute Python - Αδυναμία εκτέλεσης Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Απέτυχε ο αυτόματος εντοπισμός του εκτελέσιμου αÏχείου Python ή η διαδÏομή έχει οÏιστεί εσφαλμένα. Ελέγξτε τη ÏÏθμιση Ï€Ïοτιμήσεων του ΔιαχειÏιστή ΠÏοσθέτων για τη διαδÏομή Ï€Ïος την Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Δεν ήταν δυνατή η εγκατάσταση των εξαÏτήσεων. Θέλετε να συνεχίστε με την εγκατάσταση της {}; - - - - - Cannot execute pip - Αδυναμία εκτέλεσης pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Αποτυχία εκτέλεσης του pip, το οποίο μποÏεί να λείπει από την εγκατάσταση της Python. Βεβαιωθείτε ότι το σÏστημά σας έχει εγκατασταθεί το pip, Ï€Ïοσπαθήστε ξανά. Η αποτυχημένη εντολή ήταν: - - - - - Continue with installation of {} anyway? - Θέλετε οπωσδήποτε να συνεχίσετε με την εγκατάσταση του {} ; - - - - - Package installation failed - Η εγκατάσταση του πακέτου απέτυχε - - - - See Report View for detailed failure log. - Δείτε την ΑναφοÏά ΠÏοβολής για λεπτομεÏή καταγÏαφή αποτυχίας. - - - - Installing Addon - Εγκατάσταση ΠÏόσθετου - - - - Installing FreeCAD Addon '{}' - Εγκατάσταση ΠÏόσθετου FreeCAD '{}' - - - - Cancelling - ΑκÏÏωση - - - - Cancelling installation of '{}' - ΑκÏÏωση εγκατάστασης '{}' - - - - {} was installed successfully - εγκαταστάθηκε επιτυχώς - - - - - Installation Failed - Η εγκατάσταση απέτυχε - - - - Failed to install {} - Αποτυχία εγκατάστασης - - - - - Create new toolbar - ΔημιουÏγία νέας γÏαμμής εÏγαλείων - - - - - A macro installed with the FreeCAD Addon Manager - Μια μακÏοεντολή που έχει εγκατασταθεί με το FreeCAD ΔιαχειÏιστή ΠÏοσθέτων - - - - - Run - Indicates a macro that can be 'run' - Εκτέλεση - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Δεν είναι δυνατή η ανάγνωση δεδομένων από το GitHub: ελέγξτε τη σÏνδεσή σας στο Διαδίκτυο και τις Ïυθμίσεις διακομιστή και δοκιμάστε ξανά. - - - - XML failure while reading metadata from file {} - Αποτυχία XML κατά την ανάγνωση μεταδεδομένων από το αÏχείο {} - - - - Invalid metadata in file {} - Μη έγκυÏα μεταδεδομένα στο αÏχείο {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η διαδÏομή που καθοÏίζεται στο package.xml metadata δεν ταιÏιάζει με αυτόν τον κλάδο που έχει ολοκληÏωθεί. - - - - Name - Όνομα - - - - Class - Κλάση - - - - Description - ΠεÏιγÏαφή - - - - Subdirectory - Υποκατάλογος - - - - Files - ΑÏχεία - - - - Select the folder containing your Addon - Επιλέξτε το φάκελο που πεÏιέχει το Ï€Ïόσθετο σας - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - ΧωÏίς Vermin, ακÏÏωση λειτουÏγίας. - - - - Scanning Addon for Python version compatibility - ΣάÏωση Ï€Ïόσθετου για συμβατότητα έκδοσης Python - - - - Minimum Python Version Detected - Εντοπίστηκε Ελάχιστη Έκδοση Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin αυτόματη ανίχνευση μιας απαιτοÏμενης έκδοσης της Python 3.{} - - - - Install Vermin? - Εγκατάσταση Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Η αυτόματη ανίχνευση της απαιτοÏμενης έκδοσης της Python για αυτό το Ï€Ïόσθετο απαιτεί Vermin (https://pypi.org/project/vermin/). Εντάξει για την εγκατάσταση? - - - - Attempting to install Vermin from PyPi - ΠÏοσπάθεια εγκατάστασης του Vermin από την PyPi - - - - - Installation failed - Αποτυχία εγκατάστασης - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Αποτυχία εγκατάστασης του Vermin -- ελέγξτε την ΑναφοÏά ΠÏοβολή για λεπτομέÏειες. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Αποτυχία εισαγωγής Vermin μετά την εγκατάσταση -- Δεν είναι δυνατή η σάÏωση ΠÏόσθετο. - - - - Select an icon file for this package - Επιλέξτε ένα αÏχείο εικονιδίων για αυτό το πακέτο - - - - Filter is valid - Το φίλτÏο είναι έγκυÏο - - - - Filter regular expression is invalid - Η τυπική έκφÏαση του φίλτÏου δεν είναι έγκυÏη - - - - Search... - Αναζήτηση... - - - - Click for details about package {} - Κάντε κλικ για λεπτομέÏειες σχετικά με το πακέτο {} - - - - Click for details about workbench {} - Κάντε κλικ για λεπτομέÏειες σχετικά με τον πάγκο εÏγασίας {} - - - - Click for details about macro {} - Κάντε κλικ για λεπτομέÏειες σχετικά με τη μακÏοεντολή {} - - - - Maintainers: - ΣυντηÏητές: - - - - Tags - Ετικέτες - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - Όχι ★ ή όχι στο GitHub - - - - Created - ΔημιουÏγήθηκε - - - - Updated - ΕνημεÏώθηκε - - - - Score: - Βαθμολογία: - - - - - Up-to-date - ΕνημεÏωμένο - - - - - - - - Update available - Διαθέσιμη ενημέÏωση - - - - - Pending restart - ΕκκÏεμής επανεκκίνηση - - - - - DISABLED - ΑΠΕÎΕΓΟΠΟΙΗΣΗ - - - - Installed version - Εγκατεστημένη έκδοση - - - - Unknown version - Άγνωστη έκδοση - - - - Installed on - Εγκαταστάθηκε στο - - - - Available version - Διαθέσιμη έκδοση - - - - Filter by... - ΦίλτÏο από... - - - - Addon Type - ΤÏπος ΠÏόσθετου - - - - - Any - Οποιαδήποτε - - - - Macro - ΜακÏοεντολή - - - - Preference Pack - Πακέτο ΠÏοτιμήσεων - - - - Installation Status - Κατάσταση Εγκατάστασης - - - - Not installed - Δεν έγινε εγκατάσταση - - - - Filter - ΦίλτÏο - - - - DANGER: Developer feature - ΚΙÎΔΥÎΟΣ: ΛειτουÏγία Ï€ÏογÏαμματιστή - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - ΚΙÎΔΥÎΟΣ: Η εναλλαγή τμημάτων Ï€ÏοοÏίζεται για Ï€ÏογÏαμματιστές και δοκιμαστές beta, αυτό μποÏεί να έχει ως αποτέλεσμα σπασμένα έγγÏαφα, μη συμβατά, αστάθεια, σφάλματα ή/και ξαφνική απώλεια. -Είσαι σίγουÏος ότι θέλεις να συνεχίσεις; - - - - There are local changes - ΥπάÏχουν τοπικές αλλαγές - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ΠΡΟΣΟΧΗ: Αυτό το repo έχει τοπικές αλλαγές που δεν έχουν Ï€Ïαγματοποιηθεί. Είστε σίγουÏοι ότι θέλετε να αλλάξετε κλάδο (φέÏνοντας τις αλλαγές μαζί σας); - - - - Local - Table header for local git ref name - Τοπικό - - - - Remote tracking - Table header for git remote tracking branch name - ΑπομακÏυσμένη παÏακολοÏθηση - - - - Last Updated - Table header for git update date - Τελευταία ΕνημέÏωση - - - - Installation of Python package {} failed - Η εγκατάσταση του πακέτου Python {} απέτυχε - - - - Installation of optional package failed - Η εγκατάσταση του Ï€ÏοαιÏÎµÏ„Î¹ÎºÎ¿Ï Ï€Î±ÎºÎ­Ï„Î¿Ï… απέτυχε - - - - Installing required dependency {} - Εγκατάσταση της απαιτοÏμενης εξάÏτησης {} - - - - Installation of Addon {} failed - Η εγκατάσταση του ΠÏόσθετου {} απέτυχε - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Αποτυχία αποκωδικοποίησης του αÏχείου {} για το ΠÏόσθετο '{}' - - - - Any dependency information in this file will be ignored - Οποιαδήποτε πληÏοφοÏία εξάÏτησης σε αυτό το αÏχείο θα αγνοηθεί - - - - Unable to open macro wiki page at {} - Αδυναμία ανοίγματος σελίδας macro wiki στο {} - - - - Unable to fetch the code of this macro. - Δεν είναι δυνατή η λήψη του κώδικα αυτής της μακÏοεντολής. - - - - Unable to retrieve a description from the wiki for macro {} - Δεν είναι δυνατή η ανάκτηση μιας πεÏιγÏαφής από το wiki για την μακÏοεντολή {} - - - - Unable to open macro code URL {} - Αδυναμία άνοιγμα του URL ÎºÏ‰Î´Î¹ÎºÎ¿Ï Î¼Î±ÎºÏοεντολής {} - - - - Unable to fetch macro-specified file {} from {} - ΑδÏνατη η ανάκτηση του αÏχείου που καθοÏίστηκε μακÏοεντολή {} από {} - - - - Could not locate macro-specified file {} (expected at {}) - ΑδÏνατος ο εντοπισμός του αÏχείου {} (αναμένεται στις {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Μη αναγνωÏισμένος εσωτεÏικός πάγκος εÏγασίας '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - ΠÏοειδοποίηση ΠÏόσθετου ΠÏογÏαμματιστή: Το URL του ΑποθετηÏίου έχει οÏιστεί στο αÏχείο package.xml για Ï€Ïόσθετο {} ({}) δεν ταιÏιάζει με το URL που ανακτήθηκε από ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - ΠÏοειδοποίηση ΠÏόσθετου ΠÏογÏαμματιστή: Ο κλάδος αποθετηÏίου που οÏίστηκε στο αÏχείο package.xml για Ï€Ïόσθετο {} ({}) δεν ταιÏιάζει με τον κλάδο που ανακτήθηκε από ({}) - - - - - Got an error when trying to import {} - ΠαÏουσιάστηκε σφάλμα κατά την Ï€Ïοσπάθεια εισαγωγής του {} - - - - An unknown error occurred - Η λειτουÏγία απέτυχε λόγω άγνωστου σφάλματος. - - - - Could not find addon {} to remove it. - Δεν ήταν δυνατή η εÏÏεση του Ï€Ïόσθετου {} για την κατάÏγησή του. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Η εκτέλεση του 's uninstall.py ΠÏόσθετου απέτυχε. Συνέχεια με την απεγκατάσταση... - - - - Removed extra installed file {} - ΚαταÏγήθηκε το επιπλέον εγκατεστημένο αÏχείο {} - - - - Error while trying to remove extra installed file {} - Σφάλμα κατά την Ï€Ïοσπάθεια κατάÏγησης επιπλέον εγκατεστημένου αÏχείου {} - - - - Error while trying to remove macro file {}: - Σφάλμα κατά την αφαίÏεση του αÏχείου μακÏοεντολής {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Αποτυχία σÏνδεσης στο GitHub. Ελέγξτε τη σÏνδεσή σας και τις Ïυθμίσεις διαμεσολαβητή. - - - - WARNING: Duplicate addon {} ignored - ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Το διπλό Ï€Ïόσθετο {} αγνοήθηκε - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - ΠαÏουσιάστηκε σφάλμα στην ενημέÏωση των μακÏοεντολών από το GitHub, κατά την Ï€Ïοσπάθεια ΑποχώÏησης… - - - - Attempting to do a clean checkout... - ΠÏοσπάθεια καθαÏÎ¹ÏƒÎ¼Î¿Ï Î‘Ï€Î¿Ï‡ÏŽÏηση... - - - - Clean checkout succeeded - Η κάθαÏση ολοκληÏώθηκε με επιτυχής έξοδος - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Αποτυχία ενημέÏωσης μακÏοεντολών από το GitHub -- δοκιμάστε να καθαÏίσετε την κÏυφή μνήμη του ΔιαχειÏιστή ΠÏοσθέτων's. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Σφάλμα κατά τη σÏνδεση με το Wiki, το FreeCAD δεν μποÏεί να ανακτήσει τη λίστα μακÏοεντολών του Wiki αυτή τη στιγμή - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Αποτυχία ανάγνωσης μεταδεδομένων από {name} - - - - Failed to fetch code for macro '{name}' - Αποτυχία λήψης κώδικα για μακÏοεντολή '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - ΔιαχειÏιστής ΠÏόσθετων: μια διαδικασία εÏγασίας απέτυχε να ολοκληÏωθεί κατά τη λήψη του {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Από {num_macros} μακÏοεντολές, {num_failed} έληξε το χÏονικό ÏŒÏιο κατά την επεξεÏγασία - - - - Addon Manager: a worker process failed to halt ({name}) - ΔιαχειÏιστής ΠÏόσθετων: μια διαδικασία εÏγασίας απέτυχε να σταματήσει ({name}) - - - - Timeout while fetching metadata for macro {} - Λήξη χÏÎ¿Î½Î¹ÎºÎ¿Ï Î¿Ïίου κατά την ανάκτηση μεταδεδομένων για μακÏοεντολή {} - - - - Failed to kill process for macro {}! - - Αποτυχία τεÏÎ¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Ï„Î·Ï‚ διαδικασίας για τη μακÏοεντολή {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Αποτυχία λήψης στατιστικών στοιχείων ΠÏόσθετου από το {} -- μόνο η αλφαβητική ταξινόμηση θα είναι ακÏιβής - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Αποτυχία λήψης βαθμολογίας Ï€Ïόσθετου από '{}' -- η ταξινόμηση κατά βαθμολογία θα αποτÏχει - - - - - Repository URL - Preferences header for custom repositories - URL ΧώÏου Αποθήκευσης - - - - Branch name - Preferences header for custom repositories - Όνομα κλάδου - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - ΔημιουÏγία αντιγÏάφων ασφαλείας του αÏÏ‡Î¹ÎºÎ¿Ï ÎºÎ±Ï„Î±Î»ÏŒÎ³Î¿Ï… και επανα-κλωνοποίηση - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Η μετονομασία κλάδων Git απέτυχε με το ακόλουθο μήνυμα: - - - - Installing - Εγκατάσταση - - - - Succeeded - ΕπιτεÏχθηκε - - - - Failed - Απέτυχε - - - - Update was cancelled - ΑκÏÏωση ΕνημέÏωσης - - - - some addons may have been updated - κάποια Ï€Ïόσθετα μποÏεί να έχουν ενημεÏωθεί - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - ΦόÏτωση πληÏοφοÏιών για το {} από το wiki μακÏοεντολών FreeCAD... - - - - Loading page for {} from {}... - ΦόÏτωση σελίδας για {} από {}... - - - - Failed to download data from {} -- received response code {}. - Αποτυχία λήψης δεδομένων από {} -- κωδικός απάντησης {}. - - - - Composite view - ΣÏνθετη Ï€Ïοβολή - - - - Expanded view - Εκτεταμένη Ï€Ïοβολή - - - - Compact view - Συνεπτυγμένη Ï€Ïοβολή - - - - Alphabetical - Sort order - Αλφαβητικά - - - - Last Updated - Sort order - Τελευταία ΕνημέÏωση - - - - Date Created - Sort order - ΗμεÏομηνία ΔημιουÏγίας - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Βαθμολογία - - - - Std_AddonMgr - - - &Addon manager - &ΔιαχειÏιστής ΠÏόσθετων - - - - Manage external workbenches, macros, and preference packs - ΔιαχείÏιση εξωτεÏικών πάγκων εÏγασίας, μακÏοεντολών και πακέτων Ï€Ïοτιμήσεων - - - - AddonInstaller - - - Finished removing {} - ΟλοκληÏώθηκε η αφαίÏεση {} - - - - Failed to remove some files - Αποτυχία κατάÏγησης μεÏικών αÏχείων - - - - Addons installer - - - Finished updating the following addons - ΟλοκληÏώθηκε η ενημέÏωση των ακόλουθων ΠÏόσθετων - - - - Workbench - - - Auto-Created Macro Toolbar - ΓÏαμμή εÏγαλείων μακÏοεντολών που δημιουÏγήθηκε αυτόματα - - - - QObject - - - Addon Manager - ΔιαχειÏιστής ΠÏόσθετων - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.qm deleted file mode 100644 index a79c430e5e1192933f569ed3e20748d5687ee3ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74062 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.ts deleted file mode 100644 index 1b50b201da..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_es-AR.ts +++ /dev/null @@ -1,2485 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Repositorio personalizado - - - - Repository URL - URL del repositorio - - - - Branch - Rama - - - - CompactView - - - - Icon - Ãcono - - - - - <b>Package Name</b> - <b>Nombre del paquete</b> - - - - - Version - Versión - - - - - Description - Descripción - - - - Update Available - Actualización disponible - - - - UpdateAvailable - Actualización disponible - - - - DependencyDialog - - - Dependencies - Dependencias - - - - Dependency type - Tipo de dependencia - - - - Name - Nombre - - - - Optional? - Opcional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolver dependencias - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Este complemento tiene las siguientes dependencias requeridas y opcionales. Debes instalarlas antes de que este complemento pueda ser usado. - -¿Quieres que el gestor de complementos los instale automáticamente? Elige "Ignorar" para instalar el complemento sin instalar las dependencias. - - - - FreeCAD Addons - Complementos FreeCAD - - - - Required Python modules - Módulos Python requeridos - - - - Optional Python modules - Módulos Python opcionales - - - - DeveloperModeDialog - - - Addon Developer Tools - Herramientas de desarrollo de complementos - - - - Path to Addon - Ruta al complemento - - - - - Browse... - Navegar... - - - - Metadata - Metadatos - - - - Primary branch - Rama primaria - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explicación de lo que proporciona este complemento. Se muestra en el administrador de complementos. No es necesario que esto indique que este es un complemento de FreeCAD. - - - - Description - Descripción - - - - Discussion URL - URL de discusión - - - - Icon - Ãcono - - - - Bugtracker URL - URL del Bugtracker - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilos semánticos (1.2.3-beta) o CalVer (2022.08.30) compatibles - - - - Set to today (CalVer style) - Establecer al día de hoy (estilo CalVer) - - - - - - - (Optional) - (Opcional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Se muestra en la lista del Administrador de complemento's. No debe incluir la palabra "FreeCAD", y debe ser un nombre de directorio válido en todos los sistemas operativos soportados. - - - - README URL - URL del Léame - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - NOTA: Puesto que esto se muestra en FreeCAD, en el Administrador de Complementos, no es necesario ocupar espacio diciendo cosas como "Este es un complemento FreeCAD..." -- simplemente diga lo que hace. - - - - Repository URL - URL del repositorio - - - - Website URL - URL del sitio web - - - - Documentation URL - URL de la documentación - - - - Addon Name - Nombre del complemento - - - - Version - Versión - - - - (Recommended) - (Recomendado) - - - - Minimum Python - Python mínimo - - - - (Optional, only 3.x version supported) - (Opcional, solamente se admite la versión 3.x) - - - - Detect... - Detectar... - - - - Addon Contents - Contenidos del complemento - - - - Dialog - - - Addon Manager - Administrador de Complementos - - - - Edit Tags - Editar etiquetas - - - - Comma-separated list of tags describing this item: - Lista separada por comas de etiquetas que describen este elemento: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - PISTA: Las etiquetas comunes incluyen "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Administrador de complementos: ¡Advertencia! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - El Administrador de complementos proporciona acceso a una amplia biblioteca de útiles extensiones de terceros para FreeCAD. No se pueden ofrecer garantías sobre su seguridad o funcionalidad. - - - - Continue - Continuo - - - - Cancel - Cancelar - - - - EditDependencyDialog - - - Edit Dependency - Editar dependencias - - - - Dependency Type - Tipo de dependencia - - - - Dependency - Dependencia - - - - Package name, if "Other..." - Nombre del paquete, si "Otro..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTA: Si "Otros..." está seleccionado, el paquete no está en el archivo ALLOWED_PYTHON_PACKAGES.txt y no será instalado automáticamente por el administrador de complementos. Envía un PR en <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> para solicitar la adición de un paquete. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Si esta es una dependencia opcional, el administrador de complementos ofrecerá instalarla (cuando sea posible), pero no bloqueará la instalación si el usuario elige o no puede instalar el paquete. - - - - Optional - Opcional - - - - ExpandedView - - - - Icon - Ãcono - - - - - <h1>Package Name</h1> - <h1>Nombre del paquete</h1> - - - - - Version - Versión - - - - - (tags) - (etiquetas) - - - - - Description - Descripción - - - - - Maintainer - Mantenedor - - - - Update Available - Actualización disponible - - - - labelSort - Ordenar por etiquetas - - - - UpdateAvailable - Actualización disponible - - - - Form - - - Licenses - Licencias - - - - License - Licencia - - - - License file - Archivo de licencia - - - - People - Personas - - - - Kind - Tipo - - - - Name - Nombre - - - - Email - Correo electrónico - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Mapeo avanzado de versión - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Las próximas versiones del administrador de complementos de FreeCAD soportarán que los desarrolladores configuren una rama o etiqueta específica para su uso con una versión específica de FreeCAD (ej. establecer una etiqueta específica como la última versión de su complemento para soportar v0.19, etc.) - - - - FreeCAD Version - Versión de FreeCAD - - - - Best-available branch, tag, or commit - Mejor rama, etiqueta o confirmación - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versiones FreeCAD soportadas - - - - Minimum FreeCAD Version Supported - Versión mínima de FreeCAD soportada - - - - - Optional - Opcional - - - - Maximum FreeCAD Version Supported - Versión máxima de FreeCAD soportada - - - - Advanced version mapping... - Mapeo avanzado de versión... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opciones del administrador de complementos - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Si se selecciona esta opción, al ejecutar el Administrador de Complementos, -los complementos instalados se comprobarán si hay actualizaciones disponibles - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Descargar metadatos de macros (aproximadamente 10MB) - - - - Cache update frequency - Frecuencia de actualización del caché - - - - Manual (no automatic updates) - Manual (sin actualizaciones automáticas) - - - - Daily - Diariamente - - - - Weekly - Semanal - - - - Hide Addons without a license - Ocultar complementos sin licencia - - - - Hide Addons with non-FSF Free/Libre license - Ocultar complementos con licencia libre sin FSF - - - - Hide Addons with non-OSI-approved license - Ocultar complementos con licencia no aprobada OSI - - - - Hide Addons marked Python 2 Only - Ocultar complementos marcados Python 2 solamente - - - - Hide Addons marked Obsolete - Ocultar complementos marcados como obsoletos - - - - Hide Addons that require a newer version of FreeCAD - Ocultar complementos que requieren una versión más reciente de FreeCAD - - - - Custom repositories - Repositorios personalizados - - - - Proxy - Proxy - - - - No proxy - Sin proxy - - - - User system proxy - Proxy del sistema de usuario - - - - User-defined proxy: - Proxy definido por el usuario: - - - - Score source URL - URL de la fuente de puntuación - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - La URL para los datos de la puntuación del complemento (ver página de la Wiki del Administrador de Complementos para el formato y los detalles del alojamiento). - - - - Path to Git executable (optional): - Ruta al ejecutable de Git (opcional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opciones avanzadas - - - - Activate Addon Manager options intended for developers of new Addons. - Activar opciones del Administrador de Complementos destinadas a los desarrolladores de nuevos complementos. - - - - Addon developer mode - Modo de desarrollador de complementos - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Desinstala un macro o banco de trabajo seleccionado - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Update - Actualizar - - - - Run Macro - Ejecutar Macro - - - - Change branch - Cambiar rama - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Administrar dependencias de Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Los siguientes paquetes de Python han sido instalados localmente por el administrador de complementos para satisfacer las dependencias del complemento. Ubicación de la instalación: - - - - Package name - Nombre del paquete - - - - Installed version - Versión instalada - - - - Available version - Versión disponible - - - - Used by - Usado por - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Un asterisco (*) en la columna "Usado por" columna indica una dependencia opcional. Nota: Tenga en cuenta que sólo se utiliza para registrar las importaciones directas en el complemento. Otros paquetes Python de los que dependen pueden haber sido instalados también. - - - - Update all available - Instalar todas las actualizaciones disponibles - - - - SelectFromList - - - Dialog - Diálogo - - - - TextLabel - EtiquetaTexto - - - - UpdateAllDialog - - - Updating Addons - Actualización de Complementos o Extensiones - - - - Updating out-of-date addons... - Actualizando complementos obsoletos - - - - addContentDialog - - - Content Item - Elementos de contenido - - - - Content type: - Tipo de contenido: - - - - Macro - Macro - - - - Preference Pack - Paquete de preferencias - - - - Workbench - Banco de trabajo - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Si esto es lo único en el complemento, todos los otros metadatos pueden ser heredados desde el nivel superior, y no necesita ser especificado aquí. - - - - This is the only item in the Addon - Este es el único elemento del complemento - - - - Main macro file - Archivo de macro principal - - - - The file with the macro's metadata in it - El archivo con los metadatos de macro's en él - - - - - - Browse... - Navegar... - - - - Preference Pack Name - Nombre del paquete de preferencias - - - - Workbench class name - Nombre de la clase del banco de trabajo - - - - Class that defines "Icon" data member - Clase que define el "ícono" de miembro de datos - - - - Subdirectory - Subdirectorio - - - - Optional, defaults to name of content item - Opcional, el valor predeterminado es el nombre del elemento de contenido - - - - Icon - Ãcono - - - - Optional, defaults to inheriting from top-level Addon - Opcional, el valor por defecto es heredado del complemento de nivel superior - - - - Tags... - Etiquetas... - - - - Dependencies... - Dependencias... - - - - FreeCAD Versions... - Versiones de FreeCAD... - - - - Other Metadata - Otros metadatos - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Mostrado en la lista de complementos del administrador de complementos. No debe incluir la palabra "FreeCAD". - - - - Version - Versión - - - - Description - Descripción - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilos semánticos (1.2.3-beta) o CalVer (2022.08.30) compatibles - - - - Set to today (CalVer style) - Establecer al día de hoy (estilo CalVer) - - - - Display Name - Mostrar Nombre - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Los campos que se dejan en blanco se heredan de los metadatos del complemento de nivel superior, por lo que técnicamente son todos opcionales. Para complementos con varios elementos de contenido, cada elemento debe proporcionar un nombre y una descripción únicos. - - - - add_toolbar_button_dialog - - - Add button? - ¿Añadir botón? - - - - Add a toolbar button for this macro? - ¿Añadir un botón de barra de herramientas para esta macro? - - - - Yes - Sí - - - - No - No - - - - Never - Nunca - - - - change_branch - - - Change Branch - Cambiar Rama - - - - Change to branch: - Cambiar a rama: - - - - copyrightInformationDialog - - - Copyright Information - Información de derechos de autor - - - - Copyright holder: - Titular de derechos de autor: - - - - Copyright year: - Año de copyright: - - - - personDialog - - - Add Person - Añadir persona - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Un mantenedor es alguien con acceso actual al commit en este proyecto. Un autor es cualquiera más al que te gustaría dar crédito. - - - - Name: - Nombre: - - - - Email: - Correo electrónico: - - - - Email is required for maintainers, and optional for authors. - Se requiere correo electrónico para los mantenedores, y opcional para los autores. - - - - proxy_authentication - - - Proxy login required - Se requiere inicio de sesión del proxy - - - - Proxy requires authentication - El proxy requiere autenticación - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Marcador de posición para la dirección del proxy - - - - Realm: - Dominio: - - - - Placeholder for proxy realm - Marcador de posición para el domino proxy - - - - Username - Usuario - - - - Password - Contraseña - - - - selectLicenseDialog - - - Select a license - Seleccionar una licencia - - - - About... - Acerca... - - - - License name: - Nombre de la licencia: - - - - Path to license file: - Ruta de acceso al archivo de licencia: - - - - (if required by license) - (si es requerido por la licencia) - - - - Browse... - Navegar... - - - - Create... - Crear... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Seleccionar barra de herramientas - - - - Select a toolbar to add this macro to: - Seleccione una barra de herramientas para añadir esta macro a: - - - - Ask every time - Preguntar cada vez - - - - toolbar_button - - - - Add button? - ¿Añadir botón? - - - - Add a toolbar button for this macro? - ¿Añadir un botón de barra de herramientas para esta macro? - - - - Yes - Sí - - - - No - No - - - - Never - Nunca - - - - AddonsInstaller - - - Starting up... - Iniciando... - - - - Worker process {} is taking a long time to stop... - Proceso en ejecución {} está tomando mucho tiempo en culminar. - - - - Previous cache process was interrupted, restarting... - - El proceso en memoria anterior fue interrumpido, reiniciando... - - - - Custom repo list changed, forcing recache... - - Se cambió la lista personalizada de repositorios, forzando carga en memoria... - - - - Addon manager - Administrador de complementos - - - - You must restart FreeCAD for changes to take effect. - Debe reiniciar FreeCAD para que los cambios surtan efecto. - - - - Restart now - Reiniciar ahora - - - - Restart later - Reiniciar más adelante - - - - - Refresh local cache - Actualizar caché local - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Actualizando la información en memoria - - - - - Checking for updates... - Buscando actualizaciones... - - - - Temporary installation of macro failed. - La instalación temporal de la macro falló. - - - - - Close - Cerrar - - - - Update all addons - Actualizar todos los complementos - - - - Check for updates - Comprobar actualizaciones - - - - Python dependencies... - Dependencias de Python... - - - - Developer tools... - Herramientas del desarrollador... - - - - Apply %n available update(s) - Aplicar %n actualización(es) disponible(s) - - - - No updates available - No hay actualizaciones disponibles - - - - - - Cannot launch a new installer until the previous one has finished. - No se puede iniciar un nuevo instalador hasta que el anterior haya terminado. - - - - - - - Maintainer - Mantenedor - - - - - - - Author - Autor - - - - New Python Version Detected - Nueva versión de Python detectada - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Esta parece ser la primera vez que esta versión de Python se usa con el Administrador de Complementos. ¿Quiere instalar las mismas dependencias autoinstaladas? - - - - Processing, please wait... - Procesando, por favor, espere... - - - - - Update - Actualizar - - - - Updating... - Actualizando... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - No se pudo importar QtNetwork -- parece que no está instalado en su sistema. Su proveedor puede tener un paquete para esta dependencia (a menudo llamado "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Error al convertir el puerto proxy especificado '{}' a un número de puerto - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Error de parámetro: conjunto de opciones de proxy mutuamente exclusivas. Reiniciando a valores predeterminados. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Error de parámetro: se indicado proxy de usuario pero no se proporcionó proxy. Reiniciando al valor predeterminado. - - - - Addon Manager: Unexpected {} response from server - Administrador de complementos: Respuesta {} inesperada del servidor - - - - Error with encrypted connection - Error con conexión cifrada - - - - - - Confirm remove - Confirmar eliminación - - - - Are you sure you want to uninstall {}? - ¿Está seguro que desea desinstalar {}? - - - - - - Removing Addon - Eliminando complemento - - - - Removing {} - Eliminando {} - - - - - Uninstall complete - Desinstalación completa - - - - - Uninstall failed - Desinstalación fallida - - - - Version {version} installed on {date} - Versión {version} instalada el {date} - - - - Version {version} installed - Versión {version} instalada - - - - Installed on {date} - Instalado el {date} - - - - - - - Installed - Instalado - - - - Currently on branch {}, name changed to {} - Actualmente en la rama {}, nombre cambiado a {} - - - - Git tag '{}' checked out, no updates possible - Etiqueta Git '{}' marcada, no es posible actualizar - - - - Update check in progress - Comprobación de actualizaciones en progreso - - - - Installation location - Ubicación de instalación - - - - Repository URL - URL del repositorio - - - - Changed to branch '{}' -- please restart to use Addon. - Cambiado a rama '{}' -- por favor reinicie para usar el complemento. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Este complemento ha sido actualizado. Reinicie FreeCAD para ver los cambios. - - - - Disabled - Deshabilitado - - - - Currently on branch {}, update available to version {} - Actualmente en la rama {}, actualización disponible a la versión {} - - - - Update available to version {} - Actualización disponible a la versión {} - - - - This is the latest version available - Esta es la última versión disponible - - - - WARNING: This addon is obsolete - ATENCIÓN: Este complemento está obsoleto - - - - WARNING: This addon is Python 2 only - ADVERTENCIA: Este complemento es sólo Python 2 - - - - WARNING: This addon requires FreeCAD {} - ADVERTENCIA: Este complemento requiere FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ADVERTENCIA: Este complemento está actualmente instalado, pero desactivado. Utilice el botón 'habilitar' para reactivarlo. - - - - This Addon will be enabled next time you restart FreeCAD. - Este complemento se habilitará la próxima vez que reinicie FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Este complemento se desactivará la próxima vez que reinicie FreeCAD. - - - - - - Success - Éxito - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Enable - Habilitar - - - - Disable - Desactivar - - - - - Check for update - Buscar actualizaciones - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Ejecutar - - - - Change branch... - Cambiar rama... - - - - Return to package list - Volver a la lista de paquetes - - - - Checking connection - Comprobando conexión - - - - Checking for connection to GitHub... - Comprobando conexión a GitHub... - - - - Connection failed - Conexión fallida - - - - Missing dependency - Falta dependencia - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - No se pudo importar QtNetwork -- vea la vista de informes para más detalles. Administrador de complementos no disponible. - - - - Other... - For providing a license other than one listed - Otros... - - - - Select the corresponding license file in your Addon - Seleccione el archivo de licencia correspondiente en su complemento - - - - Location for new license file - Ubicación del nuevo archivo de licencia - - - - Received {} response code from server - Recibido {} código de respuesta del servidor - - - - Failed to install macro {} - Error al instalar macro {} - - - - Failed to create installation manifest file: - - Error al crear archivo manifest de instalación: - - - - - Unrecognized content kind '{}' - Tipo de contenido no reconocido '{}' - - - - Unable to locate icon at {} - No se puede localizar el icono en {} - - - - Select an icon file for this content item - Seleccione un archivo de icono para este elemento de contenido - - - - - - {} is not a subdirectory of {} - {} no es un subdirectorio de {} - - - - Select the subdirectory for this content item - Seleccione el subdirectorio para este artículo de contenido - - - - Automatic - Automático - - - - - Workbench - Banco de trabajo - - - - Addon - Complemento - - - - Python - Python - - - - Yes - Sí - - - - Internal Workbench - Banco de trabajo - - - - External Addon - Complemento externo - - - - Python Package - Paquete de Python - - - - - Other... - Otros... - - - - Too many to list - Demasiado para enlistar - - - - - - - - - Missing Requirement - Requisitos faltantes - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - El complemento '{}' requiere '{}', el cual no está disponible en su copia de FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - El complemento '{}' requiere los siguientes bancos de trabajo, los cuales no están disponibles en su copia de FreeCAD: - - - - Press OK to install anyway. - Pulse OK para instalar de todos modos. - - - - - Incompatible Python version - Versión de Python incompatible - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Este complemento requiere paquetes de Python que no están instalados y no se pueden instalar automáticamente. Para utilizar este complemento debe instalar manualmente los siguientes paquetes de Python: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Este complemento (o una de sus dependencias) requiere Python {}.{}, y su sistema está ejecutando {}.{}. La instalación ha sido cancelada. - - - - Optional dependency on {} ignored because it is not in the allow-list - Dependencia opcional de {} ignorada porque no está en la lista permitida - - - - - Installing dependencies - Instalando dependencias - - - - - Cannot execute Python - No se puede ejecutar Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - No se pudo localizar automáticamente el ejecutable de Python, o la ruta está configurada incorrectamente. Por favor, compruebe la configuración de preferencias del administrador de complementos para la ruta a Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - No se pudieron instalar las dependencias. ¿Continuar con la instalación de {} de cualquier forma? - - - - - Cannot execute pip - No se puede ejecutar pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Fallo al ejecutar pip, podría faltar en tu instalación de Python. Por favor, asegúrese de que su sistema tiene pip instalado y vuelva a intentarlo. El comando fallido fue: - - - - - Continue with installation of {} anyway? - ¿Continuar con la instalación de {} de todos modos? - - - - - Package installation failed - Error al instalar el paquete - - - - See Report View for detailed failure log. - Consulte Ver Informe para registro detallado de errores. - - - - Installing Addon - Instalando Complemento - - - - Installing FreeCAD Addon '{}' - Instalando complemento de FreeCAD '{}' - - - - Cancelling - Cancelando - - - - Cancelling installation of '{}' - Cancelando instalación de '{}' - - - - {} was installed successfully - {} fue instalado satisfactoriamente - - - - - Installation Failed - Instalación fallida - - - - Failed to install {} - Error al instalar {} - - - - - Create new toolbar - Crear nueva barra de herramientas - - - - - A macro installed with the FreeCAD Addon Manager - Una macro instalada con el Administrador de Complementos de FreeCAD - - - - - Run - Indicates a macro that can be 'run' - Ejecutar - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - No se han podido leer los datos de GitHub: comprueba tu conexión a Internet y la configuración del proxy e intente de nuevo. - - - - XML failure while reading metadata from file {} - Fallo en archivo XML mientras se leían los metadatos del archivo {} - - - - Invalid metadata in file {} - Metadatos no válidos en el archivo {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - PRECAUCIÓN: La ruta especificada en los metadatos de package.xml no coincide con la rama que se ha realizado actualmente. - - - - Name - Nombre - - - - Class - Clase - - - - Description - Descripción - - - - Subdirectory - Subdirectorio - - - - Files - Archivos - - - - Select the folder containing your Addon - Seleccione la carpeta que contiene su complemento - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Sin Vermin, cancelando operación. - - - - Scanning Addon for Python version compatibility - Examinando el complemento para compatibilidad con la versión de Python - - - - Minimum Python Version Detected - Versión mínima de Python detectada - - - - Vermin auto-detected a required version of Python 3.{} - Vermin ha detectado una versión requerida de Python 3.{} - - - - Install Vermin? - ¿Instalar Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Para detectar automáticamente la versión requerida de Python para este complemento requiere Vermin (https://pypi.org/project/vermin/). ¿Acepta la instalación? - - - - Attempting to install Vermin from PyPi - Intentando instalar Vermin desde PyPi - - - - - Installation failed - Instalación fallida - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Error al instalar Vermin -- compruebe la vista del informe para más detalles. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Error al importar Vermin después de la instalación -- no se puede escanear el complemento. - - - - Select an icon file for this package - Seleccione un ícono para este paquete - - - - Filter is valid - El filtro es válido - - - - Filter regular expression is invalid - La expresión regular del filtro no es válida - - - - Search... - Búsqueda... - - - - Click for details about package {} - Haga clic para obtener detalles sobre el paquete {} - - - - Click for details about workbench {} - Haga clic para obtener detalles sobre el banco de trabajo {} - - - - Click for details about macro {} - Haga clic para obtener detalles sobre la macro {} - - - - Maintainers: - Mantenedores: - - - - Tags - Etiquetas - - - - {} ★ on GitHub - {} ★ en GitHub - - - - No ★, or not on GitHub - Sin ★ o no en GitHub - - - - Created - Creado - - - - Updated - Actualizado - - - - Score: - Puntuación: - - - - - Up-to-date - Al día - - - - - - - - Update available - Actualización disponible - - - - - Pending restart - Reinicio pendiente - - - - - DISABLED - DESHABILITADO - - - - Installed version - Versión instalada - - - - Unknown version - Versión desconocida - - - - Installed on - Instalado el - - - - Available version - Versión disponible - - - - Filter by... - Filtrar por... - - - - Addon Type - Tipo de complemento - - - - - Any - Cualquiera - - - - Macro - Macro - - - - Preference Pack - Paquete de preferencias - - - - Installation Status - Estado de la instalación - - - - Not installed - No instalado - - - - Filter - Filtro - - - - DANGER: Developer feature - PELIGRO: Función de desarrollador - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - PELIGRO: Cambiar las ramas está destinado para desarrolladores y beta testers y puede resultar en rupturas, documentos no compatibles hacia atrás, inestabilidad, cierres abruptos y/o la prematura muerte térmica del universo. ¿Está seguro de que desea continuar? - - - - There are local changes - Hay cambios locales - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ADVERTENCIA: Este repositorio tiene cambios locales no confirmados. ¿Está seguro que desea cambiar de rama (trayendo los cambios contigo)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Rastreo remoto - - - - Last Updated - Table header for git update date - Última actualización - - - - Installation of Python package {} failed - La instalación del paquete de Python {} falló - - - - Installation of optional package failed - La instalación del paquete opcional falló - - - - Installing required dependency {} - Instalando dependencia requerida {} - - - - Installation of Addon {} failed - La instalación del complemento {} falló - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Error al decodificar archivo {} para el complemento '{}' - - - - Any dependency information in this file will be ignored - Cualquier información de dependencia en este archivo será ignorada - - - - Unable to open macro wiki page at {} - No se puede abrir la página de la wiki de la macro en {} - - - - Unable to fetch the code of this macro. - No se puede obtener el código de esta macro. - - - - Unable to retrieve a description from the wiki for macro {} - No se puede recuperar una descripción de la wiki para la macro {} - - - - Unable to open macro code URL {} - No se puede abrir la URL del código de la macro {} - - - - Unable to fetch macro-specified file {} from {} - No se puede obtener el archivo especificado macro {} de {} - - - - Could not locate macro-specified file {} (expected at {}) - No se pudo encontrar el archivo especificado macro {} (se esperaba en {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Banco de trabajo interno no reconocido '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Advertencia de desarrollador de complementos: la URL del repositorio establecida en el archivo package.xml para el complemento {} ({}) no coincide con la URL de la que fue obtenida ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Advertencia de desarrollador de complementos: la rama de repositorio establecida en el archivo package.xml para el complemento {} ({}) no coincide con la rama de la que fue obtenida ({}) - - - - - Got an error when trying to import {} - Se ha producido un error al intentar importar {} - - - - An unknown error occurred - Se produjo un error desconocido - - - - Could not find addon {} to remove it. - No se pudo encontrar el complemento {} para eliminarlo. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Falló la ejecución del script uninstall.py del complemento. Procediendo con la desinstalación... - - - - Removed extra installed file {} - Archivo extra instalado {} eliminado - - - - Error while trying to remove extra installed file {} - Error al intentar eliminar el archivo extra instalado {} - - - - Error while trying to remove macro file {}: - Error al intentar eliminar el archivo macro {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Error al conectar a GitHub. Compruebe su conexión y configuración de proxy. - - - - WARNING: Duplicate addon {} ignored - ADVERTENCIA: Duplicar complemento {} ignorado - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Se ha producido un error al actualizar macros desde GitHub, intentando limpiar el checkout... - - - - Attempting to do a clean checkout... - Intentando hacer una comprobación limpia... - - - - Clean checkout succeeded - Comprobación limpia exitosa - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Error al actualizar macros de GitHub -- intente limpiar la caché del administrador de complementos. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error al conectar a la Wiki, FreeCAD no puede recuperar la lista de macros de la Wiki en este momento - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Error al leer los metadatos de {name} - - - - Failed to fetch code for macro '{name}' - Error al obtener el código para el macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Administrador de complementos: no se pudo completar un proceso al obtener {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - De {num_macros} macros, a {num_failed} se les agotó el tiempo durante el procesamiento - - - - Addon Manager: a worker process failed to halt ({name}) - Administrador de complementos: un proceso de trabajo falló al detenerse ({name}) - - - - Timeout while fetching metadata for macro {} - Tiempo de espera agotado al buscar metadatos para la macro {} - - - - Failed to kill process for macro {}! - - ¡Error al matar el proceso para macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Error al obtener estadísticas del complemento de {} -- solo ordenar alfabeticamente será preciso - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - No se pudo obtener la puntuación del complemento de '{}' -- ordenar por puntuación fallará - - - - - Repository URL - Preferences header for custom repositories - URL del repositorio - - - - Branch name - Preferences header for custom repositories - Nombre de rama - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Copia de seguridad del directorio original y re-clonando - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Error al renombrar la rama Git con el siguiente mensaje: - - - - Installing - Instalando - - - - Succeeded - Éxito - - - - Failed - Falló - - - - Update was cancelled - Actualización cancelada - - - - some addons may have been updated - algunos complementos pueden haber sido actualizados - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Cargando información para {} de la wiki de Recetas de Macros de FreeCAD... - - - - Loading page for {} from {}... - Cargando página para {} desde {}... - - - - Failed to download data from {} -- received response code {}. - Error al descargar datos de {} -- código de respuesta recibido {}. - - - - Composite view - Vista compuesta - - - - Expanded view - Vista extendida - - - - Compact view - Vista compacta - - - - Alphabetical - Sort order - Alfabético - - - - Last Updated - Sort order - Última actualización - - - - Date Created - Sort order - Fecha de creación - - - - GitHub Stars - Sort order - Estrellas de GitHub - - - - Score - Sort order - Puntaje - - - - Std_AddonMgr - - - &Addon manager - &Administrador de complementos - - - - Manage external workbenches, macros, and preference packs - Administrar bancos de trabajo externos, macros y paquetes de preferencias - - - - AddonInstaller - - - Finished removing {} - Se terminó de eliminar {} - - - - Failed to remove some files - Error al eliminar algunos archivos - - - - Addons installer - - - Finished updating the following addons - Finalizó la actualización de los siguientes complementos - - - - Workbench - - - Auto-Created Macro Toolbar - Barra de herramientas de macro creada automáticamente - - - - QObject - - - Addon Manager - Administrador de Complementos - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.qm deleted file mode 100644 index d57db3806f74ad176625062b3bb10b4f9c97a282..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74200 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"bPSdWao%6^I=uj~-HexzAA&#q~ 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.ts deleted file mode 100644 index 2557902758..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_es-ES.ts +++ /dev/null @@ -1,2485 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Repositorio personalizado - - - - Repository URL - URL del repositorio - - - - Branch - Rama - - - - CompactView - - - - Icon - Icono - - - - - <b>Package Name</b> - <b>Nombre del paquete</b> - - - - - Version - Versión - - - - - Description - Descripción - - - - Update Available - Actualización disponible - - - - UpdateAvailable - Actualización disponible - - - - DependencyDialog - - - Dependencies - Dependencias - - - - Dependency type - Tipo de dependencia - - - - Name - Nombre - - - - Optional? - ¿Opcional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolver dependencias - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Este complemento tiene las siguientes dependencias requeridas y opcionales. Debe instalarlas antes de que este complemento pueda ser usado. - -¿Quiere que el administrador de complementos los instale automáticamente? Elija "Ignorar" para instalar el complemento sin instalar las dependencias. - - - - FreeCAD Addons - Complementos de FreeCAD - - - - Required Python modules - Módulos Python requeridos - - - - Optional Python modules - Módulos Python opcionales - - - - DeveloperModeDialog - - - Addon Developer Tools - Herramientas de desarrollo de complementos - - - - Path to Addon - Ruta al complemento - - - - - Browse... - Examinar... - - - - Metadata - Metadatos - - - - Primary branch - Rama primaria - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explicación de lo que proporciona este complemento. Se muestra en el administrador de complementos. No es necesario que esto indique que este es un complemento de FreeCAD. - - - - Description - Descripción - - - - Discussion URL - URL de discusión - - - - Icon - Icono - - - - Bugtracker URL - URL del Bugtracker - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilos semánticos (1.2.3-beta) o CalVer (2022.08.30) compatibles - - - - Set to today (CalVer style) - Establecer al día de hoy (estilo CalVer) - - - - - - - (Optional) - (Opcional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Se muestra en la lista de complementos del administrador de complementos. No debe incluir la palabra "FreeCAD", y debe ser un nombre de directorio válido en todos los sistemas operativos soportados. - - - - README URL - URL del Léame - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Dado que esto se muestra en FreeCAD, en el administrador de complementos, no es necesario ocupar espacio diciendo cosas como "Este es un complemento FreeCAD...." -- simplemente mencione lo que hace. - - - - Repository URL - URL del repositorio - - - - Website URL - URL del sitio web - - - - Documentation URL - URL de la documentación - - - - Addon Name - Nombre del complemento - - - - Version - Versión - - - - (Recommended) - (Recomendado) - - - - Minimum Python - Python mínimo - - - - (Optional, only 3.x version supported) - (Opcional, sólo se admite la versión 3.x) - - - - Detect... - Detectar... - - - - Addon Contents - Contenidos del complemento - - - - Dialog - - - Addon Manager - Administrador de complementos - - - - Edit Tags - Editar etiquetas - - - - Comma-separated list of tags describing this item: - Listado separado por comas de etiquetas que describen este elemento: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - PISTA: Las etiquetas comunes incluyen "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Administrador de complementos: ¡Advertencia! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - El Administrador de complementos proporciona acceso a una amplia biblioteca de útiles extensiones de terceros para FreeCAD. No se pueden ofrecer garantías sobre su seguridad o funcionalidad. - - - - Continue - Continuar - - - - Cancel - Cancelar - - - - EditDependencyDialog - - - Edit Dependency - Editar dependencias - - - - Dependency Type - Tipo de dependencia - - - - Dependency - Dependencia - - - - Package name, if "Other..." - Nombre del paquete, si "Otro..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTA: Si "Otros..." está seleccionado, el paquete no está en el archivo ALLOWED_PYTHON_PACKAGES.txt y no será instalado automáticamente por el administrador de complementos. Envía un PR en <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> para solicitar la adición de un paquete. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Si esta es una dependencia opcional, el administrador de complementos ofrecerá instalarla (cuando sea posible), pero no bloqueará la instalación si el usuario elige o no puede instalar el paquete. - - - - Optional - Opcional - - - - ExpandedView - - - - Icon - Icono - - - - - <h1>Package Name</h1> - <h1>Nombre del paquete</h1> - - - - - Version - Versión - - - - - (tags) - (etiquetas) - - - - - Description - Descripción - - - - - Maintainer - Mantenedor - - - - Update Available - Actualización disponible - - - - labelSort - Ordenar por etiquetas - - - - UpdateAvailable - Actualización disponible - - - - Form - - - Licenses - Licencias - - - - License - Licencia - - - - License file - Archivo de licencia - - - - People - Personas - - - - Kind - Tipo - - - - Name - Nombre - - - - Email - Correo electrónico - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Mapeo avanzado de versión - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Las próximas versiones del administrador de complementos de FreeCAD soportarán que los desarrolladores configuren una rama o etiqueta específica para su uso con una versión específica de FreeCAD (ej. establecer una etiqueta específica como la última versión de su complemento para soportar v0.19, etc.) - - - - FreeCAD Version - Versión de FreeCAD - - - - Best-available branch, tag, or commit - Mejor rama, etiqueta o confirmación - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versiones FreeCAD soportadas - - - - Minimum FreeCAD Version Supported - Versión mínima de FreeCAD soportada - - - - - Optional - Opcional - - - - Maximum FreeCAD Version Supported - Versión máxima de FreeCAD soportada - - - - Advanced version mapping... - Mapeo avanzado de versión... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opciones del administrador de complementos - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Si se selecciona esta opción, al iniciar el Administrador de Complementos, -se comprobarán los complementos instalados para ver si hay actualizaciones disponibles - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Descargar metadatos de macro (aproximadamente 10MB) - - - - Cache update frequency - Frecuencia de actualización del caché - - - - Manual (no automatic updates) - Manual (sin actualizaciones automáticas) - - - - Daily - Diario - - - - Weekly - Semanal - - - - Hide Addons without a license - Ocultar complementos sin licencia - - - - Hide Addons with non-FSF Free/Libre license - Ocultar complementos con licencia libre sin FSF - - - - Hide Addons with non-OSI-approved license - Ocultar complementos con licencia no aprobada OSI - - - - Hide Addons marked Python 2 Only - Ocultar complementos marcados como sólo Python 2 - - - - Hide Addons marked Obsolete - Ocultar complementos marcados como obsoletos - - - - Hide Addons that require a newer version of FreeCAD - Ocultar complementos que requieran una versión más reciente de FreeCAD - - - - Custom repositories - Repositorios personalizados - - - - Proxy - Proxy - - - - No proxy - Sin proxy - - - - User system proxy - Usar proxy del sistema - - - - User-defined proxy: - Proxy definido por el usuario: - - - - Score source URL - URL de la fuente de puntaje - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - La URL para los datos de la puntuación del complemento (ver página de la Wiki del Administrador de Complementos para el formato y los detalles del alojamiento). - - - - Path to Git executable (optional): - Ruta al ejecutable de Git (opcional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opciones avanzadas - - - - Activate Addon Manager options intended for developers of new Addons. - Activar opciones de administrador de complementos destinadas a los desarrolladores de nuevos complementos. - - - - Addon developer mode - Modo de desarrollador de complementos - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Desinstala un macro o banco de trabajo seleccionado - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Update - Actualizar - - - - Run Macro - Ejecutar Macro - - - - Change branch - Cambiar rama - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Administrar dependencias de Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Los siguientes paquetes de Python han sido instalados localmente por el administrador de complementos para satisfacer las dependencias del complemento. Ubicación de la instalación: - - - - Package name - Nombre del paquete - - - - Installed version - Versión instalada - - - - Available version - Versión disponible - - - - Used by - Usado por - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Un asterisco (*) en la columna "Usado por" columna indica una dependencia opcional. Nota: Tenga en cuenta que sólo se utiliza para registrar las importaciones directas en el complemento. Otros paquetes Python de los que dependen pueden haber sido instalados también. - - - - Update all available - Instalar todas las actualizaciones disponibles - - - - SelectFromList - - - Dialog - Diálogo - - - - TextLabel - Etiqueta Texto - - - - UpdateAllDialog - - - Updating Addons - Actualización de Complementos o Extensiones - - - - Updating out-of-date addons... - Actualizando complementos obsoletos - - - - addContentDialog - - - Content Item - Elementos de contenido - - - - Content type: - Tipo de contenido: - - - - Macro - Macro - - - - Preference Pack - Paquete de preferencias - - - - Workbench - Banco de trabajo - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Si esto es lo único en el complemento, todos los otros metadatos pueden ser heredados desde el nivel superior, y no necesita ser especificado aquí. - - - - This is the only item in the Addon - Este es el único elemento del complemento - - - - Main macro file - Archivo de macro principal - - - - The file with the macro's metadata in it - El archivo con los metadatos de macro's en él - - - - - - Browse... - Examinar... - - - - Preference Pack Name - Nombre del paquete de preferencias - - - - Workbench class name - Nombre de la clase del banco de trabajo - - - - Class that defines "Icon" data member - Clase que define el "ícono" de miembro de datos - - - - Subdirectory - Subdirectorio - - - - Optional, defaults to name of content item - Opcional, el valor predeterminado es el nombre del elemento de contenido - - - - Icon - Icono - - - - Optional, defaults to inheriting from top-level Addon - Opcional, el valor por defecto es heredado del complemento de nivel superior - - - - Tags... - Etiquetas... - - - - Dependencies... - Dependencias... - - - - FreeCAD Versions... - Versiones de FreeCAD... - - - - Other Metadata - Otros metadatos - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Mostrado en la lista de complementos del administrador de complementos. No debe incluir la palabra "FreeCAD". - - - - Version - Versión - - - - Description - Descripción - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilos semánticos (1.2.3-beta) o CalVer (2022.08.30) compatibles - - - - Set to today (CalVer style) - Establecer al día de hoy (estilo CalVer) - - - - Display Name - Mostrar Nombre - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Los campos que se dejan en blanco se heredan de los metadatos del complemento de nivel superior, por lo que técnicamente son todos opcionales. Para complementos con varios elementos de contenido, cada elemento debe proporcionar un nombre y una descripción únicos. - - - - add_toolbar_button_dialog - - - Add button? - ¿Añadir botón? - - - - Add a toolbar button for this macro? - ¿Añadir un botón de barra de herramientas para esta macro? - - - - Yes - Sí - - - - No - No - - - - Never - Nunca - - - - change_branch - - - Change Branch - Cambiar Rama - - - - Change to branch: - Cambiar a rama: - - - - copyrightInformationDialog - - - Copyright Information - Información de derechos de autor - - - - Copyright holder: - Titular de derechos de autor: - - - - Copyright year: - Año de copyright: - - - - personDialog - - - Add Person - Añadir persona - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Un mantenedor es alguien con acceso actual al commit en este proyecto. Un autor es cualquiera más al que te gustaría dar crédito. - - - - Name: - Nombre: - - - - Email: - Correo electrónico: - - - - Email is required for maintainers, and optional for authors. - Se requiere correo electrónico para los mantenedores, y opcional para los autores. - - - - proxy_authentication - - - Proxy login required - Se requiere inicio de sesión del proxy - - - - Proxy requires authentication - El proxy requiere autenticación - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Marcador de posición para la dirección del proxy - - - - Realm: - Dominio: - - - - Placeholder for proxy realm - Marcador de posición para el domino proxy - - - - Username - Usuario - - - - Password - Contraseña - - - - selectLicenseDialog - - - Select a license - Seleccionar una licencia - - - - About... - Acerca... - - - - License name: - Nombre de la licencia: - - - - Path to license file: - Ruta de acceso al archivo de licencia: - - - - (if required by license) - (si es requerido por la licencia) - - - - Browse... - Examinar... - - - - Create... - Crear... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Seleccionar barra de herramientas - - - - Select a toolbar to add this macro to: - Seleccione una barra de herramientas para añadir esta macro a: - - - - Ask every time - Preguntar cada vez - - - - toolbar_button - - - - Add button? - ¿Añadir botón? - - - - Add a toolbar button for this macro? - ¿Añadir un botón de barra de herramientas para esta macro? - - - - Yes - Sí - - - - No - No - - - - Never - Nunca - - - - AddonsInstaller - - - Starting up... - Iniciando... - - - - Worker process {} is taking a long time to stop... - Proceso en ejecución {} está tomando mucho tiempo en culminar. - - - - Previous cache process was interrupted, restarting... - - El proceso en memoria anterior fue interrumpido, reiniciando... - - - - Custom repo list changed, forcing recache... - - Se cambió la lista personalizada de repositorios, forzando carga en memoria... - - - - Addon manager - Administrador de complementos - - - - You must restart FreeCAD for changes to take effect. - Debe reiniciar FreeCAD para que los cambios surtan efecto. - - - - Restart now - Reiniciar ahora - - - - Restart later - Reiniciar más adelante - - - - - Refresh local cache - Actualizar caché local - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Actualizando la información en memoria - - - - - Checking for updates... - Buscando actualizaciones... - - - - Temporary installation of macro failed. - La instalación temporal de la macro falló. - - - - - Close - Cerrar - - - - Update all addons - Actualizar todos los complementos - - - - Check for updates - Comprobar actualizaciones - - - - Python dependencies... - Dependencias de Python... - - - - Developer tools... - Herramientas del desarrollador... - - - - Apply %n available update(s) - Aplicar %n actualización(es) disponible(s) - - - - No updates available - No hay actualizaciones disponibles - - - - - - Cannot launch a new installer until the previous one has finished. - No se puede iniciar un nuevo instalador hasta que el anterior haya terminado. - - - - - - - Maintainer - Mantenedor - - - - - - - Author - Autor - - - - New Python Version Detected - Nueva versión de Python detectada - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Esta parece ser la primera vez que esta versión de Python se usa con el Administrador de Complementos. ¿Quiere instalar las mismas dependencias autoinstaladas? - - - - Processing, please wait... - Procesando, por favor, espere... - - - - - Update - Actualizar - - - - Updating... - Actualizando... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - No se pudo importar QtNetwork -- parece que no está instalado en su sistema. Su proveedor puede tener un paquete para esta dependencia (a menudo llamado "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Error al convertir el puerto proxy especificado '{}' a un número de puerto - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Error de parámetro: conjunto de opciones de proxy mutuamente exclusivas. Reiniciando a valores predeterminados. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Error de parámetro: se indicado proxy de usuario pero no se proporcionó proxy. Reiniciando al valor predeterminado. - - - - Addon Manager: Unexpected {} response from server - Administrador de complementos: Respuesta {} inesperada del servidor - - - - Error with encrypted connection - Error con conexión cifrada - - - - - - Confirm remove - Confirmar eliminación - - - - Are you sure you want to uninstall {}? - ¿Está seguro que desea desinstalar {}? - - - - - - Removing Addon - Eliminando complemento - - - - Removing {} - Eliminando {} - - - - - Uninstall complete - Desinstalación completa - - - - - Uninstall failed - Desinstalación fallida - - - - Version {version} installed on {date} - Versión {version} instalada el {date} - - - - Version {version} installed - Versión {version} instalada - - - - Installed on {date} - Instalado el {date} - - - - - - - Installed - Instalado - - - - Currently on branch {}, name changed to {} - Actualmente en la rama {}, nombre cambiado a {} - - - - Git tag '{}' checked out, no updates possible - Etiqueta Git '{}' marcada, no es posible actualizar - - - - Update check in progress - Comprobación de actualizaciones en progreso - - - - Installation location - Ubicación de instalación - - - - Repository URL - URL del repositorio - - - - Changed to branch '{}' -- please restart to use Addon. - Cambiado a rama '{}' -- por favor reinicie para usar el complemento. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Este complemento ha sido actualizado. Reinicie FreeCAD para ver los cambios. - - - - Disabled - Deshabilitado - - - - Currently on branch {}, update available to version {} - Actualmente en la rama {}, actualización disponible a la versión {} - - - - Update available to version {} - Actualización disponible a la versión {} - - - - This is the latest version available - Esta es la última versión disponible - - - - WARNING: This addon is obsolete - ATENCIÓN: Este complemento está obsoleto - - - - WARNING: This addon is Python 2 only - ADVERTENCIA: Este complemento es sólo Python 2 - - - - WARNING: This addon requires FreeCAD {} - ADVERTENCIA: Este complemento requiere FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ADVERTENCIA: Este complemento está actualmente instalado, pero desactivado. Utilice el botón 'habilitar' para reactivarlo. - - - - This Addon will be enabled next time you restart FreeCAD. - Este complemento se habilitará la próxima vez que reinicie FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Este complemento se desactivará la próxima vez que reinicie FreeCAD. - - - - - - Success - Éxito - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Enable - Habilitar - - - - Disable - Deshabilitar - - - - - Check for update - Buscar actualizaciones - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Ejecutar - - - - Change branch... - Cambiar rama... - - - - Return to package list - Volver a la lista de paquetes - - - - Checking connection - Comprobando conexión - - - - Checking for connection to GitHub... - Comprobando conexión a GitHub... - - - - Connection failed - Conexión fallida - - - - Missing dependency - Falta dependencia - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - No se pudo importar QtNetwork -- vea la Vista del Reporte para más detalles. El Administrador de complementos no está disponible. - - - - Other... - For providing a license other than one listed - Otros... - - - - Select the corresponding license file in your Addon - Seleccione el archivo de licencia correspondiente en su complemento - - - - Location for new license file - Ubicación del nuevo archivo de licencia - - - - Received {} response code from server - Recibido {} código de respuesta del servidor - - - - Failed to install macro {} - Error al instalar macro {} - - - - Failed to create installation manifest file: - - Error al crear archivo manifest de instalación: - - - - - Unrecognized content kind '{}' - Tipo de contenido no reconocido '{}' - - - - Unable to locate icon at {} - No se puede localizar el icono en {} - - - - Select an icon file for this content item - Seleccione un archivo de icono para este elemento de contenido - - - - - - {} is not a subdirectory of {} - {} no es un subdirectorio de {} - - - - Select the subdirectory for this content item - Seleccione el subdirectorio para este artículo de contenido - - - - Automatic - Automático - - - - - Workbench - Banco de trabajo - - - - Addon - Complemento - - - - Python - Python - - - - Yes - Sí - - - - Internal Workbench - Banco de trabajo - - - - External Addon - Complemento externo - - - - Python Package - Paquete de Python - - - - - Other... - Otros... - - - - Too many to list - Demasiado para enlistar - - - - - - - - - Missing Requirement - Requisitos faltantes - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - El complemento '{}' requiere '{}', el cual no está disponible en su copia de FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - El complemento '{}' requiere los siguientes bancos de trabajo, los cuales no están disponibles en su copia de FreeCAD: - - - - Press OK to install anyway. - Pulse OK para instalar de todos modos. - - - - - Incompatible Python version - Versión de Python incompatible - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Este complemento requiere paquetes de Python que no están instalados y no se pueden instalar automáticamente. Para utilizar este complemento debe instalar manualmente los siguientes paquetes de Python: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Este complemento (o una de sus dependencias) requiere Python {}.{}, y su sistema está ejecutando {}.{}. La instalación ha sido cancelada. - - - - Optional dependency on {} ignored because it is not in the allow-list - Dependencia opcional de {} ignorada porque no está en la lista permitida - - - - - Installing dependencies - Instalando dependencias - - - - - Cannot execute Python - No se puede ejecutar Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - No se pudo localizar automáticamente el ejecutable de Python, o la ruta está configurada incorrectamente. Por favor, compruebe la configuración de preferencias del Administrador de complementos para la ruta a Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - No se pudieron instalar las dependencias. ¿Continuar con la instalación de {} de cualquier forma? - - - - - Cannot execute pip - No se puede ejecutar pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Fallo al ejecutar pip, podría faltar en tu instalación de Python. Por favor, asegúrese de que su sistema tiene pip instalado y vuelva a intentarlo. El comando fallido fue: - - - - - Continue with installation of {} anyway? - ¿Continuar con la instalación de {} de todos modos? - - - - - Package installation failed - Error al instalar el paquete - - - - See Report View for detailed failure log. - Consulte Ver Informe para registro detallado de errores. - - - - Installing Addon - Instalando Complemento - - - - Installing FreeCAD Addon '{}' - Instalando complemento de FreeCAD '{}' - - - - Cancelling - Cancelando - - - - Cancelling installation of '{}' - Cancelando instalación de '{}' - - - - {} was installed successfully - {} fue instalado satisfactoriamente - - - - - Installation Failed - Instalación fallida - - - - Failed to install {} - Error al instalar {} - - - - - Create new toolbar - Crear nueva barra de herramientas - - - - - A macro installed with the FreeCAD Addon Manager - Una macro instalada con el administrador de complementos de FreeCAD - - - - - Run - Indicates a macro that can be 'run' - Ejecutar - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - No se han podido leer los datos de GitHub: comprueba tu conexión a Internet y la configuración del proxy e intente de nuevo. - - - - XML failure while reading metadata from file {} - Fallo en archivo XML mientras se leían los metadatos del archivo {} - - - - Invalid metadata in file {} - Metadatos no válidos en el archivo {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - PRECAUCIÓN: La ruta especificada en los metadatos de package.xml no coincide con la rama que se ha realizado actualmente. - - - - Name - Nombre - - - - Class - Clase - - - - Description - Descripción - - - - Subdirectory - Subdirectorio - - - - Files - Archivos - - - - Select the folder containing your Addon - Seleccione la carpeta que contiene su complemento - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Sin Vermin, cancelando operación. - - - - Scanning Addon for Python version compatibility - Examinando el complemento para compatibilidad con la versión de Python - - - - Minimum Python Version Detected - Versión mínima de Python detectada - - - - Vermin auto-detected a required version of Python 3.{} - Vermin ha detectado una versión requerida de Python 3.{} - - - - Install Vermin? - ¿Instalar Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Para detectar automáticamente la versión requerida de Python para este complemento requiere Vermin (https://pypi.org/project/vermin/). ¿Acepta la instalación? - - - - Attempting to install Vermin from PyPi - Intentando instalar Vermin desde PyPi - - - - - Installation failed - Instalación fallida - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Error al instalar Vermin -- compruebe la vista del informe para más detalles. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Error al importar Vermin después de la instalación -- no se puede escanear el complemento. - - - - Select an icon file for this package - Seleccione un ícono para este paquete - - - - Filter is valid - El filtro es válido - - - - Filter regular expression is invalid - La expresión regular del filtro no es válida - - - - Search... - Buscar... - - - - Click for details about package {} - Haga clic para obtener detalles sobre el paquete {} - - - - Click for details about workbench {} - Haga clic para obtener detalles sobre el banco de trabajo {} - - - - Click for details about macro {} - Haga clic para obtener detalles sobre la macro {} - - - - Maintainers: - Mantenedores: - - - - Tags - Etiquetas - - - - {} ★ on GitHub - {} ★ en GitHub - - - - No ★, or not on GitHub - Sin ★, o no está en GitHub - - - - Created - Creado - - - - Updated - Actualizado - - - - Score: - Puntuación: - - - - - Up-to-date - Al día - - - - - - - - Update available - Actualización disponible - - - - - Pending restart - Reinicio pendiente - - - - - DISABLED - DESHABILITADO - - - - Installed version - Versión instalada - - - - Unknown version - Versión desconocida - - - - Installed on - Instalado el - - - - Available version - Versión disponible - - - - Filter by... - Filtrar por... - - - - Addon Type - Tipo de complemento - - - - - Any - Cualquiera - - - - Macro - Macro - - - - Preference Pack - Paquete de preferencias - - - - Installation Status - Estado de la instalación - - - - Not installed - No instalado - - - - Filter - Filtro - - - - DANGER: Developer feature - PELIGRO: Función de desarrollador - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - PELIGRO: Cambiar las ramas está destinado para desarrolladores y beta testers y puede resultar en rupturas, documentos no compatibles hacia atrás, inestabilidad, cierres abruptos y/o la prematura muerte térmica del universo. ¿Está seguro de que desea continuar? - - - - There are local changes - Hay cambios locales - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ADVERTENCIA: Este repositorio tiene cambios locales no confirmados. ¿Está seguro que desea cambiar de rama (trayendo los cambios contigo)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Rastreo remoto - - - - Last Updated - Table header for git update date - Actualizado por última vez - - - - Installation of Python package {} failed - La instalación del paquete de Python {} falló - - - - Installation of optional package failed - La instalación del paquete opcional falló - - - - Installing required dependency {} - Instalando dependencia requerida {} - - - - Installation of Addon {} failed - La instalación del complemento {} falló - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Error al decodificar archivo {} para el complemento '{}' - - - - Any dependency information in this file will be ignored - Cualquier información de dependencia en este archivo será ignorada - - - - Unable to open macro wiki page at {} - No se puede abrir la página de la wiki de la macro en {} - - - - Unable to fetch the code of this macro. - No se puede obtener el código de esta macro. - - - - Unable to retrieve a description from the wiki for macro {} - No se puede recuperar una descripción de la wiki para la macro {} - - - - Unable to open macro code URL {} - No se puede abrir la URL del código de la macro {} - - - - Unable to fetch macro-specified file {} from {} - No se puede obtener el archivo especificado macro {} de {} - - - - Could not locate macro-specified file {} (expected at {}) - No se pudo encontrar el archivo especifico para la macro {} (se esperaba en {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Banco de trabajo interno no reconocido '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Advertencia de desarrollador de complementos: la URL del repositorio establecida en el archivo package.xml para el complemento {} ({}) no coincide con la URL de la que fue obtenida ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Advertencia de desarrollador de complementos: la rama de repositorio establecida en el archivo package.xml para el complemento {} ({}) no coincide con la rama de la que fue obtenida ({}) - - - - - Got an error when trying to import {} - Se ha producido un error al intentar importar {} - - - - An unknown error occurred - Se produjo un error desconocido - - - - Could not find addon {} to remove it. - No se pudo encontrar el complemento {} para eliminarlo. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Falló la ejecución del script uninstall.py del complemento. Procediendo con la desinstalación... - - - - Removed extra installed file {} - Archivo extra instalado {} eliminado - - - - Error while trying to remove extra installed file {} - Error al intentar eliminar el archivo extra instalado {} - - - - Error while trying to remove macro file {}: - Error al intentar eliminar el archivo macro {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Error al conectar a GitHub. Compruebe su conexión y configuración de proxy. - - - - WARNING: Duplicate addon {} ignored - ADVERTENCIA: Duplicar complemento {} ignorado - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Se ha producido un error al actualizar macros desde GitHub, intentando limpiar el checkout... - - - - Attempting to do a clean checkout... - Intentando hacer una comprobación limpia... - - - - Clean checkout succeeded - Comprobación limpia exitosa - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Error al actualizar macros de GitHub -- intente limpiar la caché del administrador de complementos. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error al conectar a la Wiki, FreeCAD no puede recuperar la lista de macros de la Wiki en este momento - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Error al leer los metadatos de {name} - - - - Failed to fetch code for macro '{name}' - Error al obtener el código para el macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Administrador de complementos: no se pudo completar un proceso al obtener {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - De {num_macros} macros, a {num_failed} se les agotó el tiempo durante el procesamiento - - - - Addon Manager: a worker process failed to halt ({name}) - Administrador de complementos: un proceso de trabajo falló al detenerse ({name}) - - - - Timeout while fetching metadata for macro {} - Tiempo de espera agotado al buscar metadatos para la macro {} - - - - Failed to kill process for macro {}! - - ¡Error al matar el proceso para macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - No se pudieron obtener las estadísticas del complemento de {} -- solo ordenar alfabeticamente será preciso - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - No se pudo obtener la puntuación del complemento de '{}' -- ordenar por puntuación fallará - - - - - Repository URL - Preferences header for custom repositories - URL del repositorio - - - - Branch name - Preferences header for custom repositories - Nombre de rama - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Copia de seguridad del directorio original y re-clonando - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Error al renombrar la rama Git con el siguiente mensaje: - - - - Installing - Instalando - - - - Succeeded - Éxito - - - - Failed - Falló - - - - Update was cancelled - La actualización fue cancelada - - - - some addons may have been updated - algunos complementos podrían haber sido actualizados - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Cargando información para {} de la wiki de Recetas de Macros de FreeCAD... - - - - Loading page for {} from {}... - Cargando página de {} de {}... - - - - Failed to download data from {} -- received response code {}. - Error al descargar datos de {} -- código de respuesta recibido {}. - - - - Composite view - Vista compuesta - - - - Expanded view - Vista extendida - - - - Compact view - Vista compacta - - - - Alphabetical - Sort order - Alfabético - - - - Last Updated - Sort order - Actualizado por última vez - - - - Date Created - Sort order - Fecha de creación - - - - GitHub Stars - Sort order - Estrellas en GitHub - - - - Score - Sort order - Puntuación - - - - Std_AddonMgr - - - &Addon manager - &Administrador de complementos - - - - Manage external workbenches, macros, and preference packs - Administrar bancos de trabajo externos, macros y paquetes de preferencias - - - - AddonInstaller - - - Finished removing {} - Se terminó de eliminar {} - - - - Failed to remove some files - Error al eliminar algunos archivos - - - - Addons installer - - - Finished updating the following addons - Finalizó la actualización de los siguientes complementos - - - - Workbench - - - Auto-Created Macro Toolbar - Barra de herramientas de macros creada automáticamente - - - - QObject - - - Addon Manager - Administrador de complementos - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_eu.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_eu.qm deleted file mode 100644 index 600350a54adb4e287dbf2335eee9bca0ca62e16a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71603 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 S?7=7>t@PO|z^KzID*i9Rm>CfO diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_eu.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_eu.ts deleted file mode 100644 index 6232fc26b4..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_eu.ts +++ /dev/null @@ -1,2486 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Biltegi pertsonalizatua - - - - Repository URL - Biltegiaren URLa - - - - Branch - Adarra - - - - CompactView - - - - Icon - Ikonoa - - - - - <b>Package Name</b> - <b>Pakete-izena</b> - - - - - Version - Bertsioa - - - - - Description - Deskribapena - - - - Update Available - Eguneraketa eskuragarri - - - - UpdateAvailable - Eguneratzea eskuragarri - - - - DependencyDialog - - - Dependencies - Mendekotasunak - - - - Dependency type - Mendekotasun mota - - - - Name - Izena - - - - Optional? - Aukerakoa? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Ebatzi mendekotasunak - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Gehigarri honek derrigorrezko eta aukerako hurrengo mendekotasunak ditu. Haiek instalatu behar dira gehigarria erabili ahal izateko. - -Gehigarrien kudeatzaileak automatikoki instalatu ditzan nahi al duzu? Aukeratu "Ez ikusi" gehigarria mendekotasunik gabe instalatzeko. - - - - FreeCAD Addons - FreeCAD gehigarriak - - - - Required Python modules - Beharrezko Python moduluak - - - - Optional Python modules - Aukerako Python moduluak - - - - DeveloperModeDialog - - - Addon Developer Tools - Gehigarrien garatzaile-tresnak - - - - Path to Addon - Gehigarriaren bide-izena - - - - - Browse... - Arakatu... - - - - Metadata - Metadatuak - - - - Primary branch - Adar nagusia - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Gehigarri honek eskaintzen duenaren azalpena. Gehigarrien kudeatzailean erakutsiko da. Honetarako, ez da derrigorrezkoa adieraztea hau FreeCADerako gehigarri bat dela. - - - - Description - Deskribapena - - - - Discussion URL - Eztabaiden URLa - - - - Icon - Ikonoa - - - - Bugtracker URL - Akats-aztarnariaren URLa - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilo semantikoa (1.2.3-beta) edo egutegi-bertsioena (2022.08.30) onartzen da - - - - Set to today (CalVer style) - Ezarri gaurko data (egutegi-bertsioen estiloa) - - - - - - - (Optional) - (Aukerakoa) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Gehigarrien kudeatzaileko gehigarri-zerrendan bistaratutakoa. Ez luke "FreeCAD", hitza eduki beharko eta onartutako sistema eragile guztietan baliozkoa den direktorio-izena izan beharko luke. - - - - README URL - IRAKURRI FITXATEGIAREN URL-A - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - IRADOKIZUNA: Hau FreeCADen bistaratzen da, gehigarrien kudeatzailean, eta beraz, ez da beharrezkoa espazioa alferrik galtzea "Hau FreeCADen gehigarri bat da..." bezalakoak esanda -- zer egiten duen esan, besterik gabe. - - - - Repository URL - Biltegiaren URLa - - - - Website URL - Webgunearen URLa - - - - Documentation URL - Dokumentazioaren URLa - - - - Addon Name - Gehigarriaren izena - - - - Version - Bertsioa - - - - (Recommended) - (Gomendatua) - - - - Minimum Python - Gutxieneko Python bertsioa - - - - (Optional, only 3.x version supported) - (Aukerakoa, 3.x bertsioa soilik onartzen da) - - - - Detect... - Detektatu... - - - - Addon Contents - Gehigarri-edukiak - - - - Dialog - - - Addon Manager - Gehigarrien kudeatzailea - - - - Edit Tags - Editatu etiketak - - - - Comma-separated list of tags describing this item: - Elementu hau deskribatzen duten etiketen zerrenda, komaz banandua: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - IRADOKIZUNA: Etiketa erabilienak "Assembly", "FEM", "Mesh", "NURBS", etab. dira. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Jarraitu - - - - Cancel - Utzi - - - - EditDependencyDialog - - - Edit Dependency - Editatu mendekotasuna - - - - Dependency Type - Mendekotasun mota - - - - Dependency - Mendekotasuna - - - - Package name, if "Other..." - Paketearen izena, "Beste bat..." bada - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - OHARRA: If "Beste bat..." badago hautatuta, paketea ez dago ALLOWED_PYTHON_PACKAGES.txt fitxategian eta gehigarrien kudeatzaileak ez du automatikoki instalatuko. Bidali PR bat <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> helbidera paketea gehitu dadin. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Aukerako mendekotasun bat bada, gehigarrien kudeatzaileak hura instalatzeko aukera eskainiko du (posible bada), baina ez du instalazioa blokeatuko erabiltzaileak paketea ez instalatzea aukeratzen badu edo instalatu ezin badu. - - - - Optional - Aukerakoa - - - - ExpandedView - - - - Icon - Ikonoa - - - - - <h1>Package Name</h1> - <h1>Pakete-izena</h1> - - - - - Version - Bertsioa - - - - - (tags) - (etiketak) - - - - - Description - Deskribapena - - - - - Maintainer - Mantentzailea - - - - Update Available - Eguneraketa eskuragarri - - - - labelSort - labelSort - - - - UpdateAvailable - Eguneratzea eskuragarri - - - - Form - - - Licenses - Lizentziak - - - - License - Lizentzia - - - - License file - Lizentzia-fitxategia - - - - People - Jendea - - - - Kind - Mota - - - - Name - Izena - - - - Email - Posta elektronikoa - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Bertsioen mapatze aurreratua - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - FreeCADen gehigarrien kudeatzailearen etorkizuneko bertsioetan, garatzaileek adar edo etiketa jakin bat ezarri ahal izango dute FreeCADen bertsio jakin bat erabiltzeko (adibidez, gehigarriaren azken bertsioak v0.19 onartzen badu, etiketa zehatz bat ezarri ahal izango da horretarako) - - - - FreeCAD Version - FreeCAD bertsioa - - - - Best-available branch, tag, or commit - Eskuragarri dagoen adar, etiketa edo egikaritze onena - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Onartutako FreeCAD bertsioak - - - - Minimum FreeCAD Version Supported - Onartutako FreeCAD bertsio zaharrena - - - - - Optional - Aukerakoa - - - - Maximum FreeCAD Version Supported - Onartutako FreeCAD bertsio berriena - - - - Advanced version mapping... - Bertsioen mapatze aurreratua... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Gehigarrien kudeatzailearen aukerak - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Deskargatu makroen metadatuak (10MB inguru) - - - - Cache update frequency - Cachearen eguneratze-maiztasuna - - - - Manual (no automatic updates) - Eskuzkoa (eguneratze automatikorik ez) - - - - Daily - Egunero - - - - Weekly - Astero - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Ezkutatu Python 2 bertsiorako soilik diren gehigarriak - - - - Hide Addons marked Obsolete - Ezkutatu zaharkituta dauden gehigarriak - - - - Hide Addons that require a newer version of FreeCAD - Ezkutatu FreeCADen bertsio berriagoa behar duten gehigarriak - - - - Custom repositories - Biltegi pertsonalizatuak - - - - Proxy - Proxya - - - - No proxy - Proxyrik ez - - - - User system proxy - Erabili sistemaren proxya - - - - User-defined proxy: - Erabilitzaileak definitutako proxya: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Aukera aurreratuak - - - - Activate Addon Manager options intended for developers of new Addons. - Aktibatu gehigarri berriak garatzen dituztenentzako gehigarri-kudeatzailearen aukerak. - - - - Addon developer mode - Gehigarrien garatzaileen modua - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Hautatutako makroa edo lan-mahaia desinstalatzen du - - - - Install - Instalatu - - - - Uninstall - Desinstalatu - - - - Update - Eguneratu - - - - Run Macro - Exekutatu makroa - - - - Change branch - Aldatu adarra - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Kudeatu Python mendekotasunak - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Gehigarrien kudeatzaileak honako Python paketeak instalatu ditu gehigarriaren mendekotasunak betetzeko. Instalazioaren kokapena: - - - - Package name - Paketearen izena - - - - Installed version - Instalatutako bertsioa - - - - Available version - Bertsio eskuragarria - - - - Used by - Nork erabilia: - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - "Nork erabilia" zutabeak asteriskoa (*) badu, aukerako mendekotasun bat dagoela esan nahi du. Kontuan izan 'Nork erabilia' aukerak gehigarriaren inportazio zuzenak soilik erregistratzen dituela. Pakete horiek dituzten beste Python mendekotasunak ere instalatuta egon behar dute. - - - - Update all available - Eguneratu erabilgarri dauden guztiak - - - - SelectFromList - - - Dialog - Elkarrizketa-koadroa - - - - TextLabel - Testu-etiketa - - - - UpdateAllDialog - - - Updating Addons - Gehigarriak eguneratzen - - - - Updating out-of-date addons... - Gehigarri zaharkituak eguneratzen... - - - - addContentDialog - - - Content Item - Eduki-elementua - - - - Content type: - Eduki mota: - - - - Macro - Makroa - - - - Preference Pack - Hobespen-paketea - - - - Workbench - Lan-mahaia - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Hau bada gehigarriko gauza bakarra, beste metadatuak goiko mailatik heredatu daitezke eta ez dira zertan hemen zehaztu behar. - - - - This is the only item in the Addon - Hau gehigarriaren elementu bakarra da - - - - Main macro file - Makro-fitxategi nagusia - - - - The file with the macro's metadata in it - Makroaren metadatuak dituen fitxategia - - - - - - Browse... - Arakatu... - - - - Preference Pack Name - Hobespen-paketearen izena - - - - Workbench class name - Lan-mahaiaren klase-izena - - - - Class that defines "Icon" data member - "Ikonoa" datu-kidea definitzen duen klasea - - - - Subdirectory - Azpidirektorioa - - - - Optional, defaults to name of content item - Aukerakoa, balio lehenetsia eduki-elementuaren izena da - - - - Icon - Ikonoa - - - - Optional, defaults to inheriting from top-level Addon - Aukerakoa, balio lehenetsia goi mailako gehigarritik heredatzea da - - - - Tags... - Etiketak... - - - - Dependencies... - Mendekotasunak... - - - - FreeCAD Versions... - FreeCAD bertsioak... - - - - Other Metadata - Beste metadatu batzuk - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Gehigarrien kudeatzailearen zerrendan erakutsia. Ez du "FreeCAD" hitza eduki behar. - - - - Version - Bertsioa - - - - Description - Deskribapena - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilo semantikoa (1.2.3-beta) edo egutegi-bertsioena (2022.08.30) onartzen da - - - - Set to today (CalVer style) - Ezarri gaurko data (egutegi-bertsioen estiloa) - - - - Display Name - Bistaratze-izena - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Hutsik uzten diren eremu guztiak goi mailako gehigarriaren metadatuetatik heredatzen dira. Beraz, teknikoki denak dira aukerakoak. Eduki-elementu anitz dituzten gehigarrien kasuan, elementu bakoitzak bistaratze-izen eta deskribapen esklusiboa eduki behar du. - - - - add_toolbar_button_dialog - - - Add button? - Gehitu botoia? - - - - Add a toolbar button for this macro? - Gehitu tresna-barrako botoi bat makro honi? - - - - Yes - Bai - - - - No - Ez - - - - Never - Inoiz ez - - - - change_branch - - - Change Branch - Aldatu adarra - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Copyright informazioa - - - - Copyright holder: - Copyrightaren jabea: - - - - Copyright year: - Copyrightaren urtea: - - - - personDialog - - - Add Person - Gehitu pertsona - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Mantentzaileak proiektu honetan egikaritzeko sarbidea dutenak dira. Egileak, lana aitortu nahi diozun beste edozein dira. - - - - Name: - Izena: - - - - Email: - Posta elektronikoa: - - - - Email is required for maintainers, and optional for authors. - Mantentzaileek posta elektronikoko helbidea izan behar dute, eta egileek aukerakoa dute. - - - - proxy_authentication - - - Proxy login required - Proxyan saioa hasi behar da - - - - Proxy requires authentication - Proxyak autentifikazioa behar du - - - - Proxy: - Proxya: - - - - Placeholder for proxy address - Proxy-helbiderako leku-marka - - - - Realm: - Domeinua: - - - - Placeholder for proxy realm - Proxy-domeinurako leku-marka - - - - Username - Erabiltzaile-izena - - - - Password - Pasahitza - - - - selectLicenseDialog - - - Select a license - Hautatu lizentzia - - - - About... - Honi buruz... - - - - License name: - Lizentzia-izena: - - - - Path to license file: - Lizentzia-fitxategiaren bide-izena: - - - - (if required by license) - (lizentziak eskatzen badu) - - - - Browse... - Arakatu... - - - - Create... - Sortu... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Hautatu tresna-barra - - - - Select a toolbar to add this macro to: - Hautatu makro hau zein tresna-barrari gehituko zaion: - - - - Ask every time - Galdetu beti - - - - toolbar_button - - - - Add button? - Gehitu botoia? - - - - Add a toolbar button for this macro? - Gehitu tresna-barrako botoi bat makro honi? - - - - Yes - Bai - - - - No - Ez - - - - Never - Inoiz ez - - - - AddonsInstaller - - - Starting up... - Abiarazten... - - - - Worker process {} is taking a long time to stop... - {} langile-prozesuari kostatzen ari zaio gelditzea... - - - - Previous cache process was interrupted, restarting... - - Aurreko cache-prozesua eten egin da, berrabiarazten... - - - - - Custom repo list changed, forcing recache... - - Biltegi-zerrenda pertsonalizatua aldatu da, berriro cachea sortzen... - - - - - Addon manager - Gehigarrien kudeatzailea - - - - You must restart FreeCAD for changes to take effect. - FreeCAD berrabiarazi behar da aldaketak indarrean sartu daitezen. - - - - Restart now - Berrabiarazi orain - - - - Restart later - Berrabiarazi geroago - - - - - Refresh local cache - Freskatu cache lokala - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Cachea eguneratzen... - - - - - Checking for updates... - Eguneraketak bilatzen... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Itxi - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Ezin da instalatzaile berria abiarazi aurrekoa amaitu baino lehen. - - - - - - - Maintainer - Mantentzailea - - - - - - - Author - Egilea - - - - New Python Version Detected - Pythonen bertsio berria detektatu da - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Badirudi lehen aldia dela Python bertsio hau gehigarrien kudeatzailearekin erabiltzen dela. Autoinstalatutako mendekotasun berak instalatu nahi al dituzu harentzat? - - - - Processing, please wait... - Prozesatzen, itxaron... - - - - - Update - Eguneratu - - - - Updating... - Eguneratzen... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Ezin da QtNetwork inportatu -- ez dirudi zure sisteman instalatuta dagoenik. Agian zure hornitzaileak pakete bat dauka mendekotasun horretarako (sarritan "python3-pyside2.qtnetwork" deitzen da) - - - - Failed to convert the specified proxy port '{}' to a port number - Zehaztutako '{}' proxy-ataka ezin izan da ataka-zenbaki bihurtu - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parametro-errorea: elkar ukatzen duten proxy-aukerak ezarri dira. Balio lehenetsiak ezarriko dira. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parametro-errorea: erabiltzaile-proxya adierazi da, baina ez da proxyrik eman. Balio lehenetsiak ezarriko dira. - - - - Addon Manager: Unexpected {} response from server - Gehigarrien kudeatzailea: espero ez zen {} erantzuna zerbitzaritik - - - - Error with encrypted connection - Errorea zifratutako konexioan - - - - - - Confirm remove - Baieztatu kentzea - - - - Are you sure you want to uninstall {}? - Ziur al zaude {} desinstalatu nahi duzula? - - - - - - Removing Addon - Gehigarria kentzen - - - - Removing {} - {} kentzen - - - - - Uninstall complete - Desinstalazioa osatu da - - - - - Uninstall failed - Desinstalazioak huts egin du - - - - Version {version} installed on {date} - {version} bertsioa instalatu da {date} egunean - - - - Version {version} installed - {version} bertsioa instalatu da - - - - Installed on {date} - Instalazio-data: {date} - - - - - - - Installed - Instalatuta - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - '{}' git etiketa egiaztatu da, ezin da eguneratu - - - - Update check in progress - Eguneratzearen egiaztatzea abian - - - - Installation location - Instalazioaren kokapena - - - - Repository URL - Biltegiaren URLa - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Desgaituta - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - ABISUA: Gehigarri hau zaharkituta dago - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ABISUA: Gehigarri hau instalatuta dago, baina desgaituta dago. Erabili 'gaitu' botoia berriro gaitzeko. - - - - This Addon will be enabled next time you restart FreeCAD. - Gehigarri hau FreeCAD berrabiarazten den hurrengoan gaituko da. - - - - This Addon will be disabled next time you restart FreeCAD. - Gehigarri hau FreeCAD berrabiarazten den hurrengoan desgaituko da. - - - - - - Success - Eginda - - - - Install - Instalatu - - - - Uninstall - Desinstalatu - - - - Enable - Gaitu - - - - Disable - Desgaitu - - - - - Check for update - Check for update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - distantzia - - - - Change branch... - Change branch... - - - - Return to package list - Itzuli pakete-zerrendara - - - - Checking connection - Konexioa egiaztatzen - - - - Checking for connection to GitHub... - GitHub-erako konexioa egiaztatzen... - - - - Connection failed - Konexioak huts egin du - - - - Missing dependency - Mendekotasuna falta da - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Ezin izan da QtNetwork inportatu -- ikusi txosten-ikuspegia xehetasunetarako. Gehigarrien kudeatzailea ez dago erabilgarri. - - - - Other... - For providing a license other than one listed - Beste bat... - - - - Select the corresponding license file in your Addon - Hautatu zure gehigarriari dagokion lizentzia-fitxategia - - - - Location for new license file - Lizentzia-fitxategi berriaren kokapena - - - - Received {} response code from server - {} erantzun-kodea jaso da zerbitzaritik - - - - Failed to install macro {} - Ezin izan da {} makroa instalatu - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Eduki mota ezezaguna: '{}' - - - - Unable to locate icon at {} - Ezin da ikonoa hemen aurkitu: {} - - - - Select an icon file for this content item - Hautatu ikono-fitxategi bat eduki-elementu honetarako - - - - - - {} is not a subdirectory of {} - {} ez da {} direktorioaren azpidirektorio bat - - - - Select the subdirectory for this content item - Hautatu eduki-elementu honetarako azpidirektorioa - - - - Automatic - Automatikoa - - - - - Workbench - Lan-mahaia - - - - Addon - Gehigarria - - - - Python - Python - - - - Yes - Bai - - - - Internal Workbench - Barneko lan-mahaia - - - - External Addon - Kanpoko gehigarria - - - - Python Package - Python paketea - - - - - Other... - Beste bat... - - - - Too many to list - Gehiegi zerrendatzeko - - - - - - - - - Missing Requirement - Falta den eskakizuna - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - '{}' gehigarriak '{}' behar du, baina ez dago erabilgarri zure FreeCAD kopian. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - '{}' gehigarriak zure FreeCAD kopian ez dauden honako lan-mahaiak behar ditu: - - - - Press OK to install anyway. - Sakatu 'Ados' instalatzeko. - - - - - Incompatible Python version - Python-en bertsio bateraezina - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - {} gehigarriaren aukerako mendekotasunari ez ikusiarena egin zaio onarpen-zerrendan ez dagoelako - - - - - Installing dependencies - Mendekotasunak instalatzen - - - - - Cannot execute Python - Ezin da Python exekutatu - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Huts egin du Python exekutagarria automatikoki aurkitzeak, edo bide-izena gaizki ezarri da. Begiratu gehigarrien kudeatzailearen hobespenetako ezarpena Python-en bide-izenerako. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Mendekotasunak ezin izan dira instalatu. Jarraitu {} instalatzen? - - - - - Cannot execute pip - Ezin da pip exekutatu - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - {} instalatzen jarraitu nahi duzu? - - - - - Package installation failed - Paketearen instalazioak huts egin du - - - - See Report View for detailed failure log. - Ikusi txostena huts egitearen erregistro xehea kontsultatzeko. - - - - Installing Addon - Gehigarria instalatzen - - - - Installing FreeCAD Addon '{}' - '{}' FreeCAD gehigarria instalatzen - - - - Cancelling - Bertan behera uzten - - - - Cancelling installation of '{}' - '{}' gehigarriaren instalazioa bertan behera uzten - - - - {} was installed successfully - {} ongi instalatu da - - - - - Installation Failed - Instalazioak huts egin du - - - - Failed to install {} - Ezin izan da {} instalatu - - - - - Create new toolbar - Sortu tresna-barra berria - - - - - A macro installed with the FreeCAD Addon Manager - FreeCADen gehigarri-kudeatzailearekin instalatutako makroa - - - - - Run - Indicates a macro that can be 'run' - distantzia - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Ezin dira datuak GitHub-etik irakurri: egiaztatu zure interneteko konexioa eta proxy-ezarpenak eta saiatu berriro. - - - - XML failure while reading metadata from file {} - XML hutsegitea {} fitxategiko metadatuak irakurtzean - - - - Invalid metadata in file {} - Metadatu baliogabeak {} fitxategian - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ABISUA: pacakge.xml metadatuetan zehaztutako bide-izena ez dator bat deskargatutako uneko adarrarekin. - - - - Name - Izena - - - - Class - Klasea - - - - Description - Deskribapena - - - - Subdirectory - Azpidirektorioa - - - - Files - Fitxategiak - - - - Select the folder containing your Addon - Hautatu zure gehigarria duen karpeta - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Ez dago Vermin, eragiketa bertan behera uzten. - - - - Scanning Addon for Python version compatibility - Gehigarria eskaneatzen Python bertsioa bateragarria den jakiteko - - - - Minimum Python Version Detected - Pythonen gutxieneko bertsioa detektatu da - - - - Vermin auto-detected a required version of Python 3.{} - Vermin-ek detektatu du beharrezko Python bertsioa 3.{} dela - - - - Install Vermin? - Vermin instalatu? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Gehigarri honek behar duen Python bertsioa automatikoki detektatzeko, Vermin (https://pypi.org/project/vermin/) instalatu behar da. Instalatu? - - - - Attempting to install Vermin from PyPi - Vermin Pypi bidez instalatzeko saiakera - - - - - Installation failed - Instalazioak huts egin du - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Huts egin du Vermin instalatzeak -- begiratu txosten-bista xehetasun gehiagorako. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Huts egin du vermin inportatzeak hura instalatu ondoren -- ezin da gehigarria eskaneatu. - - - - Select an icon file for this package - Hautatu ikono-fitxategi bat pakete honetarako - - - - Filter is valid - Iragazkia baliozkoa da - - - - Filter regular expression is invalid - Iragazkiaren adierazpen erregularra baliogabea da - - - - Search... - Bilatu... - - - - Click for details about package {} - Egin klik {} paketearen xehetasunak eskuratzeko - - - - Click for details about workbench {} - Egin klik {} lan-mahaiaren xehetasunak eskuratzeko - - - - Click for details about macro {} - Egin klik {} makroaren xehetasunak eskuratzeko - - - - Maintainers: - Mantentzaileak: - - - - Tags - Etiketak - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Noiz sortua: - - - - Updated - Eguneratua: - - - - Score: - Puntuazioa: - - - - - Up-to-date - Eguneratuta - - - - - - - - Update available - Eguneraketa eskuragarri - - - - - Pending restart - Berrabioaren zain - - - - - DISABLED - DESGAITUTA - - - - Installed version - Instalatutako bertsioa - - - - Unknown version - Bertsio ezezaguna - - - - Installed on - Hemen instalatua: - - - - Available version - Bertsio eskuragarria - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Edozein - - - - Macro - Makroa - - - - Preference Pack - Hobespen-paketea - - - - Installation Status - Installation Status - - - - Not installed - Instalatu gabea - - - - Filter - Iragazkia - - - - DANGER: Developer feature - ARRISKUA: Garatzaile-eginbidea - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - ARRISKUA: Adarrez aldatzea garatzaileentzako eta beta bertsioen probatzaileentzako dago pentsatuta. Dokumentu ez bateragarriak, desegonkortasuna, kraskadurak eta unibertsoaren heriotz goiztiarra eragin ditzake. Jarraitu nahi al duzu? - - - - There are local changes - Aldaketa lokalak daude - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - AVBISUA: Biltegi honek egikaritu gabeko aldaketa lokalak ditu. Ziur zaude adarrez aldatu nahi duzula (aldaketak zurekin ekartzeko)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - {} Python paketearen instalazioak huts egin du - - - - Installation of optional package failed - Aukerako paketearen instalazioak huts egin du - - - - Installing required dependency {} - Beharrezkoa den {} mendekotasuna instalatzen - - - - Installation of Addon {} failed - {} gehigarriaren instalazioak huts egin du - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Huts egin du '{}' gehigarrirako {} fitxategia deskodetzeak - - - - Any dependency information in this file will be ignored - Fitxategi honek duen mendekotasun-informazioari ez ikusiarena egingo zaio - - - - Unable to open macro wiki page at {} - Ezin da ireki makroaren {} wiki-orria - - - - Unable to fetch the code of this macro. - Ezin izan da makro honen kodea eskuratu. - - - - Unable to retrieve a description from the wiki for macro {} - Ezin izan da {} makroaren deskribapen bat eskuratu wikitik - - - - Unable to open macro code URL {} - Ezin da ireki makro-kodearen URLa {} - - - - Unable to fetch macro-specified file {} from {} - Ezin da makro bidez zehaztutako {} fitxategia atzitu {} gunetik - - - - Could not locate macro-specified file {} (expected at {}) - Ezin da makroak zehaztutako {} fitxategia aurkitu ({} kokalekuan espero zen) - - - - {}: Unrecognized internal workbench '{}' - {}: Ezagutzen ez den barneko lan-mahaia '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Gehigarrien garatzaileen abisua: {} ({}) gehigarrirako package.xml fitxategian ezarri den biltegi URLa ez dator bat gehigarria atzitu zeneko URLarekin ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Gehigarrien garatzaileen abisua: {} ({}) gehigarrirako package.xml fitxategian ezarri den biltegi-adarra ez dator bat gehigarria atzitu zeneko adarrarekin ({}) - - - - - Got an error when trying to import {} - Errorea gertatu da {} inportatzen saiatzean - - - - An unknown error occurred - Errore ezezaguna gertatu da - - - - Could not find addon {} to remove it. - Ez da aurkitu {} gehigarria hura kendu ahal izateko. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Huts egin du gehigarriaren 'uninstall.py' script-aren exekuzioak. Desinstalatzen jarraitzen... - - - - Removed extra installed file {} - Instalatutako {} fitxategi gehigarria kendu da - - - - Error while trying to remove extra installed file {} - Errorea instalatutako {} fitxategi gehigarria kentzean - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Huts egin du GitHub gunearekin konektatzeak. Egiaztatu konexioa eta proxy-ezarpenak. - - - - WARNING: Duplicate addon {} ignored - ABISUA: Bikoiztutako {} gehigarriari ez ikusiarena egin zaio - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Errorea gertatu da makroak GitHub gunetik eguneratzean, deskarga garbia saiatzen... - - - - Attempting to do a clean checkout... - Deskarga garbia saiatzen... - - - - Clean checkout succeeded - Deskarga garbia ongi gauzatu da - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Huts egin du GitHub guneko makroak egunerateak -- saiatu gehigarrien kudeatzailearen cachea garbitzen. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Errorea wikiarekin konektatzean, FreeCADek ezin du wikiko makro-zerrenda eskuratu momentu honetan - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Huts egin du {name}(e)ko metadatuen irakurketak - - - - Failed to fetch code for macro '{name}' - Huts egin du '{name}' makroaren kodea eskuratzeak - - - - Addon Manager: a worker process failed to complete while fetching {name} - Gehigarrien kudeatzailea: langile-prozesu bat osatzeak huts egin du {name} atzitzean - - - - Out of {num_macros} macros, {num_failed} timed out while processing - {num_macros} makrotatik, {num_failed} denboraz iraungi dira prozesatzean - - - - Addon Manager: a worker process failed to halt ({name}) - Gehigarrien kudeatzailea: langile-prozesu bat gelditzeak huts egin du ({name}) - - - - Timeout while fetching metadata for macro {} - Denbora iraungi da {} makroaren metadatuak atzitzean - - - - Failed to kill process for macro {}! - - Huts egin du {} makroaren prozesua hiltzeak. - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Biltegiaren URLa - - - - Branch name - Preferences header for custom repositories - Adarraren izena - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Jatorrizko direktorioaren babeskopia egiten eta berriro klonatzen - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Instalatzen - - - - Succeeded - Ongi egin da - - - - Failed - Huts egin du - - - - Update was cancelled - Eguneraketa bertan behera geratu da - - - - some addons may have been updated - zenbait gehigarri eguneratu ahal izan dira - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Gehigarrien kudeatzailea - - - - Manage external workbenches, macros, and preference packs - Kudeatu kanpoko lan-mahaiak, makroak eta hobespen-paketeak - - - - AddonInstaller - - - Finished removing {} - {} kentzea amaitu da - - - - Failed to remove some files - Huts egin du zenbait fitxategi kentzeak - - - - Addons installer - - - Finished updating the following addons - Honako gehigarrien eguneraketa amaitu da: - - - - Workbench - - - Auto-Created Macro Toolbar - Makrorako automatikoki sortutako tresna-barra - - - - QObject - - - Addon Manager - Gehigarrien kudeatzailea - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_fi.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_fi.qm deleted file mode 100644 index 7a0cbb71e36d78a8e6246405ac72957a50f84651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68277 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_fi.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_fi.ts deleted file mode 100644 index 26246d13f3..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_fi.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Omavalintainen tietovarasto - - - - Repository URL - Tietovaraston URL-osoite - - - - Branch - Haara - - - - CompactView - - - - Icon - kuvake - - - - - <b>Package Name</b> - <b>Paketin nimi</b> - - - - - Version - Versio - - - - - Description - Kuvaus - - - - Update Available - Päivitys saatavilla - - - - UpdateAvailable - Päivitys saatavilla - - - - DependencyDialog - - - Dependencies - Riippuvuudet - - - - Dependency type - Riippuvuuden tyyppi - - - - Name - Nimi - - - - Optional? - Valinnainen? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Ratkaise riippuvuudet - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Tällä lisäosalla on seuraavat vaaditut ja valinnaiset riippuvuudet. Sinun on asennettava ne ennen kuin tätä lisäosaa voidaan käyttää. - -Haluatko Addon Manager asentaa ne automaattisesti? Valitse "Ohita" asentaaksesi lisäosan ilman riippuvuuksia. - - - - FreeCAD Addons - FreeCAD-lisäosat - - - - Required Python modules - Vaaditut Python-moduulit - - - - Optional Python modules - Valinnaiset Python-moduulit - - - - DeveloperModeDialog - - - Addon Developer Tools - Lisäosien Kehitystyökalut - - - - Path to Addon - Polku lisäosaan - - - - - Browse... - Selaa... - - - - Metadata - Metatiedot - - - - Primary branch - Ensisijainen haara - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Selitys siitä, mitä tämä lisäosa tarjoaa. Näytetään Lisäosien hallinnassa. Ei ole tarpeen todeta, että tämä on FreeCADin lisäosa. - - - - Description - Kuvaus - - - - Discussion URL - Keskustelun URL - - - - Icon - kuvake - - - - Bugtracker URL - Virheiden seurannan URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semanttinen tyyli (1.2.3-beta) ja CalVer-tyyli (2022.08.30) tuettu - - - - Set to today (CalVer style) - Aseta tähän päivään (CalVer-tyyli) - - - - - - - (Optional) - (Valinnainen) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Näytetään Addon Manager's lista Addons. Ei pitäisi sisältää sanaa "FreeCAD", ja täytyy olla kelvollinen hakemiston nimi kaikissa tuetuissa käyttöjärjestelmissä. - - - - README URL - README:n osoite - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - VINKKI: Koska tämä teksti näytetään FreeCADin Lisäosien hallinnassa, ei ole tarpeen käyttää tilaa kertoakseen, että kyseessä on FreeCAD-lisäosa. Sano vain mitä se tekee. - - - - Repository URL - Tietovaraston URL-osoite - - - - Website URL - Sivuston osoite - - - - Documentation URL - Dokumentaation osoite - - - - Addon Name - Lisäosan nimi - - - - Version - Versio - - - - (Recommended) - (Suositeltu) - - - - Minimum Python - Pythonin vähimmäisversio - - - - (Optional, only 3.x version supported) - (Valinnainen, vain versiot 3.x tuettu) - - - - Detect... - Tunnista... - - - - Addon Contents - Lisäosan sisältö - - - - Dialog - - - Addon Manager - Lisäosien hallinta - - - - Edit Tags - Muokkaa tageja - - - - Comma-separated list of tags describing this item: - Pilkulla erotettu luettelo tageista, jotka kuvaavat tätä kohdetta: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - VINKKI: Yleisiä tunnisteita ovat "Assembly", "FEM", "Mesh", "NURBS", jne. - - - - Add-on Manager: Warning! - Lisäosien hallinta: Varoitus! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Add-on Manager tarjoaa pääsyn laajaan kirjastoon hyödyllisiä kolmannen osapuolen FreeCAD -laajennuksia. Turvallisuudesta tai toiminnallisuudesta ei voida antaa takuita. - - - - Continue - Jatka - - - - Cancel - Peruuta - - - - EditDependencyDialog - - - Edit Dependency - Muokkaa riippuvuutta - - - - Dependency Type - Riippuvuuden tyyppi - - - - Dependency - Riippuvuus - - - - Package name, if "Other..." - Paketin nimi, jos "muu..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Valinnainen - - - - ExpandedView - - - - Icon - kuvake - - - - - <h1>Package Name</h1> - <h1>Paketin nimi</h1> - - - - - Version - Versio - - - - - (tags) - (tags) - - - - - Description - Kuvaus - - - - - Maintainer - Ylläpitäjä - - - - Update Available - Päivitys saatavilla - - - - labelSort - labelSort - - - - UpdateAvailable - Päivitys saatavilla - - - - Form - - - Licenses - Lisenssit - - - - License - Lisenssi - - - - License file - Lisenssitiedosto - - - - People - Ihmiset - - - - Kind - Laji - - - - Name - Nimi - - - - Email - Sähköposti - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD:in versio - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Tuetut FreeCAD-versiot - - - - Minimum FreeCAD Version Supported - Pienin tuettu FreeCAD-versio - - - - - Optional - Valinnainen - - - - Maximum FreeCAD Version Supported - Suurin tuettu FreeCAD-versio - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Lisäosien hallinnan asetukset - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Lataa Makrojen metatiedot (noin 10MB) - - - - Cache update frequency - Välimuistin päivitystiheys - - - - Manual (no automatic updates) - Manuaalinen (ei automaattisia päivityksiä) - - - - Daily - Päivittäin - - - - Weekly - Viikottain - - - - Hide Addons without a license - Piilota lisäosat ilman lisenssiä - - - - Hide Addons with non-FSF Free/Libre license - Piilota lisäosat, joilla ei ole FSF Free/Libre -lisenssiä - - - - Hide Addons with non-OSI-approved license - Piilota lisäosat, joiden lisenssi ei ole OSI: n hyväksymä - - - - Hide Addons marked Python 2 Only - Piilota Python 2: lle tarkoitetut lisäosat - - - - Hide Addons marked Obsolete - Piilota lisäosat jotka ovat vanhentuneet - - - - Hide Addons that require a newer version of FreeCAD - Piilota lisäosat, jotka vaativat uudemman version FreeCADista - - - - Custom repositories - Custom repositories - - - - Proxy - Välityspalvelin - - - - No proxy - Ei välityspalvelinta - - - - User system proxy - Käytä järjestelmän välityspalvelinta - - - - User-defined proxy: - Käyttäjän määrittelemä välityspalvelin: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Polku git-suoritustiedostoon (valinnainen): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Lisäasetukset - - - - Activate Addon Manager options intended for developers of new Addons. - Aktivoi Addon Managerin vaihtoehdot, jotka on tarkoitettu uusien lisäosien kehittäjille. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Asenna - - - - Uninstall - Poista asennus - - - - Update - Päivitä - - - - Run Macro - Suorita makro - - - - Change branch - Vaihda haaraa - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Hallitse Python-riippuvuuksia - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Paketin nimi - - - - Installed version - Asennettu versio - - - - Available version - Saatavilla oleva versio - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Päivitä kaikki saatavilla olevat - - - - SelectFromList - - - Dialog - Dialogi - - - - TextLabel - TekstiSelite - - - - UpdateAllDialog - - - Updating Addons - Päivitetään lisäosia - - - - Updating out-of-date addons... - Päivitetään vanhentuneita lisäosia... - - - - addContentDialog - - - Content Item - Sisältökohde - - - - Content type: - Sisältötyyppi: - - - - Macro - Makro - - - - Preference Pack - Preference Pack - - - - Workbench - Työpöytä - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Päämakrotiedosto - - - - The file with the macro's metadata in it - Tiedosto, jossa on makrojen metatiedot - - - - - - Browse... - Selaa... - - - - Preference Pack Name - Asetuspaketin nimi - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - kuvake - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tagit... - - - - Dependencies... - Riippuvuudet... - - - - FreeCAD Versions... - FreeCAD-versiot... - - - - Other Metadata - Muut metatiedot - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versio - - - - Description - Kuvaus - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semanttinen tyyli (1.2.3-beta) ja CalVer-tyyli (2022.08.30) tuettu - - - - Set to today (CalVer style) - Aseta tähän päivään (CalVer-tyyli) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Lisätäänkö painike? - - - - Add a toolbar button for this macro? - Lisää työkalupalkin painike tälle makrolle? - - - - Yes - Kyllä - - - - No - Ei - - - - Never - Ei koskaan - - - - change_branch - - - Change Branch - Vaihda haaraa - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Tekijänoikeustiedot - - - - Copyright holder: - Tekijänoikeuden haltija: - - - - Copyright year: - Tekijänoikeuden vuosi: - - - - personDialog - - - Add Person - Lisää henkilö - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Nimi: - - - - Email: - Sähköposti: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Välityspalvelimen kirjautuminen vaaditaan - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Välityspalvelin: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Käyttäjätunnus - - - - Password - Salasana - - - - selectLicenseDialog - - - Select a license - Valitse lisenssi - - - - About... - Tietoja... - - - - License name: - Lisenssin nimi: - - - - Path to license file: - Polku lisenssitiedostoon: - - - - (if required by license) - (jos lisenssi sitä edellyttää) - - - - Browse... - Selaa... - - - - Create... - Luo... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Valitse työkalupalkki - - - - Select a toolbar to add this macro to: - Valitse työkalurivi, johon tämä makro lisätään: - - - - Ask every time - Kysy joka kerta - - - - toolbar_button - - - - Add button? - Lisätäänkö painike? - - - - Add a toolbar button for this macro? - Lisää työkalupalkin painike tälle makrolle? - - - - Yes - Kyllä - - - - No - Ei - - - - Never - Ei koskaan - - - - AddonsInstaller - - - Starting up... - Käynnistyy... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Lisäosien hallinta - - - - You must restart FreeCAD for changes to take effect. - Käynnistä FreeCAD uudelleen, jotta muutokset tulevat voimaan. - - - - Restart now - Käynnistä uudelleen nyt - - - - Restart later - Käynnistä uudelleen myöhemmin - - - - - Refresh local cache - Päivitä paikallinen välimuisti - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Päivitetään välimuistia... - - - - - Checking for updates... - Tarkistetaan päivityksiä... - - - - Temporary installation of macro failed. - Makron väliaikainen asennus epäonnistui. - - - - - Close - Sulje - - - - Update all addons - Päivitä kaikki lisäosat - - - - Check for updates - Tarkista päivitykset - - - - Python dependencies... - Python-riippuvuudet... - - - - Developer tools... - Kehittäjätyökalut... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - Ei päivityksiä saatavilla - - - - - - Cannot launch a new installer until the previous one has finished. - Uutta asennusta ei voida käynnistää ennen kuin edellinen on valmis. - - - - - - - Maintainer - Ylläpitäjä - - - - - - - Author - Kehittäjä - - - - New Python Version Detected - Uusi Python-versio havaittu - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Käsitellään, odota hetki... - - - - - Update - Päivitä - - - - Updating... - Päivitetään... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Virhe salatussa yhteydessä - - - - - - Confirm remove - Vahvista poisto - - - - Are you sure you want to uninstall {}? - Oletko varma, että haluat poistaa {}? - - - - - - Removing Addon - Poistetaan lisäosa - - - - Removing {} - Poistetaan {} - - - - - Uninstall complete - Asennuksen poisto valmis - - - - - Uninstall failed - Asennuksen poistaminen epäonnistui - - - - Version {version} installed on {date} - Versio {version} asennettu {date} - - - - Version {version} installed - Versio {version} asennettu - - - - Installed on {date} - Asennettu {date} - - - - - - - Installed - Asennettu - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Päivitysten tarkistus käynnissä - - - - Installation location - Asennuksen sijainti - - - - Repository URL - Tietovaraston URL-osoite - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Tämä lisäosa on päivitetty. Käynnistä FreeCAD uudelleen nähdäksesi muutokset. - - - - Disabled - Pois käytöstä - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Päivitys saatavilla versioon {} - - - - This is the latest version available - Tämä on uusin saatavilla oleva versio - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Onnistui - - - - Install - Asenna - - - - Uninstall - Poista asennus - - - - Enable - Käytä - - - - Disable - Ota pois käytöstä - - - - - Check for update - Tarkista päivitykset - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Suorita - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Tarkistetaan yhteyttä - - - - Checking for connection to GitHub... - Tarkistetaan yhteyttä GitHubiin... - - - - Connection failed - Yhteys epäonnistui - - - - Missing dependency - Puuttuva riippuvuus - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automaattinen - - - - - Workbench - Työpöytä - - - - Addon - Lisäosa - - - - Python - Python - - - - Yes - Kyllä - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python-paketti - - - - - Other... - Muu... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Paina OK asentaaksesi joka tapauksessa. - - - - - Incompatible Python version - Yhteensopimaton Python-versio - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Asennetaan riippuvuuksia - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Paketin asennus epäonnistui - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Peruutetaan - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} asennettiin onnistuneesti - - - - - Installation Failed - Asennus epäonnistui - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Luo uusi työkalupalkki - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Suorita - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Nimi - - - - Class - Luokka - - - - Description - Kuvaus - - - - Subdirectory - Subdirectory - - - - Files - Tiedostot - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Asenna Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Asennus epäonnistui - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Suodatin on kelvollinen - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Etsi... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Tags - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Luotu - - - - Updated - Päivitetty - - - - Score: - Score: - - - - - Up-to-date - Ajan tasalla - - - - - - - - Update available - Päivitys saatavilla - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Asennettu versio - - - - Unknown version - Tuntematon versio - - - - Installed on - Asennettu - - - - Available version - Saatavilla oleva versio - - - - Filter by... - Filter by... - - - - Addon Type - Lisäosan tyyppi - - - - - Any - Mikä tahansa - - - - Macro - Makro - - - - Preference Pack - Preference Pack - - - - Installation Status - Asennuksen tila - - - - Not installed - Ei asennettu - - - - Filter - Suodatin - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Paikallinen - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Viimeksi päivitetty - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Tietovaraston URL-osoite - - - - Branch name - Preferences header for custom repositories - Haaran nimi - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Asennetaan - - - - Succeeded - Onnistui - - - - Failed - Epäonnistui - - - - Update was cancelled - Päivitys peruutettiin - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Aakkosjärjestyksessä - - - - Last Updated - Sort order - Viimeksi päivitetty - - - - Date Created - Sort order - Luontipäivä - - - - GitHub Stars - Sort order - GitHub-tähdet - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Lisäosien hallinta - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Seuraavien lisäosien päivittäminen on valmis - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Lisäosien hallinta - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_fil.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_fil.qm deleted file mode 100644 index aaaca96b09910d4214e59958ed3c5ab1ec776acd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29789 zcmdsg3v^vqdFGaFJ$)tl863xPPL#x!9qHP!$-~BRkR>^GV#%r{+t_4c&b{|Yy3u{* zJ}fJgqzjTEB_t_?Ov%8MQpzH*3Wdo$+VGeT8QMt*nQ6&lO*_CE1`3oWB@ECNGL+2s z?f>kv&$+ty>ME3(SzU^CuFgH@-~ayi|Nj5IbKs9so1XdM2Os^)fBTK8_)2XeUn=CwFi}Ic~q`D@0aVg>;X{hV@VD@xt*UFE$nsnq7Lskh$q zDWuRi_1yOcV1wfd9(R;BiLtG{~RZAz{Fg!)GB7jXT#df`7kp;YJn>XmOltJKDq zTDl&{Vf?3CZfe8*i{9FDtn~`uyRD`0RlwWvotF7WKCaXyFUs}ccUnGj-%8B$M=g(E z@lD*1wfx%`jw%&@q~){ET?Sf@$u+aH<*A9cDK&Yj<*R>&=lI(_X<9AnG`CkZkYSq41KZK4+M1Z#sMPHrZ=L-P@J}6U&CFZ{{J-CN;lr*{m%6PB`Defnf7^QR6QfFveZTdA zcVL}nx3#|aGT?La<<{T(I@W#XcUwRCr?)7T{%@^+`Z(~t`O((@{zdT3$f4F(e;?1^ z^tLwj4e-<1KW}R}c%M>TLv5{%!N32b?Qd@R9lZZext@5tT+=7oZ@&-t#P_rpraq;V`=0i<{z<1& z!>RU%AAp?A?Qefy9CRCbvHkr?ti$Z@wSU^(qE!Fi%XRPO_GjauN6%#YS61E*x_qzw z`Op0})@ObD_wN9`t~%WQ(>?nE_tlPd-vb?P{aVMpAN@w2bZ-&(Bm>%ZQ$??*d9kB7R(rnf3}>NmU2z5imR zu77jaUH|cuN}YMI>u&dUrEdF5*JH6SfFB;{dh!j=LH=gC{_Ma}@IznMH`n9&{lDGy z;;WEP^mpIR{WiQboB#I z{6eY3=VPtKGS*+kTE7LnrtXWy+CGZ)c`$a_C;lbm??bV8azUxS$6~u4+oRNpFUH3E z!3UTBJa%TP0{$F}S`3MEBYoF^}8s?Y{UgeiQ5U zs$6gD>AvxSP0(YnbRU_^DRn&AT{!wU^xikS@BjRLSic|1_3Ep-zx#)nhr7M|rOb~( z->>!b{}_C|qSSN!QLNu}8+s0X;!}A4TRq3SLD$ZGJrlnJ{&tS{c%Q}dx1R2q?|lYz za(iBie+191>v{RkIOPA~-n~!$Pw18FdvAE^A<*e>d-t#JRO;YV?~QN#0r+Ek@1cYL zMyWUK?oIyv-#~BwRj}5`_*5A9=iO&-WRvx{&cMOr=#Pb^AGV-_TH6P`ItJSipo_vl~l7G zxS`tk?@-arC1>05@#3LWYPeD==d&lgLcWwP=Zgy?X*ZLfY2o{QYFJfNNtIPzWt9V1 zo+{vTNu~9@qFM-`t`#^=F#y!W09(|F#UL@zN!&jcfbOx#IVVpXYXa^zbwDN5K{bKN zC)FH&&tM!!jpI`mpAM*9{5}|A{ei^62{$?C&UntaoAnOtN*v@ctB3R1f}1R#N_+E~ zBAYbG8I=Jb{v&ng@h=yET0P>GlErkPoX+QJg6IN>JYLKyH+X5);e0V$=jo$-Qq3yQ zK7BM<2liG_uAowQzKmH8sq^@h)`%wX+d}9)SxC8MZ|J<6&bWz;S99ndaE}K>OKJfK z+Znc>@`|N;v)iOb@KOQ)a=?SXlfb}Jr2zZbh*$7(DKD2ydnFFMCb$viy{$C>Eno@D zzy{z0aJ}|zr@ThJcjb6JPSV7j#&S(|aygn-H)Nu@1#ymg<{qjx0@SVr?O1qhx z>c7859oC}bL7av#EeF3-_#re)m!88#&l?^ZaUhfVoTkiXJGT>FDW9p3sY3D@Uxb*0 zIW7RzSq*O&|g^M2=>U9QbXJVl|o6kAfe5#U>)mVB=itL?$nbwm^VLDBXdBVH1 zk}i6w*Dz+kRud)6B?FeGATPya8#KMndrm+>pV^j}UdtBFn!;GV1Rk+ei$ zS|gLe?|D2;rV{lSB@9(B36!tm9|w19N{Nc&=`(n~f@{`SzK$M&YM6|h!8d{hRdNDw zhznJ-++U1)67S{wXB`dG!}xL4g`W|;>u3Szh+35ax)~u#gE0+9bZJpP!*@CR+PJwG zOH2p#Q5u>+@Ly0j;k{waq%}E0q zk#!Q@biU}}a{xW*=5W`kl)O~Dt7|0hEa1g?H&@nUYDM6TxjC4nqEpUCp}7^9ZMU3G z0{+5H&hTtLU-F#3qcb@S(pUAkKb!e9#Jv)r#p!Tz5#*`ImXH#)LG>?EJv##Wb@dzl zvV*|Zk9g<3Oupb1$MPvJq`r>TfHHvfqh8E_CmppHTzUal3Ox;xXkZ7QDv&6;B1Nn? zx!I1sEf{^k$>%Z)&ffS1=e(FKr&K8v^2M^3YK+-tU`92U#0XjZ7;6?Dr@Q}zm&|9g zv}H?x+Y(avWPDDLX!Cc-0LXd|=W}H*SJnogF6nkgAW|EWL{vvKy%f$Ve5Ss%@HYzl zU^Send_L27m<^F(eDBGwvj8;4vo5mhv>QrINm-BcCxFp;sFA**Zwhzb-$ z8FLetPG(uQnFH_^R?9cT5bSRgjfI%xDX}^iKxbAl>2tP>EKO5pi0fd$b^+{3Db1c zq*medE(n{-+o<0p?p1Kt7$sik@qJN0*;nNd^(l(IF_zZs(YWzG6#z{~TECsbmFAAb zCPXR=q~IDQ z8GboA_@Yo;4$X$Iu3%=oB2+!pb!nkg_OhkM($c5RI(bP{7aa%VzE%fUYe(|Q3Y1tG z@S9+(O==VxS(u7Mw_t@u=C!9}Jcz}!8$a7i^A{W6S7HarR}$l7FC!-P4_ zARM6tEQLwLPYQcUWFT4-A&_BK&MN$rKqed3_v0#6n7f)SKK)YHY#au%6UnzRC2)`@E`;j+yS^2WpbE-kB40+5=As-lP*xMZfsds z+pSS!pe-pTai)!8JI1`Si@4HVLY0qUt#bHBL8lKJ3LgUD>lsVu(%DMZj}{t2+^hpT z`gdG4u4oWn1@O8j-101)B5ku8g4+UcMU9?eoP^dG(JV^OL@}M^iX?(;N?np|fHN@) zq((rxQJ@#q>Rl&BhepOmm(u9!H785z;&m4^IJF)%uQ=!q9G`0-lzZ@RuNu_h1($jU zu%@o1_d?xz3h(i+emuDw|M>iFb%TCuw|<&JwSXrnf;AkrU}0{Y^s;bx(@CfQn)sgh z-oXTzXomwfA9gdyG&ucxcJJ8}-+e=T@9rI7`31zOMlX7)h6{O}o}S1uxq`ewo~6O) zubPNO*LsqdOnQ*qJpN0$3r@d}k4B-P``D6z_jMFpv>yXaYGzM@4vSR^Em^gNHo*)< zq*~$7O3Hl`%mj>%Z=&IuJlmXN6rtfd&uKjATyxC|xFeWTi7x1|8R&9!39F2kAn)~s zg6F1`Cio?e(9Z#<4dVA5+WR5SG9G;f2Hr9Y{$|odn~i{fJ~MT6V!ty9d+SG5(1NMJ za5Lb6@%EMCKutrAyEPOo*WH~%Y*uheNCA3I$z70m3BPIj@m-$|6lVO$MDG4gZBeaBx zD#_>f!eLppKfr1alI2-9Pnrb6zwF^p8WX4DR&fDW(?q{RPZY z*q5<2&Bisba$|@^t&tcQ$qFZHrKnX^GfV)}rC^dNUCDB%Pbi*I3ha@S$iqX%D7^Ujrg_j;5ey zr@(O4taYzC0-HRJH)xfOTrd+uduF(v*o9-)KBzH<5cHB*LRo;dqGe?SI|@!Pf6*l_ zL5rBb$F=4?1YIC^xTMKYY6WN?taRS?C);&^S8A%a~W1 z<#qhzi9?h4;FXiwjD&e<4JJpHHmqw)a~#4gg@d{7^U7%4H7#U*uOIB56oT2!$uOO{e6hA(=vJ<|pzR>r5E? z0POk`-gFU!b2544NCod|gg0S@Z1i7?c(F+xan~eZ%R%k%ka$!rbWWHH7Y9k)77~># zCaDavmqeRPPlyVp>5=R`RWo6k7?u(BG#H%~G?7`VAW`9Deu=oFF)5kT%6t?a|6=6r z!L5?96I!Vm!xM$XS$Kez#afBd6eo`<6@kmLAgcy*8sm9s}Ji`iXHreGXeP>mhUQ;vbVM`RVC&5@l*=A=nz7f(bl4t)Tqpir#q?Zt-?v zK^sdG8<#yd8;8Dz3sM6R0;Nz+l#5@M>W6UaUlosw@Z^rWoD z_H$Z>CKE+(8Z?F*U2;(8Nag1jX_!7JHS2-dBwNT^3s!WkRG77u5ErbPhT8y*R4T$X zp`IY8GiyT=9q6!-d$Imx$tw<~yym0zTXDzN<|Ct)+BU|n0l2q3L9uP?X8d>U#|>51#7w2Ov;|5m_M(d*^{5dtTRbNqfQT+ z(nfk1sKl1zN@7PWm3+s$)w3{Ek)(j>sj*i4$)nTYN(94};u77^k%Q5irb8xNB0E;8IGp_#{f){%${L`E9{UnTZ8Sx6;0xD9D z&vA`uvg~TcGPRZZL3)${YB>z`1%xicBv>#3RVSW0)8`ZL;D{5kJb)|PD#Wzi2>Q+9 zei@=s0-bl^XGXs{tD(ewwYjUxI9C5X2&mQ(>q86JKR#48kGX(s6gX$VwhsyyXC@eM z)}~x7jvD7%M|fHW$B$2q?sp(UeaC6E5%%;^kV;+#Wg#ymqGQYqzK|M|2-LA-$4`%r zoSQf^b>#T?xrw3STZe8Qos5?+lpVCNdjr~FSb(F42OgEVh!vha{R z1Aw%yOQDeBHYcxY4J0Jet`(T?4%3&=(2l6h{X~G^#sjn0RP{UJ z22ooKfBALt#V{JSJl1-=L0xL`;~TWQL~TXV@d{%c%(ZLGO{2I8r?FUjg1=19d|DM)5wFa{<+w^UR|B_DF*wLD3*0c}D zAg~_X7?!1NXK34mmoG?ft9^7g3}#B_y(Erev?0YT+jK$in<+q&a3+}DrlHh%^i3o7 z@cUm8Ko$y!4ms1ye9h;7HIcl4R8?;-@CcO|eW!tGDe4^Kp-D0q zrX|4YszXqdgEp#@Y9!2sJ0ornGEC`m(7eVla)i3cRRwqb9L(nW4mZ(xumvZEb_9=x6*v`9wQRwT_pb!T^q9= zqN&6636Tp^!m9@>I$tx}>RI*!gE-cou2ge48hoOis%-xe$E5bSlBr>w5T>g{GSxIZ zkMwsO#%7=9Ne8Lg1SG@IG}JiJ9d}CDgltK#UkhY9c z#gJBuY9>1cCbOa^K6|9GGLZPo$6VAh(2!xsddhF9oHQ+!)B#H%Ly5P2AHNJTes{=g zMW#s~vB7j+uj88ttsp{;r(~_(=74I|^wf5+!MN`NJ2A3MYXc%x-mu`(c+p+uh8GHT zIPF2z$|c}ivOR<5&s02XDM+K7=us%jxrMMv98JbVnm2z>Zcpty*fW zm{Uk|$fxO-q%MBt&6V{2{ldbyW@b#SOF!e+nzbv`AHqedl@uzbNvOIx^DI7NP5}pR z5afdKx$8lfWSbu}+ICB+txM`)SikKSO)k2P+ouVIrTKAVp~+e%Y7@dO50tDSoe%2( zh2td)eodfwBy7^0**wlU;9Nhs5bgjl3>ePTl2s*9AoUXVc{7J*f^BI5 zwfX@<1$)M@NCBa2(C@eMmmGw!TA?>Ty8$F$YL?4@(R6?%#Vi@xBzMtpsCec~>nJyu z)G65Jhu(&vncSm^uDvTSy5VYl_0BwhD@^kva+`>3B(oXh))7P}%f$RF;4tKH{j{f9 zJTB}s?n**6p$W@Wr#K;JbuX3l{)9{A;wZ{i0lWNz=&E#)G31&${nM;cClHP^sc`n_ z1Uhh}hz`dDdjpoa=>H#f6Ewew*CBN%UAIv+PDRNo9jkjZ2gk8Evek0R6pT^mQMvuaV%6n?f`zD?U;+-cn+*!BTkFfYm-vm?DUn`DhAPS2Qwi z1)HxKA}uQ64RqO5tSiNEowda_0o~Q+J5V;*_gm1q`gPqUux12&bGqycLXb3;!Uuq$ z<3z_dvX@|)I&i;VoUDK=GN5Ze)|hQ4i#Pj4x=6qWmP(hxk*l~Fr$3jsxoFcuv`l=O zY

    6yf@EI_PvOry=4}`g~FOW%X#_L>)#cMdz#t2nJ;9idlecn;ol7Xx)dDNi=s& z=YUoDMZEe8CCZQ2hCCQOKmSGvYIElX1oF`?eEx1+%`k|N*=TG?oA#7^(M#PNxUu5k zQE^*096}^~?~LS^#aNLYa-`xqTQ5OC0XGw|M zT!;~+u`FFdTK-afMeI2UND8c1lld9dlGLBnuq^|Yr2$gROj(?bQ{TL0`(AFLlvABjKzoaB{FPk#NKEKw=i6d$_bKrGx)*8~28(!p4$v(DtDuvw zMR|Q6;!f;xON7tYji$~gxJmYP)O|R#9P7dWRCX*n^I6{^Ob8yGtAJJsU~^*-BePQ- z)t5#yK9LI=EqXRaugyK1(ev{J|MchQ%yi0J^y|p-b0egk9;>`^G4ZoVuyAEe!jbjJ z%0+}{*9j9J?YeOL60X9sR8n~oqBp1%EE$-7q@hL$?wL{u9Xzqq9wpP-^11LXR-T_n zsm=V3qH6Vsnxvw4rU{BMz_urPNjCL*m|mGrIfLlqUTzdX>q-JKT)Ny;Na1Mm{ASi&Tl(5lX-#v(oOknj# zzCZoQbA=)N{7o2$21(IO1;xUm)A+6hx7+&J!QypZUTKfoTB!(!;X*Zzc&Jc`HJv@1c~KFp1E3je&s#WyWUlVxAEeSMjJdUFOs>D!PY}~U zq_1y`IR8N2aT~GJ;>tJ*(BzQFo|6D&u6L#aZ2uR%m*%kNqLtObx-8|!sO+bdd!wv# TQtrVhkEHn7t3hNls;d4UPX>j$ diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_gl.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_gl.ts deleted file mode 100644 index 5f34b2808c..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_gl.ts +++ /dev/null @@ -1,2516 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Custom repository - - - - Repository URL - Repository URL - - - - Branch - Branch - - - - CompactView - - - - Icon - Icona - - - - - <b>Package Name</b> - <b>Package Name</b> - - - - - Version - Versión - - - - - Description - Descrición - - - - Update Available - Update Available - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - Dependencies - - - - Dependency type - Dependency type - - - - Name - Nome - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Descrición - - - - Discussion URL - Discussion URL - - - - Icon - Icona - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Repository URL - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Versión - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Xestor de complementos - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Welcome to the Addon Manager - Welcome to the Addon Manager - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Download Settings - Download Settings - - - - Automatically check installed Addons for updates - Automatically check installed Addons for updates - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - No proxy - Sen proxy - - - - System proxy - System proxy - - - - User-defined proxy: - User-defined proxy: - - - - These and other settings are available in the FreeCAD Preferences window. - These and other settings are available in the FreeCAD Preferences window. - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - - Icon - Icona - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - Versión - - - - - (tags) - (tags) - - - - - Description - Descrición - - - - - Maintainer - Mantedor - - - - Update Available - Update Available - - - - labelSort - labelSort - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - Licenses - Licenses - - - - License - Licenza - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - Nome - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires git) - Automatically check for updates at start (requires git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manual (no automatic updates) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Proxy - Proxy - - - - No proxy - Sen proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to git executable (optional): - Path to git executable (optional): - - - - The path to the git executable. Autodetected if needed and not specified. - The path to the git executable. Autodetected if needed and not specified. - - - - Advanced Options - Advanced Options - - - - Show option to change branches (requires git) - Show option to change branches (requires git) - - - - Disable git (fall back to ZIP downloads only) - Disable git (fall back to ZIP downloads only) - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Instalado - - - - Uninstall - Desinstalar - - - - Update - Actualizar - - - - Run Macro - Executar macro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Xanela de diálogo - - - - TextLabel - TextLabel - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Macro - - - - Preference Pack - Preference Pack - - - - Workbench - Banco de traballo - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Icona - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versión - - - - Description - Descrición - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Cambiar Rama - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Nome: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - AddonsInstaller - - - Starting up... - Starting up... - - - - Loading addon information - Loading addon information - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - Actualiza a caché local - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - Checking for updates... - - - - - Close - Pechar - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - Execution of macro failed. See console for failure details. - Execution of macro failed. See console for failure details. - - - - - - - Maintainer - Mantedor - - - - - - - Author - Autor - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Actualizar - - - - Updating... - Updating... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installation location - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Disabled - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Branch change succeeded, please restart to use the new version. - Branch change succeeded, please restart to use the new version. - - - - Install - Instalado - - - - Uninstall - Desinstalar - - - - Enable - Habilitar - - - - Disable - Inhabilitar - - - - - Check for update - Check for update - - - - Run - Executar - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automática - - - - - Workbench - Banco de traballo - - - - Addon - Complementos - - - - Python - Python - - - - Yes - Yes - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Other... - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually: - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This Addon (or one if its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one if its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Executar - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Nome - - - - Class - Clase - - - - Description - Descrición - - - - Subdirectory - Subdirectory - - - - Files - Ficheiros - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Atopar... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Etiquetas - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Installed version - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Available version - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Calquera - - - - Macro - Macro - - - - Preference Pack - Preference Pack - - - - Installation Status - Installation Status - - - - Not installed - Not installed - - - - Filter - Filtro - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded package.xml for {} - Downloaded package.xml for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Downloaded metadata.txt for {} - Downloaded metadata.txt for {} - - - - Downloaded requirements.txt for {} - Downloaded requirements.txt for {} - - - - Downloaded icon for {} - Downloaded icon for {} - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Git is disabled, skipping git macros - Git is disabled, skipping git macros - - - - Attempting to change non-git Macro setup to use git - - Attempting to change non-git Macro setup to use git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Unable to fetch git updates for workbench {} - Unable to fetch git updates for workbench {} - - - - git status failed for {} - git status failed for {} - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Caching macro code... - Caching macro code... - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Getting metadata from macro {} - Getting metadata from macro {} - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Retrieving macro description... - Retrieving macro description... - - - - Retrieving info from git - Retrieving info from git - - - - Retrieving info from wiki - Retrieving info from wiki - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Repository URL - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic git update failed with the following message: - Basic git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using git - Failed to clone {} into {} using git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Xestor de complementos - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_hr.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_hr.qm deleted file mode 100644 index e709f1e330e339cc46da0a418210ebd706926b11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70490 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_hr.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_hr.ts deleted file mode 100644 index 1d8f9af8d9..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_hr.ts +++ /dev/null @@ -1,2486 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - PrilagoÄ‘eno spremiÅ¡te - - - - Repository URL - URL repozitorija - - - - Branch - Grana - - - - CompactView - - - - Icon - Ikona - - - - - <b>Package Name</b> - <b>Naziv paketa</b> - - - - - Version - Verzija - - - - - Description - Opis - - - - Update Available - Dostupno je ažuriranje - - - - UpdateAvailable - Dostupno ažuriranje - - - - DependencyDialog - - - Dependencies - Ovisnosti - - - - Dependency type - Vrsta ovisnosti - - - - Name - Ime - - - - Optional? - Opcije? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - RazrijeÅ¡i zavisnosti - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Ovaj dodatak zahtjeva slijedeće obavezne i neobavezne ovisnosti. Morate instalirati ovisnosti prije nego Å¡to ovaj dodatak može biti pokrenut. - -Da li želite da Upravitelj dodacima ih instalira automatski? Odaberi "Ignore" kako bi instalirali dodatak bez da intalirate ovisnosti. - - - - FreeCAD Addons - FreeCAD Dodatci - - - - Required Python modules - Potrebni Python moduli - - - - Optional Python modules - Opcionalni Python moduli - - - - DeveloperModeDialog - - - Addon Developer Tools - Alati dodataka za razvojne programere - - - - Path to Addon - Put do Dodatka - - - - - Browse... - Pretraživati... - - - - Metadata - Metapodaci - - - - Primary branch - Glavna grana - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - ObjaÅ¡njenje onoga Å¡to ovaj dodatak pruža. Prikazuje se u Upravitelju dodataka. Nije potrebno navesti da je to dodatak FreeCAD-a. - - - - Description - Opis - - - - Discussion URL - URL adresa diskusije - - - - Icon - Ikona - - - - Bugtracker URL - URL adresa sustava za praćenje pogreÅ¡aka - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Podržani su stilovi Semantic (1.2.3-beta) ili CalVer (2022.08.30) - - - - Set to today (CalVer style) - Podesi na danas (CalVer stil) - - - - - - - (Optional) - (Opcionalno) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Prikazuje se u popisu dodataka upravitelja dodataka. Ne smije sadržavati rijeÄ "FreeCAD" i mora biti valjano ime direktorija na svim podržanim operativnim sustavima. - - - - README URL - URL README (proÄitaj) - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - Savjet: Budući da se ovo prikazuje u FreeCAD-u, u upravitelju dodataka, nije potrebno gubiti prostor govoreći stvari poput "Ovo je dodatak FreeCAD-a..." -- samo recite Å¡to ono radi. - - - - Repository URL - URL repozitorija - - - - Website URL - URL adresa web stranice - - - - Documentation URL - URL adresa dokumentacije - - - - Addon Name - Ime Dodatka - - - - Version - Verzija - - - - (Recommended) - (PreporuÄeno) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Opcionalno, podržana je samo verzija 3.x) - - - - Detect... - Otkri... - - - - Addon Contents - Sadržaj dodatka - - - - Dialog - - - Addon Manager - Upravitelj dodataka - - - - Edit Tags - Uredi Oznake - - - - Comma-separated list of tags describing this item: - Lista tagova odvojenih zarezom opisuje ovu stavku: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - Napomena: UobiÄajeni tagovi ukljuÄuju "Assembly", "FEM", "Mesh", "NURBS" itd. - - - - Add-on Manager: Warning! - Upravitelj Dodataka: Upozorenje! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Add-on Manager omogućuje pristup opsežnoj biblioteci korisnih FreeCAD proÅ¡irenja trećih strana. Ne mogu se dati nikakva jamstva u pogledu njihove sigurnosti ili funkcionalnosti. - - - - Continue - Nastavi - - - - Cancel - Otkazati - - - - EditDependencyDialog - - - Edit Dependency - Uredi ovisnost - - - - - - Dependency Type - Vrsta ovisnosti - - - - Dependency - Ovisnost - - - - Package name, if "Other..." - Ime paketa, ako je "Ostalo..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NAPOMENA: Ako je "Ostalo..." izabran, paket se ne nalazi u datoteci ALLOVED_PYTHON_PACKAGES.txt i upravitelj dodataka ga neće automatski instalirati. PoÅ¡alji PR na <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> za zahtjev dodavanja paketa. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Ako je ovisnost opcionalna, Upravitelj dodataka će ponuditi da je instalira (kad god je to moguće), ali neće blokirati instalaciju ako korisnik ne želi ili ne može instalirati paket. - - - - Optional - Opcionalno - - - - ExpandedView - - - - Icon - Ikona - - - - - <h1>Package Name</h1> - <h1>Naziv paketa</h1> - - - - - Version - Verzija - - - - - (tags) - (oznake) - - - - - Description - Opis - - - - - Maintainer - Održavatelj - - - - Update Available - Dostupno je ažuriranje - - - - labelSort - labelSort - - - - UpdateAvailable - Dostupno ažuriranje - - - - Form - - - Licenses - Licence - - - - License - Licenca - - - - License file - Datoteka licence - - - - People - Osobe - - - - Kind - Vrsta - - - - Name - Ime - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Napredno mapiranje verzija - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Buduće verzije Upravitelja dodataka FreeCAD-a podržat će postavljanje odreÄ‘ene grane ili oznake za koriÅ¡tenje s odreÄ‘enom verzijom FreeCAD-a (npr. postavljanje odreÄ‘ene oznake kao posljednje verzije vaÅ¡eg dodatka za podrÅ¡ku v0.19 itd.) - - - - FreeCAD Version - Verzija FreeCAD-a - - - - Best-available branch, tag, or commit - Najbolja dostupna grana, oznaka ili objava - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Podržane FreeCAD inaÄice - - - - Minimum FreeCAD Version Supported - Minimalna FreeCAD verzija koja je podržana - - - - - Optional - Opcionalno - - - - Maximum FreeCAD Version Supported - Maksimalna FreeCAD verzija koja je podržana - - - - Advanced version mapping... - Napredno mapiranje verzija... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opcije ureÄ‘ivaÄa dodataka - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Aako je ova opcija odabrana, kada pokrenete Upravitelj dodataka instalirani dodatci će biti na provjeri za nova ažuriranja. - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Preuzmi meta podatke makro naredbe (otprilike 10MB) - - - - Cache update frequency - UÄestalost ažuriranja predmemorije - - - - Manual (no automatic updates) - RuÄno (nema automatskih ažuriranja) - - - - Daily - Dnevno - - - - Weekly - Tjedno - - - - Hide Addons without a license - Skriva dodatke bez licence - - - - Hide Addons with non-FSF Free/Libre license - Skriva dodatke sa non-FSF Free/Libre licencom - - - - Hide Addons with non-OSI-approved license - Skriva dodatke sa non-OSI-approved licencom - - - - Hide Addons marked Python 2 Only - Skriva dodatak oznaÄen samo za Python 2 - - - - Hide Addons marked Obsolete - Skriva dodatake oznaÄene zastarjelim - - - - Hide Addons that require a newer version of FreeCAD - Sakrij dodatke koji zahtjevaju noviju verziju FreeCAD-a - - - - Custom repositories - PrilagoÄ‘ena spremiÅ¡ta - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - KorisniÄki definiran proxy: - - - - Score source URL - Bodovi izvornog URL-a - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - URL za podatke o ocjeni dodataka (vidi wiki stranicu Addon Managera za formatiranje i detalje o hostingu). - - - - Path to Git executable (optional): - Putanja ka izvrÅ¡noj git datoteci (neobavezno): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Napredne opcije - - - - Activate Addon Manager options intended for developers of new Addons. - Aktivirajte Upravitelj dodataka opcije namijenjene programerima novih Dodataka. - - - - Addon developer mode - Dodatak Developer mod - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Deinstaliraj oznaÄenu makronaredbu ili radni stol - - - - Install - Instaliraj - - - - Uninstall - Deinstaliraj - - - - Update - Ažuriraj - - - - Run Macro - Izvedi makronaredbu - - - - Change branch - Promijeni granu - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Upravljanje sa Python zavisnostima - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Sljedeće Python pakete je lokalno instalirao Upravitelj dodataka da bi zadovoljio zavisnosti dodataka. Lokacija instalacije: - - - - Package name - Naziv paketa - - - - Installed version - Instalirana verzija - - - - Available version - Dostupna verzija - - - - Used by - KoriÅ¡ten od - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Zvjezdica t.j. asteriks (*) u polju "KoriÅ¡teno od" stupca oznaÄava neobaveznu zavisnost. Imaj na umu da 'KoriÅ¡teno od' samo snima direktne uvoze u Dodatak. Možda su instalirani i drugi Python paketi od kojih ti paketi zavise. - - - - Update all available - Ažurirajte sve dostupno - - - - SelectFromList - - - Dialog - Dijalog - - - - TextLabel - Tekst oznaka - - - - UpdateAllDialog - - - Updating Addons - Ažuriraj Dodatke - - - - Updating out-of-date addons... - Ažuriranje zastarjelih dodataka... - - - - addContentDialog - - - Content Item - Sastavni dio - - - - Content type: - Vrsta sadržaja: - - - - Macro - Makro naredbe - - - - Preference Pack - Paket postavki - - - - Workbench - Radni prostor - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Ako je ovo jedina stvar u Dodatku, svi ostali metapodaci mogu biti nasljeÄ‘eni sa najviÅ¡e razine i ne moraju se ovdje navoditi. - - - - This is the only item in the Addon - Ovo je jedina stavka u Dodatku - - - - Main macro file - Glavna datoteka makro naredbe - - - - The file with the macro's metadata in it - Datoteka sa metapodacima makro naredbe u njoj - - - - - - Browse... - Pretraživati... - - - - Preference Pack Name - Ime paketa postavki - - - - Workbench class name - Naziv klase Radnog stola - - - - Class that defines "Icon" data member - Klasa koja odreÄ‘uje podatak Älana "Icon" - - - - Subdirectory - Poddirektorij - - - - Optional, defaults to name of content item - Izborno, zadano je ime stavke sadržaja - - - - Icon - Ikona - - - - Optional, defaults to inheriting from top-level Addon - Opciono, podrazumjevano nasljeÄ‘ivanje od Dodatka najviÅ¡e razine - - - - Tags... - Oznake... - - - - Dependencies... - Ovisnosti... - - - - FreeCAD Versions... - Verzija FreeCAD-a... - - - - Other Metadata - Ostali Metapodaci - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Prikazuje se na listi Upravitelja dodataka. Ne bi trebalo da sadrži rijeÄ "FreeCAD". - - - - Version - Verzija - - - - Description - Opis - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Podržani su stilovi Semantic (1.2.3-beta) ili CalVer (2022.08.30) - - - - Set to today (CalVer style) - Podesi na danas (CalVer stil) - - - - Display Name - Ime za prikaz - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Sva polja ostavljena prazna su naslijeÄ‘ena od meta podataka dodatka najviÅ¡e razine, tako da tehniÄki, sva su neobavezna. Za dodatke sa viÅ¡e stavki sa sadržajem, svaka stavka treba da omogući jedinstveno ime i opis. - - - - add_toolbar_button_dialog - - - Add button? - Dodaj tipku? - - - - Add a toolbar button for this macro? - Dodaj tipku alatne trake za ovu makro naredbu - - - - Yes - Da - - - - No - Ne - - - - Never - Nikada - - - - change_branch - - - Change Branch - Promijeni granu - - - - Change to branch: - Promijeni na Git_granu: - - - - copyrightInformationDialog - - - Copyright Information - Copyright informacija - - - - Copyright holder: - Nositelj autorskih prava: - - - - Copyright year: - Godina autorskog prava: - - - - personDialog - - - Add Person - Dodaj osobu - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Održavatelj zadužen za održavanje je neko sa trenutnim pristupom ovom projektu. Autor je neko, kome možeÅ¡ da odaÅ¡ priznanje. - - - - Name: - Naziv: - - - - Email: - E-mail: - - - - Email is required for maintainers, and optional for authors. - E-poÅ¡ta je neophodna za osobu odgovornu za održavanje, a neobavezna za autore. - - - - proxy_authentication - - - Proxy login required - Potrebni Proxy login podaci - - - - Proxy requires authentication - Proksi zahtjeva autentifikaciju - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Rezervirano mjesto za proksi adresu - - - - Realm: - Oblast: - - - - Placeholder for proxy realm - Rezervirano mjesto za proxy oblast - - - - Username - KorisniÄko ime - - - - Password - Zaporka - - - - selectLicenseDialog - - - Select a license - Odaberite licence - - - - About... - O... - - - - License name: - Naziv licence: - - - - Path to license file: - Putanja do datoteke licence: - - - - (if required by license) - (ako to zahtijeva licenca) - - - - Browse... - Pretraživati... - - - - Create... - Stvori... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Odaberi Alatnu traku - - - - Select a toolbar to add this macro to: - Odaberi Alatnu traku za dodavanje ove makro naredbe u: - - - - Ask every time - Pitaj svaki put - - - - toolbar_button - - - - Add button? - Dodaj tipku? - - - - Add a toolbar button for this macro? - Dodaj tipku alatne trake za ovu makro naredbu - - - - Yes - Da - - - - No - Ne - - - - Never - Nikada - - - - AddonsInstaller - - - Starting up... - PokreÄe se... - - - - Worker process {} is taking a long time to stop... - Radni proces {} se dugo zaustavlja... - - - - Previous cache process was interrupted, restarting... - - Prethodni proces meÄ‘uspremanja je prekinut, ponovo se pokreće... - - - - - Custom repo list changed, forcing recache... - - KorisniÄka lista spremiÅ¡ta je promjenjena, prisilno ponovno meÄ‘uspremanje... - - - - - Addon manager - Upravitelj dodataka - - - - You must restart FreeCAD for changes to take effect. - Za primjenu promjene, ponovo pokreni FreeCAD. - - - - Restart now - Ponovno pokreni sada - - - - Restart later - Ponovno pokreni kasnije - - - - - Refresh local cache - Osvježite lokalnu predmemoriju - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Ažuriram meÄ‘uspremnik… - - - - - Checking for updates... - Provjeri ima li ažuriranja... - - - - Temporary installation of macro failed. - Instalacija makro naredbe privremeno nije uspjela. - - - - - Close - Zatvori - - - - Update all addons - Ažuriraj sve dodatke - - - - Check for updates - Provjeri ažuriranja - - - - Python dependencies... - Pythonove ovisnosti ... - - - - Developer tools... - Razvojni alati... - - - - Apply %n available update(s) - Primjeni %n dostupno(a) ažuriranja - - - - No updates available - Nema dostupnih ažuriranja - - - - - - Cannot launch a new installer until the previous one has finished. - Ne može se pokrenuti novi program za instaliranje dok se prethodni ne zavrÅ¡i. - - - - - - - Maintainer - Održavatelj - - - - - - - Author - Autor - - - - New Python Version Detected - Otkrivena nova verzija Pythona - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - ÄŒini se da je ovo prvi put da je ova verzija Python-a koriÅ¡tena sa Upraviteljem dodataka. Da li želiÅ¡ da za njega instaliraÅ¡ iste automatski instalirane zavisnosti? - - - - Processing, please wait... - U obradi, saÄekaj... - - - - - Update - Ažuriraj - - - - Updating... - Ažuriranje... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Nije moguće uvesti QtNetwork -- izgleda da nije instaliran na tvom operativnom sustavu. Tvoj davatelj usluga možda ima paket za ovu zavisnost (Äesto se na primjer naziva, "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Konvertiranje navedenog proksi porta '{}' nije uspjelo - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - GreÅ¡ka u parametru: postavljene su meÄ‘usobno iskljuÄive proksi opcije. Vraćanje na zadane vrijednosti. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - GreÅ¡ka u parametru: korisniÄki proksi je oznaÄen, ali nije moguće. Vraćanje na zadane vrijednosti. - - - - Addon Manager: Unexpected {} response from server - Upravitelj dodataka: NeoÄekivani {} odgovor s poslužitelja - - - - Error with encrypted connection - PogreÅ¡ka s Å¡ifriranom vezom - - - - - - Confirm remove - Potvrdi uklanjanje - - - - Are you sure you want to uninstall {}? - Da li ste sigurni da želite deinstalirati {}? - - - - - - Removing Addon - Uklanjanje dodatka - - - - Removing {} - Uklanjanje {} - - - - - Uninstall complete - Deinstaliranje zavrÅ¡eno - - - - - Uninstall failed - Deinstaliranje nije uspjelo - - - - Version {version} installed on {date} - Dana {date} instalirana je verzija {version} - - - - Version {version} installed - Instalirana {version} verzija - - - - Installed on {date} - Instalirano {date} - - - - - - - Installed - Instalirano - - - - Currently on branch {}, name changed to {} - Trenutno na grani {}, naziv promijenjen u {} - - - - Git tag '{}' checked out, no updates possible - Oznaka Git-a '{}' provjerena, ažuriranja nisu moguća - - - - Update check in progress - Provjera ažuriranja u tijeku - - - - Installation location - Mjesto instaliranja - - - - Repository URL - URL repozitorija - - - - Changed to branch '{}' -- please restart to use Addon. - Promjena u git_grani '{}' -- ponovo pokreni da bi koristio Dodatak. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Ovaj Dodatak je ažuriran. Trebate napraviti ponovno pokretanje FreeCAD-a za promjene. - - - - Disabled - Onemogućeno - - - - Currently on branch {}, update available to version {} - Trenutno na grani {}, dostupno ažuriranje na verziju {} - - - - Update available to version {} - Dostupno ažuriranje za verziju {} - - - - This is the latest version available - Ovo je najnovija dostupna verzija - - - - WARNING: This addon is obsolete - UPOZORENJE: Ovaj dodatak je zastario - - - - WARNING: This addon is Python 2 only - UPOZORENJE: Ovaj dodatak je samo za Python 2 - - - - WARNING: This addon requires FreeCAD {} - UPOZORENJE: Ovaj dodatak treba FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - UPOZORENJE: Ovaj dodatak je trenutno instaliran, ali je onemogućen. Koristi 'omogući' gumb da bi ponovo omogućio. - - - - This Addon will be enabled next time you restart FreeCAD. - Ovaj Dodatak će biti omogućen sljedeći put kada ponovo pokreneÅ¡ FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Ovaj Dodatak će biti onemogućen sljedeći put kada ponovo pokreneÅ¡ FreeCAD. - - - - - - Success - UspjeÅ¡no obavljeno - - - - Install - Instaliraj - - - - Uninstall - Deinstaliraj - - - - Enable - Omogući - - - - Disable - Onemogući - - - - - Check for update - Potraži ažuriranja - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - pokreni - - - - Change branch... - Promijeni Git_granu... - - - - Return to package list - Povratak na popis paketa - - - - Checking connection - Provjeravam vezu - - - - Checking for connection to GitHub... - Provjera veze s GitHubom... - - - - Connection failed - Povezivanje nije uspjelo - - - - Missing dependency - Nedostaje zavisnost - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Nije moguće uvesti QtNetwork – pogledaj pregled izvješća za detalje. Upravitelj dodataka nije dostupan. - - - - Other... - For providing a license other than one listed - Drugo... - - - - Select the corresponding license file in your Addon - Izaberi odgovarajuću datoteku licence u svom Dodatku - - - - Location for new license file - Lokacija za novu licencnu datoteku - - - - Received {} response code from server - Primljen {} kod odgovora sa servera - - - - Failed to install macro {} - Nije moguće instalirati makro naredbu {} - - - - Failed to create installation manifest file: - - GreÅ¡ka prilikom stvaranja datoteke manifesta instalacije - - - - Unrecognized content kind '{}' - Nepoznata vrsta sadržaja '{}' - - - - Unable to locate icon at {} - Nije moguće pronaći ikonu u {} - - - - Select an icon file for this content item - Izaberi datoteku ikone za ovu stavku sadržaja - - - - - - {} is not a subdirectory of {} - {} nije poddirektorij {} - - - - Select the subdirectory for this content item - Izaberi pod direktorij za ovu stavku sadržaja - - - - Automatic - Automatsko - - - - - Workbench - Radni prostor - - - - Addon - Dodatak - - - - Python - Python - - - - Yes - Da - - - - Internal Workbench - Unutarnji Radni stol - - - - External Addon - Vanjski dodatak - - - - Python Package - Python paket - - - - - Other... - Drugo... - - - - Too many to list - PreviÅ¡e ih je da bi se izlistali - - - - - - - - - Missing Requirement - Nedostaje uvjet - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Dodatak '{}' zahtijeva '{}&apos, koji nisu dostupni u vaÅ¡oj kopiji FreeCAD-a. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Dodatak '{}' zahtijeva sljedeće radne stolove, koji nisu dostupni u vaÅ¡oj kopiji FreeCAD-a: - - - - Press OK to install anyway. - Pritisni OK da bi ipak instaliralo. - - - - - Incompatible Python version - Nekompatibilna Python verzija - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Ovaj dodatak zahtijeva Python pakete koji nisu instalirani i ne mogu se automatski instalirati. Za koriÅ¡tenje ovog dodatka morate ruÄno instalirati sljedeće Python pakete: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Ovaj Dodatak (ili jedna od njegovih zavisnosti) zahtjeva Pithon {}.{}, a tvoj operativni sustav radi na {}.{}. Instalacija je prekinuta. - - - - Optional dependency on {} ignored because it is not in the allow-list - Neobavezna zavisnost od {} se zanemaruje jer se ne nalazi na listi dozvoljenih - - - - - Installing dependencies - Instalacija ovisnosti - - - - - Cannot execute Python - Nije moguće pokrenuti Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Automatsko pronalaženje izvrÅ¡ne datoteke Python-a nije uspjelo, ili je putanja pogreÅ¡no zadana. Provjeri ispravnost ove putanje u podeÅ¡avanjima za Upravitelj dodataka. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Zavisnosti se ne mogu instalirati. ŽeliÅ¡ li ipak nastaviti sa instalacijom {}? - - - - - Cannot execute pip - Nije moguće pokrenuti pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - IzvrÅ¡avanje pip-a nije uspjelo, izgleda da on nedostaje u tvojoj Python instalaciji. Uvjeri se da tvoj operativni sustav ima instaliran pip i pokuÅ¡aj ponovo. Neuspjela naredba je bila: - - - - - Continue with installation of {} anyway? - ŽeliÅ¡ li ipak nastaviti sa instalacijom {}? - - - - - Package installation failed - Instalacija paketa nije uspjela - - - - See Report View for detailed failure log. - Pogledaj Pregled izvješća za detaljan zapisnik greÅ¡aka. - - - - Installing Addon - Instaliranje Dodatka - - - - Installing FreeCAD Addon '{}' - Instalacija FreeCAD Dodatka '{}' - - - - Cancelling - Otkazivanje - - - - Cancelling installation of '{}' - Prekid instalacije '{}' - - - - {} was installed successfully - {} je uspjeÅ¡no instalirano. - - - - - Installation Failed - Instalacija nije uspjela - - - - Failed to install {} - Nije moguće instaliratii {} - - - - - Create new toolbar - Napravi novu Alatnu traku - - - - - A macro installed with the FreeCAD Addon Manager - Makro naredba instalirana sa FreeCAD Upraviteljem dodataka - - - - - Run - Indicates a macro that can be 'run' - pokreni - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Nije moguće proÄitati podatke sa GitHub-a: provjeri internet vezu i podeÅ¡avanja proksija i pokuÅ¡aj ponovo. - - - - XML failure while reading metadata from file {} - XML greÅ¡ka pri Äitanju metapodataka iz datoteke {} - - - - Invalid metadata in file {} - Nevažeća stavka metapodataka u datoteci {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - UPOZORENJE: Putanja navedena u metapodacima package.xml ne odgovara trenutnoј checked-out grani. - - - - Name - Ime - - - - Class - Klasa - - - - Description - Opis - - - - Subdirectory - Poddirektorij - - - - Files - Datoteke - - - - Select the folder containing your Addon - Izaberi mapu u kojoj se nalazi tvoj Dodatak - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Nema Vermin-a, operacija se otkazuje. - - - - Scanning Addon for Python version compatibility - Skeniranje Dodatka za Python radi utvrÄ‘ivanja kompatibilnosti - - - - Minimum Python Version Detected - Otkrivena je minimalna verzija Python-a - - - - Vermin auto-detected a required version of Python 3.{} - Vermin je automatski otkrio potrebnu verziju Python-a 3.{} - - - - Install Vermin? - Instaliraj Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Za automatsko otkrivanje potrebne verzije Python-a za ovaj dodatak potreban je Vermin (https://pipi.org/project/vermin/). Pritisnite OK ako želite instalirati? - - - - Attempting to install Vermin from PyPi - PokuÅ¡aj instaliranja Vermin-a sa PyPi - - - - - Installation failed - Instalacija neuspjeÅ¡na - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Instalacija Vermin-a nije uspjela – provjeri pregled izvješća za detalje. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Uvoz Vermin-a nakon instalacije nije uspio - ne može da se skenira Dodatak. - - - - Select an icon file for this package - Izaberi datoteku ikone za ovaj paket - - - - Filter is valid - Filter je valjan - - - - Filter regular expression is invalid - Regularni izraz filtra nije važeći - - - - Search... - Pretraživanje... - - - - Click for details about package {} - Kliknite za detalje o paketu {} - - - - Click for details about workbench {} - Kliknite za detalje o Radnom stolu {} - - - - - - Click for details about macro {} - Kliknite za detalje o makro naredbama {} - - - - Maintainers: - Održavatelji: - - - - Tags - Oznake - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Stvoreno - - - - Updated - Ažurirano - - - - Score: - Bodovi: - - - - - Up-to-date - Aktualno - - - - - - - - Update available - Dostupno ažuriranje - - - - - Pending restart - Na Äekanju ponovnog pokretanja - - - - - DISABLED - ONEMOGUĆENO - - - - Installed version - Instalirana verzija - - - - Unknown version - Nepoznata verzija - - - - Installed on - Instalirano na - - - - Available version - Dostupna verzija - - - - Filter by... - Filtriraj prema... - - - - Addon Type - Vrsta Dodatka - - - - - Any - Bilo koji - - - - Macro - Makro naredbe - - - - Preference Pack - Paket postavki - - - - Installation Status - Status instalacije - - - - Not installed - Nije instalirano - - - - Filter - Filter - - - - DANGER: Developer feature - OPASNOST: Funkcija za programere - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - OPASNOST: Prebacivanje grana je namjenjeno programerima i beta testerima i može da dovede do oÅ¡tećenih dokumenata koji nisu kompatibilni unazad, nestabilnosti, kvarova i/ili preranog toplotnog kolapsa univerzuma. Da li si siguran da želiÅ¡ da nastaviÅ¡? - - - - There are local changes - Postoje lokalne promjene - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - UPOZORENjE: Ovo spremiÅ¡te ima nepovezane lokalne promjene. Da li si siguran da želiÅ¡ da promjeniÅ¡ grane (donoseći promjene sa sobom)? - - - - Local - Table header for local git ref name - Lokalno - - - - Remote tracking - Table header for git remote tracking branch name - Daljinsko praćenje - - - - Last Updated - Table header for git update date - Posljednje ažurirano - - - - Installation of Python package {} failed - Instalacija Python paketa {} nije uspjelo - - - - Installation of optional package failed - Instalacija opcionalnih paketa {} nije uspjelo - - - - Installing required dependency {} - Instaliranje potrebne zavisnosti {} - - - - Installation of Addon {} failed - Instalacija Dodatka {} nije uspjela. - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Dekodiranje {} datoteke za Dodatak '{}' nije uspjelo - - - - Any dependency information in this file will be ignored - Sve informacije o zavisnosti u ovoj datoteci će biti ignorirane - - - - Unable to open macro wiki page at {} - Nije moguće otvoriti makro wiki stranicu na {} - - - - Unable to fetch the code of this macro. - Nije moguće preuzeti kod ove makro naredbe. - - - - Unable to retrieve a description from the wiki for macro {} - Nije moguće preuzeti opis sa wiki-ja za makro naredbu {} - - - - Unable to open macro code URL {} - Nije moguće otvoriti makro kod URL {} - - - - Unable to fetch macro-specified file {} from {} - Nije moguće preuzeti datoteku {} navedene makro naredbe iz {} - - - - Could not locate macro-specified file {} (expected at {}) - Nije moguće locirati datoteku navedenu u makro naredbi {} (trebala je biti u {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Neprepoznati interni Radni stol '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Upozorenje za programere Dodatka: URL adresa spremiÅ¡ta zadana u package.xml datoteci za dodatak {} ({}) ne odgovara URL adresi sa koje je preuzet ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Upozorenje za programere Dodatka: Grana-adresa spremiÅ¡ta zadana u package.xml datoteci za dodatak {} ({}) ne odgovara Grana-adresi sa koje je preuzet ({}) - - - - - Got an error when trying to import {} - GreÅ¡ka pri pokuÅ¡aju uvoza {} - - - - An unknown error occurred - Dogodila se nepoznata greÅ¡ka - - - - Could not find addon {} to remove it. - Nije moguće pronaći Dodatak {} da se ukloni. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - IzvrÅ¡avanje uninstall.py skripte Dodatka nije usjpelo. Nastavlja se sa deinstaliranjem... - - - - Removed extra installed file {} - Uklonjena je dodatno instalirana datoteka {} - - - - Error while trying to remove extra installed file {} - GreÅ¡ka pri pokuÅ¡aju uklanjanja dodatno instalirane datoteke {} - - - - Error while trying to remove macro file {}: - GreÅ¡ka pri pokuÅ¡aju uklanjanja datoteke makro naredbe {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Povezivanje sa GitHub-om nije uspjelo. Provjeri podeÅ¡avanja veze i proksija. - - - - WARNING: Duplicate addon {} ignored - UPOZORENJE: Duplikat dodatka {} je ignoriran - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - DoÅ¡lo je do greÅ¡ke pri ažuriranju makro naredbi a sa GitHub-a, pokuÅ¡avam Äistu provjeru... - - - - Attempting to do a clean checkout... - PokuÅ¡avam napraviti Äistu provjeru... - - - - Clean checkout succeeded - ÄŒista provjera je uspjela - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Nije uspjelo ažurirati makro naredbe s GitHuba. PokuÅ¡ajte izbrisati predmemoriju Upravitelja dodataka. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - ÄŒini se da je problem povezivanje s Wiki-em, FreeCAD trenutaÄno ne može dohvatiti popis makronaredbi Wiki-a - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Nije uspjelo Äitanje metapodataka iz {name} - - - - Failed to fetch code for macro '{name}' - Nije uspjelo preuzimanje koda za makro naredbu '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Upravitelj dodataka: radni proces nije uspio da se zavrÅ¡i prilikom preuzimanja {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Za {num_macros} makro naredbu je prekoraÄen je vremenski limit, {num_failed} tokom obrade - - - - Addon Manager: a worker process failed to halt ({name}) - Upravitelj dodataka: radni proces nije uspio da se zaustavi {name}) - - - - Timeout while fetching metadata for macro {} - Isteklo je vrijeme za preuzimanje metapodataka za makro naredbu {} - - - - Failed to kill process for macro {}! - - Zaustavljanje procesa za makro naredbu {} nije uspjelo - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Nije uspjelo dohvatiti statistike dodataka iz {} -- samo će abecedno sortiranje biti toÄno - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Nije uspjelo dohvatiti bodove dodataka iz '{}' -- sortiranje po bodovima neće biti uspjeÅ¡no. - - - - Repository URL - Preferences header for custom repositories - URL repozitorija - - - - Branch name - Preferences header for custom repositories - Naziv grane - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Pravljenje rezervne kopije originalnog direktorija i ponovno kloniranje - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Osnovno ažuriranje Git_grane nije uspjelo sa sljedećom porukom: - - - - Installing - Instalacija - - - - Succeeded - Uspijelo je - - - - Failed - NeuspjeÅ¡no - - - - Update was cancelled - Ažuriranje je obustavljeno - - - - some addons may have been updated - neki dodaci su možda ažurirani - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - UÄitavanje informacija za {} FreeCAD Macro Recipes wiki stranice... - - - - Loading page for {} from {}... - UÄitavanje stranice za {} iz {}... - - - - Failed to download data from {} -- received response code {}. - Nije uspjelo preuzeti podatke iz {} -- primljen je povratni kod {}. - - - - Composite view - Sastavljeni prikaz - - - - Expanded view - ProÅ¡ireni prikaz - - - - Compact view - Kompaktni prikaz - - - - Alphabetical - Sort order - Abecednim redom - - - - Last Updated - Sort order - Posljednje ažurirano - - - - Date Created - Sort order - Datum stvaranja - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Bodovi - - - - Std_AddonMgr - - - &Addon manager - Upr&avitelj dodataka - - - - Manage external workbenches, macros, and preference packs - Upravljajte vanjskim radnim stolovima, makronaredbama i paketima postavki - - - - AddonInstaller - - - Finished removing {} - ZavrÅ¡eno premjeÅ¡tanje {} - - - - Failed to remove some files - Nije uspjelo uklanjanje nekih datoteka - - - - Addons installer - - - Finished updating the following addons - ZavrÅ¡eno je ažuriranje sljedećih dodataka - - - - Workbench - - - Auto-Created Macro Toolbar - Automatski napravljena Makro alatna traka - - - - QObject - - - Addon Manager - Upravitelj dodataka - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_hu.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_hu.qm deleted file mode 100644 index 44a38a5477beae1e3a13cf473885095bfaf63835..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71336 zcmdtL3wT^r)i=J==H4`EODUz4atNhOF-c2{Ahlf58!a?#XnFxe>LfEsrkTuynMvEU z0*at`!z+r4cX>fx@c#NL%0=;lis ztzWC^o>OYW#d!bSN?m-nQX?N#YS(>Az3cDt`s@ewYgPRcRsHN`O1<|ndA;p4dA(<* zygoTi)p%=_y7$|vX2Xk>dinM8degP?`jxk-np+-Gs`!wqf9+(wdvjJ_>(%78hTcpxDjydy;*hay+o;BwyEXqgG#;U8|tNB+NP?iUarpjPrxy? zTbrK;br z4qWvKrM|URz589&N-e)zed_OxNFyMZ;>c1Y_sMLKURbP7W1f`x?s$Z*WAFaBt=L)4BZ>jp``M`JUTdRKfO?>}< zzF75tUiv4cUUK#nb>dS>^*u6W>cMfPrd>Ye#2uKY=E*7Ruen31*MDZp1@~UB)Y!}^ zJ%71NRjHp%+3}fXrT%o)lmjouID3wr^7b=Yl}cYa<;E}I`;Dn7w|=}I_`7P#f1dYW z*ssnhU%c~WN)0s2>rt6>w{CUbVPk}z_{@0Xeue=y|SUcrkF9u%je_(3$amOfiY+~wy%d!8v z7EfJzHO|I&elzu~C$SE-c52^MKT_(eyQU7U+osg(R!`l1-E5qf?@zt*dsixzfB)1w zx4Z-UaKqF)KLGr`^oFVTUzAm9->0X3@9Mji+J0#2UvK)8QiX@AkGcIcr7rw+^)dHf ztyIG&suz9_aKHbj)m^{;j8d!qvwH1qSoc-$s=lCjJ)YYtufJ)p-t_v1a30rI_kL%c zQvd6t)wzGY6L?=({iaX$DK+bn>KiwHS*cIIy86azZUnrl`n^NVIA0&EzHKAuW5)y4 zpM1?urGEF~>N{ruAAj$tzO(ZgrP}JM@4M<*(EYcnzczldQY&6jegBltVIQxr{{Bkf z;erL#k9_aVN_9U|{lxJ!Xk1^)E^_U040Y39~Tny){*RA5dzzt!CkivCdyr z)tvlJ?89l_uUTC69Qeg$HOmg-{o8J@S=rF3)MuZlIqTq6O1<)jHGRWJEA_Xp)eQai zY^9zn)MN$$$5%dAGxp`}O8s!KW<2+8RW)UG&4KM$=al!?yz0Fe=VH8m@-py=eKps7 z7WjB{NzEHy(}?d~QS_oEXCG7Q&Gj`O`6br#vis%rp0jKI z<5cY5#cOKr_{RCFs``SOPc8u-Ui6!q`vxBeA33?^8@Jx9)ODYg*N4AR^RrvP*AiFN z{Nk&ipI_cv^PBEpDfN!gny10L)Yfxq)k8QBPkp1d>g;Qk`q-@6s-OQD_*qq3Gxn5H z-+ZFB{#KlWx3<(Cl>py4>V(?acZ2>OysuX1VNvaiUJH0fep0*i<3)`3uG-T-1H5m^ z)L!t%KV#hKwcY1p-Q(}5?fL7sl=|P@wJ)mz-aeD6O{~WG?Dv@H|KDI)?R!zOD_UUciN^N_h_FpaU z1ijbPHQezv@bRj;xzhpn?)TN5*nCK-Y9k{nasbAb$_lBvU*Q%%L-txxP;G^HEd)ozzl{(|kbvO2>Rn^pn zx=(F67WBTR?o)~RO5OEpdAH`Q4zW zN9%riOs7(pEv@^*?&p;H;vIE|Ha@6SvRL=joezVb?5+Fj@|A$+x%yeFJ_ot=<@#B_ z2VFhVQh)rlpu@{o*SDU3rBXLsQ{VYre1F@A>o4Ecq10=BTz}2YKU3->o9o}ucsKAj zUjMcy@5DK|z5a&&PRObI>pyt^BTBttef>ut!+MvWTz}gmzXjhrrT#M)E>&vAn))w% z@?NEuyrTY#_dx!<_?`7%x*g|y=c)Byc?$b;@1^zk&HlMk=lr(*zK=nCAN|hyueW2J zZ@;Jh!F#@`ROXNMznFU-=<*Nszj!<5`B6>%AD+be2met2#E-T@Uhb*?TP?o-qNawa z|9mmd_lFvqe+9a{s<~n2?bzSH%xIXkVwF<=`IUw_k5wym`!0F?>x&xZKKnPU_Z)fs z+m#Kg+X2r-Z)@ltd`_uT|0u8T{V#d_*fa8a_s`_@@h2NDx#a8Ezq*E9lw&jB*DyHe zKBd0>M8n_@_CxOcsv$FWCH8Z?A(y>Usp-cz?D;hK#d(i6yy~B4D>d)44cEPH0oL8n z@TS?|6VLouzgE?~s^P7ly&m*_bi+Fu@%hyq4ez)c>)M=Zc;Bx9e=*f?)225A&KV8= zaot<7A1fQ~JndneyH7UUdj_6c^tFa>exVM0{=|lF{+|aS58vDHtu=oI-}rLFcb?m< z)He<`{On5@cjG4;9%^k-YT4n2-+vF!pT45uPy*-dq~3-nzdr_fbb8|n8PNTuI~te% z?3Fklw=^#Q_1Q`tb5!H$bMg5PUfp=+%%id1eB+saK1Eg4E^XZKy^n$||4(E00LFiE zRb%&CFz)*C#$7jpo*%fkv46)9_WkpXm%r{drRMBt+;gnG#UiYHkLoR&0@m<+G*7<1Tdz$VB-~4LhdoRX*w>{f<^U=p+pH<_nS7X1n^)-HR z8rJ>BM;pI*(_!G}BaL^y6zjhEC5_)Y=DiSWa~dB$3iE$|VdG;vvY?|ijgNhz1LyBR z!#05tAE>jK=)IoHH@b~*RPv){C7dOH@;=sqTxru zHw)8V*7qmqS%qmYfADOj-hIln{;z@$&3`g{1^YkxWI4HsMw{#!lm zjh}r^sejx*?L8OY1$|}aw41&PKKJsMO#AKEKcUpmrcZnPnt$TFbx(V`dAm~WhnlKy z!g-nTi>8`<5&ZR%rkaDm_n+FEW}kWn_|K-MIo}7KR(Cbc|Mib>zCPA;!fjaZu>7pA6M%0k2NiQ&vK<6+uOA4!-LRg&TTqpCg45(nWl~JZUX=QS<~h=!14L* zO+6m~{MS9v)LRQUHdZ(7Trr~5wSR27cpLWnE5|pz>{TxYf4Qe=@Q&BuTpr()y%o>j z@h&J?TSD?;F58kA9@-L!aqZ z>P_uUx7_hI@UNk!FO$y>U(c?GzI){LQ>*3m-Zpvt+xn&lzWtzr zve@)U!|_UuzGeE%v#?La6Xo^k4^Kb#2d@YIH_7YMM^8WDF?{dpuT5X{{so|uE2l5| z!zRe#<@y8eB$&C!&#;NaQ5^I7p#RI z)IL4&RjliTk4_)mcq{bh|2_S>yRHSC8F{_uN7LVS)G12s-#`85+kT64^NZRDHZOYUYtZ8^YHm9We7^55%`5&6`Z)d0<})_l z2fb{pdG&3dQ0mau<}K4Vf)4-EeBmv-lj@=oyME_prpK+CbWVEw&!wJiF_!%8i9 zM@!qxtAU^UTiRa_x>)eHmKAsY2J-6umY3XjJ?QWwEh~>|Q0m9OYdP!OKZ5>mYFT~u z=Wq_c)zUq(61LdOTVCCa2GzJaq_QflJdBd$NceY9cX_c7-A2GE9ymYP*3&Y|2>L} z9?`owj?afRh!)FKPi*l03QBv8d6ASIW{N(Y9vDyI-x~b2HWElK26(|wMlXQ7;{j0FrBMwu7h1%-BiPGfjCk1MZdsQ% zlIYLp?Bq#rZ@M_7VO^h3rPg$<^)z^1cOsh@Oy!B!76CZCqqEfNQUuyrYV-rKkKU@6 zx>%FM;>bk~=_T@XdCGjR9l!TuH*$JegIE?n-Gl$Lcr5@W|G;7k*s(#y? z;(1C*2c!?~ej11%n<8OnN>C!CZqP!en87zmEuN;pEKVJt5?bRSAYICagpuW`QOuIT z_l3V41oF5gD=qSNMIkSIIQHi9!+j}m;8ek2G?7nD4y7yOP+GOBoJ6q%ImJX4X@-%(iI>db`0%`pB#JmZqy>mFFJ1KZCJNp_3U7kD59D(r z`unjPy!_w1!IRxQB2DC(+xRHra9c{m66FEqL!;iDz^F~7ibB%iY^Bc@^=EM#JggZV zPcX^&kS3GTZGGKjwzW^IMK5e;{V|SobHPT+1Pl-n6n;FH)aXdXMW9L~fozN*ETPZ1 zppd7X3JvuDs5LnE8B61*3Nn0|x6<35P3;>^^%p^fpjj~cQOIscb5dj>mETiAE`DfI zU<(D2eB;DO?EclO;Nd zMwlt-sKM~;m~$eMiti9#!mJz?m)H$GWAbYoN@R*)GkPUU;#iGZ5V@2hIO!yAh}Is6Yrbc7NzF|L@OfBCKIAJ+^6m5RX%Qoi;a%vT*e&v^QT=v$MSg`RI7Ju1sBxI z!+Ku2xM8fX-7DtDNw58xR3hs^y7Uj{#)_St@#KYkrSN~Mn=Wb&EZTXvV+vvvmH2dupVh-LL(d-)r)}e#M_Or@V^33P!5DS1l3z3 z9UP}1i4S9i^bg3f^v!zUz5wW{Ezt<1_CqX(Imf~<+{v7mI0Ck?LmL7+FgDLCu}mBb z9AbMD23lQWVezo=@4SYT-;^WTgLB@4=V@w!J6fzR3PWeMen%=lf|H|JTF-b-Iu?(! z)F#YU#C%lqDf6A}U)wcS9LmL7^e~sY039JK>SswKbe!a|8ZkIX8>OZ;%_w4=7@v_u*dIZlIx^kj4s@_u2lg0-O8AI35Fo0P!s?FUY&zKKN|?Es)=Foc7Qp#g%7Ftr zZ-<)MW&I%jierb&0xFSV+)kP-Jm@^&PiwN47thH;XMjhz;cTNIqG7hlIhy z#aB-~i%q3fFbr@H<8!0@I`+S8HOy411Y}UKKXdu?U^<(~cuDwn`swub64@kF|Bn7l zj^=Lc3I-q&XlJBBM4n};WTE02CR79XMq0CgB>viq-+9EyI!HeJoCO>*kPj)IQ57cqd)2$=VIUPr!#={nmb&;ss06Y_=aohc02)CAc$VO&`5@7Vh$WQy@aj_1QiU{IY$UJK)|=NP`iDrE zqQ=IK=9P^mx&}F|mgW|?8D>P7vUPPH*CM!rQ4>Ivc9BP8 zQu?J*`%?X5Fn5JX$4=F*WjJ*uW1miDl368_jHX9pXLzm89?8&3@TnDgI>e2n6*kJK zfCM-~vPyqD>?trTlR|+KTTFo@cRhe4>Nf7|t@dHhB*x&ah3dp31pCf%FL#up7D zJcqbrsbe}i?tmr~#13)pgp6ngQT{(t11UTU{L(!|Jd0N5FnYScpQH@;U1d7V(9z++ zVoz8=sLDBDxS!&Es6>;eL}0aSw@N7fn9z)}ZG}pcv_n)- z&tP1_h#nCZV)uIx^Hy82+c(Ef1G&MqO+X;?)i&*b;yzI`G9jyeSrHGNKX~=n|9M!Q?{GHb` z@7J_IVoc+2(O`f^JHNLkllIRN)PLw?1uxMDH#uy_Yaq8g@mWCaoX$>6QiTV($wb+=6(S4Tc+ZM4C zoDTjazItl)Vy?*f5e8!h5Bf%m0l!xprh=I~MqeP(5PVI-Dth2NiR}2^#CW_}y93!R z65N-V7$q%#BNVzg7%Pse zUTMLjAR!kf&7?Iw(hWh-7QeQSM9pi8@j=3O%+O5~X zb&6X=#w+zYo6p+xoWf>lf_hLr1q$E30vr$@EI;8PB7 zt;&UiKIJwsjiU)G@WSHeRFQ1QgQ5jf+J>YPqob(=d@|6+n8hJUOi8G*lFv~XFTm~D z>0Qj^4)|jBq?6ElM-t;ua*+v@FyU|K*ao!gPe7^(eYVRl@BAp&cGc$t06Y$118>LPZ@pnAcEK@(%2BhS?(6=U<8U1Qh zt%43?(unhu&03RB5d_+K#au4amxy&BtGQ*)XFs>aN|t&VE$PJyltqwO zGy+M-8N3S@k{$6VJtFOZ1QYDMOuA4!qQR}dq~hRu2PzN#3gu1|&($CX5nEARI}Hb63ie)nH0^YFI@YOPb&2{Gj^xGKAG;nT z$*f;t0WR%LaxQe(*KW(PYr8g|w{Gi7&n0~gfD0fr8F#d*{uVK17w{3>3GPEqW7fQ@ zc@4f*o|88WEQ@u@USHczXJdjg~W7|AMTH-tW^lAJi^uqB)3R7GV zMh2ZEhED1v1#v^tnx+^~<4hbsiIwUzhF39Ip|#<6(lJNm562W&OcGBCozh?ut&@Q- zWS(Fw;*Qq2@F3B+B!7T7C&W%4l*j~iFRs<-sa!cvN;06zKVgWb7plCtu!S`t*AD^z zbQY=)y!5{K_LB)=B15M}Zc4%{!atAjSi63Q3KbmoV@SO> zBA+b4*8-cZm}a(ZGS@#g0*;8MwaV6)&ZLXu?OuOAfkbf`bE%HBrJ%H>5anW+eF!v- zJcR@d4>*+>5J0eP_p` z#vLP|UgEbVdP^cA`Ehee3XXL)t)*D@9>Q11^ApGMP$ zk^)8;vzR!CaU`T?G!(H6^`V`*+f4}o%s(At%BPC?G?J?AH+(-K zHCPXfNoNHV(-i`WnGn88Q;zllQ=&k zI;_+8g{1Zs^NE1n?3*gFRNWI=gP}#|d_6)a199>fRfJO%dLO#@`1slq@OWyOZDb-+ zzJXJ6EJ>u~sZ{+CS+l4+!3T-1E@Z~#$48lAZ0Mx|Q~E|k#^_>9A-aOmJ!ocjYR?E+ zJ||~|0ev?vn}S+_=v9&=#nVC^f{{_P>rNOL%Aw^YhO5~AK_O7|&rqDZjidUSu0=%m zIvrs3Q(<&OYjMG)x^<#vMmV+af9&*nn3J4JQUlhWLYo#>Dey5rfHulI?uvDDSYW2F z+cyd=1UoT-_xA$r@GfXgtjzOahihK94|)t!N%Xp6DStK;bn^w^(>xZ zXn==>`Y(NsqH~g-1QJRijzirP9!mU!ssRj3@-O{J!q?02jrRi?)A);AiYvCVN+i-=)`9zzU&thsQ`Dm#q+7$*2|s+(#Zo zStkX9$R`GaM(`KkKZy58=v1xf)F8V^+x4CsS}$xQ>L)1twJu3nn0Bq}^aWr8zHoZl zvtuKD73yU&6;@j6nsmEw7^aIWk>OBn;CJXwAj9D*9m`r7bhHH4BM#0`=m`ZE=>gcI z+S9r+-qBJCcxu+6-wm`A zm2$W#IqA(3$ec%pGg4~{#`vh!m7470m85LtXKw9Wk+8jBvc1?rW@eK=ONhJh<5;s< z9mixuoy@~TBsm8qD`yT?+8fQ$l?1=vZN5phLl&GV{iX8<4uO$$K}!#v^&XU{!J}$r zW-4n+C-R;I>2%r|h7DLFWWg|5yu@H4o$d6tfrSl7@+_Q5IP|E7PZZ* zInJDP9E%5>ssvGd1#-)TTS32yp)ZVDaaSWa+L$<3I#^f71771 zonL&lqnANc84HUmKydBXE5dVin_ML+s;V572!24AkW{gkrQ5<%R+rM z_)7#T2JyD3(@L<`4sOSIWPZla-=Z>|0s&EzkgaxErbI)u;S!$~u|t!RRAvyJl96df z3c7MQGv{_jggb-fMnq7j3+On0k^uA^mfa)}wa*(aBDpCLPQDwbfL9^NSfQkD(pU+u zp_Ew@N7TKe4}`3i$FwvP%>?9)T`LBYVdH$l1trZ+SPK|42G_sR5sS}Zy&Zx8u2!2Q ztoV-#!^dj(t9-q{IdqO-<(4DPD~C*2VFhR8OEk_!D=~E9uxl&~BhG|UwZ3C#on1a_ zh50V4AR9=J&NLMrRYbDD7sL)7H^JIx>g6W}j`Yb6s$rH-Lh+VjZ7UxRTybLj0Zmo_ zlNK~5r_R895b|u25Xp%WV5v5H3OJW}9O!4tOGp~DYwYcdYiDpT*J zio#OmJY`v#8vvd%2?58Rx+d88l9d8o-EKzBdefmPG6%a6a&SL0c&je7kJRE3@V?lI z7MN#zCQr$(bAL+0BTX_6l2vut45*xQ0$(ulne~>BC5{@=%3i)yn5W_Q^Uw5GoPChj_mPzDMJ_1h-lviYD z=*VYf828(vF%uSNnx^2k`s8SoHiS!($X8%L4g5Ty!CySNMSw60os4#8t(`ik;0c3Nz3|T?sN`u}|XF zL5NL@fRoQ-<1N!|Veb$UEL~K}SL7<}*D5Pz;?qCE20nMpuXVOS9JetWNJsEJzf2{l z6l$J<^Z=tMYvs%iSGQ3TPh%NxTi{XZ*rGj>GX%BFV5W78KcuhI#iuWn4lShURHt(G zca%T0sKz4WVj*8x0=Wz?+7bCOiNpo9!$X7Qa1djMZi}?!A{0)G=kV}yz+;DB5D7WY zCG|CzoPTr(9XcXVi3&CZ6xAs8!rO9HS3y^FzG#TN?Y;!-GcI#&dtJOk$h2%J?y zB48C31r7e-75bc%QW!Z6!}G)V2Ucl^YO+Hi0W@|u+e?6vlO`$iOpBmL)|99_c503U zg-F&r0ByZOgQwP#DU1>o#Uf`qpeJICrDz1?cI}P+FcAH*D{qT*XGI(&JL(KKs+^YC zvDa%lEKM_U4zWodVLS8jftkY{I4ipFSvXjp)D?L&?NrAErm|HD$is?V>$$%5PFIv` zu1V({^_B4Sm8U*2FtzQ5VPP1rq);u?Sw$Hoarc-KG`q%G8jRWjikv0IlUa6PNv3Bu_sUfQ33uZBU2W4?{cd(|D!JlmTUKgEPW>WnZkf>JVNBsX1f0T82e&9Xs@o5)ZIy1u zOrDO#w^ufJ3G=tZ&N9O~)*d@*EetR8rL)ggZ?4olD)0!!EV^%Jz!8*9IPVJfCx=dN7!w1(I^s07% z<2sMnT+H~J8?V(FPi&|HRZ`prv9m4+tM#bY3(u;SKoBq?8} zbBs>2LwMJ$Vt^#T`Md$X{W)EF!etpBMvM7LOWt2dWB195UE)dpjyt z(9J-S9?^%Ch7##nzXe0&E6Je9XFJwISRjUhI$EtLSfP>QZ~zOQ9p;n~s#KDS%ES}B z(^n<3P^?DOF8o-BqHeXzza{Wam4J+r>Me235WPGT?AXQjyrc%Yh07c2@~F^{MdmA^ ze<5D(knEwZ-m!;q%@(wTfKh$`iBY@6|L^x@LY<0!Q;f_jJSKl@SDq)y)_$m`lI3%H zNZ$ybBBL`^a^)P?Bi*~r3G)SdWw*iY$bgYd5Q-U2%9Ca~rLM&9#BoM5Qf9cY9*X(| z-)A)vtL`YWf{AP8*_=!}>cqFYFjBk&pC_K_N1{TLIg4wF$~5zQoVvHECy|H5VQ4qS zy#1Bl$XIbqXK|+X^=FW|h}?WhYZEts&bjPFDY8kuM2=fBHIP7&QasasFakG0%m__I zRU-zmVX}Bc=uqY6I}}6AG7I+w2!AJt)qf}Uddsi}mZDEG@*B}70lkKCUfaDs5Ig+P zf=4;$=+t(ENNm-@pQ%QaKhmL!n<<%#WYEqx($a%6GqMsyVA$_1RzjT4d}9bs#+G!2 z1Mq0V>ojpmF~*+}a4gw#+|pySaXp@z*ok&Svat+w#7~r$4KmDu-6cKnRDRxv|AlQt zS<^f&hcviGSP(>>YToX`_>d#+;{Y5wc!yd;`mHqLY1Q>&bWOy_?8)826|5cFJPU@Y zOBEv0sAP$oTr$}@=74LnD-hB?9l%PnFdf&lA#Gj;z_P)7evE|@?Pg1{yO1;SG48D} z38Oi6X>i@u4oM<~hC(Vqupny87=-9}@FJKslN3KxdFz_Kkn`3any*|SGl zlXXg@`;;fDtV+yIhHI%X8TqabHpDKJ_h&_n0}KXZdeiJ^6(V=@p$drqnqZm2{Yl)H z6`B4p;b^BgeqUheF#EpH)6uUl3j>w6~NalE7}*#T(N~m7Raev$Kt~rWsjV+(N{lU?D{FQFe8ezwwYGEI6szM%pIyY z>ebqYh;rr!JrL0ivV&d;ZX-oIbETOZ8txB3n}N27Xsr9OGlL*y>bJol=+a*18rrj^ zsm^E5ek8@#!t1*C*uysiVjz^#YcX8Y%XHb;2WOW)$d(fJ;X3{B%J`-(Goa(pD4<#u z7N-rp$a3l*sw7$7q<6w-X2zvLmyFS)iNjG~?J%$=#95m3=u#djM{%PP95ht14r$wv zygP4oKx%!oOPIB+oh$g=Xg5y5TGAWal?WV{792Ya;MTx+b!z~pN;X@{<7fxrI zYtdWH_l@I~3k>>ENP&6Uag45oQ<*D+1~BkXZPVCGZhFf>8b@inmx?K#_KuMR~Uk6_uZU zZ6{cSuJB={?*zw3^b~D-1U=vMuITE8%7T%dB7)Qq2E7~<0vXq z1X5XjZ>{)};Q7){FF)TSo;@yeAuCPPrH!EJ52D;;I<=Of7SYFSgX<9POwE81;_{m) z#pB^g(2i8NAw~zbP+ADnrl+APEE7^dlbO%}CWkJMhNGVw-VLe>CYr}6Uk5NsT$kR@ zNL$|c1%84>xsn-UEYbcCj>MU%FNtd>YNz-f#T(h3f0Jrpm-cPrWjvA})CN&NS1WcX zT|}y7pi|2dsJH&Dm%ieGa3ed8v1Cef55MFJgF(I0OhtdA)AIxWviW|%10JB*^K-l2 zi+C2yPr{K7andk9!C*m*P*y6^xk&dc_ej`(P`n3yCsLv#z9l;COZ$6=qs$%H{a{pQ zRRE9dcHWml8lr?;#M`B>9xyRvXv1u3D0k*mr~>|S!(mNwFpe4%G>_lyH~c@oLUOgz zfC?3Mx6U&o)`^s8WX~p_=Q69Vn_!uyYGNu6=f!#jS=_@j7ZdBH+Nl&&s**Ms7TcTiP(zNsyqyRkxRV&kBgMD zVplFqzp#-hlvt8RB}y6pr*TR$a8Hn{gptoNh(by~+HvllC&Q;#M@UWM@}uP8bKDlO zYyN@l;geyqU^6A*;k|l3+Kc8!wW#f6`x~yE3IKIqa(Ou(5_XFx)pGI>c%s~*gh8;w z(w2jPhIcm$3F&^ppcUOPn5F<4b7O}!FDz2J8XFyQ)!$$zAqwCr_TC;5!`*V(W2d)M zcSj@1WYWX%A?89vu zSf~+!m2&lTOkw$E(G#Z|5d+azgSqTuP14f_}#KZID=O(O+_}sjE|iP9*AT1xMs5@C84s$=j$JJVMST zCQ3-y&YiI>m&3@oC=vTw(Is|~+O7#)if2f=Ol_kTTZDArEmD$(5xT`eb8%D9VmgUS zluMooVPU(LZiGY%&RO(g@vZk{%%;rJ?GRa%@cf|JLBp4ON){n%8uyvO zFdjat%v`aQwDFzz9bHK0FIiUcV15q3i6tkFY*ba+YYoD-4sN=CJi1Q{P2oZ)7epnj$`=GNsXt)peTf6cP5YQzG)(h>uW z8}c1`%PB~m-<(=7Q@+>+k;2=r=degxusw@rM7hCidOtKa<15DnlF7=K(apl#^u{t% zg(?cHY&&M-_R$Vr6$*tZ7WP@%z9-z0fPoS0^R-e65c}-u%3W7Oqb|xY3wu%spNogj zl<}DsDCSGN11?-PIvMo#ln#G~Ak zLQZJpOW2HF0YF4y;x3gIR0ZiY+*kPY9ey7gce5~{w zi4F<4O)a)g+S#>r^Ty5R;Vy--QG^A-?0sJlGMgs4_x|BY0n5|^UhPL$7_WNT2Ld&Q z6s1{E(=;tn%Z)6IuC~tJ)`U*}xP}y6sr>s;{Qd_WwCSatMZ76> z(S+DthxN)@qey{4Y;iz@kNI-D`3vp3#8srL;NU0m-9XDhubJ`KWBS|+gs*&m!sks` zICXnTBIeFXe2WZ?432xIV*vPj1J+8mCHESM?k|3}#dxmVr%pOrjOWTTTZ75jVcUeU z8sivt)UhiDi*DB~|B-xS6O`!mw)+=7FBbp(Vx}V(k@^5hkDI;a&3FRY^a3}4$0Gp* zGUwHW;!lWKPOh(ztEha3S=Tx+FWQ3ZV8!Y@5ByG1Urwp!)6z&$j3~0yyEqC^>nk_0 ztav$7wd@G+M~#lnADn^SuO%&IFBu0(k#1Pxl&*v@Q!zn4GMBJoPg%`ErX#=kq?Boy z)NGP0^P$Na%y*~*5T-V*8?fs-i(=`AF|K1CBiSJHOfWb}xR(T6%Ll@!XKtbHW{FFe z(Wf$9L^ia^Qq{K~7b;y?61*Q7C97?HdFVdWrL^x!o);%HEb%4r4&%9?I5wOo0wjrs z3MIIRrI?0^Yp!>Lk(hqq&jKTIvyE8f!k$FHm;@*ZZy&}tg?R&e z|5#42q&PvhN~7e3vpNCu4W-FIByqveCD=ltn5&o~l2jJ~4V(17GMmrrDg|n(uoc%6 zcb;rbg34jfG@mx>67QzIJIW$-=|$a}Y%-bnsOd@}+|EVK3gw9^&Fi7`P&>%lp{HJ4 zq456=+Nl=47~7mNsa`c*xn$=UC6FTPa6v*ai0)!@bWlm4UCxccVVFU6XpA~BaN5Nt zcn0Gr6i%m)#gC4qCl+#y z!%(sp;OOzMfeeQKW99ox{H-@S7TE>KgMP?8ASUKC6E&2s{0>T!g%|fx%HQN)3L3LeWinJfdPVKxQM+G=O(*9a5wTbH;Rwz%!)|p0)#5tb`Lf;N%gH zWFixYepKwpu~4l7KR8?8xGOf|Am-u5(Xv{Fo4)X=-MXVz^_|`0XGF8`dDYUsvx&lK zYvd+k-gH?t6>m)LDxZDVzVu#%vMqLFFNvkb+2B z)zN3WtUBKwj9l4lXdvM>CBd`Xv^J39#OG(&H^$ed6G-0GJ20vIEnmuzTnyx8Yh1T>h6UoE+#M_Gg=@Q|lKon5#EN)mm@0jZ|% zr?-d^SUYC3(e89eT6?1AxfP;hAeR|qtA_xVPKyDwG?#z{2y*=}A|H0bW6UCqZ8VZg zj%7qbO*Hc|81Cinl(0<}GppbIAo)CIZ7ZV+BQnT-B<7@rzFp&NjW-mPT1@)AcP3ci zlm$@oscljiluIgkKPrQUJ6rB$GR6EkkT9=(r2mKd6S*jTm1XBeiwJ76q@b`bmg0lD zHR0p(sRNaY5I#fQ*vbF6b&$3Rv%o{0Si~O_Na!@cO_})Dg|VWr!0`!%V;SS5So@>{L=o2swY2=J_F%gEL9yHW6kXXUvwWt;L$ z6y{5D$){+fvz~#<0<{vSA^lT(86=B@DJD7@CC8$EDvZA62FD?S7E;j+;g$@rKz*xq zS$@(8a-5)HK|6M-qVN|p^9k8a$N?E0nQo9W1&Xo+vognB%CC54(>|H zFlGc*1`(rUhhAtg{AY;6QfF}c=;3TPeu+ZG@2KlMGez~#D@FIPm@=^9? zzizbQ4=}tPv18Gt;+#XI2YP<@;g!^5(xa6Q78o$BIWzj0iHLN!-L}XFXbGwflwqJKV%bvWT5LctIF@ z7f|)KI-4E1Q3f{sX<|p411~aB!Ac~_`3c*h4Xg9Hy|`RdN`+&GnGX|LOiRnuf%~$$ z#?@nkx~vq2Em9;ZE^~4^WGp~);2Y<*kmJ$PD-EbLNPD7**0n%4a^pZ`UbIHdKI?1| zi|%GzWQn3m9b=eaWmPoBsm3^8r??NInXpJ`mzc#ci}8p@KM@ovG%T`O+!@28g#NKI zQO}HbltLq{c(rOovQUjof~aKRP7GpWf0Z)@Iuh6xhD}EFP0ji_BaVqtekRWcJ5`Hu zTWV8Mc>FZ8|*ESpMm7b-UYyJC!rAlEUqT|&9e$9#AKGCSi3J+o{L~r5tx|CY+ zVv@6r>l?zUCs124x?3~@q-GUQ-prSbW}DGO8*~(N^W_STat)E=y5qzdND|@o2<*m3 z7bbDBEutWEMD-?IxtKwot8Nzu(%H*I>wtdYHwpnURi-|amp~~fXj((o5Q65cH=;jC z52pQjjJWAUZv7U%oG@hxLb2LM6iY-E?C98MX6s!ea|ndqEPJc(_Af!G$g<~S46+4w zm1B%CWJcMsn#29#Dvr1usp1UhP~WGNs!V%2Xkh1=uH$k*r#|Bqr&*-cWM-KswZI^s zCzlJly>UeB(9J#h^ayuN!gUqLo`>#6o1nmT!Q$)1m<-{Tp5?}^>$=u2CKPyo6MF~Q(SfcS^46!wOJH)raCzh*a_~A3l z)Jyb}%k&ckJo`9s%A^CSXo^xG5s|dGJ*yX2o#VRley{D+&gGpeI(X6g65c|&CXs>P z#A{o=Z29ueWiRPmv1|!k-{Y{j4Y!qMgRzTc?3_8+T&zO;Pn86pwQi%q8o}^8J6n0n%5E0o;5m^#n1xvdm8HSNF38veGY8k1 zv#i4GWGUa8wlmdNK=J*AjO*M8QVmLc9)R`O3W;veFyj%RJQj8PM9UuLf}3|h$MP#q zR(d-Vd6sUTNG4nxFmHTs46c<@B_{zAg2%h11zF?HCSzeNnJ% z8|yI2Jdw-aWzQVC8rCI2sivwsIMU~U+;xbsoUi}C7j3$mnp+T1<KUIVZ#U^at$}n>;?&)<+^ShpD>yup63ky)F&CMF`Fk_!Shm6h?A45h*hdRV zO9rbqY}~wUrAPcTKZEE7)6m94YgeI=8tKc7x3*noSSNGzVRIy*5 z+yFwVJ_Ztsa>WJc7N3)oNoCgnmM?8aNNQ}{AF47l3nB>pgh=cw&q+dgLOvoio!kp8%B*aqVlN^bJ!R^ZHCMKoUoz0)YT$BXz ztXmB)i$91nC_#AsMrbGjDXz&hAYCvr$Ca`yhITopI5~+U$rBPqlJy0|;9)$?_@R-4 za_~fsnV#sMrzH(Ecx4vx;|$#ri9*z5e#A%I4zdhsEq zZGMO;e$39YF&z=nSrErxS~P!gV3IG#&Qi5cr-d0M%cvY-p6fQh)Wgl=GO^o5+<+t` zx@)pH0M5Nasm250?nXJJk7}Dfm;oQXPrM}KCHk0}zL{bNv$l@hk)&LCd{Mu+CV^cN zVH_JEXQXs8$AJ8kBrh<#BW6AiUR@bpjo95X3;C#tDbr8v_~xA({kk#gIcSwz-u<^7 zhoaOcugmvyNRh|~{p}DeZTkKsb6eCB$*0rb*2T^!4;wa4cro77oL)x)n1exAzF6bM z9K6;^#k_i5VrqKv0>)21yu*R9>vbMdwfTQ=|N=~{C^*LmxDJB#R*!HlhT?F4nl3yx5v z_#>wodE!W^F{cKuS6paZc8cL?9qU6fARJmfTUm*?D&Y;GC+%6SL&f4~Vdc`LgRrm0 z`Z^KgS?b$Z=CvcCGnQJqk+1#wD|OjC$1wBV?Uogsbp5U`j|D$cW)i5FY zhwzPn8ovYBri5YJXt~RY$|>z7lO|H;1=s9KJ7{3@1ud{Z^1DUi$*aM4J8VM@-(e2< zlRztK>RLKAeA3|3>Ie#O@u8Ha*R}X7H&~hM@KfleFYit@vCc!glY2(H5_{z1#qA+I zqD+Dr)KpA0*w#Th~cy{KzdctfqYq{CW-(HlrplBQ9< zlYBq8gJxIbJO|NZx^>dnp}v~&M-{UoY-kW}vE2z7^+V&Z;p~HWvJI5ZhU-rE39iAw z7=;%%JB4YvPeP2VK^@K%yoCq|&=^kyap~Gq(RWQBU}^e`(QY})GC+K)Iukmo@pt>~ zBIU&GAGeQ!;OUFoBj>dsEi_Wr?hm;lQQ#1WBqvjQQW;*kQ&B7=Gqw|WgA zS|Xt+o++Fy9ZqB)C*7wf@GXB{PHPTHTdH%gGipSR<7Z@Lc#B)$S>66XV1;^RV%>X| zb)I@=yY_2om10sH=(Ho_eZVsQS^jdI<$wmd5#fM-V#m>8CRhltzVpj?NmOXckc=2G z$k8ri&>#W}&WYWLeflmegWMfHU+y)zPvk}a2B1d386?n3IIVRNj7hUtjWcs_y`zsYF!t+czc))5M~VGGLf4m zsI%+y?id7*H!ri(4@r1v;dx`}l`Dn(@tPS#)RHWupugisQ?#D8EYir2PHWTEHkSHl z3y>BL4++sacrf|NUlKWa*uxNoxU>br&!|HT8NF`uzH>=a$mF3|Si+McC9s`whUGzG z3LfEPyul>w9_iO2l$s-*1f&s`N>jC!)|ag2W~CloCp`H4jS7Z|f>4A~OS&B6ruA?9 zmejF0VRS}U$ZnTb4opKC)30J4K_!_#^%7?Q9JQwWmISiz$)(Gfy?3A}ei1vM7ZzS&A{GyA_VtVL}|D(b1Duq5>o6w~zJmD=B4FeEyQ zsYj6%7zH7DIb!HQ&XR6sg&p?V2AILthe{thPcGTmgDCUfYzFtDLSI4k_YsnSq+OUE zW7OYD(u@ER*HwB?Y8%LazB>p||z?b4gnmDelg$6K(e7?>lnDkBF5ysP3u55}tpgF~}$R<5>qq?Z*aT^dO z@>w*h@KEiU^tJ@*sV7fno8ZVLd5}khOGx%;^eum0@OcsN*(Ly6{3ZaC2a;^A+_s|l zjnl-5R;C0H?c=`CJaROz2rfhC)cM>DE=b5ohzO%OI-U5)PWgUY)VCgn|N6ixmug=| zpC$m(xbu2L)g*<7|`eeZg$D=poGpd&+%`fl4JTirEw zbz88yjewaNCr>cp-wkz`@e0~_|OYg=Ged>90(DPd5hM?C8 z>k1aDXd4{+60Rhe=y)Gr3Mp$r63+{|DzTAF$Wq(3z!CSsB{YaVEY>{Z29gd-_GDbl zY$`CZs>|mj-^<-uX9RLPN|`u&Y0O5qRf=JOXP;XAyvD*(KhNZ71P=(M*_It zw?*sT&co$vPe*phL`3o)Pj0H1b8R3(8hH%-5G`RHQTjMhClo!&p~Z>Fc9Ytd>K`j=Wv5LjB9U35Q=%p>%o-tQd3o19HEuCb z({tp@XN@a0U1s5Pm)T8(wj+-SE#=aLyBYe{BCn7e%Oii#&-tG`*q4BVGjg~W0~2R7 zi8-Os8EI_LAIJP>@)PRABtV)V1aC5CMF&bL_WEWQ)kkS^;Jc>~Xn!Hb#ACiVO(JwXo`qW;`bxrj!}JD4+5LQ=fq57o~#s91>@&pWe}fY z-j!YvmDV)Q#wyOo)wc~s5BA!x5iq_0AqCx_w2e12gxD4wf2Q3lO*;HQ9Tt}%Dk+C@ z1^s&xI&(TxSfWFqlP9CM!;ixy5b1JU4FU1!@_n&2d1&|Hr(Yj!W4=(KHx@6WO%x{m z`hRXi8jL_9qr5+wKSV0idHJq5tP7Zz&+xk}{K3^Z_7rX;vPRjF3$(}ZbNI-k=M1b~ ztQ#de&=n9w&8AXxps>J{=_0m|*Ae36bev>vYS`I*81OkI&k4SA{y7tEpOC;cjvJ## zo)05s->0bg!|Iw?E`(7Ck%z^oY!;>f<2;H`b>PC_bQU<${QU?yWj$Oe++$|~*X~TE zhL6++UgSsNY1>M<5`FTe*XtxK8BAXj>>xy8+}tCbD^T}Gn%Azb86adLjmcQrJhRW& zZFIeBqn>1`3$-Fi>kY~-@Dn>q1MUD6^E3{EBkQ6Y1<5747S(Bcqdi?RTelFn32hI6arARNYbOVj*BYZa_A>Pn`y19Uh@~qSiz&Twi9^C|@Vmdv(q*aiP@w)gIHEoj%Ol*klL-@-_ z_Av>l`7Otof7yk?NN~4&x-jguow5XpLYhCfg2gabs1>o`%-9I-`OC^h+#t2c+(0J8 zn({dRS*bN=ADlc~R8o-XrFoSX?u0UVO-vr@^mIOyX`SI`K(Xt9uH|D%^`R~! zw>#VZ%+vc=35vclh2leXRph*tNnjF=d<BEj&Ub0ko;g-JLP-?Ya zGarYP(F|@l<Nzfhb z5DnW<*szKDVR56hszotEu6$L^i^PWUV|N^~skfNirQhuy%xkcUerB-T2^FW)kl@=v z1x^#9)FYvbpDgS^LYSC6N9qjT$|+NfXRu0upBfc$;yjxk!ejnNM<3s1?D4 z3+X`5so~G;$PIL`b+zvqGrh_E#%Li(cx`8t2aC2HUE{2QpfgVrn~hE4wvPvz2omK; zTQ8Oh=h3F?Sc5K;wCN-q#6Bv034PnR>+nees``VElYi*>n3hEds0s!h*tC?G$i=N7 zCl>B5r$9)L(9k2sOU$C;KO{a%;7~<9j^tsC!T}4eKGAP)Rlnw(lQ|-tw*UA@B zCa~BJx0?sQ!BE!EbjO#+^&k`)#*^6TA>q|OmXdunGL|W(k@9J8;9vCtDG|u$)w+~C~)YHtff!%7@Pe=!plu` zOGa2(JP4E{;-zIZ9ydVH9(E~^XvF&BL4~Kw9@UfAAeGG5x5cecKpQPId2IExCu;;n zlPP^_qv4td)y0u8^*~F)c8(?=CFrvu*Mdh6C8jrNpC`o6Ob+-yrki2d8&NAE(c_f2 zTGWP5h-_)bu%Kf+KjnmJKP>q1Wcw!5ffm@u7c@PJ1ci$dA@ys zDx5v37jP9uA>#`tDJ)EnD#^&JOd1s`AEGz!DXp3EfKUe@8XaGDt_3ED&`C0=zZ11# zVmDAa(XAx8Ii>ub?rthqWCuZ+H=*=INw5?d8;Qt}B`py;95|=&eM$n7hU52ifj9ygP2Jyhpx4CP5ngl{e&7!PX zd|bhnP0{?}bo!&P15B@xGftPH7$Vf%oc|)^=(7{G^q_Ljw{hrqi3hx0$4li-H%SAK zQu@%iSQ67N_So@fmyADwtor|BFQe#<`+ujAQ8X;Gp(&R2fVW%NgmO>YATORiW`#P6 zgoR|?Hk2q<)R}1I207wleG-FGhyh?KuGI8ORSPPsr5v5zOUAmOhdeleROEm1VReLZU1lzY|vnMla$>ug{1cWjW+r zHTo0dJ4vTT2yPC~VRZH+kbWHHz^9|@q5hEd+ zE}12}r0_}m22Zh3V#d4ZhT#5+bHqiC>B4j_?wNk1n7W%TkkqDL#Ng7hT}NvmGwHct z(IndpNV=R$`=D$)9MEBoUXvRg&!-26ituntDhB-8T*JJ6^GV=?fGN+rOGVG3FUrly z4jk0ZcEcd&LV1dUOERM((<75i<@J&#n#+rsiyAn6FmC)7x1RA-Vp5}5&Conr`ie*} z)^K9-UtxjVEYT}X<*czexN>)RUDG3a@2EeT)I$CxCa5!0C9i=7ENg&_oQu^iMfE zWq%hK2QKcw4@?ktX~69)xvVdG{0qbULRr&Pi0!7xao{qd(;rza2(FHy-?$zCH?;Hl zR0iQpRO&5GBI^{r_F6?Pq80YF{e$FCRP-NZbew=6N1@`YhK;7Z z9z6yrx_r3Xu=8Shb^vGM$t2bv$6v%E-3xYDyhADwKPw}P47XE9r5~19WmX*bfZw7o z*hJg7Ke88whENq8^PICK!_T`tS*7dOxfy=4xKvoVee#|B#_K0Jpn3zO+^QT6O^{4x z`R*vy>WTFEEPsUMBRqTV>os%*#(cX8UDQbb#L{8Q#_N0FZ(|!{Zq96-!Ly5$l46TZ z-3~`{&USq~T?&xfAU`MwR0=|IknG^c_hit=P`S5eq?!!SXnD=y)}m1LGeDo@3@ zxt}qLp~>$I-=>u%zLWR~kCzE;9aeY;E6>~%nAuTMtsYU6Qv4oCew19oOI8+md@Hd# z!Q-sfCrarY=Gr7Z=dk98&dRH2j+xQw;$c~aoF5Kkgatzd)I5@!y^=Me)b$AF6~zc=nUwiq$iHw>meX|XZwebf`e=*Y?Rb@^&$S{TP3k$9GNG+!Z4e# z$Y6Xd3`~QBz9xc(-h)z{`RaCHXQ%t9&>0kZgJa?9j2O@~kCFs!*SR^Uavg2bvHgwE zmexd5ZGzBb)eQ5I-6ZAxvcl47h6J{uwEJ`MtiUeyXxVllgm0>-3Iu-hW%rmAt! z@`2_qSBWx4Sk@huIIV8dioP6~|^ZH^4KcHD*j)8!C zi$_khU{P3vj(JY_Ng$Al(?aEiXDjGdbPAUd&!#(q;{%Hi>^eZOvheO$)~7Z>mL&R>?k#`hJX27WLJ5ORV(U{}=vu65#*< diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_hu.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_hu.ts deleted file mode 100644 index 828c946622..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_hu.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Egyéni adattár - - - - Repository URL - Adattároló URL - - - - Branch - Változat - - - - CompactView - - - - Icon - Ikon - - - - - <b>Package Name</b> - <b>Csomag neve</b> - - - - - Version - Verzió - - - - - Description - Leírás - - - - Update Available - Frissítés elérhetÅ‘ - - - - UpdateAvailable - Frissítés elérhetÅ‘ - - - - DependencyDialog - - - Dependencies - FüggÅ‘ségek - - - - Dependency type - FüggÅ‘ség tpus - - - - Name - Név - - - - Optional? - Választható? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - FüggÅ‘ségek feloldása - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Ez a bÅ‘vítmény a következÅ‘ szükséges vagy opcionális függÅ‘ségekkel rendelkezik. Ezeket telepíteni kell a bÅ‘vítmény használata elÅ‘tt. - -A bÅ‘vítmény kezelÅ‘ automatikusan telepítse Å‘ket? Válassza a "Elvet" lehetÅ‘séget a bÅ‘vítmény telepítéséhez a függÅ‘ségek telepítése nélkül. - - - - FreeCAD Addons - FreeCAD kiegészítÅ‘k - - - - Required Python modules - Szükséges Python modulok - - - - Optional Python modules - Választható Python modulok - - - - DeveloperModeDialog - - - Addon Developer Tools - Kiterjesztés fejlesztÅ‘i eszközök - - - - Path to Addon - Útvonal a kiterjesztéshez - - - - - Browse... - Tallózás... - - - - Metadata - Metaadatok - - - - Primary branch - ElsÅ‘dleges változat - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Annak magyarázata, hogy mit nyújt ez a kiterjesztés. Megjelenik a kiterjesztés kezelÅ‘ben. Ehhez nem szükséges kijelenteni, hogy ez egy FreeCAD kiterjesztés. - - - - Description - Leírás - - - - Discussion URL - Beszélgetés URL - - - - Icon - Ikon - - - - Bugtracker URL - HibakövetÅ‘ URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) vagy CalVer (2022.08.30) stílusok támogatottak - - - - Set to today (CalVer style) - Mai napra beállítva (CalVer stílusban) - - - - - - - (Optional) - (Választható) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Megjelenik a bÅ‘vítmények listájában a bÅ‘vítménykezelÅ‘ben. Nem tartalmazhatja a "FreeCAD"szót, és minden támogatott operációs rendszeren érvényes könyvtárnévnek kell lennie. - - - - README URL - OLVASS EL URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - Tipp: mivel ez a FreeCAD-ben, a BÅ‘vítmény KezelÅ‘ben jelenik meg, nem szükséges olyan információkkal foglalni a helyet, mint például "Ez egy FreeCAD kiegészítÅ‘..." -- csak mondja meg, hogy mit csinál. - - - - Repository URL - Adattároló URL - - - - Website URL - Webhely URL - - - - Documentation URL - Dokumentáció URL - - - - Addon Name - BÅ‘vítmény neve - - - - Version - Verzió - - - - (Recommended) - (Javasolt) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Választható, csak a 3.x verzió támogatott) - - - - Detect... - Észlelés... - - - - Addon Contents - BÅ‘vítmény tartalma - - - - Dialog - - - Addon Manager - BÅ‘vítmény kezelÅ‘ - - - - Edit Tags - Címkék szerkesztése - - - - Comma-separated list of tags describing this item: - Az elemet leíró címkék vesszÅ‘vel elválasztott listája: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - MEGJEGYZÉS: A szokásos címkék közé tartoznak a "Összeállítás", "VEM", "Rács", "NURBS" stb. - - - - Add-on Manager: Warning! - BÅ‘vítménykezelÅ‘: Figyelmeztetés! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - A bÅ‘vítménykezelÅ‘ hozzáférést biztosít a FreeCAD hasznos, harmadik féltÅ‘l származó FreeCAD-bÅ‘vítmények széleskörű könyvtárához. Ezek biztonságosságára vagy működÅ‘képességére vonatkozóan nem vállalható garancia. - - - - Continue - Tovább - - - - Cancel - Mégse - - - - EditDependencyDialog - - - Edit Dependency - FüggÅ‘ségek szerkesztése - - - - Dependency Type - FüggÅ‘ség típus - - - - Dependency - FüggÅ‘ség - - - - Package name, if "Other..." - A csomag neve, ha "Egyéb..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - MEGJEGYZÉS: Ha a "Egyéb..." van kiválasztva, a csomag nem szerepel az ALLOWED_PYTHON_PACKAGES.txt fájlban, és a BÅ‘vítmény kezelÅ‘ nem fogja automatikusan telepíteni. Küldjön PR-t a <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-Addons</a> címre, hogy kérjen egy csomag hozzáadást. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Ha ez egy választható függÅ‘ség, a bÅ‘vítménykezelÅ‘ felajánlja a telepítését (ha lehetséges), de nem blokkolja a telepítést, ha a felhasználó nem akarja vagy nem tudja telepíteni a csomagot. - - - - Optional - Választható - - - - ExpandedView - - - - Icon - Ikon - - - - - <h1>Package Name</h1> - <h1>Csomag neve</h1> - - - - - Version - Verzió - - - - - (tags) - (címkék) - - - - - Description - Leírás - - - - - Maintainer - KözreműködÅ‘ - - - - Update Available - Frissítés elérhetÅ‘ - - - - labelSort - címke rendezés - - - - UpdateAvailable - Frissítés elérhetÅ‘ - - - - Form - - - Licenses - Engedélyek - - - - License - Licenc - - - - License file - Engedély fájl - - - - People - Személyek - - - - Kind - Típus - - - - Name - Név - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Haladó verzió leképezés - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - A FreeCAD BÅ‘vítmény kezelÅ‘ következÅ‘ verziói segíteni fogják a fejlesztÅ‘i beállításokat' abban, hogy egy adott változatot vagy mezÅ‘t a FreeCAD egy adott verziójával való használatra adjanak meg (pl. egy adott mezÅ‘ beállításával a bÅ‘vítmény legújabb verziójához, amely még támogatja a v0.19-et, stb.) - - - - FreeCAD Version - FreeCAD verzió - - - - Best-available branch, tag, or commit - Legjobb elérhetÅ‘ változat, mezÅ‘ vagy commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Támogatott FreeCAD verziók - - - - Minimum FreeCAD Version Supported - FreeCAD támogatott minimális verziója - - - - - Optional - Választható - - - - Maximum FreeCAD Version Supported - FreeCAD támogatott legutolsó verziója - - - - Advanced version mapping... - Haladó verzió leképezés... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - BÅ‘vítmény kezelÅ‘ lehetÅ‘ségei - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Ha ez a beállítás be van jelölve, az BÅ‘vítmény kezelÅ‘je indításakor, -a telepített bÅ‘vítményeket a rendszer ellenÅ‘rzi az elérhetÅ‘ frissítésekre vonatkozóan - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Makró metaadatok letöltése (kb. 10 MB) - - - - Cache update frequency - Gyorsítótár frissítési gyakoriság - - - - Manual (no automatic updates) - Manuális (nincs automatikus frissítés) - - - - Daily - Napi - - - - Weekly - Heti - - - - Hide Addons without a license - Licenc nélküli bÅ‘vítmények elrejtése - - - - Hide Addons with non-FSF Free/Libre license - Nem FSF Free/Libre licenccel rendelkezÅ‘ bÅ‘vítmények elrejtése - - - - Hide Addons with non-OSI-approved license - Nem OSI által jóváhagyott licenccel rendelkezÅ‘ bÅ‘vítmény elrejtése - - - - Hide Addons marked Python 2 Only - Csak Python v. 2 bÅ‘vítmények elrejtése - - - - Hide Addons marked Obsolete - Az elavultként megjelölt bÅ‘vítmények elrejtése - - - - Hide Addons that require a newer version of FreeCAD - A FreeCAD újabb verzióját igénylÅ‘ bÅ‘vítmények elrejtése - - - - Custom repositories - Egyéni adattárak - - - - Proxy - Proxy - - - - No proxy - Nincs proxy - - - - User system proxy - Felhasználói rendszer proxy - - - - User-defined proxy: - Felhasználó által meghatározott proxy: - - - - Score source URL - Forrás pontszám URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Az BÅ‘vítmény pontozási adatok URL címe (lásd az BÅ‘vítmény kezelÅ‘je wiki oldalát a formázás és a tárhely részleteiért). - - - - Path to Git executable (optional): - Git futtatható fájl elérési útja (opcionális): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Haladó beállítások - - - - Activate Addon Manager options intended for developers of new Addons. - Aktiválja az új BÅ‘vítmény kezelÅ‘khöz a fejlesztÅ‘knek szánt Bítmény kezelÅ‘ lehetÅ‘ségeket. - - - - Addon developer mode - BÅ‘vítmény fejlesztÅ‘i mód - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Kijelölt makró vagy munkafelület eltávolítása - - - - Install - Teleptés - - - - Uninstall - Eltávolítás - - - - Update - Frissítés - - - - Run Macro - Makró futtatás - - - - Change branch - Változat módosítása - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Python-függÅ‘ségek kezelése - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - A következÅ‘ Python-csomagokat helyileg telepítette a BÅ‘vítmény kezelÅ‘jével a BÅ‘vítmény függÅ‘ségek kielégítése érdekében. Telepítési hely: - - - - Package name - Csomag neve - - - - Installed version - Telepített verzió - - - - Available version - ElérhetÅ‘ verzió - - - - Used by - Használja - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - A csillag (*) a "Használja" oszlopban választható függÅ‘séget jelez. Vegye figyelembe, hogy a Használja csak a BÅ‘vítmény közvetlen importjait rögzíti. Más Python csomagok is települhettek, amelyektÅ‘l ezek a csomagok függnek. - - - - Update all available - Összes elérhetÅ‘ frissítése - - - - SelectFromList - - - Dialog - Párbeszédablak - - - - TextLabel - Szövegfelirat - - - - UpdateAllDialog - - - Updating Addons - KiegészítÅ‘k frissítése - - - - Updating out-of-date addons... - Az elavult kiegészítÅ‘k frissítése... - - - - addContentDialog - - - Content Item - Tartalom elem - - - - Content type: - Elem típus: - - - - Macro - Makró - - - - Preference Pack - ElÅ‘nyben részesített csomag - - - - Workbench - Munkafelület - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Ha ez az egyetlen dolog a BÅ‘vítményben, akkor minden más metaadat a legfelsÅ‘ szintrÅ‘l örökölhetÅ‘, és nem kell itt megadni. - - - - This is the only item in the Addon - Ez az egyetlen elem az bÅ‘vítményben - - - - Main macro file - FÅ‘ makró fájl - - - - The file with the macro's metadata in it - A makró'metaadatokat tartalmazó fájl - - - - - - Browse... - Tallózás... - - - - Preference Pack Name - Preferencia csomag név - - - - Workbench class name - Munkafelület osztály neve - - - - Class that defines "Icon" data member - Az "Ikon" adattagot meghatározó osztály - - - - Subdirectory - Alkönyvtár - - - - Optional, defaults to name of content item - Választható, alapértelmezés szerint a tartalomelem neve - - - - Icon - Ikon - - - - Optional, defaults to inheriting from top-level Addon - Választható, alapértelmezés szerint a legfelsÅ‘ szintű bÅ‘vítménybÅ‘l öröklÅ‘dik - - - - Tags... - Címkék... - - - - Dependencies... - FüggÅ‘ségek... - - - - FreeCAD Versions... - FreeCAD verziók... - - - - Other Metadata - Egyéb metaadat - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Megjelenik a BÅ‘vítmény kezelÅ‘k' BÅ‘vítmény listájában. Nem tartalmazhatja a "FreeCAD" szót. - - - - Version - Verzió - - - - Description - Leírás - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) vagy CalVer (2022.08.30) stílusok támogatottak - - - - Set to today (CalVer style) - Mai napra beállítva (CalVer stílusban) - - - - Display Name - Név megjelenítése - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Az üresen hagyott mezÅ‘k a legfelsÅ‘ szintű bÅ‘vítmény metaadatokból öröklÅ‘dnek, így technikailag mindegyik választható. A több tartalmi elemet tartalmazó bÅ‘vítmény esetében minden egyes elemnek egyedi megjelenítési nevet és leírást kell megadnia. - - - - add_toolbar_button_dialog - - - Add button? - Gomb hozzáadása? - - - - Add a toolbar button for this macro? - Eszköztárgomb hozzáadása ehhez a makróhoz? - - - - Yes - Igen - - - - No - Nem - - - - Never - Soha - - - - change_branch - - - Change Branch - Változat módosítása - - - - Change to branch: - Váltson a változatra: - - - - copyrightInformationDialog - - - Copyright Information - SzerzÅ‘i jogi információk - - - - Copyright holder: - SzerzÅ‘i jogtulajdonos: - - - - Copyright year: - SzerzÅ‘i jog éve: - - - - personDialog - - - Add Person - Személy hozzáadása - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A karbantartó az a személy, aki hozzáféréssel rendelkezik a projektben lévÅ‘ commitokhoz. A szerzÅ‘ bárki más, akit te' szeretnél bevonni. - - - - Name: - Név: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Az e-mail cím megadása a felügyelÅ‘k számára kötelezÅ‘, a szerzÅ‘k számára nem kötelezÅ‘. - - - - proxy_authentication - - - Proxy login required - Proxy belépés szükséges - - - - Proxy requires authentication - Proxy azonosítás szükséges - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - A proxy cím helyÅ‘rzÅ‘je - - - - Realm: - Terület: - - - - Placeholder for proxy realm - A proxy cím tartomány helyÅ‘rzÅ‘je - - - - Username - Felhasználónév - - - - Password - Jelszó - - - - selectLicenseDialog - - - Select a license - Licencfájl kiválasztása - - - - About... - Névjegy... - - - - License name: - Engedély neve: - - - - Path to license file: - Engedély fájl útvonala: - - - - (if required by license) - (ha az engedély előírja) - - - - Browse... - Tallózás... - - - - Create... - Létrehoz... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Eszköztár kiválasztása - - - - Select a toolbar to add this macro to: - Válasszon ki egy eszköztárat a makró hozzáadásához: - - - - Ask every time - Mindig kérdezzen rá - - - - toolbar_button - - - - Add button? - Gomb hozzáadása? - - - - Add a toolbar button for this macro? - Eszköztárgomb hozzáadása ehhez a makróhoz? - - - - Yes - Igen - - - - No - Nem - - - - Never - Soha - - - - AddonsInstaller - - - Starting up... - Elkezd... - - - - Worker process {} is taking a long time to stop... - Hosszú idÅ‘be telik egy futó {} folyamat leállítása... - - - - Previous cache process was interrupted, restarting... - - Az elÅ‘zÅ‘ gyorsítótár-folyamat megszakadt, újraindul... - - - - - Custom repo list changed, forcing recache... - - Megváltoztatta a felhasználói tárolók listáját, kényszerítve az újbóli gyorsítótárazást... - - - - - Addon manager - BÅ‘vítmény kezelÅ‘ - - - - You must restart FreeCAD for changes to take effect. - A módosítások érvénybe léptetéséhez újra kell indítania a FreeCAD-et. - - - - Restart now - Újraindítás most - - - - Restart later - Újraindítás késÅ‘bb - - - - - Refresh local cache - Gyorsítótár frissítése - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Gyorsítótár frissítése... - - - - - Checking for updates... - Frissítés keresése... - - - - Temporary installation of macro failed. - A makró ideiglenes telepítése sikertelen. - - - - - Close - Bezárás - - - - Update all addons - Összes bÅ‘vítmény frissítése - - - - Check for updates - Frissítések keresése - - - - Python dependencies... - Python függÅ‘ségek... - - - - Developer tools... - FejlesztÅ‘i eszközök... - - - - Apply %n available update(s) - %n elérhetÅ‘ frissítés(ek) alkalmazása - - - - No updates available - Nincs elérhetÅ‘ frissítés - - - - - - Cannot launch a new installer until the previous one has finished. - Az új telepítÅ‘ csak az elÅ‘zÅ‘ telepítÅ‘ befejezése után indítható el. - - - - - - - Maintainer - KözreműködÅ‘ - - - - - - - Author - Létrehozó - - - - New Python Version Detected - Új Python verziót érzékelt - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Úgy tűnik, hogy ez az elsÅ‘ alkalom, hogy a Python ezen verzióját a BÅ‘vítmény kezelÅ‘vel együtt használják. Szeretné telepíteni ugyanazokat az automatikusan telepített függÅ‘ségeket hozzá? - - - - Processing, please wait... - Feldolgozás folyamatban, kérjük várjon... - - - - - Update - Frissítés - - - - Updating... - Frissítés... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Nem lehet importálni a QtNetwork-et - nincs telepítve a rendszerre. ElÅ‘fordulhat, hogy a szolgáltatónak van egy csomagja ehhez a függÅ‘séghez (gyakran így nevezik "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Nem sikerült a megadott '{}' proxy portot a port számra átalakítani - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Paraméter hiba: kölcsönösen kizáró proxy beállítások. Alapértelmezettre visszaállítás. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Paraméterhiba: felhasználói proxy van megadva, de nincs megadva proxy. Alapértelmezettre visszaállítás. - - - - Addon Manager: Unexpected {} response from server - BÅ‘vítmény kezelÅ‘: Váratlan {} válasz a szervertÅ‘l - - - - Error with encrypted connection - Hiba a titkosított kapcsolat során - - - - - - Confirm remove - Eltávolítás megerÅ‘sítése - - - - Are you sure you want to uninstall {}? - Biztosan szeretné a(z) {} eltávolítani? - - - - - - Removing Addon - BÅ‘vítmény eltávolítás - - - - Removing {} - Eltávolítás {} - - - - - Uninstall complete - Eltávolítás befejezÅ‘dött - - - - - Uninstall failed - Sikertelen eltávolítás - - - - Version {version} installed on {date} - {version} telepítve ekkor {date} - - - - Version {version} installed - {version} verzió telepítve - - - - Installed on {date} - Telepítés ideje {date} - - - - - - - Installed - Telepítve - - - - Currently on branch {}, name changed to {} - Jelenleg a {} változat van, neve {}-ra változott - - - - Git tag '{}' checked out, no updates possible - Git mezÅ‘ '{}' ellenÅ‘rizve, frissítés nem lehetséges - - - - Update check in progress - Frissítések ellenÅ‘rzése folyamatban - - - - Installation location - Telepítés helye - - - - Repository URL - Adattároló URL - - - - Changed to branch '{}' -- please restart to use Addon. - Változatre módosította '{}' -- indítsa újra a bÅ‘vítmény használatához. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Ezt a bÅ‘vítményt frissítettük. A változások megtekintéséhez indítsa újra a FreeCAD-et. - - - - Disabled - Kikapcsolva - - - - Currently on branch {}, update available to version {} - Jelenleg a {} változaton van, frissítés elérhetÅ‘ a {} verzióra - - - - Update available to version {} - Rendelkezésre áll frissítés a {} verzióra - - - - This is the latest version available - Ez a legfrissebb elérhetÅ‘ verzió - - - - WARNING: This addon is obsolete - FIGYELMEZTETÉS: Ez a bÅ‘vítmény elavult - - - - WARNING: This addon is Python 2 only - FIGYELMEZTETÉS: Ez a bÅ‘vítmény csak Python 2 - - - - WARNING: This addon requires FreeCAD {} - FIGYELEM: Ehhez a bÅ‘vítményhez FreeCAD {} szükséges - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - FIGYELMEZTETÉS: Ez a bÅ‘vítmény jelenleg telepített, de le van tiltva. Használja az 'engedélyezés' gombot a visszakapcsolásához. - - - - This Addon will be enabled next time you restart FreeCAD. - Ez a bÅ‘vítmény a FreeCAD következÅ‘ újraindításakor lesz engedélyezve. - - - - This Addon will be disabled next time you restart FreeCAD. - Ez a bÅ‘vítmény a FreeCAD következÅ‘ újraindításakor lesz kiiktatva. - - - - - - Success - Sikerült - - - - Install - Teleptés - - - - Uninstall - Eltávolítás - - - - Enable - Bekapcsolás - - - - Disable - Letilt - - - - - Check for update - Frissítés keresése - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Futtat - - - - Change branch... - Változat módosítása... - - - - Return to package list - Vissza a csomag listához - - - - Checking connection - Kapcsolat tesztelése - - - - Checking for connection to GitHub... - A GitHubhoz való kapcsolat ellenÅ‘rzése... - - - - Connection failed - Csatlakozás sikertelen - - - - Missing dependency - Hiányzó függÅ‘ség - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - QtNetwork importálhatatlan - lásd a Jelentésnézetet a részletekért. A bÅ‘vítmény kezelÅ‘ nem érhetÅ‘ el. - - - - Other... - For providing a license other than one listed - Egyéb... - - - - Select the corresponding license file in your Addon - Válassza ki a megfelelÅ‘ licencfájlt a bÅ‘vítményben - - - - Location for new license file - Új licencfájl helye - - - - Received {} response code from server - {} válaszkód érkezett a szervertÅ‘l - - - - Failed to install macro {} - {} makró telepítése sikertelen - - - - Failed to create installation manifest file: - - Nem sikerült létrehozni a telepítési manifeszt fájlt: - - - - - Unrecognized content kind '{}' - Nem ismert tartalomfajta '{}' - - - - Unable to locate icon at {} - Nem sikerült megtalálni az ikont a {} - - - - Select an icon file for this content item - Válasszon ki egy ikonfájlt ehhez a tartalmi elemhez - - - - - - {} is not a subdirectory of {} - {} nem alkönyvtára ennek: {} - - - - Select the subdirectory for this content item - Válassza ki a tartalmi elem alkönyvtárát - - - - Automatic - Automatikus - - - - - Workbench - Munkafelület - - - - Addon - BÅ‘vítmény - - - - Python - Python - - - - Yes - Igen - - - - Internal Workbench - BelsÅ‘ munkafelület - - - - External Addon - KülsÅ‘ bÅ‘vítmény - - - - Python Package - Python csomag - - - - - Other... - Egyéb... - - - - Too many to list - Túl sok a listázáshoz - - - - - - - - - Missing Requirement - Hiányzó követelmény - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - A '{}' bÅ‘vítményhez a '{}', csomagra van szükség, amely nem érhetÅ‘ el a FreeCAD-ben. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - A '{}' bÅ‘vítmény olyan munkafelületeket igényel, amelyek nem állnak rendelkezésre a FreeCAD példányában: - - - - Press OK to install anyway. - Nyomja meg az OK gombot a telepítés kényszerítéséhez. - - - - - Incompatible Python version - Nem kompatibilis Python verzió - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Ez a bÅ‘vítmény olyan Python-csomagokat igényel, amelyek nincsenek telepítve, és nem is telepíthetÅ‘k automatikusan. A bÅ‘vítmény használatához a következÅ‘ Python csomagokat magának kell telepítenie: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Ez a bÅ‘vítmény (vagy valamelyik függÅ‘sége) Python {}.{}-t igényel, és az Ön rendszerén {}.{} fut. A telepítés törlÅ‘dött. - - - - Optional dependency on {} ignored because it is not in the allow-list - A rendszer figyelmen kívül hagyja a választható függÅ‘séget a(z) {} sablontól, mert nem szerepel az engedélyezett listán - - - - - Installing dependencies - FüggÅ‘ségek telepítése - - - - - Cannot execute Python - Python nem hajtható végre - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Nem sikerült automatikusan megtalálni a Python futtatható fájlt, vagy az elérési út rosszul van megadva. EllenÅ‘rizze a bÅ‘vítmény kezelÅ‘ beállításban a Python környezet elérési útvonalát. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - A függÅ‘ségeket nem sikerült telepíteni. Folytassa a {} telepítését? - - - - - Cannot execute pip - Pip nem hajtható végre - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Nem sikerült a pip futtatása, ami lehet, hogy hiányzik a Python telepítésébÅ‘l. Kérjük, gyÅ‘zÅ‘djön meg róla, hogy a rendszerén telepítve van a pip, és próbálja meg újra. A sikertelen parancs a következÅ‘ volt: - - - - - Continue with installation of {} anyway? - Folytassa a {} telepítését? - - - - - Package installation failed - Oldal telepítése sikertelen - - - - See Report View for detailed failure log. - A részletes hibanaplót a Jelentésnézet című témakörben tekintheti meg. - - - - Installing Addon - BÅ‘vítmény telepítése - - - - Installing FreeCAD Addon '{}' - A FreeCAD '{}' bÅ‘vítmény telepítése - - - - Cancelling - Megszakít - - - - Cancelling installation of '{}' - A '{}' telepítésének megszakítása - - - - {} was installed successfully - {} sikeresen telepítve - - - - - Installation Failed - Telepítés sikertelen - - - - Failed to install {} - A {} nem sikerült telepíteni - - - - - Create new toolbar - Új eszköztár létrehozása - - - - - A macro installed with the FreeCAD Addon Manager - A FreeCAD bÅ‘vítmény kezelÅ‘vel telepített makró - - - - - Run - Indicates a macro that can be 'run' - Futtat - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Nem sikerült adatokat olvasni a GitHubról: ellenÅ‘rizze az internetkapcsolat és a proxy beállításait, és próbálja meg újra. - - - - XML failure while reading metadata from file {} - XML hiba a metaadatok olvasása közben a {} fájlból - - - - Invalid metadata in file {} - Érvénytelen metaadat a {} fájlban - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - FIGYELMEZTETÉS: A package.xml metaadatokban megadott elérési út nem egyezik a jelenleg ellenÅ‘rzött változattal. - - - - Name - Név - - - - Class - Tűrési osztály - - - - Description - Leírás - - - - Subdirectory - Alkönyvtár - - - - Files - Fájlok - - - - Select the folder containing your Addon - Válassza ki a bÅ‘vítményt tartalmazó mappát - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Nincs Vermin, megszakítva a műveletet. - - - - Scanning Addon for Python version compatibility - A bÅ‘vítmény Python-környezet verzió kompatibilitásának vizsgálata - - - - Minimum Python Version Detected - Minimális Python verziót érzékelt - - - - Vermin auto-detected a required version of Python 3.{} - A Vermin automatikusan észlelte a Python 3.{} szükséges verzióját - - - - Install Vermin? - Telepítse a Vermint? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - A Python-környezet szükséges verziójának automatikus felismeréséhez a Vermin kiegészítÅ‘re van szükség (https://pypi.org/project/vermin/). "OK" a telepítéshez? - - - - Attempting to install Vermin from PyPi - A Vermin telepítésének kísérlete a PyPi-ból - - - - - Installation failed - Sikertelen telepítés - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - A Vermin telepítése sikertelen -- a részletekért nézze meg a Jelentés nézetet. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - A telepítés után nem sikerült importálni a Vermint -- nem tudja ellenÅ‘rizni a bÅ‘vítményt. - - - - Select an icon file for this package - Válasszon ki egy ikonfájlt ehhez a csomaghoz - - - - Filter is valid - A szűrÅ‘ érvényes - - - - Filter regular expression is invalid - A szűrÅ‘ alapértelmezett kifejezése érvénytelen - - - - Search... - Keres... - - - - Click for details about package {} - Kattintson a csomag részleteiért {} - - - - Click for details about workbench {} - Kattintson a munkafelület részleteiért {} - - - - Click for details about macro {} - Kattintson a makró részleteiért {} - - - - Maintainers: - KözreműködÅ‘k: - - - - Tags - Címkék - - - - {} ★ on GitHub - {} ★ GitHub-on - - - - No ★, or not on GitHub - ★ sz., vagy nincs a GitHub-on - - - - Created - Létrehozott - - - - Updated - Frissített - - - - Score: - Pontszám: - - - - - Up-to-date - Naprakész - - - - - - - - Update available - Frissítés elérhetÅ‘ - - - - - Pending restart - Újraindításra vár - - - - - DISABLED - LETILTVA - - - - Installed version - Telepített verzió - - - - Unknown version - Ismeretlen verzió - - - - Installed on - Telepítve ekkor - - - - Available version - ElérhetÅ‘ verzió - - - - Filter by... - Szűrés ezzel... - - - - Addon Type - BÅ‘vítmény típus - - - - - Any - Bármelyik - - - - Macro - Makró - - - - Preference Pack - ElÅ‘nyben részesített csomag - - - - Installation Status - Telepítés állapota - - - - Not installed - Nincs telepítve - - - - Filter - SzűrÅ‘ - - - - DANGER: Developer feature - VESZÉLY: FejlesztÅ‘i funkció - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - VESZÉLY: A változatok váltása fejlesztÅ‘knek és béta tesztelÅ‘knek szól, és törött, nem visszafelé kompatibilis dokumentumokat, instabilitást, összeomlást és/vagy az univerzum idÅ‘ elÅ‘tti hÅ‘halálát eredményezheti. Biztos vagy benne, hogy folytatni akarod? - - - - There are local changes - Helyi módosítások vannak - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - FIGYELMEZTETÉS: Ez a repo nem commitolt helyi változásokat tartalmaz. Biztos vagy benne, hogy változatot akarsz váltani (magaddal hozva a változásokat)? - - - - Local - Table header for local git ref name - Helyi - - - - Remote tracking - Table header for git remote tracking branch name - Távoli követés - - - - Last Updated - Table header for git update date - Legutóbb frissítve - - - - Installation of Python package {} failed - A {} Python csomag telepítése sikertelen - - - - Installation of optional package failed - A {} választható csomag telepítése sikertelen - - - - Installing required dependency {} - {} szükséges függÅ‘ség telepítése - - - - Installation of Addon {} failed - A {} bÅ‘vítmény telepítése sikertelen - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Nem sikerült dekódolni a {} fájlt a '{}' hozzáadásához - - - - Any dependency information in this file will be ignored - Az ebben a fájlban lévÅ‘ függÅ‘ségi információkat figyelmen kívül hagyjuk - - - - Unable to open macro wiki page at {} - A {} makro wiki oldalt nem lehet megnyitni - - - - Unable to fetch the code of this macro. - Nem sikerült beolvasni a makró kódját. - - - - Unable to retrieve a description from the wiki for macro {} - Nem olvasható be a {} makró wiki leírása - - - - Unable to open macro code URL {} - A {} makrókód URL nem nyitható meg - - - - Unable to fetch macro-specified file {} from {} - Nem sikerült lekérni a makró által megadott {} fájlt innen: {} - - - - Could not locate macro-specified file {} (expected at {}) - Nem találta a makró által megadott {} fájlt (a {}-nál kellett volna lennie) - - - - {}: Unrecognized internal workbench '{}' - {}: Nem ismert belsÅ‘ munkafelület '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - BÅ‘vítmény fejlesztÅ‘i figyelmeztetés: A bÅ‘vítmény {} ({}) package.xml fájlban megadott tároló URL címe nem egyezik az URL-címmel, ahonnan lehívásra került ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - BÅ‘vítmény fejlesztÅ‘i figyelmeztetés: A package.xml fájlban a {} ({}) bÅ‘vítmény tárolt változata nem egyezik azzal a változattal, ahonnan lekérdezték ({}) - - - - - Got an error when trying to import {} - Hibát kapott, amikor megpróbálta importálni a {} - - - - An unknown error occurred - Ismeretlen hiba történt - - - - Could not find addon {} to remove it. - Nem találta az eltávolítandó {} bÅ‘vítményt. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - BÅ‘vítmény' uninstall.py forgatókönyvének végrehajtása sikertelen volt. Folytatja az eltávolítást... - - - - Removed extra installed file {} - {} extra telepített fájl eltávolítása - - - - Error while trying to remove extra installed file {} - Hiba a(z) {} extra telepített fájl eltávolítása közben - - - - Error while trying to remove macro file {}: - Hiba a {} makrófájl eltávolítása közben: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Nem sikerült csatlakozni a GitHubhoz. EllenÅ‘rizze a kapcsolat és a proxy beállításait. - - - - WARNING: Duplicate addon {} ignored - FIGYELMEZTETÉS: A {} bÅ‘vítmény duplikátuma elhagyva - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Hiba történt a makrók frissítésében a GitHubról, próbálom tisztán ellenÅ‘rizni a... - - - - Attempting to do a clean checkout... - Megpróbálok egy tiszta kijelentkezést végezni... - - - - Clean checkout succeeded - A tiszta kilépés sikerült - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Nem sikerült frissíteni a makrókat a GitHubról -- próbálja meg törölni a bÅ‘vítmény kezelÅ‘'s cache-t. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Hiba a Wikihez csatlakozásban, a FreeCAD jelenleg nem tudja lekérdezni a Wiki makrólistáját - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Nem sikerült beolvasni a metaadatokat innen {name} - - - - Failed to fetch code for macro '{name}' - Nem sikerült kódot lekérni a '{name}' makróhoz - - - - Addon Manager: a worker process failed to complete while fetching {name} - BÅ‘vítmény kezelÅ‘: a {name} letöltése során nem sikerült befejezni a feldolgozást - - - - Out of {num_macros} macros, {num_failed} timed out while processing - A {num_macros} makrók közül {num_failed} a feldolgozás során letelt az idÅ‘ - - - - Addon Manager: a worker process failed to halt ({name}) - BÅ‘vítmény kezelÅ‘: egy munkafolyamat nem állt le ({name}) - - - - Timeout while fetching metadata for macro {} - IdÅ‘kiesés a makró metaadatainak lekérése közben innen: {} - - - - Failed to kill process for macro {}! - - Nem sikerült leállítani a {} makró folyamatát! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Sikertelenül kapta meg a BÅ‘vítmény statisztikákat innen {} - csak az ábécé szerinti rendezés lesz pontos - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Sikertelenül kapta meg a BÅ‘vítmény pontszámot a '{}' - a pontszám szerinti rendezés sikertelen lesz - - - - - Repository URL - Preferences header for custom repositories - Adattároló URL - - - - Branch name - Preferences header for custom repositories - Változat neve - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Az eredeti könyvtár biztonsági mentése és újraklónozása - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git változat átnevezés a következÅ‘ üzenettel sikertelen volt: - - - - Installing - Telepítés - - - - Succeeded - Sikerült - - - - Failed - Sikertelen - - - - Update was cancelled - Frissítés megszakításra került - - - - some addons may have been updated - egyes bÅ‘vítmények frissülhettek - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - A {} információ betöltése a FreeCAD Mkro Receptek wikibÅ‘l... - - - - Loading page for {} from {}... - Oldal betöltés ehhez {} ebbÅ‘l {}... - - - - Failed to download data from {} -- received response code {}. - Nem sikerült letölteni az adatokat innen {} - a válaszkód {}. - - - - Composite view - Összetett nézet - - - - Expanded view - BÅ‘vített nézet - - - - Compact view - Kompakt nézet - - - - Alphabetical - Sort order - Betűrendes - - - - Last Updated - Sort order - Legutóbb frissítve - - - - Date Created - Sort order - Létehozás dátuma - - - - GitHub Stars - Sort order - GitHub csillagok - - - - Score - Sort order - Pontszám - - - - Std_AddonMgr - - - &Addon manager - &BÅ‘vítmény kezelÅ‘ - - - - Manage external workbenches, macros, and preference packs - KülsÅ‘ munkafelületek, makrók és beállításcsomagok kezelése - - - - AddonInstaller - - - Finished removing {} - {} fájl eltávolítása befejezÅ‘dött - - - - Failed to remove some files - Néhány fájl eltávolítása sikertelen - - - - Addons installer - - - Finished updating the following addons - A következÅ‘ bÅ‘vítmények frissítése befejezÅ‘dött - - - - Workbench - - - Auto-Created Macro Toolbar - Automatikusan létrehozott makró eszköztár - - - - QObject - - - Addon Manager - BÅ‘vítmény kezelÅ‘ - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_id.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_id.qm deleted file mode 100644 index 6b47a58f3da7c2ab53663dc7d7df6bf8fec209eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68510 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_id.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_id.ts deleted file mode 100644 index b4d5bd5275..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_id.ts +++ /dev/null @@ -1,2514 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Repositori khusus - - - - Repository URL - URL repositori - - - - Branch - Cabang - - - - CompactView - - - - Icon - Ikon - - - - - <b>Package Name</b> - <b>Nama Paket</b> - - - - - Version - Versi - - - - - Description - Description - - - - Update Available - Pembaruan Tersedia - - - - UpdateAvailable - PembaruanTersedia - - - - DependencyDialog - - - Dependencies - Dependensi - - - - Dependency type - Tipe dependensi - - - - Name - Nama - - - - Optional? - Opsional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Selesaikan Ketergantungan - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Addon ini memiliki dependensi wajib dan opsional. Anda harus menginstalnya sebelum Addon ini dapat digunakan. - -Apakah Anda ingin Pengelola Addon menginstalnya secara otomatis? Pilih "Abaikan" untuk menginstal Addon tanpa menginstal dependensi. - - - - FreeCAD Addons - Addon FreeCAD - - - - Required Python modules - Modul Python yang diperlukan - - - - Optional Python modules - Modul Python opsional - - - - DeveloperModeDialog - - - Addon Developer Tools - Alat Pengembang Addon - - - - Path to Addon - Lokasi ke Addon - - - - - Browse... - Telusuri... - - - - Metadata - Metadata - - - - Primary branch - Cabang utama - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Description - - - - Discussion URL - URL diskusi - - - - Icon - Ikon - - - - Bugtracker URL - URL pelacak bug - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Opsional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - URL README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - URL repositori - - - - Website URL - URL situs web - - - - Documentation URL - URL dokumentasi - - - - Addon Name - Nama Addon - - - - Version - Versi - - - - (Recommended) - (Direkomendasikan) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Deteksi... - - - - Addon Contents - Konten Addon - - - - Dialog - - - Addon Manager - Pengelola Addon - - - - Edit Tags - Ubah Tanda - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Welcome to the Addon Manager - Selamat datang di Pengelola Addon - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Download Settings - Pengaturan Unduhan - - - - Automatically check installed Addons for updates - Automatically check installed Addons for updates - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - No proxy - Tanpa proxy - - - - System proxy - System proxy - - - - User-defined proxy: - User-defined proxy: - - - - These and other settings are available in the FreeCAD Preferences window. - These and other settings are available in the FreeCAD Preferences window. - - - - EditDependencyDialog - - - Edit Dependency - Sunting Dependensi - - - - Dependency Type - Dependency Type - - - - Dependency - Dependensi - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Opsional - - - - ExpandedView - - - - Icon - Ikon - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - Versi - - - - - (tags) - (tanda) - - - - - Description - Description - - - - - Maintainer - Pemelihara - - - - Update Available - Pembaruan Tersedia - - - - labelSort - labelSort - - - - UpdateAvailable - PembaruanTersedia - - - - Form - - - Licenses - Lisensi - - - - License - Lisensi - - - - License file - Berkas lisensi - - - - People - Orang - - - - Kind - Jenis - - - - Name - Nama - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Versi Pengelola Addon FreeCAD yang akan datang akan mendukung pengembangan pengembang mengatur cabang atau tanda tertentu untuk digunakan dengan versi FreeCAD tertentu (misalnya, mengatur tanda tertentu sebagai versi terakhir Addon Anda untuk mendukung v0.19, dll.) - - - - FreeCAD Version - Versi FreeCAD - - - - Best-available branch, tag, or commit - Cabang, tag, atau penerapan terbaik yang tersedia - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versi FreeCAD yang Didukung - - - - Minimum FreeCAD Version Supported - Versi FreeCAD Minimum yang Didukung - - - - - Optional - Opsional - - - - Maximum FreeCAD Version Supported - Versi FreeCAD Maksimum yang Didukung - - - - Advanced version mapping... - Pemetaan versi lanjutan... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opsi pengelola Addon - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires git) - Secara otomatis memeriksa pembaruan di awal (memerlukan git) - - - - Download Macro metadata (approximately 10MB) - Unduh metadata Makro (sekitar 10MB) - - - - Cache update frequency - Frekuensi pembaruan cache - - - - Manual (no automatic updates) - Manual (tidak ada pembaruan otomatis) - - - - Daily - Harian - - - - Weekly - Mingguan - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Repositori khusus - - - - Proxy - Proxy - - - - No proxy - Tanpa proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to git executable (optional): - Path to git executable (optional): - - - - The path to the git executable. Autodetected if needed and not specified. - The path to the git executable. Autodetected if needed and not specified. - - - - Advanced Options - Pilihan Lanjutan - - - - Show option to change branches (requires git) - Show option to change branches (requires git) - - - - Disable git (fall back to ZIP downloads only) - Disable git (fall back to ZIP downloads only) - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Pasang - - - - Uninstall - Copot pemasangan - - - - Update - Memperbarui - - - - Run Macro - Jalankan Makro - - - - Change branch - Ubah cabang - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Nama paket - - - - Installed version - Versi terpasang - - - - Available version - Versi tersedia - - - - Used by - Digunakan oleh - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Perbarui semua yang tersedia - - - - SelectFromList - - - Dialog - Dialog - - - - TextLabel - TextLabel - - - - UpdateAllDialog - - - Updating Addons - Memperbarui Addon - - - - Updating out-of-date addons... - Memperbarui Addon yang kedaluwarsa... - - - - addContentDialog - - - Content Item - Isi item - - - - Content type: - Jenis konten: - - - - Macro - Makro - - - - Preference Pack - Paket Preferensi - - - - Workbench - Meja kerja - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Telusuri... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Ikon - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tanda... - - - - Dependencies... - Dependensi... - - - - FreeCAD Versions... - Versi FreeCAD... - - - - Other Metadata - Metadata Lainnya - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versi - - - - Description - Description - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Setel ke hari ini (gaya CalVer) - - - - Display Name - Nama Tampilan - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Tambah tombol? - - - - Add a toolbar button for this macro? - Tambahkan tombol toolbar untuk makro ini? - - - - Yes - Ya - - - - No - Tidak - - - - Never - Tidak pernah - - - - change_branch - - - Change Branch - Ubah cabang - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Informasi Hak Cipta - - - - Copyright holder: - Pemegang Hak Cipta: - - - - Copyright year: - Tahun Hak Cipta: - - - - personDialog - - - Add Person - Tambah Orang - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Nama: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Nama pengguna - - - - Password - Kata sandi - - - - selectLicenseDialog - - - Select a license - Pilih Lisensi - - - - About... - Tentang... - - - - License name: - Nama lisensi: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Telusuri... - - - - Create... - Buat... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Pilih Toolbar - - - - Select a toolbar to add this macro to: - Pilih toolbar untuk menambahkan makro ini ke: - - - - Ask every time - Tanyakan setiap saat - - - - toolbar_button - - - - Add button? - Tambah tombol? - - - - Add a toolbar button for this macro? - Tambahkan tombol toolbar untuk makro ini? - - - - Yes - Ya - - - - No - Tidak - - - - Never - Tidak pernah - - - - AddonsInstaller - - - Starting up... - Memulai... - - - - Loading addon information - Memuat informasi addon - - - - Worker process {} is taking a long time to stop... - Proses bekerja {} membutuhkan waktu lama untuk berhenti... - - - - Previous cache process was interrupted, restarting... - - Proses cache sebelumnya terhenti, dimulai ulang... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - Segarkan cache lokal - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - Checking for updates... - - - - - Close - Dekat - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - Execution of macro failed. See console for failure details. - Execution of macro failed. See console for failure details. - - - - - - - Maintainer - Pemelihara - - - - - - - Author - Penulis - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Memperbarui - - - - Updating... - Updating... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Pemeriksaan pembaruan sedang berlangsung - - - - Installation location - Lokasi pemasangan - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Disabled - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - PERINGATAN: Addon ini sudah usang - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - PERINGATAN: Addon ini sedang dipasang, namun dinonaktifkan. Gunakan tombol 'aktifkan' untuk mengaktifkan kembali. - - - - This Addon will be enabled next time you restart FreeCAD. - Addon ini akan diaktifkan saat Anda memulai ulang FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Addon ini akan dinonaktifkan saat Anda memulai ulang FreeCAD. - - - - - - Success - Berhasil - - - - Branch change succeeded, please restart to use the new version. - Perubahan cabang berhasil, silakan mulai ulang untuk menggunakan versi baru. - - - - Install - Pasang - - - - Uninstall - Copot pemasangan - - - - Enable - Memungkinkan - - - - Disable - Nonaktifkan - - - - - Check for update - Check for update - - - - Run - menjalankan - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Memeriksa sambungan - - - - Checking for connection to GitHub... - Memeriksa sambungan ke GitHub... - - - - Connection failed - Sambungan gagal - - - - Missing dependency - Dependensi Hilang - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Lainnya... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Otomatis - - - - - Workbench - Meja kerja - - - - Addon - Tambahan - - - - Python - Python - - - - Yes - Ya - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Paket Python - - - - - Other... - Lainnya... - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually: - - - - Too many to list - Terlalu banyak untuk dicantumkan - - - - - - - - - Missing Requirement - Persyaratan Kurang - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Tekan OK untuk tetap memasang. - - - - - Incompatible Python version - Versi Python tidak kompatibel - - - - This Addon (or one if its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one if its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - menjalankan - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Nama - - - - Class - Kelas - - - - Description - Description - - - - Subdirectory - Subdirectory - - - - Files - Berkas - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Versi Python Minimum Terdeteksi - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Pasang Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Pemasangan gagal - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Pilih file ikon untuk paket ini - - - - Filter is valid - Filternya valid - - - - Filter regular expression is invalid - Filter ekspresi reguler tidak valid - - - - Search... - Search... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Pemelihara: - - - - Tags - Tanda - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Mutakhir - - - - - - - - Update available - Pembaruan tersedia - - - - - Pending restart - Menunggu dimulai ulang - - - - - DISABLED - DINONAKTIFKAN - - - - Installed version - Versi terpasang - - - - Unknown version - Versi tidak diketahui - - - - Installed on - Installed on - - - - Available version - Versi tersedia - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Apa saja - - - - Macro - Makro - - - - Preference Pack - Paket Preferensi - - - - Installation Status - Installation Status - - - - Not installed - Tidak terpasang - - - - Filter - Menyaring - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded package.xml for {} - Downloaded package.xml for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Downloaded metadata.txt for {} - Downloaded metadata.txt for {} - - - - Downloaded requirements.txt for {} - Downloaded requirements.txt for {} - - - - Downloaded icon for {} - Downloaded icon for {} - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Git is disabled, skipping git macros - Git is disabled, skipping git macros - - - - Attempting to change non-git Macro setup to use git - - Attempting to change non-git Macro setup to use git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Unable to fetch git updates for workbench {} - Unable to fetch git updates for workbench {} - - - - git status failed for {} - git status failed for {} - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Caching macro code... - Caching macro code... - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Getting metadata from macro {} - Getting metadata from macro {} - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Retrieving macro description... - Mengambil deskripsi makro... - - - - Retrieving info from git - Mengambil info dari git - - - - Retrieving info from wiki - Mengambil info dari wiki - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - URL repositori - - - - Branch name - Preferences header for custom repositories - Nama cabang - - - - Basic git update failed with the following message: - Basic git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using git - Failed to clone {} into {} using git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Memasang - - - - Succeeded - Berhasil - - - - Failed - Gagal - - - - Update was cancelled - Pembaruan dibatalkan - - - - some addons may have been updated - beberapa addon mungkin telah diperbarui - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Pengelola Addon - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Gagal menghapus beberapa file - - - - Addons installer - - - Finished updating the following addons - Selesai memperbarui addon berikut - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Pengelola Addon - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_it.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_it.qm deleted file mode 100644 index 272fba510184f7e920b5b229a71def117e14a77d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71925 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 BKt})o diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_it.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_it.ts deleted file mode 100644 index 913a99a083..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_it.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Repository personalizzato - - - - Repository URL - URL del repository - - - - Branch - Ramo - - - - CompactView - - - - Icon - Icona - - - - - <b>Package Name</b> - <b>Nome pacchetto</b> - - - - - Version - Versione - - - - - Description - Descrizione - - - - Update Available - Aggiornamento Disponibile - - - - UpdateAvailable - AggiornamentoDisponibile - - - - DependencyDialog - - - Dependencies - Dipendenze - - - - Dependency type - Tipo di dipendenza - - - - Name - Nome - - - - Optional? - Facoltativo? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Risolvi Dipendenze - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Questo Addon ha le seguenti dipendenze richieste e opzionali. Devi installarle prima che questo Addon possa essere usato. - -Vuoi che Addon Manager le installi automaticamente? Scegli "Ignora" per installare Addon senza installare le dipendenze. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Moduli Python richiesti - - - - Optional Python modules - Moduli Python opzionali - - - - DeveloperModeDialog - - - Addon Developer Tools - Estensione strumenti per sviluppatori - - - - Path to Addon - Percorso per l'estensione - - - - - Browse... - Sfoglia... - - - - Metadata - Metadati - - - - Primary branch - Ramo primario - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Spiegazione di ciò che questo componente aggiuntivo fornisce. Visualizzato in Addon Manager. Non è necessario per questo dichiarare che questo è un FreeCAD Addon. - - - - Description - Descrizione - - - - Discussion URL - Url della discussione - - - - Icon - Icona - - - - Bugtracker URL - URL del Bugtracker - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Stili semantici (1.2.3-beta) o calVer (2022.08.30) supportati - - - - Set to today (CalVer style) - Impostato a oggi (Stile CalVer) - - - - - - - (Optional) - (opzionale) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Visualizzati nella lista di estensioni dell'Addon Manager. Non deve contenere la parola "FreeCAD" e deve essere un nome di cartella valido su tutti i sistemi operativi supportati. - - - - README URL - URL del README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - SUGGERIMENTO: Dal momento che questo è visualizzato all'interno di FreeCAD, nel gestore di Addon, non è necessario usare spazio per dire cose come "Questo è un FreeCAD Addon.." -- basta dire quello che fa. - - - - Repository URL - URL del repository - - - - Website URL - URL del sito - - - - Documentation URL - URL documentazione - - - - Addon Name - Nome dell'estensione - - - - Version - Versione - - - - (Recommended) - (consigliato) - - - - Minimum Python - Python minimo - - - - (Optional, only 3.x version supported) - (Opzionale, solo versione 3.x supportata) - - - - Detect... - Rileva... - - - - Addon Contents - Contenuti dell'estensione - - - - Dialog - - - Addon Manager - Addon manager - - - - Edit Tags - Modifica etichette - - - - Comma-separated list of tags describing this item: - Elenco di tag separato da virgole descrivono questo elemento: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: I tag comuni includono "Assembly", "FEM", "Mesh", "NURBS", ecc. - - - - Add-on Manager: Warning! - Add-on Manager: avvertimento! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Il gestore Add-on fornisce l'accesso a un'ampia libreria di utili estensioni FreeCAD di terze parti. Non è possibile dare alcuna garanzia riguardo la loro sicurezza o funzionalità. - - - - Continue - Continua - - - - Cancel - Annulla - - - - EditDependencyDialog - - - Edit Dependency - Modifica Dipendenza - - - - Dependency Type - Tipo Dipendenza - - - - Dependency - Dipendenza - - - - Package name, if "Other..." - Nome del pacchetto, se "Altro..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTA: Se "Altro..." è selezionato, il pacchetto non è in ALLOWED_PYTHON_PACKAGES.txt file, e non sarà installato automaticamente da Addon Manager. Invia un PR a <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> per richiedere l'aggiunta di un pacchetto. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Se questa è una dipendenza opzionale, Addon Manager offrirà d'installarla (quando possibile), ma non bloccherà l'installazione se l'utente sceglie di non installare, o non poter installare il pacchetto. - - - - Optional - Opzionale - - - - ExpandedView - - - - Icon - Icona - - - - - <h1>Package Name</h1> - <h1>Nome pacchetto</h1> - - - - - Version - Versione - - - - - (tags) - (etichette) - - - - - Description - Descrizione - - - - - Maintainer - Manutentore - - - - Update Available - Aggiornamento Disponibile - - - - labelSort - Ordinamento etichette - - - - UpdateAvailable - AggiornamentoDisponibile - - - - Form - - - Licenses - Licenze - - - - License - Licenza - - - - License file - File di Licenza - - - - People - Persone - - - - Kind - Tipo - - - - Name - Nome - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Mappatura Versione Avanzata - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Le prossime versioni dell'Addon Manager consentiranno agli sviluppatori di impostare un ramo o un tag specifico da usare con una versione specifica di FreeCAD (per esempio: impostare un tag specifico come l'ultima versione della tua estensione che supporta v0.19, ecc.) - - - - FreeCAD Version - Versione FreeCAD - - - - Best-available branch, tag, or commit - Ramo migliore disponibile, tag o commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versioni FreeCAD Supportate - - - - Minimum FreeCAD Version Supported - Versione Minima FreeCAD Supportata - - - - - Optional - Opzionale - - - - Maximum FreeCAD Version Supported - Massima Versione FreeCAD Supportata - - - - Advanced version mapping... - Mappatura versione avanzata... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opzioni di Addon manager - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Se questa opzione è selezionata, quando si avvia Addon Manager, gli addons installati -saranno controllati per gli aggiornamenti disponibili - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Scarica Macro metadati (circa 10MB) - - - - Cache update frequency - Frequenza aggiornamento cache - - - - Manual (no automatic updates) - Manuale (nessun aggiornamento automatico) - - - - Daily - Giornaliero - - - - Weekly - Settimanale - - - - Hide Addons without a license - Nascondi Addons senza licenza - - - - Hide Addons with non-FSF Free/Libre license - Nascondi Addons con licenza non-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Nascondi Addons con licenza non-OSI-approved - - - - Hide Addons marked Python 2 Only - Nascondi Addons contrassegnati con Solo Python 2 - - - - Hide Addons marked Obsolete - Nascondi gli Addons contrassegnati obsoleti - - - - Hide Addons that require a newer version of FreeCAD - Nascondi Addons che richiedono una nuova versione di FreeCAD - - - - Custom repositories - Repository personalizzati - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - Proxy di sistema utente - - - - User-defined proxy: - Proxy definito dall'utente: - - - - Score source URL - Punteggio sorgente URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - L'URL per i dati di Addon Score (vedi la pagina wiki di Addon Manager per la formattazione e i dettagli di hosting). - - - - Path to Git executable (optional): - Percorso dell'eseguibile Git (opzionale): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opzioni Avanzate - - - - Activate Addon Manager options intended for developers of new Addons. - Attiva le opzioni Addon Manager destinate agli sviluppatori di nuovi Addons. - - - - Addon developer mode - Modalità sviluppatore Addon - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Disinstalla una macro o un ambiente di lavoro selezionato - - - - Install - Installa - - - - Uninstall - Disinstalla - - - - Update - Aggiorna - - - - Run Macro - Esegui macro - - - - Change branch - Cambia ramo - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Gestisci Dipendenze Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - I seguenti pacchetti Python sono stati installati localmente da Addon Manager per soddisfare le dipendenze di Addon. Posizione di installazione: - - - - Package name - Nome pacchetto - - - - Installed version - Versione installata - - - - Available version - Versione disponibile - - - - Used by - Usato da - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Un asterisco (*) nella colonna "Usato da" indica una dipendenza facoltativa. Si noti che "Usato da" registra solo le importazioni dirette in Addon. Altri pacchetti Python su cui questi pacchetti dipendono potrebbero essere stati installati. - - - - Update all available - Aggiorna tutto disponibile - - - - SelectFromList - - - Dialog - Finestra di dialogo - - - - TextLabel - Etichetta Testo - - - - UpdateAllDialog - - - Updating Addons - Aggiornamento Addons - - - - Updating out-of-date addons... - Aggiornamento addon obsoleti... - - - - addContentDialog - - - Content Item - Elemento di contenuto - - - - Content type: - Tipo di contenuto: - - - - Macro - Macro - - - - Preference Pack - Pacchetto Preferenze - - - - Workbench - Ambiente - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Se questa è l'unica cosa nell'Estensione, tutti gli altri metadati possono essere ereditati dal livello superiore, e non hanno bisogno di essere specificati qui. - - - - This is the only item in the Addon - Questo è l'unico elemento nel componente aggiuntivo - - - - Main macro file - File macro principale - - - - The file with the macro's metadata in it - Il file con i metadati macro's in esso - - - - - - Browse... - Sfoglia... - - - - Preference Pack Name - Nome Pacchetto Preferenze - - - - Workbench class name - Nome classe Ambiente di lavoro - - - - Class that defines "Icon" data member - Classe che definisce "Icona" membro dei dati - - - - Subdirectory - Sottocartella - - - - Optional, defaults to name of content item - Opzionale, predefinito per il nome dell'elemento di contenuto - - - - Icon - Icona - - - - Optional, defaults to inheriting from top-level Addon - Opzionale, predefinito per ereditare da Addon di alto livello - - - - Tags... - Etichette... - - - - Dependencies... - Dipendenze... - - - - FreeCAD Versions... - Versioni FreeCAD... - - - - Other Metadata - Altri metadati - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Visualizzati nella lista Addon Manager' di Addons. Non dovrebbe includere la parola "FreeCAD". - - - - Version - Versione - - - - Description - Descrizione - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Stili semantici (1.2.3-beta) o calVer (2022.08.30) supportati - - - - Set to today (CalVer style) - Impostato a oggi (Stile CalVer) - - - - Display Name - Nome Visualizzato - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Tutti i campi lasciati in bianco sono ereditati dai metadati di Addon di alto livello, quindi tecnicamente sono tutti facoltativi. Per Addons con contenuti multipli, ogni elemento dovrebbe fornire un nome di visualizzazione e una descrizione unica. - - - - add_toolbar_button_dialog - - - Add button? - Aggiungere pulsante? - - - - Add a toolbar button for this macro? - Aggiungere un pulsante della barra degli strumenti per questa macro? - - - - Yes - Sì - - - - No - No - - - - Never - Mai - - - - change_branch - - - Change Branch - Cambia Ramo - - - - Change to branch: - Cambia ramo: - - - - copyrightInformationDialog - - - Copyright Information - Informazioni sul copyright - - - - Copyright holder: - Titolare del copyright: - - - - Copyright year: - Anno del copyright: - - - - personDialog - - - Add Person - Aggiungi persona - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Un responsabile è qualcuno con accesso al commit corrente su questo progetto. Un autore è chiunque altro a cui tu'vorresti dare credito. - - - - Name: - Nome: - - - - Email: - Posta elettronica: - - - - Email is required for maintainers, and optional for authors. - L'email è richiesta per i manutentori e facoltativa per gli autori. - - - - proxy_authentication - - - Proxy login required - Accesso Proxy richiesto - - - - Proxy requires authentication - Il Proxy richiede l'autenticazione - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Segnaposto per l'indirizzo proxy - - - - Realm: - Dominio: - - - - Placeholder for proxy realm - Segnaposto per il proxy realm - - - - Username - Nome Utente - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Seleziona una licenza - - - - About... - Informazioni... - - - - License name: - Nome licenza: - - - - Path to license file: - Percorso del file di licenza: - - - - (if required by license) - (se richiesto dalla licenza) - - - - Browse... - Sfoglia... - - - - Create... - Crea... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Seleziona Barra Strumenti - - - - Select a toolbar to add this macro to: - Selezionare una barra degli strumenti per aggiungere questa macro a: - - - - Ask every time - Chiedi ogni volta - - - - toolbar_button - - - - Add button? - Aggiungere pulsante? - - - - Add a toolbar button for this macro? - Aggiungere un pulsante della barra degli strumenti per questa macro? - - - - Yes - Sì - - - - No - No - - - - Never - Mai - - - - AddonsInstaller - - - Starting up... - Avvio in corso... - - - - Worker process {} is taking a long time to stop... - Il processo in corso {} sta impiegando molto tempo per fermarsi... - - - - Previous cache process was interrupted, restarting... - - Il processo di cache precedente è stato interrotto, riavvio... - - - - - Custom repo list changed, forcing recache... - - L'elenco dei repository personalizzati è stato modificato, si forza la recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - È necessario riavviare FreeCAD perché le modifiche abbiano effetto. - - - - Restart now - Riavvia ora - - - - Restart later - Riavvia dopo - - - - - Refresh local cache - Aggiorna cache locale - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Aggiornamento cache... - - - - - Checking for updates... - Controllo aggiornamenti... - - - - Temporary installation of macro failed. - Installazione temporanea della macro non riuscita. - - - - - Close - Chiudi - - - - Update all addons - Aggiorna tutti gli addons - - - - Check for updates - Controlla aggiornamenti - - - - Python dependencies... - Dipendenze Python... - - - - Developer tools... - Strumenti per sviluppatori... - - - - Apply %n available update(s) - Applica %n aggiornamenti disponibili - - - - No updates available - Nessun aggiornamento disponibile - - - - - - Cannot launch a new installer until the previous one has finished. - Impossibile avviare una nuova installazione fino al termine della precedente. - - - - - - - Maintainer - Manutentore - - - - - - - Author - Autore - - - - New Python Version Detected - Rilevata Nuova Versione Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Sembra che sia la prima volta che questa versione di Python è stata usata con Addon Manager. Vuoi installare le dipendenze che erano state installate automaticamente? - - - - Processing, please wait... - Elaborazione in corso, attendere prego... - - - - - Update - Aggiorna - - - - Updating... - In aggiornamento... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Impossibile importare QtNetwork -- non sembra essere installato sul sistema. Il tuo provider può avere un pacchetto per questa dipendenza (spesso chiamata "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Impossibile convertire la porta proxy specificata '{}' in un numero di porta - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Errore nel parametro: le opzioni proxy impostate sono reciprocamente esclusive. Ripristinato valore predefinito. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Errore di parametro: proxy utente indicato, ma nessun proxy fornito. Ripristino a default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Risposta {} inattesa dal server - - - - Error with encrypted connection - Errore con connessione cifrata - - - - - - Confirm remove - Conferma rimozione - - - - Are you sure you want to uninstall {}? - Sei sicuro di voler disinstallare {}? - - - - - - Removing Addon - Rimozione Addon - - - - Removing {} - Rimozione {} - - - - - Uninstall complete - Disinstallazione completata - - - - - Uninstall failed - Disinstallazione fallita - - - - Version {version} installed on {date} - Versione {version} installata in {date} - - - - Version {version} installed - Versione {version} installata - - - - Installed on {date} - Installato il {date} - - - - - - - Installed - Installato - - - - Currently on branch {}, name changed to {} - Attualmente sul ramo {}, nome cambiato in {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' check out, nessun aggiornamento possibile - - - - Update check in progress - Controllo aggiornamento in corso - - - - Installation location - Percorso di installazione - - - - Repository URL - URL del repository - - - - Changed to branch '{}' -- please restart to use Addon. - Cambiato in ramo '{}' -- si prega di riavviare per utilizzare Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Questo Addon è stato aggiornato. Riavviare FreeCAD per vedere le modifiche. - - - - Disabled - Disabilitato - - - - Currently on branch {}, update available to version {} - Attualmente sul ramo {}, aggiornamento disponibile alla versione {} - - - - Update available to version {} - Aggiornamento disponibile alla versione {} - - - - This is the latest version available - Questa è l'ultima versione disponibile - - - - WARNING: This addon is obsolete - ATTENZIONE: Questo addon è obsoleto - - - - WARNING: This addon is Python 2 only - ATTENZIONE: Questo addon è solo Python 2 - - - - WARNING: This addon requires FreeCAD {} - ATTENZIONE: Questo addon richiede FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ATTENZIONE: Questo addon è attualmente installato, ma disabilitato. Usa il pulsante 'abilita' per riabilitare. - - - - This Addon will be enabled next time you restart FreeCAD. - Questa estensione sarà abilitata al prossimo riavvio di FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Questa estensione sarà disabilitata al prossimo riavvio di FreeCAD. - - - - - - Success - Operazione riuscita - - - - Install - Installa - - - - Uninstall - Disinstalla - - - - Enable - Abilita - - - - Disable - Disabilita - - - - - Check for update - Verifica aggiornamenti - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Esegui - - - - Change branch... - Cambia ramo... - - - - Return to package list - Ritorna alla lista dei pacchetti - - - - Checking connection - Controllo connessione - - - - Checking for connection to GitHub... - Controllo della connessione a GitHub... - - - - Connection failed - Connessione fallita - - - - Missing dependency - Dipendenza mancante - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Impossibile importare QtNetwork -- vedere Report View per i dettagli. Addon Manager non disponibile. - - - - Other... - For providing a license other than one listed - Altro... - - - - Select the corresponding license file in your Addon - Seleziona il file di licenza corrispondente nel tuo Addon - - - - Location for new license file - Posizione per il nuovo file di licenza - - - - Received {} response code from server - Ricevuto {} codice di risposta dal server - - - - Failed to install macro {} - Impossibile installare la macro {} - - - - Failed to create installation manifest file: - - Creazione del file manifest di installazione non riuscita: - - - - - Unrecognized content kind '{}' - Tipo di contenuto non riconosciuto '{}' - - - - Unable to locate icon at {} - Impossibile individuare l'icona a {} - - - - Select an icon file for this content item - Seleziona un file icona per questo elemento di contenuto - - - - - - {} is not a subdirectory of {} - {} non è una sottodirectory di {} - - - - Select the subdirectory for this content item - Seleziona la sottocartella per questo elemento di contenuto - - - - Automatic - Automatica - - - - - Workbench - Ambiente - - - - Addon - Componente aggiuntivo - - - - Python - Python - - - - Yes - Sì - - - - Internal Workbench - Ambiente Interno - - - - External Addon - Addon Esterno - - - - Python Package - Python Package - - - - - Other... - Altro... - - - - Too many to list - Troppi da elencare - - - - - - - - - Missing Requirement - Requisito Mancante - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' richiede '{}', che non è disponibile nella tua copia di FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' richiede i seguenti ambienti di lavoro, che non sono disponibili nella tua copia di FreeCAD: - - - - Press OK to install anyway. - Premere OK per installare comunque. - - - - - Incompatible Python version - Versione Python incompatibile - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Questo addon richiede pacchetti Python che non sono installati e non possono essere installati automaticamente. Per utilizzare questo addon è necessario installare manualmente i seguenti pacchetti Python: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Questo Addon (o una delle sue dipendenze) richiede Python {}.{}, e sul tuo sistema è in esecuzione {}.{}. Installazione annullata. - - - - Optional dependency on {} ignored because it is not in the allow-list - Dipendenza opzionale da {} ignorata perché non è nella lista permessi - - - - - Installing dependencies - Installazione delle dipendenze - - - - - Cannot execute Python - Impossibile eseguire Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Impossibile localizzare automaticamente l'eseguibile Python, o il percorso è impostato in modo errato. Controlla l'impostazione delle preferenze di Addon Manager per il percorso di Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Le dipendenze non possono essere installate. Continuare con l'installazione di {} comunque? - - - - - Cannot execute pip - Impossibile eseguire pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Esecuzione di pip non riuscita, che potrebbe mancare dall'installazione di Python. Assicurarsi che il sistema abbia pip installato e riprovare. Il comando fallito era: - - - - - Continue with installation of {} anyway? - Continuare con l'installazione di {} comunque? - - - - - Package installation failed - Installazione del pacchetto fallita - - - - See Report View for detailed failure log. - Vedere Report View per il registro di errore dettagliato. - - - - Installing Addon - Installazione Addon - - - - Installing FreeCAD Addon '{}' - Installazione Addon di FreeCAD '{}' - - - - Cancelling - Annullamento - - - - Cancelling installation of '{}' - Annullamento dell’installazione di '{}' - - - - {} was installed successfully - {} installato con successo - - - - - Installation Failed - Installazione Fallita - - - - Failed to install {} - Impossibile installare {} - - - - - Create new toolbar - Crea nuova barra degli strumenti - - - - - A macro installed with the FreeCAD Addon Manager - Una macro installata con FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Esegui - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Impossibile leggere i dati da GitHub: controllare la connessione internet e le impostazioni proxy e riprovare. - - - - XML failure while reading metadata from file {} - Errore XML durante la lettura dei metadati dal file {} - - - - Invalid metadata in file {} - Metadati non validi nel file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ATTENZIONE: il percorso specificato nei metadati package.xml non corrisponde al ramo attualmente selezionato. - - - - Name - Nome - - - - Class - Classe - - - - Description - Descrizione - - - - Subdirectory - Sottocartella - - - - Files - File - - - - Select the folder containing your Addon - Seleziona la cartella contenente il tuo Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Vermin assente, annullamento operazione. - - - - Scanning Addon for Python version compatibility - Scansione di Addon per la compatibilità della versione Python - - - - Minimum Python Version Detected - Rilevata Versione Minima Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin ha auto-rilevato una versione necessaria di Python 3.{} - - - - Install Vermin? - Installare Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Il rilevamento automatico della versione richiesta di Python per questo Addon richiede Vermin (https://pypi.org/project/vermin/). OK per installare? - - - - Attempting to install Vermin from PyPi - Tentativo di installare Vermin da PyPi - - - - - Installation failed - Installazione non riuscita - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Impossibile installare Vermin -- controlla Report View per i dettagli. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Impossibile importare Vermin dopo l'installazione -- impossibile scansionare Addon. - - - - Select an icon file for this package - Seleziona un file icona per questo pacchetto - - - - Filter is valid - Filtro valido - - - - Filter regular expression is invalid - L'espressione regolare del filtro non è valida - - - - Search... - Cerca... - - - - Click for details about package {} - Clicca per i dettagli sul pacchetto {} - - - - Click for details about workbench {} - Clicca per i dettagli sull'ambiente di lavoro {} - - - - Click for details about macro {} - Clicca per i dettagli sulla macro {} - - - - Maintainers: - Manutentori: - - - - Tags - Etichette - - - - {} ★ on GitHub - {} ★ su GitHub - - - - No ★, or not on GitHub - Nessuna ★, o non presente in GitHub - - - - Created - Creato - - - - Updated - Aggiornato - - - - Score: - Punteggio: - - - - - Up-to-date - Aggiornato - - - - - - - - Update available - Aggiornamento disponibile - - - - - Pending restart - Riavvio in sospeso - - - - - DISABLED - DISABILITATO - - - - Installed version - Versione installata - - - - Unknown version - Versione sconosciuta - - - - Installed on - Installato il - - - - Available version - Versione disponibile - - - - Filter by... - Filtra per... - - - - Addon Type - Tipo di Addon - - - - - Any - Qualsiasi - - - - Macro - Macro - - - - Preference Pack - Pacchetto Preferenze - - - - Installation Status - Stato Dell'Installazione - - - - Not installed - Non installato - - - - Filter - Filtro - - - - DANGER: Developer feature - PERICOLO: Funzione sviluppatore - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - PERICOLO: La commutazione dei rami è destinata a sviluppatori e beta tester, e può causare documenti corrotti, non compatibili all'indietro, instabilità, crash e/o morte termica prematura dell'universo. Sei sicuro di voler continuare? - - - - There are local changes - Ci sono cambiamenti locali - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ATTENZIONE: Questo repository ha modifiche locali non effettuate. Sei sicuro di voler cambiare i rami (apportando le modifiche con te)? - - - - Local - Table header for local git ref name - Locale - - - - Remote tracking - Table header for git remote tracking branch name - Monitoraggio remoto - - - - Last Updated - Table header for git update date - Ultimo aggiornamento - - - - Installation of Python package {} failed - Installazione del pacchetto Python {} fallita - - - - Installation of optional package failed - Installazione del pacchetto opzionale fallita - - - - Installing required dependency {} - Installazione della dipendenza richiesta {} - - - - Installation of Addon {} failed - Installazione dell'Addon {} fallita - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Impossibile decodificare il file {} per Addon '{}' - - - - Any dependency information in this file will be ignored - Qualsiasi informazione sulla dipendenza in questo file verrà ignorata - - - - Unable to open macro wiki page at {} - Impossibile aprire la pagina wiki della macro su {} - - - - Unable to fetch the code of this macro. - Impossibile recuperare il codice di questa macro. - - - - Unable to retrieve a description from the wiki for macro {} - Impossibile recuperare una descrizione dalla wiki per macro {} - - - - Unable to open macro code URL {} - Impossibile aprire l'URL del codice macro {} - - - - Unable to fetch macro-specified file {} from {} - Impossibile recuperare il file macro specificato {} da {} - - - - Could not locate macro-specified file {} (expected at {}) - Impossibile individuare il file specificato dalla macro {} (dovrebbe trovarsi a {}) - - - - {}: Unrecognized internal workbench '{}' - {}: ambiente di lavoro interno non riconosciuto '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Avviso Sviluppatore Addon: l'URL del repository impostato nel file package.xml per il componente aggiuntivo {} ({}) non corrisponde all'URL da cui è stato recuperato ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Avviso Sviluppatore Addon: il ramo del Repository impostato nel file pacchetto.xml per il componente aggiuntivo {} ({}) non corrisponde al ramo da cui è stato recuperato ({}) - - - - - Got an error when trying to import {} - Errore durante l'importazione di {} - - - - An unknown error occurred - Si è verificato un errore sconosciuto - - - - Could not find addon {} to remove it. - Impossibile trovare l'addon {} per rimuoverlo. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Esecuzione dello script di Addon's uninstall.py non riuscita. Si proseguire con la disinstallazione... - - - - Removed extra installed file {} - File extra installato rimosso {} - - - - Error while trying to remove extra installed file {} - Errore durante il tentativo di rimuovere il file extra installato {} - - - - Error while trying to remove macro file {}: - Errore durante il tentativo di rimuovere il file macro {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Impossibile connettersi a GitHub. Controlla le impostazioni di connessione e proxy. - - - - WARNING: Duplicate addon {} ignored - ATTENZIONE: Addon duplicato {} ignorato - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Si è verificato un errore durante l'aggiornamento delle macro da GitHub, ritentando il check out... - - - - Attempting to do a clean checkout... - Tentativo di fare un check out pulito... - - - - Clean checkout succeeded - Checkout pulito riuscito - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Impossibile aggiornare le macro da GitHub -- prova a cancellare la cache di Addon Manager. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Errore nel connettersi al Wiki, FreeCAD non può recuperare l'elenco macro Wiki in questo momento - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Lettura dei metadati da {name} non riuscita - - - - Failed to fetch code for macro '{name}' - Recupero del codice per macro '{name}' non riuscito - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: un processo in corso non è riuscito a completarsi durante il recupero di {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Su {num_macros} macro, {num_failed} si sono bloccate durante l'elaborazione - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: un processo in corso impedisce di arrestare ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout durante il recupero dei metadati per la macro {} - - - - Failed to kill process for macro {}! - - Impossibile terminare il processo per la macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Impossibile ottenere le statistiche di Addon da {} -- solo l'ordinamento alfabetico sarà accurato - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Impossibile ottenere il punteggio Addon da '{}' -- l'ordinamento per punteggio fallirà - - - - - Repository URL - Preferences header for custom repositories - URL del repository - - - - Branch name - Preferences header for custom repositories - Nome branch - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backup della directory originale e ri-clonazione - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Impossibile rinominare il ramo Git con il seguente messaggio: - - - - Installing - Installazione - - - - Succeeded - Riuscito - - - - Failed - Fallito - - - - Update was cancelled - Aggiornamento annullato - - - - some addons may have been updated - alcuni addons potrebbero essere stati aggiornati - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Caricamento informazioni per {} dal wiki Racolta Macro FreeCAD... - - - - Loading page for {} from {}... - Caricamento pagina per {} da {}... - - - - Failed to download data from {} -- received response code {}. - Impossibile scaricare i dati da {} -- ricevuto il codice di risposta {}. - - - - Composite view - Vista composita - - - - Expanded view - Vista espansa - - - - Compact view - Vista compatta - - - - Alphabetical - Sort order - Alfabetico - - - - Last Updated - Sort order - Ultimo aggiornamento - - - - Date Created - Sort order - Data creazione - - - - GitHub Stars - Sort order - Stelline su GitHub - - - - Score - Sort order - Punteggio - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Gestisci ambienti di lavoro, macro e pacchetti di preferenze esterni - - - - AddonInstaller - - - Finished removing {} - Terminata la rimozione {} - - - - Failed to remove some files - Rimozione di alcuni file non riuscita - - - - Addons installer - - - Finished updating the following addons - Terminato l'aggiornamento dei seguenti addons - - - - Workbench - - - Auto-Created Macro Toolbar - Barra Macro Auto-Creata - - - - QObject - - - Addon Manager - Addon manager - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ja.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ja.qm deleted file mode 100644 index 79cbf17d286d6c81dc549832a3f3038678503d6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54812 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ja.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_ja.ts deleted file mode 100644 index fe18fe9ca7..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_ja.ts +++ /dev/null @@ -1,2483 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - カスタムリãƒã‚¸ãƒˆãƒª - - - - Repository URL - リãƒã‚¸ãƒˆãƒªã®URL - - - - Branch - ブランム- - - - CompactView - - - - Icon - アイコン - - - - - <b>Package Name</b> - <b>パッケージå</b> - - - - - Version - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - - Description - 説明 - - - - Update Available - æ›´æ–°ãŒã‚りã¾ã™ - - - - UpdateAvailable - æ›´æ–°ãŒåˆ©ç”¨å¯èƒ½ - - - - DependencyDialog - - - Dependencies - ä¾å­˜é–¢ä¿‚ - - - - Dependency type - ä¾å­˜é–¢ä¿‚ã®ç¨®é¡ž - - - - Name - åå‰ - - - - Optional? - オプション? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - ä¾å­˜é–¢ä¿‚を解決 - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - ã“ã®ã‚¢ãƒ‰ã‚ªãƒ³ã«ã¯ä»¥ä¸‹ã®å¿…é ˆä¾å­˜é–¢ä¿‚ã€ã‚ªãƒ—ションä¾å­˜é–¢ä¿‚ãŒã‚りã¾ã™ã€‚ã“ã®ã‚¢ãƒ‰ã‚ªãƒ³ã‚’使用ã§ãるよã†ã«ã™ã‚‹ã«ã¯ã“れらをインストールã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ - -アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«è‡ªå‹•çš„ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã‹ï¼Ÿã€€ä¾å­˜é–¢ä¿‚をインストールã›ãšã«ã‚¢ãƒ‰ã‚ªãƒ³ã‚’インストールã™ã‚‹ã«ã¯"無視" ã‚’é¸æŠžã—ã¦ãã ã•ã„。 - - - - FreeCAD Addons - FreeCADアドオン - - - - Required Python modules - å¿…é ˆã®Pythonモジュール - - - - Optional Python modules - オプションã®Pythonモジュール - - - - DeveloperModeDialog - - - Addon Developer Tools - 拡張機能ã®é–‹ç™ºè€…ツール - - - - Path to Addon - 拡張機能ã®ãƒ‘ス - - - - - Browse... - å‚ç…§... - - - - Metadata - メタデータ - - - - Primary branch - プライマリブランム- - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - ã“ã®ã‚¢ãƒ‰ã‚ªãƒ³ãŒæä¾›ã™ã‚‹ã‚‚ã®ã®èª¬æ˜Žã§ã™ã€‚アドオンマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«è¡¨ç¤ºã•れã¾ã™ã€‚FreeCADアドオン ã§ã‚ã‚‹ã“ã¨ã‚’示ã™å¿…è¦ã‚りã¾ã›ã‚“。 - - - - Description - 説明 - - - - Discussion URL - 議論用ã®URL - - - - Icon - アイコン - - - - Bugtracker URL - ãƒã‚°ç®¡ç†ã‚·ã‚¹ãƒ†ãƒ ã®URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - セマンティック(1.2.3-beta)ã‹ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ï¼ˆ2022.08.30)ãƒãƒ¼ã‚¸ãƒ§ãƒ‹ãƒ³ã‚°ã§å…¥åŠ› - - - - Set to today (CalVer style) - ä»Šæ—¥ã®æ—¥ä»˜ã‚’挿入 - - - - - - - (Optional) - (オプション) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®ã‚¢ãƒ‰ã‚ªãƒ³ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã™ã€‚「FreeCADã€ã¨ã„ã†å˜èªžã‚’å«ã¾ãªã„ã€ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã§åˆ©ç”¨å¯èƒ½ãªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。 - - - - README URL - READMEã®URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: ã“れã¯FreeCAD内ã®ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«è¡¨ç¤ºã•れるã®ã§ã€"ã“れã¯FreeCADã®ã‚¢ãƒ‰ã‚ªãƒ³ã§ã™..." ã¨ã„ã£ãŸã“ã¨ã‚’説明ã™ã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“。å˜ã«ã“れãŒä½•ã‹ã‚’説明ã—ã¦ãã ã•ã„。 - - - - Repository URL - リãƒã‚¸ãƒˆãƒªã®URL - - - - Website URL - Webサイトã®URL - - - - Documentation URL - ドキュメントã®URL - - - - Addon Name - 拡張機能ã®åå‰ - - - - Version - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - (Recommended) - (入力を推奨) - - - - Minimum Python - Pythonã®æœ€ä½Žè¦ä»¶ - - - - (Optional, only 3.x version supported) - (オプション。3.x ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã¿ã‚µãƒãƒ¼ãƒˆï¼‰ - - - - Detect... - 検出... - - - - Addon Contents - 拡張機能ã®å†…容 - - - - Dialog - - - Addon Manager - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ - - - - Edit Tags - タグを編集 - - - - Comma-separated list of tags describing this item: - カンマã§åŒºåˆ‡ã‚‰ã‚ŒãŸã€ã“ã®é …目を説明ã™ã‚‹ã‚¿ã‚°ã®ãƒªã‚¹ãƒˆ: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - ヒント:一般的ãªã‚¿ã‚°ã«ã¯ "Assembly"ã€"FEM"ã€"Mesh"ã€"NURBS"ç­‰ãŒã‚りã¾ã™ã€‚ - - - - Add-on Manager: Warning! - アドオンマãƒãƒ¼ã‚¸ãƒ£ãƒ¼: è­¦å‘Šï¼ - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - アドオンマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã¯ã€ä¾¿åˆ©ãªã‚µãƒ¼ãƒ‰ãƒ‘ーティー製 FreeCAD 拡張機能ã®è±Šå¯Œãªãƒ©ã‚¤ãƒ–ラリーã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’æä¾›ã—ã¾ã™ã€‚ã“ã‚Œã‚‰ã®æ©Ÿèƒ½ã®å®‰å…¨æ€§ã€æ©Ÿèƒ½æ€§ã«é–¢ã—ã¦ã¯ä½•らä¿è¨¼ã—ã¾ã›ã‚“。 - - - - Continue - 続行 - - - - Cancel - キャンセル - - - - EditDependencyDialog - - - Edit Dependency - ä¾å­˜é–¢ä¿‚を編集 - - - - Dependency Type - ä¾å­˜é–¢ä¿‚ã®ç¨®é¡ž - - - - Dependency - ä¾å­˜é–¢ä¿‚ - - - - Package name, if "Other..." - パッケージåãŒã€Œãã®ä»–...ã€ã®å ´åˆ - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - 注æ„: 「ãã®ä»–...ã€ã‚’é¸æŠžã™ã‚‹ã¨ã€ãƒ‘ッケージ㯠ALLOWED_PYTHON_PACKAGES.txt ファイルã«è¨˜è¼‰ã•れãšã€ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã¯è‡ªå‹•インストールを行ãªã„ã¾ã›ã‚“。パッケージを追加ã—ãŸã„å ´åˆã¯ <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> 㸠PR を投稿ã—ã¦ãã ã•ã„。 - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - ã“れãŒã‚ªãƒ—ションã®ä¾å­˜é–¢ä¿‚ã§ã‚ã‚‹å ´åˆã€ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã¯ (å¯èƒ½ã§ã‚れã°) ãã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’æä¾›ã—ã¾ã™ãŒã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ‘ッケージをインストールã—ãªã„ã€ã¾ãŸã¯ã§ããªã„å ´åˆã§ã‚‚ã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ブロックã¯ã—ã¾ã›ã‚“。 - - - - Optional - オプション - - - - ExpandedView - - - - Icon - アイコン - - - - - <h1>Package Name</h1> - <h1>パッケージå</h1> - - - - - Version - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - - (tags) - (タグ) - - - - - Description - 説明 - - - - - Maintainer - ä¿å®ˆæ‹…当者 - - - - Update Available - æ›´æ–°ãŒã‚りã¾ã™ - - - - labelSort - ラベルソート - - - - UpdateAvailable - æ›´æ–°ãŒåˆ©ç”¨å¯èƒ½ - - - - Form - - - Licenses - ライセンス - - - - License - ライセンス - - - - License file - ライセンスファイル - - - - People - 貢献者 - - - - Kind - 役割 - - - - Name - åå‰ - - - - Email - Eメール - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - 高度ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒžãƒƒãƒ”ング - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - FreeCADアドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®ä»Šå¾Œã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã€ç‰¹å®šã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®FreeCADã§ä½¿ç”¨ã™ã‚‹ãŸã‚ã®ç‰¹å®šã®ãƒ–ランãƒã‚„タグを開発者ãŒè¨­å®šã™ã‚‹æ©Ÿèƒ½ãŒã‚µãƒãƒ¼ãƒˆã•れã¾ã™ (例ãˆã° v0.19 をサãƒãƒ¼ãƒˆã™ã‚‹è‡ªä½œã‚¢ãƒ‰ã‚ªãƒ³ã®æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨ã—ã¦ç‰¹å®šã®ã‚¿ã‚°ã‚’設定ã™ã‚‹ãªã©) - - - - FreeCAD Version - FreeCADã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Best-available branch, tag, or commit - 最良ã®ãƒ–ランãƒã€ã‚¿ã‚°ã€ã¾ãŸã¯ã‚³ãƒŸãƒƒãƒˆ - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - サãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹FreeCADã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Minimum FreeCAD Version Supported - サãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹FreeCADã®æœ€å°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - - Optional - オプション - - - - Maximum FreeCAD Version Supported - サãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹FreeCADã®æœ€å¤§ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Advanced version mapping... - 高度ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒžãƒƒãƒ”ング... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®ã‚ªãƒ—ション - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - ã“ã®ã‚ªãƒ—ションãŒé¸æŠžã•れã¦ã„ã‚‹å ´åˆã€ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®èµ·å‹•時ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ¸ˆã¿ã‚¢ãƒ‰ã‚ªãƒ³ã®åˆ©ç”¨å¯èƒ½ãªæ›´æ–°ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¾ã™ã€‚ - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - マクロã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ï¼ˆç´„10MB)をダウンロード - - - - Cache update frequency - ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã®æ›´æ–°é »åº¦ - - - - Manual (no automatic updates) - æ‰‹å‹•ï¼ˆè‡ªå‹•ã§æ›´æ–°ã—ã¾ã›ã‚“) - - - - Daily - 毎日 - - - - Weekly - 毎週 - - - - Hide Addons without a license - ライセンスã®ç„¡ã„拡張機能をéžè¡¨ç¤º - - - - Hide Addons with non-FSF Free/Libre license - éžFSF Free/Libre ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’éžè¡¨ç¤º - - - - Hide Addons with non-OSI-approved license - OSIéžæ‰¿èªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’éžè¡¨ç¤º - - - - Hide Addons marked Python 2 Only - Python 2å°‚ç”¨ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’éžè¡¨ç¤º - - - - Hide Addons marked Obsolete - 廃止ã•ã‚ŒãŸæ‹¡å¼µæ©Ÿèƒ½ã‚’éžè¡¨ç¤º - - - - Hide Addons that require a newer version of FreeCAD - æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®FreeCADãŒå¿…è¦ãªæ‹¡å¼µæ©Ÿèƒ½ã‚’éžè¡¨ç¤º - - - - Custom repositories - カスタムリãƒã‚¸ãƒˆãƒª - - - - Proxy - プロキシ - - - - No proxy - プロキシを使用ã—ãªã„ - - - - User system proxy - ユーザーシステムプロキシ - - - - User-defined proxy: - 手動ã§ãƒ—ロキシを設定ã™ã‚‹ - - - - Score source URL - スコア元ã®URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - アドオンスコアデータ㮠URL (フォーマットã¨ãƒ›ã‚¹ãƒ†ã‚£ãƒ³ã‚°ã®è©³ç´°ã«ã¤ã„ã¦ã¯ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®Wikiページをå‚ç…§) - - - - Path to Git executable (optional): - Gitã®å®Ÿè¡Œãƒ•ァイルã®ãƒ‘ス(オプション) - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - 詳細設定 - - - - Activate Addon Manager options intended for developers of new Addons. - æ–°ã—ã„アドオン開発者å‘ã‘ã®ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãƒ»ã‚ªãƒ—ションを有効ã«ã—ã¾ã™ã€‚ - - - - Addon developer mode - 拡張機能開発者モード - - - - PackageDetails - - - Uninstalls a selected macro or workbench - é¸æŠžã—ãŸãƒžã‚¯ãƒ­ã€ãƒ¯ãƒ¼ã‚¯ãƒ™ãƒ³ãƒã‚’アンインストール - - - - Install - インストール - - - - Uninstall - アンインストール - - - - Update - æ›´æ–° - - - - Run Macro - マクロを実行 - - - - Change branch - ブランãƒã®å¤‰æ›´ - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Pythonã®ä¾å­˜é–¢ä¿‚ã®ç®¡ç† - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - 以下㮠Python パッケージã¯ã‚¢ãƒ‰ã‚ªãƒ³ã®ä¾å­˜é–¢ä¿‚を満ãŸã™ã‚ˆã†ã«ã‚¢ãƒ‰ã‚ªãƒ³ãƒ»ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚ˆã£ã¦ãƒ­ãƒ¼ã‚«ãƒ«ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã¾ã™ã€‚インストール場所: - - - - Package name - パッケージå - - - - Installed version - インストール済ã¿ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Available version - 利用å¯èƒ½ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Used by - 使用先 - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - 「使用先ã€ã®ã‚¢ã‚¹ã‚¿ãƒªã‚¹ã‚¯ï¼ˆ*)ã¯ã‚ªãƒ—ションã®ä¾å­˜é–¢ä¿‚を示ã—ã¾ã™ã€‚「使用先ã€ã«ã¯æ‹¡å¼µæ©Ÿèƒ½ã§ç›´æŽ¥ã‚¤ãƒ³ãƒãƒ¼ãƒˆã•れãŸã‚‚ã®ã®ã¿è¨˜éŒ²ã•れるã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。ä¾å­˜ã—ã¦ã„ã‚‹ä»–ã®Pythonパッケージもインストールã•れã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚ - - - - Update all available - å…¨ã¦ã‚’æ›´æ–° - - - - SelectFromList - - - Dialog - ダイアログ - - - - TextLabel - テキストラベル - - - - UpdateAllDialog - - - Updating Addons - 拡張機能を更新 - - - - Updating out-of-date addons... - 廃止ã•ã‚ŒãŸæ‹¡å¼µæ©Ÿèƒ½ã‚’æ›´æ–°... - - - - addContentDialog - - - Content Item - コンテンツアイテム - - - - Content type: - コンテンツã®ç¨®é¡ž - - - - Macro - マクロ - - - - Preference Pack - 環境設定パック - - - - Workbench - ワークベンム- - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - ã“ã‚ŒãŒæ‹¡å¼µæ©Ÿèƒ½å†…ã§å”¯ä¸€ã®ã‚‚ã®ã§ã‚ã‚‹å ´åˆã€ä»–ã®ã™ã¹ã¦ã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã¯ãƒˆãƒƒãƒ—レベルã‹ã‚‰ç¶™æ‰¿ã§ãã€ã“ã“ã§æŒ‡å®šã™ã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“。 - - - - This is the only item in the Addon - ã“ã‚Œã¯æ‹¡å¼µæ©Ÿèƒ½ã®ä¸­ã®å”¯ä¸€ã®ã‚¢ã‚¤ãƒ†ãƒ ã§ã™ - - - - Main macro file - メインã®ãƒžã‚¯ãƒ­ãƒ•ァイル - - - - The file with the macro's metadata in it - マクロã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‚’å«ã‚€ãƒ•ァイル - - - - - - Browse... - å‚ç…§... - - - - Preference Pack Name - 環境設定パックå - - - - Workbench class name - ワークベンãƒã®ã‚¯ãƒ©ã‚¹å - - - - Class that defines "Icon" data member - "Icon" データメンãƒã‚’定義ã™ã‚‹ã‚¯ãƒ©ã‚¹ - - - - Subdirectory - サブディレクトリ - - - - Optional, defaults to name of content item - çœç•¥å¯èƒ½ã€æ—¢å®šã§ã¯ã‚³ãƒ³ãƒ†ãƒ³ãƒ„アイテムã®åå‰ - - - - Icon - アイコン - - - - Optional, defaults to inheriting from top-level Addon - çœç•¥å¯èƒ½ã€ãƒ‡ãƒ•ォルトã§ã¯æœ€ä¸Šä½ã®æ‹¡å¼µæ©Ÿèƒ½ã‹ã‚‰ç¶™æ‰¿ - - - - Tags... - ã‚¿ã‚°... - - - - Dependencies... - ä¾å­˜é–¢ä¿‚... - - - - FreeCAD Versions... - FreeCADã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³... - - - - Other Metadata - ãã®ä»–ã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®ã‚¢ãƒ‰ã‚ªãƒ³ä¸€è¦§ã«è¡¨ç¤ºã•れã¾ã™ã€‚"FreeCAD" ã¨ã„ã†å˜èªžãŒå«ã¾ã‚Œãªã„よã†ã«ã—ã¦ãã ã•ã„。 - - - - Version - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Description - 説明 - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - セマンティック(1.2.3-beta)ã‹ã‚«ãƒ¬ãƒ³ãƒ€ãƒ¼ï¼ˆ2022.08.30)ãƒãƒ¼ã‚¸ãƒ§ãƒ‹ãƒ³ã‚°ã§å…¥åŠ› - - - - Set to today (CalVer style) - ä»Šæ—¥ã®æ—¥ä»˜ã‚’挿入 - - - - Display Name - 表示å - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - 空白ã®ãƒ•ィールドã¯ã€ãƒˆãƒƒãƒ—ãƒ¬ãƒ™ãƒ«ã®æ‹¡å¼µæ©Ÿèƒ½ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰ç¶™æ‰¿ã•れるãŸã‚ã€å®Ÿè³ªçš„ã«ã¯ã™ã¹ã¦ã‚ªãƒ—ションã§ã™ã€‚ 複数ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„アイテムをæŒã¤æ‹¡å¼µæ©Ÿèƒ½ã§ã¯ã€å„アイテムã«ã¯ä¸€æ„ãªè¡¨ç¤ºåã¨èª¬æ˜Žã‚’指定ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ - - - - add_toolbar_button_dialog - - - Add button? - ボタンを追加ã—ã¾ã™ã‹ï¼Ÿ - - - - Add a toolbar button for this macro? - ツールãƒãƒ¼ã«ã“ã®ãƒžã‚¯ãƒ­ã‚’追加ã—ã¾ã™ã‹ï¼Ÿ - - - - Yes - ã¯ã„ - - - - No - ã„ã„㈠- - - - Never - 常ã«ã—ãªã„ - - - - change_branch - - - Change Branch - ブランãƒã®å¤‰æ›´ - - - - Change to branch: - ブランãƒã®å¤‰æ›´ - - - - copyrightInformationDialog - - - Copyright Information - 著作権情報 - - - - Copyright holder: - 著作権者 - - - - Copyright year: - 著作権年 - - - - personDialog - - - Add Person - 人物を追加 - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - ä¿å®ˆæ‹…当者ã¯ã“ã®ãƒ—ロジェクトã§ç¾åœ¨ã‚³ãƒŸãƒƒãƒˆã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’æŒã£ã¦ã„る人ã§ã™ã€‚作æˆè€…ã¯ã‚ãªãŸãŒã‚¯ãƒ¬ã‚¸ãƒƒãƒˆè¡¨è¨˜ã—ãŸã„ã¨æ€ã†ä»»æ„ã®äººã§ã™ã€‚ - - - - Name: - åå‰ - - - - Email: - Eメール - - - - Email is required for maintainers, and optional for authors. - ä¿å®ˆæ‹…当者ã¯EメールアドレスãŒå¿…è¦ã§ã™ã€‚ - - - - proxy_authentication - - - Proxy login required - プロキシã«ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„ - - - - Proxy requires authentication - プロキシã«èªè¨¼ãŒå¿…è¦ã§ã™ - - - - Proxy: - プロキシ - - - - Placeholder for proxy address - プロキシアドレスã®ãƒ—レースホルダー - - - - Realm: - レルム - - - - Placeholder for proxy realm - プロキシã®ãƒ¬ãƒ«ãƒ ã®ãƒ—レースホルダー - - - - Username - ユーザーå - - - - Password - パスワード - - - - selectLicenseDialog - - - Select a license - ライセンスã®é¸æŠž - - - - About... - ã“ã®ãƒ—ログラムã«ã¤ã„ã¦... - - - - License name: - ライセンスå - - - - Path to license file: - ライセンスファイルã®ãƒ‘ス - - - - (if required by license) - (必è¦ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®å ´åˆï¼‰ - - - - Browse... - å‚ç…§... - - - - Create... - 作æˆ... - - - - select_toolbar_dialog - - - - - - Select Toolbar - ツールãƒãƒ¼ã‚’é¸æŠž - - - - Select a toolbar to add this macro to: - ã“ã®ãƒžã‚¯ãƒ­ã‚’追加ã™ã‚‹ãƒ„ールãƒãƒ¼ã‚’é¸æŠž - - - - Ask every time - 毎回確èªã™ã‚‹ - - - - toolbar_button - - - - Add button? - ボタンを追加ã—ã¾ã™ã‹ï¼Ÿ - - - - Add a toolbar button for this macro? - ツールãƒãƒ¼ã«ã“ã®ãƒžã‚¯ãƒ­ã‚’追加ã—ã¾ã™ã‹ï¼Ÿ - - - - Yes - ã¯ã„ - - - - No - ã„ã„㈠- - - - Never - 常ã«ã—ãªã„ - - - - AddonsInstaller - - - Starting up... - èµ·å‹•ã—ã¦ã„ã¾ã™â€¦ - - - - Worker process {} is taking a long time to stop... - ワーカープロセス {} ã®åœæ­¢ã«æ™‚é–“ãŒã‹ã‹ã£ã¦ã„ã¾ã™â€¦ - - - - Previous cache process was interrupted, restarting... - - キャッシュプロセスãŒä¸­æ–­ã•れã¾ã—ãŸã€‚å†èµ·å‹•ã—ã¦ã„ã¾ã™â€¦ - - - - - Custom repo list changed, forcing recache... - - カスタムリãƒã‚¸ãƒˆãƒªã®ä¸€è¦§ãŒå¤‰æ›´ã•れã¾ã—ãŸã€‚強制的ã«å†ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’ã—ã¦ã„ã¾ã™â€¦ - - - - Addon manager - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ - - - - You must restart FreeCAD for changes to take effect. - 変更を有効ã«ã™ã‚‹ã«ã¯FreeCADã‚’å†èµ·å‹•ã—ã¦ãã ã•ã„。 - - - - Restart now - 今ã™ãå†èµ·å‹• - - - - Restart later - 後ã§å†èµ·å‹• - - - - - Refresh local cache - ローカルキャッシュを更新 - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - キャッシュを更新ã—ã¦ã„ã¾ã™â€¦ - - - - - Checking for updates... - 更新を確èªã—ã¦ã„ã¾ã™â€¦ - - - - Temporary installation of macro failed. - マクロを一時インストールã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ - - - - - Close - é–‰ã˜ã‚‹ - - - - Update all addons - å…¨ã¦ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’æ›´æ–° - - - - Check for updates - æ›´æ–°ã‚’ç¢ºèª - - - - Python dependencies... - Pythonã®ä¾å­˜é–¢ä¿‚... - - - - Developer tools... - 開発者ツール... - - - - Apply %n available update(s) - %n ã‚’æ›´æ–° - - - - No updates available - æ›´æ–°ã¯ã‚りã¾ã›ã‚“ - - - - - - Cannot launch a new installer until the previous one has finished. - å‰ã®ã‚‚ã®ãŒçµ‚了ã™ã‚‹ã¾ã§ã€æ–°ã—ã„インストーラーã¯èµ·å‹•ã§ãã¾ã›ã‚“。 - - - - - - - Maintainer - ä¿å®ˆæ‹…当者 - - - - - - - Author - 作æˆè€… - - - - New Python Version Detected - æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®PythonãŒæ¤œå‡ºã•れã¾ã—ãŸã€‚ - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Python ãŒã‚¢ãƒ‰ã‚ªãƒ³ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã§ä½¿ç”¨ã•れãŸã®ã¯åˆã‚ã¦ã®ã‚ˆã†ã§ã™ã€‚ åŒã˜è‡ªå‹•インストールä¾å­˜é–¢ä¿‚をインストールã—ã¾ã™ã‹ï¼Ÿ - - - - Processing, please wait... - 処ç†ã—ã¦ã„ã¾ã™ã€‚ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„… - - - - - Update - æ›´æ–° - - - - Updating... - æ›´æ–°ã—ã¦ã„ã¾ã™â€¦ - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - QtNetwork をインãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ä¾å­˜é–¢ä¿‚ã®ãƒ‘ッケージ("python3-pyside2.qtnetwork")をインストールã—ã¦ãã ã•ã„。 - - - - Failed to convert the specified proxy port '{}' to a port number - 指定ã•れãŸãƒ—ロキシãƒãƒ¼ãƒˆ '{}' ã‚’ãƒãƒ¼ãƒˆç•ªå·ã«å¤‰æ›ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - パラメーターエラー:相互排他的ãªãƒ—ロキシオプションãŒè¨­å®šã•れã¦ã„ã¾ã™ã€‚既定ã®ãƒ—ロキシã«å†è¨­å®šã—ã¾ã™ã€‚ - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - パラメーターエラー:「手動ã§ãƒ—ロキシを設定ã™ã‚‹ã€ãŒé¸æŠžã•れã¾ã—ãŸãŒã€ãƒ—ãƒ­ã‚­ã‚·ãŒæä¾›ã•れã¦ã„ã¾ã›ã‚“。既定ã®ãƒ—ロキシã«å†è¨­å®šã—ã¾ã™ã€‚ - - - - Addon Manager: Unexpected {} response from server - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼: サーãƒãƒ¼ã‹ã‚‰ã®äºˆæœŸã—ãªã„ {} レスãƒãƒ³ã‚¹ - - - - Error with encrypted connection - æš—å·åŒ–ã•ã‚ŒãŸæŽ¥ç¶šã§ã‚¨ãƒ©ãƒ¼ - - - - - - Confirm remove - å‰Šé™¤ã‚’ç¢ºèª - - - - Are you sure you want to uninstall {}? - {} をアンインストールã—ã¾ã™ã‹ï¼Ÿ - - - - - - Removing Addon - 拡張機能を削除ã—ã¦ã„ã¾ã™ - - - - Removing {} - {}を削除ã—ã¦ã„ã¾ã™ - - - - - Uninstall complete - アンインストールã—ã¾ã—㟠- - - - - Uninstall failed - アンインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Version {version} installed on {date} - {date} ã«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ {version} ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¾ã—㟠- - - - Version {version} installed - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ {version} ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¾ã—㟠- - - - Installed on {date} - {date} ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¾ã—㟠- - - - - - - Installed - インストール済㿠- - - - Currently on branch {}, name changed to {} - ç¾åœ¨ã®ãƒ–ランム{} ã®åå‰ãŒ {} ã«å¤‰æ›´ã•れã¾ã—㟠- - - - Git tag '{}' checked out, no updates possible - Gitã‚¿ã‚° '{}' ãŒãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã•れã¾ã—ãŸã€‚æ›´æ–°ã¯ã‚りã¾ã›ã‚“。 - - - - Update check in progress - 更新を確èªã—ã¦ã„ã¾ã™ - - - - Installation location - インストール先 - - - - Repository URL - リãƒã‚¸ãƒˆãƒªã®URL - - - - Changed to branch '{}' -- please restart to use Addon. - ブランム'{}' ã«å¤‰æ›´ã•れã¾ã—ãŸã€‚拡張機能を使用ã™ã‚‹ã«ã¯å†èµ·å‹•ã—ã¦ãã ã•ã„。 - - - - This Addon has been updated. Restart FreeCAD to see changes. - ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚FreeCADã‚’å†èµ·å‹•ã—ã¦å¤‰æ›´ã‚’確èªã—ã¦ãã ã•ã„。 - - - - Disabled - 無効 - - - - Currently on branch {}, update available to version {} - ç¾åœ¨ã®ãƒ–ランム{} ã§ ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ {} ã«æ›´æ–°ã§ãã¾ã™ - - - - Update available to version {} - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ {} ã«æ›´æ–°ã§ãã¾ã™ - - - - This is the latest version available - ãŠä½¿ã„ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯æœ€æ–°ã§ã™ - - - - WARNING: This addon is obsolete - 警告:ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯å»ƒæ­¢ã•れã¾ã—㟠- - - - WARNING: This addon is Python 2 only - 警告:ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯ Python 2専用ã§ã™ - - - - WARNING: This addon requires FreeCAD {} - 警告:ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯ FreeCAD {} ãŒå¿…è¦ã§ã™ - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - 警告:ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯ç¾åœ¨ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã¾ã™ãŒç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚å†åº¦æœ‰åйã«ã™ã‚‹ã«ã¯ã€Œæœ‰åйã€ãƒœã‚¿ãƒ³ã‚’押ã—ã¦ãã ã•ã„。 - - - - This Addon will be enabled next time you restart FreeCAD. - ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯æ¬¡ã«FreeCADã‚’å†èµ·å‹•ã—ãŸã¨ãã«æœ‰åйã«ãªã‚Šã¾ã™ã€‚ - - - - This Addon will be disabled next time you restart FreeCAD. - ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯æ¬¡ã«FreeCADã‚’å†èµ·å‹•ã—ãŸã¨ãã«ç„¡åйã«ãªã‚Šã¾ã™ã€‚ - - - - - - Success - インストールã—ã¾ã—㟠- - - - Install - インストール - - - - Uninstall - アンインストール - - - - Enable - 有効 - - - - Disable - 無効化 - - - - - Check for update - æ›´æ–°ã‚’ç¢ºèª - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - 実行 - - - - Change branch... - ブランãƒã‚’変更... - - - - Return to package list - パッケージã®ä¸€è¦§ã«æˆ»ã‚‹ - - - - Checking connection - 接続を確èªã—ã¦ã„ã¾ã™ - - - - Checking for connection to GitHub... - GitHubã¸ã®æŽ¥ç¶šã‚’確èªã—ã¦ã„ã¾ã™â€¦ - - - - Connection failed - 接続ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Missing dependency - ä¾å­˜é–¢ä¿‚ãŒå¤±ã‚れã¦ã„ã¾ã™ - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - QtNetworkをインãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚詳細ã«ã¤ã„ã¦ã¯ãƒ¬ãƒãƒ¼ãƒˆãƒ“ューをå‚ç…§ã—ã¦ãã ã•ã„。アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。 - - - - Other... - For providing a license other than one listed - ãã®ä»–ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹... - - - - Select the corresponding license file in your Addon - 拡張機能ã§å¯¾å¿œã™ã‚‹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„ - - - - Location for new license file - æ–°è¦ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ•ァイルã®ä¿å­˜å…ˆ - - - - Received {} response code from server - サーãƒãƒ¼ã‹ã‚‰ {} レスãƒãƒ³ã‚¹ãŒã‚りã¾ã—㟠- - - - Failed to install macro {} - マクロ {} をインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Failed to create installation manifest file: - - インストールマニフェストファイルを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ - - - - Unrecognized content kind '{}' - èªè­˜ã§ããªã„コンテンツ '{}' ã§ã™ - - - - Unable to locate icon at {} - {} ã§ã‚¢ã‚¤ã‚³ãƒ³ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠- - - - Select an icon file for this content item - ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ç”¨ã®ã‚¢ã‚¤ã‚³ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„ - - - - - - {} is not a subdirectory of {} - {} 㯠{} ã®ã‚µãƒ–ディレクトリã§ã¯ã‚りã¾ã›ã‚“ - - - - Select the subdirectory for this content item - ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„アイテムã®ã‚µãƒ–ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„ - - - - Automatic - 自動 - - - - - Workbench - ワークベンム- - - - Addon - アドオン - - - - Python - Python - - - - Yes - ã¯ã„ - - - - Internal Workbench - 内部ワークベンム- - - - External Addon - å¤–éƒ¨ã®æ‹¡å¼µæ©Ÿèƒ½ - - - - Python Package - Pythonã®ãƒ‘ッケージ - - - - - Other... - ãã®ä»–... - - - - Too many to list - é …ç›®ãŒå¤šã„ãŸã‚å…¨ã¦ã‚’一覧ã«ã§ãã¾ã›ã‚“ - - - - - - - - - Missing Requirement - ä¸è¶³ã—ã¦ã„ã‚‹è¦ä»¶ - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - 拡張機能 '{}' ã«ã¯ '{}' をインストールã—ã¦ãã ã•ã„。 - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - 拡張機能 '{}' ã«ã¯ä»¥ä¸‹ã®ãƒ¯ãƒ¼ã‚¯ãƒ™ãƒ³ãƒã‚’インストールã—ã¦ãã ã•ã„。 - - - - Press OK to install anyway. - インストールã™ã‚‹ã«ã¯OKをクリックã—ã¦ãã ã•ã„。 - - - - - Incompatible Python version - Pythonã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«äº’æ›æ€§ãŒã‚りã¾ã›ã‚“ - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã¯å¿…è¦ãªPythonパッケージãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ãªã„ãŸã‚ã€è‡ªå‹•ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã›ã‚“。 ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’使用ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®Pythonパッケージを手動ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。 - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - ã“ã®æ‹¡å¼µæ©Ÿèƒ½ï¼ˆã‚ã‚‹ã„ã¯ä¾å­˜é–¢ä¿‚ãŒã‚ã‚‹å ´åˆã¯ãã®1ã¤ï¼‰ã§ã¯ Python {}.{} ãŒå¿…è¦ã§ã™ãŒã€ã‚·ã‚¹ãƒ†ãƒ ãŒ {}.{} ã§å®Ÿè¡Œã•れã¦ã„ã‚‹ãŸã‚インストールã¯ä¸­æ­¢ã•れã¾ã—ãŸã€‚ - - - - Optional dependency on {} ignored because it is not in the allow-list - 許å¯ãƒªã‚¹ãƒˆã«ãªã„ãŸã‚ã€{} ã®ã‚ªãƒ—ションã®ä¾å­˜é–¢ä¿‚ã¯ç„¡è¦–ã•れã¾ã™ã€‚ - - - - - Installing dependencies - ä¾å­˜é–¢ä¿‚をインストールã—ã¦ã„ã¾ã™ - - - - - Cannot execute Python - Pythonを実行ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Pythonã®å®Ÿè¡Œãƒ•ァイルã®è‡ªå‹•検索ã«å¤±æ•—ã—ãŸã‹ã€ã‚ã‚‹ã„ã¯ãƒ‘ã‚¹ãŒæ­£ã—ã設定ã•れã¦ã„ã¾ã›ã‚“。アドオンマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼è¨­å®šã§Pythonã®ãƒ‘スを確èªã—ã¦ãã ã•ã„。 - - - - Dependencies could not be installed. Continue with installation of {} anyway? - ä¾å­˜é–¢ä¿‚をインストールã§ãã¾ã›ã‚“ã§ã—ãŸã€‚{} ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã—ã¾ã™ã‹ï¼Ÿ - - - - - Cannot execute pip - pipを実行ã§ãã¾ã›ã‚“ - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - pipを実行ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚システムã«pipãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。失敗ã—ãŸã‚³ãƒžãƒ³ãƒ‰ã¯æ¬¡ã®é€šã‚Šã§ã™ã€‚ - - - - - Continue with installation of {} anyway? - {} ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã—ã¾ã™ã‹ï¼Ÿ - - - - - Package installation failed - パッケージをインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - See Report View for detailed failure log. - 詳細ãªå¤±æ•—ログã«ã¤ã„ã¦ã¯ã€ãƒ¬ãƒãƒ¼ãƒˆãƒ“ューをå‚ç…§ã—ã¦ãã ã•ã„。 - - - - Installing Addon - 拡張機能をインストールã—ã¦ã„ã¾ã™ - - - - Installing FreeCAD Addon '{}' - 拡張機能 '{}' をインストールã—ã¦ã„ã¾ã™ - - - - Cancelling - 中止ã—ã¦ã„ã¾ã™ - - - - Cancelling installation of '{}' - '{}' ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’中止ã—ã¦ã„ã¾ã™ - - - - {} was installed successfully - {} をインストールã—ã¾ã—㟠- - - - - Installation Failed - インストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Failed to install {} - {} をインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - - Create new toolbar - ツールãƒãƒ¼ã‚’æ–°è¦ä½œæˆ - - - - - A macro installed with the FreeCAD Addon Manager - FreeCAD アドオンマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れãŸãƒžã‚¯ãƒ­ - - - - - Run - Indicates a macro that can be 'run' - 実行 - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - GitHubã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—ãŸã€‚インターãƒãƒƒãƒˆæŽ¥ç¶šã¨ãƒ—ロキシ設定を確èªã—ã¦ãã ã•ã„。 - - - - XML failure while reading metadata from file {} - ファイル {} ã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¿ä¸­ã«XMLエラーãŒç™ºç”Ÿã—ã¾ã—㟠- - - - Invalid metadata in file {} - ファイル {} ã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ãŒç„¡åйã§ã™ - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - 警告:package.xmlãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã§æŒ‡å®šã•れãŸãƒ‘スãŒç¾åœ¨ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã•れã¦ã„るブランãƒã¨ä¸€è‡´ã—ã¾ã›ã‚“ã§ã—ãŸã€‚ - - - - Name - åå‰ - - - - Class - クラス - - - - Description - 説明 - - - - Subdirectory - サブディレクトリ - - - - Files - ファイル - - - - Select the folder containing your Addon - 拡張機能をä¿å­˜ã—ãŸãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¦ãã ã•ã„ - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - VerminãŒã‚りã¾ã›ã‚“。æ“作を中止ã—ã¾ã™ã€‚ - - - - Scanning Addon for Python version compatibility - Pythonã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³äº’æ›æ€§ã‚’確èªã™ã‚‹ãŸã‚ã€æ‹¡å¼µæ©Ÿèƒ½ã‚’スキャンã—ã¦ã„ã¾ã™ - - - - Minimum Python Version Detected - 最å°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®PythonãŒæ¤œå‡ºã•れã¾ã—㟠- - - - Vermin auto-detected a required version of Python 3.{} - Verminã¯Python 3.{} ã‚’å¿…è¦ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨ã—ã¦æ¤œå‡ºã—ã¾ã—㟠- - - - Install Vermin? - Verminをインストールã—ã¾ã™ã‹ï¼Ÿ - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - ã“ã®æ‹¡å¼µæ©Ÿèƒ½ã«å¿…è¦ãªPythonã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’è‡ªå‹•çš„ã«æ¤œå‡ºã™ã‚‹ã«ã¯ã€Vermin(https://pypi.org/project/vermin/)ãŒå¿…è¦ã§ã™ã€‚Verminをインストールã—ã¾ã™ã‹ï¼Ÿ - - - - Attempting to install Vermin from PyPi - PyPiã‹ã‚‰Verminをインストールã—ã¦ã„ã¾ã™ - - - - - Installation failed - インストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Verminをインストールã§ãã¾ã›ã‚“ã§ã—ãŸã€‚詳細ã«ã¤ã„ã¦ã¯ãƒ¬ãƒãƒ¼ãƒˆãƒ“ューを確èªã—ã¦ãã ã•ã„。 - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - インストールã—ãŸVerminをインãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚拡張機能をスキャンã§ãã¾ã›ã‚“。 - - - - Select an icon file for this package - ã“ã®ãƒ‘ッケージ用ã®ã‚¢ã‚¤ã‚³ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„ - - - - Filter is valid - ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã¯æœ‰åйã§ã™ - - - - Filter regular expression is invalid - ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã®æ­£è¦è¡¨ç¾ãŒæ­£ã—ãã‚りã¾ã›ã‚“ - - - - Search... - 検索... - - - - Click for details about package {} - パッケージ {} ã®è©³ç´°ã«ã¤ã„ã¦ã¯ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„ - - - - Click for details about workbench {} - ワークベンム{} ã®è©³ç´°ã«ã¤ã„ã¦ã¯ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„ - - - - Click for details about macro {} - マクロ {} ã®è©³ç´°ã«ã¤ã„ã¦ã¯ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„ - - - - Maintainers: - ä¿å®ˆæ‹…当者 - - - - Tags - ã‚¿ã‚° - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - ★ãŒã‚りã¾ã›ã‚“。ã¾ãŸã¯GitHubã«ã‚りã¾ã›ã‚“ - - - - Created - ä½œæˆ - - - - Updated - æ›´æ–° - - - - Score: - スコア - - - - - Up-to-date - 最新版 - - - - - - - - Update available - æ›´æ–°ãŒã‚りã¾ã™ - - - - - Pending restart - å†èµ·å‹•ã‚’ä¿ç•™ã—ã¦ã„ã¾ã™ - - - - - DISABLED - 無効 - - - - Installed version - インストール済ã¿ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Unknown version - 䏿˜Žãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Installed on - インストール済㿠- - - - Available version - 利用å¯èƒ½ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ - - - - Filter by... - フィルター... - - - - Addon Type - 拡張機能ã®ç¨®é¡ž - - - - - Any - ä»»æ„ - - - - Macro - マクロ - - - - Preference Pack - 環境設定パック - - - - Installation Status - インストールã®çŠ¶æ…‹ - - - - Not installed - 未インストール - - - - Filter - フィルター - - - - DANGER: Developer feature - å±é™ºï¼šé–‹ç™ºè€…機能 - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - å±é™ºï¼šãƒ–ランãƒã®åˆ‡ã‚Šæ›¿ãˆã¯é–‹ç™ºè€…ã¨ãƒ™ãƒ¼ã‚¿ãƒ†ã‚¹ã‚¿ãƒ¼ã‚’対象ã¨ã—ã¦ãŠã‚Šã€å£Šã‚ŒãŸå¾Œæ–¹äº’æ›æ€§ã®ãªã„ドキュメントファイルã€ä¸å®‰å®šãªæŒ™å‹•ã€ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚’引ãèµ·ã“ã™å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚ 実行ã—ã¾ã™ã‹ï¼Ÿ - - - - There are local changes - ローカルã®å¤‰æ›´ãŒã‚りã¾ã™ - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - 警告:ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã¯ã‚³ãƒŸãƒƒãƒˆã•れã¦ã„ãªã„ローカルãªå¤‰æ›´ãŒã‚りã¾ã™ã€‚ï¼ˆå¤‰æ›´ã‚’ä¿æŒã—ãŸã¾ã¾ï¼‰ãƒ–ランãƒã‚’変更ã—ã¾ã™ã‹ï¼Ÿ - - - - Local - Table header for local git ref name - ローカル - - - - Remote tracking - Table header for git remote tracking branch name - リモートトラッキング - - - - Last Updated - Table header for git update date - 最終更新 - - - - Installation of Python package {} failed - Pythonã®ãƒ‘ッケージ {} をインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Installation of optional package failed - オプションã®ãƒ‘ッケージをインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Installing required dependency {} - å¿…è¦ãªä¾å­˜é–¢ä¿‚ {} をインストールã—ã¦ã„ã¾ã™ - - - - Installation of Addon {} failed - 拡張機能 {} をインストールã§ãã¾ã›ã‚“ã§ã—㟠- - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - {} ファイルを拡張機能 '{}' 用ã«ãƒ‡ã‚³ãƒ¼ãƒ‰ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Any dependency information in this file will be ignored - ã“ã®ãƒ•ァイル内ã®ä¾å­˜é–¢ä¿‚ã®æƒ…å ±ã¯ç„¡è¦–ã•れã¾ã™ - - - - Unable to open macro wiki page at {} - {} ã®ãƒžã‚¯ãƒ­ã®Wikiã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—㟠- - - - Unable to fetch the code of this macro. - ã“ã®ãƒžã‚¯ãƒ­ã®ã‚³ãƒ¼ãƒ‰ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Unable to retrieve a description from the wiki for macro {} - マクロ {} ã®èª¬æ˜Žã‚’Wikiã‹ã‚‰å–å¾—ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Unable to open macro code URL {} - マクロã®ã‚³ãƒ¼ãƒ‰ã® URL {} ã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—㟠- - - - Unable to fetch macro-specified file {} from {} - マクロ指定ファイル {} ã‚’ {} ã‹ã‚‰å–å¾—ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Could not locate macro-specified file {} (expected at {}) - マクロ指定ファイル {} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠({}) - - - - {}: Unrecognized internal workbench '{}' - {}:èªè­˜ã§ããªã„内部ワークベンム'{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - 拡張機能開発者警告: 拡張機能 {} ({}) ã®package.xmlファイルã«è¨­å®šã•れã¦ã„るリãƒã‚¸ãƒˆãƒªURL㌠({}) ã‹ã‚‰å–å¾—ã—ãŸURLã¨ä¸€è‡´ã—ã¾ã›ã‚“ã§ã—㟠- - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - 拡張機能開発者警告: 拡張機能 {} ({}) ã®package.xmlファイルã«è¨­å®šã•れã¦ã„るリãƒã‚¸ãƒˆãƒªã®ãƒ–ランãƒãŒ ({}) ã‹ã‚‰å–å¾—ã—ãŸãƒ–ランãƒã¨ä¸€è‡´ã—ã¾ã›ã‚“ã§ã—㟠- - - - - Got an error when trying to import {} - {} ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ - - - - An unknown error occurred - 䏿˜Žãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ - - - - Could not find addon {} to remove it. - 削除ã™ã‚‹æ‹¡å¼µæ©Ÿèƒ½ {} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - 拡張機能ã®uninstall.pyスクリプトを実行ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚アンインストールã—ã¦ã„ã¾ã™â€¦ - - - - Removed extra installed file {} - 追加ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れãŸãƒ•ァイル {} を削除ã—ã¾ã—㟠- - - - Error while trying to remove extra installed file {} - 追加ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れãŸãƒ•ァイル {} ã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—㟠- - - - Error while trying to remove macro file {}: - マクロファイル {} ã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—㟠- - - - Failed to connect to GitHub. Check your connection and proxy settings. - GitHubã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚インターãƒãƒƒãƒˆæŽ¥ç¶šã¨ãƒ—ロキシ設定を確èªã—ã¦ãã ã•ã„。 - - - - WARNING: Duplicate addon {} ignored - 警告:é‡è¤‡ã™ã‚‹æ‹¡å¼µæ©Ÿèƒ½ {} ã¯ç„¡è¦–ã•れã¾ã—㟠- - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - GitHubã®ãƒžã‚¯ãƒ­ã‚’更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã‚’削除ã—ã¦ã„ã¾ã™â€¦ - - - - Attempting to do a clean checkout... - ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã‚’削除ã—ã¦ã„ã¾ã™â€¦ - - - - Clean checkout succeeded - ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã‚’削除ã—ã¾ã—㟠- - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - GitHub ã‹ã‚‰ãƒžã‚¯ãƒ­ã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—㟠-- アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’クリアã—ã¦ã¿ã¦ãã ã•ã„。 - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Wikiã¸ã®æŽ¥ç¶šä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ç¾åœ¨ã€FreeCADã¯Wikiã®ãƒžã‚¯ãƒ­ä¸€è¦§ã‚’å–å¾—ã§ãã¾ã›ã‚“。 - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - {name} ã‹ã‚‰ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã‚ã¾ã›ã‚“ã§ã—㟠- - - - Failed to fetch code for macro '{name}' - マクロ '{name}' ã®ã‚³ãƒ¼ãƒ‰ãŒå–å¾—ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Addon Manager: a worker process failed to complete while fetching {name} - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼: {name} ã®å–得中ã«ãƒ¯ãƒ¼ã‚«ãƒ¼ãƒ—ロセスãŒå‡¦ç†ã‚’完了ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Out of {num_macros} macros, {num_failed} timed out while processing - {num_macros}個ã®ãƒžã‚¯ãƒ­ã®ã†ã¡ã€{num_failed}個ãŒå‡¦ç†ä¸­ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—㟠- - - - Addon Manager: a worker process failed to halt ({name}) - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼: ワーカープロセスã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—㟠({name}) - - - - Timeout while fetching metadata for macro {} - マクロ {} ã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‚’å–得中ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—㟠- - - - Failed to kill process for macro {}! - - マクロ {} ã®ãƒ—ロセスを強制終了ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - {} ã‹ã‚‰æ‹¡å¼µæ©Ÿèƒ½ã®çµ±è¨ˆãƒ‡ãƒ¼ã‚¿ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚アルファベット順ã§ã®ä¸¦ã¹æ›¿ãˆã®ã¿æ­£ã—ã„ã‚‚ã®ã«ãªã‚Šã¾ã™ - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - '{}' ã‹ã‚‰æ‹¡å¼µæ©Ÿèƒ½ã®ã‚¹ã‚³ã‚¢ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚スコア順ã§ã®ä¸¦ã¹æ›¿ãˆã¯ã§ãã¾ã›ã‚“ - - - - - Repository URL - Preferences header for custom repositories - リãƒã‚¸ãƒˆãƒªã®URL - - - - Branch name - Preferences header for custom repositories - ブランãƒå - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - å…ƒã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¦å†ã‚¯ãƒ­ãƒ¼ãƒ³ã—ã¾ã™ - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Giã®ãƒ–ランãƒåを変更ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ - - - - Installing - インストールã—ã¦ã„ã¾ã™ - - - - Succeeded - æˆåŠŸ - - - - Failed - 失敗 - - - - Update was cancelled - 更新を中止ã—ã¾ã—㟠- - - - some addons may have been updated - ä¸€éƒ¨ã®æ‹¡å¼µæ©Ÿèƒ½ãŒæ›´æ–°ã•れã¾ã™ - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - マクロã®Wikiã‹ã‚‰ {} ã®æƒ…報を読ã¿è¾¼ã‚“ã§ã„ã¾ã™â€¦ - - - - Loading page for {} from {}... - {} ã®ãƒšãƒ¼ã‚¸ã‚’ {} ã‹ã‚‰èª­ã¿è¾¼ã‚“ã§ã„ã¾ã™â€¦ - - - - Failed to download data from {} -- received response code {}. - {} ã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ã‚’ダウンロードã§ãã¾ã›ã‚“ã§ã—㟠-- レスãƒãƒ³ã‚¹ã‚³ãƒ¼ãƒ‰ {} ã‚’å—ä¿¡ã—ã¾ã—ãŸã€‚ - - - - Composite view - 複åˆè¡¨ç¤º - - - - Expanded view - 展開表示 - - - - Compact view - コンパクト表示 - - - - Alphabetical - Sort order - アルファベット順 - - - - Last Updated - Sort order - 最終更新 - - - - Date Created - Sort order - ä½œæˆæ—¥æ™‚ - - - - GitHub Stars - Sort order - GitHubã®ã‚¹ã‚¿ãƒ¼æ•° - - - - Score - Sort order - スコア - - - - Std_AddonMgr - - - &Addon manager - アドオンマãƒãƒ¼ã‚¸ãƒ£ãƒ¼(&A) - - - - Manage external workbenches, macros, and preference packs - 外部ã®ãƒ¯ãƒ¼ã‚¯ãƒ™ãƒ³ãƒã€ãƒžã‚¯ãƒ­ã€ç’°å¢ƒè¨­å®šãƒ‘ãƒƒã‚¯ã‚’ç®¡ç† - - - - AddonInstaller - - - Finished removing {} - {}を削除ã—ã¾ã—㟠- - - - Failed to remove some files - 一部ã®ãƒ•ァイルを削除ã§ãã¾ã›ã‚“ã§ã—㟠- - - - Addons installer - - - Finished updating the following addons - ä»¥ä¸‹ã®æ‹¡å¼µæ©Ÿèƒ½ã‚’æ›´æ–°ã—ã¾ã—㟠- - - - Workbench - - - Auto-Created Macro Toolbar - 自動ã§ä½œæˆã•れãŸãƒžã‚¯ãƒ­ã®ãƒ„ールãƒãƒ¼ - - - - QObject - - - Addon Manager - アドオン・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ka.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ka.qm deleted file mode 100644 index 70fd85b4aee7e08eb1af9879bec272c66ca82b69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70807 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ka.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_ka.ts deleted file mode 100644 index 5aa6669d9d..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_ka.ts +++ /dev/null @@ -1,2486 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - ხელით მითითებული რეპáƒáƒ–იტáƒáƒ áƒ˜áƒ - - - - Repository URL - რეპáƒáƒ–იტáƒáƒ áƒ˜áƒ˜áƒ¡ URL - - - - Branch - ბრენჩი - - - - CompactView - - - - Icon - ხáƒáƒ¢áƒ£áƒšáƒ - - - - - <b>Package Name</b> - <b>პáƒáƒ™áƒ”ტის სáƒáƒ®áƒ”ლი</b> - - - - - Version - ვერსირ- - - - - Description - áƒáƒ¦áƒ¬áƒ”რრ- - - - Update Available - ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - UpdateAvailable - გáƒáƒœáƒáƒ®áƒšáƒ”ბრხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ - - - - DependencyDialog - - - Dependencies - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებები - - - - Dependency type - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულების ტიპი - - - - Name - სáƒáƒ®áƒ”ლი - - - - Optional? - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒ? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების áƒáƒ›áƒáƒ®áƒ¡áƒœáƒ - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბáƒáƒ¡ გáƒáƒáƒ©áƒœáƒ˜áƒ შემდეგი სáƒáƒ­áƒ˜áƒ áƒ დრáƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრდáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებები. დáƒáƒáƒ§áƒ”ნეთ ისინი áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბის სრული ფუნქციáƒáƒœáƒáƒšáƒ˜áƒ¡ მისáƒáƒ¦áƒ”ბáƒáƒ“. - -იქნებ გნებáƒáƒ•თ, რáƒáƒ› ეს დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებები დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველმრáƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ დáƒáƒáƒ§áƒ”ნáƒáƒ¡? დáƒáƒ›áƒáƒ¢áƒ”ბის დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების გáƒáƒ áƒ”შე დáƒáƒ¡áƒáƒ§áƒ”ნებლáƒáƒ“ áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ "იგნáƒáƒ áƒ˜". - - - - FreeCAD Addons - FreeCAD-ის დáƒáƒ›áƒáƒ¢áƒ”ბები - - - - Required Python modules - Python-ის სáƒáƒ­áƒ˜áƒ áƒ მáƒáƒ“ულები - - - - Optional Python modules - Python-ის áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრმáƒáƒ“ულები - - - - DeveloperModeDialog - - - Addon Developer Tools - დáƒáƒ›áƒáƒ¢áƒ”ბის პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜áƒ¡ ხელსáƒáƒ¬áƒ§áƒáƒ”ბი - - - - Path to Addon - ბილიკი დáƒáƒ›áƒáƒ¢áƒ”ბáƒáƒ›áƒ“ე - - - - - Browse... - მáƒáƒ«áƒ”ბნáƒ... - - - - Metadata - მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მები - - - - Primary branch - ძირითáƒáƒ“ი ბრენჩი - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - áƒáƒ¦áƒ¬áƒ”რáƒ, რáƒáƒ¡ áƒáƒ™áƒ”თებს ეს დáƒáƒ›áƒáƒ¢áƒ”ბáƒ. გáƒáƒ›áƒáƒ©áƒœáƒ“ებრდáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველში. ეს სáƒáƒ™áƒ›áƒáƒ áƒ˜áƒ¡áƒ˜ áƒáƒ áƒáƒ, რáƒáƒ› ის FreeCAD-ის დáƒáƒ›áƒáƒ¢áƒ”ბრáƒáƒ¦áƒ›áƒáƒ©áƒœáƒ“ეს. - - - - Description - áƒáƒ¦áƒ¬áƒ”რრ- - - - Discussion URL - გáƒáƒœáƒ®áƒ˜áƒšáƒ•ის URL - - - - Icon - ხáƒáƒ¢áƒ£áƒšáƒ - - - - Bugtracker URL - შეცდáƒáƒ›áƒ”ბის სიის URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - მხáƒáƒ áƒ“áƒáƒ­áƒ”რილირSemantic (1.2.3-beta) დრCalVer (2022.08.30) სტილები - - - - Set to today (CalVer style) - დღევáƒáƒœáƒ“ელ დღეზე დáƒáƒ§áƒ”ნებრ(CalVer-ის სტილი) - - - - - - - (Optional) - (áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒ) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - ნáƒáƒ©áƒ•ენებირდáƒáƒ›áƒáƒ¢áƒ”ბების სიáƒáƒ¨áƒ˜. áƒáƒ  უნდრშეიცáƒáƒ•დეს სიტყვáƒáƒ¡ "FreeCAD" დრყველრმხáƒáƒ áƒ“áƒáƒ­áƒ”რილი áƒáƒžáƒ”რáƒáƒªáƒ˜áƒ£áƒšáƒ˜ სისტემებისთვის სწáƒáƒ  სáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ის სáƒáƒ®áƒ”ლს უნდრწáƒáƒ áƒ›áƒáƒáƒ“გენდეს. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - მინიშნებáƒ: იმის გáƒáƒ›áƒ, რáƒáƒ› ეს FreeCAD-ის შიგნით, დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველში გáƒáƒ›áƒáƒ©áƒœáƒ“ებáƒ, ნუ დáƒáƒ®áƒáƒ áƒ¯áƒáƒ•თ áƒáƒ“გილს, რáƒáƒ› მიáƒáƒ¬áƒ”რáƒáƒ— "ეს FreeCAD-ის დáƒáƒ›áƒáƒ¢áƒ”ბáƒáƒ" -- უბრáƒáƒšáƒáƒ“ დáƒáƒáƒ¬áƒ”რეთ, რáƒáƒ¡ áƒáƒ™áƒ”თებს. - - - - Repository URL - რეპáƒáƒ–იტáƒáƒ áƒ˜áƒ˜áƒ¡ URL - - - - Website URL - ვებსáƒáƒ˜áƒ¢áƒ˜áƒ¡ URL - - - - Documentation URL - დáƒáƒ™áƒ£áƒ›áƒ”ნტáƒáƒªáƒ˜áƒ˜áƒ¡ URL - - - - Addon Name - დáƒáƒ›áƒáƒ¢áƒ”ბის სáƒáƒ®áƒ”ლი - - - - Version - ვერსირ- - - - (Recommended) - (რეკáƒáƒ›áƒ”ნდებული) - - - - Minimum Python - მინიმáƒáƒšáƒ£áƒ áƒ˜ Python - - - - (Optional, only 3.x version supported) - (áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒ. მხáƒáƒ áƒ“áƒáƒ­áƒ”რილირმხáƒáƒšáƒáƒ“ ვერსირ3.x) - - - - Detect... - áƒáƒ¦áƒ›áƒáƒ©áƒ”ნáƒ... - - - - Addon Contents - დáƒáƒ›áƒáƒ¢áƒ”ბის სáƒáƒ™áƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ - - - - Dialog - - - Addon Manager - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი - - - - Edit Tags - ჭდეების ჩáƒáƒ¡áƒ¬áƒáƒ áƒ”ბრ- - - - Comma-separated list of tags describing this item: - áƒáƒ› ელემენტის áƒáƒ¦áƒ›áƒ¬áƒ”რი მძიმეებით-გáƒáƒ›áƒáƒ§áƒáƒ¤áƒ˜áƒšáƒ˜ ჭდეების სიáƒ: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - მინიშნებáƒ: გáƒáƒ•რცელებული ჭდეები შეიცáƒáƒ•ენ "áƒáƒœáƒáƒ¬áƒ§áƒáƒ‘ს","სემ","ბáƒáƒ“ე","NURBS" დრáƒ.შ. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - გáƒáƒ’რძელებრ- - - - Cancel - გáƒáƒ£áƒ¥áƒ›áƒ”ბრ- - - - EditDependencyDialog - - - Edit Dependency - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულების ჩáƒáƒ¡áƒ¬áƒáƒ áƒ”ბრ- - - - Dependency Type - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულების ტიპი - - - - Dependency - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებრ- - - - Package name, if "Other..." - პáƒáƒ™áƒ”ტის სáƒáƒ®áƒ”ლი, თუ "სხვáƒ..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - შენიშვნáƒ: თუ áƒáƒ áƒ©áƒ”ულირ"სხვáƒ" პáƒáƒ™áƒ”ტი, რáƒáƒ›áƒ”ლიც ALLOWED_PYTHON_PACKAGES.txt ფáƒáƒ˜áƒšáƒ¨áƒ˜ მáƒáƒ§áƒ•áƒáƒœáƒšáƒ˜ áƒáƒ áƒáƒ, áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ áƒáƒ  იქნებრდáƒáƒ§áƒ”ნებული დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის მიერ. პáƒáƒ™áƒ”ტის დáƒáƒ¡áƒáƒ›áƒáƒ¢áƒ”ბლáƒáƒ“ გáƒáƒ®áƒ¡áƒ”ნით PR მისáƒáƒ›áƒáƒ áƒ—ზე <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a>. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - თუ ეს áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრდემáƒáƒ™áƒ˜áƒ“ებულებáƒáƒ, დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი შემáƒáƒ’თáƒáƒ•áƒáƒ–ებთ, დáƒáƒáƒ§áƒ”ნáƒáƒ— ის (თუ ეს შესáƒáƒ«áƒšáƒ”ბელიáƒ), მáƒáƒ’რáƒáƒ› áƒáƒ  დáƒáƒ‘ლáƒáƒ™áƒáƒ•ს დáƒáƒ§áƒ”ნებáƒáƒ¡, თუ უáƒáƒ áƒ¡ გáƒáƒœáƒáƒªáƒ®áƒáƒ“ებთ, პáƒáƒ™áƒ”ტი დáƒáƒáƒ§áƒ”ნáƒáƒ—. - - - - Optional - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრ- - - - ExpandedView - - - - Icon - ხáƒáƒ¢áƒ£áƒšáƒ - - - - - <h1>Package Name</h1> - <h1>პáƒáƒ™áƒ”ტის სáƒáƒ®áƒ”ლი</h1> - - - - - Version - ვერსირ- - - - - (tags) - (ჭდეები) - - - - - Description - áƒáƒ¦áƒ¬áƒ”რრ- - - - - Maintainer - პრáƒáƒ”ქტის ლიდერი - - - - Update Available - გáƒáƒœáƒáƒ®áƒšáƒ”ბრხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ - - - - labelSort - ჭდეების დáƒáƒšáƒáƒ’ებრ- - - - UpdateAvailable - ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒáƒ’áƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Form - - - Licenses - ლიცენზიები - - - - License - ლიცენზირ- - - - License file - ლიცენზიის ფáƒáƒ˜áƒšáƒ˜ - - - - People - ხáƒáƒšáƒ®áƒ˜ - - - - Kind - ტიპი - - - - Name - სáƒáƒ®áƒ”ლი - - - - Email - ელფáƒáƒ¡áƒ¢áƒ - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - ვერსიების დáƒáƒ›áƒáƒ¢áƒ”ბითი ბმრ- - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - FreeCAD-ის დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის მáƒáƒ›áƒáƒ•áƒáƒš ვერსიებს დáƒáƒ›áƒáƒ¢áƒ”ბების ბრენჩის áƒáƒœ ჭდის მითითების სáƒáƒ¨áƒ£áƒáƒšáƒ”ბრექნებáƒ, რáƒáƒ—რსáƒáƒ¨áƒ£áƒáƒšáƒ”ბრმáƒáƒ’ცეთ, ის FreeCAD-ის მითითებულ ვერსიáƒáƒ¨áƒ˜ გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნáƒáƒ— (მáƒáƒ’áƒáƒšáƒ˜áƒ—დ, გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნეთ ჭდეები, რáƒáƒ› áƒáƒ˜áƒ áƒ©áƒ˜áƒáƒ— დáƒáƒ›áƒáƒ¢áƒ”ბáƒ, რáƒáƒ›áƒ”ლსáƒáƒª 0.19-ის მხáƒáƒ áƒ“áƒáƒ­áƒ”რრგáƒáƒáƒ©áƒœáƒ˜áƒ დრáƒ.შ.) - - - - FreeCAD Version - FreeCAD-ის ვერსირ- - - - Best-available branch, tag, or commit - სáƒáƒ£áƒ™áƒ”თესრხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜ ბრენჩი, ჭდე áƒáƒœ კáƒáƒ›áƒ˜áƒ¢áƒ˜ - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - FreeCAD-ის მხáƒáƒ áƒ“áƒáƒ­áƒ”რილი ვერსიები - - - - Minimum FreeCAD Version Supported - FreeCAD-ის მინიმáƒáƒšáƒ£áƒ áƒ˜ მხáƒáƒ áƒ“áƒáƒ­áƒ”რილი ვერსირ- - - - - Optional - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრ- - - - Maximum FreeCAD Version Supported - FreeCAD-ის მáƒáƒ¥áƒ¡áƒ˜áƒ›áƒáƒšáƒ£áƒ áƒ˜ მხáƒáƒ áƒ“áƒáƒ­áƒ”რილი ვერსირ- - - - Advanced version mapping... - ვერსიების დáƒáƒ›áƒáƒ¢áƒ”ბითი ბმáƒ... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის გáƒáƒ›áƒáƒ áƒ—ვრ- - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - თუ ეს პáƒáƒ áƒáƒ›áƒ”ტრი áƒáƒ áƒ©áƒ”ულიáƒ, დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის გáƒáƒ¨áƒ•ებისáƒáƒ¡ -დáƒáƒ§áƒ”ნებული დáƒáƒ›áƒáƒ¢áƒ”ბების გáƒáƒœáƒáƒ®áƒšáƒ”ბებიც შემáƒáƒ¬áƒ›áƒ“ებრ- - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - მáƒáƒ™áƒ áƒáƒ¡ მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მების გáƒáƒ“მáƒáƒ¬áƒ”რრ(დáƒáƒáƒ®áƒš. 10მბ) - - - - Cache update frequency - ქეშის გáƒáƒœáƒáƒ®áƒšáƒ”ბის სიხშირე - - - - Manual (no automatic updates) - ხელით (áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜ გáƒáƒœáƒáƒ®áƒšáƒ”ბების გáƒáƒ›áƒáƒ áƒ—ვáƒ) - - - - Daily - ყáƒáƒ•ელდღიური - - - - Weekly - ყáƒáƒ•ელკვირეული - - - - Hide Addons without a license - ლიცენზიის áƒáƒ áƒ›áƒ¥áƒáƒœáƒ” დáƒáƒ›áƒáƒ¢áƒ”ბების დáƒáƒ›áƒáƒšáƒ•რ- - - - Hide Addons with non-FSF Free/Libre license - áƒáƒ áƒ-FSF/Libre ლიცენზიის მქáƒáƒœáƒ” დáƒáƒ›áƒáƒ¢áƒ”ბების დáƒáƒ›áƒáƒšáƒ•რ- - - - Hide Addons with non-OSI-approved license - áƒáƒ áƒ-OSI-ის მიერ მáƒáƒ¬áƒáƒœáƒ”ბული ლიცენზიის მქáƒáƒœáƒ” გáƒáƒ¤áƒáƒ áƒ—áƒáƒ”ბების დáƒáƒ›áƒáƒšáƒ•რ- - - - Hide Addons marked Python 2 Only - მხáƒáƒšáƒáƒ“ Python v2-თáƒáƒœ თáƒáƒ•სებáƒáƒ“ი დáƒáƒ›áƒáƒ¢áƒ”ბების დáƒáƒ›áƒáƒšáƒ•რ- - - - Hide Addons marked Obsolete - მáƒáƒ«áƒ•ელებულáƒáƒ“ მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ დáƒáƒ›áƒáƒ¢áƒ”ბების დáƒáƒ›áƒáƒšáƒ•რ- - - - Hide Addons that require a newer version of FreeCAD - იმ დáƒáƒ›áƒáƒ¢áƒ”ბების დáƒáƒ›áƒáƒšáƒ•áƒ, რáƒáƒ›áƒ”ლსáƒáƒª FreeCAD-ის უფრრáƒáƒ®áƒáƒšáƒ˜ ვერსირსჭირდებáƒáƒ— - - - - Custom repositories - ხელით მითითებული რეპáƒáƒ–იტáƒáƒ áƒ˜áƒ”ბი - - - - Proxy - პრáƒáƒ¥áƒ¡áƒ˜ - - - - No proxy - პრáƒáƒ¥áƒ¡áƒ˜áƒ¡ გáƒáƒ áƒ”შე - - - - User system proxy - მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის სისტემური პრáƒáƒ¥áƒ¡áƒ˜ - - - - User-defined proxy: - მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის პრáƒáƒ¥áƒ¡áƒ˜: - - - - Score source URL - წყáƒáƒ áƒáƒ¡ ბმულის შეფáƒáƒ¡áƒ”ბრ- - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - ბმული დáƒáƒ›áƒáƒ¢áƒ”ბის ქულების მáƒáƒœáƒáƒªáƒ”მისთვის (იხილეთ დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის ვიკის გვერდი დáƒáƒ¤áƒáƒ áƒ›áƒáƒ¢áƒ”ბისრდრჰáƒáƒ¡áƒ¢áƒ˜áƒœáƒ’ის დეტáƒáƒšáƒ”ბისთვის). - - - - Path to Git executable (optional): - 'git'-ის გáƒáƒ›áƒ¨áƒ•ები ფáƒáƒ˜áƒšáƒ˜áƒ¡ ბილიკი (áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒáƒ): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - დáƒáƒ›áƒáƒ¢áƒ”ბითი პáƒáƒ áƒáƒ›áƒ”ტრები - - - - Activate Addon Manager options intended for developers of new Addons. - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველში áƒáƒ®áƒáƒšáƒ˜ დáƒáƒ›áƒáƒ¢áƒ”ბების პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ”ბისáƒáƒ—ვის გáƒáƒœáƒ™áƒ£áƒ—ვნილი პáƒáƒ áƒáƒ›áƒ”ტრების áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒªáƒ˜áƒ. - - - - Addon developer mode - დáƒáƒ›áƒáƒ¢áƒ”ბის პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜áƒ¡ რეჟიმი - - - - PackageDetails - - - Uninstalls a selected macro or workbench - მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ მáƒáƒ™áƒ áƒáƒ¡ áƒáƒœ სáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდის წáƒáƒ¨áƒšáƒ - - - - Install - დáƒáƒ§áƒ”ნებრ- - - - Uninstall - წáƒáƒ¨áƒšáƒ - - - - Update - გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Run Macro - მáƒáƒ™áƒ áƒáƒ¡ გáƒáƒ¨áƒ•ებრ- - - - Change branch - ბრენჩის შეცვლრ- - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Python-ის დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების მáƒáƒ áƒ—ვრ- - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის მიერ დáƒáƒ›áƒáƒ¢áƒ”ბის მáƒáƒ—ხáƒáƒ•ნების დáƒáƒ¡áƒáƒ™áƒ›áƒáƒ§áƒáƒ¤áƒ˜áƒšáƒ”ბლáƒáƒ“ Python-ის პáƒáƒ™áƒ”ტები იქნრდáƒáƒ§áƒ”ნებული. -დáƒáƒ§áƒ”ნების მდებáƒáƒ áƒ”áƒáƒ‘áƒ: - - - - Package name - პáƒáƒ™áƒ”ტის სáƒáƒ®áƒ”ლი - - - - Installed version - დáƒáƒ§áƒ”ნებული ვერსირ- - - - Available version - ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜ ვერსირ- - - - Used by - გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრ- - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - ვáƒáƒ áƒ¡áƒ™áƒ•ლáƒáƒ•ი (*), "გáƒáƒ›áƒáƒ§áƒ”ნებული" სვეტის მიერ, დáƒáƒ›áƒáƒ¢áƒ”ბითი დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების áƒáƒ áƒ¡áƒ”ბáƒáƒ‘áƒáƒ¡ áƒáƒ¦áƒœáƒ˜áƒ¨áƒœáƒáƒ•ს. გáƒáƒ˜áƒ—ვáƒáƒšáƒ˜áƒ¡áƒ¬áƒ˜áƒœáƒ”თ, რáƒáƒ› ის გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრმხáƒáƒšáƒáƒ“ ჩáƒáƒœáƒáƒ¬áƒ”რების მიერ, რáƒáƒ›áƒšáƒ”ბიც დáƒáƒ›áƒáƒ¢áƒ”ბáƒáƒ¨áƒ˜ პირდáƒáƒžáƒ˜áƒ áƒáƒ შემáƒáƒ¢áƒáƒœáƒ˜áƒšáƒ˜. Python-ის სხვრპáƒáƒ™áƒ”ტები, რáƒáƒ›áƒšáƒ”ბზეც ისინი áƒáƒ áƒ˜áƒáƒœ დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულები, áƒáƒ¡áƒ”ვე დáƒáƒ“გებáƒ. - - - - Update all available - ყველრხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - SelectFromList - - - Dialog - ფáƒáƒœáƒ¯áƒáƒ áƒ - - - - TextLabel - ტექსტური ჭდე - - - - UpdateAllDialog - - - Updating Addons - დáƒáƒ›áƒáƒ¢áƒ”ბების გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Updating out-of-date addons... - მáƒáƒ«áƒ•ელებული დáƒáƒ›áƒáƒ¢áƒ”ბების გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ... - - - - addContentDialog - - - Content Item - შემცველáƒáƒ‘ის ელემენტი - - - - Content type: - შემცველáƒáƒ‘ის ტიპი: - - - - Macro - მáƒáƒ™áƒ áƒ - - - - Preference Pack - პáƒáƒ áƒáƒ›áƒ”ტრების პáƒáƒ™áƒ”ტი - - - - Workbench - სáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდრ- - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - თუ ეს áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბის ერთáƒáƒ“-ერთი რáƒáƒ›áƒáƒ, სხვრმეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მების მიღებრმემკვიდრეáƒáƒ‘ით შეგიძლიáƒáƒ—, უმáƒáƒ¦áƒšáƒ”სი დáƒáƒœáƒ˜áƒ“áƒáƒœ დრáƒáƒ  სჭირდებáƒ, áƒáƒ¥áƒáƒª იყáƒáƒ¡ მითითებული. - - - - This is the only item in the Addon - ეს áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბის ერთáƒáƒ“ ერთი ელემენტირ- - - - Main macro file - მáƒáƒ™áƒ áƒáƒ¡ მთáƒáƒ•áƒáƒ áƒ˜ ფáƒáƒ˜áƒšáƒ˜ - - - - The file with the macro's metadata in it - მáƒáƒ™áƒ áƒáƒ¡ მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მების შემცველი ფáƒáƒ˜áƒšáƒ˜ - - - - - - Browse... - მáƒáƒ«áƒ”ბნáƒ... - - - - Preference Pack Name - პáƒáƒ áƒáƒ›áƒ”ტრების პáƒáƒ™áƒ”ტის სáƒáƒ®áƒ”ლი - - - - Workbench class name - სáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒ˜áƒ¡ კლáƒáƒ¡áƒ˜áƒ¡ სáƒáƒ®áƒ”ლი - - - - Class that defines "Icon" data member - კლáƒáƒ¡áƒ˜, რáƒáƒ›áƒ”ლიც "ხáƒáƒ¢áƒ£áƒšáƒ˜áƒ¡" მáƒáƒœáƒáƒªáƒ”მების წევრს áƒáƒ¦áƒ¬áƒ”რს - - - - Subdirectory - ქვესáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ე - - - - Optional, defaults to name of content item - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒ, ნáƒáƒ’ულისხმევáƒáƒ“ შემცველáƒáƒ‘ის ელემენტის სáƒáƒ®áƒ”ლს შეიცáƒáƒ•ს - - - - Icon - ხáƒáƒ¢áƒ£áƒšáƒ - - - - Optional, defaults to inheriting from top-level Addon - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒ. ნáƒáƒ’ულისხმევირყველáƒáƒ–ე ზედრდáƒáƒ›áƒáƒ¢áƒ”ბიდáƒáƒœ, მემკვიდრეáƒáƒ‘ით - - - - Tags... - ჭდეები... - - - - Dependencies... - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებები... - - - - FreeCAD Versions... - FreeCAD-ის ვერსიები... - - - - Other Metadata - სხვრმეტáƒáƒ˜áƒœáƒ¤áƒáƒ áƒ›áƒáƒªáƒ˜áƒ - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - ნáƒáƒ©áƒ•ენებირდáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის სიáƒáƒ¨áƒ˜. áƒáƒ  უნდრშეიცáƒáƒ•დეს სიტყვáƒáƒ¡ "FreeCAD". - - - - Version - ვერსირ- - - - Description - áƒáƒ¦áƒ¬áƒ”რრ- - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - მხáƒáƒ áƒ“áƒáƒ­áƒ”რილირSemantic (1.2.3-beta) áƒáƒœ CalVer (2022.08.30) სტილები - - - - Set to today (CalVer style) - დღევáƒáƒœáƒ“ელზე დáƒáƒ§áƒ”ნებრ(CalVer-ის სტილი) - - - - Display Name - სáƒáƒ©áƒ•ენებელი სáƒáƒ®áƒ”ლი - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - ნებისმიერი ცáƒáƒ áƒ˜áƒ”ლáƒáƒ“ დáƒáƒ¢áƒáƒ•ებული ველი მემკვირდრეáƒáƒ‘ით იქნებრáƒáƒ¦áƒ”ბული ზედáƒ-დáƒáƒœáƒ˜áƒ¡ დáƒáƒ›áƒáƒ¢áƒ”ბის მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მებიდáƒáƒœ, áƒáƒ¡áƒ” რáƒáƒ›, ტექნიკურáƒáƒ“, ისინი სáƒáƒ•áƒáƒšáƒ“ებული áƒáƒ áƒáƒ. დáƒáƒ›áƒáƒ¢áƒ”ბებისთვის, რáƒáƒ›áƒšáƒ”ბსáƒáƒª შემცველáƒáƒ‘ის მრáƒáƒ•áƒáƒšáƒ˜ ელემენტი გáƒáƒáƒ©áƒœáƒ˜áƒáƒ—, თითáƒáƒ”ულ მáƒáƒ—გáƒáƒœáƒ¡ თáƒáƒ•ისი, უნიკáƒáƒšáƒ£áƒ áƒ˜ სáƒáƒ®áƒ”ლი დრáƒáƒ¦áƒ¬áƒ”რრუნდრგáƒáƒáƒ©áƒœáƒ“ეს. - - - - add_toolbar_button_dialog - - - Add button? - დáƒáƒ•áƒáƒ›áƒáƒ¢áƒ ღილáƒáƒ™áƒ˜? - - - - Add a toolbar button for this macro? - დáƒáƒ•áƒáƒ›áƒáƒ¢áƒ áƒáƒ› ღილáƒáƒ™áƒ˜ áƒáƒ› მáƒáƒ™áƒ áƒáƒ¡áƒ—ვის? - - - - Yes - დიáƒáƒ® - - - - No - áƒáƒ áƒ - - - - Never - áƒáƒ áƒáƒ¡áƒ“რáƒáƒ¡ - - - - change_branch - - - Change Branch - ბრენჩის შეცვლრ- - - - Change to branch: - შეცვლრბრენჩზე: - - - - copyrightInformationDialog - - - Copyright Information - სáƒáƒáƒ•ტáƒáƒ áƒ უფლებები - - - - Copyright holder: - სáƒáƒáƒ•ტáƒáƒ áƒ უფლების მფლáƒáƒ‘ელი: - - - - Copyright year: - სáƒáƒáƒ•ტáƒáƒ áƒ უფლებების წელი: - - - - personDialog - - - Add Person - პირáƒáƒ•ნების დáƒáƒ›áƒáƒ¢áƒ”ბრ- - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - პრáƒáƒ”ქტის წáƒáƒ›áƒ§áƒ•áƒáƒœáƒ˜ წáƒáƒ áƒ›áƒáƒáƒ“გენს პირáƒáƒ•ნებáƒáƒ¡, რáƒáƒ›áƒ”ლსáƒáƒª áƒáƒ› პრáƒáƒ”ქტში ცვლილებების შეტáƒáƒœáƒ შეუძლიáƒ. áƒáƒ•ტáƒáƒ áƒ˜ წáƒáƒ áƒ›áƒáƒáƒ“გენს ნებისმიერს, ვისáƒáƒª გნებáƒáƒ•თ, პáƒáƒ¢áƒ˜áƒ•ი მიáƒáƒ’áƒáƒ—. - - - - Name: - სáƒáƒ®áƒ”ლი: - - - - Email: - ელფáƒáƒ¡áƒ¢áƒ: - - - - Email is required for maintainers, and optional for authors. - ელფáƒáƒ¡áƒ¢áƒ áƒáƒ£áƒªáƒšáƒ”ბელირპრáƒáƒ”ქტის ხელმძღვáƒáƒœáƒ”ლებისáƒáƒ—ვის დრáƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულáƒáƒ áƒáƒ•ტáƒáƒ áƒ”ბისთვის. - - - - proxy_authentication - - - Proxy login required - სáƒáƒ­áƒ˜áƒ áƒáƒ პრáƒáƒ¥áƒ¡áƒ˜áƒ–ე შესვლრ- - - - Proxy requires authentication - პრáƒáƒ¥áƒ¡áƒ˜ მáƒáƒ˜áƒ—ხáƒáƒ•ს áƒáƒ•ტენთიფიკáƒáƒªáƒ˜áƒáƒ¡ - - - - Proxy: - პრáƒáƒ¥áƒ¡áƒ˜: - - - - Placeholder for proxy address - პრáƒáƒ¥áƒ¡áƒ˜ რეáƒáƒšáƒ›áƒ˜áƒ¡ áƒáƒ“გილის დáƒáƒ›áƒ™áƒáƒ•ებელი - - - - Realm: - რეáƒáƒšáƒ›áƒ˜: - - - - Placeholder for proxy realm - პრáƒáƒ¥áƒ¡áƒ˜ რეáƒáƒšáƒ›áƒ˜áƒ¡ áƒáƒ“გილი - - - - Username - მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის სáƒáƒ®áƒ”ლი - - - - Password - პáƒáƒ áƒáƒšáƒ˜ - - - - selectLicenseDialog - - - Select a license - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ ლიცენზირ- - - - About... - შესáƒáƒ®áƒ”ბ... - - - - License name: - ლიცენზიის სáƒáƒ®áƒ”ლი: - - - - Path to license file: - ბილიკი ლიცენზიის ფáƒáƒ˜áƒšáƒáƒ›áƒ“ე: - - - - (if required by license) - (თუ მთხáƒáƒ•ნილირლიცენზიის მიერ) - - - - Browse... - მáƒáƒ«áƒ”ბნáƒ... - - - - Create... - შექმნáƒ... - - - - select_toolbar_dialog - - - - - - Select Toolbar - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ ხელსáƒáƒ¬áƒ§áƒáƒ—რზáƒáƒšáƒ˜ - - - - Select a toolbar to add this macro to: - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ ხელსáƒáƒ¬áƒ§áƒáƒ”ბის ზáƒáƒšáƒ˜, რáƒáƒ›áƒ”ლსáƒáƒª ეს მáƒáƒ™áƒ áƒ დáƒáƒ”მáƒáƒ¢áƒ”ბáƒ: - - - - Ask every time - შეკითხვრყáƒáƒ•ელთვის - - - - toolbar_button - - - - Add button? - დáƒáƒ•áƒáƒ›áƒáƒ¢áƒ ღილáƒáƒ™áƒ˜? - - - - Add a toolbar button for this macro? - დáƒáƒ•áƒáƒ›áƒáƒ¢áƒ ხელსáƒáƒ¬áƒ§áƒáƒ”ბის პáƒáƒœáƒ”ლის ღილáƒáƒ™áƒ˜ áƒáƒ› მáƒáƒ™áƒ áƒáƒ¡áƒ—ვის? - - - - Yes - დიáƒáƒ® - - - - No - áƒáƒ áƒ - - - - Never - áƒáƒ áƒáƒ¡áƒ“რáƒáƒ¡ - - - - AddonsInstaller - - - Starting up... - გáƒáƒ¨áƒ•ებáƒ... - - - - Worker process {} is taking a long time to stop... - დáƒáƒ›áƒ®áƒ›áƒáƒ áƒ” პრáƒáƒªáƒ”სი {} გáƒáƒ©áƒ”რებáƒáƒ¡ მეტისმეტáƒáƒ“ დიდხáƒáƒœáƒ¡ უნდებáƒ... - - - - Previous cache process was interrupted, restarting... - - ქეშის წინრპრáƒáƒªáƒ”სი გáƒáƒ¬áƒ§áƒ“áƒ. თáƒáƒ•იდáƒáƒœ დáƒáƒ¬áƒ§áƒ”ბáƒ... - - - - - Custom repo list changed, forcing recache... - - ხელით მითითებული რეპáƒáƒ”ბის სირშეიცვáƒáƒšáƒ. მიმდინáƒáƒ áƒ”áƒáƒ‘ს ლáƒáƒ™áƒáƒšáƒ£áƒ áƒ˜ ქეშის თáƒáƒ•იდáƒáƒœ áƒáƒ’ებáƒ... - - - - - Addon manager - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი - - - - You must restart FreeCAD for changes to take effect. - ცვლილებების ძáƒáƒšáƒáƒ¨áƒ˜ შესáƒáƒ¡áƒ•ლელáƒáƒ“ სáƒáƒ­áƒ˜áƒ áƒáƒ FreeCAD-ის გáƒáƒ“áƒáƒ¢áƒ•ირთვáƒ. - - - - Restart now - áƒáƒ®áƒšáƒáƒ•ე გáƒáƒ“áƒáƒ¢áƒ•ირთვრ- - - - Restart later - მáƒáƒ’ვიáƒáƒœáƒ”ბით გáƒáƒ“áƒáƒ¢áƒ•ირთვრ- - - - - Refresh local cache - ლáƒáƒ™áƒáƒšáƒ£áƒ áƒ˜ კეშის გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - კეშის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ... - - - - - Checking for updates... - გáƒáƒœáƒáƒ®áƒšáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბáƒ... - - - - Temporary installation of macro failed. - მáƒáƒ™áƒ áƒáƒ¡ დრáƒáƒ”ბით დáƒáƒ§áƒ”ნების ჩáƒáƒ•áƒáƒ áƒ“áƒ. - - - - - Close - დáƒáƒ®áƒ£áƒ áƒ•რ- - - - Update all addons - ყველრდáƒáƒ›áƒáƒ¢áƒ”ბის გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Check for updates - გáƒáƒœáƒáƒ®áƒšáƒ”ბების შემáƒáƒ¬áƒ›áƒ”ბრ- - - - Python dependencies... - Python-ის დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებები... - - - - Developer tools... - პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜áƒ¡ ხელსáƒáƒ¬áƒ§áƒáƒ”ბი... - - - - Apply %n available update(s) - %n ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜ გáƒáƒœáƒáƒ®áƒšáƒ”ბის გáƒáƒ“áƒáƒ¢áƒáƒ áƒ”ბრ- - - - No updates available - გáƒáƒœáƒáƒ®áƒšáƒ”ბები ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜ áƒáƒ áƒáƒ - - - - - - Cannot launch a new installer until the previous one has finished. - áƒáƒ®áƒáƒšáƒ˜ დáƒáƒ›áƒ§áƒ”ნებლის გáƒáƒ¨áƒ•ებრმáƒáƒ¨áƒ˜áƒœ, რáƒáƒªáƒ წინრჯერ áƒáƒ  დáƒáƒ¡áƒ áƒ£áƒšáƒ”ბულáƒ, შეუძლებელიáƒ. - - - - - - - Maintainer - წáƒáƒ›áƒ§áƒ•áƒáƒœáƒ˜ პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜ - - - - - - - Author - áƒáƒ•ტáƒáƒ áƒ˜ - - - - New Python Version Detected - áƒáƒ¦áƒ›áƒáƒ©áƒ”ნილირPython-ის áƒáƒ®áƒáƒšáƒ˜ ვერსირ- - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - რáƒáƒ’áƒáƒ áƒª ჩáƒáƒœáƒ¡, Python-ის ეს ვერსირდáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველში პირველáƒáƒ“ გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებáƒ. გნებáƒáƒ•თ იგივე áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“-დáƒáƒ§áƒ”ნებული დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების დáƒáƒ§áƒ”ნებáƒ? - - - - Processing, please wait... - მიმდინáƒáƒ áƒ”áƒáƒ‘ს დáƒáƒ›áƒ£áƒ¨áƒáƒ•ებáƒ. გთხáƒáƒ•თ, მáƒáƒ˜áƒªáƒáƒ“ეთ... - - - - - Update - გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Updating... - მიმდინáƒáƒ áƒ”áƒáƒ‘ს გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - QtNetwork-ის შემáƒáƒ¢áƒáƒœáƒ˜áƒ¡ შეცდáƒáƒ›áƒ. რáƒáƒ’áƒáƒ áƒª ჩáƒáƒœáƒ¡, ის თქვენს სისტემáƒáƒ–ე დáƒáƒ§áƒ”ნებული áƒáƒ áƒáƒ. თქვენს მáƒáƒ›áƒ¬áƒáƒ“ებელს შეიძლებრმისთვის ცáƒáƒšáƒ™áƒ” პáƒáƒ™áƒ”ტი ჰქáƒáƒœáƒ“ეს (ხშირáƒáƒ“ ჰქვირ"python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - მითითებული პáƒáƒ áƒáƒ¥áƒ¡áƒ˜áƒ¡ პáƒáƒ áƒ¢áƒ˜áƒ¡ '{}' პáƒáƒ áƒ¢áƒ˜áƒ¡ ნáƒáƒ›áƒ áƒáƒ“ გáƒáƒ áƒ“áƒáƒ¥áƒ›áƒœáƒ˜áƒ¡ შეცდáƒáƒ›áƒ - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - პáƒáƒ áƒáƒ›áƒ”ტრის შეცდáƒáƒ›áƒ: პრáƒáƒ¥áƒ¡áƒ˜áƒ¡ ურთიერთგáƒáƒ›áƒáƒ›áƒ áƒ˜áƒªáƒ®áƒáƒ•ი პáƒáƒ áƒáƒ›áƒ”ტრები. დáƒáƒ‘რუნებული იქნებრნáƒáƒ’ულისხმევი მნიშვნელáƒáƒ‘ები. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - პáƒáƒ áƒáƒ›áƒ”ტრის შეცდáƒáƒ›áƒ: მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის პრáƒáƒ¥áƒ¡áƒ˜ ჩáƒáƒ áƒ—ულიáƒ, მáƒáƒ’რáƒáƒ› მითითებული áƒáƒ áƒáƒ. გáƒáƒ›áƒáƒ§áƒ”ნებული იქნებრნáƒáƒ’ულისხმევი მნიშვნელáƒáƒ‘ები. - - - - Addon Manager: Unexpected {} response from server - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი: სერვერის მáƒáƒ£áƒšáƒáƒ“ნელი პáƒáƒ¡áƒ£áƒ®áƒ˜: {} - - - - Error with encrypted connection - დáƒáƒ¨áƒ˜áƒ¤áƒ áƒ£áƒšáƒ˜ კáƒáƒ•შირის შეცდáƒáƒ›áƒ - - - - - - Confirm remove - წáƒáƒ¨áƒšáƒ˜áƒ¡ დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბრ- - - - Are you sure you want to uninstall {}? - დáƒáƒ áƒ¬áƒ›áƒ£áƒœáƒ”ბული ბრძáƒáƒœáƒ“ებით, რáƒáƒ› გნებáƒáƒ•თ, წáƒáƒ¨áƒáƒšáƒáƒ— {}? - - - - - - Removing Addon - დáƒáƒ›áƒáƒ¢áƒ”ბის წáƒáƒ¨áƒšáƒ - - - - Removing {} - {}-ის წáƒáƒ¨áƒšáƒ - - - - - Uninstall complete - წáƒáƒ¨áƒšáƒ დáƒáƒ¡áƒ áƒ£áƒšáƒ“რ- - - - - Uninstall failed - წáƒáƒ¨áƒšáƒ˜áƒ¡ შეცდáƒáƒ›áƒ - - - - Version {version} installed on {date} - დáƒáƒ§áƒ”ნებული ვერსირ{version}. თáƒáƒ áƒ˜áƒ¦áƒ˜ {date} - - - - Version {version} installed - დáƒáƒ§áƒ”ნებული ვერსირ{version} - - - - Installed on {date} - ინსტáƒáƒšáƒáƒªáƒ˜áƒ˜áƒ¡ თáƒáƒ áƒ˜áƒ¦áƒ˜ {date} - - - - - - - Installed - დáƒáƒ§áƒ”ნებულირ- - - - Currently on branch {}, name changed to {} - áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ვáƒáƒ  ბრენჩზე {}. სáƒáƒ®áƒ”ლი შეიცვáƒáƒšáƒ მნიშვნელáƒáƒ‘áƒáƒ–ე {} - - - - Git tag '{}' checked out, no updates possible - Git ჭდით '{}' შემáƒáƒ¬áƒ›áƒ“áƒ. გáƒáƒœáƒáƒ®áƒšáƒ”ბები ხელმიუწვდáƒáƒ›áƒ”ლირ- - - - Update check in progress - მიმდინáƒáƒ áƒ”áƒáƒ‘ს გáƒáƒœáƒáƒ®áƒšáƒ”ბების შემáƒáƒ¬áƒ›áƒ”ბრ- - - - Installation location - დáƒáƒ§áƒ”ნების áƒáƒ“გილი - - - - Repository URL - რეპáƒáƒ–იტáƒáƒ áƒ˜áƒ˜áƒ¡ URL - - - - Changed to branch '{}' -- please restart to use Addon. - ბრენჩი შეიცვáƒáƒšáƒ '{}' - დáƒáƒ›áƒáƒ¢áƒ”ბის გáƒáƒ›áƒáƒ¡áƒáƒ§áƒ”ნებლáƒáƒ“ გáƒáƒ“áƒáƒ¢áƒ•ირთეთ. - - - - This Addon has been updated. Restart FreeCAD to see changes. - დáƒáƒ›áƒáƒ¢áƒ”ბრგáƒáƒœáƒáƒ®áƒšáƒ“áƒ. ცვლილებების სáƒáƒœáƒáƒ®áƒáƒ•áƒáƒ“ გáƒáƒ“áƒáƒ¢áƒ•ირთეთ FreeCAD. - - - - Disabled - გáƒáƒ—იშული - - - - Currently on branch {}, update available to version {} - áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ბრენჩირ{}. ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ გáƒáƒœáƒáƒ®áƒšáƒ”ბრვერსიáƒáƒ›áƒ“ე {} - - - - Update available to version {} - ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ გáƒáƒœáƒáƒ®áƒšáƒ”ბრვერსიáƒáƒ›áƒ“ე {} - - - - This is the latest version available - ეს áƒáƒ áƒ˜áƒ¡ უáƒáƒ®áƒšáƒ”სი ვერსირ- - - - WARNING: This addon is obsolete - გáƒáƒ¤áƒ áƒ—ხილებáƒ: ეს დáƒáƒ›áƒáƒ¢áƒ”ბრმáƒáƒ«áƒ•ელებულირ- - - - WARNING: This addon is Python 2 only - გáƒáƒ¤áƒ áƒ—ხილებáƒ: ეს დáƒáƒ›áƒáƒ¢áƒ”ბრმუშáƒáƒáƒ‘ს, მხáƒáƒšáƒáƒ“, Python v2-ზე - - - - WARNING: This addon requires FreeCAD {} - გáƒáƒ¤áƒ áƒ—ხილებáƒ: áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბáƒáƒ¡ სჭირდებრFreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - გáƒáƒ¤áƒ áƒ—ხილებáƒ: ეს დáƒáƒ›áƒáƒ¢áƒ”ბრáƒáƒ›áƒŸáƒáƒ›áƒáƒ“ დáƒáƒ§áƒ”ნებულიáƒ, მáƒáƒ’რáƒáƒ› გáƒáƒ›áƒáƒ áƒ—ული. ჩáƒáƒ¡áƒáƒ áƒ—áƒáƒ•áƒáƒ“ გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნეთ 'ჩáƒáƒ áƒ—ვის' ღილáƒáƒ™áƒ˜. - - - - This Addon will be enabled next time you restart FreeCAD. - ეს დáƒáƒ›áƒáƒ¢áƒ”ბრმხáƒáƒšáƒáƒ“ FreeCAD-ის მáƒáƒ áƒ˜áƒ’ი რესტáƒáƒ áƒ¢áƒ˜áƒ¡ შემდეგ ჩáƒáƒ˜áƒ áƒ—ვებáƒ. - - - - This Addon will be disabled next time you restart FreeCAD. - ეს დáƒáƒ›áƒáƒ¢áƒ”ბრმხáƒáƒšáƒáƒ“ FreeCAD-ის მáƒáƒ áƒ˜áƒ’ი რესტáƒáƒ áƒ¢áƒ˜áƒ¡ შემდეგ გáƒáƒ˜áƒ—იშებáƒ. - - - - - - Success - წáƒáƒ áƒ›áƒáƒ¢áƒ”ბრ- - - - Install - დáƒáƒ§áƒ”ნებრ- - - - Uninstall - წáƒáƒ¨áƒšáƒ - - - - Enable - ჩáƒáƒ áƒ—ვრ- - - - Disable - გáƒáƒ›áƒáƒ áƒ—ვრ- - - - - Check for update - გáƒáƒœáƒáƒ®áƒšáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბრ- - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - გáƒáƒ¨áƒ•ებრ- - - - Change branch... - ბრენჩის შეცვლáƒ... - - - - Return to package list - პáƒáƒ™áƒ”ტების სიáƒáƒ¡áƒ—áƒáƒœ დáƒáƒ‘რუნებრ- - - - Checking connection - შეერთების შემáƒáƒ¬áƒ›áƒ”ბრ- - - - Checking for connection to GitHub... - GitHub-მდე კáƒáƒ•შირის შემáƒáƒ¬áƒ›áƒ”ბáƒ... - - - - Connection failed - დáƒáƒ™áƒáƒ•შირებრვერ მáƒáƒ®áƒ”რხდრ- - - - Missing dependency - áƒáƒ™áƒšáƒ˜áƒ დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებრ- - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - QtNetwork-ის შემáƒáƒ¢áƒáƒœáƒ˜áƒ¡ შეცდáƒáƒ›áƒ -- დეტáƒáƒšáƒ”ბისთვის იხილეთ áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜. დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი ხელმიუწვდáƒáƒ›áƒ”ლიáƒ. - - - - Other... - For providing a license other than one listed - სხვáƒ... - - - - Select the corresponding license file in your Addon - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ შესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒ˜ ლიცენზიის ფáƒáƒ˜áƒšáƒ˜ თქვენი დáƒáƒ›áƒáƒ¢áƒ”ბისთვის - - - - Location for new license file - áƒáƒ®áƒáƒšáƒ˜ ლიცენზიის ფáƒáƒ˜áƒšáƒ˜áƒ¡ მდებáƒáƒ áƒ”áƒáƒ‘რ- - - - Received {} response code from server - სერვერიდáƒáƒœ მიღებულირპáƒáƒ¡áƒ£áƒ®áƒ˜áƒ¡ კáƒáƒ“ი {} - - - - Failed to install macro {} - მáƒáƒ™áƒ áƒ {} დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - Failed to create installation manifest file: - - დáƒáƒ§áƒ”ნების მáƒáƒœáƒ˜áƒ¤áƒ”სტის ფáƒáƒ˜áƒšáƒ˜áƒ¡ შექმნრჩáƒáƒ•áƒáƒ áƒ“áƒ: - - - - - Unrecognized content kind '{}' - შემცველáƒáƒ‘ის უცნáƒáƒ‘ი ტიპი '{}' - - - - Unable to locate icon at {} - {}-ზე ხáƒáƒ¢áƒ£áƒšáƒ˜áƒ¡ პáƒáƒ•ნის შეცდáƒáƒ›áƒ - - - - Select an icon file for this content item - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ ხáƒáƒ¢áƒ£áƒšáƒáƒ¡ ფáƒáƒ˜áƒšáƒ˜ áƒáƒ› შემცველáƒáƒ‘ის ელემენტისთვის - - - - - - {} is not a subdirectory of {} - {} -ი {}-ის ქვესáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ეს áƒáƒ  წáƒáƒ áƒ›áƒáƒáƒ“გენს - - - - Select the subdirectory for this content item - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ áƒáƒ› შემცველáƒáƒ‘ის ელემენტის ქვესáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ე - - - - Automatic - áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜ - - - - - Workbench - სáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდრ- - - - Addon - დáƒáƒ›áƒáƒ¢áƒ”ბრ- - - - Python - Python - - - - Yes - დიáƒáƒ® - - - - Internal Workbench - შიდრსáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდრ- - - - External Addon - გáƒáƒ áƒ” დáƒáƒ›áƒáƒ¢áƒ”ბრ- - - - Python Package - Python-ის პáƒáƒ™áƒ”ტი - - - - - Other... - სხვáƒ... - - - - Too many to list - მეტისმეტáƒáƒ“ ბევრ ელემენტს áƒáƒ›áƒáƒ¢áƒ”ბთ სიáƒáƒ¨áƒ˜ - - - - - - - - - Missing Requirement - áƒáƒ áƒáƒ¡áƒáƒ™áƒ›áƒáƒ áƒ˜áƒ¡áƒ˜ პირáƒáƒ‘ები - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - დáƒáƒ›áƒáƒ¢áƒ”ბრ'{}'-ს ესáƒáƒ­áƒ˜áƒ áƒáƒ”ბრ'{}', რáƒáƒ›áƒ”ლიც FreeCAD-ის თქვენს ვერსიáƒáƒ¨áƒ˜ ხელმიუწვდáƒáƒ›áƒ”ლიáƒ. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - დáƒáƒ›áƒáƒ¢áƒ”ბრ'{}'-ს ესáƒáƒ­áƒ˜áƒ áƒáƒ”ბრშემდეგი სáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდები, რáƒáƒ›áƒ”ლიც FreeCAD-ის თქვენს ვერსიáƒáƒ¨áƒ˜ ხელმიუწვდáƒáƒ›áƒ”ლიáƒ: - - - - Press OK to install anyway. - დáƒáƒáƒ¬áƒ”ქით "დიáƒáƒ®"-ს ნებისმიერ შემთხვევáƒáƒ¨áƒ˜ დáƒáƒ¡áƒáƒ§áƒ”ნებლáƒáƒ“. - - - - - Incompatible Python version - Python-ის შეუთáƒáƒ•სებელი ვერსირ- - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბáƒáƒ¡ სჭირდებრPython-ის პáƒáƒ™áƒ”ტები, რáƒáƒ›áƒšáƒ”ბიც დáƒáƒ§áƒ”ნებული áƒáƒ áƒáƒ დრმáƒáƒ—ი დáƒáƒ§áƒ”ნებრáƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“áƒáƒª შეუძლებელიáƒ. áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბის გáƒáƒ›áƒáƒ¡áƒáƒ§áƒ”ნებლáƒáƒ“ სáƒáƒ­áƒ˜áƒ áƒáƒ ხელით დáƒáƒáƒ§áƒ”ნáƒáƒ— Python-ის შემდეგი პáƒáƒ™áƒ”ტები: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - ეს დáƒáƒ›áƒáƒ¢áƒ”ბრ(áƒáƒœ მისი რáƒáƒ›áƒ”ლიმე დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებáƒ) Python {}.{}-ს მáƒáƒ˜áƒ—ხáƒáƒ•ს. თქვენ კი {}.{} გáƒáƒ¥áƒ•თ. დáƒáƒ§áƒ”ნებრგáƒáƒ£áƒ¥áƒ›áƒ“áƒ. - - - - Optional dependency on {} ignored because it is not in the allow-list - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრდáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებრ{} იგნáƒáƒ áƒ˜áƒ áƒ”ბულიáƒ. ის დáƒáƒ¨áƒ•ებულ სიáƒáƒ¨áƒ˜ áƒáƒ áƒáƒ - - - - - Installing dependencies - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების დáƒáƒ§áƒ”ნებრ- - - - - Cannot execute Python - Python-ის გáƒáƒ¨áƒ•ების შეცდáƒáƒ›áƒ - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Python-ის გáƒáƒ›áƒ¨áƒ•ები ფáƒáƒ˜áƒšáƒ˜áƒ¡ პáƒáƒ•ნრშეუძლებელიáƒ. დáƒáƒ áƒ¬áƒ›áƒ£áƒœáƒ“ით, რáƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის პáƒáƒ áƒáƒ›áƒ”ტრებში ბილიკი Python-ის გáƒáƒ›áƒ¨áƒ•ებ ფáƒáƒ˜áƒšáƒ”ბáƒáƒ›áƒ“ე სწáƒáƒ áƒáƒ“áƒáƒ დáƒáƒ§áƒ”ნებული. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ. მáƒáƒ˜áƒœáƒª დáƒáƒ•áƒáƒ§áƒ”ნრ{}? - - - - - Cannot execute pip - Pip-ის გáƒáƒ¨áƒ•ების შეცდáƒáƒ›áƒ - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Pip-ის გáƒáƒ¨áƒ•ების შეცდáƒáƒ›áƒ. შეიძლებრის Python-ის თქვენს დისტრიბუტივს უბრáƒáƒšáƒáƒ“ áƒáƒ™áƒšáƒ˜áƒ. დáƒáƒ áƒ¬áƒ›áƒ£áƒœáƒ“ით, რáƒáƒ› pip-ი áƒáƒ§áƒ”ნირდრთáƒáƒ•იდáƒáƒœ სცáƒáƒ“ეთ. ბრძáƒáƒœáƒ”ბáƒ, რáƒáƒ›áƒ”ლმáƒáƒª შეცდáƒáƒ›áƒ დáƒáƒáƒ‘რუნáƒ: - - - - - Continue with installation of {} anyway? - გნებáƒáƒ•თ, მáƒáƒ˜áƒœáƒª გáƒáƒáƒ’რძელáƒáƒ— {}-ის დáƒáƒ§áƒ”ნებáƒ? - - - - - Package installation failed - პáƒáƒ™áƒ”ტის დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - See Report View for detailed failure log. - შეცდáƒáƒ›áƒ˜áƒ¡ შესáƒáƒ®áƒ”ბ დეტáƒáƒšáƒ£áƒ áƒ˜ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡áƒ—ვის იხილეთ áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ ხედი. - - - - Installing Addon - დáƒáƒ›áƒáƒ¢áƒ”ბის დáƒáƒ§áƒ”ნებრ- - - - Installing FreeCAD Addon '{}' - მიმდინáƒáƒ áƒ”áƒáƒ‘ს FreeCAD-ის დáƒáƒ›áƒáƒ¢áƒ”ბის დáƒáƒ§áƒ”ნებáƒ: '{}' - - - - Cancelling - გáƒáƒ£áƒ¥áƒ›áƒ”ბრ- - - - Cancelling installation of '{}' - '{}'-ის დáƒáƒ§áƒ”ნების შეწყვეტáƒ; - - - - {} was installed successfully - {} -ის დáƒáƒ§áƒ”ნებრწáƒáƒ áƒ›áƒáƒ¢áƒ”ბულირ- - - - - Installation Failed - დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - Failed to install {} - {}-ის დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - - Create new toolbar - ხელსáƒáƒ¬áƒ§áƒáƒ”ბის áƒáƒ®áƒáƒšáƒ˜ ზáƒáƒšáƒ˜áƒ¡ შექმნრ- - - - - A macro installed with the FreeCAD Addon Manager - FreeCAD-ის დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველით დáƒáƒ§áƒ”ნებული მáƒáƒ™áƒ áƒ - - - - - Run - Indicates a macro that can be 'run' - გáƒáƒ¨áƒ•ებრ- - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - GitHub-დáƒáƒœ მáƒáƒœáƒáƒªáƒ”მების წáƒáƒ™áƒ˜áƒ—ხვრშეუძლებელიáƒ. შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ ინტერნეტთáƒáƒœ შეერთებისრდრპრáƒáƒ¥áƒ¡áƒ˜áƒ¡ პáƒáƒ áƒáƒ›áƒ”ტრებ დრთáƒáƒ•იდáƒáƒœ სცáƒáƒ“ეთ. - - - - XML failure while reading metadata from file {} - XML-ის შეცდáƒáƒ›áƒ მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მების კითხვისáƒáƒ¡ ფáƒáƒ˜áƒšáƒ˜áƒ“áƒáƒœ {} - - - - Invalid metadata in file {} - áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მები ფáƒáƒ˜áƒšáƒ¨áƒ˜ {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - გáƒáƒ¤áƒ áƒ—ხილებáƒ: package.xml-ის მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მებში მითითებული ვილიკი áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ გáƒáƒ›áƒáƒ—ხáƒáƒ•ილი ბრენჩის ბილიკს áƒáƒ  ემთხვევáƒ. - - - - Name - სáƒáƒ®áƒ”ლი - - - - Class - კლáƒáƒ¡áƒ˜ - - - - Description - áƒáƒ¦áƒ¬áƒ”რრ- - - - Subdirectory - ქვესáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ე - - - - Files - ფáƒáƒ˜áƒšáƒ”ბი - - - - Select the folder containing your Addon - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ თქვენი დáƒáƒ›áƒáƒ¢áƒ”ბის შემცველი სáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ე - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Vermin áƒáƒ¦áƒ›áƒáƒ©áƒ”ნილი áƒáƒ áƒáƒ. áƒáƒžáƒ”რáƒáƒªáƒ˜áƒ გáƒáƒ£áƒ¥áƒ›áƒ“ებáƒ. - - - - Scanning Addon for Python version compatibility - დáƒáƒ›áƒáƒ¢áƒ”ბის სკáƒáƒœáƒ˜áƒ áƒ”ბრPython-ის ვერსიის თáƒáƒ•სებáƒáƒ“áƒáƒ‘áƒáƒ–ე - - - - Minimum Python Version Detected - áƒáƒ¦áƒ›áƒáƒ©áƒ”ნილირPython-ის მინიმáƒáƒšáƒ£áƒ áƒ˜ ვერსირ- - - - Vermin auto-detected a required version of Python 3.{} - Vermin-მრáƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ იპáƒáƒ•რსáƒáƒ­áƒ˜áƒ áƒ ვერსირPython 3.{} - - - - Install Vermin? - დáƒáƒ•áƒáƒ§áƒ”ნრVermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Python-ის ვერსიის áƒáƒ› დáƒáƒ›áƒáƒ¢áƒ”ბისთვის áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜ áƒáƒ›áƒáƒªáƒœáƒáƒ‘რVermin-ს (https://pypi.org/project/vermin/) მáƒáƒ˜áƒ—ხáƒáƒ•ს. დáƒáƒ•áƒáƒ§áƒ”ნáƒ? - - - - Attempting to install Vermin from PyPi - Vermin-ის PyPi-დáƒáƒœ დáƒáƒ§áƒ”ნების მცდელáƒáƒ‘რ- - - - - Installation failed - დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Vermn-ის დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - მეტი დეტáƒáƒšáƒ”ბისთვის იხილეთ áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ ხედი. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - დáƒáƒ§áƒ”ნების შემდეგ Vermin-ის შემáƒáƒ¢áƒáƒœáƒ˜áƒ¡ შეცდáƒáƒ›áƒ - დáƒáƒ›áƒáƒ¢áƒ”ბის სკáƒáƒœáƒ˜áƒ áƒ”ბრშეუძლებელიáƒ. - - - - Select an icon file for this package - áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ áƒáƒ› პáƒáƒ™áƒ”ტის ხáƒáƒ¢áƒ£áƒšáƒ - - - - Filter is valid - ფილტრი სწáƒáƒ áƒ˜áƒ - - - - Filter regular expression is invalid - ფილტრის რეგულáƒáƒ áƒ£áƒšáƒ˜ გáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ”ბრáƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜áƒ - - - - Search... - ძებნáƒ... - - - - Click for details about package {} - პáƒáƒ™áƒ”ტის დეტáƒáƒšáƒ”ბის გáƒáƒ¡áƒáƒ’ებáƒáƒ“ დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ {} - - - - Click for details about workbench {} - სáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდის დეტáƒáƒšáƒ”ბის გáƒáƒ¡áƒáƒ’ებáƒáƒ“ დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ {} - - - - Click for details about macro {} - მáƒáƒ™áƒ áƒáƒ¡ დეტáƒáƒšáƒ”ბის სáƒáƒœáƒáƒ®áƒáƒ•áƒáƒ“ დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ {} - - - - Maintainers: - პრáƒáƒ”ქტის ლიდერები: - - - - Tags - ჭდეები - - - - {} ★ on GitHub - {} ★ GitHub-ზე - - - - No ★, or not on GitHub - ★-ის გáƒáƒ áƒ”შე, áƒáƒœ GitHub-ზე áƒáƒ áƒáƒ - - - - Created - შექმნლირ- - - - Updated - გáƒáƒœáƒáƒ®áƒšáƒ”ბულირ- - - - Score: - ქულáƒ: - - - - - Up-to-date - გáƒáƒœáƒáƒ®áƒšáƒ”ბულირ- - - - - - - - Update available - გáƒáƒœáƒáƒ®áƒšáƒ”ბრხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜áƒ - - - - - Pending restart - რესტáƒáƒ áƒ¢áƒ˜áƒ¡ მáƒáƒšáƒáƒ“ინი - - - - - DISABLED - გáƒáƒ—იშულირ- - - - Installed version - დáƒáƒ§áƒ”ნებული ვერსირ- - - - Unknown version - უცნáƒáƒ‘ი ვერსირ- - - - Installed on - დáƒáƒ§áƒ”ნების დრრ- - - - Available version - ხელმისáƒáƒ¬áƒ•დáƒáƒ›áƒ˜ ვერსირ- - - - Filter by... - ფილტრის პირáƒáƒ‘áƒ... - - - - Addon Type - დáƒáƒ›áƒáƒ¢áƒ”ბის ტიპი - - - - - Any - ნებისმიერი - - - - Macro - მáƒáƒ™áƒ áƒ - - - - Preference Pack - პáƒáƒ áƒáƒ›áƒ”ტრების პáƒáƒ™áƒ”ტი - - - - Installation Status - დáƒáƒ§áƒ”ნების სტáƒáƒ¢áƒ£áƒ¡áƒ˜ - - - - Not installed - áƒáƒ  áƒáƒ áƒ˜áƒ¡ დáƒáƒ§áƒ”ნებული - - - - Filter - ფილტრი - - - - DANGER: Developer feature - სáƒáƒ¨áƒ˜áƒ¨áƒ áƒáƒ”ბáƒ: პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜áƒ¡áƒ—ვის სáƒáƒ­áƒ˜áƒ áƒ თვისებრ- - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - სáƒáƒ¨áƒ˜áƒ¨áƒ áƒáƒ”ბáƒ: ბრენჩებს შáƒáƒ áƒ˜áƒ¡ გáƒáƒ“áƒáƒ áƒ—ვრგáƒáƒœáƒ™áƒ£áƒ—ვნილირპრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ”ბისრდრბეტრტესტერებისთვის დრშეიძლებრყველáƒáƒ¤áƒ”რი გáƒáƒ¤áƒ£áƒ­áƒ”ბული, áƒáƒ áƒáƒ—áƒáƒ•სებáƒáƒ“ი დáƒáƒ™áƒ£áƒ›áƒ”ნტებით დრáƒáƒ áƒáƒ¡áƒ¢áƒáƒ‘ილურáƒáƒ‘ით áƒáƒœ/დრსáƒáƒ›áƒ§áƒáƒ áƒáƒ¡ გáƒáƒ“áƒáƒªáƒ®áƒ”ლებით. დáƒáƒ áƒ¬áƒ›áƒ£áƒœáƒ”ბული ბრძáƒáƒœáƒ“ებით, რáƒáƒ› გáƒáƒ’რძელებრგნებáƒáƒ•თ? - - - - There are local changes - გáƒáƒ¥áƒ•თ áƒáƒ“გილáƒáƒ‘რივი ცვლილებები - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - გáƒáƒ¤áƒ áƒ—ხილებáƒ: áƒáƒ› რეპáƒáƒ¡ დáƒáƒ£áƒ™áƒáƒ›áƒ˜áƒ¢áƒ”ბელი ლáƒáƒ™áƒáƒšáƒ£áƒ áƒ˜ ცვლილებები გáƒáƒáƒ©áƒœáƒ˜áƒ. დáƒáƒ áƒ¬áƒ›áƒ£áƒœáƒ”ბული ბრძáƒáƒœáƒ“ებით, რáƒáƒ› გნებáƒáƒ•თ შეცვáƒáƒšáƒáƒ— ბრენჩი (დრთáƒáƒœ წáƒáƒ˜áƒ§áƒáƒšáƒáƒ— თქვენი ცვლილებები)? - - - - Local - Table header for local git ref name - ლáƒáƒ™áƒáƒšáƒ£áƒ áƒ˜ - - - - Remote tracking - Table header for git remote tracking branch name - დáƒáƒ¨áƒáƒ áƒ”ბული ტრეკინგი - - - - Last Updated - Table header for git update date - ბáƒáƒšáƒáƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბული - - - - Installation of Python package {} failed - Python-ის პáƒáƒ™áƒ”ტის {} დáƒáƒ§áƒ”ნებრშეუძლებელირ- - - - Installation of optional package failed - áƒáƒ áƒáƒ¡áƒáƒ•áƒáƒšáƒ“ებულრპáƒáƒ™áƒ”ტის დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - Installing required dependency {} - áƒáƒ£áƒªáƒ˜áƒšáƒ”ბელი დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულების დáƒáƒ§áƒ”ნებáƒ: {} - - - - Installation of Addon {} failed - დáƒáƒ›áƒáƒ¢áƒ”ბის "{}" დáƒáƒ§áƒ”ნების შეცდáƒáƒ›áƒ - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - {} ფáƒáƒ˜áƒšáƒ˜áƒ¡ გáƒáƒ¨áƒ˜áƒ¤áƒ•რის შეცდáƒáƒ›áƒ დáƒáƒ›áƒáƒ¢áƒ”ბისთვის '{}' - - - - Any dependency information in this file will be ignored - áƒáƒ› ფáƒáƒ˜áƒšáƒ¨áƒ˜ áƒáƒ áƒ¡áƒ”ბული ნებისმიერი დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებრიგნáƒáƒ áƒ˜áƒ áƒ”ბული იქნებრ- - - - Unable to open macro wiki page at {} - მáƒáƒ™áƒ áƒáƒ”ბის ვიკის გვერდის {} გáƒáƒ®áƒ¡áƒœáƒ˜áƒ¡ შეცდáƒáƒ›áƒ - - - - Unable to fetch the code of this macro. - მáƒáƒ™áƒ áƒáƒ¡ კáƒáƒ“ის მáƒáƒžáƒáƒ•ებრშეუძლებელიáƒ. - - - - Unable to retrieve a description from the wiki for macro {} - ვიკიდáƒáƒœ მáƒáƒ™áƒ áƒáƒ¡ {} áƒáƒ¦áƒ¬áƒ”რის მიღებრშეუძლებელირ- - - - Unable to open macro code URL {} - მáƒáƒ™áƒ áƒáƒ¡ კáƒáƒ“ის URL-ის ({}) გáƒáƒ®áƒ¡áƒœáƒ შეუძლებელირ- - - - Unable to fetch macro-specified file {} from {} - შეცდáƒáƒ›áƒ მáƒáƒ™áƒ áƒáƒ¡áƒ—ვის-მითითებული ფáƒáƒ˜áƒšáƒ˜áƒ¡ {} {}-დáƒáƒœ გáƒáƒ›áƒáƒ—ხáƒáƒ•ისáƒáƒ¡ - - - - Could not locate macro-specified file {} (expected at {}) - მáƒáƒ™áƒ áƒáƒ¡ მიერ მითითებული ფáƒáƒ˜áƒšáƒ˜áƒ¡ {} პáƒáƒ•ნრშეუძლებელირ(ველáƒáƒ“ი მისáƒáƒ›áƒáƒ áƒ—ზე {}) - - - - {}: Unrecognized internal workbench '{}' - {}: უცნáƒáƒ‘ი შიდრსáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒ '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - დáƒáƒ›áƒáƒ¢áƒ”ბის პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜áƒ¡ გáƒáƒ¤áƒ áƒ—ხილებáƒ: რეპáƒáƒ¡ URL, რáƒáƒ›áƒ”ლიც დáƒáƒ§áƒ”ნებულირდáƒáƒ›áƒáƒ¢áƒ”ბის {} ({}) package.xml ფáƒáƒ˜áƒšáƒ¨áƒ˜, áƒáƒ  ემთხვევრURL-ს, სáƒáƒ˜áƒ“áƒáƒœáƒáƒª ის გáƒáƒ“მáƒáƒ•წერეთ ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - დáƒáƒ›áƒáƒ¢áƒ”ბის პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡áƒ¢áƒ˜áƒ¡ გáƒáƒ¤áƒ áƒ—ხილებáƒ: რეპáƒáƒ¡ ბრენჩი, რáƒáƒ›áƒ”ლიც დáƒáƒ§áƒ”ნებულირდáƒáƒ›áƒáƒ¢áƒ”ბის {} ({}) package.xml ფáƒáƒ˜áƒšáƒ¨áƒ˜, áƒáƒ  ემთხვევრბრენჩს, სáƒáƒ˜áƒ“áƒáƒœáƒáƒª ის გáƒáƒ“მáƒáƒ•წერეთ ({}) - - - - - Got an error when trying to import {} - შეცდáƒáƒ›áƒ {}-ის შემáƒáƒ¢áƒáƒœáƒ˜áƒ¡ მცდელáƒáƒ‘ისáƒáƒ¡ - - - - An unknown error occurred - უცნáƒáƒ‘ი შეცდáƒáƒ›áƒ - - - - Could not find addon {} to remove it. - წáƒáƒ¡áƒáƒ¨áƒšáƒ”ლáƒáƒ“ დáƒáƒ›áƒáƒ¢áƒ”ბრ{} ვერ ვიპáƒáƒ•ე. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - დáƒáƒ›áƒáƒ¢áƒ”ბის uninstall.py სკრიპტის შესრულებრვერ მáƒáƒ®áƒ”რხდáƒ. ვუშვებ წáƒáƒ¨áƒšáƒ˜áƒ¡ პრáƒáƒªáƒ”სს... - - - - Removed extra installed file {} - დáƒáƒ›áƒáƒ¢áƒ”ბითი დáƒáƒ§áƒ”ნებული ფáƒáƒ˜áƒšáƒ˜ {} წáƒáƒ˜áƒ¨áƒáƒšáƒ - - - - Error while trying to remove extra installed file {} - შეცდáƒáƒ›áƒ დáƒáƒ›áƒáƒ¢áƒ”ბითი დáƒáƒ§áƒ”ნებული ფáƒáƒ˜áƒšáƒ˜áƒ¡ {} წáƒáƒ¨áƒšáƒ˜áƒ¡ მცდელáƒáƒ‘ისáƒáƒ¡ - - - - Error while trying to remove macro file {}: - შეცდáƒáƒ›áƒ მáƒáƒ™áƒ áƒáƒ¡ ფáƒáƒ˜áƒšáƒ˜áƒ¡ {} წáƒáƒ¨áƒšáƒ˜áƒ¡áƒáƒ¡: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - GitHub-თáƒáƒœ მიერთების შეცდáƒáƒ›áƒ. შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ შეერთებისრდრპრáƒáƒ¥áƒ¡áƒ˜áƒ¡ პáƒáƒ áƒáƒ›áƒ”ტრები. - - - - WARNING: Duplicate addon {} ignored - გáƒáƒ¤áƒ áƒ—ხილებáƒ: დუბლიკáƒáƒ¢áƒ˜ გáƒáƒ¤áƒáƒ áƒ—áƒáƒ”ბრ{} გáƒáƒ›áƒáƒ¢áƒáƒ•ებულირ- - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - შეცდáƒáƒ›áƒ მáƒáƒ™áƒ áƒáƒ”ბის GitHub-დáƒáƒœ გáƒáƒœáƒáƒ®áƒšáƒ”ბისáƒáƒ¡. ვცდი სუფთáƒáƒ“ გáƒáƒ›áƒáƒ•ითხáƒáƒ•áƒ... - - - - Attempting to do a clean checkout... - სუფთრგáƒáƒ›áƒáƒ—ხáƒáƒ•ის მცდელáƒáƒ‘áƒ... - - - - Clean checkout succeeded - სუფთრგáƒáƒ›áƒáƒ—ხáƒáƒ•რწáƒáƒ áƒ›áƒáƒ¢áƒ”ბულირ- - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - GitHub-დáƒáƒœ მáƒáƒ™áƒ áƒáƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბის შეცდáƒáƒ›áƒ -- სცáƒáƒ“ეთ დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველის ქეში გáƒáƒ¬áƒ›áƒ˜áƒœáƒ“áƒáƒ—. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - ვიკისთáƒáƒœ დáƒáƒ™áƒáƒ•შირების შეცდáƒáƒ›áƒ. FreeCAD-ს áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ვკიდáƒáƒœ მáƒáƒ™áƒ áƒáƒ”ბის სიის მიღებრáƒáƒ  შეუძლირ- - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მების {name}-დáƒáƒœ კითხვის შეცდáƒáƒ›áƒ - - - - Failed to fetch code for macro '{name}' - მáƒáƒ™áƒ áƒáƒ¡ '{name}' კáƒáƒ“ის გáƒáƒ›áƒáƒ—ხáƒáƒ•ის შეცდáƒáƒ›áƒ; - - - - Addon Manager: a worker process failed to complete while fetching {name} - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი: დáƒáƒ›áƒ®áƒ›áƒáƒ áƒ” პრáƒáƒªáƒ”სის შეცდáƒáƒ›áƒ {name}-ის გáƒáƒ“მáƒáƒ¬áƒ”რისáƒáƒ¡ - - - - Out of {num_macros} macros, {num_failed} timed out while processing - {num_macros} მáƒáƒ™áƒ áƒáƒ“áƒáƒœ {num_failed}-ის დáƒáƒ›áƒ£áƒ¨áƒáƒ•ების ვáƒáƒ“რგáƒáƒ•იდრ- - - - Addon Manager: a worker process failed to halt ({name}) - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი: დáƒáƒ›áƒ®áƒ›áƒáƒ áƒ” პრáƒáƒªáƒ”სის შეჩერების შეცდáƒáƒ›áƒ ({name}) - - - - Timeout while fetching metadata for macro {} - მáƒáƒ™áƒ áƒáƒ¡ {} მეტáƒáƒ›áƒáƒœáƒáƒªáƒ”მების გáƒáƒ›áƒáƒ—ხáƒáƒ•ნის ვáƒáƒ“რგáƒáƒ•იდრ- - - - Failed to kill process for macro {}! - - მáƒáƒ™áƒ áƒáƒ¡ {} პრáƒáƒªáƒ”სის მáƒáƒ™áƒ•ლრშეუძლებელიáƒ! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - {}-დáƒáƒœ დáƒáƒ›áƒáƒ¢áƒ”ბის სტáƒáƒ¢áƒ˜áƒ¡áƒ¢áƒ˜áƒ™áƒ˜áƒ¡ მიღებრჩáƒáƒ•áƒáƒ áƒ“რ-- სწáƒáƒ áƒ˜, მხáƒáƒšáƒáƒ“, áƒáƒœáƒ‘áƒáƒœáƒ˜áƒ— დáƒáƒšáƒáƒ’ებრიქნებრ- - - - Failed to get Addon score from '{}' -- sorting by score will fail - - '{}'-დáƒáƒœ დáƒáƒ›áƒáƒ¢áƒ”ბის ქულების გáƒáƒ›áƒáƒ—ხáƒáƒ•ნრჩáƒáƒ•áƒáƒ áƒ“რ-- ქულებით დáƒáƒšáƒáƒ’ებრჩáƒáƒ•áƒáƒ áƒ“ებრ- - - - Repository URL - Preferences header for custom repositories - რეპáƒáƒ–იტáƒáƒ áƒ˜áƒ˜áƒ¡ URL - - - - Branch name - Preferences header for custom repositories - ბრენჩის სáƒáƒ®áƒ”ლი - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ სáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ის მáƒáƒ áƒ¥áƒáƒ¤áƒ˜ დრთáƒáƒ•იდáƒáƒœ კლáƒáƒœáƒ˜áƒ áƒ”ბრ- - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git-ის ბრენჩის სáƒáƒ®áƒ”ლის გáƒáƒ“áƒáƒ áƒ¥áƒ›áƒ”ვრჩáƒáƒ•áƒáƒ áƒ“რშემდეგი შეტყáƒáƒ‘ინებით: - - - - Installing - დáƒáƒ§áƒ”ნებრ- - - - Succeeded - წáƒáƒ áƒ›áƒáƒ¢áƒ”ბულირ- - - - Failed - შეცდáƒáƒ›áƒ - - - - Update was cancelled - გáƒáƒœáƒáƒ®áƒšáƒ”ბრგáƒáƒ£áƒ¥áƒ›áƒ“რ- - - - some addons may have been updated - ზáƒáƒ’იერთი გáƒáƒœáƒáƒ®áƒšáƒ”ბ შეიძლებრგáƒáƒœáƒáƒ®áƒšáƒ“რ- - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - იტვირთებრინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ {}-სთვის FreeCAD-ის მáƒáƒ™áƒ áƒáƒ¡ რეცეპტების ვიკიდáƒáƒœ... - - - - Loading page for {} from {}... - იტვირთებრგვერდი {} {}-დáƒáƒœ... - - - - Failed to download data from {} -- received response code {}. - {}-დáƒáƒœ მáƒáƒœáƒáƒªáƒ”მების გáƒáƒ“მáƒáƒ¬áƒ”რრჩáƒáƒ•áƒáƒ áƒ“რ- მივიღე პáƒáƒ¡áƒ£áƒ®áƒ˜áƒ¡ კáƒáƒ“ი {}. - - - - Composite view - კáƒáƒ›áƒžáƒáƒ–იტური ხედი - - - - Expanded view - გáƒáƒ¤áƒáƒ áƒ—áƒáƒ”ბული ხედი - - - - Compact view - კáƒáƒ›áƒžáƒáƒ¥áƒ¢áƒ£áƒ áƒ˜ ხედი - - - - Alphabetical - Sort order - áƒáƒœáƒ‘áƒáƒœáƒ˜áƒ¡ მიხედვით - - - - Last Updated - Sort order - ბáƒáƒšáƒáƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბული - - - - Date Created - Sort order - შექმნის თáƒáƒ áƒ˜áƒ¦áƒ˜ - - - - GitHub Stars - Sort order - GitHub-ის ვáƒáƒ áƒ¡áƒ™áƒ•ლáƒáƒ•ები - - - - Score - Sort order - ქულრ- - - - Std_AddonMgr - - - &Addon manager - &დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი - - - - Manage external workbenches, macros, and preference packs - მáƒáƒ áƒ—ეთ გáƒáƒ áƒ” სáƒáƒ›áƒ£áƒ¨áƒáƒ მáƒáƒ’იდები, მáƒáƒ™áƒ áƒáƒ”ბი დრპáƒáƒ áƒáƒ›áƒ”ტრების ნáƒáƒ™áƒ áƒ”ბები - - - - AddonInstaller - - - Finished removing {} - {}-ის წáƒáƒ¨áƒšáƒ დáƒáƒ¡áƒ áƒ£áƒšáƒ“რ- - - - Failed to remove some files - ზáƒáƒ’იერთი ფáƒáƒ˜áƒšáƒ˜áƒ¡ წáƒáƒ¨áƒšáƒ შეუძლებელირ- - - - Addons installer - - - Finished updating the following addons - დáƒáƒ¡áƒ áƒ£áƒšáƒ“რშემდეგი დáƒáƒ›áƒáƒ¢áƒ”ბების გáƒáƒœáƒáƒ®áƒšáƒ”ბრ- - - - Workbench - - - Auto-Created Macro Toolbar - áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ შექმნილი მáƒáƒ™áƒ áƒáƒ”ბის პáƒáƒœáƒ”ლი - - - - QObject - - - Addon Manager - დáƒáƒ›áƒáƒ¢áƒ”ბების მმáƒáƒ áƒ—ველი - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_kab.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_kab.qm deleted file mode 100644 index df0fe19f9e50fbe716aaac83b3bc815915dc73a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13467 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_kab.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_kab.ts deleted file mode 100644 index 89072874b5..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_kab.ts +++ /dev/null @@ -1,427 +0,0 @@ - - - - - AddonInstaller - - - Installed location - Installed location - - - - AddonsInstaller - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description for this macro. - Unable to retrieve a description for this macro. - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - - - - Checking for updates... - Checking for updates... - - - - Apply - Apply - - - - update(s) - update(s) - - - - No update available - No update available - - - - Macro successfully installed. The macro is now available from the Macros dialog. - Macro successfully installed. The macro is now available from the Macros dialog. - - - - Unable to install - Unable to install - - - - Addon successfully removed. Please restart FreeCAD - Addon successfully removed. Please restart FreeCAD - - - - Unable to remove this addon - Unable to remove this addon - - - - Macro successfully removed. - Macro successfully removed. - - - - Macro could not be removed. - Macro could not be removed. - - - - Unable to download addon list. - Unable to download addon list. - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Outdated GitPython detected, consider upgrading with pip. - Outdated GitPython detected, consider upgrading with pip. - - - - List of macros successfully retrieved. - List of macros successfully retrieved. - - - - Retrieving description... - Retrieving description... - - - - Retrieving info from - Retrieving info from - - - - An update is available for this addon. - An update is available for this addon. - - - - This addon is already installed. - This addon is already installed. - - - - Retrieving info from git - Retrieving info from git - - - - Retrieving info from wiki - Retrieving info from wiki - - - - GitPython not found. Using standard download instead. - GitPython not found. Using standard download instead. - - - - Your version of python doesn't appear to support ZIP files. Unable to proceed. - Your version of python doesn't appear to support ZIP files. Unable to proceed. - - - - Workbench successfully installed. Please restart FreeCAD to apply the changes. - Workbench successfully installed. Please restart FreeCAD to apply the changes. - - - - Missing workbench - Missing workbench - - - - Missing python module - Missing python module - - - - Missing optional python module (doesn't prevent installing) - Missing optional python module (doesn't prevent installing) - - - - Some errors were found that prevent to install this workbench - Some errors were found that prevent to install this workbench - - - - Please install the missing components first. - Please install the missing components first. - - - - Error: Unable to download - Error: Unable to download - - - - Successfully installed - Successfully installed - - - - GitPython not installed! Cannot retrieve macros from git - GitPython not installed! Cannot retrieve macros from git - - - - Installed - Installed - - - - Update available - Update available - - - - Restart required - Restart required - - - - This macro is already installed. - This macro is already installed. - - - - A macro has been installed and is available under Macro -> Macros menu - A macro has been installed and is available under Macro -> Macros menu - - - - This addon is marked as obsolete - This addon is marked as obsolete - - - - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - - - - Error: Unable to locate zip from - Error: Unable to locate zip from - - - - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - - - - This addon is marked as Python 2 Only - This addon is marked as Python 2 Only - - - - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - - - - User requested updating a Python 2 workbench on a system running Python 3 - - User requested updating a Python 2 workbench on a system running Python 3 - - - - - Workbench successfully updated. Please restart FreeCAD to apply the changes. - Workbench successfully updated. Please restart FreeCAD to apply the changes. - - - - User requested installing a Python 2 workbench on a system running Python 3 - - User requested installing a Python 2 workbench on a system running Python 3 - - - - - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - - - - Raw markdown displayed - Raw markdown displayed - - - - Python Markdown library is missing. - Python Markdown library is missing. - - - - Dialog - - - Workbenches - Ateliers - - - - Macros - Macros - - - - Execute - Lancer - - - - Downloading info... - Downloading info... - - - - Update all - Update all - - - - Executes the selected macro, if installed - Executes the selected macro, if installed - - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Installs or updates the selected macro or workbench - Installs or updates the selected macro or workbench - - - - Download and apply all available updates - Download and apply all available updates - - - - Custom repositories (one per line): - Custom repositories (one per line): - - - - Sets configuration options for the Addon Manager - Sets configuration options for the Addon Manager - - - - Configure... - Configure... - - - - Addon manager options - Addon manager options - - - - Uninstall selected - Uninstall selected - - - - Install/update selected - Install/update selected - - - - Close - Fermer - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires GitPython) - Automatically check for updates at start (requires GitPython) - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User defined proxy : - User defined proxy : - - - - Addon Manager - Addon Manager - - - - Close the Addon Manager - Close the Addon Manager - - - - You can use this window to specify additional addon repositories -to be scanned for available addons - You can use this window to specify additional addon repositories -to be scanned for available addons - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches and macros - Manage external workbenches and macros - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ko.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ko.qm deleted file mode 100644 index 34c24f6ed912814ec9b1f4575cd52340804c1249..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64916 zcmdtL3wT^rxj($pCTWtUNpC=fQif346qB^H$R$FxZCYAr+R&sIuu>+;BpEuHi8GV7 zp@OL8sDRu=t%$cH2xw$P?1mnu|06%YkKMG-mYpr3M%p8xN+-o4h^dop{H zqUZab=X-eQB$K_@de>U-{kG2C-8tp^f4u#(PoF&X-!A*wqc7g2lp3`$wNR<5IZBnR zRO(lsmCrZcP-^MLN{w5j)Wwe})p?Cl8y;8c+GX! z@rr!@bgU|gG%0mYLX|9ik5X$I<@3gk@_Fw}RdUxWN^P8{%Kl}AQtx_DmB0QsrDl#& z$M64{Qj34CPCTVSsmtc8la~RG-UF(B^Ce0h+@a>ybu0DhQuW@4+mw23j5`0@fMe8y z>Vn#@D>e01b-|ff%d|hK3$8v#sXeEvd)W42WnXT_r>e%n7D>{!?YV>Pr>qqWU z>U*cD&ws91sfH)ieg9RV)YF~np)WoIIPX_`W}bqxSg0N?!TKYAReNholzMot`q{1P zmHOPN>cwh&|GCZT*GrxPTz9C~pLjs2ThCK(zk=VtdTLR{bxEauzNu)+=@;Smo}#&r zeo3hl|5miT1mhn6!=k?DF#nF$qRpTArc(P7MO$C|yHX!mU$nh@vQi)GD!TiWmjL&i zqVK+rv%l}PqKBV3NvU66C!cSW6g}Q@rBXjWsc7&5?Dt8#i=G?A^Dn=*==bk^L#cWH zF-o2MmQt7eX4L3k4k%S|-l&t;V4jlGMlIR4Q>m-27_9~@%emQ#2%Fo~&ZXCVm%h=zu z#*IF-E~!-VOQWCt*kekqcyjcgZhu3m%TFynZpRr)UGU@L;|_gHsj_Q}r$0-$w-zt> z&HbFFxanJ1cYkH^h1nbM-W>USs;+qXr(RU*Q`?JMf3R4oM`OjQ|G8DEUwpav`g_}z znowW7ec2;QeXXc?`?l?XR~6sZQw93!DE`(m;K$1C#rJ-Etx|`_7VjC4{di?r@t%gi zDmDF;;>SPoHt@c;_=$m2m70B7@u5+>lse=6#fKZQ4^7*OUwQV^N}d1i;y<4FBjD2y z3Ma&QvdhGC5djpaqrTS{zq0T_1JSI z11X&2Yp<7VU5#~)I;-UB+c3_m3rnuP_fqhry(QZoz;cc2Oa%xX2~rl-JsO} zwX@_i?VFW4=a!Ps{`3x|K6+`%zrKL=v~7{komC~@I34GA(Z84MJa~apzyD#$y|b_n zwU?JX-u(ygkx!Hyy!%e2uKbdG9{N$qPwxU>yZGjkpYI3$3{ETgRr4>D`oys%e?ARx zTsW^(y$E`E@v73I`PTpsUM?;A*%9ndX=zFSTT1PErL^pB(80EMmrja;?@Wl6PJRsd z_i%lw;KS6?cmE6E?Yysa_BXQ_?{lSR-j97>dTr^2zx#KkUU;#z`TbaTDplI@rze$q zd|c@Vim-2A`*~?}A?S124@w6<@Dldtccs^K;r-5&Nri6rCY*1hH6^Y0&X z?P%a@(O1XZc-=y!{xEOM%@@uDU%6|{_KrBt_v>TsTlp@f#(#dyebK2(eLE(f-|ZVS z_~V_R`}@W`)$oQ=+joz7dNj`Eiwnm*|H$WoPnj`4Ij#Zn=m%qdd->m$y6d}RUR(Bz zQtLa%ytU^g@P|{z{Aq5ZQm&iZ~p)}&YvpvnOn-Pt#}OkcS70CZ|=dloL2VP4$SvjqU&tf_?wZQ)TyGG#hgGJ7v4?-HUyzEPLqRu2t&vO=S=70G+oKmF;^A z&)rj2_W0zVDfQmcvd8a$_?~oa*?~H&^Ixtkd*GW+532|IAUKc8Mcao)Mu zrz7RZzFw@wEU7w4nPimqI?78*!VH!-N!zz)Pr}GcmL=L$el;a6a80#?k1I|lK33^^YTsK z0l!%Ac=^?To3GTAf$~p&VwzHo?=HW7GWf)=%H{KoE#)^oa0BrD#PZKn;P0EG<)3*B z>pK7Q1Y&9iua?g{0uML}ng z50<}qxF7OpTE$5T;Qi`R6|;Z(VbI6L6?0#nuhiuKsyK5B{{GlW73WMi2J4+$an8S= z20Z>m#nNZL4z~PsMROO%|7l}I^Nkqy{Wn)^*baPtsHLJ~O%LGyWW|R*@hyxqzhcXI zIPVX?SaHQZoZkzL6<0+s1;6jC_~g5P1G(^tiq9p}IFGMXe4+9&@XhTNw_S|$KK1^J zJC8XL=d3F3{us`yd3nV{W3le5*H%1q`+s78-mcj5Uab4Gzp8lhxZ9MPzpdh>NtpkU z`4z9PNdk{nSG;~tJ?L*i#UK7>J>dPge765uK5su^Z0Q8>uN$|IExY*(!27nbVLr-J@e?Z2UF&<_E@pp#2TV>l4R*@R|A0BR7rh*bhE5Y1G)BKLDODJvjDb z&*HhQFO9wSLj3;w8^&Juz~4cC-yi#hiywu)@{zH(?|%~e`|{XV58MNO_w?95Z2KGN zEj9MfRjZYnbxdXP?Vy+H^D9fzS@732l_kH#e*dJga`NeCf&W}xdF)~A(|JXeQ(t}_ z^tH6|q;FxpKklhKWhv%+-_FX0jsd0aEUTRTg}F){xvp}~*Sew4TweLU34r&6Ybuw0 zz7lx(naUNlfa8vhl`UTe{8v6(*;)!X7JjdC?Yv&4uK0fC#ceq6dmgI%z}4@8-mtQ= zd*{bNm#0=H@5cMvGnF4|$2#x0zcRzm8{b`d#e>tKzkIav#*b`MYF&Hf7j|Gh(X%SQ z*oAqXy`l1}_c!CbwpZS@^Jd7)?^QlRKHL7)%Ex~V`o8gS<&$5ng8u!ae17FW z^7-tZ1=Uq2NsYB6mOE)H! z`r%9CE}GV)ROR#IqWiI~6DN)9TXr}2x*GS%N3Q{#*URV5FOR!<66m0B{p%X=s$+Iw{+{Vor_^KKy6;rYc<~A7LA$DI{}cOp!&_DJ{tNgq z_x7r@mOT!=th{RBx9(BuNB38)9JdVeR#jbe*9PFlwyM@A!B3~0R26#|<3Dv%Rbs*- z=qLNC`m>WUZhzJ0>hA;3l2uRFtM+~B zLEuA8)e8qN2A@8s>KES_2maJi^=8A@vF=Y-{pCXqz~_1L`GZ5%@45@?U;aS#jQ@TK z_Q)~SwG%!D_|{j~eF}In^{VQ5dwvCZ^^NMYAHM;3xU0HxQn^xl|5AP4`+o;M8L3`4 ze;4TR@#^N@M&Q>e)tCKbG33UK>dXEgeBQ8BK6f@(cl;T6vZuFN@AF{1I{O{KadS=e zrn0wz@3&Qd^pw}Y_upIn>2T=c@O&WBzr=RsUfc{{Gu>)qh&N0`zfd^?xlXhFx}HT&X`U8V!z6{OGoO z=9J+FRm%StrlZM@9-xML*MiQ@Mg5sjB%8ttdQ+QXkxZ&L7U{y58BSk?JxL{( zB{SJ*A`wgLji|+(ah1gX8P(&>>t^I%x-sikb)}tU@{)Kmp6S6ndXjjuJF@l4u;G{I z8NOfjVR=z3&kUc{Q%6)67MH+(DYe=DEsAG5@l8^>h0d@b^!If}vjidAgN3FNiPUEP z7Ue?qn#b!kXCm>ys_TvvKeXeSn|8f0xK2e5T(;|lgS9HMQ$4g}@TT4CRb=1vXV&eS zsv-})dN{Fry=H(>x^uUXM6PAOVY8}q6JM6Jzb5Q5mL0uBKN$MTE$$T@$V?sy{uT82km|>N@z^rHzt!RA&Dhzv>cGDdeDbeJ>}3|8 zQ6Q8cTU51cl;aag{AB=7^kcLL-b>-E2Jlk~XA{9$a*mi<1X!9>g9Uw=ta|3wD`x^J zKGYvi$1)NARu|da6YuDW#50j(DjSJz0)j@{6EW;yWFXa_j&!8@1|q4hh_`(Wq04`4 z#LF*)Oq;QgwAzRT$FNjx3%4wHqoR75|IDpwv|F_y-&O^YcXKMeu{{Pp7R#9Zi>6~E z+rY-K4J;ZJ*uW+%oD7Au)`w4?_FCXW8rvdN*@$me;V*r7B7^V9jM5qxG@HX;Gx#ep zNwB65Z+Bp8qhJ^@)u6V3O(pPG!={9~Igg`g%~Wif#YoqBT_(o$S$g?AvSeB^T z7wy;xdT!X#o6y`8oF*+i2COeqyYv&ODbfRA9leUN^Ths3r_EWN3KB)VxBu%iIRa7|$oeVVK~09M8$yP-M@1xGIyL`{ZE zHG+u0b8-BZglZIkt=OEX)@z)eu{39q(FhqMh_x@B>WF1PR94&RNcHw5V%Zp_4TOuP zHm#Q=qrEY$o8*3G~uVYpi(@>KG3uyzF z2A0|BDrCC0fxcMi2*(FTAkQV>qIn!{|0sFjN8na33gVspfTXPb@%{3le=j z(e_w2-VsfNf^-AMp*ljWBO|BiNMWQ7t(;I1A(J1fOcMAG{RY(?Cj`#dLToACXx9=y zi)RKb26kv%<+7>vP%oe`qau`rFvEWq`tuhgBe8TE5+K#l(VtF(=&Tm1)k9z=3Ge)P zc4>cmT_l?xATD+!V$oy-QlMjFsz2M%5U%RX^%mX_U^e1^YQw{9gaz(h0Iol|F`3$& z3uNd%m+I*T>=2_DBnLttCdnkV7SM?;A}>qg7(|((o=AeG7M}(&i-u3l-RKCE-=c*& zt$><7b^eG(7CzaHH#hv; zbvfqc(u|r-$xLP2{|yzIq~;)E0TL0ou^D_v-onkI;CP?io*4_EAVQ&zWcs}yHb;|L z8iM`MYqY%w$?(3=-RJ>SS^P&!vk#w!FU$O-2SP-4AX;%!)hnSV5p_auM$6!y8SAwl zQ1dN$y23(y#)51%*4rnxTMBd$O?FeqP1b{MU_a5!g7($lrxyWXhOa9^;a^%1ekzqz zJ4xA;KqH~@=|T89Q<3OVkT6dvl&5{%)zdSrF%gG zn(4F*w8TSqsbcWveWwrJM0LcDS-PM<+mi~nRR4~ZkO!u4;v{t92-O#dA>@_0W+*u` z&5JZnKaO{~E-@jwCb9wfPFMwT#V`iH5=E*Anzq56s>NH}DJ#+c3kd3J==py_IkFOg(o9wrMeLR3a$sw#!=WuuurM_PAC~2*5BZnx}6aySQ&C6 z7_uz`*iIY<#Diu^A~UT~?44C@Pd3|^X`DT~Z=f&UkV<#YhEj7mhMtX~aG0}aHAGfk zNYwWZIh=Hh2XA`dr}j9@2`2esM<^E5;6#U-{(;l7!%bLVEp~5>p~GIL7J{%SG!1GP zHXsPX10iqcU&+L1>xs{T=)}KLevmYYJUse(O|C=~J)#9_&O(@D6scqmu(ML>cy~M* zO+-53cj%y_FA`05LJh9(NTg`ig~HsWVJ3=pU{1r({4Ag3=vQwkt%$6GvPArRJ}Wxt zs2qz1<&6J%3!|BM2U(e@3{X`?hqZ1b=fdiRiVK@F)Sy@20`PtdFUX}SRj4b`T|>I< z1g2NOED=9qCw?}X5sec{lL~zd?za|?R|@~;fr$J`<2geuhP!i1L^i~rtmM+Z)16j} zgVwP7On*m5EY=z8Y^Z34yRx%_JggCtsv?`xA1zRt!24m*WTR=3XZV$eo{ViaWEZYU z9hWXA%u?$}dVZ;wxoEpB;Q+&ftCVzR;1k<&2yFj!;h{o`|kNbDy*j+(XJl zS}oM?sQ5ZYLc5wyIm%1Y6(uIeh+stH;Nn=$Q}5_%p$B;)+7G`WR27nkCpus;_b0RQ zgeIH5bZk>R)t`x^lCek+JyV`DKb(k&v3~u}@6QQZM&lQW7AG#0LMBckFeVwkNMHZh zekXT5gaJ=Ww6~FPB&SEXT{=_X>!e)u+&tQ4U0)x8`ydaa(ZYMUoe@h>1c98b32!(P z96JNMPiqBYB81{qjoz68WBS4%6LLq@5s$pCjv2mTwKT_gp)fDaGq}<0@=Rh+TLi9H;}`B3+Vwum z{IJNZ7eqzHd6ax5wIPz}dOJVNjyIfoegE#Fvo1gdXI`~a8^+(>? zJ$(=KhQry1b{<)`@9cxO+F2uu5^;|W4UyyZWJ*PO%|BSMR1=+ zJF<~Y@!00jB~lHNaZEgjqA7Q*Dvrf)du$}5(N{zpfH4{hKQGK}A;W0Nu6Vi^3LwMT zp|Fu@4&h}O)2F-JF(+V5kD+v{HG#MnJOFVA6AO%Mjn8MW?KE46TQv1A#;g+CmM{kKmkfi?QU#|C zN@a)Uu&8mlEW@xF=d$4YLp`Cjn5j$8Oo+4tT(e~!R}G$bZjgD{0sc-qlw-{Wq#weY zRQ}vP)%aYG_ql_LgWO;lU6frB%aVCSpv=I$wBg8TUtcT=Uj#HBM%^X#qZ8_%#NRUm z8MxsZA{R3l4`YYz_8NRBv-uL6JZ_aOz=htWK2kp{`&@ zCaVkYekK;vVPu@j8ZcD7bDm&p2&RWXFSi*Hp=5c<8uqaXWOD2;0H5j)}}JtFnvC{v9hiFhV^RD-({i(t`VgX`TcJa`)*Cr2anG%6*a zA$%}sPVwmLaKxS$1V8y*M&wH(BJiAD=V^-=;Ywx^=)fvHqiO4vbrHHuJU5QErwS-X zH1>`TLZ8+QsD{#_fi&Q>#FKu=&kTcHv~6F|2E5TYa0{&B61@t_63Hpyev{|e_A|2l%+44zd$?!iH6sh;+AL>&#J6uOD(m`~ChZByb7_5@;Xvkb7XDxu3 zJzp&bYotf736pWN{OLZ7!jlMf^vNFhyP6iPIDhe~#)wOf=>i2JtQ3acMK2ARt`*Xq z@|>$QEBE7~WcWxVkbfr=lQ<%=(9gAlK#Mvr3XX)98Pwt1BI6lu;I11lvXSWAbvi^P zEYBGkZDe3zqn=r)f;3aF`40^Ws%&Y#>BTiIt1QB-cZ~y`S!r$pNm!Ifn5+|H-zDk(T&;+rI za*k^^8qr9Cja;iZr;=D(%%`;e(V#{vlvZ(e3PV8V6T+|YB$NU8ay^0PrB=b1gC>bs ze>9SX7Z-t&I{gh*47hdsk=}sVReL(MF_r{ZLHw^B-u=zdbY}*3KkSlhocV&CsgC|$ z@FBddm6-N;BAy+ni*%%;NJW(~XX}_t3~Eda5fBDKdw{u!8b_gG!vRURF~Xsw^%x{^ zSi}_G2CbTh>)zvm@F>;9<}OsrL1RspddixXwJun=d~s74v8X9{mj}s1aUus&+Ky4# zM1ki?tk7|8(=;7aJE`^(GZ!#;Ub zeY?UlWQCF+=Vc^0t3I|Rn~wUdLr#n?6f0Q`Q%H)xi)IO)3!LMuwK2V;1Abbbzy z6vPyo6xKu$W(trGQ{~7-RER*kbtiei&{2cjqx3)@^DGUn6ksy90RR_n3Z_9g`*Wsd z*+Wx&8UP->5g83E!c+h@;L+0Zy+z}?3G)&kSgzrmRQbmByS$qh>p+^9yrAP9Gczt} zr~%pe!c9G2Swp0S*_W|S>Z00rWfP1FIm(aMTR{cNsd>4s!*PqZ^g&m^-VWo3#=p;ay30$qbi0eVfLm|O{-W8?ew?NTYE345z(q5m!Hx6mmAfMOkx-*`!n zpi7=&&|G&F7A^QI(NgR+(l&V|$1&1?d@)x)PbH!UTM5Ah z@^Xy`rZR_0Vpj~7Ei#FjXQp#{BxwfmV4_(@gh1FW@>?~W1cnxypdbLedKI1;iqtQ zfmMq!MB*?=na?}sUx#xex)Lix-XsO%WTbJ_3lk4SVORS8z)E3fP!~WEo^_VVlC;BC z2cEGH@UYT7X9DXj8n_4o{f!7)9NOfx3&`JQw zR*1V`ipdorfCbfO8ra-Bs#hjM$^a~Z3hp@tZd@y&)E@W^@rt`Gxe39gI$Ai-w+K%S zkD!1tD#@E5a(M5-z+x~`J82$E9f!BtP!cF=%)2zdG~ur6WEZVx`>O(p9F$OEATlwM znQMkUxh-%^!OzEYbx?Cyz0FUkpn616>jOM~R*VZqY{G?)KPb_KD zvC|O=wCI!@4C~Xi$?BkxN21-)c(NhV28PikNr7;Gfap3|Ko+j$<|j8-VIvC{vNHmj zn_!G2l9_P`qoCCCG9S6=avCVSAUTqnsNXZCCM7(hYg=BNWC}SMke|}2;gYQqD;&N# z_A6w^!e_>J3}&`_V#mEptyhxc&B;5@>OyzA-Kgmkc9DU)fHkpL!{h;Fz>Fzo+o|{R zuezRq2NKTl?m3E;lCf|NWW&@DsYkgri+UjIB{LD-F?Z$EdGnOlcu%`s5Q^qeQ=_EC zNUhoJ$=bYol7+`DgZyEyibZ%*DhY+m>`l~Hy@Rh!#YL3WFmPRkZ&ZFs9SjhQ#5TF` zQEZN=`nin2F&YyMN9E8jGmjm~!<*V>_r)vxw(6m(B=#JFmNRc(NFs?$Y!mM!3 z7n%&!Dr?5619RwR$a0JCpN)j!9+!-OveH3QY&Qy$e=F(3T)QP@NQ4fGCJ!TgbFL;h|Gc_ohzA zy89DILP3fEbXr|0qvJ(|;pwpj8UE0rXxoMaC_MeV!#TbTu2JV9o%>sggq3HU!NLqL z#tqj1Bivo@ygp;8g+{?KqL>xR3pHblmB`?tP_usrjgIK&w^KMTGKaFr8}~MZieLerdx>2;*%+NePMvdd zPLz4c%`_oce?_lEvnU4z<8DZYwGD{4@}xAy{!V>+u)?Vx~X9D<}ndyCc&)d7Feu~80KbSc_x zFo)sP^Vu}TRPt`_L9&(e-Fu2lfm1jWQA%+MasttqOz=8r#EI5Lvkz2l7kP z`QR8nEfiX-(vu2`f$;2LW0pzsStw(i7JLz#<=2v2?qsz$kf+&%hiPZz4Cq%GeJY2A zaFRE$sC^=DLZK}*xS)`xuaLokN+70pG`Nr9g$ynv8anuC1-8Yxse_nsOkiuYXSNUy z%r7v7WpZr2livjuyc z6?C>XgiK9GRGy?2ySU?g)7ea8WRHZdabd_rT%oHSrXhnCV&#{sc+Lpq4yzZ^fekt+1W(psLSHzPZx zkcoKikQGsmNEeT=6>)_@$fg;{`cRG@fNblPg=VkNv(uJ$N?^%yWRWLA(XP?HV#J@@ zdXp#4Bc`*)gjzhTx3qO4r_g<2XrnN19OY&3!~=97edyGsIlUfB^j3#HK3PY}i6FEV z_~{P>Ry4zxk5aZ|K|cVIBxeL5h>J*6x={)Q0OkV{jzTvoLz0a4`*R9JiS|@`{Iv;? zl20)|z)#R8HKP)^x4+kPuz=rCTk1`^N|3r+ky#CXSh$*!{ z(kYT@ouT_YeaPT>*ti{fq8ZvT?a+~n2eS`tvu_r!DAWRA#@<7_*B{)aB2uM}a>i|k z@V<)d82{wnT~iJm%5j69umWi3DTX87$M+*+o4m$v_0TF7KQ>XGeheNp?P=4t(HS+) zyB%4P@{A)S$lBun2s<5W$_V#f*LpDcy?^9cLsIbV#!bdt;*dk8uW1$%y6JT?{)`gs z{ScmN())yi`#g$vjwzVqSKF`AIUg+khngoQdFVXH>v<@>xL?*74Iuou6&NaRDxyM% zx)$wWa@FxXIH-?AR8)5K3v{u50dPy9TjOQG(o>)aLqv^(y1BWRYy?99dAd5<{d5 zas9mS)-M4ohL0T8Wm*_pmYm{n01G}2X1froSSOW%;V1eR0LeTllLgN(Ci&k6{BMMB z2Er`hO4DfPp7fbf`bkP1vMZ{K;+7KMjnS)up#n{c_DmM7M9DHt)U8P6*dV@XuWtvk z)Ag5Peq9-1YN&QpdF=|l;6Wkl;7l;}poJR5YsUow9#IS22`$pW)Zn`(APXDO+x4W3 z8;ZtBkCxxB#ljNG96CA#Td7dfO-$FnBstNtk_@sGzUSZl#x1d5vd9|n6UB!7#&a+s z1F}TY8_!BAI2@x}-V#lNZ!=^UV+LI(Da9VD%AC&>msPEF47K!g{M^ZN2n8>c#d*&reSj^-?>aVGFo23aS^V!7+Bqc z;t&!)A^_~=6UuKnAcqL%8&a#$1mGLcX7ELb-Jt`Lb_6D(TX?T8$!jyU+78K1XkpMI z*pAC9&ko0#gf}VAlAMH76AQ%oZBE?<9VHt@#Fbc)X}o0;l&J;;w$5pWpfl2;{|$MmWoDYPqkFErqIKjihcEKw*j_jN2&63FOTbm zj#ig5+EBSJB{e~V=vZ%bD|_LeD73~4G-u;kyOc38B;`!=Cyu$S5c0&_4#20v29zu@ zn2EqoU!s^c8i(onJ8}2=XI@v4XKvd6f{HxWbnrf3KZ!}JVqF-qM4h|@5LY;x`-4;6Fd^;dT2L&+&%F!1*oWu#4MR&Bd4O4vp z7?w8F35UxaFg*F0c1edW=h!@>`CU$9?KlPEI7e~AMBV^(p7&1!r?C0YD3fE=KkelX zePsqP%DXcIs7-YY%Qcs1n7b_U&UCz9uI2tXJ;_A%8^_~TdEML+5JTZ{a@jfmP}GxM z*AncU794bIYDW1`{AbboRtcfR0gmm*pz=AqXk5sS09il2>>C&)8N zSge$l0E5YlQ+cCCzRHSnQS7ouHv4WaOFb4W5Jg+^pQL_s+nR#J4diV09tcmY|1la)^uHo zA&TZG_NW0~0u>aDI>%AtB%WfPx2|f#Hz@LjEs3Tfp(nOf@7_BDFF=|WsObfP@@O;^ zo~|5tjMG*!NBuI`DX}45M!jKVBrY4;(wl{Lo(Cbp~-^0kR?l zc%CeK|A#CUFp_706`wB6KDHtv95-kE$w)$WVMazkL zocx{G%3FtRy+*!hTD-#fY9}9~UoFrduK4f^JO5%IFK&x=hey|Dh*zAqBn@t(uDCBx z_NR}z&1^$Y?^HU9Bs|ZvCY}cPMYK!Ai;ah~wgxYIpSVMVOg>FoLIU5>f+E9X7{jgl zxHdSF;M~%z6Cnn#aYp#c-qaHbPqZYA;n}u{W;{75L6CF>y6b4dg&7FEx`v=SuQ#6# zid~7U@L!s9TmrRQN2C5$RmL?)Bak`GhN9gVbPX)SUqnHotI+QQ5~aZSj47C$J-eli z&GIFaq85yujyIf7Jd4CKU%mb;D1qKhPM)YoxQCrzSdyUmgICgk!Jw>YwxOSBhf3)A(U~ZV-Jz}VPXbHKbSkZ*yX$FwTwz zt;yu*o6JGP#kQb04UR}2rEv$CFk|>hrAN3To|Y+KC6@m))^kpt^&m+TxqY4Qa5+Vn z_?8m|k(e;@aHJg2QZ!?rPC){6Jj?IZcSK53^pn5Q-f2IZ8Y~if@C}YiKP!XILgsvr zL@)KdZTJg`gJ>=h1YvCcH3_2;k1aj{&xeFi(>B7 z$0qUjT#n*tZW%@ZpmKtFOP~UV9b3u?uc7II@P)r=NF-1xjG`&Tpmbkw@FJOsSltU- z)`%g@z}U69AJF4yc7D`ZX}57`omJ5V0aS4<3CZV$$4I%2Q7);2)5zjRI~sO+c&-s9 zawfRV`S>4?m=rZM)7dY@n)Pv*ta{1{CZm|1Fa{N<W(u+g+zQKd{3zWHe{IJO+>1W_*)wMxl zur+VaJzK8c1p0(1dIj8Btk7hyKZ(rAZ9+mqxsI6eZK)K-!__}HyMiv5bx2ckBF7-K zTXX)~9Z0;!Dlz>?Nybc?X5WIq+E;5?LrA0`l1cF<@=beWM6G)-9TrZv_akfN=={Wf zXlLg_t4}3Q-$v~%E^t^Yh6UIlJ#A2O0HZTIUgwtNw3C^+021YOjVY*HQ@w^bTopMp zFJQ(}5O1_|iHL0W@6ZVj0I$=8_IE_ty)sl&eSh9bB^QJGsavVI)nq@+b(Q|EAnZg6$@PX zy~|A@FUw6#bO>PhoF7H~2>D+B(!B;(Q3yoaOwDB@YRn+Z8Zaw+M}c5ez5+sEPR{Ip21=|p83x_p2;>!R+opIkN;No~(8&Dg zhL1XY_iA(IGPw#voJ@8XCwp@+@4)(hLJxg>V0@sk9j8pjDbTmsk1$*}QzHqN>_^bS zD+ojPw$uO@NK2S#Fqg>>Iey}?8Ym1?$Vr?Cq;V2E#C{K6q9>$Gjvn+lkc@M&CZB;g z51{$6>C81=7Xx=!9Y{WEJbCD><|XwyOKKi`dZ8zCrnd?gE8Lm`m*hI;n1c5FP5?YQ ziFm6wG4d0KO}M<^olS}@ljv8z8lh7Q0HPBo3s(&-f%&`up=6eBv8}SSRAvZ4;zXJ? z0szORG?n9wms8d*ShZr=iu2KBxxWuVAuv(TZ-H!%;chP7od=i}Oig{8>2$0! z2zGxr48b4ub{Dh{H3R7eBhzrHsZ<)wCG65nga}K?BP~iC`yoo#<9(vLG+Cy0#=ko) zYrS253p=g3{#fKj5^&d7ty{Cw-e!QlzPR2>-@2=Nl6zIZ^|VQ)a68;!Sej?w+5p#3 zSDAbh^u^4@YKUK0uRX@;b{*o#&^0Eo-aRM9Twqor{3_kYjuM`H`yNzaxc77}ngqjK zzcT$mt8uQzNyyKc`W%g~cBXxsqKjfgL>N!IKJcVF%?%;D;7-ZXyyP4jCv-z(wRf4{ zO!4E+WJ+QdL1)N7+}ekQ3XXXRQ`c6$0q5$9ib3woe40Fz0uPp|ds8F&$7F~2Sx+sH;H9aKm2D!sb z6OQBp6S=*;=%gg^iwl(Vkqz)0F+}}s9faM~;)G1Q5F^cvD@-)+mq$J7Ii}QO^jV4n&=TrzaYb-vP~YpkIkquGuc$ZAo-LPJ5%Tn*A1HBgC3QPk%IU+qSnoJrA-PT7}%L%_Q@$R9ur z<)7zLdBwnjz$Rcu)D2G}5jEJ40@DOf86%3~$~s?`2(;V+OtR6N-Iy~&WvRd+85*o_ z>(UVvzXot3=9c7YFJvWm=4CQn{b*quy6~wo^^6iMRm7~%A!c`WJO)SE6ZO+!%AH#D zc+^Vi1t%sBbr^7Yy?dgRr(wV;`Ks?h4Xh8tOP$^oeQo$|GC=3 zcRaZlX(Xt+!#A_}on7gqbKB>)c$t^#NG;Qq)v@MLH3?cH(ko2cwl_upyXGhP9E8+P6?s@xcXx2wg9E&OsZOA76T zV?28$?>wc0>kei2oo*klZ1SaT@Qv~Ii-D$i6sd%I?<(ar96{vA$Jm#v-LsMGK%Z82 z^1mNaFq!}1ihYs8FYeuOq}L~v%T3jqmXZ12J2qD_I&j&p7Y^21aI1{=qeFe#XK}n+ z0aAifiGCLU`qn-1>05UwSGu|9?p=rMaK{;tjLzPh>g-Pl=O1?5BTf5pMX@Of4UX&8 zwsyXQaqT%B$?mw%LONNm4dqOBwO&_*VZbaZWu2<*;(^2W->M?_zdE>_30(yLP!Vcb ztC7}))8fyEuG#nLeW&w{L9ewRH9a>1uks{)=(O6%q2dE*1UQ)8^(wz-YS@wN0bF=_ zB<@vnb%@Iv}5ol9)x+G_tp=dyL-L&=DG)-*!@AgyKesrJHE<#+IyC(_gRR{ z`0L0+4qUL~WwRzb^E$a;RLy+&3?!<}9d?O5UZx- z_N*lSu{W6D@IG|OPT`KvNX@eDBqpiJdE6U|VQ?D4-atl04FFH}Fbu}1N>yvA*Ifly zQEO;L-|aTZ-igwT#;`teLkb<=)`lqkQ(L53`k|-bO51zzuAD{rBO}?JL*5E*li`ts4p?ah3{GFHEO4;{qh{eulm}6?Yr;!%&mT8%E~D1ktff%ay7Y_IK-&9+(XXTNYeO zVc8uD$izU$f}q7xF3kysUrUqLG3h~(J_Vw5<*Wsl?V$Wc`zwc8OVQchl|6I-QehTz znJN|)`r)orkS>>AvV&FuyYTM<7($YO#`}lZh>q7nn4BG>9diyTua(%cnN5^A8tpYX zBD5xuaK?gNNlTG@C2HIL<}x(KM1iDXB8l5ftPo>C_RU0PsHHO#iqFx=mpC{JhG}q$ z>FLjE_1_9`J9fJ-5gmXf?iHp77$O>VGT(!Vsrq|Z=&fLG-tDyUB#L{{j+%TFYAEg= z_0)ozI?cFs<`-CRR9ar5VImaRYzkS)x~U@+Y6guw7GwG%z+{w+R>|lLMaasB&)zo` zs|{k$geLEXGRb-!4uPh47ore-xVWEC5dp$ z^n5{MOhWCnY?%ZWmd7tPtXRKfpaOL+{4z2TF4s18D{~g_^|%fuflMyl$^~e!nJI!k z>FO0M12GC?64H?&5;Hop5K(#rx|p3#t62}GeHrw>>l8%&6&{Y7R9L}2ZAphBM5vV! z`bNc`w!?cF8uj&!Eo=6g_7-HKQ{h!1Y31$q;@EPqmrKDBt%TX}=dQew@3-jt|abq%_h!p~-gFo|d-KeH2NL21N@mS4&m$FE4+AS+?? zL%uh1(Xp1?i;d)2E`E5Hm+PdX+@p6$5}^q>+2eqoo99}WVki_mBBmGX>vX;h3D`ci;oq)d~1mg)`8VwM@p8TxK zD~$1N9u~@Tr?auY4-vd52G2wX#OA=i6yNw;O&iUjJPfs=p@!YMFK3E2-V^SQSs3Xn z%x%LRC820O{@`Et?qD7Y_9w_o#;%REXHd*IEHjzosb>srQpsz^aZ_$Hl9ASEycWOF zwm=en#D3FlLeOg45uoi>Ob`A{f7=IJHWVrVwC$<+0(z> zcRkH<`+Vsl-SR2-!A^b6r`&+T%u>dH2r-ezM0-dGL?Y2a$kw{?O)%e#^}!~pV1lPa zJ+euc^*(}U%sL}xm9=}=0t7)hsZPE3??>^DC-!~XuBwdo zS3KFT9aR3uDp<}2H_YxQe`p^rU)%{?GL>!qr?;u4I)>k-&x|G?cSO$At(PnGE7>(T zeQH2lBO53WfF#L2sA?|;E|}k%@dWSpHNP`?b`=b%R__~%iVmMIV&T$dE7}@y18Q$C zqn_LvquSOi$Yf%@?TLY!I%v0xoB7dGBMD7_!ECWSAWw3 zk@f6jsSlPC?F#-~*F+B@wsEB5CdkfYUl5{+LHU0tP ziCVsV<=Vwf8(J=ITe@<^hL#13E?jW_;?{;NYG#>7P^X!nsLP)*83C6N zKPd54KVbnp=G>msb0XOIf}jl@zpx*C=<}iOrJ;`=RafGnuhTm6r?fB7o?-GnFF(+( zH*Y|E=zvEP5g+cswi?Edho-8*?p1yci5rEESLV%!ROdvozj8PCdxM} zW$b&E-g~xhwS#1Q&dV-XRpz~x;NGCwZ*S`%_zLA(Z!y9z5Yw zo-cqgB~pQMDW`}7d+75#dRhWWpG?N6WH!msLUrmw@WpytUh6q1As?b>V@N$mrwoo5 z#K}1VRriXvlT~}GG&?ZTVT+#Ev?(&1NJuYJutb20s4?6n0+nOqL9;QEJlBEY*JpyB zNKxuJ6BTAE_dI9j2@`8wg`Mal!R+%6Jmo(Ta|*(ciScqOqF4(I)K9|33a;0zHg}b^ zfU5!fLyc)^+~VI?6AB4N#x}wC+W?tzj>bjL4d4q}|88|3 z(2O?eCZUWBOwz_s+~T*JVSu@UrSV%!OvaWMH%oe6Ux7 zu9^2e<;}}!&6KsVhVF)ZBXS%sb0Wc8AbjuY!bpJ?N{4}P)0~FW&k=ux7P=#%^)ofT z2Kh|xNsw(@K7$>`f0oovu-wML*DKt{3l|>~WH=cgn^~y+dt1PuO;7z?BwOPVf>B7R zn!8Xan4$&al%;uwVDhE@_=E0A;tf5fbp9Azf)jFs0tQX&KcT_3G5Y! zuJHak`F6bBHH)U+erkzVVBTwiPEs^Xl#(c=pKvL%oJW_;#i_jF`CwWI#We%(Gyx6! z;_pOEKZ7*PiSg6Tc-GD24}vdV0DsdaMjwOZEv7!5fpCCzLS8al>ByW!%8M=ZOX4n{ zetv(vu~ASMpNVcnX4uOtqo477&svMA^}&*lxibe?7xG&So-DxG`6Eb@({9+2PipgG zBn?bO4!&ofOUv}~Vi4s*wK*D6X-9`X&ymj{TO8yTeyhcy(0I!i#CSQ%iIUhq7B^9m z7;56vGsNs$`jrfRkTWokrbU7UTaH5kT$IO?Z~%rva|$tnXHd3ec%a;3CAvqVqR}X)PvKeOm=98=g6m+ z0WS+BzHFhCK8pK}7Ctos-E`SbI%(0+p0s3{BcHJX-X5*q`)apJnxNkwCFGZ296CTv zwUlcrQj5bj&dGNCBnTk7z$H4;NmAn-q^uy5`-?vYfCUB<_^aEtf9p&LRNH;$fap?z42R*oJ_j*PKRP6y~2`n-xKp*B&!p7sX8C@`Str> z*o71u6Ux|Md(RwSfa`>%2o-qD4;2TfS?P?d^wnyO95L!l@-D*j$YwqG%@NHX$uqw# z`CI9g{EZxlGoN0+AL*?6N*Tmff})TKvqzc^-pcq*$ac*0gQK%pJo<+c2q^)EYV;qc z+Z`SKtbvadR|!^k5BMqYVaJ2bcR;_lZ#b z(Ah3hi;F(2liH{ZN6D+l!vV@HA=_rhZde(jtrP@DDNmcUhgB?ok(HwKNY8(&QB<^? zv}JErr<7CP&hn)k)R>etO3v7pSVw;5m zzzrQY!U9==%vwlEcnYSYjMqKQBbiix8u>I{4(Z4NW=m!UCTVc^cgn<7{H2FM&x|Oh zBT+-^k%qh3Q_-oENa>;HWMFyhKcIX*foPm~uJpEG6-I?7js&Goa8pISCO@o&ekQ$M z!}*Hv40gq(&o4MpulzT>;#Mfrxe%xQ`uI776MdB#E_+tE>H~>iM|b1hgway2t?TDC>PE z>~4mgOS-@?tjrywieY)GkD*QCeD%1V3in8M%7jPB!735z=80?saylMXx;7Tuc(k_9 z@vz!l0e*mcSmroxk-t`+0H}W22`DUG=i^!mTo7pAnNox6}bPZWjeRdVKwp|!3avN>-I;DZ6ZPjcTxMfC` z+aY~Tv+_V#v>Rl}EC=yc6P0PB(g9JcPScsjL^G#v8I&j5G5eqfpA=8LvaMG?$>$kw zXYPV?T5t@%RH6LMpYlUiK~+JVY-BFt@(@xp^Kvw?e#HkMBC->(b5vJ_LJgDc-Y7t& z3wv-qj?Z&mmqn7>e?6Efz*!t*{7KSzL?Y0Bm*h@?#wAoq8N4J6QbvRo%M(U%@i6sy(^Vk2^CghlcY4?tV)T6Ko~5v2008Bbj4aoQcodf-?viY?CyU$ntfP$VVI;)t@Xi(!?mE+|n&awTx{VNR*B( zV%L+L6m{-bQUDyqkDW6e+9iyh6Z{1AEM(B}CqgAnH6BOrbA$f2xjU^v zNarvNx%YumoC8wA4sFvxYmGS#oL1U&%kRcUp)$!FK#oFRo0yu0G+iX*9FN^F&pM5) zXQ!ORaA&P|WOhHhSIh(Yg(-U>aMX_Aph_@sir z$EF!joL}|e7F}@GnYaqoALkSb27;x>CZ~fJtUlGHo0fVVYfKMEuSG{-_G#i<+56(Y z)9H;i3Ls0m_uM_W+@ACCv`y+4q3;lF6LFEVvb#O1Z?|)Oo_OFzcLQ^z=Q;I%ssf_& zP)X~= zuZ(IWqCbKo(3{MtxmHJc(9sZR5#8`j1MyV zhiM96;!H#y{wqb!n8(gg>1_b2gyl-R`~%Va4GzTOP3m$^D;Q^nVjmqXp7W2DuL8vA zBmM*yR{=sTK>9W0AF*&sY5sSngi(gu8n3WgBM_xm{(7N8?iccx*DYubDw>F;(-N(6gcImAtzyc_IhB$6gDz{a<5V}}_D9cC z#WIKR5iidz2+*2@FnR|1DC0#4P`3!4F@K}o=+|BfXe}1H_ei!*6gvn>5QS94`J`|r zdarprB7%eBH+&6kN3{mej0W72Vk-j7i4{*jvCy8DA6jWY(iM>9;UG>0h>nz+fvP^` z%}!M%ej9)Lh`bc9rs;UrP{W`_YgrrZfYt79=m@<9;Q&tj@wy$4?wfw-7?g~n0Yach z(d3*_hLIxw|LC-kf8+nR+brat^&Q+(ntz}w_9gmwe=3R+9#I<^TE(Zm{YVK;i+mT1l?~ow8>CP8hECVr@>tL4q+-FW0h+=|-#lYEkGwXL;VKZo z5M9F=BPA;!z_m#~3@pWrept*HwIan$8|Iy`{=>t(mK&B^2z8QnEl$@0V8U`zP(xV8 zNz{IW^y1NesG6Mkp5$Zrt2dmXGr^1VQE$;jI@;LDGw5mBYU+cfM88EhFiuRcB&0t* z1*Ck>yK135W>KndARX`S$-?g`0dROb3H9+E<}bcK_zYJrfto~cHhK%pMcMu(n6VI5 z=k3>e3B%1WE$<9$|3>eK8@<}CVE~uSk7(?-fWYF?BdejH=O?vOqnXoFL*7WlrtidY z(%{tq;#D!d+^Ltl7RI92i(w|LPdq4>V?^C?8spMG#kWXC+&u>YF^gp{GCzG+jGdbf z@H4eniV11{OC?!!OkWhCqA!b~Jz@b7%xT?MEC8t^-5vi!p=O;fx=QnAVx11?T_xa^ zVwolpY?(nG0mlcOz{n9m7_A>YF!cbqHIVPe5(r$ODrF|K@z9Y5INQyR5*_IndxT_D zTG6g#^-Q2^>}1PNSQtke4a>Gj$_9*)7X1z}bLi_^TumX?Dm%^9yBu%v;K}Zi4suUD z=+e#gwz);h-k=M-7Zg*J=yg+R9$IYIsGtD*-)EL`h>1G9*hc#jV ziZlAV{bcVp%cWTm!RavOpfl%4iOnbszW1y8Z?{H#$m^E-?x)gx+@3O|`j^hxk`+lP#$tGKhnyvp0D zBts}yKPqE>j?sz2=bnQ+3`vj5ISXu=1UUmayuRekDYZy+veb)S0$x6`&fAjm)*e~d{a^|o6VU>BZ-*@zT}B1B0FVVT+E zB@79b*BhNU9|}G@6iY6Tr;I}Uav{u!aWVa>1;`trZi=7+?&si$#|U;UD0P2br7x=FWd#_foAhTRQg06;#2*ZP!yh-kg{ m1!n(WwmhnWR)-cfM{9268>6s|k?)PXhDE*y!>oziXa5f< - - - - AddCustomRepositoryDialog - - - Custom repository - ê°œì¸ ì €ìž¥ì†Œ - - - - Repository URL - 저장소 URL - - - - Branch - 분기 - - - - CompactView - - - - Icon - ì•„ì´ì½˜ - - - - - <b>Package Name</b> - <b>패키지 ì´ë¦„</b> - - - - - Version - 버전 - - - - - Description - 설명 - - - - Update Available - ì—…ë°ì´íЏ 사용 가능 - - - - UpdateAvailable - ì—…ë°ì´íЏ 가능 - - - - DependencyDialog - - - Dependencies - ì˜ì¡´ì„± - - - - Dependency type - ì˜ì¡´ì„± 유형 - - - - Name - ì´ë¦„ - - - - Optional? - ì„ íƒì‚¬í•­? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - ì˜ì¡´ì„± í•´ê²° - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - ì´ ì• ë“œì˜¨ì—는 다ìŒì˜ í•„ìˆ˜ì  ë° ì„ íƒì  종ì†ì„±ì´ 있습니다. ì´ ì• ë“œì˜¨ì„ ì‚¬ìš©í•˜ê¸° ì „ì— ì´ë“¤ì„ 설치해야 합니다. - -애드온 관리ìžê°€ ì´ë“¤ì„ ìžë™ìœ¼ë¡œ 설치하ë„ë¡ í•˜ì‹œê² ìŠµë‹ˆê¹Œ? 종ì†ì„±ì„ 설치하지 않고 ì• ë“œì˜¨ì„ ì„¤ì¹˜í•˜ë ¤ë©´ '무시'를 ì„ íƒí•˜ì„¸ìš”. - - - - FreeCAD Addons - FreeCAD 애드온 - - - - Required Python modules - 필수 파ì´ì¬ 모듈 - - - - Optional Python modules - 추가 파ì´ì¬ 모듈 - - - - DeveloperModeDialog - - - Addon Developer Tools - 애드온 ê°œë°œìž ë„구 - - - - Path to Addon - 애드온 경로 - - - - - Browse... - íƒìƒ‰... - - - - Metadata - 메타ë°ì´í„° - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - 설명 - - - - Discussion URL - Discussion URL - - - - Icon - ì•„ì´ì½˜ - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (ì„ íƒì‚¬í•­) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - 저장소 URL - - - - Website URL - 웹사ì´íЏ URL - - - - Documentation URL - 문서 URL - - - - Addon Name - 애드온 ì´ë¦„ - - - - Version - 버전 - - - - (Recommended) - (권장) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (ì„ íƒ, 3.x 버전만 ì§€ì›) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - 애드온 매니저 - - - - Edit Tags - 태그 편집 - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - 애드온 매니저는 유용한 서드 파티 FreeCAD 확장 ê¸°ëŠ¥ì„ í­ë„“게 제공합니다. ì• ë“œì˜¨ì˜ ì•ˆì „ ë˜ëŠ” ê¸°ëŠ¥ì— ëŒ€í•´ì„œëŠ” 보장할 수 없습니다. - - - - Continue - ê³„ì† - - - - Cancel - 취소하기 - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - - Icon - ì•„ì´ì½˜ - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - 버전 - - - - - (tags) - (tags) - - - - - Description - 설명 - - - - - Maintainer - Maintainer - - - - Update Available - Update Available - - - - labelSort - labelSort - - - - UpdateAvailable - ì—…ë°ì´íЏ 가능 - - - - Form - - - Licenses - Licenses - - - - License - ë¼ì´ì„ ìФ - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - ì´ë¦„ - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD 버전 - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - 애드온 ê´€ë¦¬ìž ì˜µì…˜ - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - 매í¬ë¡œ 메타ë°ì´í„° 다운로드 (약 10MB) - - - - Cache update frequency - ìºì‹œ ì—…ë°ì´íЏ ë¹ˆë„ - - - - Manual (no automatic updates) - ìˆ˜ë™ (ìžë™ ì—…ë°ì´íЏ ì—†ìŒ) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - 파ì´ì¬ 2 전용으로 í‘œì‹œëœ ì• ë“œì˜¨ 숨기기 - - - - Hide Addons marked Obsolete - 사용ë˜ì§€ 않ìŒìœ¼ë¡œ í‘œì‹œëœ ì• ë“œì˜¨ 숨기기 - - - - Hide Addons that require a newer version of FreeCAD - 최신 ë²„ì „ì˜ FreeCADê°€ 필요한 애드온 숨기기 - - - - Custom repositories - Custom repositories - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Advanced Options - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - ì„ íƒí•œ 매í¬ë¡œ ë˜ëŠ” 작업대 설치제거 - - - - Install - Install - - - - Uninstall - Uninstall - - - - Update - ì—…ë°ì´íЏ - - - - Run Macro - 매í¬ë¡œ 실행 - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - 다ì´ì–¼ë¡œê·¸ - - - - TextLabel - í…스트 ë¼ë²¨ - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - 매í¬ë¡œ - - - - Preference Pack - Preference Pack - - - - Workbench - 작업대 - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - íƒìƒ‰... - - - - Preference Pack Name - 환경설정 팩 ì´ë¦„ - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - ì•„ì´ì½˜ - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - 버전 - - - - Description - 설명 - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - ì´ ë§¤í¬ë¡œì˜ ë„êµ¬ëª¨ìŒ ë²„íŠ¼ì„ ì¶”ê°€í• ê¹Œìš”? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - ì´ë¦„: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - íƒìƒ‰... - - - - Create... - Create... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - ì´ ë§¤í¬ë¡œë¥¼ 추가할 ë„구모ìŒì„ ì„ íƒí•˜ì„¸ìš”: - - - - Ask every time - Ask every time - - - - toolbar_button - - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - ì´ ë§¤í¬ë¡œì˜ ë„êµ¬ëª¨ìŒ ë²„íŠ¼ì„ ì¶”ê°€í• ê¹Œìš”? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - AddonsInstaller - - - Starting up... - Starting up... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - 로컬 ìºì‹œ 비우기 - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - Checking for updates... - - - - Temporary installation of macro failed. - 매í¬ë¡œì˜ 임시 ì„¤ì¹˜ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. - - - - - Close - 닫기 - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - - - - Maintainer - Maintainer - - - - - - - Author - 작성ìž: - - - - New Python Version Detected - 새로운 파ì´ì¬ ë²„ì „ì´ ê°ì§€ë˜ì—ˆìŠµë‹ˆë‹¤ - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - 처리 중입니다. 기다려주세요... - - - - - Update - ì—…ë°ì´íЏ - - - - Updating... - ì—…ë°ì´íЏ 중... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installation location - - - - Repository URL - 저장소 URL - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Disabled - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Install - Install - - - - Uninstall - Uninstall - - - - Enable - 활성화 - - - - Disable - 비활성화 - - - - - Check for update - Check for update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - 실행 - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - 매í¬ë¡œ {} ì„¤ì¹˜ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤ - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - ìžë™ - - - - - Workbench - 작업대 - - - - Addon - Addon - - - - Python - 파ì´ì¬ - - - - Yes - Yes - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Other... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - 파ì´ì¬ì„ 실행할 수 없습니다 - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - 프리ìºë“œì˜ 애드온 관리ìžë¡œ ì„¤ì¹˜ëœ ë§¤í¬ë¡œ - - - - - Run - Indicates a macro that can be 'run' - 실행 - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - ì´ë¦„ - - - - Class - í´ëž˜ìФ - - - - Description - 설명 - - - - Subdirectory - Subdirectory - - - - Files - Files - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - 검색하기... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - ìž‘ì—…ëŒ€ì— ê´€í•œ 세부정보를 위해 í´ë¦­ - - - - Click for details about macro {} - 매í¬ë¡œ {} ì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì„ ë³´ë ¤ë©´ í´ë¦­í•˜ì„¸ìš” - - - - Maintainers: - Maintainers: - - - - Tags - 태그 - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Installed version - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Available version - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Any - - - - Macro - 매í¬ë¡œ - - - - Preference Pack - Preference Pack - - - - Installation Status - Installation Status - - - - Not installed - Not installed - - - - Filter - í•„í„° - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - 저장소 URL - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - ìžë™ ìƒì„±ëœ 매í¬ë¡œ ë„êµ¬ëª¨ìŒ - - - - QObject - - - Addon Manager - 애드온 매니저 - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_lt.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_lt.qm deleted file mode 100644 index a564526eef41bfea585f72aa4f3ce4db932fd3de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67207 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 O8Gk!W{bhCi-2VqAziKQ1 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_lt.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_lt.ts deleted file mode 100644 index 329f6a0a7a..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_lt.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Custom repository - - - - Repository URL - Repository URL - - - - Branch - Branch - - - - CompactView - - - - Icon - Piktograma - - - - - <b>Package Name</b> - <b>Package Name</b> - - - - - Version - Laida - - - - - Description - Aprašymas - - - - Update Available - Update Available - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - Dependencies - - - - Dependency type - Dependency type - - - - Name - Pavadinimas - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - FreeCAD Addons - „FreeCad“ papildiniai - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Aprašymas - - - - Discussion URL - Discussion URL - - - - Icon - Piktograma - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Repository URL - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Laida - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Papildinių tvarkyklė - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Tęsti - - - - Cancel - Atšaukti - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - - Icon - Piktograma - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - Laida - - - - - (tags) - (tags) - - - - - Description - Aprašymas - - - - - Maintainer - Prižiūrėtojas - - - - Update Available - Update Available - - - - labelSort - labelSort - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - Licenses - Licenses - - - - License - Licencija - - - - License file - License file - - - - People - People - - - - Kind - Rūšis - - - - Name - Pavadinimas - - - - Email - El. paštas - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - Cache update frequency - Podėlio atnaujinimo dažnis - - - - Manual (no automatic updates) - Rankinis (savaiminis atnaujinimas išjungtas) - - - - Daily - Kasdien - - - - Weekly - Kas savaitę - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Proxy - Tarpinis serveris - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Advanced Options - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Įdiegti - - - - Uninstall - Išdiegti - - - - Update - Atnaujinti - - - - Run Macro - Vykdyti makrokomandą - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Dialogas - - - - TextLabel - Žymė - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Makrokomandos - - - - Preference Pack - Preference Pack - - - - Workbench - Darbastalis - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Nuostatų rinkinio pavadinimas - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Klasė, apibrėžianti "Piktogramos" nario duomenis - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Piktograma - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Laida - - - - Description - Aprašymas - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Rodomasis pavadinimas - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Taip - - - - No - Ne - - - - Never - Niekada - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Pavadinimas: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Taip - - - - No - Ne - - - - Never - Niekada - - - - AddonsInstaller - - - Starting up... - Starting up... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - Atnaujinti vietinį podėlį - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - Checking for updates... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Užverti - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - - - - Maintainer - Prižiūrėtojas - - - - - - - Author - Autorius - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Atnaujinti - - - - Updating... - Updating... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installation location - - - - Repository URL - Repository URL - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Disabled - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Install - Įdiegti - - - - Uninstall - Išdiegti - - - - Enable - Įgalinti - - - - Disable - Išjungti - - - - - Check for update - Check for update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Paleisti - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Neįmanoma rasti piktogramos {} - - - - Select an icon file for this content item - Pasirinkite piktogramos failą turinio nariui - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automatinis - - - - - Workbench - Darbastalis - - - - Addon - Papildinys - - - - Python - Python - - - - Yes - Taip - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Other... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Paleisti - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Pavadinimas - - - - Class - Klasė - - - - Description - Aprašymas - - - - Subdirectory - Subdirectory - - - - Files - Rinkmenos - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Pasirinkite piktogramos failą šiam paketui - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Paieška... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Žymės - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Installed version - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Available version - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Bet koks - - - - Macro - Makrokomandos - - - - Preference Pack - Preference Pack - - - - Installation Status - Installation Status - - - - Not installed - Not installed - - - - Filter - Filtras - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Vietinis - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Repository URL - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Įvertinimas - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Papildinių tvarkyklė - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_nl.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_nl.qm deleted file mode 100644 index e7291f186ac66eeadc35acb31b65766558b004f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69711 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 n)DZNUvte35bn diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_nl.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_nl.ts deleted file mode 100644 index 711affe423..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_nl.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Aangepaste repository - - - - Repository URL - URL van de repository - - - - Branch - Aftakking - - - - CompactView - - - - Icon - Pictogram - - - - - <b>Package Name</b> - <b>Pakket Naam</b> - - - - - Version - Versie - - - - - Description - Omschrijving - - - - Update Available - Update beschikbaar - - - - UpdateAvailable - UpdateBeschikbaar - - - - DependencyDialog - - - Dependencies - Afhankelijkheden - - - - Dependency type - Afhankelijkheidstype - - - - Name - Naam - - - - Optional? - Optioneel? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Afhankelijkheden oplossen - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Deze uitbreiding heeft de volgende vereiste en optionele afhankelijkheden. Je moet ze installeren voordat deze uitbreiding kan worden gebruikt. - -Wilt u dat de Uitbreidingsmanager deze automatisch installeert? Kies "Negeren" om de uitbreiding te installeren zonder de afhankelijkheden te installeren. - - - - FreeCAD Addons - FreeCAD Uitbreidingen - - - - Required Python modules - Vereiste Python modules - - - - Optional Python modules - Optionele Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Uitbreiding ontwikkelaar gereedschappen - - - - Path to Addon - Pad naar de uitbreiding - - - - - Browse... - Bladeren... - - - - Metadata - Metagegevens - - - - Primary branch - Primaire branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Uitleg waar deze uitbreiding over gaat. Wordt weergegeven in de Uitbreidingsmanager. Het is niet nodig om te vermelden dat dit een FreeCAD Uitbreiding is. - - - - Description - Omschrijving - - - - Discussion URL - Discussie URL - - - - Icon - Pictogram - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) of CalVer (2022.08.30) stijlen worden ondersteund - - - - Set to today (CalVer style) - Op vandaag instellen (CalVer stijl) - - - - - - - (Optional) - (Optioneel) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Wordt weergegeven in de Uitbreidingsmanager's lijst met Uitbreidingen. Zou het woord "FreeCAD" niet moeten bevatten, en moet een geldige mapnaam zijn op alle ondersteunende besturingssystemen. - - - - README URL - LEESME URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Omdat dit wordt weergegeven in het programma FreeCAD, in de Uitbreidingsmanager, is het niet nodig om ruimte te gebruiken om dingen te zeggen zoals "dit is een FreeCAD Uitbreiding..." -- zeg gewoon wat het doet. - - - - Repository URL - URL van de repository - - - - Website URL - Website-URL - - - - Documentation URL - URL documentatie - - - - Addon Name - Naam van de uitbreiding - - - - Version - Versie - - - - (Recommended) - (Aanbevolen) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optioneel, slechts 3.x versie ondersteund) - - - - Detect... - Detecteer... - - - - Addon Contents - Inhoud van de uitbreiding - - - - Dialog - - - Addon Manager - Uitbreidingsmanager - - - - Edit Tags - Labels bewerken - - - - Comma-separated list of tags describing this item: - Komma-gescheiden lijst van tags die dit item beschrijven: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Veelvoorkomende tags zijn "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Doorgaan - - - - Cancel - Annuleren - - - - EditDependencyDialog - - - Edit Dependency - Bewerk afhankelijkheid - - - - Dependency Type - Afhankelijkheid Type - - - - Dependency - Afhankelijkheid - - - - Package name, if "Other..." - Pakket naam, indien "Anders..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - LET OP: Als "Anders..." is geselecteerd, is het pakket niet onderdeel van het ALLOWED_PYTHON_PACKAGES.txt bestand, en zal niet automatisch worden geïnstalleerd door de Uitbreidingsmanager. Stuur een PR naar <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> om toevoegen van een pakket aan te vragen. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Als dit een optionele afhankelijkheid is, biedt de Uitbreidingsmanager aan om deze te installeren (indien mogelijk), maar zal de installatie niet blokkeren als de gebruiker besluit het pakket niet te installeren, of niet kan installeren. - - - - Optional - Optioneel - - - - ExpandedView - - - - Icon - Pictogram - - - - - <h1>Package Name</h1> - <h1>Pakket Naam</h1> - - - - - Version - Versie - - - - - (tags) - (labels) - - - - - Description - Omschrijving - - - - - Maintainer - Beheerder - - - - Update Available - Update beschikbaar - - - - labelSort - labelSort - - - - UpdateAvailable - UpdateBeschikbaar - - - - Form - - - Licenses - Licenties - - - - License - Licentie - - - - License file - Licentiebestand - - - - People - Personen - - - - Kind - Soort - - - - Name - Naam - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Geavanceerd Versie Overzicht - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - In volgende versies van FreeCAD Uitbreidingsmanager zal de ontwikkelaars instelling van een specifieke branch of tag voor gebruik met een specifieke versie van FreeCAD, worden ondersteund (b.v. het instellen van een specifiek label dat de laatste versie van uw uitbreiding v0.19 ondersteund, enz.) - - - - FreeCAD Version - FreeCAD versie - - - - Best-available branch, tag, or commit - Meest beschikbare branche, tag of commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Ondersteunde FreeCAD versies - - - - Minimum FreeCAD Version Supported - Minimale FreeCAD versie ondersteund - - - - - Optional - Optioneel - - - - Maximum FreeCAD Version Supported - Maximale FreeCAD versie ondersteund - - - - Advanced version mapping... - Geavanceerd versie overzicht... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Uitbreidingsmanager voorkeuren - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Download Macro-metadata (ongeveer 10MB) - - - - Cache update frequency - Cache update frequentie - - - - Manual (no automatic updates) - Handmatig (geen automatische updates) - - - - Daily - Dagelijks - - - - Weekly - Wekelijks - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Verberg uitbreidingen die gemarkeerd zijn als -Alleen voor Python 2- - - - - Hide Addons marked Obsolete - Verberg uitbreidingen die gemarkeerd zijn als -Obsolete- - - - - Hide Addons that require a newer version of FreeCAD - Verberg uitbreidingen die een nieuwere versie van FreeCAD vereisen - - - - Custom repositories - Aangepaste repositories - - - - Proxy - Proxy - - - - No proxy - Geen proxy - - - - User system proxy - Proxy van het systeem van de gebruiker - - - - User-defined proxy: - Proxy gedefinieerd door gebruiker: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Geavanceerde Opties - - - - Activate Addon Manager options intended for developers of new Addons. - Activeer de voorkeuren voor Uitbreidingsmanager voor ontwikkelaars van nieuwe uitbreidingen. - - - - Addon developer mode - Uitbreiding ontwikkelaar gereedschappen - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Verwijder een geselecteerde macro of werkbank - - - - Install - Installeren - - - - Uninstall - De-installeren - - - - Update - Update - - - - Run Macro - Macro uitvoeren - - - - Change branch - Wijzig branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Beheer Python afhankelijkheden - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - De volgende Python pakketten zijn lokaal door de Uitbreidingsmanager geïnstalleerd om te voldoen aan de uitbreidingsafhankelijkheden. Installatie locatie: - - - - Package name - Pakketnaam - - - - Installed version - Geïnstalleerde versie - - - - Available version - Beschikbare versie - - - - Used by - Gebruikt door - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Een asterisk (*) in de "Gebruikt door" kolom geeft een optionele afhankelijkheid aan. Merk op dat Gebruikt door alleen directe imports in de uitbreiding aangeeft. Andere Python pakketten waarvan die pakketten afhankelijk zijn kunnen ook geïnstalleerd zijn. - - - - Update all available - Update alle beschikbare - - - - SelectFromList - - - Dialog - Dialoog - - - - TextLabel - Tekstbenaming - - - - UpdateAllDialog - - - Updating Addons - Uitbreidingen aan het bijwerken - - - - Updating out-of-date addons... - Verouderde uitbreidingen aan het bijwerken... - - - - addContentDialog - - - Content Item - Inhoud Item - - - - Content type: - Soort: - - - - Macro - Macro - - - - Preference Pack - Voorkeurspakket - - - - Workbench - Werkbank - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Als dit het enige is in de uitbreiding, kunnen alle andere metadata worden overgenomen van het bovenste niveau, en hoeft hier niet nader te worden gespecificeerd. - - - - This is the only item in the Addon - Dit is het enige onderwerp in de uitbreiding - - - - Main macro file - Hoofd macrobestand - - - - The file with the macro's metadata in it - Het bestand met de metadata van de macro er in - - - - - - Browse... - Bladeren... - - - - Preference Pack Name - Naam van het voorkeuren pakket - - - - Workbench class name - Werkbank class naam - - - - Class that defines "Icon" data member - Class die het "Icoon" gegevens onderdeel definieert - - - - Subdirectory - Submap - - - - Optional, defaults to name of content item - Optioneel, staat standaard op de naam van het onderwerp van de inhoud - - - - Icon - Pictogram - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Labels... - - - - Dependencies... - Afhankelijkheden... - - - - FreeCAD Versions... - FreeCAD versie... - - - - Other Metadata - Andere metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versie - - - - Description - Omschrijving - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) of CalVer (2022.08.30) stijlen worden ondersteund - - - - Set to today (CalVer style) - Op vandaag instellen (CalVer stijl) - - - - Display Name - Weergavenaam - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Knop toevoegen? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Ja - - - - No - Nee - - - - Never - Nooit - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Auteursrechtinformatie - - - - Copyright holder: - Auteursrechthouder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Persoon toevoegen - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Naam: - - - - Email: - E-mail: - - - - Email is required for maintainers, and optional for authors. - E-mail is vereist voor beheerders en optioneel voor auteurs. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Gebruikersnaam - - - - Password - Wachtwoord - - - - selectLicenseDialog - - - Select a license - Selecteer een licentie - - - - About... - Over... - - - - License name: - Naam van de licentie: - - - - Path to license file: - Pad naar licentiebestand: - - - - (if required by license) - (indien vereist door de licentie) - - - - Browse... - Bladeren... - - - - Create... - Aanmaken... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Werkbalk selecteren - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Elke keer vragen - - - - toolbar_button - - - - Add button? - Knop toevoegen? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Ja - - - - No - Nee - - - - Never - Nooit - - - - AddonsInstaller - - - Starting up... - Opstarten... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Aangepaste repo lijst veranderd, geheugen-update forceren... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - U moet FreeCAD herstarten om de wijzigingen toe te passen. - - - - Restart now - Nu opnieuw opstarten - - - - Restart later - Later opnieuw opstarten - - - - - Refresh local cache - Lokale cache vernieuwen - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Bezig met updaten van cache... - - - - - Checking for updates... - Zoeken naar updates... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Sluiten - - - - Update all addons - Update all addons - - - - Check for updates - Op updates controleren - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - Geen updates beschikbaar - - - - - - Cannot launch a new installer until the previous one has finished. - Kan geen nieuw installatieprogramma starten totdat de vorige klaar is. - - - - - - - Maintainer - Beheerder - - - - - - - Author - Auteur - - - - New Python Version Detected - Nieuwe Python versie gedetecteerd - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Bezig, even geduld... - - - - - Update - Update - - - - Updating... - Updaten... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Bevestig verwijdering - - - - Are you sure you want to uninstall {}? - Weet u zeker dat u {} wilt de-installeren? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - {} wordt verwijderd - - - - - Uninstall complete - De-installatie voltooid - - - - - Uninstall failed - Verwijderen mislukt - - - - Version {version} installed on {date} - Versie {version} geïnstalleerd op {date} - - - - Version {version} installed - Versie {version} geïnstalleerd - - - - Installed on {date} - Geïnstalleerd op {date} - - - - - - - Installed - Geïnstalleerd - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Controle van updates bezig - - - - Installation location - Locatie van de installatie - - - - Repository URL - URL van de repository - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Uitgeschakeld - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update beschikbaar voor versie {} - - - - This is the latest version available - Dit is de nieuwste versie die beschikbaar is - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Geslaagd - - - - Install - Installeren - - - - Uninstall - De-installeren - - - - Enable - Schakel in - - - - Disable - Uitschakelen - - - - - Check for update - Controleer op update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Uitvoeren - - - - Change branch... - Change branch... - - - - Return to package list - Terug naar de lijst met pakketten - - - - Checking connection - Verbinding controleren - - - - Checking for connection to GitHub... - Controleren op verbinding met GitHub... - - - - Connection failed - Verbinden mislukt - - - - Missing dependency - Ontbrekende afhankelijkheid - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Andere... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Locatie van nieuwe licentiebestand - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Kan pictogram niet vinden op {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is geen submap van {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automatisch - - - - - Workbench - Werkbank - - - - Addon - Uitbreiding - - - - Python - Python - - - - Yes - Ja - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Andere... - - - - Too many to list - Te veel om weer te geven - - - - - - - - - Missing Requirement - Ontbrekende Vereiste - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Druk op OK om toch te installeren. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Afhankelijkheden installeren - - - - - Cannot execute Python - Kan Python niet uitvoeren - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Afhankelijkheden konden niet worden geïnstalleerd. Toch doorgaan met de installatie van {}? - - - - - Cannot execute pip - Kan -pip- niet uitvoeren - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Installatie pakket mislukt - - - - See Report View for detailed failure log. - Zie rapportweergave voor gedetailleerde foutenlog. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Annuleren - - - - Cancelling installation of '{}' - Installatie van '{}' annuleren - - - - {} was installed successfully - {} is succesvol geïnstalleerd - - - - - Installation Failed - Installatie mislukt - - - - Failed to install {} - Installatie van {} is mislukt - - - - - Create new toolbar - Nieuwe werkbalk maken - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Uitvoeren - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Ongeldige metadata in het bestand {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Naam - - - - Class - Klasse - - - - Description - Omschrijving - - - - Subdirectory - Submap - - - - Files - Bestanden - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installatie mislukt - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is geldig - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Zoeken... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Beheerders: - - - - Tags - Labels - - - - {} ★ on GitHub - {} ★ op GitHub - - - - No ★, or not on GitHub - Geen ★, of niet op GitHub - - - - Created - Aangemaakt - - - - Updated - Bijgewerkt - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update beschikbaar - - - - - Pending restart - Wachten op herstarten - - - - - DISABLED - UITGESCHAKELD - - - - Installed version - Geïnstalleerde versie - - - - Unknown version - Onbekende versie - - - - Installed on - Geïnstalleerd op - - - - Available version - Beschikbare versie - - - - Filter by... - Filteren op... - - - - Addon Type - Addon Type - - - - - Any - Elke - - - - Macro - Macro - - - - Preference Pack - Voorkeurspakket - - - - Installation Status - Installatiestatus - - - - Not installed - Niet geïnstalleerd - - - - Filter - Filter - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - Er zijn lokale wijzigingen - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Lokaal - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Laatst bijgewerkt - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Er is een fout opgetreden bij het importeren van {} - - - - An unknown error occurred - Er is een onbekende fout opgetreden - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Extra geïnstalleerd bestand {} verwijderd - - - - Error while trying to remove extra installed file {} - Fout bij het verwijderen van extra geïnstalleerd bestand {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Kan geen verbinding maken met GitHub. Controleer je verbinding en proxy-instellingen. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - URL van de repository - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Aan het installeren - - - - Succeeded - Geslaagd - - - - Failed - Mislukt - - - - Update was cancelled - Update werd geannuleerd - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Uitgebreide weergave - - - - Compact view - Compacte weergave - - - - Alphabetical - Sort order - Alfabetisch - - - - Last Updated - Sort order - Laatst bijgewerkt - - - - Date Created - Sort order - Datum aangemaakt - - - - GitHub Stars - Sort order - GitHub Sterren - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Uitbreidingsmanager - - - - Manage external workbenches, macros, and preference packs - Beheer externe werkbanken, macro's en voorkeurspakketten - - - - AddonInstaller - - - Finished removing {} - Verwijderen van {} voltooid - - - - Failed to remove some files - Kan sommige bestanden niet verwijderen - - - - Addons installer - - - Finished updating the following addons - Bijwerken van de volgende uitbreidingen is voltooid - - - - Workbench - - - Auto-Created Macro Toolbar - Automatisch aangemaakte Macro werkbalk - - - - QObject - - - Addon Manager - Uitbreidingsmanager - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_no.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_no.qm deleted file mode 100644 index 7015e809a37328d9df0ec3f86e7636a1a680d8f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13995 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_no.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_no.ts deleted file mode 100644 index c4958b17db..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_no.ts +++ /dev/null @@ -1,424 +0,0 @@ - - - - - AddonInstaller - - - Installed location - Installasjonssted - - - - AddonsInstaller - - - Unable to fetch the code of this macro. - Kan ikke hente koden for denne makroen. - - - - Unable to retrieve a description for this macro. - Kan ikke hente en beskrivelse for denne makroen. - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - Programtilleggene som kan installeres her, er ikke offisielt en del av FreeCAD, og er ikke vurdert av FreeCAD-teamet. Vær sikker pÃ¥ at du vet hva du installerer! - - - - Addon manager - HÃ¥ndterer for tilleggsmoduler - - - - You must restart FreeCAD for changes to take effect. Press Ok to restart FreeCAD now, or Cancel to restart later. - Du mÃ¥ starte FreeCAD pÃ¥ nytt for at endringene skal tre i kraft. Trykk OK for Ã¥ starte FreeCAD pÃ¥ nytt, eller Avbryt Ã¥ starte pÃ¥ nytt senere. - - - - Checking for updates... - Ser etter oppdateringer... - - - - Apply - Bruk - - - - update(s) - oppdatering(er) - - - - No update available - Ingen oppdatering tilgjengelig - - - - Macro successfully installed. The macro is now available from the Macros dialog. - Makro installert. Makroen er nÃ¥ tilgjengelig i Makrodialogen. - - - - Unable to install - Kunne ikke installere - - - - Addon successfully removed. Please restart FreeCAD - Tillegg fjernet. Start FreeCAD pÃ¥ nytt - - - - Unable to remove this addon - Kan ikke fjerne dette tillegget - - - - Macro successfully removed. - Makroen er fjernet. - - - - Macro could not be removed. - Makroen kunne ikke fjernes. - - - - Unable to download addon list. - Kunne ikke laste ned liste over tilleggsmoduler. - - - - Workbenches list was updated. - Liste over arbeidsbenker ble oppdatert. - - - - Outdated GitPython detected, consider upgrading with pip. - Utdatert GitPython oppdaget, vurder oppgradering med pip. - - - - List of macros successfully retrieved. - Makroliste hentet. - - - - Retrieving description... - Henter beskrivelse... - - - - Retrieving info from - Henter informasjon fra - - - - An update is available for this addon. - En oppdatering er tilgjengelig for denne tilleggsmodulen. - - - - This addon is already installed. - Denne tilleggsmoduler er allerede installert. - - - - Retrieving info from git - Henter informasjon fra git - - - - Retrieving info from wiki - Henter informasjon fra wiki - - - - GitPython not found. Using standard download instead. - GitPython ble ikke funnet. Bruker standard nedlasting. - - - - Your version of python doesn't appear to support ZIP files. Unable to proceed. - Den installerte versjonen av Python støtter ikke ZIP-filer. Kan ikke fortsette. - - - - Workbench successfully installed. Please restart FreeCAD to apply the changes. - Arbeidsbenken er installert. Start FreeCAD pÃ¥ nytt for at den skal bli tilgjengelig. - - - - Missing workbench - Arbeidsbenken mangler - - - - Missing python module - Python-modul mangler - - - - Missing optional python module (doesn't prevent installing) - Python-modul mangler (hindrer ikke installering) - - - - Some errors were found that prevent to install this workbench - Noen feil ble funnet som hindrer installering av denne arbeidsbenken - - - - Please install the missing components first. - Vennligst installer manglende komponenter først. - - - - Error: Unable to download - Feil: Kan ikke lastes ned - - - - Successfully installed - Installert - - - - GitPython not installed! Cannot retrieve macros from git - GitPython er ikke installert! Kan ikke hente makroer fra git - - - - Installed - Installert - - - - Update available - Oppdatering tilgjengelig - - - - Restart required - Omstart nødvendig - - - - This macro is already installed. - Denne makroen er allerede installert. - - - - A macro has been installed and is available under Macro -> Macros menu - En makro er installert og er tilgjengelig under Makro -> Makroer menyen - - - - This addon is marked as obsolete - Denne tilleggsmodulen er merket utdatert - - - - This usually means it is no longer maintained, and some more advanced addon in this list provides the same functionality. - Dette betyr vanligvis at den ikke lenger vedlikeholdes og at andre mer avanserte tilleggsmoduler i denne listen gir samme funksjonalitet. - - - - Error: Unable to locate zip from - Feil: Finner ikke zip-filen fra - - - - Something went wrong with the Git Macro Retrieval, possibly the Git executable is not in the path - Noe gikk galt med Git Macro-nedlastingen, muligens er ikke Git lagt til søkestien - - - - This addon is marked as Python 2 Only - Denne tilleggsmodulen er markert som kun for Python 2 - - - - This workbench may no longer be maintained and installing it on a Python 3 system will more than likely result in errors at startup or while in use. - Denne arbeidsbenken vedlikeholdes ikke lenger og vil sannsynligvis gi problemer om den installeres pÃ¥ et system med Python 3. - - - - User requested updating a Python 2 workbench on a system running Python 3 - - Brukeren forsøkte Ã¥ oppdatere en arbeidsbenk for Python 2 pÃ¥ et system med Python 3 - - - - - Workbench successfully updated. Please restart FreeCAD to apply the changes. - Arbeidsbenken er oppdatert. Start FreeCAD pÃ¥ nytt for Ã¥ se endringene. - - - - User requested installing a Python 2 workbench on a system running Python 3 - - Brukeren forsøkte Ã¥ installer en arbeidsbenk for Python 2 pÃ¥ et system med Python 3 - - - - - Appears to be an issue connecting to the Wiki, therefore cannot retrieve Wiki macro list at this time - Makrolisten fra Wiki kan ikke hentes, sannsynligvis pÃ¥ grunn av et tilkoblingsproblem - - - - Raw markdown displayed - Raw markdown displayed - - - - Python Markdown library is missing. - Python Markdown library is missing. - - - - Dialog - - - Workbenches - Workbenches - - - - Macros - Makroer - - - - Execute - Kjør - - - - Downloading info... - Laster ned informasjon... - - - - Update all - Oppdater alt - - - - Executes the selected macro, if installed - Den valgte makroen kjøres hvis den er installert - - - - Uninstalls a selected macro or workbench - Den valgte makroen eller arbeidsbenken fjernes fra fra systemet - - - - Installs or updates the selected macro or workbench - Den valgte makroen eller arbeidsbenken installeres eller oppdateres - - - - Download and apply all available updates - Last ned og legg till alle tilgjengelige oppdateringer - - - - Custom repositories (one per line): - Egendefinerte repositorier (ett per linje): - - - - Sets configuration options for the Addon Manager - Viser konfigurasjonsvalg for hÃ¥ndtereren av tilleggsmoduler - - - - Configure... - Konfigurer... - - - - Addon manager options - Valg for hÃ¥ndterer av tilleggsmoduler - - - - Uninstall selected - Avinstaller valgte - - - - Install/update selected - Installer/oppdater valgte - - - - Close - Lukk - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - HÃ¥ndtereren for tilleggsmoduler ser etter tilgjengelige oppdateringer nÃ¥r den starter hvis dette alternativet er valgt (krever at pakken GitPython er installert pÃ¥ systemet) - - - - Automatically check for updates at start (requires GitPython) - Se etter oppdateringer ved oppstart (krever GitPython) - - - - Proxy - Mellomtjener - - - - No proxy - Ikke bruk mellomtjener - - - - User system proxy - Mellomtjener for brukersystem - - - - User defined proxy : - Brukerdefinert mellomtjener: - - - - Addon Manager - HÃ¥ndterer for tilleggsmoduler - - - - Close the Addon Manager - Lukk hÃ¥ndtereren for tilleggsmoduler - - - - You can use this window to specify additional addon repositories -to be scanned for available addons - Du kan spesifisere flere repositorier som skal søkes for tilleggsmoduler i dette vinduet - - - - Std_AddonMgr - - - &Addon manager - &HÃ¥ndterer for tilleggsmoduler - - - - Manage external workbenches and macros - HÃ¥ndter eksterne arbeidsbenker og makroer - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_pl.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_pl.qm deleted file mode 100644 index e7f945957860c5a85f2641754fcd95c6fcc5da04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73201 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 Iy&ZG^UlQRd00000 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_pl.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_pl.ts deleted file mode 100644 index 547660f106..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_pl.ts +++ /dev/null @@ -1,2492 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Repozytoria użytkownika - - - - Repository URL - Adres URL repozytorium - - - - Branch - Gałąź - - - - CompactView - - - - Icon - Ikonka - - - - - <b>Package Name</b> - <b>Nazwa pakietu</b> - - - - - Version - Wersja - - - - - Description - Opis - - - - Update Available - Aktualizacja jest dostÄ™pna - - - - UpdateAvailable - DostÄ™pna aktualizacja - - - - DependencyDialog - - - Dependencies - ZależnoÅ›ci - - - - Dependency type - Typ zależnoÅ›ci - - - - Name - Nazwa - - - - Optional? - Opcjonalne? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Rozwiąż zależnoÅ›ci - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Ten dodatek ma nastÄ™pujÄ…ce wymagane i opcjonalne zależnoÅ›ci. Musisz je zainstalować, zanim ten dodatek bÄ™dzie mógÅ‚ być używany. - -Czy chcesz, aby Menadżer dodatków zainstalowaÅ‚ je automatycznie? Wybierz "Zignoruj" aby zainstalować dodatek bez instalowania zależnoÅ›ci. - - - - FreeCAD Addons - Dodatki dla FreeCAD - - - - Required Python modules - Wymagane moduÅ‚y Python - - - - Optional Python modules - Opcjonalne moduÅ‚y Python - - - - DeveloperModeDialog - - - Addon Developer Tools - NarzÄ™dzia dla twórców dodatków - - - - Path to Addon - Åšcieżka do dodatku - - - - - Browse... - PrzeglÄ…daj... - - - - Metadata - Metadane - - - - Primary branch - Gałąź główna - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - WyjaÅ›nienie tego, co zawiera ten dodatek. WyÅ›wietlane w Menedżerze Dodatków. Nie jest to konieczne, aby stwierdzić, że jest to dodatek dla programu FreeCAD. - - - - Description - Opis - - - - Discussion URL - Adres URL dyskusji - - - - Icon - Ikonka - - - - Bugtracker URL - Adres URL systemu rejestracji błędów - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - ObsÅ‚ugiwane style semantyczne (1.2.3-beta) lub CalVer (2022.08.30) - - - - Set to today (CalVer style) - Ustaw na dzisiaj (styl CalVer) - - - - - - - (Optional) - (Opcjonalne) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - WyÅ›wietlany na liÅ›cie dodatków Menedżera dodatków. Nie powinien zawierać sÅ‚owa "FreeCAD". i musi być prawidÅ‚owÄ… nazwÄ… katalogu we wszystkich obsÅ‚ugiwanych systemach operacyjnych. - - - - README URL - Adres URL pliku readme - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - Wskazówka: ponieważ jest to wyÅ›wietlane w programie FreeCAD, w Menedżerze Dodatków, nie jest konieczne zajmowanie miejsca informacjami takimi jak "To jest dodatek do programu FreeCAD..." -- po prostu powiedz, co on robi. - - - - Repository URL - Adres URL repozytorium - - - - Website URL - Adres URL strony - - - - Documentation URL - Adres URL dokumentacji - - - - Addon Name - Nazwa dodatku - - - - Version - Wersja - - - - (Recommended) - (zalecane) - - - - Minimum Python - Minimalna wersja Pythona - - - - (Optional, only 3.x version supported) - (Opcjonalne, obsÅ‚ugiwana jest tylko wersja 3.x) - - - - Detect... - Wykryj ... - - - - Addon Contents - Zawartość dodatku - - - - Dialog - - - Addon Manager - Menedżer dodatków - - - - Edit Tags - Edytuj tagi - - - - Comma-separated list of tags describing this item: - Lista tagów oddzielonych przecinkami, opisujÄ…cych element: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - UWAGA: ZwykÅ‚e tagi obejmujÄ… obiekty "ZÅ‚ożenie", "MES", "Siatka", "NURBS" itd. - - - - Add-on Manager: Warning! - Menedżer dodatków: Ostrzeżenie! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Menedżer dodatków zapewnia dostÄ™p do obszernej biblioteki przydatnych rozszerzeÅ„ dla FreeCAD, od osób trzecich. -Nie można zagwarantować ich bezpieczeÅ„stwa ani funkcjonalnoÅ›ci. - - - - Continue - Kontynuuj - - - - Cancel - Anuluj - - - - EditDependencyDialog - - - Edit Dependency - Edytuj zależność - - - - Dependency Type - Typ zależnoÅ›ci - - - - Dependency - Zależność - - - - Package name, if "Other..." - Nazwa pakietu, jeÅ›li "Inne ..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - UWAGA: JeÅ›li wybrano "Inne ...", pakiet nie jest w pliku ALLOWED_PYTHON_PACKAGES.txt i nie zostanie automatycznie zainstalowany przez Menedżera Dodatków. PrzeÅ›lij PR na <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a>, aby poprosić o dodanie pakietu. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - JeÅ›li jest to opcjonalna zależność, Menedżer dodatków zaoferuje zainstalowanie tej zależnoÅ›ci (jeÅ›li to możliwe), ale nie zablokuje instalacji, jeÅ›li użytkownik nie zdecyduje siÄ™ na zainstalowanie pakietu lub nie może go zainstalować. - - - - Optional - Opcjonalne - - - - ExpandedView - - - - Icon - Ikonka - - - - - <h1>Package Name</h1> - <h1>Nazwa pakietu</h1> - - - - - Version - Wersja - - - - - (tags) - (znaczniki) - - - - - Description - Opis - - - - - Maintainer - Opiekun - - - - Update Available - Aktualizacja jest dostÄ™pna - - - - labelSort - sortowanie etykiet - - - - UpdateAvailable - DostÄ™pna aktualizacja - - - - Form - - - Licenses - Licencje - - - - License - Licencja - - - - License file - Plik licencji - - - - People - Twórcy - - - - Kind - Rodzaj - - - - Name - Nazwa - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Zaawansowane mapowanie wersji - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - PrzyszÅ‚e wersje Menadżera dodatków FreeCAD bÄ™dÄ… wspierać deweloperów, ustawiajÄ…c konkretnÄ… gałąź lub tag do użytku z konkretnÄ… wersjÄ… FreeCAD (np. ustawiajÄ…c konkretny tag jako ostatniÄ… wersjÄ™ twojego dodatku, aby obsÅ‚ugiwaÅ‚ v0.19, itp.) - - - - FreeCAD Version - Wersja FreeCAD - - - - Best-available branch, tag, or commit - Najlepsza dostÄ™pna gałąź, tag lub commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Wspierane wersje FreeCAD - - - - Minimum FreeCAD Version Supported - Minimalna wersja FreeCAD, która jest obsÅ‚ugiwana - - - - - Optional - Opcjonalne - - - - Maximum FreeCAD Version Supported - Maksymalna wersja FreeCAD, która jest obsÅ‚ugiwana - - - - Advanced version mapping... - Zaawansowane mapowanie wersji ... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opcje Menedżera dodatków - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - JeÅ›li ta opcja jest zaznaczona, podczas uruchamiania Menedżera dodatków, -zainstalowane dodatki bÄ™dÄ… sprawdzane pod kÄ…tem dostÄ™pnych aktualizacji - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Pobierz metadane makrodefinicji (okoÅ‚o 10 MB) - - - - Cache update frequency - CzÄ™stotliwość aktualizacji pamiÄ™ci podrÄ™cznej - - - - Manual (no automatic updates) - RÄ™cznie (bez aktualizacji automatycznych) - - - - Daily - Codziennie - - - - Weekly - Tygodniowo - - - - Hide Addons without a license - Ukryj dodatki bez zdefiniowanej licencji - - - - Hide Addons with non-FSF Free/Libre license - Ukryj dodatki bez licencji FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Ukryj dodatki z licencjÄ… niezatwierdzonÄ… przez OSI - - - - Hide Addons marked Python 2 Only - Ukryj dodatki wymagajÄ…ce Å›rodowiska Python 2 - - - - Hide Addons marked Obsolete - Ukryj dodatki oznaczone jako przestarzaÅ‚e - - - - Hide Addons that require a newer version of FreeCAD - Ukryj dodatki, które wymagajÄ… nowszej wersji programu FreeCAD - - - - Custom repositories - Repozytoria użytkownika - - - - Proxy - Serwer poÅ›redniczÄ…cy - - - - No proxy - Bez serwera poÅ›redniczÄ…cego - - - - User system proxy - Użyj ustawieÅ„ serwera poÅ›redniczÄ…cego z systemu - - - - User-defined proxy: - Serwer poÅ›redniczÄ…cy użytkownika: - - - - Score source URL - Adres URL źródÅ‚a wyniku - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Adres URL dla danych o punktacji dodatków (Szczegóły dotyczÄ…ce formatowania i hostingu można znaleźć na stronie wiki Menedżera dodatków). - - - - Path to Git executable (optional): - Åšcieżka do pliku wykonywalnego Git (opcjonalnie): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opcje zaawansowane - - - - Activate Addon Manager options intended for developers of new Addons. - Aktywuj opcje Menedżera dodatków przeznaczone dla twórców nowych dodatków. - - - - Addon developer mode - Tryb dewelopera dodatków - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Odinstalowuje wybrane makrodefinicje lub Å›rodowiska pracy - - - - Install - Zainstaluj - - - - Uninstall - Odinstaluj - - - - Update - Zaktualizuj - - - - Run Macro - Uruchom makrodefinicjÄ™ - - - - Change branch - ZmieÅ„ gałąź - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - ZarzÄ…dzaj zależnoÅ›ciami Å›rodowiska Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - NastÄ™pujÄ…ce pakiety Å›rodowiska Python zostaÅ‚y zainstalowane lokalnie przez menedżera dodatków w celu speÅ‚nienia zależnoÅ›ci dodatków. Lokalizacja plików instalacji: - - - - Package name - Nazwa pakietu - - - - Installed version - Wersja zainstalowana - - - - Available version - Wersja dostÄ™pna - - - - Used by - Używany przez - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Gwiazdka (*) w kolumnie "Używany przez" wskazuje zależność opcjonalnÄ…. Zauważ, że kolumna "Używany przez" zapisuje tylko bezpoÅ›redni import w dodatku. Inne pakiety Å›rodowiska Python, od których te pakiety zależą, mogÅ‚y również zostać zainstalowane. - - - - Update all available - Aktualizuj wszystkie dostÄ™pne - - - - SelectFromList - - - Dialog - Okno dialogowe - - - - TextLabel - Etykieta tekstu - - - - UpdateAllDialog - - - Updating Addons - Aktualizacja dodatków - - - - Updating out-of-date addons... - Aktualizacja nieaktualnych dodatków ... - - - - addContentDialog - - - Content Item - Element zawartoÅ›ci - - - - Content type: - Typ zawartoÅ›ci: - - - - Macro - Makrodefinicja - - - - Preference Pack - Pakiet preferencji - - - - Workbench - Åšrodowisko pracy - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - JeÅ›li jest to jedyna rzecz w dodatku, wszystkie inne metadane mogÄ… być odziedziczone z najwyższego poziomu i nie muszÄ… być w tym miejscu okreÅ›lone. - - - - This is the only item in the Addon - To jest jedyny element w dodatku - - - - Main macro file - Plik główny makrodefinicji - - - - The file with the macro's metadata in it - Plik z metadanymi makrodefinicji - - - - - - Browse... - PrzeglÄ…daj ... - - - - Preference Pack Name - Nazwa Pakietu preferencji - - - - Workbench class name - Nazwa klasy Å›rodowiska pracy - - - - Class that defines "Icon" data member - Klasa, która definiuje element danych "Ikona" - - - - Subdirectory - Katalog podrzÄ™dny - - - - Optional, defaults to name of content item - Opcjonalne, domyÅ›lnie nazwa elementu zawartoÅ›ci - - - - Icon - Ikonka - - - - Optional, defaults to inheriting from top-level Addon - Opcjonalne, domyÅ›lnie odziedziczone z dodatku najwyższego poziomu - - - - Tags... - Tagi... - - - - Dependencies... - ZależnoÅ›ci... - - - - FreeCAD Versions... - Wersje FreeCAD... - - - - Other Metadata - Inne metadane - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - WyÅ›wietlany na liÅ›cie dodatków Menedżera dodatków. Nie powinien zawierać sÅ‚owa "FreeCAD". - - - - Version - Wersja - - - - Description - Opis - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - ObsÅ‚ugiwane style semantyczne (1.2.3-beta) lub CalVer (2022.08.30) - - - - Set to today (CalVer style) - Ustaw na dzisiaj (styl CalVer) - - - - Display Name - Nazwa wyÅ›wietlana - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Wszelkie pola pozostawione puste sÄ… dziedziczone z metadanych dodatku najwyższego poziomu, wiÄ™c technicznie wszystkie sÄ… opcjonalne. W przypadku dodatków z wieloma elementami zawartoÅ›ci każdy element powinien mieć unikalnÄ… nazwÄ™ wyÅ›wietlanÄ… i opis. - - - - add_toolbar_button_dialog - - - Add button? - Dodać przycisk? - - - - Add a toolbar button for this macro? - Dodać przycisk paska narzÄ™dzi dla tej makrodefinicji? - - - - Yes - Tak - - - - No - Nie - - - - Never - Nigdy - - - - change_branch - - - Change Branch - ZmieÅ„ gałąź - - - - Change to branch: - ZmieÅ„ na gałąź: - - - - copyrightInformationDialog - - - Copyright Information - Informacje o prawach autorskich - - - - Copyright holder: - WÅ‚aÅ›ciciel praw autorskich: - - - - Copyright year: - Rok praw autorskich: - - - - personDialog - - - Add Person - Dodaj osobÄ™ - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Opiekun to ktoÅ›, kto ma dostÄ™p do commitów w tym projekcie. Autorem jest każdy, kogo jeszcze chciaÅ‚byÅ› uwzglÄ™dnić. - - - - Name: - Nazwa: - - - - Email: - Adres e-mail: - - - - Email is required for maintainers, and optional for authors. - Adres e-mail jest wymagany dla opiekunów i opcjonalny dla autorów. - - - - proxy_authentication - - - Proxy login required - Wymagane logowanie do serwera proxy - - - - Proxy requires authentication - Serwer proxy wymaga uwierzytelnienia - - - - Proxy: - Serwer proxy: - - - - Placeholder for proxy address - Miejsce dla adresu serwera poÅ›redniczÄ…cego - - - - Realm: - Domena: - - - - Placeholder for proxy realm - Miejsce dla domeny serwera poÅ›redniczÄ…cego - - - - Username - Nazwa użytkownika - - - - Password - HasÅ‚o - - - - selectLicenseDialog - - - Select a license - Wybierz licencjÄ™ - - - - About... - O licencji ... - - - - License name: - Nazwa licencji: - - - - Path to license file: - Åšcieżka do pliku licencji: - - - - (if required by license) - (jeÅ›li wymaga tego licencja) - - - - Browse... - PrzeglÄ…daj ... - - - - Create... - Utwórz ... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Wybierz pasek narzÄ™dzi - - - - Select a toolbar to add this macro to: - Wybierz pasek narzÄ™dzi, do którego chcesz dodać tÄ™ makrodefinicjÄ™: - - - - Ask every time - Pytaj za każdym razem - - - - toolbar_button - - - - Add button? - Dodać przycisk? - - - - Add a toolbar button for this macro? - Dodać przycisk paska narzÄ™dzi dla tej makrodefinicji? - - - - Yes - Tak - - - - No - Nie - - - - Never - Nigdy - - - - AddonsInstaller - - - Starting up... - Uruchamianie ... - - - - Worker process {} is taking a long time to stop... - Zatrzymanie dziaÅ‚ajÄ…cego procesu {} zajmuje dużo czasu ... - - - - Previous cache process was interrupted, restarting... - - Poprzedni proces pamiÄ™ci podrÄ™cznej zostaÅ‚ przerwany, ponowne uruchamianie... - - - - - Custom repo list changed, forcing recache... - - Zmieniono listÄ™ repozytoriów użytkownika, wymuszajÄ…c ponowne buforowanie ... - - - - Addon manager - Menadżera dodatków - - - - You must restart FreeCAD for changes to take effect. - Musisz zrestartować FreeCAD, aby zmiany zaczęły obowiÄ…zywać. - - - - Restart now - Uruchom ponownie teraz - - - - Restart later - Uruchom ponownie później - - - - - Refresh local cache - OdÅ›wież pamięć podrÄ™cznÄ… - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Aktualizowanie pamiÄ™ci podrÄ™cznej ... - - - - - Checking for updates... - Sprawdzam dostÄ™pność aktualizacji ... - - - - Temporary installation of macro failed. - Tymczasowa instalacja makrodefinicji nie powiodÅ‚a siÄ™. - - - - - Close - Zamknij - - - - Update all addons - Aktualizuj wszystkie dodatki - - - - Check for updates - Sprawdź dostÄ™pność aktualizacji - - - - Python dependencies... - ZależnoÅ›ci Å›rodowiska Python ... - - - - Developer tools... - NarzÄ™dzia programisty ... - - - - Apply %n available update(s) - Zastosuj %n dostÄ™pne aktualizacje - - - - No updates available - Brak dostÄ™pnych aktualizacji - - - - - - Cannot launch a new installer until the previous one has finished. - Nie można uruchomić nowej instalacji, dopóki poprzednia nie zostanie zakoÅ„czona. - - - - - - - Maintainer - Opiekun - - - - - - - Author - Autor - - - - New Python Version Detected - Wykryto nowÄ… wersjÄ™ Å›rodowiska Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - WyglÄ…da na to, że po raz pierwszy ta wersja Python zostaÅ‚a użyta z Menedżerem dodatków. Czy chciaÅ‚byÅ› zainstalować dla niego te same automatycznie instalowane zależnoÅ›ci? - - - - Processing, please wait... - Przetwarzanie, proszÄ™ czekać ... - - - - - Update - Aktualizuj - - - - Updating... - AktualizujÄ™ ... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Nie można zaimportować QtNetwork -- wyglÄ…da na to, że nie jest zainstalowany w Twoim systemie. Twój dostawca może mieć pakiet dla tej zależnoÅ›ci (czÄ™sto nazywany np. "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Nie udaÅ‚o siÄ™ przekonwertować okreÅ›lonego portu serwera poÅ›redniczÄ…cego "{}"; na numer portu - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Błąd parametru: ustawiono wzajemnie wykluczajÄ…ce siÄ™ opcje serwera poÅ›redniczÄ…cego. Resetowanie do wartoÅ›ci domyÅ›lnych. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Błąd parametru: wskazano serwer poÅ›redniczÄ…cy użytkownika, ale nie podano serwera poÅ›redniczÄ…cego. Przywrócenie ustawieÅ„ domyÅ›lnych. - - - - Addon Manager: Unexpected {} response from server - Menedżer dodatków: Nieoczekiwana odpowiedź {} z serwera - - - - Error with encrypted connection - Błąd z połączeniem szyfrowanym - - - - - - Confirm remove - Potwierdź usuniÄ™cie - - - - Are you sure you want to uninstall {}? - Czy na pewno odinstalować {}? - - - - - - Removing Addon - Usuwanie dodatku - - - - Removing {} - Usuwanie {} - - - - - Uninstall complete - Odinstalowanie zakoÅ„czone - - - - - Uninstall failed - Odinstalowanie nie powiodÅ‚o siÄ™ - - - - Version {version} installed on {date} - Wersja {version} zostaÅ‚a zainstalowana: {date} - - - - Version {version} installed - Wersja {version} zainstalowana - - - - Installed on {date} - Data instalacji {date} - - - - - - - Installed - Zainstalowano - - - - Currently on branch {}, name changed to {} - Obecnie w gałęzi {}, nazwa zostaÅ‚a zmieniona na {} - - - - Git tag '{}' checked out, no updates possible - Identyfikator Git '{}' sprawdzony, brak możliwoÅ›ci aktualizacji - - - - Update check in progress - Sprawdzanie aktualizacji w toku - - - - Installation location - Miejsce instalacji - - - - Repository URL - Adres URL repozytorium - - - - Changed to branch '{}' -- please restart to use Addon. - Zmieniono na gałąź "{}" -- uruchom ponownie, aby korzystać z dodatku. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Ten dodatek zostaÅ‚ zaktualizowany. Uruchom ponownie FreeCAD, aby zobaczyć zmiany. - - - - Disabled - Wyłączone - - - - Currently on branch {}, update available to version {} - W gałęzi {} aktualizacja dostÄ™pna do wersji {} - - - - Update available to version {} - Aktualizacja dostÄ™pna do wersji {} - - - - This is the latest version available - To jest najnowsza dostÄ™pna wersja - - - - WARNING: This addon is obsolete - UWAGA: Ten dodatek jest przestarzaÅ‚y - - - - WARNING: This addon is Python 2 only - UWAGA: Ten dodatek jest przeznaczony tylko dla Å›rodowiska Python 2 - - - - WARNING: This addon requires FreeCAD {} - OSTRZEÅ»ENIE: Ten dodatek wymaga programu FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - OSTRZEÅ»ENIE: Ten dodatek jest obecnie zainstalowany, ale wyłączony. Użyj przycisku 'włącz', aby go ponownie włączyć. - - - - This Addon will be enabled next time you restart FreeCAD. - Ten dodatek zostanie włączony przy nastÄ™pnym ponownym uruchomieniu programu FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Ten dodatek zostanie wyłączony przy ponownym uruchomieniu programu FreeCAD. - - - - - - Success - ZakoÅ„czono pomyÅ›lnie - - - - Install - Zainstaluj - - - - Uninstall - Odinstaluj - - - - Enable - Włącz - - - - Disable - Wyłącz - - - - - Check for update - Sprawdź dostÄ™pność aktualizacji - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - uruchom - - - - Change branch... - ZmieÅ„ gałąź ... - - - - Return to package list - Wróć do listy pakietów - - - - Checking connection - Sprawdzanie połączenia - - - - Checking for connection to GitHub... - Sprawdzanie połączenia z GitHub ... - - - - Connection failed - NawiÄ…zanie połączenia nie powiodÅ‚o siÄ™ - - - - Missing dependency - BrakujÄ…ca zależność - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Nie można zaimportować QtNetwork — szczegóły możesz zobaczyć w Widoku raportu. Menedżer dodatków jest niedostÄ™pny. - - - - Other... - For providing a license other than one listed - Inne ... - - - - Select the corresponding license file in your Addon - Wybierz odpowiedni plik licencyjny w swoim dodatku - - - - Location for new license file - Lokalizacja nowego pliku licencji - - - - Received {} response code from server - Otrzymano {} kod odpowiedzi z serwera - - - - Failed to install macro {} - Nie udaÅ‚o siÄ™ zainstalować makrodefinicji {} - - - - Failed to create installation manifest file: - - Nie udaÅ‚o siÄ™ utworzyć pliku informacji o instalacji: - - - - - Unrecognized content kind '{}' - Nierozpoznany rodzaj treÅ›ci "{}" - - - - Unable to locate icon at {} - Nie można zlokalizować ikony {} - - - - Select an icon file for this content item - Wybierz plik ikon dla tego elementu - - - - - - {} is not a subdirectory of {} - {} nie jest podkatalogiem {} - - - - Select the subdirectory for this content item - Wybierz podkatalog dla tego elementu - - - - Automatic - Automatycznie - - - - - Workbench - Åšrodowiska pracy - - - - Addon - Dodatek - - - - Python - Python - - - - Yes - Tak - - - - Internal Workbench - Wbudowane Å›rodowisko pracy - - - - External Addon - Dodatek zewnÄ™trzny - - - - Python Package - Pakiet Python - - - - - Other... - Inne ... - - - - Too many to list - Lista jest zbyt dÅ‚uga do wyÅ›wietlenia - - - - - - - - - Missing Requirement - NiespeÅ‚nione wymagania - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Dodatek "{}" wymaga pakietu "{}", który nie jest dostÄ™pny w twojej kopii FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Dodatek '{}' wymaga danych Å›rodowisk pracy, które nie sÄ… dostÄ™pne w twojej kopii programu FreeCAD: - - - - Press OK to install anyway. - NaciÅ›nij przycisk OK, aby pomimo to zainstalować. - - - - - Incompatible Python version - Niekompatybilna wersja Å›rodowiska Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Ten dodatek wymaga pakietów Python, które nie sÄ… zainstalowane i nie mogÄ… być zainstalowane automatycznie. Aby użyć tego dodatku, musisz zainstalować samodzielnie nastÄ™pujÄ…ce pakiety Å›rodowiska Python: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Ten dodatek (lub jedna jego zależność) wymaga Pythona {}.{}, a Twój system jest uruchomiony z {}.{}. Instalacja anulowana. - - - - Optional dependency on {} ignored because it is not in the allow-list - Opcjonalna zależność od {} jest ignorowana, ponieważ nie znajduje siÄ™ na liÅ›cie dopuszczonych - - - - - Installing dependencies - Instalowanie zależnoÅ›ci - - - - - Cannot execute Python - Nie można wykonać skryptu Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Nie udaÅ‚o siÄ™ automatycznie zlokalizować pliku wykonywalnego Python, lub Å›cieżka jest ustawiona nieprawidÅ‚owo. Sprawdź ustawienie preferencji Menedżera dodatków dotyczÄ…ce Å›cieżki do Å›rodowiska Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Nie można byÅ‚o zainstalować zależnoÅ›ci. Czy mimo to kontynuować instalacjÄ™ {}? - - - - - Cannot execute pip - Nie można uruchomić programu - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Niepowodzenie nie udaÅ‚o siÄ™ uruchomić polecenia, którego może brakować -w Twojej instalacji Å›rodowiska Python. -Upewnij siÄ™, że w systemie jest zainstalowane to polecenie -i spróbuj ponownie. Polecenie, którego wykonanie siÄ™ nie powiodÅ‚o, to: - - - - - Continue with installation of {} anyway? - Czy mimo to kontynuować instalacjÄ™ {}? - - - - - Package installation failed - Instalacja pakietu nie powiodÅ‚a siÄ™ - - - - See Report View for detailed failure log. - Szczegóły zapisu awarii znajdujÄ… siÄ™ w widoku raportu. - - - - Installing Addon - Instalacja dodatku - - - - Installing FreeCAD Addon '{}' - Instalowanie dodatku FreeCAD "{}" - - - - Cancelling - Anulowanie - - - - Cancelling installation of '{}' - Anulowanie instalacji "{}" - - - - {} was installed successfully - {} zostaÅ‚ poprawnie zainstalowany - - - - - Installation Failed - Instalacja nie powiodÅ‚a siÄ™ - - - - Failed to install {} - Nie udaÅ‚o siÄ™ zainstalować {} - - - - - Create new toolbar - Utwórz nowy pasek narzÄ™dzi - - - - - A macro installed with the FreeCAD Addon Manager - Makro zainstalowane przy pomocy Menedżera dodatków FreeCAD - - - - - Run - Indicates a macro that can be 'run' - Uruchom - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Nie można odczytać danych z GitHub: sprawdź swoje połączenie internetowe i ustawienia serwera poÅ›redniczÄ…cego i spróbuj ponownie. - - - - XML failure while reading metadata from file {} - Błąd XML podczas odczytywania metadanych z pliku {} - - - - Invalid metadata in file {} - NieprawidÅ‚owe metadane w pliku {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - OSTRZEÅ»ENIE: Åšcieżka okreÅ›lona w metadanych package.xml nie pasuje do aktualnie sprawdzanej gałęzi. - - - - Name - Nazwa - - - - Class - Klasa - - - - Description - Opis - - - - Subdirectory - Katalog podrzÄ™dny - - - - Files - Pliki - - - - Select the folder containing your Addon - Wybierz folder zawierajÄ…cy dodatek - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Brak Vermin, operacja zostaje anulowania. - - - - Scanning Addon for Python version compatibility - Skanowanie dodatku w celu kompatybilnoÅ›ci wersji Å›rodowiska Python - - - - Minimum Python Version Detected - Wykryto minimalnÄ… wymaganÄ… wersjÄ™ Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin automatycznie wykryÅ‚ wymaganÄ… wersjÄ™ Å›rodowiska Python 3.{} - - - - Install Vermin? - Zainstalować Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Automatyczne wykrywanie wymaganej wersji Å›rodowiska Python dla tego dodatku wymaga dodatku Vermin (https://pypi.org/project/vermin/). "OK" aby zainstalować? - - - - Attempting to install Vermin from PyPi - Próba zainstalowania Vermin z PyPi - - - - - Installation failed - Instalacja nie powiodÅ‚a siÄ™ - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Nie udaÅ‚o siÄ™ zainstalować Vermin -- sprawdź widok raportu, aby uzyskać szczegóły. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Nie udaÅ‚o siÄ™ zaimportować vermin po instalacji -- nie można sprawdzić dodatku. - - - - Select an icon file for this package - Wybierz plik ikon dla tego pakietu - - - - Filter is valid - Filtr jest prawidÅ‚owy - - - - Filter regular expression is invalid - Wyrażenie regularne filtra jest nieprawidÅ‚owe - - - - Search... - Szukaj ... - - - - Click for details about package {} - Kliknij, aby uzyskać informacje o pakiecie {} - - - - Click for details about workbench {} - Kliknij, aby uzyskać informacje o Å›rodowisku pracy {} - - - - Click for details about macro {} - Kliknij, aby uzyskać informacje o makrodefinicji {} - - - - Maintainers: - Opiekunowie: - - - - Tags - Znaczniki - - - - {} ★ on GitHub - {} ★ na GitHub - - - - No ★, or not on GitHub - Bez ★, lub nie na GitHub - - - - Created - Utworzono - - - - Updated - Zaktualizowano - - - - Score: - Wynik: - - - - - Up-to-date - Aktualny - - - - - - - - Update available - DostÄ™pna aktualizacja - - - - - Pending restart - Oczekuje na ponowne uruchomienie - - - - - DISABLED - WYÅÄ„CZONY - - - - Installed version - Wersja zainstalowana - - - - Unknown version - Nieznana wersja - - - - Installed on - Data instalacji - - - - Available version - Wersja dostÄ™pna - - - - Filter by... - Filtruj wedÅ‚ug ... - - - - Addon Type - Typ dodatku - - - - - Any - Dowolny - - - - Macro - Makrodefinicje - - - - Preference Pack - Pakiet preferencji - - - - Installation Status - Stan instalacji - - - - Not installed - Nie zainstalowano - - - - Filter - Filtr - - - - DANGER: Developer feature - OSTRZEÅ»ENIE: Funkcja dewelopera - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Przełączanie gałęzi jest przeznaczone dla deweloperów i beta testerów i może skutkować uszkodzeniem, nieskutecznie kompatybilnymi dokumentami, niestabilność, awarie lub przedwczesna Å›mierć wszechÅ›wiata. Czy na pewno chcesz kontynuować? - - - - There are local changes - WystÄ™pujÄ… zmiany lokalne - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - OSTRZEÅ»ENIE: To repozytorium ma niezatwierdzone lokalne zmiany. Czy na pewno chcesz zmienić gałęzie (wprowadzajÄ…c zmiany w życie)? - - - - Local - Table header for local git ref name - Lokalnie - - - - Remote tracking - Table header for git remote tracking branch name - Åšledzenie zdalne - - - - Last Updated - Table header for git update date - Ostatnia aktualizacja - - - - Installation of Python package {} failed - Instalacja pakietu Python {} nie powiodÅ‚a siÄ™ - - - - Installation of optional package failed - Instalacja pakietu opcjonalnego nie powiodÅ‚a siÄ™. - - - - Installing required dependency {} - Instalowanie wymaganej zależnoÅ›ci {} - - - - Installation of Addon {} failed - Instalacja dodatku {} nie powiodÅ‚a siÄ™ - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Nie udaÅ‚o siÄ™ dekodować pliku {} dla dodatku "{}" - - - - Any dependency information in this file will be ignored - Wszelkie informacje o zależnoÅ›ci w tym pliku zostanÄ… zignorowane - - - - Unable to open macro wiki page at {} - Nie można otworzyć strony Wiki makrodefinicji w {} - - - - Unable to fetch the code of this macro. - Nie można pobrać kodu makrodefinicji. - - - - Unable to retrieve a description from the wiki for macro {} - Nie można pobrać opisu z Wiki dla makrodefinicji {} - - - - Unable to open macro code URL {} - Nie można otworzyć adresu URL kodu makrodefinicji {} - - - - Unable to fetch macro-specified file {} from {} - Nie można pobrać pliku okreÅ›lonego przez makrodefinicjÄ™ {} z {} - - - - Could not locate macro-specified file {} (expected at {}) - Nie można zlokalizować okreÅ›lonego przez makrodefinicjÄ™ pliku {} (oczekiwany w {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Nierozpoznane wewnÄ™trzne Å›rodowisko pracy "{}" - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Ostrzeżenie dla twórców dodatku: Adres URL repozytorium ustawiony w pliku package.xml dla dodatku {} ({}) nie pasuje do adresu URL pobranego z ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Ostrzeżenie dla twórców dodatku: Gałąź repozytorium ustawiona w pliku package.xml dla dodatku {} ({}) nie pasuje do gałęzi, z której zostaÅ‚ on pobrany ({}) - - - - - Got an error when trying to import {} - WystÄ…piÅ‚ błąd podczas próby zaimportowania {} - - - - An unknown error occurred - WystÄ…piÅ‚ nieznany błąd - - - - Could not find addon {} to remove it. - Nie można znaleźć dodatku {} do usuniÄ™cia. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Wykonanie skryptu dodatku uninstall.py nie powiodÅ‚o siÄ™. KontynuujÄ™ odinstalowywanie ... - - - - Removed extra installed file {} - UsuniÄ™to dodatkowy zainstalowany plik {} - - - - Error while trying to remove extra installed file {} - Błąd podczas próby usuniÄ™cia dodatkowego zainstalowanego pliku {} - - - - Error while trying to remove macro file {}: - Błąd podczas próby usuniÄ™cia pliku makrodefinicji {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Niepowodzenie nie udaÅ‚o siÄ™ połączyć z GitHub. Sprawdź swoje połączenie i ustawienia serwera poÅ›redniczÄ…cego. - - - - WARNING: Duplicate addon {} ignored - OSTRZEÅ»ENIE: Duplikat dodatku {} pominiÄ™to - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - WystÄ…piÅ‚ błąd podczas aktualizacji makrodefinicji z GitHub, próba czyszczenia ... - - - - Attempting to do a clean checkout... - Próbuje wykonać czyszczenie ... - - - - Clean checkout succeeded - Czyszczenie zakoÅ„czone pomyÅ›lnie - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Nie udaÅ‚o siÄ™ zaktualizować makrodefinicji z repozytorium GitHub — próba oczyszczenia pamiÄ™ci podrÄ™cznej Menedżera dodatków. - - - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Błąd połączenia z Wiki, FreeCAD nie może w tej chwili pobrać listy makrodefinicji Wiki - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Niepowodzenie nie udaÅ‚o siÄ™ odczytać metadanych z {name} - - - - Failed to fetch code for macro '{name}' - Niepowodzenie nie udaÅ‚o siÄ™ pobrać kodu dla makrodefinicji "{name}" - - - - Addon Manager: a worker process failed to complete while fetching {name} - Menedżer dodatków: nie udaÅ‚o siÄ™ ukoÅ„czyć procesu przetwarzania podczas pobierania {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Dla {num_macros} makrodefinicji przekroczono limit czasu {num_failed} podczas przetwarzania - - - - Addon Manager: a worker process failed to halt ({name}) - Menadżer dodatków: nie udaÅ‚o siÄ™ zatrzymać uruchomionego procesu ({name}) - - - - Timeout while fetching metadata for macro {} - UpÅ‚ynÄ…Å‚ limit czasu pobierania metadanych dla makrodefinicji {} - - - - Failed to kill process for macro {}! - - Nie udaÅ‚o siÄ™ przerwać procesu makrodefinicji {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Nie udaÅ‚o siÄ™ pobrać statystyk dodatku z {} - tylko sortowanie alfabetyczne bÄ™dzie dokÅ‚adne. - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Nie udaÅ‚o siÄ™ pobrać wyniku dodatku z "{}" -- sortowanie wedÅ‚ug wyniku nie powiedzie siÄ™. - - - - - Repository URL - Preferences header for custom repositories - Adres URL repozytorium - - - - Branch name - Preferences header for custom repositories - Nazwa gałęzi - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Tworzenie kopii zapasowej oryginalnego katalogu i ponowne klonowanie - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Zmiana nazwy gałęzi Git nie powiodÅ‚a siÄ™, z nastÄ™pujÄ…cym komunikatem: - - - - Installing - Instalowanie - - - - Succeeded - ZakoÅ„czono z powodzeniem - - - - Failed - Niepowodzenie - - - - Update was cancelled - Aktualizacja zostaÅ‚a przerwana - - - - some addons may have been updated - niektóre dodatki mogÅ‚y zostać zaktualizowane - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Wczytywanie informacji dla {} z wiki systemu makro FreeCAD... - - - - Loading page for {} from {}... - Wczytywanie strony {} z {}... - - - - Failed to download data from {} -- received response code {}. - Nie udaÅ‚o siÄ™ pobrać danych z {} -- otrzymano kod odpowiedzi {}. - - - - Composite view - Widok zÅ‚ożony - - - - Expanded view - Widok rozszerzony - - - - Compact view - Widok skrócony - - - - Alphabetical - Sort order - Alfabetycznie - - - - Last Updated - Sort order - Ostatnia aktualizacja - - - - Date Created - Sort order - Data utworzenia - - - - GitHub Stars - Sort order - Odznaki GitHub - - - - Score - Sort order - Wynik - - - - Std_AddonMgr - - - &Addon manager - &Menadżer dodatków - - - - Manage external workbenches, macros, and preference packs - ZarzÄ…dzanie zewnÄ™trznymi Å›rodowiskami pracy, makroinstrukcjami i pakietami preferencji - - - - AddonInstaller - - - Finished removing {} - ZakoÅ„czono usuwanie {} - - - - Failed to remove some files - Nie udaÅ‚o siÄ™ usunąć niektórych plików - - - - Addons installer - - - Finished updating the following addons - ZakoÅ„czono aktualizacjÄ™ nastÄ™pujÄ…cych dodatków - - - - Workbench - - - Auto-Created Macro Toolbar - Pasek narzÄ™dzi makr tworzonych automatycznie - - - - QObject - - - Addon Manager - Menedżer dodatków - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_pt-BR.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_pt-BR.qm deleted file mode 100644 index d090c1b1a42e772eab583345f57529faab549c88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71404 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 jhZ|axaR - - - - AddCustomRepositoryDialog - - - Custom repository - Repositório personalizado - - - - Repository URL - URL do repositório - - - - Branch - Ramo - - - - CompactView - - - - Icon - Ãcone - - - - - <b>Package Name</b> - <b>Nome do pacote</b> - - - - - Version - Versão - - - - - Description - Descrição - - - - Update Available - Atualização disponível - - - - UpdateAvailable - Atualização Disponível - - - - DependencyDialog - - - Dependencies - Dependências - - - - Dependency type - Tipo de dependência - - - - Name - Nome - - - - Optional? - Opcional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolver Dependências - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Este complemento tem as seguintes dependências obrigatórias e opcionais. Você deve instalá-las antes que este complemento possa ser usado. - -Você quer que o Gerenciador de Complementos os instale automaticamente? Escolha "Ignorar" para instalar o Complemento sem instalar as dependências. - - - - FreeCAD Addons - Extensões FreeCAD - - - - Required Python modules - Módulos Python necessários - - - - Optional Python modules - Módulos opcionais do Python - - - - DeveloperModeDialog - - - Addon Developer Tools - Ferramentas do Desenvolvedor de Complementos (Addon) - - - - Path to Addon - Caminho para o Complemento (addon) - - - - - Browse... - Procurar... - - - - Metadata - Metadados - - - - Primary branch - Ramificação primária - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explicação do que este Complemento fornece. Exibido no Gerenciador de Complementos. Não é necessário que isso declare que este é um Complemento do FreeCAD. - - - - Description - Descrição - - - - Discussion URL - URL de Discussão - - - - Icon - Ãcone - - - - Bugtracker URL - URL do rastreador de bugs - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilos semânticos (1.2.3-beta) ou calendário (2022.08.30) suportados - - - - Set to today (CalVer style) - Definir para hoje (Estilo CalVer) - - - - - - - (Optional) - (Opcional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Exibido na lista de Complementos 's de Complementos. Não deve incluir a palavra "FreeCAD", e deve ser um nome de diretório válido em todos os sistemas operacionais de suporte. - - - - README URL - LEIA-ME URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - DICA: Como isso é exibido no FreeCAD, no Gerenciador de Complementos, não é necessário ocupar espaço dizendo coisas como "Este é um Complemento do FreeCAD. ." -- apenas diga o que faz. - - - - Repository URL - URL do repositório - - - - Website URL - URL do site - - - - Documentation URL - URL da Documentação - - - - Addon Name - Nome Complemento - - - - Version - Versão - - - - (Recommended) - (Recomendado) - - - - Minimum Python - Versão mínima Python - - - - (Optional, only 3.x version supported) - (Opcional, apenas versão 3.x suportada) - - - - Detect... - Detectar... - - - - Addon Contents - Comentários do complemento - - - - Dialog - - - Addon Manager - Gerenciador de Extensões - - - - Edit Tags - Editar marcações - - - - Comma-separated list of tags describing this item: - Lista de tags separadas por vírgulas descrevendo este item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - DICA: Tags comuns incluem "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Gerenciador de Extensões: Aviso! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - O Gerenciador de Extensões fornece acesso a uma vasta biblioteca de extensões FreeCAD úteis e de terceiros. Nenhuma garantia pode ser feita acerca da segurança ou funcionalidade delas. - - - - Continue - Continuar - - - - Cancel - Cancelar - - - - EditDependencyDialog - - - Edit Dependency - Editar Dependência - - - - Dependency Type - Tipo de dependência - - - - Dependency - Dependência - - - - Package name, if "Other..." - Nome do pacote, se for "Outro..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTA: Se "Outro..." for selecionado, o pacote não está no arquivo ALLOWED_PYTHON_PACKAGES.txt, e não será instalado automaticamente pelo gerenciador de extensões. Crie um PR em <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> para pedir a inclusão de um novo pacote. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Se esta for uma dependência opcional, o gerenciador de extensões oferecerá para instalá-la (se for possível), mas não irá bloquear a instalação se o usuário escolher não instalar o pacote. - - - - Optional - Opcional - - - - ExpandedView - - - - Icon - Ãcone - - - - - <h1>Package Name</h1> - <h1>Nome do pacote</h1> - - - - - Version - Versão - - - - - (tags) - (etiquetas) - - - - - Description - Descrição - - - - - Maintainer - Mantenedor - - - - Update Available - Atualização disponível - - - - labelSort - labelSort - - - - UpdateAvailable - Atualização Disponível - - - - Form - - - Licenses - Licenças - - - - License - Licença - - - - License file - Arquivo de licença - - - - People - Pessoas - - - - Kind - Tipo - - - - Name - Nome - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Mapeamento Avançado de Versão - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Versões futuras do gerenciador de extensões permitirão que desenvolvedores definam um branch ou tag específico para uso com uma versão específica do FreeCAD (ex. definindo uma tag específica como a última versão da sua extensão que suporte o FreeCAD v0.19, etc.) - - - - FreeCAD Version - Versão do FreeCAD - - - - Best-available branch, tag, or commit - Branch, tag ou commit mais apropriado - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versões do FreeCAD suportadas - - - - Minimum FreeCAD Version Supported - Versão mínima do FreeCAD suportada - - - - - Optional - Opcional - - - - Maximum FreeCAD Version Supported - Máximo de versão do FreeCAD suportada - - - - Advanced version mapping... - Mapeamento avançado da versão... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opções de gerenciamento de extensões - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Se esta opção for selecionada, ao iniciar o Addon Manager, -será verificado se há atualizações disponíveis - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Baixar metadados de macro (aproximadamente 10MB) - - - - Cache update frequency - Frequência de atualização do cache - - - - Manual (no automatic updates) - Manual (sem atualizações automáticas) - - - - Daily - Diariamente - - - - Weekly - Semanalmente - - - - Hide Addons without a license - Ocultar Complementos sem licença - - - - Hide Addons with non-FSF Free/Libre license - Ocultar complementos com licença não-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Ocultar complementos com licença não-aprovada - - - - Hide Addons marked Python 2 Only - Ocultar Complementos marcados apenas para Python 2 - - - - Hide Addons marked Obsolete - Ocultar Complementos marcados como obsoletos - - - - Hide Addons that require a newer version of FreeCAD - Ocultar Complementos que requerem uma versão mais recente do FreeCAD - - - - Custom repositories - Repositórios personalizados - - - - Proxy - Proxy - - - - No proxy - Sem proxy - - - - User system proxy - Proxy do sistema do usuário - - - - User-defined proxy: - Proxy definido pelo usuário: - - - - Score source URL - URL da fonte da pontuação - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - A URL para os dados de pontuação das extensões (veja a página wiki do gerenciador de extensões para formatação e detalhes de hospedagem). - - - - Path to Git executable (optional): - Executável Git (opcional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opções Avançadas - - - - Activate Addon Manager options intended for developers of new Addons. - Ativar opções de gerenciador de extensões destinadas aos desenvolvedores. - - - - Addon developer mode - Modo de desenvolvedor - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Desinstala uma macro ou bancada de trabalho selecionada - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Update - Atualizar - - - - Run Macro - Executar macro - - - - Change branch - Alterar branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Gerenciar Dependências do Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Os seguintes pacotes do Python foram instalados localmente pelo Addon Manager para satisfazer as dependências do Addon. Localização da instalação: - - - - Package name - Nome do pacote - - - - Installed version - Versão instalada - - - - Available version - Versão disponível - - - - Used by - Utilizado por - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Um asterisco (*) no "usado por" coluna indica uma dependência opcional. Note que usado apenas registra importações diretas no Addon. Outros pacotes Python dos quais esses pacotes dependem também podem ter sido instalados. - - - - Update all available - Atualizar tudo que estiver disponível - - - - SelectFromList - - - Dialog - Diálogo - - - - TextLabel - Rótulo de texto - - - - UpdateAllDialog - - - Updating Addons - Atualizando Complementos - - - - Updating out-of-date addons... - Atualizando addons desatualizados... - - - - addContentDialog - - - Content Item - Item de Conteúdo - - - - Content type: - Tipo de conteúdo: - - - - Macro - Macro - - - - Preference Pack - Pacote de preferência - - - - Workbench - Bancada - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Se esta é a única coisa no Addon, todos os outros metadados podem ser herdados do nível superior, e não precisa ser especificado aqui. - - - - This is the only item in the Addon - Este é o único item do Addon - - - - Main macro file - Arquivo de macro principal - - - - The file with the macro's metadata in it - O arquivo com os metadados da macro's nele - - - - - - Browse... - Procurar... - - - - Preference Pack Name - Nome do pacote de preferências - - - - Workbench class name - Nome da classe da Bancada de Trabalho - - - - Class that defines "Icon" data member - Classe que define o dado "Ãcone" - - - - Subdirectory - Subdiretório - - - - Optional, defaults to name of content item - Opcional, o padrão é o nome do item de conteúdo - - - - Icon - Ãcone - - - - Optional, defaults to inheriting from top-level Addon - Opcional, padrão para herdar de Addon de nível superior - - - - Tags... - Etiquetas... - - - - Dependencies... - Dependências... - - - - FreeCAD Versions... - Versões do FreeCAD... - - - - Other Metadata - Outros metadados - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Exibido na lista de extensões do gerenciador. Não deve incluir a palavra "FreeCAD". - - - - Version - Versão - - - - Description - Descrição - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Estilos semânticos (1.2.3-beta) ou calendário (2022.08.30) suportados - - - - Set to today (CalVer style) - Definir para hoje (Estilo CalVer) - - - - Display Name - Nome de exibição - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Qualquer campo deixado em branco herdará os metadados da extensão acima, por tanto tecnicamente todos são opcionais. Para extensões com vários itens de conteúdo, cada item deve fornecer um único nome e descrição. - - - - add_toolbar_button_dialog - - - Add button? - Adicionar botão? - - - - Add a toolbar button for this macro? - Adicionar um botão na barra de ferramentas desta macro? - - - - Yes - Sim - - - - No - Não - - - - Never - Nunca - - - - change_branch - - - Change Branch - Alterar Ramo - - - - Change to branch: - Alterar branch: - - - - copyrightInformationDialog - - - Copyright Information - Informações sobre Direitos Autorais - - - - Copyright holder: - Titular dos direitos autorais: - - - - Copyright year: - Ano do direito autoral: - - - - personDialog - - - Add Person - Adicionar perfil - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Um mantenedor é alguém com acesso de commit atual neste projeto. Um autor é qualquer pessoa para quem você deseja dar créditos. - - - - Name: - Nome: - - - - Email: - E-mail: - - - - Email is required for maintainers, and optional for authors. - E-mail é obrigatório para os mantenedores, e opcional para os autores. - - - - proxy_authentication - - - Proxy login required - Requer configuração de proxy - - - - Proxy requires authentication - Proxy requer autenticação - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Espaço reservado para o endereço de proxy - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Espaço reservado para o realm de proxy - - - - Username - Nome de usuário - - - - Password - Senha - - - - selectLicenseDialog - - - Select a license - Selecionar licença - - - - About... - Sobre... - - - - License name: - Nome da licença: - - - - Path to license file: - Local do arquivo de licença: - - - - (if required by license) - (se exigido pela licença) - - - - Browse... - Procurar... - - - - Create... - Criar... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Selecionar Barra de Ferramentas - - - - Select a toolbar to add this macro to: - Selecionar uma barra de ferramentas para adicionar a esse macro: - - - - Ask every time - Sempre perguntar - - - - toolbar_button - - - - Add button? - Adicionar botão? - - - - Add a toolbar button for this macro? - Adicionar um botão na barra de ferramentas para esta macro? - - - - Yes - Sim - - - - No - Não - - - - Never - Nunca - - - - AddonsInstaller - - - Starting up... - Iniciando... - - - - Worker process {} is taking a long time to stop... - Processo de trabalhador {} está demorando muito para parar... - - - - Previous cache process was interrupted, restarting... - - Processamento do cache anterior foi interrompido, reiniciando... - - - - - Custom repo list changed, forcing recache... - - Lista personalizada de repositórios alterada, forçando recache... - - - - - Addon manager - Gerenciador de complementos - - - - You must restart FreeCAD for changes to take effect. - Você deve reiniciar o FreeCAD para que as alterações tenham efeito. - - - - Restart now - Reiniciar agora - - - - Restart later - Reiniciar depois - - - - - Refresh local cache - Atualizar o cache local - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Atualizando cache... - - - - - Checking for updates... - Verificando por atualizações... - - - - Temporary installation of macro failed. - Falha na instalação temporária do macro. - - - - - Close - Fechar - - - - Update all addons - Atualizar todos os addons - - - - Check for updates - Verificar atualizações - - - - Python dependencies... - Dependências do Python... - - - - Developer tools... - Ferramentas do desenvolvedor... - - - - Apply %n available update(s) - Aplicar %n atualizações disponíveis - - - - No updates available - Não há atualizações disponíveis - - - - - - Cannot launch a new installer until the previous one has finished. - Não é possível iniciar um novo instalador até que o anterior tenha terminado. - - - - - - - Maintainer - Mantenedor - - - - - - - Author - Autor - - - - New Python Version Detected - Nova versão do Python detectada - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Parece ser a primeira vez que esta versão do Python é usada no Addon Manager. Você gostaria de instalar as mesmas dependências instaladas automaticamente para ele? - - - - Processing, please wait... - Processando, aguarde... - - - - - Update - Atualizar - - - - Updating... - Atualizando... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Não foi possível importar QtNetwork -- aparentemente não está instalada em seu sistema. Seu provedor pode ter um pacote para esta dependência (frequentemente chamado "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Falha ao converter a porta especificada '{}' do proxy para um número de porta - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Erro de parâmetro: opções de proxy mutualmente exclusivas definidas. Redefinindo ao padrão. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Erro de parâmetro: proxy de usuário indicado, mas nenhum proxy foi fornecido. Redefinindo para o padrão. - - - - Addon Manager: Unexpected {} response from server - Gerente de Addons: Resposta inesperada {} do servidor - - - - Error with encrypted connection - Erro na conexão criptografada - - - - - - Confirm remove - Confirme a remoção - - - - Are you sure you want to uninstall {}? - Tem certeza que deseja desinstalar {}? - - - - - - Removing Addon - Removendo complemento - - - - Removing {} - Removendo {} - - - - - Uninstall complete - Desinstalação concluída - - - - - Uninstall failed - Falha ao desinstalar - - - - Version {version} installed on {date} - Versão {version} instalada no dia {date} - - - - Version {version} installed - Versão {version} instalada - - - - Installed on {date} - Instalado no dia {date} - - - - - - - Installed - Instalado - - - - Currently on branch {}, name changed to {} - Atualmente na branch {}, nome alterado para {} - - - - Git tag '{}' checked out, no updates possible - Tag do Git '{}' verificada, nenhuma atualização possivel - - - - Update check in progress - Verificação de atualização em andamento - - - - Installation location - Local da instalação - - - - Repository URL - URL do repositório - - - - Changed to branch '{}' -- please restart to use Addon. - Alterado para a ramificação '{}' - por favor reinicie para usar o Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Este complemento foi atualizado. Reinicie o FreeCAD para ver as alterações. - - - - Disabled - Desabilitado - - - - Currently on branch {}, update available to version {} - Atualmente na ramificação {}, atualização disponível para a versão {} - - - - Update available to version {} - Atualização disponível para versão {} - - - - This is the latest version available - Esta é a versão mais recente disponível - - - - WARNING: This addon is obsolete - AVISO: Este complemento é obsoleto - - - - WARNING: This addon is Python 2 only - AVISO: Esta extensão é apenas Python 2 - - - - WARNING: This addon requires FreeCAD {} - AVISO: Esta extensão requer o FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - AVISO: Este addon está instalado, mas desabilitado. Use o botão 'ativar' para reativá-lo. - - - - This Addon will be enabled next time you restart FreeCAD. - Este complemento será ativado na próxima vez que você reiniciar o FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Este addon vai ser desabilitado na próxima vez que você reiniciar o FreeCad. - - - - - - Success - Sucesso - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Enable - Ativar - - - - Disable - Desativar - - - - - Check for update - Verificar atualizações - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - executar - - - - Change branch... - Mudar ramificação... - - - - Return to package list - Retornar à lista de pacotes - - - - Checking connection - Verificando conexão - - - - Checking for connection to GitHub... - Verificando a conexão com o GitHub... - - - - Connection failed - Conexão falhou - - - - Missing dependency - Dependência ausente - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Não foi possível importar QtNetwork -- consulte Ver relatórios para detalhes. Gerenciador de Addons indisponível. - - - - Other... - For providing a license other than one listed - Outro... - - - - Select the corresponding license file in your Addon - Selecione o arquivo de licença correspondente no seu Addon - - - - Location for new license file - Local para o novo arquivo de licença - - - - Received {} response code from server - Código de resposta {} recebido do servidor - - - - Failed to install macro {} - Falha ao instalar macro {} - - - - Failed to create installation manifest file: - - Falha ao criar arquivo de manifesto de instalação: - - - - - Unrecognized content kind '{}' - Tipo de conteúdo desconhecido '{}' - - - - Unable to locate icon at {} - Não foi possível localizar o ícone em {} - - - - Select an icon file for this content item - Selecione um arquivo de ícone para este pacote - - - - - - {} is not a subdirectory of {} - {} não é um subdiretório de {} - - - - Select the subdirectory for this content item - Selecione o subdiretório para este item de conteúdo - - - - Automatic - Automática - - - - - Workbench - Bancada - - - - Addon - Complemento - - - - Python - Python - - - - Yes - Sim - - - - Internal Workbench - Bancada Interna - - - - External Addon - Editor externo - - - - Python Package - Pacote Python - - - - - Other... - Outro... - - - - Too many to list - Muitos para listar - - - - - - - - - Missing Requirement - Requisito ausente - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Complemento '{}' requer '{}', que não está disponível na sua cópia do FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Complemento '{}' requer as seguintes bancadas de trabalho, que não estão disponíveis na sua cópia do FreeCAD: - - - - Press OK to install anyway. - Pressione OK para instalar mesmo assim. - - - - - Incompatible Python version - Versão incompatível do Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Esta extensão requer pacotes do Python que não estão instalados e não podem ser instalados automaticamente. Para usar esta bancada de trabalho, você deve instalar os seguintes pacotes do Python manualmente: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Esta extensão (ou uma das suas dependências) necessita o Python {}.{}, porém seu sistema está rodando a {}.{}. A instalação foi cancelada. - - - - Optional dependency on {} ignored because it is not in the allow-list - Dependência opcional de {} ignorada porque não está na lista de permissão - - - - - Installing dependencies - Instalando dependências - - - - - Cannot execute Python - Não é possível executar Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Falha ao localizar automaticamente o executável do Python, ou o caminho está definido incorretamente. Por favor, verifique a configuração das preferências do Gerenciador de complementos para o caminho do Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependências não puderam ser instaladas. Continuar com a instalação de {} mesmo assim? - - - - - Cannot execute pip - Não é possível executar pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Falha ao executar pip, que pode estar faltando na instalação do Python. Por favor, certifique-se de que seu sistema tem o pip instalado e tente novamente. O comando que falhou foi: - - - - - Continue with installation of {} anyway? - Continuar com a instalação de {} mesmo assim? - - - - - Package installation failed - Instalação do pacote falhou - - - - See Report View for detailed failure log. - Consulte Ver Relatório um registro de falhas detalhado. - - - - Installing Addon - Instalando complemento - - - - Installing FreeCAD Addon '{}' - Instalando complemento '{}' - - - - Cancelling - Cancelando - - - - Cancelling installation of '{}' - Cancelando a instalação de '{}' - - - - {} was installed successfully - {} foi instalado com sucesso - - - - - Installation Failed - Falha na instalação - - - - Failed to install {} - Falha ao instalar {} - - - - - Create new toolbar - Criar nova barra de ferramentas - - - - - A macro installed with the FreeCAD Addon Manager - Uma macro instalada com o Gerenciador de complementos do FreeCAD - - - - - Run - Indicates a macro that can be 'run' - executar - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Não foi possível ler os dados do GitHub: verifique sua conexão de internet e configurações de proxy e tente novamente. - - - - XML failure while reading metadata from file {} - Falha XML ao ler metadados do arquivo {} - - - - Invalid metadata in file {} - Metadados inválidos no arquivo {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - AVISO: caminho especificado nos metadados package.xml não corresponde à ramificação atualmente marcada como check-out. - - - - Name - Nome - - - - Class - Classe - - - - Description - Descrição - - - - Subdirectory - Subdiretório - - - - Files - Arquivos - - - - Select the folder containing your Addon - Selecione a pasta que contém seu complemento - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Nenhum Vermin, cancelando a operação. - - - - Scanning Addon for Python version compatibility - Escaneando compatibilidade com versões de extensão Python - - - - Minimum Python Version Detected - Nova versão do Python detectada - - - - Vermin auto-detected a required version of Python 3.{} - Vermin detectou automaticamente uma versão do Python 3.{} - - - - Install Vermin? - Instalar Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - A Detecção automática da versão do Python para este complemento requer o Vermin (https://pypi.org/project/vermin/). OK para instalar? - - - - Attempting to install Vermin from PyPi - Tentando instalar o Vermin pelo PyPi - - - - - Installation failed - Falha na instalação - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Falha ao instalar Vermin -- verifique Ver Relatório para mais detalhes. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Falha ao importar vermin após a instalação -- não é possível verificar o complemento. - - - - Select an icon file for this package - Selecione um arquivo de ícone para este pacote - - - - Filter is valid - O filtro é válido - - - - Filter regular expression is invalid - Uma expressão regular de filtro é inválida - - - - Search... - Procurar... - - - - Click for details about package {} - Clique para detalhes sobre o pacote {} - - - - Click for details about workbench {} - Clique para detalhes sobre a bancada de trabalho {} - - - - Click for details about macro {} - Clique para detalhes sobre a macro {} - - - - Maintainers: - Mantenedores: - - - - Tags - Etiquetas - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - Sem ★ ou não no GitHub - - - - Created - Criado - - - - Updated - Atualizado - - - - Score: - Pontuação: - - - - - Up-to-date - Atualizado - - - - - - - - Update available - Atualização Disponível - - - - - Pending restart - Reinício pendente - - - - - DISABLED - DESATIVADO - - - - Installed version - Versão instalada - - - - Unknown version - Versão desconhecida - - - - Installed on - Instalado em - - - - Available version - Versão disponível - - - - Filter by... - Filtrar por... - - - - Addon Type - Tipo de Complemento - - - - - Any - Qualquer um - - - - Macro - Macro - - - - Preference Pack - Pacote de preferência - - - - Installation Status - Status da instalação - - - - Not installed - Não instalado - - - - Filter - Filtro - - - - DANGER: Developer feature - PERIGO: Recurso de desenvolvedor - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - PERIGO: A troca de branch é destinada aos desenvolvedores e testadores beta, e pode resultar em quebras, documentos não compatíveis com a retrocompatibilidade, instabilidade e travamentos. Tem certeza que deseja continuar? - - - - There are local changes - Existem alterações locais - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - AVISO: Este repositório tem mudanças locais não confirmadas. Tem certeza de que deseja alterar ramificações (trazendo as alterações com você)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Rastreamento remoto - - - - Last Updated - Table header for git update date - Atualizado pela última vez - - - - Installation of Python package {} failed - Falha na instalação do pacote Python {} - - - - Installation of optional package failed - Falha na instalação do pacote opcional - - - - Installing required dependency {} - Instalando dependência requerida {} - - - - Installation of Addon {} failed - Falha na instalação do complemento {} - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Falha ao decodificar o arquivo {} do complemento '{}' - - - - Any dependency information in this file will be ignored - Qualquer informação sobre dependências neste arquivo será ignorada - - - - Unable to open macro wiki page at {} - Não é possível abrir a página da wiki da macro em {} - - - - Unable to fetch the code of this macro. - Incapaz de buscar o código desta macro. - - - - Unable to retrieve a description from the wiki for macro {} - Não é possível exibir uma descrição deste macro {} - - - - Unable to open macro code URL {} - Não foi possível abrir o URL do código da macro {} - - - - Unable to fetch macro-specified file {} from {} - Não foi possível buscar o arquivo {} especificado de {} - - - - Could not locate macro-specified file {} (expected at {}) - Não foi possível localizar o arquivo {} macro-especificada (esperado em {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Bancada interna desconhecida '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - AVISO DO DESENVOLVEDOR DE EXTENSÕES: URL do repositório definido no arquivo package.xml para extensão {} ({}) não corresponde ao URL do qual foi buscado ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - AVISO DO DESENVOLVEDOR DE EXTENSÕES: A ramificação do repositório definida no arquivo package.xml para extensão {} ({}) não corresponde à ramificação da qual foi buscado ({}) - - - - - Got an error when trying to import {} - Ocorreu um erro ao tentar importar {} - - - - An unknown error occurred - Ocorreu um erro desconhecido - - - - Could not find addon {} to remove it. - Não foi possível encontrar a extensão {} para removê-la. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execução do complemento's uninstall.py falhou. Prosseguindo com a desistalação... - - - - Removed extra installed file {} - Arquivo extra instalado removido {} - - - - Error while trying to remove extra installed file {} - Erro ao tentar remover o arquivo extra instalado {} - - - - Error while trying to remove macro file {}: - Erro enquanto tentava remover o arquivo da macro {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Falha ao se conectar ao GitHub. Verifique sua conexão e configurações de proxy. - - - - WARNING: Duplicate addon {} ignored - AVISO: Extensão {} duplicada ignorada - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Ocorreu um erro ao atualizar macros do GitHub, tentando check-out limpo... - - - - Attempting to do a clean checkout... - Tentando fazer um checkout... - - - - Clean checkout succeeded - Check-out limpo bem-sucedido - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Falha ao atualizar macros do GitHub -- tente limpar o cache do Gerenciador de extensões's. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Erro ao conectar ao Wiki, o FreeCAD não pode recuperar a lista de macros Wiki neste momento - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Falha ao ler metadados de {name} - - - - Failed to fetch code for macro '{name}' - Falha ao obter código para macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Gerenciador de extensões: um processo de trabalho falhou em completar ao obter {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Sem {num_macros} macros, {num_failed} expiraram durante o processamento - - - - Addon Manager: a worker process failed to halt ({name}) - Gerenciador de extensões: um processo de trabalho falhou ao parar ({name}) - - - - Timeout while fetching metadata for macro {} - Tempo limite para buscar metadados para macro {} - - - - Failed to kill process for macro {}! - - Falha ao matar o processo para macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Falha ao obter as estatísticas da extensão de {} -- somente ordenar o valor alfabético será preciso - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Falha ao obter pontuação da extensão de '{}' -- classificar por pontuação falhará - - - - - Repository URL - Preferences header for custom repositories - URL do repositório - - - - Branch name - Preferences header for custom repositories - Nome da ramificação - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Fazendo cópia de segurança do diretório original e re-clonando - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Renomeação de branch do Git falhou com a seguinte mensagem: - - - - Installing - Instalando - - - - Succeeded - Concluído - - - - Failed - Falhou - - - - Update was cancelled - A atualização foi cancelada - - - - some addons may have been updated - alguns complementos podem ter sido atualizados - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Carregando informações para {} da wiki de receitas de Macro do FreeCAD... - - - - Loading page for {} from {}... - Carregando página para {} de {}... - - - - Failed to download data from {} -- received response code {}. - Falha ao baixar dados de {} -- código de resposta recebido {}. - - - - Composite view - Vista composta - - - - Expanded view - Expandir visão - - - - Compact view - Visualização compacta - - - - Alphabetical - Sort order - Alfabético - - - - Last Updated - Sort order - Atualizado pela última vez - - - - Date Created - Sort order - Data de criação - - - - GitHub Stars - Sort order - Estrelas no GitHub - - - - Score - Sort order - Pontuação - - - - Std_AddonMgr - - - &Addon manager - Gerenciador de Extensões - - - - Manage external workbenches, macros, and preference packs - Gerenciar bancadas, macros e pacotes de preferência externos - - - - AddonInstaller - - - Finished removing {} - Finalizando e removendo {} - - - - Failed to remove some files - Falha ao remover alguns arquivos - - - - Addons installer - - - Finished updating the following addons - Terminou de atualizar as seguintes extensões - - - - Workbench - - - Auto-Created Macro Toolbar - Barra de Macro Criada Automaticamente - - - - QObject - - - Addon Manager - Gerenciador de Extensões - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.qm deleted file mode 100644 index 63d2c0a245d2b9ad29c88c8886cb75400ffc4aea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70232 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 Ziwt`s!gUOPG~8b-e)e)O@QjLz{|DBLQuY7< diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.ts deleted file mode 100644 index 0c2d172b0c..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_pt-PT.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Repositório personalizado - - - - Repository URL - URL do Repositório - - - - Branch - Ramo - - - - CompactView - - - - Icon - Ãcone - - - - - <b>Package Name</b> - <b>Nome do Pacote</b> - - - - - Version - Versão - - - - - Description - Descrição - - - - Update Available - Atualização Disponível - - - - UpdateAvailable - AtualizacaoDisponivel - - - - DependencyDialog - - - Dependencies - Dependências - - - - Dependency type - Tipo de Dependência - - - - Name - Nome - - - - Optional? - Opcional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolver Dependências - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Este Suplemento tem as seguintes dependências obrigatórias e opcionais. Tem de instalá-las para ser possível utilizar este Suplemento. - -Pretende que o Gestor de Suplementos as instale automaticamente? Escolha "Ignorar" para instalar o Suplemento sem instalar as dependências. - - - - FreeCAD Addons - Suplementos FreeCAD - - - - Required Python modules - Módulos Python obrigatórios - - - - Optional Python modules - Módulos opcionais do Python - - - - DeveloperModeDialog - - - Addon Developer Tools - Ferramentas do Programador de Suplementos - - - - Path to Addon - Caminho para o Suplemento - - - - - Browse... - Explorar... - - - - Metadata - Metadados - - - - Primary branch - Ramo primário - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explicação do que este Suplemento fornece. Exibido no Gestor de Suplementos. Não é necessário especificar que este é um Suplemento do FreeCAD. - - - - Description - Descrição - - - - Discussion URL - URL de Discussão - - - - Icon - Ãcone - - - - Bugtracker URL - URL do Seguidor de Erros - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Suportados os estilos Semantic (1.2.3-beta) ou CalVer (2022.08.30) - - - - Set to today (CalVer style) - Definir para hoje (estilo CalVer) - - - - - - - (Optional) - (Opcional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Exibido na lista Suplementos do Gestor de Suplementos. Não deve incluir a palavra "FreeCAD", e tem de ser um nome de diretório válido em todos os sistemas operativos suportados. - - - - README URL - URL do README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - DICA: Como isto é exibido no FreeCAD, no Gestor de Suplementos, não é necessário escrever coisas como "This is a FreeCAD Addon..." — descreva apenas o que faz. - - - - Repository URL - URL do Repositório - - - - Website URL - URL do Website - - - - Documentation URL - URL da Documentação - - - - Addon Name - Nome do Suplemento - - - - Version - Versão - - - - (Recommended) - (Recomendado) - - - - Minimum Python - Python mínimo - - - - (Optional, only 3.x version supported) - (Opcional, apenas é suportada a versão 3.x) - - - - Detect... - Detetar... - - - - Addon Contents - Conteúdo do Suplemento - - - - Dialog - - - Addon Manager - Gestor de Suplementos - - - - Edit Tags - Editar Etiquetas - - - - Comma-separated list of tags describing this item: - Lista de etiquetas separadas por vírgulas que descrevem este item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - DICA: São etiquetas comuns "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Aviso! Gestor de Extras! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - O Gestor de Extras oferece acesso a uma ampla biblioteca de extensões FreeCAD úteis de terceiros. Não podem ser dadas garantias sobre sua segurança ou funcionalidade. - - - - Continue - Continuar - - - - Cancel - Cancelar - - - - EditDependencyDialog - - - Edit Dependency - Editar Dependência - - - - Dependency Type - Tipo de Dependência - - - - Dependency - Dependência - - - - Package name, if "Other..." - Nome do Pacote, se "Outro..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTA: Se "Outro..." estiver selecionado, o pacote não está no ficheiro ALLOWED_PYTHON_PACKAGES.txt, e não será automaticamente instalado pelo Gestor de Suplementos. Envie um PR em <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> para pedir que um pacote seja adicionado. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Se esta for uma dependência opcional, o Gestor de Suplementos vai propor a sua instalação (quando possível), mas não irá impedir a instalação se o utilizador optar por não o fazer, ou não possa, instalar o pacote. - - - - Optional - Opcional - - - - ExpandedView - - - - Icon - Ãcone - - - - - <h1>Package Name</h1> - <h1>Nome do Pacote</h1> - - - - - Version - Versão - - - - - (tags) - (etiquetas) - - - - - Description - Descrição - - - - - Maintainer - Mantido por - - - - Update Available - Atualização disponível - - - - labelSort - labelSort - - - - UpdateAvailable - AtualizacaoDisponivel - - - - Form - - - Licenses - Licenças - - - - License - Licença - - - - License file - Ficheiro da licença - - - - People - Pessoas - - - - Kind - Tipo - - - - Name - Nome - - - - Email - Correio eletrónico - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Mapeamento Avançado de Versão - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Versões futuras do Gestor de Suplementos FreeCAD vão permitir que os programadores definam um ramo específico ou etiqueta para uso com uma versão específica do FreeCAD (e.g. definir uma etiqueta específica que indique que a última versão do seu Suplemento suporta v0.19, etc.) - - - - FreeCAD Version - Versão do FreeCAD - - - - Best-available branch, tag, or commit - Melhor ramo, etiqueta ou confirmação (commit) disponível - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versões do FreeCAD suportadas - - - - Minimum FreeCAD Version Supported - Versão mínima do FreeCAD suportada - - - - - Optional - Opcional - - - - Maximum FreeCAD Version Supported - Versão máxima do FreeCAD suportada - - - - Advanced version mapping... - Mapeamento avançado de versão... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opções do Gestor de Suplementos - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Se esta opção estiver selecionada, ao iniciar o Gestor de Suplementos, -será verificado se existem atualizações disponíveis para os suplementos instalados - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Transferir metadados da Macro (cerca de 10 MB) - - - - Cache update frequency - Frequência de atualização da Cache - - - - Manual (no automatic updates) - Manual (sem atualizações automáticas) - - - - Daily - Diariamente - - - - Weekly - Semanalmente - - - - Hide Addons without a license - Ocultar Suplementos sem licença - - - - Hide Addons with non-FSF Free/Libre license - Ocultar extras com licença não-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Ocultar extras com licença não-aprovada - - - - Hide Addons marked Python 2 Only - Ocultar extras marcados apenas para Python 2 - - - - Hide Addons marked Obsolete - Ocultar extras marcados como obsoletos - - - - Hide Addons that require a newer version of FreeCAD - Ocultar Suplementos que requerem uma versão mais recente do FreeCAD - - - - Custom repositories - Repositórios personalizados - - - - Proxy - Proxy - - - - No proxy - Sem proxy - - - - User system proxy - Proxy do sistema do utilizador - - - - User-defined proxy: - Proxy definido pelo utilizador: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Opções Avançadas - - - - Activate Addon Manager options intended for developers of new Addons. - Ativar opções do Gestor de Suplementos destinadas aos programadores de novos Suplementos. - - - - Addon developer mode - Modo de desenvolvedor de extras - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Desinstala uma macro ou bancada de trabalho selecionada - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Update - Atualizar - - - - Run Macro - Executar Macro - - - - Change branch - Mudar ramo - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Os seguintes pacotes do Python foram instalados localmente pelo Gestor de Suplementos para satisfazer as dependências do Suplemento. Localização da instalação: - - - - Package name - Nome do pacote - - - - Installed version - Versão instalada - - - - Available version - Versão disponível - - - - Used by - Usado por - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Atualizar todos os disponíveis - - - - SelectFromList - - - Dialog - Caixa de diálogo - - - - TextLabel - Rótulo de texto - - - - UpdateAllDialog - - - Updating Addons - A atualizar os Suplementos - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Item de Conteúdo - - - - Content type: - Tipo de conteúdo: - - - - Macro - Macro - - - - Preference Pack - Pacote de Preferências - - - - Workbench - Bancada de trabalho - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Explorar... - - - - Preference Pack Name - Nome do Pacote de Preferências - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Ãcone - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Etiquetas... - - - - Dependencies... - Dependências... - - - - FreeCAD Versions... - Versões do FreeCAD... - - - - Other Metadata - Outros Metadados - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versão - - - - Description - Descrição - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Suportados os estilos Semantic (1.2.3-beta) ou CalVer (2022.08.30) - - - - Set to today (CalVer style) - Definir para hoje (estilo CalVer) - - - - Display Name - Nome a exibir - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Adicionar botão? - - - - Add a toolbar button for this macro? - Adicionar um botão na barra de ferramentas para esta macro? - - - - Yes - Sim - - - - No - Não - - - - Never - Nunca - - - - change_branch - - - Change Branch - Mudar Ramo - - - - Change to branch: - Mudar para o ramo: - - - - copyrightInformationDialog - - - Copyright Information - Informação de Direitos de Autor - - - - Copyright holder: - Detentor dos Direitos de Autor: - - - - Copyright year: - Ano dos Direitos de Autor: - - - - personDialog - - - Add Person - Adicionar Pessoa - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Uma pessoa que mantém é alguém que possui atualmente acesso de confirmação (commit) neste projeto. Um autor é qualquer pessoa a quem deseja dar crédito. - - - - Name: - Nome: - - - - Email: - Correio eletrónico: - - - - Email is required for maintainers, and optional for authors. - O correio eletrónico é obrigatório para mentenedores, e opcional para autores. - - - - proxy_authentication - - - Proxy login required - É necessário o início de sessão do proxy - - - - Proxy requires authentication - O proxy exige autenticação - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Nome de utilizador - - - - Password - Palavra-passe - - - - selectLicenseDialog - - - Select a license - Escolha uma licença - - - - About... - Acerca de... - - - - License name: - Nome da Licença: - - - - Path to license file: - Caminho para o ficheiro da licença: - - - - (if required by license) - (se exigido pela licença) - - - - Browse... - Explorar... - - - - Create... - Criar... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Selecionar Barra de Ferramentas - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Perguntar sempre - - - - toolbar_button - - - - Add button? - Adicionar botão? - - - - Add a toolbar button for this macro? - Adicionar um botão na barra de ferramentas para esta macro? - - - - Yes - Sim - - - - No - Não - - - - Never - Nunca - - - - AddonsInstaller - - - Starting up... - A iniciar... - - - - Worker process {} is taking a long time to stop... - O processo Trabalhador {} está a demorar muito tempo a parar... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Gestor de Suplementos - - - - You must restart FreeCAD for changes to take effect. - Tem de reiniciar o FreeCAD para que as alterações surtam efeito. - - - - Restart now - Reiniciar agora - - - - Restart later - Reiniciar mais tarde - - - - - Refresh local cache - Refresh local cache - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - A procurar atualizações... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Fechar - - - - Update all addons - Atualizar todos os suplementos - - - - Check for updates - A procurar atualizações - - - - Python dependencies... - Dependências do Python... - - - - Developer tools... - Ferramentas do Programador... - - - - Apply %n available update(s) - Aplicar atualizações disponíveis: %n - - - - No updates available - Nenhuma atualização disponível - - - - - - Cannot launch a new installer until the previous one has finished. - Não é possível iniciar um novo instalador até que o anterior tenha terminado. - - - - - - - Maintainer - Mantido por - - - - - - - Author - Autor - - - - New Python Version Detected - Nova Versão do Python Detetada - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Parece ser a primeira vez que esta versão do Python foi usada no Gestor de Suplementos. Pretende instalar as mesmas dependências automaticamente instaladas, para esta versão? - - - - Processing, please wait... - A processar. Por favor aguarde... - - - - - Update - Atualizar - - - - Updating... - A atualizar... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Não foi possível importar o QtNetwork — parece não estar instalado no seu sistema. O seu fornecedor pode ter um pacote para esta dependência (muitas vezes chamada "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Falha ao converter a porta proxy especificada '{}' para um número de porta - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Erro de parâmetro: definidas opções de proxy mutuamente exclusivas. Vai ser redefinido o valor padrão. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Erro de parâmetro: indicado um proxy do utilizador, mas nenhum proxy foi fornecido. Vai ser redefinido o valor padrão. - - - - Addon Manager: Unexpected {} response from server - Gestor de Suplementos: Resposta inesperada {} do servidor - - - - Error with encrypted connection - Erro com a ligação encriptada - - - - - - Confirm remove - Confirme a remoção - - - - Are you sure you want to uninstall {}? - Tem a certeza que quer desinstalar {}? - - - - - - Removing Addon - A remover o Suplemento - - - - Removing {} - A remover {} - - - - - Uninstall complete - Desinstalação concluída - - - - - Uninstall failed - Falha ao desinstalar - - - - Version {version} installed on {date} - Versão {version} instalada a {date} - - - - Version {version} installed - Versão {version} instalada - - - - Installed on {date} - Instalado a {date} - - - - - - - Installed - Instalado - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Verificação de atualização em curso - - - - Installation location - Local de instalação - - - - Repository URL - URL do Repositório - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Desativado - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - AVISO: Este suplemento requer o FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Sucesso - - - - Install - Instalar - - - - Uninstall - Desinstalar - - - - Enable - Ativar - - - - Disable - Desativar - - - - - Check for update - Verificar atualização - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Executar - - - - Change branch... - Mudar ramo... - - - - Return to package list - Voltar à lista de pacotes - - - - Checking connection - A verificar a ligação - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - A ligação falhou - - - - Missing dependency - Dependência em falta - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Outra... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Falha ao instalar a macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automática - - - - - Workbench - Bancada de trabalho - - - - Addon - Suplemento - - - - Python - Python - - - - Yes - Sim - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Pacote Python - - - - - Other... - Outra... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Requisito em Falta - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - O suplemento '{}' requer '{}', que não está disponível no seu FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - O suplemento '{}' requer as seguintes bancadas de trabalho, que não estão disponíveis no seu FreeCAD: - - - - Press OK to install anyway. - Pressione OK para instalar mesmo assim. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Este suplemento requer pacotes Python que não estão instalados e não podem ser instalados automaticamente. Para usar este suplemento, tem de instalar os seguintes pacotes Python manualmente: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Este Suplemento (ou uma das suas dependências) requer Python {}.{}, e o seu sistema possui Python {}.{}. A instalação foi cancelada. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - A instalar dependências - - - - - Cannot execute Python - Não é possível executar o Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Não é possível executar o pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Instalação do pacote falhou - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - A cancelar - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Executar - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Nome - - - - Class - Classe - - - - Description - Descrição - - - - Subdirectory - Subdirectory - - - - Files - Ficheiros - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - O Vermin detetou automaticamente uma versão requerida do Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - A deteção automática da versão do Python exigida para este Suplemento requer Vermin (https://pypi.org/project/vermin/). OK para instalar? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - O filtro é válido - - - - Filter regular expression is invalid - A expressão regular do filtro não é válida - - - - Search... - Procurar... - - - - Click for details about package {} - Clique para detalhes acerca do pacote {} - - - - Click for details about workbench {} - Clique para detalhes acerca da bancada de trabalho {} - - - - Click for details about macro {} - Clique para detalhes acerca da macro {} - - - - Maintainers: - Mantido por: - - - - Tags - Etiquetas - - - - {} ★ on GitHub - {} ★ no GitHub - - - - No ★, or not on GitHub - Sem ★, ou não no GitHub - - - - Created - Criado - - - - Updated - Atualizado - - - - Score: - Pontuação: - - - - - Up-to-date - Atualizado - - - - - - - - Update available - Atualização disponível - - - - - Pending restart - Reinício pendente - - - - - DISABLED - DESATIVADO - - - - Installed version - Versão instalada - - - - Unknown version - Versão desconhecida - - - - Installed on - Instalado a - - - - Available version - Versão disponível - - - - Filter by... - Filtrar por... - - - - Addon Type - Tipo de Suplemento - - - - - Any - Qualquer - - - - Macro - Macro - - - - Preference Pack - Pacote de Preferências - - - - Installation Status - Estado da Instalação - - - - Not installed - Não instalado - - - - Filter - Filtro - - - - DANGER: Developer feature - PERIGO: Recurso de programador - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - PERIGO: A troca de ramos é destinada a programadores e testadores beta, e pode resultar em documentos danificados e não retrocompatíveis, instabilidade, o programa deixar de funcionar e/ou ao fim prematuro do universo. Tem certeza que quer continuar? - - - - There are local changes - Existem alterações locais - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - AVISO: Este repositório tem alterações locais não confirmadas (uncommited). Tem certeza que deseja mudar de ramos (trazendo as alterações consigo)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Última Atualização - - - - Installation of Python package {} failed - Falha na instalação do pacote Python {} - - - - Installation of optional package failed - Falha na instalação do pacote opcional - - - - Installing required dependency {} - A instalar a dependência necessária {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Erro ao tentar importar {} - - - - An unknown error occurred - Ocorreu um erro desconhecido - - - - Could not find addon {} to remove it. - Não foi possível encontrar o suplemento {} para removê-lo. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - AVISO: Suplemento duplicado {} foi ignorado - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Falha ao ler metadados de {name} - - - - Failed to fetch code for macro '{name}' - Falha ao obter código para a macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Gestor de Suplementos: um processo trabalhador não completou a tarefa ao obter {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Das {num_macros} macros, {num_failed} excederam o tempo limite durante o processamento - - - - Addon Manager: a worker process failed to halt ({name}) - Gestor de Suplementos: um processo trabalhador falhou a parar ({name}) - - - - Timeout while fetching metadata for macro {} - Tempo limite excedido ao obter metadados para a macro {} - - - - Failed to kill process for macro {}! - - Falha ao terminar o processo para a macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Falha ao obter estatísticas do Suplemento de {} — apenas a ordenação alfabética estará correta - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Falha ao obter a pontuação do Suplemento de '{}' — ordenar por pontuação vai falhar - - - - - Repository URL - Preferences header for custom repositories - URL do Repositório - - - - Branch name - Preferences header for custom repositories - Nome do ramo - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - A fazer cópia de segurança do diretório original e a reclonar - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - A renomeação do ramo do Git falhou com a seguinte mensagem: - - - - Installing - A instalar - - - - Succeeded - Sucesso - - - - Failed - Falha - - - - Update was cancelled - A atualização foi cancelada - - - - some addons may have been updated - alguns suplementos podem ter sido atualizados - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - A carregar a informação para {} da wiki de Receitas de Macros FreeCAD... - - - - Loading page for {} from {}... - A carregar a página para {} de {}... - - - - Failed to download data from {} -- received response code {}. - Falha ao transferir dados a partir de {} — recebido o código de resposta {}. - - - - Composite view - Vista composta - - - - Expanded view - Vista expandida - - - - Compact view - Vista compacta - - - - Alphabetical - Sort order - Alfabeticamente - - - - Last Updated - Sort order - Última Atualização - - - - Date Created - Sort order - Data de Criação - - - - GitHub Stars - Sort order - Estrelas do GitHub - - - - Score - Sort order - Pontuação - - - - Std_AddonMgr - - - &Addon manager - &Gestor de suplementos - - - - Manage external workbenches, macros, and preference packs - Gerir bancadas de trabalho, macros, e pacote de preferências externas - - - - AddonInstaller - - - Finished removing {} - Remoção concluída de {} - - - - Failed to remove some files - Falha ao remover alguns ficheiros - - - - Addons installer - - - Finished updating the following addons - Atualização concluída para os seguintes suplementos - - - - Workbench - - - Auto-Created Macro Toolbar - Barra de ferramentas de Macros criada automaticamente - - - - QObject - - - Addon Manager - Gestor de Suplementos - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ro.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ro.qm deleted file mode 100644 index 11b255ea3aeafc88ca805652b39c7da29634bcd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66678 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 - - - - AddCustomRepositoryDialog - - - Custom repository - Depozit de cod - - - - Repository URL - URL repozitoriu - - - - Branch - Ramură - - - - CompactView - - - - Icon - Iconiță - - - - - <b>Package Name</b> - Numele Pachetului - - - - - Version - Versiunea - - - - - Description - Descriere - - - - Update Available - Actualizare disponibilă - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - DependinÈ›e - - - - Dependency type - Dependency type - - - - Name - Nume - - - - Optional? - OpÅ£ional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Această Adăugare are atât dependinÈ›e necesare cât È™i opÈ›ionale. Trebuie să le instalezi pentru a putea folosi această Adăugare. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Descriere - - - - Discussion URL - Discussion URL - - - - Icon - Iconiță - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - URL repozitoriu - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Versiunea - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Manager de addon - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Continua - - - - Cancel - Renunţă - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - - Icon - Iconiță - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - Versiunea - - - - - (tags) - (tags) - - - - - Description - Descriere - - - - - Maintainer - Maintainer - - - - Update Available - Actualizare disponibilă - - - - labelSort - labelSort - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - Licenses - Licenses - - - - License - Licenţă - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - Nume - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manual (no automatic updates) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Proxy - OpÈ›iuni Proxy - - - - No proxy - Fără proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Advanced Options - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Install - - - - Uninstall - Uninstall - - - - Update - Actualizare - - - - Run Macro - Run Macro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Dialog - - - - TextLabel - TextLabel - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Macrocomandă - - - - Preference Pack - Preference Pack - - - - Workbench - Banc de lucru - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Numele pachetului de preferinÈ›e - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Iconiță - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versiunea - - - - Description - Descriere - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Nume afiÈ™at - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Nume: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - AddonsInstaller - - - Starting up... - Starting up... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - Refresh local cache - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - Checking for updates... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - ÃŽnchide - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - - - - Maintainer - Maintainer - - - - - - - Author - Autor - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Actualizare - - - - Updating... - Updating... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installation location - - - - Repository URL - URL repozitoriu - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Dezactivat - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Install - Install - - - - Uninstall - Uninstall - - - - Enable - Activeaza - - - - Disable - Dezactivare - - - - - Check for update - Check for update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Execută - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automat - - - - - Workbench - Banc de lucru - - - - Addon - Addon - - - - Python - Python - - - - Yes - Yes - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Other... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Execută - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Nume - - - - Class - Clasă - - - - Description - Descriere - - - - Subdirectory - Subdirectory - - - - Files - Files - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Caută... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Etichete - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Installed version - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Available version - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Oricare - - - - Macro - Macrocomandă - - - - Preference Pack - Preference Pack - - - - Installation Status - Installation Status - - - - Not installed - Not installed - - - - Filter - Filtru - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - URL repozitoriu - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - Bară Macro creată automat - - - - QObject - - - Addon Manager - Manager de addon - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ru.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_ru.qm deleted file mode 100644 index 72cb9f2a1e2c858283a9b1d8a3a3f59e9d206f37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70826 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 QikW|!J1zC}%I4Gm4_7_ZumAu6 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_ru.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_ru.ts deleted file mode 100644 index f6f3526490..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_ru.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - ПользовательÑкий репозиторий - - - - Repository URL - URL Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ - - - - Branch - Ветка - - - - CompactView - - - - Icon - Иконка - - - - - <b>Package Name</b> - <b>Ðазвание пакета</b> - - - - - Version - ВерÑÐ¸Ñ - - - - - Description - ОпиÑание - - - - Update Available - ДоÑтупно обновление - - - - UpdateAvailable - ДоÑтупно обновление - - - - DependencyDialog - - - Dependencies - ЗавиÑимоÑти - - - - Dependency type - Тип завиÑимоÑти - - - - Name - Ðазвание - - - - Optional? - ÐеобÑзательное? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Разрешить завиÑимоÑти - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Это Дополнение имеет Ñледующие необходимые и необÑзательные завиÑимоÑти. Ð’Ñ‹ должны уÑтановить их перед иÑпользованием Ñтого дополнениÑ. - -Хотите, чтобы менеджер дополнений уÑтановил их автоматичеÑки? Выберите "Игнорировать" Ð´Ð»Ñ ÑƒÑтановки Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð±ÐµÐ· уÑтановки завиÑимоÑтей. - - - - FreeCAD Addons - Ð”Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ FreeCAD - - - - Required Python modules - Ðеобходимые модули Python - - - - Optional Python modules - ÐеобÑзательные модули Python - - - - DeveloperModeDialog - - - Addon Developer Tools - ИнÑтрументы разработчика дополнений - - - - Path to Addon - Путь к дополнению - - - - - Browse... - Обзор... - - - - Metadata - Метаданные - - - - Primary branch - ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - ОпиÑание возможноÑтей Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÐµÑ‚ÑÑ Ð² менеджере дополнений. Ðет необходимоÑти пиÑать, что Ñто дополнение Ð´Ð»Ñ FreeCAD. - - - - Description - ОпиÑание - - - - Discussion URL - СÑылка на обÑуждение - - - - Icon - Иконка - - - - Bugtracker URL - СÑылка Ð´Ð»Ñ Ð¾Ñ‚ÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - ПоддерживаютÑÑ Ñтили Semantic (1.2.3-beta) или CalVer (2022.08.30) - - - - Set to today (CalVer style) - ПоÑтавить ÑегоднÑшнюю дату (Ñтиль CalVer) - - - - - - - (Optional) - (ÐеобÑзательно) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - ОтображаетÑÑ Ð² ÑпиÑке дополнений менеджера дополнений. Ðе должно включать Ñлово "FreeCAD", и должно быть корректным именем каталога во вÑех поддерживаемых операционных ÑиÑтемах. - - - - README URL - URL опиÑÐ°Ð½Ð¸Ñ - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - СОВЕТ: ПоÑкольку Ñто отображаетÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ FreeCAD, в диÑпетчере дополнений, нет необходимоÑти занимать меÑто Ñловами типа "Это дополнение FreeCAD..." - проÑто опишите, что оно делает. - - - - Repository URL - URL Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ - - - - Website URL - СÑылка на Ñайт - - - - Documentation URL - СÑылка на документацию - - - - Addon Name - Ðазвание Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - Version - ВерÑÐ¸Ñ - - - - (Recommended) - (РекомендуетÑÑ) - - - - Minimum Python - ÐœÐ¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Python - - - - (Optional, only 3.x version supported) - (ÐеобÑзательно, поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ верÑÐ¸Ñ 3.x) - - - - Detect... - Ðайти... - - - - Addon Contents - Содержимое Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - Dialog - - - Addon Manager - Менеджер дополнений - - - - Edit Tags - Редактировать теги - - - - Comma-separated list of tags describing this item: - СпиÑок тегов, разделённых запÑтыми, опиÑывающих Ñтот Ñлемент: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - ПОДСКÐЗКÐ: Обычно теги Ñодержат "Assembly", "FEM", "Mesh", "NURBS" и Ñ‚.д. - - - - Add-on Manager: Warning! - Менеджер дополнений: Предупреждение! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Менеджер дополнений предоÑтавлÑет доÑтуп к обширной библиотеке полезных Ñторонних раÑширений FreeCAD. Ðе может быть никаких гарантий отноÑительно их безопаÑноÑти или функциональноÑти. - - - - Continue - Продолжить - - - - Cancel - Отмена - - - - EditDependencyDialog - - - Edit Dependency - Редактировать завиÑимоÑти - - - - Dependency Type - Тип завиÑимоÑти - - - - Dependency - ЗавиÑимоÑть - - - - Package name, if "Other..." - Ðазвание пакета, еÑли "Другое..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - ПРИМЕЧÐÐИЕ: ЕÑли выбрано "Другое..." и название пакета отÑутÑтвует в ALLOWED_PYTHON_PACKAGES.txt, то пакет не будет автоматичеÑки уÑтановлен менеджером дополнений. Отправьте PR на <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a>, чтобы запроÑить добавление пакета. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - ЕÑли Ñто необÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ð²Ð¸ÑимоÑть, менеджер дополнений предложит уÑтановить ее (когда Ñто возможно), но не будет блокировать уÑтановку, еÑли пользователь решит не уÑтанавливать или не Ñможет уÑтановить пакет. - - - - Optional - ÐеобÑзательное - - - - ExpandedView - - - - Icon - Иконка - - - - - <h1>Package Name</h1> - <h1>Ðазвание пакета</h1> - - - - - Version - ВерÑÐ¸Ñ - - - - - (tags) - (теги) - - - - - Description - ОпиÑание - - - - - Maintainer - ПоÑтавщик ПО - - - - Update Available - ДоÑтупно обновление - - - - labelSort - Сортировка - - - - UpdateAvailable - ДоÑтупно обновление - - - - Form - - - Licenses - Лицензии - - - - License - Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ - - - - License file - Файл лицензии - - - - People - Контакты - - - - Kind - Роль - - - - Name - Ð˜Ð¼Ñ - - - - Email - Эл. почта - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - РаÑÑˆÐ¸Ñ€ÐµÐ½Ð½Ð°Ñ Ð½Ð°Ñтройка поддержки верÑий - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - ПредÑтоÑщие верÑии Менеджера дополнений FreeCAD будут поддерживать наÑтройку разработчиком конкретной ветки или тега Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ð¹ верÑией FreeCAD (например указание отдельного тега в качеÑтве поÑледней верÑии, поддерживаемой вашим дополнением v0.19 и Ñ‚. д.) - - - - FreeCAD Version - ВерÑÐ¸Ñ FreeCAD - - - - Best-available branch, tag, or commit - Ðаиболее доÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ‚ÐºÐ°, Ñ‚Ñг или коммит - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Поддерживаемые верÑии FreeCAD - - - - Minimum FreeCAD Version Supported - ÐœÐ¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ FreeCAD - - - - - Optional - Дополнительно - - - - Maximum FreeCAD Version Supported - МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ FreeCAD - - - - Advanced version mapping... - РаÑÑˆÐ¸Ñ€ÐµÐ½Ð½Ð°Ñ Ð½Ð°Ñтройка ÑопоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€Ñий... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - ÐаÑтройки менеджера дополнений - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - ЕÑли выбран Ñтот пункт, то при запуÑке менеджера дополнений -уÑтановленные Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ проверены на наличие доÑтупных обновлений - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Скачать метаданные макроÑов (примерно 10 Мб) - - - - Cache update frequency - ЧаÑтота Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÑша - - - - Manual (no automatic updates) - Вручную (без автоматичеÑкого обновлениÑ) - - - - Daily - Ежедневно - - - - Weekly - Еженедельно - - - - Hide Addons without a license - Скрыть Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð±ÐµÐ· лицензии - - - - Hide Addons with non-FSF Free/Libre license - Скрыть Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸ÐµÐ¹ отличной от СПО Free/Libre - - - - Hide Addons with non-OSI-approved license - Скрыть Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸ÐµÐ¹, не одобренной OSI - - - - Hide Addons marked Python 2 Only - Скрыть дополнениÑ, помеченные "Только Python 2" - - - - Hide Addons marked Obsolete - Скрыть дополнениÑ, помеченные "УÑтаревшие" - - - - Hide Addons that require a newer version of FreeCAD - Скрыть дополнениÑ, которые требуют более новой верÑии FreeCAD - - - - Custom repositories - ПользовательÑкие репозитории - - - - Proxy - ПрокÑи-Ñервер - - - - No proxy - Без прокÑи - - - - User system proxy - ИÑпользовать ÑиÑтемный прокÑи - - - - User-defined proxy: - Заданный пользователем прокÑи: - - - - Score source URL - URL-Ð°Ð´Ñ€ÐµÑ Ð¸Ñточника оценки - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - URL-Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… о баллах дополнений (подробноÑти о форматировании и хоÑтинге Ñм. на вики Ñтранице менеджера дополнений). - - - - Path to Git executable (optional): - Путь к иÑполнÑемому файлу git (необÑзательно): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Дополнительные наÑтройки - - - - Activate Addon Manager options intended for developers of new Addons. - Ðктивировать функции менеджера дополнений, предназначенные Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² новых дополнений. - - - - Addon developer mode - Режим разработчика дополнений - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Удаление выбранного макроÑа или верÑтака - - - - Install - УÑтановить - - - - Uninstall - Удалить - - - - Update - Обновить - - - - Run Macro - Выполнить Ð¼Ð°ÐºÑ€Ð¾Ñ - - - - Change branch - Изменить ветку - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Управление завиÑимоÑÑ‚Ñми Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Следующие пакеты Python были уÑтановлены локально Менеджером дополнений Ð´Ð»Ñ ÑƒÐ´Ð¾Ð²Ð»ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð¸Ñ Ð·Ð°Ð²Ð¸ÑимоÑтей. МеÑто уÑтановки: - - - - Package name - Ðазвание пакета - - - - Installed version - УÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - Available version - ДоÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - Used by - ИÑпользуетÑÑ Ð² - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Знак (*) в Ñтолбце "ИÑпользуетÑÑ Ð²" указывает на необÑзательную завиÑимоÑть. Заметьте, что в Ñтолбце "ИÑпользуетÑÑ Ð²" показаны прÑмо импортированные пакеты. Также могут быть уÑтановлены другие Python пакеты, необходимые Ð´Ð»Ñ Ñтих пакетов,. - - - - Update all available - Обновить вÑе - - - - SelectFromList - - - Dialog - Диалог - - - - TextLabel - Заголовок - - - - UpdateAllDialog - - - Updating Addons - Обновление дополнений - - - - Updating out-of-date addons... - Обновление уÑтаревших дополнений... - - - - addContentDialog - - - Content Item - Содержимое Ñлемента - - - - Content type: - Тип Ñодержимого: - - - - Macro - Макрокоманда - - - - Preference Pack - Пакет наÑтроек - - - - Workbench - ВерÑтак - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - ЕÑли Ñто единÑÑ‚Ð²ÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ‰ÑŒ в дополнении, вÑе оÑтальные метаданные могут быть унаÑледованы от верхнего уровнÑ, и не требует ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð·Ð´ÐµÑÑŒ. - - - - This is the only item in the Addon - Это единÑтвенный Ñлемент в дополнении - - - - Main macro file - ОÑновной файл макроÑа - - - - The file with the macro's metadata in it - Файл, Ñодержащий метаданные, макроÑа - - - - - - Browse... - Обзор... - - - - Preference Pack Name - Ðазвание пакета наÑтроек - - - - Workbench class name - Ðазвание клаÑÑа верÑтака - - - - Class that defines "Icon" data member - КлаÑÑ, определÑющий Ñлемент оÑновных данных - - - - Subdirectory - Подкаталог - - - - Optional, defaults to name of content item - ÐеобÑзательно, по умолчанию равно названию Ñлемента - - - - Icon - Иконка - - - - Optional, defaults to inheriting from top-level Addon - ÐеобÑзательно, по умолчанию наÑледуетÑÑ Ð¾Ñ‚ общих наÑтроек Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - Tags... - Теги... - - - - Dependencies... - ЗавиÑимоÑти... - - - - FreeCAD Versions... - ВерÑии FreeCAD... - - - - Other Metadata - Другие данные - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - ОтображаетÑÑ Ð² ÑпиÑке Менеджера дополнений. Ðе Ñледует указывать Ñлово "FreeCAD". - - - - Version - ВерÑÐ¸Ñ - - - - Description - ОпиÑание - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - ПоддерживаютÑÑ Ñтили Semantic (1.2.3-beta) или CalVer (2022.08.30) - - - - Set to today (CalVer style) - ПоÑтавить ÑегоднÑшнюю дату (Ñтиль CalVer) - - - - Display Name - Отображаемое название - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Любые незаполненные Ð¿Ð¾Ð»Ñ ÑƒÐ½Ð°Ñледуют Ñодержимое от метаданных верхнего уровнÑ, поÑтому техничеÑки вÑе они ÑвлÑÑŽÑ‚ÑÑ Ð½ÐµÐ¾Ð±Ñзательными. Ð”Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ð¹ Ñ Ð½ÐµÑколькими Ñлементами Ñодержимого, каждый Ñлемент должен предоÑтавить уникальное отображаемое Ð¸Ð¼Ñ Ð¸ опиÑание. - - - - add_toolbar_button_dialog - - - Add button? - Добавить кнопку? - - - - Add a toolbar button for this macro? - Добавить кнопку на панель инÑтрументов Ð´Ð»Ñ Ñтого макроÑа? - - - - Yes - Да - - - - No - Ðет - - - - Never - Ðикогда - - - - change_branch - - - Change Branch - Изменить ветку - - - - Change to branch: - Перейти в ветку: - - - - copyrightInformationDialog - - - Copyright Information - Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± авторÑких правах - - - - Copyright holder: - Владелец авторÑких прав: - - - - Copyright year: - Год авторÑких прав: - - - - personDialog - - - Add Person - Добавить учаÑтника проекта - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - ПоÑтавщик ПО ― кто-то Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñтью коммита в Ñтом проекте. Ðвтор ― кто-либо еще внеÑший вклад. - - - - Name: - ИмÑ: - - - - Email: - Эл. почта: - - - - Email is required for maintainers, and optional for authors. - Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° обÑзательна Ð´Ð»Ñ Ð¿Ð¾Ñтавщиков ПО, но необÑзательна Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð². - - - - proxy_authentication - - - Proxy login required - ТребуетÑÑ Ð²Ñ…Ð¾Ð´ на прокÑи - - - - Proxy requires authentication - Ð”Ð»Ñ Ð¿Ñ€Ð¾ÐºÑи Ñервера требуетÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ - - - - Proxy: - ПрокÑи Ñервер: - - - - Placeholder for proxy address - Введите Ñюда Ð°Ð´Ñ€ÐµÑ Ð¿Ñ€Ð¾ÐºÑи Ñервера - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Введите Ñюда proxy realm - - - - Username - Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ - - - - Password - Пароль - - - - selectLicenseDialog - - - Select a license - Выберите лицензию - - - - About... - О лицензии... - - - - License name: - Ðазвание лицензии: - - - - Path to license file: - Путь к файлу лицензии: - - - - (if required by license) - (еÑли требуетÑÑ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸ÐµÐ¹) - - - - Browse... - Обзор... - - - - Create... - Создать... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Выберите Панель инÑтрументов - - - - Select a toolbar to add this macro to: - Выберите панель инÑтрументов, на которую добавить Ñтот макроÑ: - - - - Ask every time - Ð’Ñегда Ñпрашивать - - - - toolbar_button - - - - Add button? - Добавить кнопку? - - - - Add a toolbar button for this macro? - Добавить кнопку на панель инÑтрументов Ð´Ð»Ñ Ñтого макроÑа? - - - - Yes - Да - - - - No - Ðет - - - - Never - Ðикогда - - - - AddonsInstaller - - - Starting up... - ЗапуÑк... - - - - Worker process {} is taking a long time to stop... - Работающий процеÑÑ {} занимает много времени при оÑтановке... - - - - Previous cache process was interrupted, restarting... - - Предыдущий процеÑÑ ÐºÑÑˆÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ñ‹Ð» прерван, перезапуÑк... - - - - - Custom repo list changed, forcing recache... - - ПользовательÑкий ÑпиÑок Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½Ñ‘Ð½, запущено обновление кÑша... - - - - - Addon manager - Менеджер дополнений - - - - You must restart FreeCAD for changes to take effect. - Ð’Ñ‹ должны перезапуÑтить FreeCAD, чтобы Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ñтупили в Ñилу. - - - - Restart now - Перезагрузить ÑÐµÐ¹Ñ‡Ð°Ñ - - - - Restart later - Перезагрузить позже - - - - - Refresh local cache - Обновить локальный кÑш - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Обновление кÑша... - - - - - Checking for updates... - Проверка обновлений... - - - - Temporary installation of macro failed. - Ðе удалоÑÑŒ уÑтановить макроÑ. - - - - - Close - Закрыть - - - - Update all addons - Обновить вÑе Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - Check for updates - Проверить наличие обновлений - - - - Python dependencies... - ЗавиÑимоÑти Python... - - - - Developer tools... - ИнÑтрументы разработчика... - - - - Apply %n available update(s) - Применить %n доÑтупных обновлений - - - - No updates available - Обновлений нет - - - - - - Cannot launch a new installer until the previous one has finished. - Ðевозможно запуÑтить новую уÑтановку, пока не завершена предыдущаÑ. - - - - - - - Maintainer - ПоÑтавщик ПО - - - - - - - Author - Ðвтор - - - - New Python Version Detected - Обнаружена Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Похоже, что Ñта верÑÐ¸Ñ Python впервые иÑпользуетÑÑ Ð² Менеджере дополнений. УÑтановить такие же необходимые завиÑимоÑти? - - - - Processing, please wait... - Обработка, пожалуйÑта подождите... - - - - - Update - Обновить - - - - Updating... - Обновление... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Ðе удалоÑÑŒ импортировать QtNetwork ― видимо, он не уÑтановлен в ÑиÑтеме. У вашего диÑтрибутива может быть пакет Ð´Ð»Ñ Ñтой завиÑимоÑти (обычно Ñто "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Ðе удалоÑÑŒ преобразовать указанный прокÑи порт '{}' в номер порта - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Ошибка параметров: введены взаимно иÑключающие параметры прокÑи. ИÑпользуютÑÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ‹ по умолчанию. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Ошибка параметров: выбран пользовательÑкий прокÑи, но Ð°Ð´Ñ€ÐµÑ Ð¿Ñ€Ð¾ÐºÑи не введен. ИÑпользуютÑÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ‹ по умолчанию. - - - - Addon Manager: Unexpected {} response from server - Менеджер дополнений: Ðеожиданный ответ Ñервера {} - - - - Error with encrypted connection - Ошибка защищенного ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ - - - - - - Confirm remove - Подтвердите удаление - - - - Are you sure you want to uninstall {}? - Ð’Ñ‹ уверены, что хотите удалить {}? - - - - - - Removing Addon - Удаление Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - Removing {} - Удаление {} - - - - - Uninstall complete - Удаление завершено - - - - - Uninstall failed - Удаление не удалоÑÑŒ - - - - Version {version} installed on {date} - ВерÑÐ¸Ñ {version} уÑтановлена {date} - - - - Version {version} installed - УÑтановлена верÑÐ¸Ñ {version} - - - - Installed on {date} - УÑтановлено {date} - - - - - - - Installed - УÑтановлено - - - - Currently on branch {}, name changed to {} - Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð² ветке {}, Ð¸Ð¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¾ на {} - - - - Git tag '{}' checked out, no updates possible - ВерÑÐ¸Ñ git Ñ‚Ñг '{}' получена, Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½ÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹ - - - - Update check in progress - ВыполнÑетÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ° обновлений - - - - Installation location - МеÑто уÑтановки - - - - Repository URL - URL Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ - - - - Changed to branch '{}' -- please restart to use Addon. - Изменено на ветку '{}' -- пожалуйÑта, перезапуÑтите, Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ñ. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Это дополнение было обновлено. ПерезапуÑтите FreeCAD, чтобы увидеть изменениÑ. - - - - Disabled - Отключено - - - - Currently on branch {}, update available to version {} - Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ð²ÐµÑ‚ÐºÐ¸ {}, доÑтупно обновление до верÑии {} - - - - Update available to version {} - ДоÑтупно обновление до верÑии {} - - - - This is the latest version available - Это поÑледнÑÑ Ð´Ð¾ÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - WARNING: This addon is obsolete - Ð’ÐИМÐÐИЕ: Это дополнение уÑтарело - - - - WARNING: This addon is Python 2 only - Ð’ÐИМÐÐИЕ: Это дополнение только Ð´Ð»Ñ Python 2 - - - - WARNING: This addon requires FreeCAD {} - Ð’ÐИМÐÐИЕ: Ð”Ð»Ñ Ñтого Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - Ð’ÐИМÐÐИЕ: Это дополнение в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтановлено, но отключено. ИÑпользуйте кнопку 'включить' Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ включениÑ. - - - - This Addon will be enabled next time you restart FreeCAD. - Это дополнение будет включено при перезапуÑке FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Это дополнение будет отключено при перезапуÑке FreeCAD. - - - - - - Success - УÑпешно - - - - Install - УÑтановить - - - - Uninstall - Удалить - - - - Enable - Включить - - - - Disable - Отключить - - - - - Check for update - Проверить Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - ЗапуÑтить - - - - Change branch... - Изменить ветку... - - - - Return to package list - ВернутьÑÑ Ðº ÑпиÑку пакетов - - - - Checking connection - Проверка ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ - - - - Checking for connection to GitHub... - Проверка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº GitHub... - - - - Connection failed - Ðе удалоÑÑŒ подключитьÑÑ - - - - Missing dependency - ОтÑутÑтвуют завиÑимоÑти - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Ðе удалоÑÑŒ импортировать QtNetwork ― Ñмотрите панель отчёта Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей. Менеджер дополнений недоÑтупен. - - - - Other... - For providing a license other than one listed - ДругаÑ... - - - - Select the corresponding license file in your Addon - Выберите ÑоответÑтвующий файл лицензии в вашем дополнении - - - - Location for new license file - РаÑположение нового файла лицензии - - - - Received {} response code from server - Получен ответ {} от Ñервера - - - - Failed to install macro {} - Ðе удалоÑÑŒ уÑтановить Ð¼Ð°ÐºÑ€Ð¾Ñ {} - - - - Failed to create installation manifest file: - - Ðе удалоÑÑŒ Ñоздать файл манифеÑта уÑтановки: - - - - - Unrecognized content kind '{}' - ÐераÑпознанный тип Ñодержимого '{}' - - - - Unable to locate icon at {} - Ðе удалоÑÑŒ найти иконку в {} - - - - Select an icon file for this content item - Выберите файл иконки Ð´Ð»Ñ Ñтого Ñлемента Ñодержимого - - - - - - {} is not a subdirectory of {} - {} не ÑвлÑетÑÑ Ð¿Ð¾Ð´ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼ {} - - - - Select the subdirectory for this content item - Выберите подкаталог Ð´Ð»Ñ Ñтого Ñлемента Ñодержимого - - - - Automatic - ÐвтоматичеÑки - - - - - Workbench - ВерÑтак - - - - Addon - Дополнение - - - - Python - Python - - - - Yes - Да - - - - Internal Workbench - Внутренний верÑтак - - - - External Addon - Внешнее дополнение - - - - Python Package - Пакет Python - - - - - Other... - Другое... - - - - Too many to list - Слишком много Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ - - - - - - - - - Missing Requirement - ОтÑутÑтвует завиÑимоÑть - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Дополнению '{}' необходима завиÑимоÑть '{}', ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½ÐµÐ´Ð¾Ñтупна в Ñтой копии FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Дополнению '{}' необходимы Ñледующие верÑтаки, недоÑтупные в Ñтой копии FreeCAD: - - - - Press OK to install anyway. - Ðажмите OK, чтобы вÑе равно уÑтановить. - - - - - Incompatible Python version - ÐеÑовмеÑÑ‚Ð¸Ð¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Это дополнение требует неуÑтановленные пакеты Python, которые не могут быть уÑтановлены автоматичеÑки. Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹ должны вручную уÑтановить Ñледующие пакеты Python: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Этому дополнению или его завиÑимоÑÑ‚Ñм необходим Python {}.{}, но уÑтановлен: {}.{}. УÑтановка отменена. - - - - Optional dependency on {} ignored because it is not in the allow-list - ÐеобÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ð²Ð¸ÑимоÑть {} пропущена, потому что её нет в белом ÑпиÑке - - - - - Installing dependencies - УÑтановка завиÑимоÑтей - - - - - Cannot execute Python - Ðевозможно запуÑтить Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Ðе удалоÑÑŒ автоматичеÑки найти иÑполнÑемый файл Python или путь к нему уÑтановлен неправильно. ПожалуйÑта, проверьте путь к Python в наÑтройках Менеджера дополнений. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - ЗавиÑимоÑти не могут быть уÑтановлены. Ð’ÑÑ‘ равно продолжить уÑтановку {}? - - - - - Cannot execute pip - Ðевозможно запуÑтить pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Ðе удалоÑÑŒ запуÑтить pip, возможно он отÑутÑтвует в уÑтановленном вами Python. УбедитеÑÑŒ, что в вашей ÑиÑтеме уÑтановлен pip, и повторите попытку. ÐÐµÑƒÐ´Ð°Ñ‡Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° была такаÑ: - - - - - Continue with installation of {} anyway? - Ð’ÑÑ‘ равно продолжить уÑтановку {}? - - - - - Package installation failed - УÑтановка пакета не удалаÑÑŒ - - - - See Report View for detailed failure log. - Подробный журнал ошибок Ñмотрите на панели отчетов. - - - - Installing Addon - УÑтановка Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - Installing FreeCAD Addon '{}' - УÑтановка Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ FreeCAD '{}' - - - - Cancelling - Отмена - - - - Cancelling installation of '{}' - Отмена уÑтановки '{}' - - - - {} was installed successfully - {0} уÑпешно уÑтановлен - - - - - Installation Failed - УÑтановка не удалаÑÑŒ - - - - Failed to install {} - Ðе удалоÑÑŒ уÑтановить {} - - - - - Create new toolbar - Создать новую панель инÑтрументов - - - - - A macro installed with the FreeCAD Addon Manager - МакроÑ, уÑтановленный менеджером дополнений FreeCAD - - - - - Run - Indicates a macro that can be 'run' - ЗапуÑтить - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Ðе удаётÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚ÑŒ данные Ñ GitHub: проверьте подключение к интернету и наÑтройки прокÑи и повторите попытку. - - - - XML failure while reading metadata from file {} - Ошибка XML при чтении метаданных из файла {} - - - - Invalid metadata in file {} - Ðекорректные метаданные в файле {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ПРЕДУПРЕЖДЕÐИЕ: Указанный в метаданных package.xml путь не ÑоответÑтвует полученной ветке. - - - - Name - Ðазвание - - - - Class - КлаÑÑ - - - - Description - ОпиÑание - - - - Subdirectory - Подкаталог - - - - Files - Файлы - - - - Select the folder containing your Addon - Выберите папку, Ñодержащую дополнение - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - ОтÑутÑтвует Vermin, Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚Ð¼ÐµÐ½ÑетÑÑ. - - - - Scanning Addon for Python version compatibility - Проверка Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð½Ð° ÑовмеÑтимоÑть Ñ Ð²ÐµÑ€Ñией Python - - - - Minimum Python Version Detected - Определена Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin автоматичеÑки определил необходимую верÑию как Python 3.{} - - - - Install Vermin? - УÑтановить Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Ð”Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð¾Ð¹ верÑии Python требуетÑÑ Vermin (https://pypi.org/project/vermin/). УÑтановить? - - - - Attempting to install Vermin from PyPi - УÑтановка Vermin из PyPi - - - - - Installation failed - УÑтановка не удалаÑÑŒ - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Ðе удалоÑÑŒ уÑтановить Vermin ― подробноÑти Ñмотрите в панели отчётов. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Ðе удалоÑÑŒ импортировать Vermin поÑле уÑтановки ― невозможно Ñканировать дополнение. - - - - Select an icon file for this package - Выберите файл иконки Ð´Ð»Ñ Ñтого пакета - - - - Filter is valid - Фильтр корректен - - - - Filter regular expression is invalid - Ðекорректное регулÑрное выражение фильтра - - - - Search... - ПоиÑк... - - - - Click for details about package {} - Ðажмите Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей о пакете {} - - - - Click for details about workbench {} - Ðажмите Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей о верÑтаке {} - - - - Click for details about macro {} - Ðажмите Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей о макроÑе {} - - - - Maintainers: - ПоÑтавщики ПО: - - - - Tags - Теги - - - - {} ★ on GitHub - {} ★ на GitHub - - - - No ★, or not on GitHub - Ðет ★ или не на GitHub - - - - Created - Создано - - - - Updated - Обновлено - - - - Score: - Оценка: - - - - - Up-to-date - ÐÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - - - - - Update available - ДоÑтупно обновление - - - - - Pending restart - ОжидаетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк - - - - - DISABLED - ОТКЛЮЧЕÐО - - - - Installed version - УÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - Unknown version - ÐеизвеÑÑ‚Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - Installed on - УÑтановлено - - - - Available version - ДоÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ - - - - Filter by... - Фильтр по... - - - - Addon Type - Тип Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ - - - - - Any - Любое - - - - Macro - ÐœÐ°ÐºÑ€Ð¾Ñ - - - - Preference Pack - Пакет наÑтроек - - - - Installation Status - Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑƒÑтановки - - - - Not installed - Ðе уÑтановлено - - - - Filter - Фильтр - - - - DANGER: Developer feature - ОПÐСÐО: Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ° - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - ОПÐСÐО: Переключение веток предназначено Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² и бета-теÑтеров и может привеÑти к повреждению, неÑовмеÑтимоÑти Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð¸Ð¼Ð¸ верÑиÑми документов, неÑтабильноÑти, ÑбоÑм и/или преждевременной гибели вÑеленной. Ð’Ñ‹ уверены, что хотите продолжить? - - - - There are local changes - ИмеютÑÑ Ð½ÐµÑохраненные локальные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ПРЕДУПРЕЖДЕÐИЕ: Ð’ Ñтом репозитории еÑть незафикÑированные локальные изменениÑ. Ð’Ñ‹ уверены, что хотите заменить ветки (что приведёт к изменениÑм у ВаÑ)? - - - - Local - Table header for local git ref name - Локально - - - - Remote tracking - Table header for git remote tracking branch name - Удаленное отÑлеживание - - - - Last Updated - Table header for git update date - ПоÑледнее обновление - - - - Installation of Python package {} failed - Ðе удалоÑÑŒ уÑтановить python пакет {} - - - - Installation of optional package failed - Ðе удалоÑÑŒ уÑтановить необÑзательный пакет - - - - Installing required dependency {} - УÑтановка требуемой завиÑимоÑти {} - - - - Installation of Addon {} failed - Ðе удалоÑÑŒ уÑтановить дополнение {} - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Ðе удалоÑÑŒ декодировать файл {} Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ '{}' - - - - Any dependency information in this file will be ignored - Ð›ÑŽÐ±Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ завиÑимоÑÑ‚ÑÑ… в Ñтом файле будет игнорироватьÑÑ - - - - Unable to open macro wiki page at {} - Ðевозможно открыть Ñтраницу о макроÑе в вики {} - - - - Unable to fetch the code of this macro. - Ðе удаётÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ код макроÑа. - - - - Unable to retrieve a description from the wiki for macro {} - Ðе удаётÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ опиÑание макроÑа {} Ñ Ð²Ð¸ÐºÐ¸ - - - - Unable to open macro code URL {} - Ðе удаётÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ URL {} кода макроÑа - - - - Unable to fetch macro-specified file {} from {} - Ðе удалоÑÑŒ загрузить файл {}, необходимый Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа из {} - - - - Could not locate macro-specified file {} (expected at {}) - Ðе удалоÑÑŒ найти необходимый Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа файл {} (ожидалÑÑ Ð² {}) - - - - {}: Unrecognized internal workbench '{}' - {}: ÐераÑпознанный внутренний верÑтак '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Предупреждение разработчика ДополнениÑ: URL-Ð°Ð´Ñ€ÐµÑ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ, заданный в файле package.xml Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ {} ({}), не ÑоответÑтвует URL-адреÑу, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ он был получен ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Предупреждение разработчика ДополнениÑ: ветка репозиториÑ, ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð² файле package.xml Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ {} ({}), не ÑоответÑтвует ветке, из которой оно было получено ({}) - - - - - Got an error when trying to import {} - Произошла ошибка при попытке импортировать {} - - - - An unknown error occurred - Произошла неизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° - - - - Could not find addon {} to remove it. - Ðе удалоÑÑŒ найти дополнение {}, чтобы удалить его. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Выполнение Ñкрипта uninstall.py из Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð½Ðµ удалоÑÑŒ. Продолжение удалениÑ... - - - - Removed extra installed file {} - Удален дополнительно уÑтановленный файл {} - - - - Error while trying to remove extra installed file {} - Ошибка при попытке удалить дополнительно уÑтановленный файл {} - - - - Error while trying to remove macro file {}: - Ошибка при попытке удалить файл макроÑа {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Ðе удалоÑÑŒ подключитьÑÑ Ðº GitHub. Проверьте подключение и наÑтройки прокÑи. - - - - WARNING: Duplicate addon {} ignored - Ð’ÐИМÐÐИЕ: ПовторÑющееÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ðµ {} игнорируетÑÑ - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Произошла ошибка при обновлении макроÑов Ñ GitHub, попытка очиÑтить недоуÑтановленную верÑию... - - - - Attempting to do a clean checkout... - Попытка очиÑтки недоуÑтановленной верÑии... - - - - Clean checkout succeeded - ÐедоуÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ ÑƒÑпешно удалена - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Ðе удалоÑÑŒ обновить Ð¼Ð°ÐºÑ€Ð¾Ñ Ñ GitHub ― попробуйте очиÑтить кÑш менеджера дополнений. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Ошибка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Wiki, FreeCAD не может получить ÑпиÑок Вики по макроÑам в данное Ð²Ñ€ÐµÐ¼Ñ - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Ðе удалоÑÑŒ прочитать метаданные из {name} - - - - Failed to fetch code for macro '{name}' - Ðе удалоÑÑŒ получить код Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Менеджер дополнений: рабочему процеÑÑу не удалоÑÑŒ загрузить {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - При обработке {num_macros} макроÑ(ов/а), у {num_failed} иÑтекло Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ - - - - Addon Manager: a worker process failed to halt ({name}) - Менеджер дополнений: рабочий процеÑÑ ({name}) не удалоÑÑŒ оÑтановить - - - - Timeout while fetching metadata for macro {} - Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð¸Ñтекло при получении метаданных Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа {} - - - - Failed to kill process for macro {}! - - Ðе удалоÑÑŒ завершить процеÑÑ Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Ðе удалоÑÑŒ получить ÑтатиÑтику Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸Ð· {}. Корректно будет работать только Ñортировка по алфавиту - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Ðе удалоÑÑŒ получить оценку Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸Ð· '{}' - Ñортировка по оценкам не будет работать - - - - - Repository URL - Preferences header for custom repositories - URL Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ - - - - Branch name - Preferences header for custom repositories - Ðазвание ветки - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - ДелаетÑÑ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð¸Ñходного каталога и обновлÑетÑÑ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾ - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Переименование ветки Git не удалоÑÑŒ Ñо Ñледующим Ñообщением: - - - - Installing - УÑтановка - - - - Succeeded - УÑпешно - - - - Failed - Ðе удалоÑÑŒ - - - - Update was cancelled - Обновление было отменено - - - - some addons may have been updated - некоторые Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ обновлены - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Загрузка информации о {} из Ñтраницы вики рецептов макроÑов FreeCAD... - - - - Loading page for {} from {}... - Загрузка Ñтраницы о {} из {}... - - - - Failed to download data from {} -- received response code {}. - Ðе удалоÑÑŒ загрузить данные из {} -- получен код ответа {}. - - - - Composite view - СоÑтавной вид - - - - Expanded view - РаÑширенный вид - - - - Compact view - Компактный вид - - - - Alphabetical - Sort order - Ð’ алфавитном порÑдке - - - - Last Updated - Sort order - ПоÑледнее обновление - - - - Date Created - Sort order - Дата ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ - - - - GitHub Stars - Sort order - GitHub звёзды - - - - Score - Sort order - Оценка - - - - Std_AddonMgr - - - &Addon manager - &Менеджер дополнений - - - - Manage external workbenches, macros, and preference packs - Управление внешними верÑтаками, макроÑами и пакетами наÑтроек - - - - AddonInstaller - - - Finished removing {} - Завершено удаление {} - - - - Failed to remove some files - Ðе удалоÑÑŒ удалить некоторые файлы - - - - Addons installer - - - Finished updating the following addons - Завершено обновление Ñледующих дополнений - - - - Workbench - - - Auto-Created Macro Toolbar - ÐвтоматичеÑки ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ инÑтрументов Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа - - - - QObject - - - Addon Manager - Менеджер дополнений - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sk.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_sk.qm deleted file mode 100644 index 8f1391d90ed48629fac762552bb81bb9f261e399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29800 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sk.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_sk.ts deleted file mode 100644 index 263a67601c..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_sk.ts +++ /dev/null @@ -1,1168 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Custom repository - - - - Repository URL - Repository URL - - - - Branch - Branch - - - - CompactView - - - Form - Forma - - - - Icon - Ikona - - - - <b>Package Name</b> - <b>Package Name</b> - - - - Version - Verzia - - - - Description - Popis - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - Dependencies - - - - Dependency type - Dependency type - - - - Name - Názov - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Popis - - - - Discussion URL - Discussion URL - - - - Icon - Ikona - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Repository URL - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Verzia - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Správca doplnkov - - - - Downloading info... - Preberajú sa informácie... - - - - Pause cache update - Pause cache update - - - - Refresh local cache - Refresh local cache - - - - Download and apply all available updates - Preberie a aplikuje vÅ¡etky dostupné aktualizácie - - - - Update all Addons - Update all Addons - - - - Check for updates - Check for updates - - - - View and update Python package dependencies - View and update Python package dependencies - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Close the Addon Manager - Zavrie správcu doplnkov - - - - Close - ZavrieÅ¥ - - - - Welcome to the Addon Manager - Welcome to the Addon Manager - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Download Settings - Download Settings - - - - Automatically check installed Addons for updates - Automatically check installed Addons for updates - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - No proxy - Bez proxy - - - - System proxy - System proxy - - - - User-defined proxy: - User-defined proxy: - - - - These and other settings are available in the FreeCAD Preferences window. - These and other settings are available in the FreeCAD Preferences window. - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - Form - Forma - - - - Icon - Ikona - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - Version - Verzia - - - - (tags) - (tags) - - - - Description - Popis - - - - Maintainer - Správca - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - - Form - Forma - - - - Licenses - Licenses - - - - License - Licencia - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - Názov - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires git) - Automatically check for updates at start (requires git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - - Addons - Addons - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manual (no automatic updates) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Show option to change branches (requires git) - Show option to change branches (requires git) - - - - Disable git (fall back to ZIP downloads only) - Disable git (fall back to ZIP downloads only) - - - - disableGit - disableGit - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - developerMode - developerMode - - - - Proxy - Proxy - - - - No proxy - Bez proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Python executable (optional): - Python executable (optional): - - - - The path to the Python executable for package installation with pip. Autodetected if needed and not specified. - The path to the Python executable for package installation with pip. Autodetected if needed and not specified. - - - - git executable (optional): - git executable (optional): - - - - The path to the git executable. Autodetected if needed and not specified. - The path to the git executable. Autodetected if needed and not specified. - - - - Advanced Options - Advanced Options - - - - PackageDetails - - - Form - Forma - - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - InÅ¡talovaÅ¥ - - - - Uninstall - OdinÅ¡talovaÅ¥ - - - - Update - AktualizovaÅ¥ - - - - Run Macro - SpustiÅ¥ makro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Dialógové okno - - - - TextLabel - Popisok - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Makro - - - - Preference Pack - Preference Pack - - - - Workbench - Pracovný priestor - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Ikona - - - - actualIcon - actualIcon - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Verzia - - - - Description - Popis - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch or tag: - Change to branch or tag: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Name: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sl.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_sl.qm deleted file mode 100644 index e90a8457e4e2f1973e98b6223bdbc8dcf1f49da8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68930 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

    Ve0rI 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sl.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_sl.ts deleted file mode 100644 index b3ae456359..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_sl.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - SkladiÅ¡Äe po meri - - - - Repository URL - Spletni naslov skladiÅ¡Äa - - - - Branch - Veja - - - - CompactView - - - - Icon - Ikona - - - - - <b>Package Name</b> - <b>Naziv paketa</b> - - - - - Version - RazliÄica - - - - - Description - Opis - - - - Update Available - Na voljo je nadgradnja - - - - UpdateAvailable - Posodobitev na voljo - - - - DependencyDialog - - - Dependencies - Odvisnosti - - - - Dependency type - Vrsta odvisnosti - - - - Name - Naziv - - - - Optional? - Neobvezno? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - RazreÅ¡i odvisnosti - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Ta Dodatek ima naslednje obvezne in neobvezne odvisnosti. Namestiti jih je potrebno pred uporabo Dodatka. - -Ali želite, da jih upravljalinik dodatkov namesti samodejno? Izberite "Prezri", Äe želite namestiti Dodatek brez, da bi namestili odvisnosti. - - - - FreeCAD Addons - FreeCADovi dodatki - - - - Required Python modules - Potrebni Pythonovi moduil - - - - Optional Python modules - Neobvezni Pythonovi moduli - - - - DeveloperModeDialog - - - Addon Developer Tools - Orodja za razvijalce dodatkov - - - - Path to Addon - Pot do dodatka - - - - - Browse... - Prebrskaj ... - - - - Metadata - Samopodatki - - - - Primary branch - Glavna veja - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Kaj ta dodatek ponuja je prikazano v Upravljalniku dodatkov. Ni nujno, da je tam navedeno ali je to FreeCADov dodatek. - - - - Description - Opis - - - - Discussion URL - Spletni naslov razprave - - - - Icon - Ikona - - - - Bugtracker URL - Spletni naslov do sledilnika hroÅ¡Äev - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Podprta sta Semantic (1.2.3.-beta) ali CalVer (2022.08.30) sloga - - - - Set to today (CalVer style) - Nastavi na danes (slog CalVer) - - - - - - - (Optional) - (Neobvezno) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Prikazano v seznamu dodatkov iz Upravljalnika dodatkov. Ne sme vsebovati besede "FreeCAD" in mora biti veljavno ime mape v vseh podprtih operacijskih sistemih. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - Nasvet: Ker je to prikazano v upravljalniku dodatko znotraj FreeCADa, ni treba tratiti prostora z opisi, kot npr. "To je FreeCADov dodatek ..." -- povejte le, kaj dela. - - - - Repository URL - Spletni naslov skladiÅ¡Äa - - - - Website URL - Naslov spletne strani - - - - Documentation URL - Spletni naslov dokumentacije - - - - Addon Name - Ime dodatka - - - - Version - RazliÄica - - - - (Recommended) - (PriporoÄljivo) - - - - Minimum Python - Najmanj Python - - - - (Optional, only 3.x version supported) - (Izbirno, podprta le razliÄica 3.x) - - - - Detect... - Zaznaj... - - - - Addon Contents - Vsebina dodatka - - - - Dialog - - - Addon Manager - Upravljalnik dodatkov - - - - Edit Tags - Uredi znaÄke - - - - Comma-separated list of tags describing this item: - Z vejico loÄen seznam znaÄk, ki opisujejo ta predmet: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - Namig: ObiÄajne oznake vkljuÄujejo "Assembly", "FEM", "Mesh", "NURBS" itd. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Nadaljuj - - - - Cancel - PrekliÄi - - - - EditDependencyDialog - - - Edit Dependency - Uredi odvisnosti - - - - Dependency Type - Vrsta odvisnosti - - - - Dependency - Odvisnost - - - - Package name, if "Other..." - Ime paketa, Äe "Drugo ..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - OPOMB: ÄŒe je izbrano "Drugo ...", paketa ni v datoteki ALLOWED_PYTHON_PACKAGES.txt in ga bo upravljalnik vtiÄnikov samodejno namestil. ÄŒe želite zaprosti za dodajanje paketa, oddajte predobjavo na <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a>. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - To je neobvezna odvisnost, ki jo bo upravljalnik dodatkov ponudil namestiti, (ko je to mogoÄe) vendar ne bo onemogoÄil namestitve, Äe uporabnik ne bo želel ali mogel namestiti paketa. - - - - Optional - Neobvezno - - - - ExpandedView - - - - Icon - Ikona - - - - - <h1>Package Name</h1> - <h1>Naziv paketa</h1> - - - - - Version - RazliÄica - - - - - (tags) - (znaÄke) - - - - - Description - Opis - - - - - Maintainer - Vzdrževalec - - - - Update Available - Na voljo je nadgradnja - - - - labelSort - labelSort - - - - UpdateAvailable - Posodobitev na voljo - - - - Form - - - Licenses - Licence - - - - License - Dovoljenje - - - - License file - Datoteka z licenco - - - - People - Osebe - - - - Kind - Vrsta - - - - Name - Ime - - - - Email - E-poÅ¡ta - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Preslikava napredne razliÄice - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - PrihajajoÄe razliÄice FreeCADovega upravljalnika dodatkov bodo podpirale razvijalce z nastavitvijo doloÄene veje ali znaÄke za delo s toÄno doloÄeno razliÄico FreeCADa (npr. nastavitev posebne znaÄke, da zadnja razliÄica vaÅ¡ega vtiÄnika podpira v0.19 itn.) - - - - FreeCAD Version - RezliÄica FreeCADa - - - - Best-available branch, tag, or commit - NajprimernejÅ¡a razpoložljiva veja, znaÄka ali predaja - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Podprte FreeCAD razliÄice - - - - Minimum FreeCAD Version Supported - NajstarejÅ¡a Å¡e podprta razliÄica FreeCADa - - - - - Optional - Neobvezno - - - - Maximum FreeCAD Version Supported - NajnovejÅ¡a podprta razliÄica FreeCADa - - - - Advanced version mapping... - Preslikava napredne razliÄice ... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Nastavitve urejevalnika dodatkov - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Prenesi samopodatke o makrih (približno 10 MB) - - - - Cache update frequency - Pogostnost posodobitve predpomnilnika - - - - Manual (no automatic updates) - RoÄno (brez samodejnih posodobitev) - - - - Daily - Dnevno - - - - Weekly - Tedensko - - - - Hide Addons without a license - Skrij dodatke brez dovoljenja - - - - Hide Addons with non-FSF Free/Libre license - Skrij dodatke brez Libre dovoljenja organizacije FSF - - - - Hide Addons with non-OSI-approved license - Skrij dodatke brez dovoljenja Odprtokodne pobude (OSI) - - - - Hide Addons marked Python 2 Only - Skrij dodatke z oznako Le Python 2 - - - - Hide Addons marked Obsolete - Skrij dodatke z oznako Zastarelo - - - - Hide Addons that require a newer version of FreeCAD - Skrij dodatke, ki zahtevajo novejÅ¡o razliÄico FreeCADa - - - - Custom repositories - SkladiÅ¡Äa po meri - - - - Proxy - PosredniÅ¡ki strežnik - - - - No proxy - Ni posredniÅ¡kega strežnika - - - - User system proxy - PosredniÅ¡ki strežnik uporabniÅ¡kega okolja - - - - User-defined proxy: - PosredniÅ¡ki strežnik, ki ga doloÄi uporabnik: - - - - Score source URL - Vrednoten spletni naslov vira - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Spletni naslov podatkov o toÄkovanju dodatka (veÄ o oblikovanju in gostovanju si poglejte na vikistani Upravljalnik dodatkov - Addon Manager). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Napredne možnosti - - - - Activate Addon Manager options intended for developers of new Addons. - OmogoÄi možnosti upravljalnika dodatkov, ki so namenjene razvijalcem novih dodatkov. - - - - Addon developer mode - Razvijalski naÄin dodatkov - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Odmesti izbrani makro ali delovno okolje - - - - Install - Namesti - - - - Uninstall - Odmesti - - - - Update - Posodobitev - - - - Run Macro - Zaženi makro - - - - Change branch - Spremeni vejo - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Upravljaj Pythonove odvisnosti - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Upravljalnik dodatkov je za zadostitev odvisnosti vtiÄnika krajevno namestil naslednje Pythonove pakete. Mesto namestitve: - - - - Package name - Ime paketa - - - - Installed version - NameÅ¡Äena razliÄica - - - - Available version - Razpoložljiva razliÄica - - - - Used by - Uporablja - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Zvezdica (*) v stolpcu "Uporablja" pomeni neobvezno odvisnost. Pozor, seznam "Uporablja" navaja neposredne uvoze v dodatke. Možno je, da so nameÅ¡Äeni tudi drugi Pythonovi paketi, ki so od teh paketov odvisni. - - - - Update all available - Posodobi vse razpoložljive - - - - SelectFromList - - - Dialog - Pogovorno okno - - - - TextLabel - Besedilna oznaka - - - - UpdateAllDialog - - - Updating Addons - Posodabljanje dodatkov - - - - Updating out-of-date addons... - Posodabljanje zastarelih dodatkov ... - - - - addContentDialog - - - Content Item - Predmeti vsebine - - - - Content type: - Vrsta vsebine: - - - - Macro - Makro - - - - Preference Pack - Prednastavitveni sveženj - - - - Workbench - Delovno okolje - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - ÄŒe je to edina stvar v dodatku, se lahko vsi ostali samopodatki prenesejo z viÅ¡je ravni in jih ni treba posebej navajati. - - - - This is the only item in the Addon - To je edni predmet v dodatku - - - - Main macro file - Glavna datoteka makra - - - - The file with the macro's metadata in it - Datoteka z makrovimi samopodatki - - - - - - Browse... - Prebrskaj ... - - - - Preference Pack Name - Ime prednastavitvenega svežnja - - - - Workbench class name - Ime razreda delovnega okolja - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Podmapa - - - - Optional, defaults to name of content item - Po meri, privzeto na ime vsebovanega predmeta - - - - Icon - Ikona - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - ZnaÄke... - - - - Dependencies... - Odvisnosti ... - - - - FreeCAD Versions... - RezliÄica FreeCADa ... - - - - Other Metadata - Drugi sampodatki - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Prikazano v upravljalnikovem seznamu dodatkov. Ne sme vsebovati besede "FreeCAD". - - - - Version - RazliÄica - - - - Description - Opis - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Podprta sta sloga Semantic (1.2.3.-beta) ali CalVer (2022.08.30) - - - - Set to today (CalVer style) - Nastavi na danes (slog CalVer) - - - - Display Name - Prikazano ime - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Vsa polja, ki jih pustite prazna, prevzamejo vsebino nadrejenih samopodatkov Dodatka, zato bi lahko rekli, da so neobvezna. Pri Dodatkih z veÄimi vsebinskimi predmeti mora vsak tak predmet omogoÄati edinstveno ime in opis. - - - - add_toolbar_button_dialog - - - Add button? - Želite dodati gumb? - - - - Add a toolbar button for this macro? - Želite dodati gumb tega makra v orodno vrstico? - - - - Yes - Da - - - - No - Ne - - - - Never - Nikoli - - - - change_branch - - - Change Branch - Spremeni vejo - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Podatki o avtorskih pravicah - - - - Copyright holder: - Imetnik avtorskih pravic: - - - - Copyright year: - Leto avtorskih pravic: - - - - personDialog - - - Add Person - Dodaj osebo - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Vzdrževalec je tisti, ki ima odobren dostop do projekta. Ustvarjalec pa je vsak, ki mu želite priznati zasluge. - - - - Name: - Ime: - - - - Email: - E-poÅ¡ta: - - - - Email is required for maintainers, and optional for authors. - EpoÅ¡ta je za vzdrževalce zahtevana, za stvaritelje pa neobvezna. - - - - proxy_authentication - - - Proxy login required - Potreben vpis v posredniÅ¡ki strežnik - - - - Proxy requires authentication - PosredniÅ¡ki strežnik zahteva overitev - - - - Proxy: - PosredniÅ¡ki strežnik: - - - - Placeholder for proxy address - Prostornik naslova posredniÅ¡kega strežnika - - - - Realm: - PodroÄje: - - - - Placeholder for proxy realm - Prostornik podroÄja posredniÅ¡kega strežnika - - - - Username - UporabniÅ¡ko ime - - - - Password - Geslo - - - - selectLicenseDialog - - - Select a license - Izberi licenco - - - - About... - O programu ... - - - - License name: - Ime licence: - - - - Path to license file: - Pot do datoteke z licenco: - - - - (if required by license) - (Äe je zahtevano po licenci) - - - - Browse... - Prebrskaj ... - - - - Create... - Ustvari... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Izberite orodno vrstico - - - - Select a toolbar to add this macro to: - Izberite orodno vrstico, v katero želite vstaviti ta makro: - - - - Ask every time - Vedno vpraÅ¡aj - - - - toolbar_button - - - - Add button? - Želite dodati gumb? - - - - Add a toolbar button for this macro? - Želite dodati gumb tega makra v orodno vrstico? - - - - Yes - Da - - - - No - Ne - - - - Never - Nikoli - - - - AddonsInstaller - - - Starting up... - PriÄenjanje ... - - - - Worker process {} is taking a long time to stop... - Delovni proces {} se predolgo zaustavlja ... - - - - Previous cache process was interrupted, restarting... - - Predhodno predpomnenje je bilo prekinjeno, ponovni zagon ... - - - - - Custom repo list changed, forcing recache... - - SkladiÅ¡Äni seznam po meri se je spremenil, prisilno ponovno predpomnenje ... - - - - - Addon manager - Upravljalnik dodatkov - - - - You must restart FreeCAD for changes to take effect. - Da bi spremembe stopile v veljavo, morate ponovno zagnati FreeCAD. - - - - Restart now - TakojÅ¡nji pozagon - - - - Restart later - Pozaženi pozneje - - - - - Refresh local cache - Osveži krajevni predpomnilnik - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Posodabljanje predpomnilnika ... - - - - - Checking for updates... - Preverjanje za posodobitve … - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Zapri - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Novega namestilnika ni mogoÄe zagnati, dokler se prejÅ¡nji ne konÄa. - - - - - - - Maintainer - Vzdrževalec - - - - - - - Author - Ustvarjalec - - - - New Python Version Detected - Zaznana je nova Pythonova razliÄica - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Kaže, da je tokrat ta razliÄica Pythona prviÄ uporabljena z Upravljalnikom dodatkov (Addon Manager). Ali želite zanjo samodejno namestiti enako odvisnost? - - - - Processing, please wait... - V obdelavi, prosimo, poÄakajte ... - - - - - Update - Posodobi - - - - Updating... - Posodabljanje ... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - QtNetwork-a ni mogoÄe uvoziti - kaže, da ni nameÅ¡Äen na vaÅ¡em sistemu. Morda ima vaÅ¡ ponudnik paket za to odvisnost (pogosto imenovan "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Pretvarjanje izbranih vrat posredniÅ¡kega strežnika '{}' v Å¡tevilko vrat je spodletela - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Napaka doloÄilke: nastavljene medsebojno izkljuÄujeÄe možnosti posredniÅ¡kega strežnika. Ponastavljanje na privzeto. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Napaka doloÄilke: posredniÅ¡ki strežnik nakazan, vendar ni na voljo. Ponastavljanje na privzeto. - - - - Addon Manager: Unexpected {} response from server - Upravljalnik dodatkov: NepriÄakovan {} odziv strežnika - - - - Error with encrypted connection - Napaka kodirane povezave - - - - - - Confirm remove - Potrdi odstranitev - - - - Are you sure you want to uninstall {}? - Ali res želite odmestiti {}? - - - - - - Removing Addon - OdmeÅ¡Äanje dodatka - - - - Removing {} - OdmeÅ¡Äa se {} - - - - - Uninstall complete - Odmestitev zakljuÄena - - - - - Uninstall failed - Odmestitev spodletela - - - - Version {version} installed on {date} - RazliÄica {version} nameÅ¡Äena {date} - - - - Version {version} installed - RazliÄica {version} nameÅ¡Äena - - - - Installed on {date} - NameÅ¡Äeno {date} - - - - - - - Installed - NameÅ¡Äeno - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installation location - - - - Repository URL - Spletni naslov skladiÅ¡Äa - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Disabled - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Install - Namesti - - - - Uninstall - Odmesti - - - - Enable - OmogoÄi - - - - Disable - OnemogoÄi - - - - - Check for update - Check for update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Zaženi (postopek), - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Samodejno - - - - - Workbench - Delovno okolje - - - - Addon - Dodatek - - - - Python - Python - - - - Yes - Da - - - - Internal Workbench - Notranje delovno okolje - - - - External Addon - Zunanji dodatek - - - - Python Package - Pythonov paket - - - - - Other... - Drugo ... - - - - Too many to list - PreveÄ za navedbo - - - - - - - - - Missing Requirement - Neizpolnjen pogoj - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Dodatek '{}' potrebuje '{}', ki za vaÅ¡o razliÄico FreeCADa ni na voljo. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Dodatek '{}' potrebuje naslednja delovna okolja, ki pa za vaÅ¡o razliÄico FreeCADa niso na voljo: - - - - Press OK to install anyway. - Pritisnite V redu, Äe želite vseeno namestiti. - - - - - Incompatible Python version - Nezdružljiva razliÄica Pythona - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Neobvezna odvisnost od {} prezrta, saj ni na seznamu dopustnih - - - - - Installing dependencies - NameÅ¡Äanje odvisnosti - - - - - Cannot execute Python - Pythona ni mogoÄe izvesti - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Pythonove izvrÅ¡ljive datoteke ni mogoÄe samodejno najti ali pa je pot napaÄno nastavljena. Preverite pot do Pythona v prednastavitvah Upravljalnika dodatkov. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Odvisnosti ni bilo mogoÄe namestiti. Ali želite vseeno nadaljevati z namestitvijo {}? - - - - - Cannot execute pip - Slike v sliki ni mogoÄe izvesti - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Ali želite vseeno nadaljevati z namestitvijo {}? - - - - - Package installation failed - Namestitev paketa spodletela - - - - See Report View for detailed failure log. - Za podrobnejÅ¡i zapisnik o napaki poglejte PoroÄevalni pogled. - - - - Installing Addon - NameÅ¡Äanje dodatka - - - - Installing FreeCAD Addon '{}' - NameÅ¡Äanje FreeCADovega dodatka '{}' - - - - Cancelling - Preklic - - - - Cancelling installation of '{}' - Preklicevanje nameÅ¡Äanja '{}' - - - - {} was installed successfully - {} je bil uspeÅ¡no nameÅ¡Äen - - - - - Installation Failed - Namestitev spodletela - - - - Failed to install {} - Spodletelo nameÅ¡Äanje {} - - - - - Create new toolbar - Ustvari novo orodno vrstico - - - - - A macro installed with the FreeCAD Addon Manager - Makro nameÅ¡Äen s FreeCAD-ovim Upravljalnikom dodatkov - - - - - Run - Indicates a macro that can be 'run' - Zaženi - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Podatkov na GitHubu ni mogoÄe brati: preverite spletno povezavo in nastavitve posredniÅ¡kega strežnika ter poskusite ponovno. - - - - XML failure while reading metadata from file {} - XML napaka pri branju samopodatkov iz datoteke {} - - - - Invalid metadata in file {} - Neveljavni samopodatki v datoteki {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - OPOZORILO: Pot, doloÄena v samopodatkih package.xml, se ne sklada s trenutno prevzeto vejo. - - - - Name - Naziv - - - - Class - Razred - - - - Description - Opis - - - - Subdirectory - Podmapa - - - - Files - Datoteke - - - - Select the folder containing your Addon - Izberite mapo z vaÅ¡im dodatkom - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Brez Vermina, prekinitev dejanja. - - - - Scanning Addon for Python version compatibility - Pregledovanje združljivosti dodatka s Pythonovo razliÄico - - - - Minimum Python Version Detected - Zaznana je minimalna Pythonova razliÄica - - - - Vermin auto-detected a required version of Python 3.{} - Vermin je samodejno zaznal zahtevano razliÄico Pythona 3.{} - - - - Install Vermin? - Želite namestiti Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Samodejno zaznavanje potrebne razliÄice Pythona javlja, da je za ta dodatek potreben Vermin (https://pypi.org/project/vermin/). Dovolite namestitev? - - - - Attempting to install Vermin from PyPi - Poskus namestitve Vermina s PyPi - - - - - Installation failed - NameÅ¡Äanje spodletelo - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Iskanje ... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - ZnaÄke - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - NameÅ¡Äena razliÄica - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Razpoložljiva razliÄica - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Po želji - - - - Macro - Makro - - - - Preference Pack - Prednastavitveni sveženj - - - - Installation Status - Installation Status - - - - Not installed - Not installed - - - - Filter - Sito - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Ni mogoÄe odpreti vikistrani z makri na naslovu {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Upravljalnik dodatkov: delovni proces je med pridobivanjem {name} spodletel - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Upravljalnik dodatkov: delovni proces se ni mogel zaustaviti ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Spletni naslov skladiÅ¡Äa - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Posodobitev je bila preklicana - - - - some addons may have been updated - nekateri dodatki so bili lahko posodobljeni - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Upravljalnik dodatkov - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sr-CS.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_sr-CS.qm deleted file mode 100644 index c241a077609e6584b7fe03de6ee046576ae96bee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70115 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 - - - - AddCustomRepositoryDialog - - - Custom repository - Sopstveno spremiÅ¡te - - - - Repository URL - URL adresa spremiÅ¡ta - - - - Branch - Grana - - - - CompactView - - - - Icon - Ikona - - - - - <b>Package Name</b> - <b>Ime paketa</b> - - - - - Version - Verzija - - - - - Description - Opis - - - - Update Available - Dostupno jе ažuriranjе - - - - UpdateAvailable - Na raspolaganju je novija verzija - - - - DependencyDialog - - - Dependencies - Zavisnosti - - - - Dependency type - Vrsta zavisnosti - - - - Name - Ime - - - - Optional? - Neobavezno? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - ReÅ¡i zavisnosti - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Ovaj Dodatak ima sledeće obavezne i neobavezne zavisnosti. MoraÅ¡ ih instalirati da bi mogao da koristiÅ¡ ovaj Dodatak. - -Da li želiÅ¡ da ih Menadžer dodataka automatski instalira? Izaberi "Zanemari" da instaliraÅ¡ dodatak bez instaliranja zavisnosti. - - - - FreeCAD Addons - FreeCAD Dodaci - - - - Required Python modules - Potrebni Python moduli - - - - Optional Python modules - Neobavezni Python moduli - - - - DeveloperModeDialog - - - Addon Developer Tools - Alatke za programere dodataka - - - - Path to Addon - Putanja do Dodatka - - - - - Browse... - Potraži... - - - - Metadata - Metapodaci - - - - Primary branch - Glavna grana - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - ObjaÅ¡njenje Å¡ta ovaj Dodatak pruža. Prikazuje se u Menadžeru dodataka. Nije neophodno da se navodi da je ovo dodatak za FreeCAD. - - - - Description - Opis - - - - Discussion URL - URL adresa diskusije - - - - Icon - Ikona - - - - Bugtracker URL - URL adresa sistema za praćenje greÅ¡aka - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Podržani su Semantic (1.2.3-beta) ili CalVer (2022.08.30) stilovi - - - - Set to today (CalVer style) - Postavljeno na danas (CalVer stil) - - - - - - - (Optional) - (neobavezno) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Prikazuje se na listi Menadžera dodataka. Ne bi trebalo da sadrži reÄ "FreeCAD" i mora postojati važeće ime fascikle za sve podržane operativne sisteme. - - - - README URL - URL adresa datoteke README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - SAVET: PoÅ¡to je ovo prikazano u Menadžeru dodataka FreeCAD programa, nije neophodno da zauzimaÅ¡ prostor govoreći stvari poput "Ovo je FreeCAD dodatak..." -- samo reci Å¡ta radi. - - - - Repository URL - URL adresa spremiÅ¡ta - - - - Website URL - URL adresa veb sajta - - - - Documentation URL - URL adresa dokumentacije - - - - Addon Name - Ime dodatka - - - - Version - Verzija - - - - (Recommended) - (PreporuÄeno) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Neobavezno, podržana je samo verzija 3.x) - - - - Detect... - Otkrij... - - - - Addon Contents - Sadržaj dodatka - - - - Dialog - - - Addon Manager - Menadžer dodataka - - - - Edit Tags - Uredi tagove - - - - Comma-separated list of tags describing this item: - Lista tagova razdvojenih zarezima koje opisuju ovu stavku: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - SAVET: UobiÄajeni tagovi ukljuÄuju "Sklop", "FEM", "Mreža", "NURBS", etc. - - - - Add-on Manager: Warning! - Menadžer dodataka: Upozorenje! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Menadžer dodataka pruža pristup biblioteci korisnih FreeCAD dodataka nezavisnih proizvoÄ‘aÄa. Dodatke koristite na svoju odgovornost poÅ¡to FreeCAD ne može garantovati za njihovu bezbednosti ili funkcionalnosti. - - - - Continue - Nastavi - - - - Cancel - Otkaži - - - - EditDependencyDialog - - - Edit Dependency - Uredi zavisnost - - - - Dependency Type - Vrsta zavisnosti - - - - Dependency - Zavisnost - - - - Package name, if "Other..." - Ime paketa, ako je "Ostalo..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NAPOMENA: Ako je "Ostalo..." izabran, paket se ne nalazi u datoteci ALLOVED_PYTHON_PACKAGES.txt i Menadžer dodataka ga neće automatski instalirati. PoÅ¡alji PR na <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> da zatraži dodavanje paketa. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Ako je ovo neobavezna zavisnost, Menadžer dodataka će ponuditi da je instalira (kada je to moguće), ali neće blokirati instalaciju ako korisnik odluÄi da ne instalira ili ne može da instalira paket. - - - - Optional - Neobavezno - - - - ExpandedView - - - - Icon - Ikona - - - - - <h1>Package Name</h1> - <h1>Ime paketa</h1> - - - - - Version - Verzija - - - - - (tags) - (tagovi) - - - - - Description - Opis - - - - - Maintainer - Programer zadužen za održavanje - - - - Update Available - Dostupno jе ažuriranjе - - - - labelSort - labelSort - - - - UpdateAvailable - Na raspolaganju je novija verzija - - - - Form - - - Licenses - Licence - - - - License - Licenca - - - - License file - Datoteka licence - - - - People - Osobe - - - - Kind - Vrsta - - - - Name - Ime - - - - Email - Elektronska poÅ¡ta - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Napredno mapiranje verzija - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Predstojeće verzije FreeCAD Menadžera dodataka će podržavati programersko podeÅ¡avanje odreÄ‘ene grane ili tagove za upotrebu sa odreÄ‘enom verzijom FreeCAD-a (npr. podeÅ¡avanje odreÄ‘enog tag-a kao poslednje verzije vaÅ¡eg Dodatka za podrÅ¡ku v0.19, itd.) - - - - FreeCAD Version - FreeCAD verzija - - - - Best-available branch, tag, or commit - Najbolja dostupna grana, tag ili commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Podržane FreeCAD verzije - - - - Minimum FreeCAD Version Supported - Minimalna podržana FreeCAD verzija - - - - - Optional - Neobavezno - - - - Maximum FreeCAD Version Supported - Maksimalna podržana FreeCAD verzija - - - - Advanced version mapping... - Napredno mapiranje verzija... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Opcije menadžera dodataka - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Ako je ova opcija izabrana, prilikom pokretanja Menadžera dodataka -će biti provereno da li postoje dostupna ažuriranja za instalirane dodatke - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Preuzmi makro metapodatke (približno 10MB) - - - - Cache update frequency - UÄestalost ažuriranja keÅ¡a - - - - Manual (no automatic updates) - RuÄno (bez automatskog ažuriranja) - - - - Daily - Dnevno - - - - Weekly - Nedeljno - - - - Hide Addons without a license - Sakrij dodatke bez licence - - - - Hide Addons with non-FSF Free/Libre license - Sakrij dodatke koji nemaju FSF Free/Libre licencu - - - - Hide Addons with non-OSI-approved license - Sakrij dodatke koji nemaju OSI odobrenu licencu - - - - Hide Addons marked Python 2 Only - Sakrij Dodatke sa oznakom "Samo Python 2" - - - - Hide Addons marked Obsolete - Sakrij Dodatke oznaÄene kao zastareli - - - - Hide Addons that require a newer version of FreeCAD - Sakrij Dodatke koji zahtevaju noviju verziju FreeCAD-a - - - - Custom repositories - Sopstveno spremiÅ¡te - - - - Proxy - Proksi - - - - No proxy - Bez proksi - - - - User system proxy - KorisniÄki sistemski proksi - - - - User-defined proxy: - KorisniÄki proksi: - - - - Score source URL - URL izvora ocena - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - URL za оцене додатка (za viÅ¡e detalja pogledaj wiki stranu Addon Manager). - - - - Path to Git executable (optional): - Staza ka izvrÅ¡noj git datoteci (Neobavezno): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Napredne opcije - - - - Activate Addon Manager options intended for developers of new Addons. - Aktiviraj opcije menadžera dodataka namenjene programerima novih dodataka. - - - - Addon developer mode - Režim programera dodataka - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Deinstaliraj izabrani makro ili radno okruženje - - - - Install - Instaliraj - - - - Uninstall - Deinstaliraj - - - - Update - Ažuriranje - - - - Run Macro - Pokreni makro - - - - Change branch - Promeni granu - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Upravljanje Python zavisnostima - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Sledeće Python pakete je lokalno instalirao Menadžer dodataka da bi zadovoljio zavisnosti dodataka. Lokacija instalacije: - - - - Package name - Ime paketa - - - - Installed version - Instalirana verzija - - - - Available version - Dostupna verzija - - - - Used by - Koristio - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Zvezdica t.j. asteriks (*) u polju "Koristio" kolone oznaÄava neobaveznu zavisnost. Imaj na umu da 'Koristio' samo beleži direktan uvoz u Dodatak. Možda su instalirani i drugi Python paketi od kojih ti paketi zavise. - - - - Update all available - Ažuriraj sve dostupno - - - - SelectFromList - - - Dialog - Dijalog - - - - TextLabel - Tekstualna oznaka - - - - UpdateAllDialog - - - Updating Addons - Ažuriranje Dodataka - - - - Updating out-of-date addons... - Ažuriranje zastarelih dodataka... - - - - addContentDialog - - - Content Item - Stavka sa sadržajem - - - - Content type: - Vrsta sadržaja: - - - - Macro - Makro - - - - Preference Pack - Paket podeÅ¡avanja - - - - Workbench - Radno okruženje - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Ako je ovo jedina stvar u Dodatku, svi ostali metapodaci mogu biti nasleÄ‘eni sa najviÅ¡eg nivoa i ne moraju se ovde navoditi. - - - - This is the only item in the Addon - Ovo je jedina stavka u Dodatku - - - - Main macro file - Glavna makro datoteka - - - - The file with the macro's metadata in it - Datoteka sa metapodacima makro-a u njoj - - - - - - Browse... - Potraži... - - - - Preference Pack Name - Ime paketa podeÅ¡avanja - - - - Workbench class name - Ime klase radnog okruženja - - - - Class that defines "Icon" data member - Klasa koja odreÄ‘uje podatak Älana "Icon" - - - - Subdirectory - Podfascikla - - - - Optional, defaults to name of content item - Opciono, podrazumevano je ime stavke sa sadržajem - - - - Icon - Ikona - - - - Optional, defaults to inheriting from top-level Addon - Opciono, podrazumevano nasleÄ‘ivanje od Dodatka najviÅ¡eg nivoa - - - - Tags... - Tagovi... - - - - Dependencies... - Zavisnosti... - - - - FreeCAD Versions... - FreeCAD verzija... - - - - Other Metadata - Ostali metapodaci - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Prikazuje se na listi Menadžera dodataka. Ne bi trebalo da sadrži reÄ "FreeCAD". - - - - Version - Verzija - - - - Description - Opis - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Podržani su Semantic (1.2.3-beta) ili CalVer (2022.08.30) stilovi - - - - Set to today (CalVer style) - Postavljeno na danas (CalVer stil) - - - - Display Name - Prikazano ime - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Sva polja ostavljena prazna su nasleÄ‘ena od metapodataka dodatka najviÅ¡eg nivoa, tako da tehniÄki, sva su neobavezna. Za dodatke sa viÅ¡e stavki sa sadržajem, svaka stavka treba da omogući jedinstveno ime i opis. - - - - add_toolbar_button_dialog - - - Add button? - Dodaj dugme? - - - - Add a toolbar button for this macro? - ŽeliÅ¡ li dodati dugme na paleti alatki za ovaj makro? - - - - Yes - Da - - - - No - Ne - - - - Never - Nikada - - - - change_branch - - - Change Branch - Promeni granu - - - - Change to branch: - Promeni granu: - - - - copyrightInformationDialog - - - Copyright Information - Informacije o autorskim pravima - - - - Copyright holder: - Nosilac autorskih prava: - - - - Copyright year: - Godina od kad važi autorsko pravo: - - - - personDialog - - - Add Person - Dodaj osobu - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Programer zadužen za održavanje je neko sa trenutnim pristupom ovom projektu. Autor je neko, kome možeÅ¡ da odaÅ¡ priznanje. - - - - Name: - Ime: - - - - Email: - E-poÅ¡ta: - - - - Email is required for maintainers, and optional for authors. - E-poÅ¡ta je neophodna za osobu odgovornu za održavanje, a neobavezno za autore. - - - - proxy_authentication - - - Proxy login required - Potrebna je prijava za proksi - - - - Proxy requires authentication - Proksi zahteva autentifikaciju - - - - Proxy: - Proksi: - - - - Placeholder for proxy address - Rezervisano mesto za proksi adresu - - - - Realm: - Oblast: - - - - Placeholder for proxy realm - Rezervisano mesto za proksi oblast - - - - Username - KorisniÄko ime - - - - Password - Lozinka - - - - selectLicenseDialog - - - Select a license - Izaberi licencu - - - - About... - O... - - - - License name: - Naziv licence: - - - - Path to license file: - Putanja do datoteke licence: - - - - (if required by license) - (ako to zahteva licenca) - - - - Browse... - Potraži... - - - - Create... - Napravi... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Izaberi paletu alatki - - - - Select a toolbar to add this macro to: - Izaberi paletu alatki u koju ćeÅ¡ dodati ovaj makro: - - - - Ask every time - Pitaj svaki put - - - - toolbar_button - - - - Add button? - Dodaj dugme? - - - - Add a toolbar button for this macro? - ŽeliÅ¡ li dodati dugme na paleti alatki za ovaj makro? - - - - Yes - Da - - - - No - Ne - - - - Never - Nikada - - - - AddonsInstaller - - - Starting up... - Pokreće se... - - - - Worker process {} is taking a long time to stop... - Radni proces {} se dugo zaustavlja... - - - - Previous cache process was interrupted, restarting... - - Prethodni proces keÅ¡iranja je prekinut, ponovo se pokreće... - - - - - Custom repo list changed, forcing recache... - - KorisniÄka lista spremiÅ¡ta je promenjena, prinudno ponovno keÅ¡iranje... - - - - - Addon manager - Menadžer dodataka - - - - You must restart FreeCAD for changes to take effect. - MoraÅ¡ ponovo pokrenuti FreeCAD da bi promene stupile na snagu. - - - - Restart now - Ponovo pokreni sada - - - - Restart later - Ponovo pokreni kasnije - - - - - Refresh local cache - Osveži lokalni keÅ¡ - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Ažuriranje keÅ¡a... - - - - - Checking for updates... - Proveravam da li postoje ažuriranja... - - - - Temporary installation of macro failed. - Privremena instalacija makro-a nije uspela. - - - - - Close - Zatvori - - - - Update all addons - Ažuriraj sve dodatke - - - - Check for updates - Proveri ažuriranja - - - - Python dependencies... - Python zavisnosti... - - - - Developer tools... - Alati za programere... - - - - Apply %n available update(s) - Primeni %n dostupnih ažuriranja - - - - No updates available - Nema dostupnih ažuriranja - - - - - - Cannot launch a new installer until the previous one has finished. - Ne može se pokrenuti novi program za instalaciju dok se prethodni ne zavrÅ¡i. - - - - - - - Maintainer - Programer zadužen za održavanje - - - - - - - Author - Autor - - - - New Python Version Detected - Otkrivena je nova verzija Python-a - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - ÄŒini se da je ovo prvi put da je ova verzija Python-a korišćena sa menadžerom dodataka. Da li želiÅ¡ za njega da instaliraÅ¡ iste automatski instalirane zavisnosti? - - - - Processing, please wait... - ObraÄ‘uje se, saÄekaj... - - - - - Update - Ažuriranje - - - - Updating... - Ažuriranje... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Nije moguće uvesti QtNetwork -- izgleda da nije instaliran na tvom sistemu. Tvoj provajder možda ima paket za ovu zavisnost (Äesto se na primer naziva, "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Konvertovanje navedenog proksi porta '{}' nije uspelo - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - GreÅ¡ka u parametru: postavljene su meÄ‘usobno iskljuÄive proksi opcije. Vraćanje na podrazumevane vrednosti. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - GreÅ¡ka u parametru: korisniÄki proksi je naznaÄen, ali nije obezbeÄ‘en. Vraćanje na podrazumevane vrednosti. - - - - Addon Manager: Unexpected {} response from server - Menadžer dodataka: NeoÄekivani {} odgovor od servera - - - - Error with encrypted connection - GreÅ¡ka Å¡ifrovane veze - - - - - - Confirm remove - Potvrdi uklanjanje - - - - Are you sure you want to uninstall {}? - Da li si siguran da želiÅ¡ da deinstaliraÅ¡ {}? - - - - - - Removing Addon - Uklanjanje Dodatka - - - - Removing {} - Уклања Ñе {} - - - - - Uninstall complete - Deinstaliranje je zavrÅ¡eno - - - - - Uninstall failed - Deinstaliranje nije uspelo - - - - Version {version} installed on {date} - Dana {date} instalirana je verzija {version} - - - - Version {version} installed - Instalirana je verzija {version} - - - - Installed on {date} - Instalirano {date} - - - - - - - Installed - Instalirano - - - - Currently on branch {}, name changed to {} - Trenutno na grani {}, promenjeno je ime u {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, ažuriranja nisu moguća - - - - Update check in progress - U toku je provera ažuriranja - - - - Installation location - Lokacija instalacije - - - - Repository URL - URL adresa spremiÅ¡ta - - - - Changed to branch '{}' -- please restart to use Addon. - Promenjeno u granu '{}' -- ponovo pokreni da bi koristio Dodatak. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Ovaj dodatak je ažuriran. Ponovo pokrenite FreeCAD da biste videli promene. - - - - Disabled - Onemogućen unos - - - - Currently on branch {}, update available to version {} - Na grani {} dostupno je ažuriranje do verzije {} - - - - Update available to version {} - Dostupno je ažuriranje do verzije {} - - - - This is the latest version available - Ovo je najnovija dostupna verzija - - - - WARNING: This addon is obsolete - UPOZORENJE: Ovaj dodatak je zastareo - - - - WARNING: This addon is Python 2 only - UPOZORENJE: Ovaj dodatak je samo za Python 2 - - - - WARNING: This addon requires FreeCAD {} - UPOZORENJE: Ovaj dodatak zahteva FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - UPOZORENJE: Ovaj dodatak je trenutno instaliran, ali je onemogućen. Koristi 'omogući' dugme da bi ponovo omogućio. - - - - This Addon will be enabled next time you restart FreeCAD. - Ovaj Dodatak će biti omogućen sledeći put kada ponovo pokreneÅ¡ FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Ovaj Dodatak će biti onemogućen sledeći put kada ponovo pokreneÅ¡ FreeCAD. - - - - - - Success - UspeÅ¡no - - - - Install - Instaliraj - - - - Uninstall - Deinstaliraj - - - - Enable - Omogući - - - - Disable - Onemogući - - - - - Check for update - Provеri ažuriranja - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Pokreni - - - - Change branch... - Promeni granu... - - - - Return to package list - Vrati se na listu paketa - - - - Checking connection - Proverava se veza - - - - Checking for connection to GitHub... - Proverava se veza sa GitHub-om... - - - - Connection failed - Veza nije uspostavljena - - - - Missing dependency - Nedostaje zavisnost - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Nije moguće uvesti QtNetwork – pogledaj PregledaÄ objava za detalje. Menadžer dodataka nije dostupan. - - - - Other... - For providing a license other than one listed - Ostalo... - - - - Select the corresponding license file in your Addon - Izaberi odgovarajuću datoteku licence u svom Dodatku - - - - Location for new license file - Lokacija za novu licencnu datoteku - - - - Received {} response code from server - Primljen {} kod odgovora sa servera - - - - Failed to install macro {} - Instaliranje makro-a {} nije uspelo - - - - Failed to create installation manifest file: - - Nije uspelo pravljenje manifest datoteke instalacije: - - - - - Unrecognized content kind '{}' - Nepoznata vrsta sadržaja '{}' - - - - Unable to locate icon at {} - Nije moguće pronaći ikonu u {} - - - - Select an icon file for this content item - Izaberi datoteku ikone za ovu stavku sadržaja - - - - - - {} is not a subdirectory of {} - {} nije podfascikla {} - - - - Select the subdirectory for this content item - Izaberi podfasciklu za ovu stavku sadržaja - - - - Automatic - Automatski - - - - - Workbench - Radno okruženje - - - - Addon - Dodatni modul - - - - Python - Python - - - - Yes - Da - - - - Internal Workbench - UnutraÅ¡nje radno okruženje - - - - External Addon - Spoljni Dodatak - - - - Python Package - Python paket - - - - - Other... - Ostalo... - - - - Too many to list - PreviÅ¡e ih je da bi se izlistali - - - - - - - - - Missing Requirement - Nedostaje Zahtev - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Dodatak '{}' zahteva '{}', Å¡to nije dostupno u tvojoj kopiji FreeCAD-a. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Dodatak '{}' zahteva sledeća radna okrženja koja nisu dostupna u tvojoj kopiji FreeCAD-a: - - - - Press OK to install anyway. - Pritisni U redu da bi ipak instalirao. - - - - - Incompatible Python version - Nekompatibilna verzija Python-a - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Ovaj Dodatak zahteva Python pakete koji nisu instalirani i ne mogu se instalirati automatski. Da bi koristio ovo radno okruženje, moraÅ¡ ruÄno da instaliraÅ¡ sledeće Python pakete: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Ovaj Dodatak (ili jedna od njegovih zavisnosti) zahteva Pithon {}.{}, a tvoj sistem radi na {}.{}. Instalacija je prekinuta. - - - - Optional dependency on {} ignored because it is not in the allow-list - Neobavezna zavisnost od {} se zanemaruje jer se ne nalazi na listi dozvoljenih - - - - - Installing dependencies - Instaliranje zavisnosti - - - - - Cannot execute Python - Nije moguće izvrÅ¡iti Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Automatsko pronalaženje izvrÅ¡ne datoteke Python-a nije uspelo, ili je putanja pogreÅ¡no zadata. Proveri ispravnost ove putanje u podeÅ¡avanjima za Menadžer dodataka. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Zavisnosti se ne mogu instalirati. ŽeliÅ¡ li ipak nastaviti sa instalacijom {}? - - - - - Cannot execute pip - Nije moguće izvrÅ¡iti pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - IzvrÅ¡avanje pip-a nije uspelo, izgleda da on nedostaje u tvojoj Python instalaciji. Uveri se da tvoj sistem ima instaliran pip i pokuÅ¡aj ponovo. Neuspela komanda je bila: - - - - - Continue with installation of {} anyway? - ŽeliÅ¡ li ipak nastaviti sa instalacijom {}? - - - - - Package installation failed - Instaliranje paketa nije uspelo - - - - See Report View for detailed failure log. - Pogledaj PregledaÄ objava za detaljan dnevnik greÅ¡aka. - - - - Installing Addon - Instaliranje Dodatka - - - - Installing FreeCAD Addon '{}' - Instaliranje FreeCAD dodatka '{}' - - - - Cancelling - Otkazivanje - - - - Cancelling installation of '{}' - Otkazivanje instalacije '{}' - - - - {} was installed successfully - {} je uspeÅ¡no instaliran - - - - - Installation Failed - Instalacija nije uspela - - - - Failed to install {} - Instaliranje {} nije uspelo - - - - - Create new toolbar - Napravi novu paletu sa alatkama - - - - - A macro installed with the FreeCAD Addon Manager - Makro instaliran sa FreeCAD Menadžerom dodataka - - - - - Run - Indicates a macro that can be 'run' - Pokreni - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Nije moguće proÄitati podatke sa GitHub-a: proveri internet vezu i podeÅ¡avanja proksija i pokuÅ¡aj ponovo. - - - - XML failure while reading metadata from file {} - XML greÅ¡ka pri Äitanju metapodataka iz datoteke {} - - - - Invalid metadata in file {} - Nevažeći metapodaci u datoteci {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - UPOZORENJE: Putanja navedena u metapodacima package.xml ne odgovara trenutnoј checked-out grani. - - - - Name - Ime - - - - Class - Klasa - - - - Description - Opis - - - - Subdirectory - Podfascikla - - - - Files - Datoteke - - - - Select the folder containing your Addon - Izaberi fasciklu u kojoj se nalazi tvoj Dodatak - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Nema Vermin-a, operacija se otkazuje. - - - - Scanning Addon for Python version compatibility - Skeniranje Dodatka radi utvrÄ‘ivanja kompatibilne verzije Pythom-a - - - - Minimum Python Version Detected - Otkrivena je minimalna verzija Python-a - - - - Vermin auto-detected a required version of Python 3.{} - Vermin je automatski otkrio potrebnu verziju Python-a 3.{} - - - - Install Vermin? - Instaliraj Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Za automatsko otkrivanje potrebne verzije Python-a za ovaj dodatak potreban je Vermin (https://pipi.org/project/vermin/). Pritisnite U redu ako želite instalirati? - - - - Attempting to install Vermin from PyPi - PokuÅ¡aj instaliranja Vermin-a sa PyPi-ja - - - - - Installation failed - Instalacija nije uspela - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Instalacija Vermin-a nije uspela – proveri PregledaÄ objava za detalje. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Uvoz Vermin-a nakon instalacije nije uspeo - ne može da se skenira Dodatak. - - - - Select an icon file for this package - Izaberi datoteku ikone za ovaj paket - - - - Filter is valid - Filter je važeći - - - - Filter regular expression is invalid - Regularni izraz filtra je nevažeći - - - - Search... - Pretraži... - - - - Click for details about package {} - Klikni za detalje o paketu {} - - - - Click for details about workbench {} - Klikni za detalje o radnom okruženju {} - - - - Click for details about macro {} - Klikni za detalje o makro-u {} - - - - Maintainers: - Programeri zaduženi za održavanje: - - - - Tags - Tagovi - - - - {} ★ on GitHub - {} ★ na GitHub - - - - No ★, or not on GitHub - Nema ★, ili nema na GitHub - - - - Created - Napravljeno - - - - Updated - Ažurirano - - - - Score: - Ocena: - - - - - Up-to-date - Ažurirano - - - - - - - - Update available - Dostupno jе ažuriranjе - - - - - Pending restart - Ponovno pokretanje na Äekanju - - - - - DISABLED - ONEMOGUĆENO - - - - Installed version - Instalirana verzija - - - - Unknown version - Nepoznata verzija - - - - Installed on - Instaliran na - - - - Available version - Dostupna verzija - - - - Filter by... - Filter... - - - - Addon Type - Vrsta dodatka - - - - - Any - Bilo koji - - - - Macro - Makro - - - - Preference Pack - Paket podeÅ¡avanja - - - - Installation Status - Status instalacije - - - - Not installed - Nije instalirano - - - - Filter - Filter - - - - DANGER: Developer feature - OPASNOST: Funkcija za programere - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - OPASNOST: Prebacivanje grana je namenjeno programerima i beta testerima i može da dovede do oÅ¡tećenih dokumenata koji nisu kompatibilni unazad, nestabilnosti, kvarova i/ili preranog toplotnog kolapsa univerzuma. Da li si siguran da želiÅ¡ da nastaviÅ¡? - - - - There are local changes - Postoje lokalne promene - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - UPOZORENjE: Ovo spremiÅ¡te ima nepovezane lokalne promene. Da li si siguran da želiÅ¡ da promeniÅ¡ grane (donoseći promene sa sobom)? - - - - Local - Table header for local git ref name - Lokalno - - - - Remote tracking - Table header for git remote tracking branch name - Daljinsko pracÌenje - - - - Last Updated - Table header for git update date - Poslednje ažurirano - - - - Installation of Python package {} failed - Instalacija Python paketa {} nije uspela - - - - Installation of optional package failed - Instalacija neobaveznog paketa nije uspela - - - - Installing required dependency {} - Instaliranje neophodne zavisnosti {} - - - - Installation of Addon {} failed - Instalacija Dodatka {} nije uspela - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Dekodiranje {} datoteke za Dodatak '{}' nije uspelo - - - - Any dependency information in this file will be ignored - Sve informacije u ovoj datoteci o zavisnosti će biti zanemarene - - - - Unable to open macro wiki page at {} - Nije moguće otvoriti makro wiki stranicu na {} - - - - Unable to fetch the code of this macro. - Nije moguće preuzeti kod ovog makroa. - - - - Unable to retrieve a description from the wiki for macro {} - Nije moguće preuzeti opis sa wiki-ja za makro {} - - - - Unable to open macro code URL {} - Nije moguće otvoriti URL adresu koda makro-a {} - - - - Unable to fetch macro-specified file {} from {} - Nije moguće preuzeti datoteku {} navedenu makroom iz {} - - - - Could not locate macro-specified file {} (expected at {}) - Nije moguće locirati datoteku navedenu makro-om {} (trebala je biti u {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Neprepoznato unutraÅ¡nje radno okruženje '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Upozorenje za programere dodataka: URL adresa spremiÅ¡ta zadata u package.xml datoteci za dodatak {} ({}) ne odgovara URL adresi sa koje je preuzet ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Upozorenje za programere dodataka: Grana spremiÅ¡ta postavljena u package.xml datoteci za dodatak {} ({}) se ne podudara sa granom iz koje je preuzeta ({}) - - - - - Got an error when trying to import {} - GreÅ¡ka pri pokuÅ¡aju uvoza {} - - - - An unknown error occurred - DoÅ¡lo je do nepoznate greÅ¡ke - - - - Could not find addon {} to remove it. - Nije moguće pronaći Dodatak {} za uklanjanje. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - IzvrÅ¡avanje uninstall.py skripte Dodatka nije uspelo. Nastavlja se sa deinstaliranjem... - - - - Removed extra installed file {} - Uklonjena je dodatno instalirana datoteka {} - - - - Error while trying to remove extra installed file {} - GreÅ¡ka pri pokuÅ¡aju uklanjanja dodatno instalirane datoteke {} - - - - Error while trying to remove macro file {}: - GreÅ¡ka pri pokuÅ¡aju uklanjanja datoteke makro-a {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Povezivanje sa GitHub-om nije uspelo. Proveri podeÅ¡avanja veze i proksija. - - - - WARNING: Duplicate addon {} ignored - UPOZORENJE: Duplikat dodatka {} je ignorisan - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - DoÅ¡lo je do greÅ¡ke pri ažuriranju makro-a sa GitHub-a, pokuÅ¡avam clean checkout... - - - - Attempting to do a clean checkout... - PokuÅ¡avam da uradim clean checkout... - - - - Clean checkout succeeded - Clean checkout je uspeo - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Ažuriranje makro-a sa GitHub-a nije uspelo -- pokuÅ¡aj da obriÅ¡ete keÅ¡ memoriju Menadžera dodataka. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - GreÅ¡ka pri povezivanju na Wiki, FreeCAD trenutno ne može da preuzme Wiki listu makro-a - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - ÄŒitanje metapodataka sa {name} nije uspelo - - - - Failed to fetch code for macro '{name}' - Nije uspelo preuzimanje koda za makro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Menadžer dodataka: radni proces nije uspeo da se zavrÅ¡i tokom preuzimanja {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Za {num_macros} makro je prekoraÄen je vremenski limit, {num_failed} tokom obrade - - - - Addon Manager: a worker process failed to halt ({name}) - Menadžer dodataka: radni proces nije uspeo da se zaustavi ({name}) - - - - Timeout while fetching metadata for macro {} - Isteklo je vreme za preuzimanje metapodataka za makro {} - - - - Failed to kill process for macro {}! - - Ubijanje procesa za makro {} nije uspelo! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Nije uspelo preuzimanje statistike o dodatku od {} – samo cÌe sortiranje po abecednom redu biti taÄno - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - NeuspeÅ¡no preuzimanje ocena o dodatku od '{}' -- sortiranje po ocenama necÌe uspeti - - - - - Repository URL - Preferences header for custom repositories - URL adresa spremiÅ¡ta - - - - Branch name - Preferences header for custom repositories - Ime grane - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Pravljenje rezervne kopije originalne fascikle i ponovno kloniranje - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Preimenovanje Git grane nije uspelo sa sledecÌom porukom: - - - - Installing - Instaliranje - - - - Succeeded - UspeÅ¡no - - - - Failed - NeuspeÅ¡no - - - - Update was cancelled - Ažuriranje je otkazano - - - - some addons may have been updated - neki dodaci su možda ažurirani - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - UÄitavanje informacija za {} sa wiki strana FreeCAD Macro Recipes... - - - - Loading page for {} from {}... - UÄitavanje stranice za {} od {}... - - - - Failed to download data from {} -- received response code {}. - Preuzimanje podataka sa {} nije uspelo -- primljen je kod odgovora {}. - - - - Composite view - Razdvojeni izgled - - - - Expanded view - ProÅ¡iren izgled - - - - Compact view - Kompaktan izgled - - - - Alphabetical - Sort order - Po abecednom redu - - - - Last Updated - Sort order - Poslednje ažurirano - - - - Date Created - Sort order - Datum kreiranja - - - - GitHub Stars - Sort order - Github zvezde - - - - Score - Sort order - Ocena - - - - Std_AddonMgr - - - &Addon manager - &Menadžer dodataka - - - - Manage external workbenches, macros, and preference packs - Upravljaj spoljnim radnim okruženjima, makro-ima i paketima podeÅ¡avanja - - - - AddonInstaller - - - Finished removing {} - ZavrÅ¡eno uklanjanje {} - - - - Failed to remove some files - Uklanjanje nekih datoteka nije uspelo - - - - Addons installer - - - Finished updating the following addons - ZavrÅ¡eno je ažuriranje sledećih dodataka - - - - Workbench - - - Auto-Created Macro Toolbar - Automatski napravljena Makro paleta alatki - - - - QObject - - - Addon Manager - Menadžer dodataka - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sr.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_sr.qm deleted file mode 100644 index ac04ef12842a4a3d44dffd1bee1d300c24c22d81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69684 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 qI&a#783K*!05Ndue&w}MO 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 - - - - AddCustomRepositoryDialog - - - Custom repository - СопÑтвено Ñпремиште - - - - Repository URL - URL адреÑа Ñпремишта - - - - Branch - Грана - - - - CompactView - - - - Icon - Икона - - - - - <b>Package Name</b> - <b>Име пакета</b> - - - - - Version - Верзија - - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Update Available - ДоÑтупно је ажурирање - - - - UpdateAvailable - Ðа раÑполагању је новија верзија - - - - DependencyDialog - - - Dependencies - ЗавиÑноÑти - - - - Dependency type - Ð’Ñ€Ñта завиÑноÑти - - - - Name - Име - - - - Optional? - Ðеобавезно? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Реши завиÑноÑти - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Овај Додатак има Ñледеће обавезне и необавезне завиÑноÑти. Мораш их инÑталирати да би могао кориÑтити овај Додатак. - -Да ли желиш да их Менаџер додатака аутоматÑки инÑталира? Изабери "Занемари" да инÑталираш додатак без инÑталирања завиÑноÑти. - - - - FreeCAD Addons - FreeCAD Додаци - - - - Required Python modules - Потребни Python модули - - - - Optional Python modules - Ðеобавезни Python модули - - - - DeveloperModeDialog - - - Addon Developer Tools - Ðлатке за програмере додатака - - - - Path to Addon - Путања до Додатка - - - - - Browse... - Потражи... - - - - Metadata - Метаподаци - - - - Primary branch - Главна грана - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Објашњење шта овај додатак пружа. Приказује Ñе у Менаџеру додатака. Ðије неопходно да Ñе наводи да је ово додатак за FreeCAD. - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Discussion URL - URL адреÑа диÑкуÑије - - - - Icon - Икона - - - - Bugtracker URL - URL адреÑа ÑиÑтема за праћење грешака - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Подржани Ñу Semantic (1.2.3-beta) или CalVer (2022.08.30) Ñтилови - - - - Set to today (CalVer style) - ПоÑтављено на Ð´Ð°Ð½Ð°Ñ (CalVer Ñтил) - - - - - - - (Optional) - (необавезно) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Приказује Ñе на лиÑти Менаџера додатака. Ðе би требало да Ñадржи реч "FreeCAD", и мора поÑтојати важеће име фаÑцикле за Ñве подржане оперативне ÑиÑтеме. - - - - README URL - URL адреÑа датотеке README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - СÐВЕТ: Пошто је ово приказано у Менаџеру додатака FreeCAD програма, није неопходно да заузимаш проÑтор говорећи Ñтвари попут "Ово је FreeCAD додатак..." -- Ñамо реци шта ради. - - - - Repository URL - URL адреÑа Ñпремишта - - - - Website URL - URL адреÑа веб Ñајта - - - - Documentation URL - URL адреÑа документације - - - - Addon Name - Име додатка - - - - Version - Верзија - - - - (Recommended) - (Препоручено) - - - - Minimum Python - Минимум Python - - - - (Optional, only 3.x version supported) - (Ðеобавезно, подржана је Ñамо верзија 3.x) - - - - Detect... - Откриј... - - - - Addon Contents - Садржај додатка - - - - Dialog - - - Addon Manager - Менаџер додатака - - - - Edit Tags - Уреди тагове - - - - Comma-separated list of tags describing this item: - ЛиÑта тагова раздвојених зарезима које опиÑују ову Ñтавку: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - СÐВЕТ: Уобичајени тагови укључују "Склоп", "FEM", "Мрежа", "NURBS", etc. - - - - Add-on Manager: Warning! - Менаџер додатака: Упозорење! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Менаџер додатака пружа приÑтуп библиотеци кориÑних FreeCAD додатака незавиÑних произвођача. Додатке кориÑтите на Ñвоју одговорноÑÑ‚ пошто FreeCAD не може гарантовати за њихову безбедноÑти или функционалноÑти. - - - - Continue - ÐаÑтави - - - - Cancel - Откажи - - - - EditDependencyDialog - - - Edit Dependency - Уреди завиÑноÑÑ‚ - - - - Dependency Type - Ð’Ñ€Ñта завиÑноÑти - - - - Dependency - ЗавиÑноÑÑ‚ - - - - Package name, if "Other..." - Име пакета, ако је "ОÑтало..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - ÐÐПОМЕÐÐ: Ðко је "Ostalo..." изабран, пакет Ñе не налази у датотеци ALLOWED_PYTHON_PACKAGES.txt и Менаџер додатака га неће аутоматÑки инÑталирати. Пошаљи PR на <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> да затражи додавање пакета. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Ðко је ово необавезна завиÑноÑÑ‚, Менаџер додатака ће понудити да је инÑталира (када је то могуће), али неће блокирати инÑталацију ако кориÑник одлучи да не инÑталира или не може да инÑталира пакет. - - - - Optional - Ðеобавезно - - - - ExpandedView - - - - Icon - Икона - - - - - <h1>Package Name</h1> - <h1>Име пакета</h1> - - - - - Version - Верзија - - - - - (tags) - (тагови) - - - - - Description - ÐžÐ¿Ð¸Ñ - - - - - Maintainer - Програмер задужен за одржавање - - - - Update Available - ДоÑтупно је ажурирање - - - - labelSort - labelSort - - - - UpdateAvailable - Ðа раÑполагању је новија верзија - - - - Form - - - Licenses - Лиценце - - - - License - Лиценца - - - - License file - Датотека лиценце - - - - People - ОÑобе - - - - Kind - Ð’Ñ€Ñта - - - - Name - Име - - - - Email - ЕлектронÑка пошта - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Ðапредно мапирање верзија - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - ПредÑтојеће верзије FreeCAD Менаџера додатака ће подржавати програмерÑко подешавање одређених грана или тагова за употребу Ñа одређеном верзијом FreeCAD-а (нпр. подешавање одређеног таг-а као поÑледње верзије вашег Додатка за подршку v0.19, итд.) - - - - FreeCAD Version - FreeCAD верзија - - - - Best-available branch, tag, or commit - Ðајбоља доÑтупна грана, таг или commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Подржане FreeCAD верзије - - - - Minimum FreeCAD Version Supported - Минимална подржана FreeCAD верзија - - - - - Optional - Ðеобавезно - - - - Maximum FreeCAD Version Supported - МакÑимална подржана FreeCAD верзија - - - - Advanced version mapping... - Ðапредно мапирање верзија... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Опције Менаџера додатака - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Ðко је ова опција изабрана, приликом покретања Менаџера додатака -ће бити проверено да ли поÑтоје доÑтупна ажурирања за инÑталиране додатке - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Преузми макро метаподатке (приближно 10MB) - - - - Cache update frequency - УчеÑталоÑÑ‚ ажурирања кеша - - - - Manual (no automatic updates) - Ручно (без аутоматÑког ажурирања) - - - - Daily - Дневно - - - - Weekly - Ðедељно - - - - Hide Addons without a license - Sakrij dodatke bez licence - - - - Hide Addons with non-FSF Free/Libre license - Сакриј додатке који немају FSF Free/Libre лиценцу - - - - Hide Addons with non-OSI-approved license - Сакриј додатке који немају ОСИ одобрену лиценцу - - - - Hide Addons marked Python 2 Only - Сакриј Додатке Ñа ознаком "Само Python 2" - - - - Hide Addons marked Obsolete - Сакриј Додатке означене као заÑтарели - - - - Hide Addons that require a newer version of FreeCAD - Сакриј Додатке који захтевају новију верзију FreeCAD-а - - - - Custom repositories - СопÑтвено Ñпремиште - - - - Proxy - ПрокÑи, ПоÑреднички Ñервер - - - - No proxy - Без прокÑи - - - - User system proxy - КориÑнички ÑиÑтемÑки прокÑи - - - - User-defined proxy: - КориÑнички прокÑи: - - - - Score source URL - URL извора оцена - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - УРЛ за оцене додатка (за више детаља погледај wики Ñтрану Ðддон Манагер). - - - - Path to Git executable (optional): - Путања до Git извршне датотеке (необавезно): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Ðапредне опције - - - - Activate Addon Manager options intended for developers of new Addons. - Ðктивирај опције Менаџера додатака намењене програмерима нових додатака. - - - - Addon developer mode - Режим програмера додатака - - - - PackageDetails - - - Uninstalls a selected macro or workbench - ДеинÑталирај изабрани макро или радно окружење - - - - Install - ИнÑталирај - - - - Uninstall - ДеинÑталирај - - - - Update - Ðжурирање - - - - Run Macro - Покрени макро - - - - Change branch - Промени грану - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Управљање Python завиÑноÑтима - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Следеће Python пакете је локално инÑталирао Менаџер додатака да би задовољио завиÑноÑти додатака. Локација инÑталације: - - - - Package name - Име пакета - - - - Installed version - ИнÑталирана верзија - - - - Available version - ДоÑтупна верзија - - - - Used by - Koristio - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Звездица Ñ‚.ј. аÑÑ‚ÐµÑ€Ð¸ÐºÑ (*) у пољу "КориÑтио" колоне означава необавезну завиÑноÑÑ‚. Имај на уму да 'КориÑтио' Ñамо бележи директан увоз у Додатак. Можда Ñу инÑталирани и други Пyтхон пакети од којих ти пакети завиÑе. - - - - Update all available - Ðжурирај Ñве доÑтупно - - - - SelectFromList - - - Dialog - Дијалог - - - - TextLabel - ТекÑтуална ознака - - - - UpdateAllDialog - - - Updating Addons - Ðжурирање Додатака - - - - Updating out-of-date addons... - Ðжурирање заÑтарелих додатака... - - - - addContentDialog - - - Content Item - Ставка Ñа Ñадржајем - - - - Content type: - Ð’Ñ€Ñта Ñадржаја: - - - - Macro - Макро - - - - Preference Pack - Пакет подешавања - - - - Workbench - Радно окружење - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Ðко је ово једина Ñтвар у Додатку, Ñви оÑтали метаподаци могу бити наÑлеђени Ñа највишег нивоа и не морају Ñе овде наводити. - - - - This is the only item in the Addon - Ово је једина Ñтавка у Додатку - - - - Main macro file - Главна макро датотека - - - - The file with the macro's metadata in it - Датотека Ñа метаподацима макро-а у њој - - - - - - Browse... - Потражи... - - - - Preference Pack Name - Име пакета подешавања - - - - Workbench class name - Име клаÑе радног окружења - - - - Class that defines "Icon" data member - КлаÑа која одређује податак члана "Icon" - - - - Subdirectory - ПодфаÑцикла - - - - Optional, defaults to name of content item - Опционо, подразумевано је име Ñтавке Ñа Ñадржајем - - - - Icon - Икона - - - - Optional, defaults to inheriting from top-level Addon - Опционо, подразумевано наÑлеђивање од Додатка највишег нивоа - - - - Tags... - Тагови... - - - - Dependencies... - ЗавиÑноÑти... - - - - FreeCAD Versions... - FreeCAD верзија... - - - - Other Metadata - ОÑтали метаподаци - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Приказује Ñе на лиÑти Менаџера додатака. Ðе би требало да Ñадржи реч "FreeCAD". - - - - Version - Верзија - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Подржани Ñу Semantic (1.2.3-beta) или CalVer (2022.08.30) Ñтилови - - - - Set to today (CalVer style) - ПоÑтављено на Ð´Ð°Ð½Ð°Ñ (CalVer Ñтил) - - - - Display Name - Приказано име - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Сва поља оÑтављена празна Ñу наÑлеђена од метаподатака додатка највишег нивоа, тако да технички, Ñва Ñу необавезна. За додатке Ñа више Ñтавки Ñа Ñадржајем, Ñвака Ñтавка треба да омогући јединÑтвено име и опиÑ. - - - - add_toolbar_button_dialog - - - Add button? - Додај дугме? - - - - Add a toolbar button for this macro? - Желиш ли додати дугме на палети алатки за овај макро? - - - - Yes - Да - - - - No - Ðе - - - - Never - Ðикада - - - - change_branch - - - Change Branch - Промени грану - - - - Change to branch: - Промени грану: - - - - copyrightInformationDialog - - - Copyright Information - Информације о ауторÑким правима - - - - Copyright holder: - ÐоÑилац ауторÑких права: - - - - Copyright year: - Година од кад важи ауторÑко право: - - - - personDialog - - - Add Person - Додај оÑобу - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Програмер задужен за одржавање је неко Ñа тренутним приÑтупом овом пројекту. Ðутор је неко, коме можеш да одаш признање. - - - - Name: - Име: - - - - Email: - Е-пошта: - - - - Email is required for maintainers, and optional for authors. - Е-пошта је неопходна за оÑобу одговорну за одржавање, а необавезно за ауторе. - - - - proxy_authentication - - - Proxy login required - Потребна је пријава за прокÑи - - - - Proxy requires authentication - ПрокÑи захтева аутентификацију - - - - Proxy: - ПрокÑи: - - - - Placeholder for proxy address - РезервиÑано меÑто за прокÑи адреÑу - - - - Realm: - ОблаÑÑ‚: - - - - Placeholder for proxy realm - РезервиÑано меÑто за прокÑи облаÑÑ‚ - - - - Username - КориÑничко име - - - - Password - Лозинка - - - - selectLicenseDialog - - - Select a license - Изабери лиценцу - - - - About... - О... - - - - License name: - Ðазив лиценце: - - - - Path to license file: - Путања до датотеке лиценце: - - - - (if required by license) - (ако то захтева лиценца) - - - - Browse... - Потражи... - - - - Create... - Ðаправи... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Изабери палету алатки - - - - Select a toolbar to add this macro to: - Изабери палету алатки у коју ћеш додати овај макро: - - - - Ask every time - Питај Ñваки пут - - - - toolbar_button - - - - Add button? - Додај дугме? - - - - Add a toolbar button for this macro? - Желиш ли додати дугме на палети алатки за овај макро? - - - - Yes - Да - - - - No - Ðе - - - - Never - Ðикада - - - - AddonsInstaller - - - Starting up... - Покреће Ñе... - - - - Worker process {} is taking a long time to stop... - Радни Ð¿Ñ€Ð¾Ñ†ÐµÑ {} Ñе дуго зауÑтавља... - - - - Previous cache process was interrupted, restarting... - - Претходни Ð¿Ñ€Ð¾Ñ†ÐµÑ ÐºÐµÑˆÐ¸Ñ€Ð°ÑšÐ° је прекинут, поново Ñе покреће... - - - - - Custom repo list changed, forcing recache... - - КориÑничка лиÑта Ñпремишта је промењена, принудно поновно кеширање... - - - - - Addon manager - Менаџер додатака - - - - You must restart FreeCAD for changes to take effect. - Мораш поново покренути FreeCAD да би промене Ñтупиле на Ñнагу. - - - - Restart now - Поново покрени Ñада - - - - Restart later - Поново покрени каÑније - - - - - Refresh local cache - ОÑвежи локални кеш - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Ðжурирање кеша... - - - - - Checking for updates... - Проверавам да ли поÑтоје ажурирања... - - - - Temporary installation of macro failed. - Привремена инÑталација макро-а није уÑпела. - - - - - Close - Затвори - - - - Update all addons - Ðжурирај Ñве додатке - - - - Check for updates - Провери ажурирања - - - - Python dependencies... - Python завиÑноÑти... - - - - Developer tools... - Ðлати за програмере... - - - - Apply %n available update(s) - Примени %n доÑтупних ажурирања - - - - No updates available - Ðема доÑтупних ажурирања - - - - - - Cannot launch a new installer until the previous one has finished. - Ðе може Ñе покренути нови програм за инÑталацију док Ñе претходни не заврши. - - - - - - - Maintainer - Програмер задужен за одржавање - - - - - - - Author - Ðутор - - - - New Python Version Detected - Откривена је нова верзија Python-а - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Чини Ñе да је ово први пут да је ова верзија Python-а коришћена Ñа Менаџером додатака. Да ли желиш за њега да инÑталираш иÑте аутоматÑки инÑталиране завиÑноÑти? - - - - Processing, please wait... - Обрађује Ñе, Ñачекај... - - - - - Update - Ðжурирање - - - - Updating... - Ðжурирање... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Ðије могуће увеÑти QtNetwork -- изгледа да није инÑталиран твом на ÑиÑтему. Твој провајдер можда има пакет за ову завиÑноÑÑ‚ (чеÑто Ñе на пример назива, "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Конвертовање наведеног прокÑи порта '{}' није уÑпело - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Грешка у параметру: поÑтављене Ñу међуÑобно иÑкључиве прокÑи опције. Враћање на подразумеване вредноÑти. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Грешка у параметру: кориÑнички прокÑи је назначен, али није обезбеђен. Враћање на подразумеване вредноÑти. - - - - Addon Manager: Unexpected {} response from server - Менаџер додатака: Ðеочекивани {} одговор од Ñервера - - - - Error with encrypted connection - Грешка шифроване везе - - - - - - Confirm remove - Потврди уклањање - - - - Are you sure you want to uninstall {}? - Да ли Ñи Ñигуран да желиш да деинÑталираш {}? - - - - - - Removing Addon - Уклањање Додатка - - - - Removing {} - Уклања Ñе {} - - - - - Uninstall complete - ДеинÑталирање је завршено - - - - - Uninstall failed - ДеинÑталирање није уÑпело - - - - Version {version} installed on {date} - Дана {date} инÑталирана је верзија {version} - - - - Version {version} installed - ИнÑталирана је верзија {version} - - - - Installed on {date} - ИнÑталирано {date} - - - - - - - Installed - ИнÑталирано - - - - Currently on branch {}, name changed to {} - Тренутно на грани {}, промењено је име у {} - - - - Git tag '{}' checked out, no updates possible - Git таг '{}' checked out, ажурирања ниÑу могућа - - - - Update check in progress - У току је провера ажурирања - - - - Installation location - Локација инÑталације - - - - Repository URL - URL адреÑа Ñпремишта - - - - Changed to branch '{}' -- please restart to use Addon. - Промењено у грану '{}' -- поново покрени да би кориÑтио Додатак. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Овај додатак је ажуриран. Поново покрените FreeCAD да биÑте видели промене. - - - - Disabled - Онемогућен ÑƒÐ½Ð¾Ñ - - - - Currently on branch {}, update available to version {} - Ðа грани {} доÑтупно је ажурирање до верзије {} - - - - Update available to version {} - ДоÑтупно је ажурирање до верзије {} - - - - This is the latest version available - Ово је најновија доÑтупна верзија - - - - WARNING: This addon is obsolete - УПОЗОРЕЊЕ: Овај додатак је заÑтарео - - - - WARNING: This addon is Python 2 only - УПОЗОРЕЊЕ: Овај додатак је Ñамо за Python 2 - - - - WARNING: This addon requires FreeCAD {} - УПОЗОРЕЊЕ: Овај додатак захтева FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - УПОЗОРЕЊЕ: Овај додатак је тренутно инÑталиран, али онемогућен. КориÑти 'омогући' дугме да би поново омогућио. - - - - This Addon will be enabled next time you restart FreeCAD. - Овај Додатак ће бити омогућен Ñледећи пут када поново покренеш FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Овај Додатак ће бити онемогућен Ñледећи пут када поново покренеш FreeCAD. - - - - - - Success - УÑпешно - - - - Install - ИнÑталирај - - - - Uninstall - ДеинÑталирај - - - - Enable - Омогући - - - - Disable - Онемогући - - - - - Check for update - Провери ажурирања - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Покрени - - - - Change branch... - Промени грану... - - - - Return to package list - Врати Ñе на лиÑту пакета - - - - Checking connection - Проверава Ñе веза - - - - Checking for connection to GitHub... - Проверава Ñе веза Ñа GitHub-ом... - - - - Connection failed - Веза није уÑпоÑтављена - - - - Missing dependency - ÐедоÑтаје завиÑноÑÑ‚ - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Ðије могуће увеÑти QtNetwork – погледај Прегледач објава за детаље. Менаджер додатака није доÑтупан. - - - - Other... - For providing a license other than one listed - ОÑтало... - - - - Select the corresponding license file in your Addon - Изабери одговарајућу датотеку лиценце у Ñвом Додатку - - - - Location for new license file - Локација за нову лиценцну датотеку - - - - Received {} response code from server - Примљен {} код одговора Ñа Ñервера - - - - Failed to install macro {} - ИнÑталирање макро-а {} није уÑпело - - - - Failed to create installation manifest file: - - Ðије уÑпело прављење манифеÑÑ‚ датотеке инÑталације: - - - - - Unrecognized content kind '{}' - Ðепозната врÑта Ñадржаја '{}' - - - - Unable to locate icon at {} - Ðије могуће пронаћи икону у {} - - - - Select an icon file for this content item - Изабери датотеку иконе за ову Ñтавку Ñадржаја - - - - - - {} is not a subdirectory of {} - {} није подфаÑцикла {} - - - - Select the subdirectory for this content item - Изабери подфаÑциклу за ову Ñтавку Ñадржаја - - - - Automatic - ÐутоматÑки - - - - - Workbench - Радно окружење - - - - Addon - Додатни модул - - - - Python - Python - - - - Yes - Да - - - - Internal Workbench - Унутрашње радно окружење - - - - External Addon - Cпољни Додатак - - - - Python Package - Python пакет - - - - - Other... - ОÑтало... - - - - Too many to list - Превише их је да би Ñе излиÑтали - - - - - - - - - Missing Requirement - ÐедоÑтаје Захтев - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Додатак '{}' захтева '{}', што није доÑтупно у твојојј копији FreeCAD-а. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Додатак '{}' захтева Ñледећа радна окружења, која ниÑу доÑтупна у твојој копији FreeCAD-а: - - - - Press OK to install anyway. - ПритиÑни У реду да би ипак инÑталирао. - - - - - Incompatible Python version - Ðекомпатибилна верзија Python-а - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Овај додатак захтева Python пакете који ниÑу инÑталирани и не могу Ñе инÑталирати аутоматÑки. Да биÑте кориÑтили овај додатак, морате ручно да инÑталирате Ñледеће Python пакете: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Овај Додатак (или једна од његових завиÑноÑти) захтева Python {}.{}, а ваш ÑиÑтем ради {}.{}. ИнÑталација је отказана. - - - - Optional dependency on {} ignored because it is not in the allow-list - Ðеобавезна завиÑноÑÑ‚ од {} Ñе занемарује јер Ñе не налази на лиÑти дозвољених - - - - - Installing dependencies - ИнÑталирање завиÑноÑти - - - - - Cannot execute Python - Ðије могуће извршити Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - ÐутоматÑко проналажење извршне датотеке Python-а није уÑпело, или је путања погрешно задата. Провери иÑправноÑÑ‚ ове путање у подешавањима за Менаџер додатака. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - ЗавиÑноÑти Ñе не могу инÑталирати. Желиш ли ипак наÑтавити Ñа инÑталацијом {}? - - - - - Cannot execute pip - Ðије могуће извршити pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Извршавање pip-а није уÑпело, изгледа да он недоÑтаје у твојој Python инÑталацији. Увери Ñе да твој ÑиÑтем има инÑталиран pip и покушај поново. ÐеуÑпела команда је била: - - - - - Continue with installation of {} anyway? - Желиш ли ипак наÑтавити Ñа инÑталацијом {}? - - - - - Package installation failed - ИнÑталирање пакета није уÑпело - - - - See Report View for detailed failure log. - Погледај Прегледач објава за детаљан дневник грешака. - - - - Installing Addon - ИнÑталирање Додатка - - - - Installing FreeCAD Addon '{}' - ИнÑталирање FreeCAD Додатка '{}' - - - - Cancelling - Отказивање - - - - Cancelling installation of '{}' - Отказивање од инÑталације '{}' - - - - {} was installed successfully - {} је уÑпешно инÑталиран - - - - - Installation Failed - ИнÑталација није уÑпела - - - - Failed to install {} - ИнÑталирање {} није уÑпело - - - - - Create new toolbar - Ðаправи нову палету Ñа алаткама - - - - - A macro installed with the FreeCAD Addon Manager - Макро инÑталиран Ñа FreeCAD Менаџером додатака - - - - - Run - Indicates a macro that can be 'run' - Покрени - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Ðије могуће прочитати податке Ñа GitHub-а: провери интернет везу и подешавања прокÑија и покушај поново. - - - - XML failure while reading metadata from file {} - XML грешка при читању метаподатака из датотеке {} - - - - Invalid metadata in file {} - Ðеважећи метаподаци у датотеци {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - УПОЗОРЕЊЕ: Путања наведена у метаподацима package.xml не одговара тренутној checked-out грани. - - - - Name - Име - - - - Class - КлаÑа - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Subdirectory - ПодфаÑцикла - - - - Files - Датотеке - - - - Select the folder containing your Addon - Изабери фаÑциклу у којој Ñе налази твој Додатак - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Ðема Вермин-а, операција Ñе отказује. - - - - Scanning Addon for Python version compatibility - Скенирање Додатка ради утврђивања компатибилне верзије Python-а - - - - Minimum Python Version Detected - Откривена је минимална верзија Python-а - - - - Vermin auto-detected a required version of Python 3.{} - Vermin је аутоматÑки открио потребну верзију Python-а 3.{} - - - - Install Vermin? - ИнÑталирај Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - За аутоматÑко откривање потребне верзије Python-а за овај додатак потребан је Vermin (https://pypi.org/project/vermin/). ПритиÑните У реду ако желите инÑталирати? - - - - Attempting to install Vermin from PyPi - Покушај инÑталирања Vermin-a Ñа PyPi-ја - - - - - Installation failed - ИнÑталација није уÑпела - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - ИнÑталација Vermin-а није уÑпела – провери Прегледач објава за детаље. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Увоз Vermin-а након инÑталације није уÑпео - не може да Ñе Ñкенира Додатак. - - - - Select an icon file for this package - Изабери датотеку иконе за овај пакет - - - - Filter is valid - Филтер је важећи - - - - Filter regular expression is invalid - Регуларни израз филтра је неважећи - - - - Search... - Претрага... - - - - Click for details about package {} - Кликни за детаље о пакету {} - - - - Click for details about workbench {} - Кликни за детаље о радном окружењу {} - - - - Click for details about macro {} - Кликни за детаље о макро-у {} - - - - Maintainers: - Програмери задужени за одржавање: - - - - Tags - Тагови - - - - {} ★ on GitHub - {} ★ на GitHub - - - - No ★, or not on GitHub - Ðема ★, или нема на GitHub - - - - Created - Ðаправљено - - - - Updated - Ðжурирано - - - - Score: - Оцена: - - - - - Up-to-date - Ðжурирано - - - - - - - - Update available - ДоÑтупно је ажурирање - - - - - Pending restart - Поновно покретање на чекању - - - - - DISABLED - ОÐЕМОГУЋЕÐО - - - - Installed version - ИнÑталирана верзија - - - - Unknown version - Ðепозната верзија - - - - Installed on - ИнÑталиран на - - - - Available version - ДоÑтупна верзија - - - - Filter by... - Филтери... - - - - Addon Type - Ð’Ñ€Ñта додатка - - - - - Any - Било који - - - - Macro - Макро - - - - Preference Pack - Пакет подешавања - - - - Installation Status - Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¸Ð½Ñталације - - - - Not installed - Ðије инÑталирано - - - - Filter - Филтер - - - - DANGER: Developer feature - ОПÐСÐОСТ: Функција за програмере - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - ОПÐСÐОСТ: Пребацивање грана је намењено програмерима и бета теÑтерима и може да доведе до оштећених докумената који ниÑу компатибилни уназад, неÑтабилноÑти, кварова и/или прераног топлотног колапÑа универзума. Да ли Ñи Ñигуран да желиш да наÑтавиш? - - - - There are local changes - ПоÑтоје локалне промене - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - УПОЗОРЕЊЕ: Ово Ñпремиште има неповезане локалне промене. Да ли Ñи Ñигуран да желиш да промениш гране (доноÑећи промене Ñа Ñобом)? - - - - Local - Table header for local git ref name - Локално - - - - Remote tracking - Table header for git remote tracking branch name - ДаљинÑко праћење - - - - Last Updated - Table header for git update date - ПоÑледње ажурирано - - - - Installation of Python package {} failed - ИнÑталација Python пакета {} није уÑпела - - - - Installation of optional package failed - ИнÑталација необавезног пакета није уÑпела - - - - Installing required dependency {} - ИнÑталирање неопходне завиÑноÑти {} - - - - Installation of Addon {} failed - ИнÑталација Додатка {} није уÑпела - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Декодирање {} датотеке за Додатак '{}' није уÑпело - - - - Any dependency information in this file will be ignored - Све информације у овој датотеци о завиÑноÑти ће бити занемарене - - - - Unable to open macro wiki page at {} - Ðије могуће отворити макро wiki Ñтраницу на {} - - - - Unable to fetch the code of this macro. - Ðије могуће преузети код овог макроа. - - - - Unable to retrieve a description from the wiki for macro {} - Ðије могуће преузети Ð¾Ð¿Ð¸Ñ Ñа wiki-ја за макро {} - - - - Unable to open macro code URL {} - Ðије могуће отворити URL адреÑу кода макроа {} - - - - Unable to fetch macro-specified file {} from {} - Ðије могуће преузети датотеку {} наведену макроом из {} - - - - Could not locate macro-specified file {} (expected at {}) - Ðије могуће лоцирати датотеку наведену макро-ом {} (требала је бити у {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Ðепрепознато унутрашње радно окружење '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Упозорење за програмере додатака: URL адреÑа Ñпремишта задата у package.xml датотеци за додатак {} ({}) не одговара URL адреÑи Ñа које је преузет ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Упозорење за програмере додатака: Грана Ñпремишта поÑтављена у package.xml датотеци за додатак {} ({}) Ñе не подудара Ñа граном из које је преузета ({}) - - - - - Got an error when trying to import {} - Грешка при покушају увоза {} - - - - An unknown error occurred - Дошло је до непознате грешке - - - - Could not find addon {} to remove it. - Ðије могуће пронаћи Додатак {} за уклањање. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Извршавање uninstall.py Ñкрипте Додатка није уÑпело. ÐаÑтавља Ñе Ñа деинÑталирањем... - - - - Removed extra installed file {} - Уклоњена је додатно инÑталирана датотека {} - - - - Error while trying to remove extra installed file {} - Грешка при покушају уклањања додатно инÑталиране датотеке {} - - - - Error while trying to remove macro file {}: - Грешка при покушају уклањања датотеке макро-а {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Повезивање Ñа GitHub-ом није уÑпело. Провери подешавања везе и прокÑија. - - - - WARNING: Duplicate addon {} ignored - УПОЗОРЕЊЕ: Дупликат додатка {} је игнориÑан - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Дошло је до грешке при ажурирању макро-а Ñа GitHub-а, покушавам clean checkout... - - - - Attempting to do a clean checkout... - Покушавам да урадим clean checkout... - - - - Clean checkout succeeded - Clean checkout је уÑпео - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Ðжурирање макро-а Ñа GitHub-а није уÑпело -- покушај да обришете кеш меморију Менаџера додатака. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Грешка при повезивању на Wiki, FreeCAD тренутно не може да преузме Wiki лиÑту макро-а - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Читање метаподатака Ñа {name} није уÑпело - - - - Failed to fetch code for macro '{name}' - Ðије уÑпело преузимање кода за '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Менаџер додатака: радни Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð¸Ñ˜Ðµ уÑпео да Ñе заврши током преузимања {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - За {num_macros} макро је прекорачен је временÑки лимит, {num_failed} током обраде - - - - Addon Manager: a worker process failed to halt ({name}) - Менаџер додатака: радни Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð¸Ñ˜Ðµ уÑпео да Ñе зауÑтави ({name}) - - - - Timeout while fetching metadata for macro {} - ИÑтекло је време за преузимање метаподатака за макро {} - - - - Failed to kill process for macro {}! - - Убијање процеÑа за макро {} није уÑпело! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Ðије уÑпело преузимање ÑтатиÑтике о додатку од {} – Ñамо ће Ñортирање по абецедном реду бити тачно - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - ÐеуÑпешно преузимање о додатку од '{}' -- Ñортирање по оценама неће уÑпети - - - - - Repository URL - Preferences header for custom repositories - URL адреÑа Ñпремишта - - - - Branch name - Preferences header for custom repositories - Име гране - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Прављење резервне копије оригиналне фаÑцикле и поновно клонирање - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Преименовање Git гране није уÑпело Ñа Ñледећом поруком: - - - - Installing - ИнÑталирање - - - - Succeeded - Уcпешно - - - - Failed - ÐеуÑпешно - - - - Update was cancelled - Ðжурирање је отказано - - - - some addons may have been updated - неки додаци Ñу можда ажурирани - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Учитавање информација за {} Ñа wiki Ñтрана FreeCAD Macro Recipes... - - - - Loading page for {} from {}... - Учитавање Ñтранице за {} од {}... - - - - Failed to download data from {} -- received response code {}. - Преузимање података Ñа {} није уÑпело -- примљен је код одговора {}. - - - - Composite view - Раздвојени изглед - - - - Expanded view - Проширен приказ - - - - Compact view - Компактан изглед - - - - Alphabetical - Sort order - По абецедном реду - - - - Last Updated - Sort order - ПоÑледње ажурирано - - - - Date Created - Sort order - Датум креирања - - - - GitHub Stars - Sort order - GitHub звезде - - - - Score - Sort order - Оцена - - - - Std_AddonMgr - - - &Addon manager - &Менаџер додатака - - - - Manage external workbenches, macros, and preference packs - Управљај Ñпољним радним окружењима, макро-има и пакетима подешавања - - - - AddonInstaller - - - Finished removing {} - Завршено уклањање {} - - - - Failed to remove some files - Уклањање неких датотека није уÑпело - - - - Addons installer - - - Finished updating the following addons - Завршено је ажурирање Ñледећих додатака - - - - Workbench - - - Auto-Created Macro Toolbar - ÐутоматÑки направљена Макро палета алатки - - - - QObject - - - Addon Manager - Менаџер додатака - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.qm deleted file mode 100644 index c0989a04394da48c047a26819c9b4711a247883a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67422 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.ts deleted file mode 100644 index 5b091d0000..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_sv-SE.ts +++ /dev/null @@ -1,2486 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Anpassat kodarkiv - - - - Repository URL - Kodarkiv URL - - - - Branch - Gren - - - - CompactView - - - - Icon - Ikon - - - - - <b>Package Name</b> - <b>Paketnamn</b> - - - - - Version - Version - - - - - Description - Beskrivning - - - - Update Available - Uppdatering tillgänglig - - - - UpdateAvailable - Uppdatering Tillgänglig - - - - DependencyDialog - - - Dependencies - Beroenden - - - - Dependency type - Beroendetyp - - - - Name - Namn - - - - Optional? - Valfri? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Lös beroenden - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Detta Tillägg har följande nödvändiga och valfria beroenden. Du mÃ¥ste installera dem innan detta TIllägg kan användas. - -Vill du att TIlläggshanteraren ska installera dem automatiskt? Välj "Ignorera" för att installera Tillägget utan att installera dess beroenden. - - - - FreeCAD Addons - FreeCAD Tillägg - - - - Required Python modules - Obligatoriska Pythonmoduler - - - - Optional Python modules - Valfria Pythonmoduler - - - - DeveloperModeDialog - - - Addon Developer Tools - Utvecklarverktyg För Tillägg - - - - Path to Addon - Sökväg till Tillägg - - - - - Browse... - Bläddra... - - - - Metadata - Metadata - - - - Primary branch - Primär gren - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Förklaring till vad detta Tillägg tillhandahÃ¥ller. Visas i Tilläggshanteraren. Det är inte nödvändigt för detta att ange att det är ett tillägg för FreeCAD. - - - - Description - Beskrivning - - - - Discussion URL - Diskussion URL - - - - Icon - Ikon - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantisk (1.2.3-beta) eller CalVer (2022.08.30) stilar stöds - - - - Set to today (CalVer style) - Sätt till idag (CalVer-stil) - - - - - - - (Optional) - (Valfri) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Visas i Tilläggshanterarens lista över TIllägg. Ska inte innehÃ¥lla orded "FreeCAD" och mÃ¥ste vara ett giltigt katalognamn pÃ¥ alla operativsystem som stöds. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - Tips: Eftersom detta visas i FreeCADs Tilläggshanterare är det inte nödvändigt att skriva saker som "Detta är ett Tillägg till FreeCAD" -- skriv bara vad Tillägget gör. - - - - Repository URL - Kodarkiv URL - - - - Website URL - Hemsida URL - - - - Documentation URL - Dokumentation URL - - - - Addon Name - Tilläggsnamn - - - - Version - Version - - - - (Recommended) - (Rekommenderad) - - - - Minimum Python - Minimiversion Python - - - - (Optional, only 3.x version supported) - (Valfri, endast version 3.x stöds) - - - - Detect... - Upptäck... - - - - Addon Contents - Tillägg InnehÃ¥ll - - - - Dialog - - - Addon Manager - Tilläggshanterare - - - - Edit Tags - Redigera Taggar - - - - Comma-separated list of tags describing this item: - Kommaseparerad lista med taggar som beskriver detta objekt: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Fortsätt - - - - Cancel - Avbryt - - - - EditDependencyDialog - - - Edit Dependency - Redigera beroende - - - - Dependency Type - Beroendetyp - - - - Dependency - Beroende - - - - Package name, if "Other..." - Paketets namn, om "Andra..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Om detta är ett frivilligt beroende, kommer Tilläggshanteraren att erbjuda att installera det (när det är möjligt), men kommer inte att blockera installationen om användaren väljer att, eller inte kan, installera paketet. - - - - Optional - Valfri - - - - ExpandedView - - - - Icon - Ikon - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - Version - - - - - (tags) - (taggar) - - - - - Description - Beskrivning - - - - - Maintainer - UnderhÃ¥llare - - - - Update Available - Uppdatering tillgänglig - - - - labelSort - labelSort - - - - UpdateAvailable - Uppdatering Tillgänglig - - - - Form - - - Licenses - Licenser - - - - License - Licens - - - - License file - Licensfil - - - - People - Personer - - - - Kind - Sort - - - - Name - Namn - - - - Email - E-post - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD-version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - FreeCAD-versioner Som Stöds - - - - Minimum FreeCAD Version Supported - Minsta Version Av FreeCAD Som Stöds - - - - - Optional - Valfri - - - - Maximum FreeCAD Version Supported - Högsta Version Av FreeCAD Som Stöds - - - - Advanced version mapping... - Avancerad versionsmappning - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Val för tilläggshanteraren - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Om detta alternativ är valt söker tilläggshanteraren efter uppdateringar för installerade tillägg dÃ¥ den startas - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Hämta metadata för makron (cirka 10 MB) - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manuell (inga automatiska uppdateringar) - - - - Daily - Dagligen - - - - Weekly - Veckovis - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Dölj tillägg som enbart stödjer Python 2 - - - - Hide Addons marked Obsolete - Dölj tillägg som har markerats som förÃ¥ldrade - - - - Hide Addons that require a newer version of FreeCAD - Dölj tillägg som kräver en nyare version av FreeCAD - - - - Custom repositories - Custom repositories - - - - Proxy - Proxy - - - - No proxy - Ingen proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - Användardefinierad proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Avancerade alternativ - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Installera - - - - Uninstall - Avinstallera - - - - Update - Uppdatera - - - - Run Macro - Kör makro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Hantera Python-beroenden - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Paketnamn - - - - Installed version - Installerad version - - - - Available version - Tillgänglig version - - - - Used by - Används av - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Uppdatera alla tillgängliga - - - - SelectFromList - - - Dialog - Dialog - - - - TextLabel - TextLabel - - - - UpdateAllDialog - - - Updating Addons - Uppdaterar tillägg - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Makro - - - - Preference Pack - Preference Pack - - - - Workbench - Arbetsbänk - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Bläddra... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Underkatalog - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Ikon - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Beroenden... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Annan metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Version - - - - Description - Beskrivning - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantisk (1.2.3-beta) eller CalVer (2022.08.30) stilar stöds - - - - Set to today (CalVer style) - Sätt till idag (CalVer-stil) - - - - Display Name - Visningsnamn - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Lägg till knapp? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Ja - - - - No - Nej - - - - Never - Aldrig - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Upphovsrättsinformation - - - - Copyright holder: - Upphovsrättsinnehavare: - - - - Copyright year: - UpphovsrättsÃ¥r: - - - - personDialog - - - Add Person - Lägg till person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Namn: - - - - Email: - E-post: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Användarnamn - - - - Password - Lösenord - - - - selectLicenseDialog - - - Select a license - Välj en licens - - - - About... - Om... - - - - License name: - Licensnamn: - - - - Path to license file: - Sökväg till licensfil: - - - - (if required by license) - (if required by license) - - - - Browse... - Bläddra... - - - - Create... - Skapa... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - FrÃ¥ga varje gÃ¥ng - - - - toolbar_button - - - - Add button? - Lägg till knapp? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Ja - - - - No - Nej - - - - Never - Aldrig - - - - AddonsInstaller - - - Starting up... - Startar upp... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Tilläggshanterare - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Starta om nu - - - - Restart later - Starta om senare - - - - - Refresh local cache - Uppdatera lokal cache - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Uppdaterar cache... - - - - - Checking for updates... - Söker efter uppdateringar... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Stäng - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - - - - Maintainer - UnderhÃ¥llare - - - - - - - Author - Upphovsman - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Uppdatera - - - - Updating... - Uppdaterar... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Bekräfta borttagning - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Tar bort {} - - - - - Uninstall complete - Avinstallation slutförd - - - - - Uninstall failed - Avinstallation misslyckades - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installerad den {date} - - - - - - - Installed - Installerad - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installationsplats - - - - Repository URL - Kodarkiv URL - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Inaktiverad - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Install - Installera - - - - Uninstall - Avinstallera - - - - Enable - Aktivera - - - - Disable - Avaktivera - - - - - Check for update - Check for update - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Kör - - - - Change branch... - Change branch... - - - - Return to package list - Tillbaka till paketlistan - - - - Checking connection - Kontrollerar anslutning - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Anslutningen misslyckades - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Annat... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Plats för ny licensfil - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Det gick inte att installera makro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automatisk - - - - - Workbench - Arbetsbänk - - - - Addon - Tillägg - - - - Python - Python - - - - Yes - Ja - - - - Internal Workbench - Intern arbetsbänk - - - - External Addon - Externt tillägg - - - - Python Package - Python Package - - - - - Other... - Annat... - - - - Too many to list - För mÃ¥nga för att lista - - - - - - - - - Missing Requirement - Krav ej uppfyllda - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installerar beroenden - - - - - Cannot execute Python - Kan inte köra Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Avbryter - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installationen misslyckades - - - - Failed to install {} - Det gick inte att installera {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - Ett makro installerat med FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Kör - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Ogiltig metadata i fil {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Namn - - - - Class - Klass - - - - Description - Beskrivning - - - - Subdirectory - Underkatalog - - - - Files - Filer - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Installera Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installationen misslyckades - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Välj en ikonfil för detta paket - - - - Filter is valid - Filtret är giltigt - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Sök... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Taggar - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Uppdatering tillgänglig - - - - - Pending restart - Väntande omstart - - - - - DISABLED - INAKTIVERAD - - - - Installed version - Installerad version - - - - Unknown version - Okänd version - - - - Installed on - Installerad den - - - - Available version - Tillgänglig version - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Vilken som - - - - Macro - Makro - - - - Preference Pack - Preference Pack - - - - Installation Status - Installation Status - - - - Not installed - Inte installerad - - - - Filter - Filter - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - Det finns lokala ändringar - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Kan inte hämta koden för detta makro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - Ett okänt fel har uppstÃ¥tt - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Tog bort extra installerad fil {} - - - - Error while trying to remove extra installed file {} - Fel vid försök att ta bort extra installerad fil {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Kodarkiv URL - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installerar - - - - Succeeded - Succeeded - - - - Failed - Misslyckades - - - - Update was cancelled - Uppdateringen avbröts - - - - some addons may have been updated - vissa tillägg kan ha uppdaterats - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Tog bort {} - - - - Failed to remove some files - Det gick inte att ta bort nÃ¥gra filer - - - - Addons installer - - - Finished updating the following addons - Uppdatering av följande tillägg slutfördes - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Tilläggshanterare - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_tr.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_tr.qm deleted file mode 100644 index e412bc823e8f29f8130a221689bcb939d84d17ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67980 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 - - - - AddCustomRepositoryDialog - - - Custom repository - Özel depo - - - - Repository URL - Depo URL' si - - - - Branch - Dal - - - - CompactView - - - - Icon - Simge - - - - - <b>Package Name</b> - <b>Paket Adı</b> - - - - - Version - Sürüm - - - - - Description - Açıklama - - - - Update Available - Güncelleme Mevcut - - - - UpdateAvailable - Güncelleme Mevcut - - - - DependencyDialog - - - Dependencies - Bağımlılıklar - - - - Dependency type - Bağımlılık türü - - - - Name - Isim - - - - Optional? - İsteÄŸe baÄŸlı? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Bağımlılıkları Çöz - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Bu Eklenti aÅŸağıdaki gerekli ve isteÄŸe baÄŸlı bağımlılıklara sahiptir. Bu Eklentinin kullanılabilmesi için bunları yüklemeniz gerekir. - -Eklenti Yöneticisinin bunları otomatik olarak kurmasını istiyor musunuz? Eklentiyi bağımlılıklar olmadan kurmak için " Yoksay " seçin. - - - - FreeCAD Addons - FreeCAD Eklentileri - - - - Required Python modules - Gerekli Python modülleri - - - - Optional Python modules - İsteÄŸe baÄŸlı Python modülleri - - - - DeveloperModeDialog - - - Addon Developer Tools - Eklenti GeliÅŸtirici Araçları - - - - Path to Addon - Eklentiyi giden yol - - - - - Browse... - Gözat... - - - - Metadata - Üst veri - - - - Primary branch - Birincil dal - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Bu Eklentinin neler saÄŸladığının açıklaması. Eklenti Yöneticisinde görüntülenir. Bunun için bunun bir FreeCAD Eklentisi olduÄŸunu belirtmemize gerek yoktur. - - - - Description - Açıklama - - - - Discussion URL - Tartışma URL'si - - - - Icon - Simge - - - - Bugtracker URL - Hata İzleyici URL'si - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) ya da CalVer (2022.08.30) stilleri desteklenir - - - - Set to today (CalVer style) - Bugüne ayarla (CalVer stili) - - - - - - - (Optional) - (IsteÄŸe baÄŸlı) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - BENIOKU URL'si - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Depo URL' si - - - - Website URL - Web Sitesi URL’si - - - - Documentation URL - Döküman URL'si - - - - Addon Name - Eklenti Adı - - - - Version - Sürüm - - - - (Recommended) - (Önerilen) - - - - Minimum Python - Min. Python - - - - (Optional, only 3.x version supported) - (İsteÄŸe baÄŸlı, yalnızca 3.x sürümü desteklenir) - - - - Detect... - Algıla... - - - - Addon Contents - Eklenti İçeriÄŸi - - - - Dialog - - - Addon Manager - Eklenti Yöneticisi - - - - Edit Tags - Etiketleri Düzenle - - - - Comma-separated list of tags describing this item: - Bu öğeyi açıklayan virgülle ayrılmış etiketler listesi: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Devam - - - - Cancel - İptal - - - - EditDependencyDialog - - - Edit Dependency - Bağımlılığı Düzenle - - - - Dependency Type - Bağımlılığı Biçimi - - - - Dependency - Bağımlılık - - - - Package name, if "Other..." - Paket adı, eÄŸer "DiÄŸer..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - IsteÄŸe baÄŸlı - - - - ExpandedView - - - - Icon - Simge - - - - - <h1>Package Name</h1> - <h1>Paket Adı</h1> - - - - - Version - Sürüm - - - - - (tags) - (etiketler) - - - - - Description - Açıklama - - - - - Maintainer - GeliÅŸtirici - - - - Update Available - Güncelleme Mevcut - - - - labelSort - labelSort - - - - UpdateAvailable - Güncelleme Mevcut - - - - Form - - - Licenses - Lisanslar - - - - License - Lisans - - - - License file - Lisans dosyası - - - - People - KiÅŸiler - - - - Kind - Tür - - - - Name - Isim - - - - Email - E-Posta - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - GeliÅŸmiÅŸ Sürüm EÅŸleme - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Sürümü - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Desteklenen FreeCAD Sürümleri - - - - Minimum FreeCAD Version Supported - Desteklenen En Düşük FreeCAD Sürümü - - - - - Optional - IsteÄŸe baÄŸlı - - - - Maximum FreeCAD Version Supported - Desteklenen En Yüksek FreeCAD Sürümü - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Eklenti yöneticisi seçenekleri - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Makro MetaVerilerini indirin (yaklaşık 10MB) - - - - Cache update frequency - Arabellek güncelleme sıklığı - - - - Manual (no automatic updates) - Elle (otomatik güncellemeler yok) - - - - Daily - Günlük - - - - Weekly - Haftalık - - - - Hide Addons without a license - Lisansa sahip olmayan eklentileri gizle - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Geçersiz olarak iÅŸaretlenmiÅŸ Eklentileri Gizle - - - - Hide Addons that require a newer version of FreeCAD - FreeCAD'in daha yeni bir sürümünü gerektiren Eklentileri Gizle - - - - Custom repositories - Özel depolar - - - - Proxy - Vekil Sunucu - - - - No proxy - Vekil sunucu yok - - - - User system proxy - Kullanıcı sistem vekil sunucusu - - - - User-defined proxy: - Kullanıcı tanımlı vekil sunucu: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - GeliÅŸmiÅŸ seçenekler - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Eklenti geliÅŸtirici modu - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Yükle - - - - Uninstall - Kaldır - - - - Update - Güncelle - - - - Run Macro - Makro Çalıştır - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Python Bağımlılıklarını Yönet - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Paket adı - - - - Installed version - Kurulu sürüm - - - - Available version - Bulunan sürüm - - - - Used by - Kullanıldı - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Tüm uygun eklentileri güncelle - - - - SelectFromList - - - Dialog - Pencere - - - - TextLabel - MetinEtiketi - - - - UpdateAllDialog - - - Updating Addons - Eklentiler güncellenyor - - - - Updating out-of-date addons... - Güncel olmayan eklentilerin güncellenmesi... - - - - addContentDialog - - - Content Item - İçerik öğeleri - - - - Content type: - İçerik tipi: - - - - Macro - Makro - - - - Preference Pack - Ön tanımlar paketi - - - - Workbench - Tezgah - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Ana makro dosyası - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Gözat... - - - - Preference Pack Name - Tercih Paketi Adı - - - - Workbench class name - Tezgah sınıfı adı - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Alt dizin - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Simge - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Etiketler... - - - - Dependencies... - Bağımlılık... - - - - FreeCAD Versions... - FreeCAD Sürümü... - - - - Other Metadata - DiÄŸer meta veriler - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Sürüm - - - - Description - Açıklama - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) ya da CalVer (2022.08.30) stilleri desteklenir - - - - Set to today (CalVer style) - Bugüne ayarla (CalVer stili) - - - - Display Name - İsmi Görüntüle - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - TuÅŸ ekle? - - - - Add a toolbar button for this macro? - Bu makro için bir araç çubuÄŸu düğmesi eklensin mi? - - - - Yes - Evet - - - - No - Hayır - - - - Never - Asla - - - - change_branch - - - Change Branch - Branch DeÄŸiÅŸtir - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Telif Hakkı Bilgisi - - - - Copyright holder: - Telif hakkı sahibi: - - - - Copyright year: - Telif Hakkı Yılı: - - - - personDialog - - - Add Person - KiÅŸi Ekle - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - GeliÅŸtirici, bu projede geçerli taahhüt eriÅŸimine sahip olan kiÅŸidir. Bir yazar, kredi vermek istediÄŸiniz herhangi bir kiÅŸidir. - - - - Name: - Adı: - - - - Email: - E-Posta: - - - - Email is required for maintainers, and optional for authors. - E-posta, geliÅŸtiriciler için gereklidir, yazarlar için isteÄŸe baÄŸlıdır. - - - - proxy_authentication - - - Proxy login required - Vekil sunucu giriÅŸi gerekli - - - - Proxy requires authentication - Vekil sunucu kimlik doÄŸrulaması gerektiriyor - - - - Proxy: - Vekil Sunucu: - - - - Placeholder for proxy address - Vekil sunucu adresi için yer tutucu - - - - Realm: - EriÅŸim Alanı: - - - - Placeholder for proxy realm - Proxy alanı için yer tutucu - - - - Username - Kullanıcı adı - - - - Password - Åžifre - - - - selectLicenseDialog - - - Select a license - Bir lisans seçin - - - - About... - Hakkında... - - - - License name: - Lisans adı: - - - - Path to license file: - Lisans dosyasının yolu: - - - - (if required by license) - (lisans gerektiriyorsa) - - - - Browse... - Gözat... - - - - Create... - OluÅŸtur... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Araç ÇubuÄŸunu Seç - - - - Select a toolbar to add this macro to: - Bu makroyu eklemek için bir araç çubuÄŸu seçin: - - - - Ask every time - Her seferinde sor - - - - toolbar_button - - - - Add button? - TuÅŸ ekle? - - - - Add a toolbar button for this macro? - Bu makro için bir araç çubuÄŸu düğmesi eklensin mi? - - - - Yes - Evet - - - - No - Hayır - - - - Never - Asla - - - - AddonsInstaller - - - Starting up... - BaÅŸlatılıyor... - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Eklenti Yöneticisi - - - - You must restart FreeCAD for changes to take effect. - DeÄŸiÅŸikliklerin uygulanması için FreeCAD' ı yeniden baÅŸlatmalısınız. - - - - Restart now - Åžimdi yeniden baÅŸlat - - - - Restart later - Daha sonra yeniden baÅŸlat - - - - - Refresh local cache - Yerel önbelleÄŸi yenile - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Önbellek güncelleniyor... - - - - - Checking for updates... - Güncellemeler kontrol ediliyor... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Kapat - - - - Update all addons - Tüm Eklentileri Güncelle - - - - Check for updates - Güncellemeleri denetle - - - - Python dependencies... - Python gereksinimleri... - - - - Developer tools... - GeliÅŸtirici araçları.... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - Güncelleme Mevcut DeÄŸil - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - - - - Maintainer - GeliÅŸtirici - - - - - - - Author - Yazar - - - - New Python Version Detected - Yeni Python Sürümü Tespit Edildi - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - İşleminiz yapılıyor, Lütfen bekleyiniz... - - - - - Update - Güncelle - - - - Updating... - Güncelleniyor... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Kaldırmayı onayla - - - - Are you sure you want to uninstall {}? - {} kaldırmak istediÄŸinizden emin misiniz? - - - - - - Removing Addon - Eklentiyi Kaldırma - - - - Removing {} - {} kaldırılıyor - - - - - Uninstall complete - Kaldırma iÅŸlemi tamamlandı - - - - - Uninstall failed - Kaldırma iÅŸlemi baÅŸarısız oldu - - - - Version {version} installed on {date} - Sürüm {version}, {date} tarihinde yüklendi - - - - Version {version} installed - Sürüm {version} yüklendi - - - - Installed on {date} - {date} tarihinde yüklendi - - - - - - - Installed - Yüklendi - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git etiketi '{}' kontrol edildi, güncelleme mümkün deÄŸil - - - - Update check in progress - Güncellemelerin kontrol edilmesi devam ediyor - - - - Installation location - Kurulum konumu - - - - Repository URL - Depo URL' si - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Devre dışı - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - BaÅŸarılı - - - - Install - Yükle - - - - Uninstall - Kaldır - - - - Enable - EtkinleÅŸtir - - - - Disable - Devre dışı - - - - - Check for update - Güncellemeleri kontrol et - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Çalıştırmak - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - BaÄŸlantı kontrol ediliyor - - - - Checking for connection to GitHub... - Github baÄŸlantısı kontrol ediliyor... - - - - Connection failed - BaÄŸlantı baÅŸarısız oldu - - - - Missing dependency - Eksik bağımlılık - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - DiÄŸer... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Otomatik - - - - - Workbench - Tezgah - - - - Addon - Eklenti - - - - Python - Python - - - - Yes - Evet - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - DiÄŸer... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Bağımlılıklar kuruluyor - - - - - Cannot execute Python - Python çalıştırılamıyor - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Yürütülebilir Python dosyanız otomatik olarak bulunamadı veya yol yanlış ayarlanmış. Lütfen Python yolu için Eklenti Yöneticisi tercihlerini kontrol edin. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Paket kurulumu baÅŸarısız oldu - - - - See Report View for detailed failure log. - Ayrıntılı hata raporu için Rapor Görünümü'ne bakın. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - İptal Ediliyor - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Kurulum BaÅŸarısız Oldu - - - - Failed to install {} - Yükleme baÅŸarısız {} - - - - - Create new toolbar - Yeni araç çubuÄŸu oluÅŸtur - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Çalıştırmak - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Isim - - - - Class - Sınıf - - - - Description - Açıklama - - - - Subdirectory - Alt dizin - - - - Files - Dosyalar - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Kurulum BaÅŸarısız Oldu - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Ara... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Sorumlular: - - - - Tags - Etiketler - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Güncel - - - - - - - - Update available - Güncelleme mevcut - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Kurulu sürüm - - - - Unknown version - Bilinmeyen sürüm - - - - Installed on - YüklendiÄŸi konum - - - - Available version - Mevcut sürüm - - - - Filter by... - Filter by... - - - - Addon Type - Eklenti Türü - - - - - Any - Herhangi biri - - - - Macro - Makro - - - - Preference Pack - Ön tanımlar paketi - - - - Installation Status - Kurulum Durumu - - - - Not installed - Yüklenmedi - - - - Filter - Filtre - - - - DANGER: Developer feature - TEHLİKE: GeliÅŸtirici özelliÄŸi - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Son Güncellenme Tarihi - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Depo URL' si - - - - Branch name - Preferences header for custom repositories - Åžube adı - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Kuruluyor - - - - Succeeded - BaÅŸarılı - - - - Failed - BaÅŸarısız - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - GeniÅŸletilmiÅŸ görünüm - - - - Compact view - Kompakt görünüm - - - - Alphabetical - Sort order - Alfabetik - - - - Last Updated - Sort order - Son Güncelleme - - - - Date Created - Sort order - OluÅŸturulma Tarihi - - - - GitHub Stars - Sort order - GitHub Yıldızları - - - - Score - Sort order - Puan - - - - Std_AddonMgr - - - &Addon manager - &Eklenti Yöneticisi - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Bazı dosyalar kaldırılamadı - - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Eklenti Yöneticisi - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_uk.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_uk.qm deleted file mode 100644 index 79b233c328f514b16acf7eb0e3eb3b3756c7a1de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70004 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 rSgxfPX8V - - - - AddCustomRepositoryDialog - - - Custom repository - КориÑтувацький репозиторій - - - - Repository URL - URL репозиторію - - - - Branch - Гілка - - - - CompactView - - - - Icon - Піктограма - - - - - <b>Package Name</b> - <b>Ðазва Додатку</b> - - - - - Version - ВерÑÑ–Ñ - - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Update Available - ÐаÑвні Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - UpdateAvailable - ÐаÑвніÑть ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - DependencyDialog - - - Dependencies - ЗалежноÑті - - - - Dependency type - Тип залежноÑті - - - - Name - Ðазва - - - - Optional? - Ðеобов'Ñзково? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Додаток має наÑтупні обовʼÑзкові та необовʼÑзкові залежноÑті. Ðеобхідно вÑтановити Ñ—Ñ…, перш ніж кориÑтуватиÑÑŒ додатком. - -Хочете, щоб менеджер додатків вÑтановив Ñ—Ñ… автоматично? Виберіть «Ігнорувати», щоб вÑтановити додаток без залежноÑтей. - - - - FreeCAD Addons - Додатки FreeCAD - - - - Required Python modules - Ðеобхідні Python модулі - - - - Optional Python modules - Додаткові Python модулі - - - - DeveloperModeDialog - - - Addon Developer Tools - ІнÑтрументи розробника Додатків - - - - Path to Addon - ШлÑÑ… до Додатка - - - - - Browse... - ОглÑд... - - - - Metadata - Метадані - - - - Primary branch - ОÑновна гілка - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - ПоÑÑненнÑ, що надає цей Додаток. ПоказуєтьÑÑ Ð² Менеджері Додатків. Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ не обов'Ñзково вказувати, що це Додаток FreeCAD. - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Discussion URL - URL-адреÑа диÑкуÑій - - - - Icon - Піктограма - - - - Bugtracker URL - URL-адреÑа багтрекеру - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - ПідтримуютьÑÑ Ñтилі Semantic (1.2.3-beta) або CalVer (2022.08.30) - - - - Set to today (CalVer style) - Ð’Ñтановити дату на Ñьогодні (Ñтиль CalVer) - - - - - - - (Optional) - (Ðеобов'Ñзково) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - ПоказуєтьÑÑ Ð² ÑпиÑку додатків Менеджера Додатків. Ðе повинна міÑтити Ñлова "FreeCAD", Ñ– має бути дійÑним ім'Ñм каталогу на вÑÑ–Ñ… підтримуваних операційних ÑиÑтемах. - - - - README URL - URL-адреÑа README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - ПОРÐДÐ: ОÑкільки це показуєтьÑÑ Ð² межах FreeCAD, в Менеджері Додатків, нема потреби займати міÑце, кажучи щоÑÑŒ на кшталт "Це Додаток FreeCAD..." - проÑто Ñкажіть, що він робить. - - - - Repository URL - URL репозиторію - - - - Website URL - URL-адреÑа веб-Ñайту - - - - Documentation URL - URL-адреÑа документації - - - - Addon Name - Ðазва Додатку - - - - Version - ВерÑÑ–Ñ - - - - (Recommended) - (Рекомендовано) - - - - Minimum Python - Мінімальна верÑÑ–Ñ Python - - - - (Optional, only 3.x version supported) - (Ðеобов'Ñзково, підтримуєтьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ верÑÑ–Ñ 3.x) - - - - Detect... - ВиÑвити... - - - - Addon Contents - ВміÑÑ‚ Додатку - - - - Dialog - - - Addon Manager - Менеджер додатків - - - - Edit Tags - Редагувати Мітки - - - - Comma-separated list of tags describing this item: - Перелік міток через кому, Ñкі опиÑують цей елемент: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - ПІДКÐЗКÐ: Зазвичай теги міÑÑ‚Ñть "Assembly", "FEM", "Mesh", "NURBS" тощо. - - - - Add-on Manager: Warning! - Менеджер додатків: Увага! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Менеджер додатків надає доÑтуп до розширеної бібліотеки кориÑних Ñторонніх розширень FreeCAD. Жодних гарантій не можна робити щодо Ñ—Ñ… безпеки або функціональноÑті. - - - - Continue - Продовжити - - - - Cancel - СкаÑувати - - - - EditDependencyDialog - - - Edit Dependency - Редагувати залежніÑть - - - - Dependency Type - Тип залежноÑті - - - - Dependency - ЗалежніÑть - - - - Package name, if "Other..." - Ðазва пакету, Ñкщо "Інше..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - ПРИМІТКÐ: Якщо вибрано "Інше..." Ñ– назва пакета відÑÑƒÑ‚Ð½Ñ Ð² ALLOWED_PYTHON_PACKAGES.txt, то пакет не буде автоматично вÑтановлений Менеджером доповнень. Ðадішліть PR на <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a>, щоб запроÑити Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÐµÑ‚Ð°. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - Якщо це необов'Ñзкова залежніÑть, ДиÑпетчер доповнень запропонує вÑтановити Ñ—Ñ— (коли це можливо), але не заблокує вÑтановленнÑ, Ñкщо кориÑтувач вирішить не вÑтановлювати пакет або не зможе його вÑтановити. - - - - Optional - Ðеобов'Ñзково - - - - ExpandedView - - - - Icon - Піктограма - - - - - <h1>Package Name</h1> - <h1>Ðазва Додатку</h1> - - - - - Version - ВерÑÑ–Ñ - - - - - (tags) - (теги) - - - - - Description - ÐžÐ¿Ð¸Ñ - - - - - Maintainer - Розробник - - - - Update Available - ДоÑтупне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - labelSort - позначка ÑÐ¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ - - - - UpdateAvailable - ÐаÑвніÑть ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Form - - - Licenses - Ліцензії - - - - License - Ð›Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ - - - - License file - Файл ліцензії - - - - People - Люди - - - - Kind - Тип - - - - Name - Ðазва - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Розширене Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²ÐµÑ€Ñій - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Майбутні верÑÑ–Ñ— Менеджер доповнень FreeCAD буде підтримувати розробників' вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ñ— гілки або тегу Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð· певною верÑією FreeCAD (наприклад, вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñпецифічного тегу Ñк оÑтанньої верÑÑ–Ñ— вашого Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ v0.19, Ñ– Ñ‚. д.) - - - - FreeCAD Version - ВерÑÑ–Ñ FreeCAD - - - - Best-available branch, tag, or commit - Ðайкраще доÑтупна гілка, тег або коміт - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Підтримувані верÑÑ–Ñ— FreeCAD - - - - Minimum FreeCAD Version Supported - Мінімальна верÑÑ–Ñ FreeCAD, що підтримуєтьÑÑ - - - - - Optional - Ðеобов'Ñзково - - - - Maximum FreeCAD Version Supported - МакÑимальна верÑÑ–Ñ FreeCAD, що підтримуєтьÑÑ - - - - Advanced version mapping... - Розширене зіÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²ÐµÑ€Ñій... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Параметри Менеджера Додатків - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Якщо Ñ†Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð°, при запуÑку Менеджера доповнень, -вÑтановлені Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ перевірено на наÑвніÑть оновлень - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Завантажити метадані МакроÑів (приблизно 10 Мб) - - - - Cache update frequency - ЧаÑтота Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐµÑˆÑƒ - - - - Manual (no automatic updates) - Вручну (без автоматичного оновленнÑ) - - - - Daily - Щоденно - - - - Weekly - Ð©Ð¾Ñ‚Ð¸Ð¶Ð´Ð½Ñ - - - - Hide Addons without a license - Приховати Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð±ÐµÐ· ліцензії - - - - Hide Addons with non-FSF Free/Libre license - Приховати Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð· ліцензією non-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Приховати Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð· ліцензіÑми, не Ñхваленими OSI - - - - Hide Addons marked Python 2 Only - Приховати Додатки Ð´Ð»Ñ Python 2 - - - - Hide Addons marked Obsolete - Приховати заÑтарілі Додатки - - - - Hide Addons that require a newer version of FreeCAD - Приховати додатки Ð´Ð»Ñ Ð½Ð¾Ð²Ñ–ÑˆÐ¸Ñ… верÑій FreeCAD - - - - Custom repositories - ВлаÑні репозиторії - - - - Proxy - ПрокÑÑ– - - - - No proxy - Без прокÑÑ–-Ñервера - - - - User system proxy - ВикориÑтовувати ÑиÑтемний - - - - User-defined proxy: - Заданий кориÑтувачем: - - - - Score source URL - URL-адреÑа джерела оцінки - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - URL-адреÑа Ð´Ð»Ñ Ð´Ð°Ð½Ð¸Ñ… про оцінку Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ (див. вікі-Ñторінку Менеджера доповнень Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° хоÑтинг). - - - - Path to Git executable (optional): - ШлÑÑ… до виконуваного Git-файлу (необов'Ñзково): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Додаткові Опції - - - - Activate Addon Manager options intended for developers of new Addons. - Ðктивувати опції Менеджеру Додатків, призначені Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² нових Додатків. - - - - Addon developer mode - Режим розробника додатків - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Видалити вибраний Ð¼Ð°ÐºÑ€Ð¾Ñ Ð°Ð±Ð¾ робоче Ñередовище - - - - Install - Ð’Ñтановити - - - - Uninstall - Видалити - - - - Update - Оновити - - - - Run Macro - ЗапуÑтити ÐœÐ°ÐºÑ€Ð¾Ñ - - - - Change branch - Змінити гілку - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾ÑÑ‚Ñми Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - ÐаÑтупні пакети Python було вÑтановлено локально Менеджером Додатків Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей. ШлÑÑ… до пакетів: - - - - Package name - Ðазва пакету - - - - Installed version - Ð’Ñтановлена верÑÑ–Ñ - - - - Available version - ДоÑтупна верÑÑ–Ñ - - - - Used by - ВикориÑтовуєтьÑÑ - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Знак (*) у Ñтовпці "ВикориÑтовуєтьÑÑ Ð²" вказує на необов'Ñзкову залежніÑть. Зауважте, що в Ñтовпці "ВикориÑтовуєтьÑÑ Ð²" показані прÑмо імпортовані пакети. Інші пакети Python, необхідні Ð´Ð»Ñ Ñ†Ð¸Ñ… пакетів, також можуть бути вÑтановлені. - - - - Update all available - ДоÑтупне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - SelectFromList - - - Dialog - Діалогове вікно - - - - TextLabel - ТекÑтовийÐÐ°Ð´Ð¿Ð¸Ñ - - - - UpdateAllDialog - - - Updating Addons - ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½ÑŒ - - - - Updating out-of-date addons... - ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ñтарілих доповнень... - - - - addContentDialog - - - Content Item - Елемент вміÑту - - - - Content type: - Тип вміÑту: - - - - Macro - ÐœÐ°ÐºÑ€Ð¾Ñ - - - - Preference Pack - Ðабір Ðалаштувань - - - - Workbench - Робочі Ñередовища - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Якщо це єдине, що Ñ” в доповненні, вÑÑ– інші метадані можуть бути уÑпадковані з верхнього рівнÑ, Ñ– Ñ—Ñ… не потрібно вказувати тут. - - - - This is the only item in the Addon - Це єдиний елемент у доповненні - - - - Main macro file - ОÑновний файл макроÑу - - - - The file with the macro's metadata in it - Файл з метаданими макроÑу - - - - - - Browse... - ОглÑд... - - - - Preference Pack Name - Ð†Ð¼Ê¼Ñ Ðабору Ðалаштувань - - - - Workbench class name - Ðазва клаÑу робочого проÑтору - - - - Class that defines "Icon" data member - КлаÑ, що визначає елемент "Icon" - - - - Subdirectory - Підкаталог - - - - Optional, defaults to name of content item - Ðеобов'Ñзково, за замовчуваннÑм назва елемента вміÑту - - - - Icon - Піктограма - - - - Optional, defaults to inheriting from top-level Addon - Ðеобов'Ñзково, за замовчуваннÑм уÑпадковуєтьÑÑ Ð²Ñ–Ð´ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð²ÐµÑ€Ñ…Ð½ÑŒÐ¾Ð³Ð¾ Ñ€Ñ–Ð²Ð½Ñ - - - - Tags... - Мітки... - - - - Dependencies... - ЗалежноÑті... - - - - FreeCAD Versions... - FreeCAD верÑÑ–Ñ—... - - - - Other Metadata - Інші метадані - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - ВідображаєтьÑÑ Ñƒ ÑпиÑку Менеджера доповнень. Ðе може міÑтити Ñлово "FreeCAD". - - - - Version - ВерÑÑ–Ñ - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - ПідтримуютьÑÑ Ñтилі Semantic (1.2.3-beta) або CalVer (2022.08.30) - - - - Set to today (CalVer style) - Ð’Ñтановити дату на Ñьогодні (Ñтиль CalVer) - - - - Display Name - Відображуване ім'Ñ - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Будь-Ñкі полÑ, залишені незаповненими, заповнюютьÑÑ Ð· метаданих Додатку верхнього рівнÑ, тому технічно вÑÑ– вони Ñ” необов'Ñзковими. Ð”Ð»Ñ Ð”Ð¾Ð´Ð°Ñ‚ÐºÑ–Ð² з декількох елементів, кожен з них повинен мати унікальну Ðазву та ОпиÑ. - - - - add_toolbar_button_dialog - - - Add button? - Додати кнопку? - - - - Add a toolbar button for this macro? - Додати кнопку на панель Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку цього макроÑу? - - - - Yes - Так - - - - No - ÐÑ– - - - - Never - ÐÑ– (Ðе питати більше) - - - - change_branch - - - Change Branch - Змінити гілку - - - - Change to branch: - Перейти до гілки: - - - - copyrightInformationDialog - - - Copyright Information - Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ авторÑькі права - - - - Copyright holder: - ВлаÑник авторÑьких прав: - - - - Copyright year: - Рік авторÑьких прав: - - - - personDialog - - - Add Person - Додати перÑону - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Супроводжувач - це оÑоба з поточним доÑтупом до коммітів у цьому проєкт. Ðвтор - це будь-хто інший, Ð´Ð»Ñ ÐºÐ¾Ð³Ð¾ ви хочете вказати авторÑтво. - - - - Name: - Ðазва: - - - - Email: - E-mail: - - - - Email is required for maintainers, and optional for authors. - Електронна пошта Ñ” обов'Ñзковою Ð´Ð»Ñ Ñупроводжувачів та необов'Ñзковою Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ñ–Ð². - - - - proxy_authentication - - - Proxy login required - Потрібен вхід через прокÑÑ–-Ñервер - - - - Proxy requires authentication - ПрокÑÑ–-Ñервер вимагає автентифікації - - - - Proxy: - ПрокÑÑ–-Ñервер: - - - - Placeholder for proxy address - Введіть тут адреÑу прокÑÑ–-Ñервера - - - - Realm: - МіÑце: - - - - Placeholder for proxy realm - МіÑце Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐºÑÑ–-Ñервера - - - - Username - Ð†Ð¼Ê¼Ñ ÐºÐ¾Ñ€Ð¸Ñтувача - - - - Password - Пароль - - - - selectLicenseDialog - - - Select a license - Оберіть ліцензію - - - - About... - Про... - - - - License name: - Ðазва ліцензії: - - - - Path to license file: - ШлÑÑ… до файлу ліцензії: - - - - (if required by license) - (Ñкщо вимагаєтьÑÑ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ”ÑŽ) - - - - Browse... - ОглÑд... - - - - Create... - Створити... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Виберіть Панель ІнÑтрументів - - - - Select a toolbar to add this macro to: - Виберіть Панель ІнÑтрументів до Ñкої додати макроÑ: - - - - Ask every time - Запитувати щоразу - - - - toolbar_button - - - - Add button? - Додати кнопку? - - - - Add a toolbar button for this macro? - Додати кнопку на панель Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку цього макроÑу? - - - - Yes - Так - - - - No - ÐÑ– - - - - Never - ÐÑ– (Ðе питати більше) - - - - AddonsInstaller - - - Starting up... - ЗапуÑк... - - - - Worker process {} is taking a long time to stop... - Зупинка запущеного процеÑу {} займає багато чаÑу... - - - - Previous cache process was interrupted, restarting... - - Попередній Ð¿Ñ€Ð¾Ñ†ÐµÑ ÐºÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ перервано, перезапуÑк... - - - - - Custom repo list changed, forcing recache... - - Змінено ÑпиÑок кориÑтувацьких репозиторіїв, що призводить до повторного кешуваннÑ... - - - - - Addon manager - Менеджер доповнень - - - - You must restart FreeCAD for changes to take effect. - Ðеобхідно перезапуÑтити FreeCAD, щоб зміни набрали Ñили. - - - - Restart now - Перезавантажити зараз - - - - Restart later - Перезавантажити пізніше - - - - - Refresh local cache - Оновити локальний кеш - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐµÑˆÑƒ... - - - - - Checking for updates... - Перевірка оновлень... - - - - Temporary installation of macro failed. - Ðе вдалоÑÑ Ð²Ñтановити макроÑ. - - - - - Close - Закрити - - - - Update all addons - Оновити вÑÑ– Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ - - - - Check for updates - Перевірити наÑвніÑть оновлень - - - - Python dependencies... - Python залежноÑті... - - - - Developer tools... - ІнÑтрументи розробника... - - - - Apply %n available update(s) - ЗаÑтоÑувати %n доÑтупних оновлень - - - - No updates available - Оновлень немає - - - - - - Cannot launch a new installer until the previous one has finished. - Ðеможливо запуÑтити нове вÑтановленнÑ, поки не завершено попереднє. - - - - - - - Maintainer - Розробник - - - - - - - Author - Ðвтор - - - - New Python Version Detected - ВиÑвлено нову верÑÑ–ÑŽ Python - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Схоже, що Ñ†Ñ Ð²ÐµÑ€ÑÑ–Ñ Python вперше викориÑтовуєтьÑÑ Ð· Менеджером доповнень. Чи бажаєте ви вÑтановити Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾ ті ж Ñамі автоматично вÑтановлені залежноÑті? - - - - Processing, please wait... - Обробка, зачекайте будь лаÑка... - - - - - Update - Оновити - - - - Updating... - ОновленнÑ... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - QtNetwork не можна імпортувати - Ñ—Ñ— не вÑтановлено у ÑиÑтемі. Ваш поÑтачальник може мати пакет Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— залежноÑті (чаÑто його називають ""python3-pyside2.qtnetwork"") - - - - Failed to convert the specified proxy port '{}' to a port number - Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ вказаний прокÑÑ–-порт '{}' на номер порту - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Помилка параметра: вÑтановлено взаємовиключні параметри прокÑÑ–. Ð¡ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð´Ð¾ налаштувань за замовчуваннÑм. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Помилка параметра: вказано прокÑÑ– кориÑтувача, але прокÑÑ– не надано. Ð¡ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð´Ð¾ значень за замовчуваннÑм. - - - - Addon Manager: Unexpected {} response from server - Менеджер доповнень: Ðеочікувана {} відповідь від Ñервера - - - - Error with encrypted connection - Помилка із зашифрованим з'єднаннÑм - - - - - - Confirm remove - Підтвердіть Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ - - - - Are you sure you want to uninstall {}? - Ви впевнені, що хочете видалити {}? - - - - - - Removing Addon - Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ - - - - Removing {} - Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ {} - - - - - Uninstall complete - Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¾ - - - - - Uninstall failed - Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ - - - - Version {version} installed on {date} - ВерÑÑ–Ñ {version} вÑтановлена {date} - - - - Version {version} installed - ВерÑÑ–Ñ {version} вÑтановлена - - - - Installed on {date} - Ð’Ñтановлено {date} - - - - - - - Installed - Ð’Ñтановлено - - - - Currently on branch {}, name changed to {} - Ðаразі на гілці {}, назву змінено на {} - - - - Git tag '{}' checked out, no updates possible - Git-тег '{}' перевірено, Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ñ– - - - - Update check in progress - Триває перевірка оновлень - - - - Installation location - МіÑце вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Repository URL - URL репозиторію - - - - Changed to branch '{}' -- please restart to use Addon. - Змінено на гілку '{}' -- будь лаÑка, перезапуÑтіть, щоб викориÑтовувати доповненнÑ. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ оновлено. ПерезапуÑтіть FreeCAD, щоб побачити зміни. - - - - Disabled - Вимкнено - - - - Currently on branch {}, update available to version {} - Ðаразі на гілці {} доÑтупне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ верÑÑ–Ñ— {} - - - - Update available to version {} - ДоÑтупне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ верÑÑ–Ñ— {} - - - - This is the latest version available - Це оÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупна верÑÑ–Ñ - - - - WARNING: This addon is obsolete - УВÐГÐ: Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð·Ð°Ñтаріле - - - - WARNING: This addon is Python 2 only - УВÐГÐ: Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Python 2 - - - - WARNING: This addon requires FreeCAD {} - УВÐГÐ: Ð”Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ цього Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±ÐµÐ½ FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - УВÐГÐ: Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– вÑтановлено, але вимкнено. ВикориÑтовуйте кнопку 'увімкнути' Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ ввімкненнÑ. - - - - This Addon will be enabled next time you restart FreeCAD. - Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ ввімкнено під Ñ‡Ð°Ñ Ð½Ð°Ñтупного перезапуÑку FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ вимкнено під Ñ‡Ð°Ñ Ð½Ð°Ñтупного перезапуÑку FreeCAD. - - - - - - Success - УÑпішно - - - - Install - Ð’Ñтановити - - - - Uninstall - Видалити - - - - Enable - Ввімкнути - - - - Disable - Вимкнути - - - - - Check for update - Перевірити наÑвніÑть оновлень - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - ЗапуÑтити - - - - Change branch... - Змінити гілку... - - - - Return to package list - ПовернутиÑÑŒ до ÑпиÑку пакетів - - - - Checking connection - Перевірка Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ - - - - Checking for connection to GitHub... - Перевірка Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ GitHub... - - - - Connection failed - Ðе вдалоÑÑ Ð²Ñтановити з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ - - - - Missing dependency - ВідÑÑƒÑ‚Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ñ–Ñть - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Ðе вдалоÑÑ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸ QtNetwork - дивітьÑÑ ÐŸÐµÑ€ÐµÐ³Ð»Ñд звіту Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð¸Ñ†ÑŒ. Менеджер доповнень недоÑтупний. - - - - Other... - For providing a license other than one listed - Інше... - - - - Select the corresponding license file in your Addon - Виберіть відповідний файл ліцензії у вашому доповненні - - - - Location for new license file - Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ файлу ліцензії - - - - Received {} response code from server - Отримано {} код відповіді від Ñервера - - - - Failed to install macro {} - Ðе вдалоÑÑ Ð²Ñтановити Ð¼Ð°ÐºÑ€Ð¾Ñ {} - - - - Failed to create installation manifest file: - - Ðе вдалоÑÑ Ñтворити файл маніфеÑту вÑтановленнÑ: - - - - - Unrecognized content kind '{}' - Ðерозпізнаний тип вміÑту '{}' - - - - Unable to locate icon at {} - Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ піктограму в {} - - - - Select an icon file for this content item - Виберіть файл піктограми Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ елемента вміÑту - - - - - - {} is not a subdirectory of {} - {} не Ñ” підкаталогом {} - - - - Select the subdirectory for this content item - Вибери підкаталог Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ елемента вміÑту - - - - Automatic - Ðвтоматичний - - - - - Workbench - Робочі Ñередовища - - - - Addon - Додаток - - - - Python - Python - - - - Yes - Так - - - - Internal Workbench - Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ñ€Ð¾Ð±Ð¾Ñ‡Ð° облаÑть - - - - External Addon - Зовнішнє Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ - - - - Python Package - Пакет Python - - - - - Other... - Інше... - - - - Too many to list - Забагато Ð´Ð»Ñ ÑпиÑку - - - - - - - - - Missing Requirement - ВідÑутні вимоги - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ '{}' вимагає '{}', Ñке відÑутнє у вашій копії FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ '{}' потребує наÑтупних робочих проÑторів, Ñкі відÑутні у вашій копії FreeCAD: - - - - Press OK to install anyway. - Ð”Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² будь-Ñкому разі натиÑніть OK. - - - - - Incompatible Python version - ÐеÑуміÑна верÑÑ–Ñ Python - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Ð”Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ цього Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ñ– пакети Python, Ñкі не вÑтановлені й не можуть бути вÑтановлені автоматично. Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð²Ð¸ повинні вÑтановити наÑтупні пакети Python вручну: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Цей Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ (або одна з його залежноÑтей) потребує Python {}.{}, а у вашій ÑиÑтемі запущено {}.{}. Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑкаÑовано. - - - - Optional dependency on {} ignored because it is not in the allow-list - Ðеобов'Ñзкова залежніÑть від {} ігноруєтьÑÑ, оÑкільки Ñ—Ñ— немає у ÑпиÑку дозволених - - - - - Installing dependencies - Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей - - - - - Cannot execute Python - Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Ðе вдалоÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾ знайти виконуваний файл Python, або шлÑÑ… до нього вказано неправильно. Будь лаÑка, перевірте шлÑÑ… до Python в параметрах Менеджера доповнень. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Ðе вдалоÑÑ Ð²Ñтановити залежноÑті. Ð’Ñе одно продовжити вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ {}? - - - - - Cannot execute pip - Ðеможливо виконати pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ pip, Ñкий може бути відÑутнім у вашому пакеті Python. ПереконайтеÑÑ, що у вашій ÑиÑтемі вÑтановлено pip, Ñ– повторіть Ñпробу. Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ команду: - - - - - Continue with installation of {} anyway? - Продовжити вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ {} у будь-Ñкому випадку? - - - - - Package installation failed - Ðе вдалоÑÑ Ð²Ñтановити пакет - - - - See Report View for detailed failure log. - Докладний журнал помилок дивітьÑÑ Ñƒ Звіті. - - - - Installing Addon - Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ - - - - Installing FreeCAD Addon '{}' - Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ FreeCAD Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ '{}' - - - - Cancelling - СкаÑÑƒÐ²Ð°Ð½Ð½Ñ - - - - Cancelling installation of '{}' - СкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ '{}' - - - - {} was installed successfully - {} було уÑпішно вÑтановлено - - - - - Installation Failed - Помилка вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Failed to install {} - Ðе вдалоÑÑ Ð²Ñтановити {} - - - - - Create new toolbar - Створити нову панель інÑтрументів - - - - - A macro installed with the FreeCAD Addon Manager - МакроÑ, вÑтановлений за допомогою ДиÑпетчера доповнень FreeCAD - - - - - Run - Indicates a macro that can be 'run' - ЗапуÑтити - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Ðе вдаєтьÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дані з GitHub: перевірте Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÑ€Ð½ÐµÑ‚-з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ‚Ð° прокÑÑ– та Ñпробуйте ще раз. - - - - XML failure while reading metadata from file {} - Помилка XML під Ñ‡Ð°Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð½Ð¸Ñ… з файлу {} - - - - Invalid metadata in file {} - ÐеприпуÑтимі метадані у файлі {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ПОПЕРЕДЖЕÐÐЯ: ШлÑÑ…, вказаний у метаданих package.xml, не збігаєтьÑÑ Ð· поточною перевіреною гілкою. - - - - Name - Ðазва - - - - Class - ÐšÐ»Ð°Ñ - - - - Description - ÐžÐ¿Ð¸Ñ - - - - Subdirectory - Підкаталог - - - - Files - Файли - - - - Select the folder containing your Addon - Виберіть папку з вашим доповненнÑм - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Ðемає Vermin, ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ—. - - - - Scanning Addon for Python version compatibility - Перевірка Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð½Ð° ÑуміÑніÑть верÑій Python - - - - Minimum Python Version Detected - ВиÑвлено мінімальну верÑÑ–ÑŽ Python - - - - Vermin auto-detected a required version of Python 3.{} - Vermin автоматично визначив необхідну верÑÑ–ÑŽ Python 3.{} - - - - Install Vermin? - Ð’Ñтановити Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Ð”Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ñ…Ñ–Ð´Ð½Ð¾Ñ— верÑÑ–Ñ— Python Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±ÐµÐ½ Vermin (https://pypi.org/project/vermin/). Ð’Ñтановити? - - - - Attempting to install Vermin from PyPi - Спроба вÑтановити Vermin з PyPi - - - - - Installation failed - Помилка вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Ðе вдалоÑÑ Ð²Ñтановити Vermin -- Ð´Ð»Ñ Ð´ÐµÑ‚Ð°Ð»ÐµÐ¹ перевірте звіт. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Ðе вдалоÑÑ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸ Vermin піÑÐ»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - неможливо Ñканувати доповненнÑ. - - - - Select an icon file for this package - Виберіть файл піктограми Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ пакета - - - - Filter is valid - Фільтр дійÑний - - - - Filter regular expression is invalid - РегулÑрний вираз фільтра Ñ” недійÑним - - - - Search... - Шукати... - - - - Click for details about package {} - ÐатиÑніть, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про пакет {} - - - - Click for details about workbench {} - ÐатиÑніть, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про робочий проÑтір {} - - - - Click for details about macro {} - ÐатиÑніть, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð¼Ð°ÐºÑ€Ð¾Ñ {} - - - - Maintainers: - Супровідники: - - - - Tags - Мітки - - - - {} ★ on GitHub - {} ★ на GitHub - - - - No ★, or not on GitHub - Ðемає ★ або немає на GitHub - - - - Created - Створено - - - - Updated - Оновлено - - - - Score: - Оцінка: - - - - - Up-to-date - Ðктуально - - - - - - - - Update available - ДоÑтупне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - - Pending restart - Очікує Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ - - - - - DISABLED - ВИМКÐЕÐО - - - - Installed version - Ð’Ñтановлена верÑÑ–Ñ - - - - Unknown version - Ðевідома верÑÑ–Ñ - - - - Installed on - Ð’Ñтановлено на - - - - Available version - ДоÑтупна верÑÑ–Ñ - - - - Filter by... - Фільтрувати за... - - - - Addon Type - Тип Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ - - - - - Any - Будь-Ñкий - - - - Macro - ÐœÐ°ÐºÑ€Ð¾Ñ - - - - Preference Pack - Ðабір Ðалаштувань - - - - Installation Status - Стан вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Not installed - Ðе вÑтановлено - - - - Filter - Фільтр - - - - DANGER: Developer feature - ÐЕБЕЗПЕКÐ: Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÐ° - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - ÐЕБЕЗПЕКÐ: ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð³Ñ–Ð»Ð¾Ðº призначено Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² Ñ– бета-теÑтерів, Ñ– може призвеÑти до Ð¿Ð¾ÑˆÐºÐ¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ñ–Ð², відÑутноÑті зворотної ÑуміÑноÑті, неÑтабільноÑті, збоїв Ñ–/або передчаÑної теплової Ñмерті вÑеÑвіту. Ви впевнені, що хочете продовжити? - - - - There are local changes - ÐаÑвні локальні зміни - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ПОПЕРЕДЖЕÐÐЯ: Цей репозиторій має нефікÑовані локальні зміни. Ви впевнені, що хочете змінити гілки (тим Ñамим приніÑши зміни)? - - - - Local - Table header for local git ref name - Локально - - - - Remote tracking - Table header for git remote tracking branch name - ДиÑтанційне відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ - - - - Last Updated - Table header for git update date - ОÑтаннє Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Installation of Python package {} failed - Ðе вдалоÑÑ Ð²Ñтановити пакет Python {} - - - - Installation of optional package failed - Ðе вдалоÑÑ Ð²Ñтановити необов'Ñзковий пакет - - - - Installing required dependency {} - Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ñ…Ñ–Ð´Ð½Ð¾Ñ— залежноÑті {} - - - - Installation of Addon {} failed - Помилка вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ {} - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Ðе вдалоÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ файл {} Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ '{}' - - - - Any dependency information in this file will be ignored - Будь-Ñка Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ залежноÑті у цьому файлі буде проігнорована - - - - Unable to open macro wiki page at {} - Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ вікі-Ñторінку макроÑів за адреÑою {} - - - - Unable to fetch the code of this macro. - Ðе вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ код макроÑу. - - - - Unable to retrieve a description from the wiki for macro {} - Ðе вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Ð¾Ð¿Ð¸Ñ Ð· wiki Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñу {} - - - - Unable to open macro code URL {} - Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ URL-адреÑу макроÑу {} - - - - Unable to fetch macro-specified file {} from {} - Ðе вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ файл {}, вказаний у макроÑÑ–, з {} - - - - Could not locate macro-specified file {} (expected at {}) - Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ вказаний макроÑом файл {} (очікувавÑÑ Ð·Ð° адреÑою {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Ðерозпізнаний внутрішній робочий проÑтір '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÐ° доповненнÑ: URL-адреÑа Ñховища, задана у файлі package.xml Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ {} ({}), не відповідає URL-адреÑÑ–, з Ñкої вона була отримана ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÐ° доповненнÑ: гілка репозиторію, зазначена у файлі package.xml Ð´Ð»Ñ Ð½Ð°Ð´Ð±ÑƒÐ´Ð¾Ð²Ð¸ {} ({}), не відповідає гілці, з Ñкої Ñ—Ñ— було отримано ({}) - - - - - Got an error when trying to import {} - Виникла помилка при Ñпробі імпорту {} - - - - An unknown error occurred - СталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка - - - - Could not find addon {} to remove it. - Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ {}, щоб видалити його. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ñкрипту uninstall.py доповненнÑ' не вдалоÑÑ. ÐŸÑ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ... - - - - Removed extra installed file {} - Видалено додатково вÑтановлений файл {} - - - - Error while trying to remove extra installed file {} - Помилка при Ñпробі Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ð³Ð¾ вÑтановленого файлу {} - - - - Error while trying to remove macro file {}: - Помилка при Ñпробі видалити файл макроÑу {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Ðе вдалоÑÑ Ð¿Ñ–Ð´Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ GitHub. Перевірте Ð·Ê¼Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ‚Ð° параметри прокÑÑ–-Ñервера. - - - - WARNING: Duplicate addon {} ignored - УВÐГÐ: Дублікат Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ {} проігноровано - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Виникла помилка при оновленні макроÑів з GitHub, Ñпроба чиÑтої перевірки... - - - - Attempting to do a clean checkout... - Спроба зробити чиÑту перевірку... - - - - Clean checkout succeeded - ЧиÑта перевірка уÑпішно виконана - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ макроÑи з GitHub - Ñпробуйте очиÑтити кеш Менеджера доповнень. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Помилка Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ Wiki, FreeCAD наразі не може отримати ÑпиÑок макроÑів Wiki - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Помилка Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð½Ð¸Ñ… з {name} - - - - Failed to fetch code for macro '{name}' - Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ код Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñу '{name}' - - - - Addon Manager: a worker process failed to complete while fetching {name} - Менеджер доповнень: робочий Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ðµ вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸ під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - З {num_macros} макроÑів {num_failed} завершилиÑÑ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ - - - - Addon Manager: a worker process failed to halt ({name}) - Менеджер доповнень: не вдалоÑÑ Ð·ÑƒÐ¿Ð¸Ð½Ð¸Ñ‚Ð¸ робочий Ð¿Ñ€Ð¾Ñ†ÐµÑ ({name}) - - - - Timeout while fetching metadata for macro {} - Тайм-аут під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¼ÐµÑ‚Ð°Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñу {} - - - - Failed to kill process for macro {}! - - Ðе вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸ Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð´Ð»Ñ Ð¼Ð°ÐºÑ€Ð¾Ñу {}! - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ÑтатиÑтику Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð· {} -- точним буде лише ÑÐ¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° алфавітом - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ оцінку Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð· '{}' -- ÑÐ¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° оцінкою не вдаÑтьÑÑ - - - - - - Repository URL - Preferences header for custom repositories - URL репозиторію - - - - Branch name - Preferences header for custom repositories - Ðазва гілки - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ñ— копії вихідного каталогу та повторне ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - ÐŸÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ–Ð»ÐºÐ¸ git завершилоÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾ з наÑтупним повідомленнÑм: - - - - Installing - Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Succeeded - УÑпішно - - - - Failed - Помилка - - - - Update was cancelled - ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ ÑкаÑовано - - - - some addons may have been updated - деÑкі додатки можуть бути оновлені - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— Ð´Ð»Ñ {} з вікі-Ñторінки рецептів макроÑів FreeCAD... - - - - Loading page for {} from {}... - Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñторінки Ð´Ð»Ñ {} з {}... - - - - Failed to download data from {} -- received response code {}. - Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ дані з {} -- отримано код відповіді {}. - - - - Composite view - Композитний виглÑд - - - - Expanded view - Розширений виглÑд - - - - Compact view - Компактний виглÑд - - - - Alphabetical - Sort order - За алфавітом - - - - Last Updated - Sort order - ОÑтаннє Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - - - - Date Created - Sort order - Дата ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ - - - - GitHub Stars - Sort order - Зірки на Github - - - - Score - Sort order - Оцінка - - - - Std_AddonMgr - - - &Addon manager - &Менеджер доповнень - - - - Manage external workbenches, macros, and preference packs - ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ð¼Ð¸ робочими проÑторами, макроÑами та пакетами налаштувань - - - - AddonInstaller - - - Finished removing {} - Завершено Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ {} - - - - Failed to remove some files - Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ деÑкі файли - - - - Addons installer - - - Finished updating the following addons - Завершено Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ñтупних доповнень - - - - Workbench - - - Auto-Created Macro Toolbar - Ðвтоматично Ñтворено панель інÑтрументів макроÑу - - - - QObject - - - Addon Manager - Менеджер додатків - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_val-ES.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_val-ES.qm deleted file mode 100644 index dea7cac0a918eedbf4ca93b30c5d5f95af957c26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67330 zcmdtL3wWGWwKu-g=H4`EOMz0_GKA8mkff#DB$h(j^h%S4CT%HtsFRsVGITN%W+qKT z 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 - - - - AddCustomRepositoryDialog - - - Custom repository - Custom repository - - - - Repository URL - Repository URL - - - - Branch - Branch - - - - CompactView - - - - Icon - Icona - - - - - <b>Package Name</b> - <b>Package Name</b> - - - - - Version - Versió - - - - - Description - Descripció - - - - Update Available - Update Available - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - Dependencies - - - - Dependency type - Dependency type - - - - Name - Nom - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Descripció - - - - Discussion URL - Discussion URL - - - - Icon - Icona - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Repository URL - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Versió - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Addon Manager - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Add-on Manager: Warning! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - - - - Continue - Continua - - - - Cancel - Cancel·la - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - - Icon - Icona - - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - - Version - Versió - - - - - (tags) - (tags) - - - - - Description - Descripció - - - - - Maintainer - Maintainer - - - - Update Available - Update Available - - - - labelSort - labelSort - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - Licenses - Licenses - - - - License - Llicència - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - Nom - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - - - - Automatically check for updates at start (requires git) - Automatically check for updates at start (requires git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manual (no automatic updates) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons without a license - Hide Addons without a license - - - - Hide Addons with non-FSF Free/Libre license - Hide Addons with non-FSF Free/Libre license - - - - Hide Addons with non-OSI-approved license - Hide Addons with non-OSI-approved license - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Proxy - Proxy - - - - No proxy - Sense servidor intermediari - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Score source URL - Score source URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - - - - Path to Git executable (optional): - Path to Git executable (optional): - - - - The path to the git executable. Autodetected if needed and not specified. - The path to the git executable. Autodetected if needed and not specified. - - - - Advanced Options - Advanced Options - - - - Show option to change branches (requires git) - Show option to change branches (requires git) - - - - Disable git (fall back to ZIP downloads only) - Disable git (fall back to ZIP downloads only) - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Install - - - - Uninstall - Uninstall - - - - Update - Actualitza - - - - Run Macro - Run Macro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Diàleg - - - - TextLabel - EtiquetaText - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Macro - - - - Preference Pack - Preference Pack - - - - Workbench - Banc de treball - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Icona - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Versió - - - - Description - Descripció - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch: - Change to branch: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Nom: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - AddonsInstaller - - - Starting up... - Starting up... - - - - Loading addon information - Loading addon information - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - Refresh local cache - - - - Updating cache... - Updating cache... - - - - - Checking for updates... - Checking for updates... - - - - Temporary installation of macro failed. - Temporary installation of macro failed. - - - - - Close - Tanca - - - - Update all addons - Update all addons - - - - Check for updates - Check for updates - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Apply %n available update(s) - Apply %n available update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - - - - Maintainer - Maintainer - - - - - - - Author - Autor - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Actualitza - - - - Updating... - Updating... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - Currently on branch {}, name changed to {} - Currently on branch {}, name changed to {} - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - Update check in progress - Update check in progress - - - - Installation location - Installation location - - - - Changed to branch '{}' -- please restart to use Addon. - Changed to branch '{}' -- please restart to use Addon. - - - - This Addon has been updated. Restart FreeCAD to see changes. - This Addon has been updated. Restart FreeCAD to see changes. - - - - Disabled - Disabled - - - - Currently on branch {}, update available to version {} - Currently on branch {}, update available to version {} - - - - Update available to version {} - Update available to version {} - - - - This is the latest version available - This is the latest version available - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 only - WARNING: This addon is Python 2 only - - - - WARNING: This addon requires FreeCAD {} - WARNING: This addon requires FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - This Addon will be enabled next time you restart FreeCAD. - This Addon will be enabled next time you restart FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - This Addon will be disabled next time you restart FreeCAD. - - - - - - Success - Success - - - - Branch change succeeded, please restart to use the new version. - Branch change succeeded, please restart to use the new version. - - - - Install - Install - - - - Uninstall - Uninstall - - - - Enable - Habilita - - - - Disable - Desactiva - - - - - Check for update - Check for update - - - - Run - executa - - - - Change branch... - Change branch... - - - - Return to package list - Return to package list - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Failed to create installation manifest file: - - Failed to create installation manifest file: - - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Automàtica - - - - - Workbench - Banc de treball - - - - Addon - Addon - - - - Python - Python - - - - Yes - Yes - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Other... - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - executa - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Nom - - - - Class - Classe - - - - Description - Descripció - - - - Subdirectory - Subdirectory - - - - Files - Fitxers - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Search... - Busca... - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Tags - - - - {} ★ on GitHub - {} ★ on GitHub - - - - No ★, or not on GitHub - No ★, or not on GitHub - - - - Created - Created - - - - Updated - Updated - - - - Score: - Score: - - - - - Up-to-date - Up-to-date - - - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Installed version - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Available version - - - - Filter by... - Filter by... - - - - Addon Type - Addon Type - - - - - Any - Qualsevol - - - - Macro - Macro - - - - Preference Pack - Preference Pack - - - - Installation Status - Installation Status - - - - Not installed - Not installed - - - - Filter - Filtre - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - Local - Table header for local git ref name - Local - - - - Remote tracking - Table header for git remote tracking branch name - Remote tracking - - - - Last Updated - Table header for git update date - Last Updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded package.xml for {} - Downloaded package.xml for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Downloaded metadata.txt for {} - Downloaded metadata.txt for {} - - - - Downloaded requirements.txt for {} - Downloaded requirements.txt for {} - - - - Downloaded icon for {} - Downloaded icon for {} - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (expected at {}) - Could not locate macro-specified file {} (expected at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - - Got an error when trying to import {} - Got an error when trying to import {} - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Git is disabled, skipping git macros - Git is disabled, skipping git macros - - - - Attempting to change non-git Macro setup to use git - - Attempting to change non-git Macro setup to use git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Unable to fetch git updates for workbench {} - Unable to fetch git updates for workbench {} - - - - git status failed for {} - git status failed for {} - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Caching macro code... - Caching macro code... - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Getting metadata from macro {} - Getting metadata from macro {} - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Retrieving macro description... - Retrieving macro description... - - - - Retrieving info from git - Retrieving info from git - - - - Retrieving info from wiki - Retrieving info from wiki - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Failed to get Addon score from '{}' -- sorting by score will fail - - - - - Repository URL - Preferences header for custom repositories - Repository URL - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic git update failed with the following message: - Basic git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using git - Failed to clone {} into {} using git - - - - Git branch rename failed with the following message: - Git branch rename failed with the following message: - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Loading info for {} from the FreeCAD Macro Recipes wiki... - - - - Loading page for {} from {}... - Loading page for {} from {}... - - - - Failed to download data from {} -- received response code {}. - Failed to download data from {} -- received response code {}. - - - - Composite view - Composite view - - - - Expanded view - Expanded view - - - - Compact view - Compact view - - - - Alphabetical - Sort order - Alphabetical - - - - Last Updated - Sort order - Last Updated - - - - Date Created - Sort order - Date Created - - - - GitHub Stars - Sort order - GitHub Stars - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - - Workbench - - - Auto-Created Macro Toolbar - Auto-Created Macro Toolbar - - - - QObject - - - Addon Manager - Addon Manager - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_vi.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_vi.qm deleted file mode 100644 index 9e2d085650d32cbca3128b8cb28793495bdc2865..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67679 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_vi.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_vi.ts deleted file mode 100644 index 6a461cfe2d..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_vi.ts +++ /dev/null @@ -1,2477 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Custom repository - - - - Repository URL - Repository URL - - - - Branch - Branch - - - - CompactView - - - Form - Hình thức - - - - Icon - Biểu tượng - - - - <b>Package Name</b> - <b>Package Name</b> - - - - Version - Phiên bản - - - - Description - Mô tả - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - Dependencies - - - - Dependency type - Dependency type - - - - Name - Tên - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Mô tả - - - - Discussion URL - Discussion URL - - - - Icon - Biểu tượng - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Repository URL - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Phiên bản - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Addon Manager - - - - Downloading info... - Thông tin tải xuống... - - - - Pause cache update - Pause cache update - - - - Refresh local cache - Refresh local cache - - - - Download and apply all available updates - Download and apply all available updates - - - - Update all Addons - Update all Addons - - - - Check for updates - Check for updates - - - - View and update Python package dependencies - View and update Python package dependencies - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Close the Addon Manager - Close the Addon Manager - - - - Close - Äóng - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Welcome to the Addon Manager - Welcome to the Addon Manager - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Download Settings - Download Settings - - - - Automatically check installed Addons for updates - Automatically check installed Addons for updates - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - No proxy - No proxy - - - - System proxy - System proxy - - - - User-defined proxy: - User-defined proxy: - - - - These and other settings are available in the FreeCAD Preferences window. - These and other settings are available in the FreeCAD Preferences window. - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - Form - Hình thức - - - - Icon - Biểu tượng - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - Version - Phiên bản - - - - (tags) - (tags) - - - - Description - Mô tả - - - - Maintainer - Maintainer - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - - Form - Hình thức - - - - Licenses - Licenses - - - - License - Giấy phép - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - Tên - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires git) - Automatically check for updates at start (requires git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manual (no automatic updates) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Python executable (optional): - Python executable (optional): - - - - The path to the Python executable for package installation with pip. Autodetected if needed and not specified. - The path to the Python executable for package installation with pip. Autodetected if needed and not specified. - - - - git executable (optional): - git executable (optional): - - - - The path to the git executable. Autodetected if needed and not specified. - The path to the git executable. Autodetected if needed and not specified. - - - - Advanced Options - Advanced Options - - - - Show option to change branches (requires git) - Show option to change branches (requires git) - - - - Disable git (fall back to ZIP downloads only) - Disable git (fall back to ZIP downloads only) - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - PackageDetails - - - Form - Hình thức - - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Install - - - - Uninstall - Uninstall - - - - Update - Cập nhật - - - - Run Macro - Run Macro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Há»™p thoại - - - - TextLabel - Văn bản dán nhãn - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Macro - - - - Preference Pack - Preference Pack - - - - Workbench - Bàn làm việc - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Biểu tượng - - - - actualIcon - actualIcon - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Phiên bản - - - - Description - Mô tả - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch or tag: - Change to branch or tag: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Tên: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - AddonsInstaller - - - Addon Manager - Addon Manager - - - - Starting up... - Starting up... - - - - Loading addon information - Loading addon information - - - - Worker process {} is taking a long time to stop... - Worker process {} is taking a long time to stop... - - - - Previous cache process was interrupted, restarting... - - Previous cache process was interrupted, restarting... - - - - - Custom repo list changed, forcing recache... - - Custom repo list changed, forcing recache... - - - - - Addon manager - Addon manager - - - - You must restart FreeCAD for changes to take effect. - You must restart FreeCAD for changes to take effect. - - - - Restart now - Restart now - - - - Restart later - Restart later - - - - - Refresh local cache - Refresh local cache - - - - Updating cache... - Updating cache... - - - - Could not find addon '{}' to select - - Could not find addon '{}' to select - - - - - - Checking for updates... - Checking for updates... - - - - Apply {} update(s) - Apply {} update(s) - - - - No updates available - No updates available - - - - - - Cannot launch a new installer until the previous one has finished. - Cannot launch a new installer until the previous one has finished. - - - - Execution of macro failed. See console for failure details. - Execution of macro failed. See console for failure details. - - - - - - - Maintainer - Maintainer - - - - - - - Author - Tác giả - - - - New Python Version Detected - New Python Version Detected - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - - - - Processing, please wait... - Processing, please wait... - - - - - Update - Cập nhật - - - - Updating... - Updating... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Failed to convert the specified proxy port '{}' to a port number - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Parameter error: mutually exclusive proxy options set. Resetting to default. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - - - - Addon Manager: Unexpected {} response from server - Addon Manager: Unexpected {} response from server - - - - Error with encrypted connection - Error with encrypted connection - - - - - - Confirm remove - Confirm remove - - - - Are you sure you want to uninstall {}? - Are you sure you want to uninstall {}? - - - - - - Removing Addon - Removing Addon - - - - Removing {} - Removing {} - - - - - Uninstall complete - Uninstall complete - - - - - Uninstall failed - Uninstall failed - - - - Addon Manager Warning: Could not import QtWebEngineWidgets -- README data will display as text-only - Addon Manager Warning: Could not import QtWebEngineWidgets -- README data will display as text-only - - - - Version {version} installed on {date} - Version {version} installed on {date} - - - - Version {version} installed - Version {version} installed - - - - Installed on {date} - Installed on {date} - - - - - - - Installed - Installed - - - - On branch {}, update available to version - On branch {}, update available to version - - - - Update available to version - Update available to version - - - - An update is available - An update is available - - - - Git tag '{}' checked out, no updates possible - Git tag '{}' checked out, no updates possible - - - - This is the latest version available for branch {} - This is the latest version available for branch {} - - - - Updated, please restart FreeCAD to use - Updated, please restart FreeCAD to use - - - - Update check in progress - Update check in progress - - - - Automatic update checks disabled - Automatic update checks disabled - - - - Installation location - Installation location - - - - WARNING: This addon is obsolete - WARNING: This addon is obsolete - - - - WARNING: This addon is Python 2 Only - WARNING: This addon is Python 2 Only - - - - WARNING: This addon requires FreeCAD - WARNING: This addon requires FreeCAD - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - - - - - No URL or wiki page provided by this macro - No URL or wiki page provided by this macro - - - - Could not load README data from URL {} - Could not load README data from URL {} - - - - This Addon will be enabled next time you restart fci. - This Addon will be enabled next time you restart fci. - - - - This Addon will be disabled next time you restart fci. - This Addon will be disabled next time you restart fci. - - - - - - Success - Success - - - - Branch change succeeded, please restart to use the new version. - Branch change succeeded, please restart to use the new version. - - - - Changed to git ref '{}' -- please restart to use Addon. - Changed to git ref '{}' -- please restart to use Addon. - - - - Page JavaScript reported - Page JavaScript reported - - - - Install - Install - - - - Uninstall - Uninstall - - - - Check for Update - Check for Update - - - - Run Macro - Run Macro - - - - Change Branch - Change Branch - - - - Enable - Bật - - - - Disable - Không cho phép - - - - Return to package list - Return to package list - - - - QtWebEngine Python bindings not installed -- using fallback README display. See Report View for details and installation instructions. - QtWebEngine Python bindings not installed -- using fallback README display. See Report View for details and installation instructions. - - - - The page is taking a long time to load... showing the data we have so far... - The page is taking a long time to load... showing the data we have so far... - - - - Checking connection - Checking connection - - - - Checking for connection to GitHub... - Checking for connection to GitHub... - - - - Connection failed - Connection failed - - - - Missing dependency - Missing dependency - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - - - - Other... - For providing a license other than one listed - Other... - - - - Select the corresponding license file in your Addon - Select the corresponding license file in your Addon - - - - Location for new license file - Location for new license file - - - - Received {} response code from server - Received {} response code from server - - - - Failed to install macro {} - Failed to install macro {} - - - - Unrecognized content kind '{}' - Unrecognized content kind '{}' - - - - Unable to locate icon at {} - Unable to locate icon at {} - - - - Select an icon file for this content item - Select an icon file for this content item - - - - - - {} is not a subdirectory of {} - {} is not a subdirectory of {} - - - - Select the subdirectory for this content item - Select the subdirectory for this content item - - - - Automatic - Tá»± động - - - - Workbench - Bàn làm việc - - - - Addon - Addon - - - - Python - Python - - - - Yes - Yes - - - - Internal Workbench - Internal Workbench - - - - External Addon - External Addon - - - - Python Package - Python Package - - - - - Other... - Other... - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually: - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually: - - - - Too many to list - Too many to list - - - - - - - - - Missing Requirement - Missing Requirement - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - - - - Press OK to install anyway. - Press OK to install anyway. - - - - - Incompatible Python version - Incompatible Python version - - - - This Addon (or one if its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - This Addon (or one if its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - - - - Optional dependency on {} ignored because it is not in the allow-list - Optional dependency on {} ignored because it is not in the allow-list - - - - - Installing dependencies - Installing dependencies - - - - - Cannot execute Python - Cannot execute Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Dependencies could not be installed. Continue with installation of {} anyway? - - - - - Cannot execute pip - Cannot execute pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - - - - - Continue with installation of {} anyway? - Continue with installation of {} anyway? - - - - - Package installation failed - Package installation failed - - - - See Report View for detailed failure log. - See Report View for detailed failure log. - - - - Installing Addon - Installing Addon - - - - Installing FreeCAD Addon '{}' - Installing FreeCAD Addon '{}' - - - - Cancelling - Cancelling - - - - Cancelling installation of '{}' - Cancelling installation of '{}' - - - - {} was installed successfully - {} was installed successfully - - - - - Installation Failed - Installation Failed - - - - Failed to install {} - Failed to install {} - - - - - Create new toolbar - Create new toolbar - - - - - A macro installed with the FreeCAD Addon Manager - A macro installed with the FreeCAD Addon Manager - - - - - Run - Indicates a macro that can be 'run' - Chạy - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - - - - XML failure while reading metadata from file {} - XML failure while reading metadata from file {} - - - - Invalid metadata in file {} - Invalid metadata in file {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - - - - Name - Tên - - - - Class - Lá»›p - - - - Description - Mô tả - - - - Subdirectory - Subdirectory - - - - Files - Files - - - - Select the folder containing your Addon - Select the folder containing your Addon - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - No Vermin, cancelling operation. - - - - Scanning Addon for Python version compatibility - Scanning Addon for Python version compatibility - - - - Minimum Python Version Detected - Minimum Python Version Detected - - - - Vermin auto-detected a required version of Python 3.{} - Vermin auto-detected a required version of Python 3.{} - - - - Install Vermin? - Install Vermin? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - - - - Attempting to install Vermin from PyPi - Attempting to install Vermin from PyPi - - - - - Installation failed - Installation failed - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Failed to install Vermin -- check Report View for details. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Failed to import vermin after installation -- cannot scan Addon. - - - - Select an icon file for this package - Select an icon file for this package - - - - Filter is valid - Filter is valid - - - - Filter regular expression is invalid - Filter regular expression is invalid - - - - Click for details about package {} - Click for details about package {} - - - - Click for details about workbench {} - Click for details about workbench {} - - - - Click for details about macro {} - Click for details about macro {} - - - - Maintainers: - Maintainers: - - - - Tags - Tags - - - - updated - updated - - - - - Up-to-date - Up-to-date - - - - - - Update available - Update available - - - - - Pending restart - Pending restart - - - - - DISABLED - DISABLED - - - - Installed version - Installed version - - - - Unknown version - Unknown version - - - - Installed on - Installed on - - - - Available version - Available version - - - - Show Addons containing: - Show Addons containing: - - - - All - Tất cả - - - - Workbenches - Bàn làm việc - - - - Macros - Macro - - - - Preference Packs - Preference Packs - - - - Status: - Status: - - - - Any - Bất kỳ - - - - Not installed - Not installed - - - - Filter - Bá»™ lá»c - - - - OK - Äồng ý - - - - DANGER: Developer feature - DANGER: Developer feature - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - - - - There are local changes - There are local changes - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - - - - - - Branch - git terminology - Branch - - - - Tag - git terminology - Tag - - - - Kind - Table header for git ref type (e.g. either Tag or Branch) - Kind - - - - Local name - Table header for git ref name - Local name - - - - Tracking - Table header for git remote tracking branch name name - Theo dõi - - - - Local updated - Table header for git update time of local branch - Local updated - - - - Remote updated - Table header for git update time of remote branch - Remote updated - - - - Installation of Python package {} failed - Installation of Python package {} failed - - - - Installation of optional package failed - Installation of optional package failed - - - - Installing required dependency {} - Installing required dependency {} - - - - Installation of Addon {} failed - Installation of Addon {} failed - - - - Downloaded package.xml for {} - Downloaded package.xml for {} - - - - Failed to decode {} file for Addon '{}' - Failed to decode {} file for Addon '{}' - - - - Any dependency information in this file will be ignored - Any dependency information in this file will be ignored - - - - Downloaded metadata.txt for {} - Downloaded metadata.txt for {} - - - - Downloaded requirements.txt for {} - Downloaded requirements.txt for {} - - - - Downloaded icon for {} - Downloaded icon for {} - - - - Unable to open macro wiki page at {} - Unable to open macro wiki page at {} - - - - Unable to fetch the code of this macro. - Unable to fetch the code of this macro. - - - - Unable to retrieve a description from the wiki for macro {} - Unable to retrieve a description from the wiki for macro {} - - - - Unable to open macro code URL {} - Unable to open macro code URL {} - - - - Unable to fetch macro-specified file {} from {} - Unable to fetch macro-specified file {} from {} - - - - Could not locate macro-specified file {} (should have been at {}) - Could not locate macro-specified file {} (should have been at {}) - - - - {}: Unrecognized internal workbench '{}' - {}: Unrecognized internal workbench '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - - - - An unknown error occurred - An unknown error occurred - - - - Could not find addon {} to remove it. - Could not find addon {} to remove it. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - - - - Removed extra installed file {} - Removed extra installed file {} - - - - Error while trying to remove extra installed file {} - Error while trying to remove extra installed file {} - - - - Error while trying to remove macro file {}: - Error while trying to remove macro file {}: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Failed to connect to GitHub. Check your connection and proxy settings. - - - - WARNING: Duplicate addon {} ignored - WARNING: Duplicate addon {} ignored - - - - Workbenches list was updated. - Workbenches list was updated. - - - - Git is disabled, skipping git macros - Git is disabled, skipping git macros - - - - Attempting to change non-git Macro setup to use git - - Attempting to change non-git Macro setup to use git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - An error occurred updating macros from GitHub, trying clean checkout... - - - - Attempting to do a clean checkout... - Attempting to do a clean checkout... - - - - Clean checkout succeeded - Clean checkout succeeded - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - - - - Unable to fetch git updates for workbench {} - Unable to fetch git updates for workbench {} - - - - git status failed for {} - git status failed for {} - - - - Failed to read metadata from {name} - Failed to read metadata from {name} - - - - Failed to fetch code for macro '{name}' - Failed to fetch code for macro '{name}' - - - - Caching macro code... - Caching macro code... - - - - Addon Manager: a worker process failed to complete while fetching {name} - Addon Manager: a worker process failed to complete while fetching {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Out of {num_macros} macros, {num_failed} timed out while processing - - - - Addon Manager: a worker process failed to halt ({name}) - Addon Manager: a worker process failed to halt ({name}) - - - - Getting metadata from macro {} - Getting metadata from macro {} - - - - Timeout while fetching metadata for macro {} - Timeout while fetching metadata for macro {} - - - - Failed to kill process for macro {}! - - Failed to kill process for macro {}! - - - - - Retrieving macro description... - Retrieving macro description... - - - - Retrieving info from git - Retrieving info from git - - - - Retrieving info from wiki - Retrieving info from wiki - - - - Repository URL - Preferences header for custom repositories - Repository URL - - - - Branch name - Preferences header for custom repositories - Branch name - - - - Basic git update failed with the following message: - Basic git update failed with the following message: - - - - Backing up the original directory and re-cloning - Backing up the original directory and re-cloning - - - - Failed to clone {} into {} using git - Failed to clone {} into {} using git - - - - Installing - Installing - - - - Succeeded - Succeeded - - - - Failed - Failed - - - - Update was cancelled - Update was cancelled - - - - some addons may have been updated - some addons may have been updated - - - - Std_AddonMgr - - - &Addon manager - &Addon manager - - - - Manage external workbenches, macros, and preference packs - Manage external workbenches, macros, and preference packs - - - - AddonInstaller - - - Finished removing {} - Finished removing {} - - - - Failed to remove some files - Failed to remove some files - - - - Addons installer - - - Finished updating the following addons - Finished updating the following addons - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.qm deleted file mode 100644 index 83528673295aa99f24f6e44fa6a11044f3851c3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49059 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 diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.ts deleted file mode 100644 index f34f691d06..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_zh-CN.ts +++ /dev/null @@ -1,2486 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - 自定义æ’件仓库 - - - - Repository URL - ä»“åº“çš„ç½‘å€ - - - - Branch - 分支 - - - - CompactView - - - - Icon - 图标 - - - - - <b>Package Name</b> - <b>软件包åç§°</b> - - - - - Version - 版本 - - - - - Description - æè¿° - - - - Update Available - æ›´æ–°å¯ç”¨ - - - - UpdateAvailable - å¯ç”¨æ›´æ–° - - - - DependencyDialog - - - Dependencies - ä¾èµ– - - - - Dependency type - ä¾èµ–类型 - - - - Name - åç§° - - - - Optional? - å¯é€‰çš„? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - è§£æžä¾èµ– - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - æ­¤æ’件具有以下所需和å¯é€‰çš„ä¾èµ–å…³ç³»ã€‚æ‚¨å¿…é¡»å…ˆå®‰è£…å®ƒä»¬ï¼Œç„¶åŽæ‰èƒ½ä½¿ç”¨æ­¤æ’件。 - -æ‚¨æƒ³è¦æ’件管ç†å™¨è‡ªåŠ¨å®‰è£…å®ƒä»¬å—?选择 “忽略†将直接安装æ’件,而ä¸å®‰è£…ä¾èµ–项。 - - - - FreeCAD Addons - FreeCAD æ’ä»¶ - - - - Required Python modules - 必需的 Python æ¨¡å— - - - - Optional Python modules - å¯é€‰çš„ Python æ¨¡å— - - - - DeveloperModeDialog - - - Addon Developer Tools - æ’ä»¶å¼€å‘者工具 - - - - Path to Addon - æ’件路径 - - - - - Browse... - æµè§ˆ... - - - - Metadata - å…ƒæ•°æ® - - - - Primary branch - 主è¦åˆ†æ”¯ - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - æ­¤æ’ä»¶æä¾›çš„解释,在æ’件管ç†å™¨ä¸­æ˜¾ç¤ºã€‚这个æ’件无需声明它是一个 FreeCAD æ’件。 - - - - Description - æè¿° - - - - Discussion URL - è®¨è®ºç½‘å€ - - - - Icon - 图标 - - - - Bugtracker URL - Bug è·Ÿè¸ªç½‘å€ - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - 支æŒè¯­ä¹‰åŒ–版本 (1.2.3-beta) 或日期版本 (2022.08.30) 风格 - - - - Set to today (CalVer style) - 设置为今日(CalVer风格) - - - - - - - (Optional) - (å¯é€‰çš„) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - 显示在附加组件管ç†å™¨'的附加组件列表中。 ä¸åº”包å«å•è¯ "FreeCAD",并且必须是所有支æŒçš„æ“ä½œç³»ç»Ÿä¸Šçš„æœ‰æ•ˆç›®å½•å。 - - - - README URL - README ç½‘å€ - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - æç¤ºï¼šå› ä¸ºå®ƒæ˜¯æ˜¾ç¤ºåœ¨ FreeCAD 内部的附加组件管ç†å™¨ä¸­ï¼Œæ‰€ä»¥æ— éœ€å ç”¨ç©ºé—´æ¥è¡¨è¾¾ç±»ä¼¼ "这是一个 FreeCAD 附加组件......"之类的æè¿°â€”—åªéœ€è¯´æ˜Žå…¶ç”¨é€”å³å¯ã€‚ - - - - Repository URL - ä»“åº“çš„ç½‘å€ - - - - Website URL - ç½‘ç«™ç½‘å€ - - - - Documentation URL - æ–‡æ¡£ç½‘å€ - - - - Addon Name - 附加组件åç§° - - - - Version - 版本 - - - - (Recommended) - (推è) - - - - Minimum Python - 最低 Python 版本 - - - - (Optional, only 3.x version supported) - (å¯é€‰ï¼Œä»…æ”¯æŒ 3.x 版本) - - - - Detect... - 检测… - - - - Addon Contents - 附加组件内容 - - - - Dialog - - - Addon Manager - æ’件管ç†å™¨ - - - - Edit Tags - 编辑标签 - - - - Comma-separated list of tags describing this item: - 逗å·åˆ†éš”çš„æè¿°æ­¤é¡¹ç›®çš„æ ‡ç­¾åˆ—表: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - æç¤ºï¼šå¸¸ç”¨æ ‡ç­¾åŒ…括“装é…â€ã€â€œæœ‰é™å…ƒæ–¹æ³•(FEM)â€ã€â€œç½‘æ ¼â€ã€â€œéžå‡åŒ€æœ‰ç†Bæ ·æ¡ï¼ˆNURBS)â€ç­‰ã€‚ - - - - Add-on Manager: Warning! - æ’件库:警告 ï¼ - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Add-on Manageræä¾›äº†ä¸€ä¸ªå¹¿æ³›çš„æ‰©å±•åº“ï¼ŒåŒ…å«æœ‰ç”¨çš„第三方FreeCAD 扩展。ä¸ä¿è¯å…¶å®‰å…¨æ€§æˆ–功能。 - - - - Continue - ç»§ç»­ - - - - Cancel - å–æ¶ˆ - - - - EditDependencyDialog - - - Edit Dependency - 编辑ä¾èµ– - - - - Dependency Type - ä¾èµ–类型 - - - - Dependency - ä¾èµ– - - - - Package name, if "Other..." - 如果选择其他包,请输入包åç§° - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - 注æ„:如果选择了“其他...â€ï¼Œåˆ™è¯¥åŒ…ä¸åœ¨ALLOWED_PYTHON_PACKAGES.txt文件中,Addon Managerå°†ä¸ä¼šè‡ªåŠ¨å®‰è£…å®ƒã€‚è¯·åœ¨<a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a>æäº¤ä¸€ä¸ªPR请求添加一个包。 - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - 如果这是一个å¯é€‰çš„ä¾èµ–项,Addon Manager 将在å¯èƒ½çš„æƒ…况下æä¾›å®‰è£…它,但如果用户选择ä¸å®‰è£…或无法安装该包,Addon Manager ä¸ä¼šé˜»æ­¢å®‰è£…。 - - - - Optional - å¯é€‰çš„ - - - - ExpandedView - - - - Icon - 图标 - - - - - <h1>Package Name</h1> - <h1>软件包åç§°</h1> - - - - - Version - 版本 - - - - - (tags) - (标签) - - - - - Description - æè¿° - - - - - Maintainer - 维护者 - - - - Update Available - æ›´æ–°å¯ç”¨ - - - - labelSort - æ ‡ç­¾æŽ’åº - - - - UpdateAvailable - å¯ç”¨æ›´æ–° - - - - Form - - - Licenses - 许å¯è¯ - - - - License - 授æƒè®¸å¯ - - - - License file - 许å¯è¯æ–‡ä»¶ - - - - People - 人员 - - - - Kind - 类型 - - - - Name - åç§° - - - - Email - 邮箱 - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - 高级版本映射 - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - FreeCAD 附加组件管ç†å™¨å³å°†æŽ¨å‡ºçš„版本将支æŒç”±å¼€å‘者' 设置一个特定分支或标签用于特定版本的 FreeCAD (例如,设置一个特定标签作为您的附加组件的最åŽç‰ˆæœ¬ï¼Œä»¥æ”¯æŒ v0.19,等等)。 - - - - FreeCAD Version - FreeCAD 版本 - - - - Best-available branch, tag, or commit - 最佳å¯ç”¨åˆ†æ”¯ï¼Œæ ‡è®°æˆ–æäº¤ - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - 支æŒçš„ FreeCAD 版本 - - - - Minimum FreeCAD Version Supported - 支æŒçš„æœ€ä½Ž FreeCAD 版本 - - - - - Optional - å¯é€‰çš„ - - - - Maximum FreeCAD Version Supported - 支æŒçš„æœ€é«˜ FreeCAD 版本 - - - - Advanced version mapping... - 高级版本映射... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - æ’件管ç†å™¨é€‰é¡¹ - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - 如果选中了这个选项,在å¯åЍAddon Manager时,已安装的æ’ä»¶å°†æ£€æŸ¥æ˜¯å¦æœ‰å¯ç”¨çš„æ›´æ–°ã€‚ - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - 下载å®å…ƒæ•°æ®(大约10MB) - - - - Cache update frequency - 缓存更新频率 - - - - Manual (no automatic updates) - 手动(ä¸è‡ªåŠ¨æ›´æ–°) - - - - Daily - æ¯å¤© - - - - Weekly - æ¯å‘¨ - - - - Hide Addons without a license - 在许å¯ä¸­éšè—附加组件 - - - - Hide Addons with non-FSF Free/Libre license - éšè—éž FSF Free/Libre 许å¯è¯çš„附加组件 - - - - Hide Addons with non-OSI-approved license - éšè—éžOSI许å¯çš„附加组件 - - - - Hide Addons marked Python 2 Only - éšè—标记为 Python 2 çš„æ’ä»¶ - - - - Hide Addons marked Obsolete - éšè—标记过时的æ’ä»¶ - - - - Hide Addons that require a newer version of FreeCAD - éšè—éœ€è¦æ›´æ–°ç‰ˆæœ¬çš„ FreeCAD çš„æ’ä»¶ - - - - Custom repositories - 自定义仓库 - - - - Proxy - ä»£ç† - - - - No proxy - æ— ä»£ç† - - - - User system proxy - ä½¿ç”¨ç³»ç»Ÿä»£ç† - - - - User-defined proxy: - 使用默认代ç†ï¼š - - - - Score source URL - æºä»£ç  URL - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - Addon Score æ•°æ®çš„ URL(请å‚è§Addon Manager的维基页é¢äº†è§£æ ¼å¼åŒ–和托管详情)。 - - - - Path to Git executable (optional): - Git 坿‰§è¡Œæ–‡ä»¶è·¯å¾„(å¯é€‰): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - 高级选项 - - - - Activate Addon Manager options intended for developers of new Addons. - 激活为新附加组件开å‘者设计的附加组件管ç†å™¨é€‰é¡¹ã€‚ - - - - Addon developer mode - 附加组件开å‘è€…æ¨¡å¼ - - - - PackageDetails - - - Uninstalls a selected macro or workbench - å¸è½½é€‰å®šçš„宿ˆ–å·¥ä½œå° - - - - Install - 安装 - - - - Uninstall - å¸è½½ - - - - Update - æ›´æ–° - - - - Run Macro - è¿è¡Œå® - - - - Change branch - 更改分支 - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - ç®¡ç† Python ä¾èµ– - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - 以下Python 软件包已被附加组件管ç†å™¨æœ¬åœ°å®‰è£…以满足附加组件ä¾èµ–。安装ä½ç½®ï¼š - - - - Package name - 安装包å - - - - Installed version - 已安装的版本 - - - - Available version - å¯ç”¨ç‰ˆæœ¬ - - - - Used by - 使用于 - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - 在“Used byâ€ï¼ˆè¢«ä½¿ç”¨ï¼‰åˆ—中的星å·ï¼ˆ*)表示一个å¯é€‰çš„ä¾èµ–项。请注æ„,“Used byâ€åªè®°å½•Addon中的直接导入。其他那些包所ä¾èµ–çš„Python包也å¯èƒ½å·²ç»è¢«å®‰è£…。 - - - - Update all available - 更新所有å¯ç”¨ - - - - SelectFromList - - - Dialog - å¯¹è¯æ¡† - - - - TextLabel - 文本标签 - - - - UpdateAllDialog - - - Updating Addons - 更新附加组件ing - - - - Updating out-of-date addons... - 正在更新过期的æ’ä»¶... - - - - addContentDialog - - - Content Item - 内容项目 - - - - Content type: - 内容类型: - - - - Macro - å® - - - - Preference Pack - 首选项é…置包 - - - - Workbench - å·¥ä½œå° - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - 如果这是附加组件中唯一的东西,所有其他元数æ®éƒ½å¯ä»¥ä»Žé¡¶å±‚继承。 无需在此处指定。 - - - - This is the only item in the Addon - 这是附加组件中唯一的项目 - - - - Main macro file - 䏻宿–‡ä»¶ - - - - The file with the macro's metadata in it - 带å®çš„元数æ®çš„æ–‡ä»¶ä»¬ - - - - - - Browse... - æµè§ˆ... - - - - Preference Pack Name - 首选项é…置包åç§° - - - - Workbench class name - 工作å°ç±»åç§° - - - - Class that defines "Icon" data member - 定义 "图标" æ•°æ®æˆå‘˜çš„ç±» - - - - Subdirectory - å­ç›®å½• - - - - Optional, defaults to name of content item - å¯é€‰ï¼Œé»˜è®¤å†…容项åç§° - - - - Icon - 图标 - - - - Optional, defaults to inheriting from top-level Addon - å¯é€‰ï¼Œé»˜è®¤ä»Žé¡¶çº§é™„加组件继承。 - - - - Tags... - 标签… - - - - Dependencies... - ä¾èµ–… - - - - FreeCAD Versions... - FreeCAD 版本… - - - - Other Metadata - å…¶ä»–å…ƒæ•°æ® - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - 显示在Addon Managerçš„æ’件列表中。ä¸åº”该包括“FreeCADâ€è¿™ä¸ªè¯ã€‚ - - - - Version - 版本 - - - - Description - æè¿° - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - 支æŒè¯­ä¹‰åŒ–版本 (1.2.3-beta) 或日期版本 (2022.08.30) 风格 - - - - Set to today (CalVer style) - 设置为今日(CalVer风格) - - - - Display Name - 显示åç§° - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - 任何留空的字段都是从顶层Addon元数æ®ç»§æ‰¿è€Œæ¥çš„,因此它们在技术上都是å¯é€‰çš„。对于具有多个内容项的æ’件,æ¯ä¸ªé¡¹éƒ½åº”该æä¾›ä¸€ä¸ªå”¯ä¸€çš„æ˜¾ç¤ºåç§°å’Œæè¿°ã€‚ - - - - add_toolbar_button_dialog - - - Add button? - 添加按钮 - - - - Add a toolbar button for this macro? - ä¸ºæ­¤å®æ·»åŠ å·¥å…·æ æŒ‰é’®ï¼Ÿ - - - - Yes - 是 - - - - No - å¦ - - - - Never - ä»Žä¸ - - - - change_branch - - - Change Branch - 更改分支 - - - - Change to branch: - 更改分支: - - - - copyrightInformationDialog - - - Copyright Information - 版æƒä¿¡æ¯ - - - - Copyright holder: - ç‰ˆæƒæ‰€æœ‰äºº: - - - - Copyright year: - 版æƒå¹´ä»½: - - - - personDialog - - - Add Person - 添加人员 - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - ç»´æŠ¤è€…æ˜¯åœ¨è¿™ä¸ªé¡¹ç›®ä¸Šæ‹¥æœ‰å½“å‰æäº¤è®¿é—®æƒé™çš„人。作者是您的任何其他人,对ta的贡献åšå‡ºè‚¯å®šã€‚ - - - - Name: - å称: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - 电å­é‚®ç®±å¯¹äºŽç»´æŠ¤è€…必须填写,对于作者å¯ä»¥ä¸å¡«å†™ - - - - proxy_authentication - - - Proxy login required - 代ç†éœ€è¦ç™»å½• - - - - Proxy requires authentication - ä»£ç†æœåŠ¡å™¨éœ€è¦éªŒè¯ - - - - Proxy: - 代ç†: - - - - Placeholder for proxy address - 代ç†åœ°å€å ä½ç¬¦ - - - - Realm: - 域: - - - - Placeholder for proxy realm - 代ç†åŸŸå ä½ç¬¦ - - - - Username - 用户å - - - - Password - å¯†ç  - - - - selectLicenseDialog - - - Select a license - 选择一个许å¯è¯ - - - - About... - 关于... - - - - License name: - 许å¯å称: - - - - Path to license file: - è®¸å¯æ–‡ä»¶è·¯å¾„: - - - - (if required by license) - (如果许å¯éœ€è¦ï¼‰ - - - - Browse... - æµè§ˆ... - - - - Create... - 创建… - - - - select_toolbar_dialog - - - - - - Select Toolbar - é€‰æ‹©å·¥å…·æ  - - - - Select a toolbar to add this macro to: - é€‰æ‹©å·¥å…·æ æ·»åŠ æ­¤å®ï¼š - - - - Ask every time - æ¯æ¬¡éƒ½è¯¢é—® - - - - toolbar_button - - - - Add button? - 添加按钮 - - - - Add a toolbar button for this macro? - ä¸ºæ­¤å®æ·»åŠ å·¥å…·æ æŒ‰é’®ï¼Ÿ - - - - Yes - 是 - - - - No - å¦ - - - - Never - ä»Žä¸ - - - - AddonsInstaller - - - Starting up... - 正在å¯åŠ¨â€¦ - - - - Worker process {} is taking a long time to stop... - 工作进程 {} 需è¦å¾ˆé•¿æ—¶é—´æ‰èƒ½åœæ­¢... - - - - Previous cache process was interrupted, restarting... - - å…ˆå‰çš„ç¼“å­˜è¿›ç¨‹è¢«ä¸­æ–­ï¼Œæ­£åœ¨é‡æ–°å¯åЍ... - - - - - Custom repo list changed, forcing recache... - - 自定义仓库列表产生å˜åŠ¨ï¼Œæ­£åœ¨å¼ºåˆ¶é‡æ–°ç¼“å­˜... - - - - - Addon manager - 附加组件管ç†å™¨ - - - - You must restart FreeCAD for changes to take effect. - 您必须容器 FreeCAD æ‰èƒ½åº”用这些更改 - - - - Restart now - ç«‹å³é‡å¯ - - - - Restart later - ç¨åŽé‡å¯ - - - - - Refresh local cache - 刷新本地缓存 - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - 正在更新缓存… - - - - - Checking for updates... - 正在检查更新… - - - - Temporary installation of macro failed. - 临时安装å®å¤±è´¥ã€‚ - - - - - Close - 关闭 - - - - Update all addons - 更新所有æ’ä»¶ - - - - Check for updates - 检查更新 - - - - Python dependencies... - Python ä¾èµ–... - - - - Developer tools... - å¼€å‘者工具... - - - - Apply %n available update(s) - 应用 %n å¯ç”¨çš„æ›´æ–°(s) - - - - No updates available - 暂时无更新 - - - - - - Cannot launch a new installer until the previous one has finished. - 在å‰ä¸€ä¸ªå®‰è£…程åºå®Œæˆä¹‹å‰ï¼Œæ— æ³•å¯åŠ¨æ–°å®‰è£…ç¨‹åºã€‚ - - - - - - - Maintainer - 维护者 - - - - - - - Author - 作者 - - - - New Python Version Detected - 检测到新的 Python 版本 - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - 这似乎是第一次在附加组件管ç†å™¨ä¸­ä½¿ç”¨æ­¤ç‰ˆæœ¬çš„ Python 。 您想è¦ä¸ºå®ƒå®‰è£…相åŒçš„自动安装ä¾èµ–关系å—? - - - - Processing, please wait... - 正在处ç†ï¼Œè¯·ç¨å€™... - - - - - Update - æ›´æ–° - - - - Updating... - 正在更新… - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - 无法导入 QtNetwork -- 它似乎未安装在您的系统上。 您的æä¾›å•†å¯èƒ½æœ‰æ­¤ä¾èµ–关系的软件包(通常称为 "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - 将指定的代ç†ç«¯å£ '{}' 转æ¢ä¸ºç«¯å£å·å¤±è´¥ - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - 傿•°é”™è¯¯ï¼šè®¾ç½®äº†ç›¸äº’排斥的代ç†é€‰é¡¹ã€‚é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚ - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - 傿•°é”™è¯¯ï¼šç”¨æˆ·ä»£ç†å·²è¯´æ˜Žï¼Œä½†æ²¡æœ‰æä¾›ä»£ç†ã€‚é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚ - - - - Addon Manager: Unexpected {} response from server - 附加组件管ç†å™¨ï¼šæœåС噍å‘生了未知å“应: {} - - - - Error with encrypted connection - 加密连接错误 - - - - - - Confirm remove - 确认删除 - - - - Are you sure you want to uninstall {}? - 您确定è¦å¸è½½ {0} å—? - - - - - - Removing Addon - 移除附加组件 - - - - Removing {} - 正在删除 {} - - - - - Uninstall complete - å¸è½½å®Œæˆ - - - - - Uninstall failed - å¸è½½å¤±è´¥ - - - - Version {version} installed on {date} - 版本 {version} 安装在 {date} - - - - Version {version} installed - 版本 {version} 已安装 - - - - Installed on {date} - 安装于{date} - - - - - - - Installed - 已安装 - - - - Currently on branch {}, name changed to {} - ç›®å‰åœ¨åˆ†æ”¯ {},å称已更改为{} - - - - Git tag '{}' checked out, no updates possible - Git 标签 '{}' 签出,没有å¯èƒ½çš„æ›´æ–° - - - - Update check in progress - 更新检查进行中 - - - - Installation location - 安装ä½ç½® - - - - Repository URL - ä»“åº“çš„ç½‘å€ - - - - Changed to branch '{}' -- please restart to use Addon. - 已更改为分支 '{}' -- 请é‡å¯ä»¥ä½¿ç”¨é™„加组件 - - - - This Addon has been updated. Restart FreeCAD to see changes. - æ­¤æ’件已更新。é‡å¯FreeCAD 以查看更改。 - - - - Disabled - ç¦ç”¨ - - - - Currently on branch {}, update available to version {} - ç›®å‰å¤„于分支 {}, 更新到版本 {} - - - - Update available to version {} - 坿›´æ–°è‡³ç‰ˆæœ¬ {} - - - - This is the latest version available - 这是å¯ç”¨çš„æœ€æ–°ç‰ˆæœ¬ - - - - WARNING: This addon is obsolete - 警告:此æ’件已过期 - - - - WARNING: This addon is Python 2 only - 警告:此æ’ä»¶åªèƒ½ä½¿ç”¨Python 2 - - - - WARNING: This addon requires FreeCAD {} - 警告:此æ’ä»¶éœ€è¦ FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - 警告:此æ’ä»¶ç›®å‰å·²å®‰è£…,但已ç¦ç”¨ã€‚请使用 'å¯ç”¨' æŒ‰é’®é‡æ–°å¯ç”¨ã€‚ - - - - This Addon will be enabled next time you restart FreeCAD. - 此附加组件将在您下次é‡å¯ FreeCAD æ—¶å¯ç”¨ã€‚ - - - - This Addon will be disabled next time you restart FreeCAD. - 此附加组件将在您下次é‡å¯ FreeCAD æ—¶å¯ç”¨ã€‚ - - - - - - Success - æˆåŠŸ - - - - Install - 安装 - - - - Uninstall - å¸è½½ - - - - Enable - å¯ç”¨ - - - - Disable - ç¦ç”¨ - - - - - Check for update - 检查更新 - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - è¿è¡Œ - - - - Change branch... - 更改分支... - - - - Return to package list - 返回列表 - - - - Checking connection - 检查连接中 - - - - Checking for connection to GitHub... - 正在检查到 GitHub 的连接... - - - - Connection failed - 连接失败 - - - - Missing dependency - 缺少ä¾èµ– - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - 无法导入 QtNetwork -- 查看报表视图以获得详细信æ¯ã€‚æ’件管ç†å™¨ä¸å¯ç”¨ã€‚ - - - - Other... - For providing a license other than one listed - 其它… - - - - Select the corresponding license file in your Addon - åœ¨æ‚¨çš„é™„åŠ ç»„ä»¶ä¸­é€‰æ‹©ç›¸åº”çš„è®¸å¯æ–‡ä»¶ - - - - Location for new license file - 新许å¯è¯æ–‡ä»¶çš„ä½ç½® - - - - Received {} response code from server - 从æœåŠ¡å™¨æ”¶åˆ°å“åº”ä»£ç  {} - - - - Failed to install macro {} - 安装å®å¤±è´¥ {} - - - - Failed to create installation manifest file: - - åˆ›å»ºå®‰è£…æ¸…å•æ–‡ä»¶å¤±è´¥ï¼š - - - - - Unrecognized content kind '{}' - 无法识别的内容类型 '{}' - - - - Unable to locate icon at {} - 无法在 {} 找到图标 - - - - Select an icon file for this content item - 为此内容项选择图标文件 - - - - - - {} is not a subdirectory of {} - {} 䏿˜¯ {} çš„å­ç›®å½• - - - - Select the subdirectory for this content item - 选择此内容项的å­ç›®å½• - - - - Automatic - 自动 - - - - - Workbench - å·¥ä½œå° - - - - Addon - 附加组件 - - - - Python - Python - - - - Yes - 是 - - - - Internal Workbench - å†…éƒ¨å·¥ä½œå° - - - - External Addon - 外部附加组件 - - - - Python Package - Python包 - - - - - Other... - 其它… - - - - Too many to list - 列表数æ®è¿‡å¤š - - - - - - - - - Missing Requirement - ç¼ºå°‘è¦æ±‚ - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - 附加组件 '{}' éœ€è¦ '{}', 这在您的 FreeCAD 副本中ä¸å¯ç”¨ã€‚ - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - æ’ä»¶ '{}' 需è¦ä¸‹åˆ—工作å°, 这在您的 FreeCAD 副本中ä¸å¯ç”¨ã€‚ - - - - Press OK to install anyway. - 按“确定â€å®‰è£…。 - - - - - Incompatible Python version - ä¸å…¼å®¹ Python 版本 - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - 此附加软件ä¾èµ–çš„Python软件包没有安装, 也ä¸èƒ½è‡ªåŠ¨å®‰è£…ã€‚è¦ä½¿ç”¨æ­¤é™„加软件,您必须手动安装以下Python软件包: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - 这个附加组件 (或它的一个ä¾èµ–) éœ€è¦ Python {}.{},您的系统正在è¿è¡Œ {}.{}ã€‚å®‰è£…å·²å–æ¶ˆã€‚ - - - - Optional dependency on {} ignored because it is not in the allow-list - 忽略对 {} çš„å¯é€‰ä¾èµ–,因为它ä¸åœ¨å…许列表 - - - - - Installing dependencies - 安装ä¾èµ–项 - - - - - Cannot execute Python - 无法执行 Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - è‡ªåŠ¨å®šä½æ‚¨çš„ Python 坿‰§è¡Œæ–‡ä»¶å¤±è´¥ï¼Œæˆ–è€…è·¯å¾„è®¾ç½®ä¸æ­£ç¡®ã€‚请检查 Python æ’件管ç†å™¨é¦–选项设置。 - - - - Dependencies could not be installed. Continue with installation of {} anyway? - 无法安装ä¾èµ–关系。继续安装 {} å—? - - - - - Cannot execute pip - 无法执行 pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - 无法执行pip命令,你å¯èƒ½è¿˜æ²¡æœ‰å®‰è£…pip. è¯·ç¡®ä¿æ‚¨çš„系统安装了pipå¹¶å†è¯•一次. 无法执行的命令是: - - - - - Continue with installation of {} anyway? - 继续安装 {} å—? - - - - - Package installation failed - 软件包安装失败 - - - - See Report View for detailed failure log. - 查看报告视图以获å–详细记录 - - - - Installing Addon - 正在安装附加项目 - - - - Installing FreeCAD Addon '{}' - 正在安装FreeCAD附加项目'{}' - - - - Cancelling - æ­£åœ¨å–æ¶ˆ - - - - Cancelling installation of '{}' - æ­£åœ¨å–æ¶ˆ '{}' 的安装 - - - - {} was installed successfully - {} å·²æˆåŠŸå®‰è£… - - - - - Installation Failed - 安装失败 - - - - Failed to install {} - 无法安装{} - - - - - Create new toolbar - åˆ›å»ºæ–°å·¥å…·æ  - - - - - A macro installed with the FreeCAD Addon Manager - 使用 FreeCAD æ’件管ç†å™¨å®‰è£…çš„å® - - - - - Run - Indicates a macro that can be 'run' - è¿è¡Œ - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - 无法从 GitHub èŽ·å–æ•°æ®ï¼šè¯·æ£€æŸ¥æ‚¨çš„互è”网连接和代ç†è®¾ç½®ï¼Œç„¶åŽé‡è¯•。 - - - - XML failure while reading metadata from file {} - 从文件 {} 读å–å…ƒæ•°æ®æ—¶XML 失败 - - - - Invalid metadata in file {} - 文件 {} ä¸­çš„å…ƒæ•°æ®æ— æ•ˆ - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - 警告:package.xml 元数æ®ä¸­æŒ‡å®šçš„路径与当å‰ç­¾å‡ºåˆ†æ”¯ä¸åŒ¹é…。 - - - - Name - åç§° - - - - Class - ç§ç±» - - - - Description - æè¿° - - - - Subdirectory - å­ç›®å½• - - - - Files - 文件 - - - - Select the folder containing your Addon - 选择包å«é™„加组件的文件夹 - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - æ— Verminï¼Œå–æ¶ˆæ“作。 - - - - Scanning Addon for Python version compatibility - 检查附加组件与Python的版本兼容性中 - - - - Minimum Python Version Detected - 检测到最低Pythonç‰ˆæœ¬è¦æ±‚ - - - - Vermin auto-detected a required version of Python 3.{} - Vermin æ£€æµ‹åˆ°éœ€è¦ Python 3.{} 的版本 - - - - Install Vermin? - 安装Verminå—? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - 自动检测此附加组件所需的 Python ç‰ˆæœ¬éœ€è¦ Vermin (https://pypi.org/project/vermin/)。è¦å®‰è£…å—? - - - - Attempting to install Vermin from PyPi - 正在å°è¯•从 PyPi 安装 Vermin - - - - - Installation failed - 安装失败 - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - 安装 Vermin 失败 -- 请查看报告视图以获å–详细信æ¯ã€‚ - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - å®‰è£…åŽæ— æ³•导入vermin - 无法扫æé™„加项目。 - - - - Select an icon file for this package - 选择此软件包的ico图标文件 - - - - Filter is valid - 筛选器有效 - - - - Filter regular expression is invalid - è¿‡æ»¤æ­£åˆ™è¡¨è¾¾å¼æ— æ•ˆ - - - - Search... - æœç´¢... - - - - Click for details about package {} - 点击获å–软件包 {} çš„è¯¦ç»†ä¿¡æ¯ - - - - Click for details about workbench {} - 点击查看工作å°çš„è¯¦ç»†ä¿¡æ¯ {} - - - - Click for details about macro {} - 点击查看å®çš„è¯¦ç»†ä¿¡æ¯ {} - - - - Maintainers: - 维护者: - - - - Tags - 标签 - - - - {} ★ on GitHub - {} Github上的★数 - - - - No ★, or not on GitHub - 没有★,或者ä¸åœ¨Github上 - - - - Created - 创造日期 - - - - Updated - 更新日期 - - - - Score: - 评分: - - - - - Up-to-date - 已是最新 - - - - - - - - Update available - 有å¯ç”¨çš„æ›´æ–° - - - - - Pending restart - 等待é‡å¯ - - - - - DISABLED - ç¦ç”¨ - - - - Installed version - 已安装的版本 - - - - Unknown version - 未知版本 - - - - Installed on - 安装于 - - - - Available version - å¯ç”¨ç‰ˆæœ¬ - - - - Filter by... - 筛选æ¡ä»¶... - - - - Addon Type - 附加组件类型 - - - - - Any - ä»»æ„ - - - - Macro - å® - - - - Preference Pack - 首选项é…置包 - - - - Installation Status - å®‰è£…çŠ¶æ€ - - - - Not installed - 未安装 - - - - Filter - 筛选器 - - - - DANGER: Developer feature - 警告: å¼€å‘者功能 - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - 警告:切æ¢åˆ†æ”¯æ“作应由开å‘者或测试者完æˆï¼Œå¯èƒ½å¯¼è‡´è½¯ä»¶æ•…éšœã€æ‰¾ä¸åˆ°å¤åŽŸæ•™ç¨‹ã€ä¸ç¨³å®šã€å´©æºƒå’Œ/或宇宙æ¯ç­ã€‚您确定è¦ç»§ç»­å—? - - - - There are local changes - 局部内容有更改 - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - è­¦å‘Šï¼šæ­¤ä»“åº“æœ‰æœªæ‰¿è¯ºçš„æœ¬åœ°æ›´æ”¹ã€‚æ‚¨ç¡®å®šè¦æ›´æ”¹åˆ†æ”¯ (与您è”ç³»å˜åŒ–) å—? - - - - Local - Table header for local git ref name - 本地 - - - - Remote tracking - Table header for git remote tracking branch name - 远程跟踪 - - - - Last Updated - Table header for git update date - æœ€åŽæ›´æ–° - - - - Installation of Python package {} failed - 安装Python软件包 {} 失败 - - - - Installation of optional package failed - å¯é€‰è½¯ä»¶åŒ…安装失败 - - - - Installing required dependency {} - 正在安装需è¦çš„ä¾èµ–关系{} - - - - Installation of Addon {} failed - æ’ä»¶ {} 安装失败 - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - 为附加组件 '{}' è§£ç  {} 文件失败 - - - - Any dependency information in this file will be ignored - 此文件中的任何ä¾èµ–ä¿¡æ¯å°†è¢«å¿½ç•¥ - - - - Unable to open macro wiki page at {} - 无法在 {} 打开å®çš„ wiki é¡µé¢ - - - - Unable to fetch the code of this macro. - æ— æ³•èŽ·å–æ­¤å®çš„代ç ã€‚ - - - - Unable to retrieve a description from the wiki for macro {} - 无法从 wiki èŽ·å–æ­¤å®çš„æè¿°ã€‚ - - - - Unable to open macro code URL {} - 无法打开å®ä»£ç  URL {} - - - - Unable to fetch macro-specified file {} from {} - - - - - Could not locate macro-specified file {} (expected at {}) - 无法定ä½å®æŒ‡å®šçš„æ–‡ä»¶ {} (预期在 {}) - - - - {}: Unrecognized internal workbench '{}' - {}: æ— æ³•è¯†åˆ«çš„å†…éƒ¨å·¥ä½œå° '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - 附加组件开å‘者警告: 在 package.xml 文件中为附加组件 {} 设置的资æºåº“ URL ({}) 与获å–它的 URL ({}) ä¸åŒ¹é… - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - 附加组件开å‘者警告: 在 package.xml 文件中为附加组件 {} 设置的资æºåº“分支 ({}) 与获å–它的分支 ({}) ä¸åŒ¹é… - - - - - Got an error when trying to import {} - å°è¯•导入 {} 时出错 - - - - An unknown error occurred - å‘生未知错误 - - - - Could not find addon {} to remove it. - 未找到è¦ç§»é™¤çš„附件{} 。 - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - 执行æ’ä»¶'çš„uninstall.py脚本失败。正在继续å¸è½½... - - - - Removed extra installed file {} - 已移除é¢å¤–安装的文件 {} - - - - Error while trying to remove extra installed file {} - å°è¯•删除é¢å¤–安装的文件 {} 时出错 - - - - Error while trying to remove macro file {}: - å°è¯•åˆ é™¤å®æ–‡ä»¶ {} 时出错 - - - - Failed to connect to GitHub. Check your connection and proxy settings. - 连接到 GitHub 失败。请检查您的连接和代ç†è®¾ç½®ã€‚ - - - - WARNING: Duplicate addon {} ignored - 警告:é‡å¤æ’ä»¶ {} 已忽略 - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - 从 GitHub æ›´æ–°å®æ—¶å‡ºé”™ï¼Œæ­£åœ¨å°è¯•干净签出(clean checkout)... - - - - Attempting to do a clean checkout... - 正在å°è¯•干净签出(clean checkout)... - - - - Clean checkout succeeded - 干净签出(clean checkout) æˆåŠŸ - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - 从 GitHub æ›´æ–°å®å¤±è´¥ -- å°è¯•æ¸…ç†æ’件管ç†å™¨'缓存。 - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - 连接到 Wiki 时出错,FreeCAD æ­¤æ—¶æ— æ³•èŽ·å– Wiki å®åˆ—表 - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - 从 {name} 读å–元数æ®å¤±è´¥ - - - - Failed to fetch code for macro '{name}' - 获å–å® '{name}' 代ç å¤±è´¥ - - - - Addon Manager: a worker process failed to complete while fetching {name} - æ’件管ç†å™¨ï¼šå·¥ä½œè¿›ç¨‹æœªèƒ½èŽ·å– {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - 在{num_macros} 个å®ä¸­ {num_failed} ä¸ªå¤„ç†æ—¶è¶…æ—¶ - - - - Addon Manager: a worker process failed to halt ({name}) - æ’件管ç†å™¨ï¼šå·¥ä½œè¿›ç¨‹æœªèƒ½åœæ­¢ ({name}) - - - - Timeout while fetching metadata for macro {} - 获å–å® {} å…ƒæ•°æ®æ—¶è¶…æ—¶ - - - - Failed to kill process for macro {}! - - ä¸ºå® {} æ€æ­»è¿›ç¨‹å¤±è´¥ï¼ - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - 从 {} 获å–é™„åŠ ç»„ä»¶ç»Ÿè®¡å¤±è´¥â€”â€”åªæœ‰æŒ‰å­—æ¯é¡ºåºæŽ’åºæ‰æ˜¯å‡†ç¡®çš„ - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - 从'{}' 获å–附加组件分数失败——通过分数排åºå°†å¤±è´¥ - - - - - Repository URL - Preferences header for custom repositories - ä»“åº“çš„ç½‘å€ - - - - Branch name - Preferences header for custom repositories - 分支åç§° - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - æ­£åœ¨å¤‡ä»½åŽŸå§‹ç›®å½•å¹¶é‡æ–°å…‹éš† - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git 分支é‡å‘½å失败: - - - - Installing - 正在安装 - - - - Succeeded - æˆåŠŸ - - - - Failed - 失败 - - - - Update was cancelled - æ›´æ–°å·²å–æ¶ˆ - - - - some addons may have been updated - 一些附加组件å¯èƒ½å·²æ›´æ–° - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - 从 FreeCAD å®ä»£ç  wiki 中加载 {} ä¿¡æ¯... - - - - Loading page for {} from {}... - 从 {} 加载 {} 页é¢... - - - - Failed to download data from {} -- received response code {}. - 无法从 {} ä¸‹è½½æ•°æ® -- 收到的å“åº”ä»£ç  {}。 - - - - Composite view - å¤åˆè§†å›¾ - - - - Expanded view - 展开视图 - - - - Compact view - 精简视图 - - - - Alphabetical - Sort order - 按字æ¯é¡ºåº - - - - Last Updated - Sort order - æœ€åŽæ›´æ–° - - - - Date Created - Sort order - 创建日期 - - - - GitHub Stars - Sort order - GitHub 点赞数 - - - - Score - Sort order - 分数 - - - - Std_AddonMgr - - - &Addon manager - 附加组件管ç†å™¨ (&A) - - - - Manage external workbenches, macros, and preference packs - 管ç†å¤–部工作å°ã€å®å’Œé¦–选项é…置包 - - - - AddonInstaller - - - Finished removing {} - 移除 {} 已完æˆã€‚ - - - - Failed to remove some files - 未能删除æŸäº›æ–‡ä»¶ - - - - Addons installer - - - Finished updating the following addons - å·²å®Œæˆæ›´æ–°ä»¥ä¸‹é™„加组件 - - - - Workbench - - - Auto-Created Macro Toolbar - 自动创建的å®å·¥å…·æ  - - - - QObject - - - Addon Manager - æ’件管ç†å™¨ - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.qm deleted file mode 100644 index 69f45cfb9d8b4e57c75f7771f99c552c15b46275..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49589 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 Q(+Fj0UrQs2rM~xn00irmiU0rr diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.ts deleted file mode 100644 index d67f2abed0..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_zh-TW.ts +++ /dev/null @@ -1,2487 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - 自訂儲存庫 - - - - Repository URL - å„²å­˜åº«ç¶²å€ - - - - Branch - 分支 - - - - CompactView - - - - Icon - 圖示 - - - - - <b>Package Name</b> - <b>套件å稱</b> - - - - - Version - 版本 - - - - - Description - 說明 - - - - Update Available - 有å¯ç”¨æ›´æ–° - - - - UpdateAvailable - å¯ç²å¾—æ›´æ–° - - - - DependencyDialog - - - Dependencies - ç›¸ä¾æ€§ - - - - Dependency type - 相ä¾é¡žåˆ¥ - - - - Name - å稱 - - - - Optional? - é¸ç”¨? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - è§£æ±ºç›¸ä¾æ€§ - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - 此附加元件需è¦ä»¥ä¸‹å¿…è¦å’Œé¸ç”¨ç›¸ä¾å¥—件。您必須在使用此附加元件之å‰å®‰è£å®ƒå€‘。 - -您是å¦å¸Œæœ›é™„加元件管ç†å“¡è‡ªå‹•安è£å®ƒå€‘ï¼Ÿé¸æ“‡"忽略"以安è£é™„加元件而ä¸å®‰è£ç›¸ä¾å¥—件。 - - - - FreeCAD Addons - FreeCAD 附件元件 - - - - Required Python modules - 所需之 Python 模組 - - - - Optional Python modules - å¯é¸çš„ Python 模組 - - - - DeveloperModeDialog - - - Addon Developer Tools - 附加元件開發者工具 - - - - Path to Addon - 附加元件路徑 - - - - - Browse... - ç€è¦½... - - - - Metadata - 後設資料é¸é … - - - - Primary branch - 主è¦åˆ†æ”¯ - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - 說明此附加元件æä¾›ä»€éº¼ã€‚在附加元件管ç†å“¡ä¸­é¡¯ç¤ºã€‚æ²’æœ‰å¿…è¦æŒ‡æ˜Žé€™æ˜¯ FreeCAD 附加元件 - - - - Description - 說明 - - - - Discussion URL - è¨Žè«–ç¶²å€ - - - - Icon - 圖示 - - - - Bugtracker URL - 錯誤追蹤系統的URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - æ”¯æ´ Semantic (1.2.3-beta 版) 或 CalVer (2022.08.30 版) 風格 - - - - Set to today (CalVer style) - 設置為今天(CalVeræ ¼å¼ï¼‰ - - - - - - - (Optional) - (å¯é¸ï¼‰ - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - 顯示在附加元件管ç†å“¡'çš„é™„åŠ å…ƒä»¶æ¸…å–®ä¸­ã€‚ä¸æ‡‰åŒ…括單詞 "FreeCAD"ï¼Œä¸¦ä¸”å¿…é ˆæ˜¯æ‰€æœ‰æ”¯æ´æ“作系統上的有效目錄å稱。 - - - - README URL - README ç¶²å€ - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - æç¤ºï¼šç”±æ–¼é€™æ˜¯åœ¨ FreeCAD 中顯示的,附加元件管ç†å“¡ä¸­ä¸éœ€è¦ä½”用空間說明 "這是 FreeCAD 的附加元件...",åªéœ€èªªæ˜Žå…¶åŠŸèƒ½å³å¯ã€‚ - - - - Repository URL - å„²å­˜åº«ç¶²å€ - - - - Website URL - ç¶²å€ - - - - Documentation URL - æ–‡ä»¶ç¶²å€ - - - - Addon Name - 附加元件å稱 - - - - Version - 版本 - - - - (Recommended) - (建議) - - - - Minimum Python - æœ€ä½Žè¦æ±‚çš„Python版本 - - - - (Optional, only 3.x version supported) - (å¯é¸ï¼Œåªæ”¯æ´ 3.x 版) - - - - Detect... - 嵿¸¬... - - - - Addon Contents - 附加元件內容 - - - - Dialog - - - Addon Manager - 附加元件管ç†å“¡ - - - - Edit Tags - 編輯標籤 - - - - Comma-separated list of tags describing this item: - 逗號分隔的標籤清單以æè¿°æ­¤é …目: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - æç¤ºï¼šå¸¸è¦‹çš„æ¨™ç±¤åŒ…括 "Assembly&quotã€"FEM"ã€"Mesh"ã€"NURBS" 等。 - - - - Add-on Manager: Warning! - 附加元件管ç†å“¡ï¼šè­¦å‘Š! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - 附加元件管ç†å“¡æä¾›å­˜å–有用的第三方 FreeCAD 擴充功能的廣泛函å¼åº«ã€‚無法ä¿è­‰å…¶å®‰å…¨æ€§æˆ–功能性。 - - - - Continue - 繼續 - - - - Cancel - å–æ¶ˆ - - - - EditDependencyDialog - - - Edit Dependency - ç·¨è¼¯ç›¸ä¾æ€§ - - - - Dependency Type - 相ä¾é¡žåž‹ - - - - Dependency - ç›¸ä¾æ€§ - - - - Package name, if "Other..." - 套件å稱,若 " 其它..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - 注æ„ï¼šå¦‚æžœé¸æ“‡äº† "å…¶ä»–...",該套件ä¸åœ¨ ALLOWED_PYTHON_PACKAGES.txt æ–‡ä»¶ä¸­ï¼Œå°‡ä¸æœƒè¢«é™„加元件管ç†å“¡è‡ªå‹•安è£ã€‚è«‹æäº¤ä¸€å€‹ PR 到 <a href="https://github.com/FreeCAD/FreeCAD-addons">>https://github.com/FreeCAD/FreeCAD-addons</a>,以請求添加該套件。 - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - 如果這是一個å¯é¸ç›¸ä¾ï¼Œé™„加元件管ç†å“¡å°‡åœ¨å¯èƒ½çš„æƒ…æ³ä¸‹æä¾›å®‰è£é¸é …ï¼Œä½†å¦‚æžœä½¿ç”¨è€…é¸æ“‡ä¸å®‰è£æˆ–無法安è£è©²å¥—ä»¶ï¼Œå°‡ä¸æœƒé˜»æ­¢å®‰è£ã€‚ - - - - Optional - é¸ç”¨é … - - - - ExpandedView - - - - Icon - 圖示 - - - - - <h1>Package Name</h1> - <h1>套件å稱</h1> - - - - - Version - 版本 - - - - - (tags) - (標籤) - - - - - Description - 說明 - - - - - Maintainer - 維護者 - - - - Update Available - 有å¯ç”¨æ›´æ–° - - - - labelSort - æ¨™ç±¤æŽ’åº - - - - UpdateAvailable - å¯ç²å¾—æ›´æ–° - - - - Form - - - Licenses - æŽˆæ¬Šæ¢æ¬¾ - - - - License - 版權 - - - - License file - 授權檔案 - - - - People - 人 - - - - Kind - 類別 - - - - Name - å稱 - - - - Email - é›»å­éƒµä»¶ - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - é€²éšŽç‰ˆæœ¬å°æ˜  - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - å³å°‡æŽ¨å‡ºçš„ FreeCAD 附加元件管ç†å“¡çš„版本將支æ´é–‹ç™¼äººå“¡ç‚ºç‰¹å®šç‰ˆæœ¬çš„ FreeCAD è¨­å®šç‰¹å®šçš„åˆ†æ”¯æˆ–æ¨™ç±¤ï¼ˆä¾‹å¦‚ï¼Œè¨­å®šç‰¹å®šçš„æ¨™ç±¤ä½œç‚ºæ‚¨çš„é™„åŠ å…ƒä»¶æ”¯æ´ v0.19 的最後一個版本等)。 - - - - FreeCAD Version - FreeCAD 版本 - - - - Best-available branch, tag, or commit - 最佳å¯ç”¨çš„åˆ†æ”¯ã€æ¨™ç±¤æˆ–æäº¤ - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - 所支æ´ä¹‹ FreeCAD 版本 - - - - Minimum FreeCAD Version Supported - 所支æ´çš„æœ€ä½Ž FreeCAD 版本 - - - - - Optional - é¸ç”¨é … - - - - Maximum FreeCAD Version Supported - 所支æ´çš„æœ€é«˜ FreeCAD 版本 - - - - Advanced version mapping... - é€²éšŽç‰ˆæœ¬å°æ˜ ... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - 附加元件管ç†å“¡é¸é … - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - å¦‚æžœé¸æ“‡æ­¤é¸é …,,則啟動附加元件管ç†å“¡æ™‚, -將檢查已安è£çš„é™„ä»¶å…ƒä»¶æ˜¯å¦æœ‰å¯ç”¨æ›´æ–° - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - 下載巨集後設資料(ç´„ 10 MB) - - - - Cache update frequency - å¿«å–æ›´æ–°é »çއ - - - - Manual (no automatic updates) - 手動 (éžè‡ªå‹•æ›´æ–°) - - - - Daily - æ¯æ—¥ - - - - Weekly - æ¯é€± - - - - Hide Addons without a license - éš±è—æœªæŽˆæ¬Šçš„附加元件 - - - - Hide Addons with non-FSF Free/Libre license - éš±è—具有éžè‡ªç”±è»Ÿé«”基金會(FSF)自由許å¯çš„附加元件 - - - - Hide Addons with non-OSI-approved license - éš±è—具有éžé–‹æ”¾åŽŸå§‹ç¢¼ä¿ƒé€²æœƒï¼ˆOSI)批准的許å¯è­‰çš„附加元件 - - - - Hide Addons marked Python 2 Only - éš±è—æ¨™è¨˜åªèƒ½ä½¿ç”¨æ–¼ Python 2 之附加元件 - - - - Hide Addons marked Obsolete - éš±è—å·²æ¨™è¨˜ç‚ºéŽæ™‚的附加元件 - - - - Hide Addons that require a newer version of FreeCAD - éš±è—éœ€è¦æ›´æ–°ç‰ˆæœ¬çš„ FreeCAD 的附加元件 - - - - Custom repositories - 自訂儲存庫 - - - - Proxy - 代ç†ä¼ºæœå™¨ - - - - No proxy - ä¸ä½¿ç”¨ä»£ç†ä¼ºæœå™¨ - - - - User system proxy - 使用系統代ç†ä¼ºæœå™¨ - - - - User-defined proxy: - 使用者定義的代ç†ä¼ºæœå™¨ï¼š - - - - Score source URL - 得分來æºç¶²å€ - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - 附加元件資料的網å€ï¼ˆè«‹åƒé–±é™„加元件管ç†å“¡ç¶­åŸºé é¢ä»¥æŸ¥çœ‹æ ¼å¼å’Œä¸»æ©Ÿè©³ç´°è³‡è¨Šï¼‰ã€‚ - - - - Path to Git executable (optional): - Git å¯åŸ·è¡Œæª”的路徑(é¸å¡«): - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - 進階é¸é … - - - - Activate Addon Manager options intended for developers of new Addons. - 啟用é‡å°æ–°é™„加元件開發者設計的附加元件管ç†å“¡é¸é …。 - - - - Addon developer mode - é™„åŠ å…ƒä»¶é–‹ç™¼è€…æ¨¡å¼ - - - - PackageDetails - - - Uninstalls a selected macro or workbench - 解除安è£ä¸€é¸å®šå·¨é›†æˆ–å·¥ä½œå° - - - - Install - å®‰è£ - - - - Uninstall - è§£é™¤å®‰è£ - - - - Update - æ›´æ–° - - - - Run Macro - 執行巨集 - - - - Change branch - 變更分支 - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - ç®¡ç† Python ç›¸ä¾æ€§ - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - 以下 Python 套件已由附加元件管ç†å“¡å®‰è£åœ¨æœ¬åœ°ä»¥æ»¿è¶³é™„åŠ å…ƒä»¶ç›¸ä¾æ€§ã€‚安è£ä½ç½®ï¼š - - - - Package name - 套件å稱 - - - - Installed version - 已安è£ç‰ˆæœ¬ - - - - Available version - å¯ç”¨ç‰ˆæœ¬ - - - - Used by - 使用中 - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - 在 "被使用" 列中的星號(*)表示å¯é¸ç›¸ä¾æ€§ã€‚請注æ„,“被使用â€åƒ…記錄附加元件中的直接匯入。這些套件所相ä¾çš„å…¶ä»– Python 套件å¯èƒ½ä¹Ÿå·²å®‰è£ã€‚ - - - - Update all available - 更新所有å¯ç”¨æ›´æ–° - - - - SelectFromList - - - Dialog - å°è©±æ–¹å¡Š - - - - TextLabel - 文字標籤 - - - - UpdateAllDialog - - - Updating Addons - 更新附加元件 - - - - Updating out-of-date addons... - æ­£åœ¨æ›´æ–°éŽæ™‚的附加元件... - - - - addContentDialog - - - Content Item - 內容項目 - - - - Content type: - 內容類型: - - - - Macro - 巨集 - - - - Preference Pack - å好設定包 - - - - Workbench - å·¥ä½œå° - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - 如果這是附加元件中唯一的內容,則所有其他後設資料都å¯ä»¥å¾žæœ€é«˜éšŽç¹¼æ‰¿ï¼Œä¸éœ€è¦åœ¨æ­¤è™•指定。 - - - - This is the only item in the Addon - 這是附加元件中唯一的項目 - - - - Main macro file - 主巨集檔 - - - - The file with the macro's metadata in it - 包å«å·¨é›†å¾Œè¨­è³‡æ–™çš„æª”案 - - - - - - Browse... - ç€è¦½... - - - - Preference Pack Name - å好設定包å稱 - - - - Workbench class name - 工作å°é¡žåˆ¥å稱 - - - - Class that defines "Icon" data member - 定義 "圖示 "資料æˆå“¡ä¹‹é¡žåˆ¥ - - - - Subdirectory - å­ç›®éŒ„ - - - - Optional, defaults to name of content item - å¯é¸é …,é è¨­å€¼ç‚ºå…§å®¹é …目的å稱 - - - - Icon - 圖示 - - - - Optional, defaults to inheriting from top-level Addon - å¯é¸çš„,é è¨­ç¹¼æ‰¿è‡ªæœ€é«˜éšŽé™„加元件 - - - - Tags... - 標籤... - - - - Dependencies... - ç›¸ä¾æ€§... - - - - FreeCAD Versions... - FreeCAD 版本... - - - - Other Metadata - 其它後設資料 - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - 顯示在附加元件管ç†å“¡çš„é™„åŠ å…ƒä»¶åˆ—è¡¨ä¸­ã€‚ä¸æ‡‰åŒ…括單詞 "FreeCAD"。 - - - - Version - 版本 - - - - Description - 說明 - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - æ”¯æ´ Semantic (1.2.3-beta 版) 或 CalVer (2022.08.30 版) 風格 - - - - Set to today (CalVer style) - 設置為今天(CalVeræ ¼å¼ï¼‰ - - - - Display Name - 顯示å稱 - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - 所有未填寫的欄ä½éƒ½æ˜¯ç¹¼æ‰¿è‡ªæœ€é«˜éšŽé™„加元件後設資料,因此從技術上講,它們都是å¯é¸çš„ã€‚å°æ–¼å…·æœ‰å¤šå€‹å…§å®¹é …目的附加元件,æ¯å€‹é …目應æä¾›å”¯ä¸€çš„顯示å稱和æè¿°ã€‚ - - - - add_toolbar_button_dialog - - - Add button? - 添加按鈕? - - - - Add a toolbar button for this macro? - 鏿“‡è¦åŠ å…¥æ­¤å·¨é›†çš„å·¥å…·åˆ—æŒ‰éˆ• ? - - - - Yes - 是 - - - - No - å¦ - - - - Never - æ±ºä¸ - - - - change_branch - - - Change Branch - 變更分支 - - - - Change to branch: - 變更分支: - - - - copyrightInformationDialog - - - Copyright Information - 版權資訊 - - - - Copyright holder: - 版權所有人: - - - - Copyright year: - 版權年份: - - - - personDialog - - - Add Person - 添加人員 - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - 一ä½ç¶­è­·è€…æ˜¯æŒ‡åœ¨è©²å°ˆæ¡ˆä¸Šå…·æœ‰ç›®å‰æäº¤å­˜å–æ¬Šé™çš„人。而作者則是指您'æƒ³è¦æ­¸åŠŸçš„å…¶ä»–ä»»ä½•äººã€‚ - - - - Name: - å稱: - - - - Email: - é›»å­éƒµä»¶ï¼š - - - - Email is required for maintainers, and optional for authors. - ç¶­è­·è€…éœ€è¦æä¾›é›»å­éƒµä»¶ï¼Œè€Œä½œè€…å¯ä»¥é¸æ“‡æ€§æä¾›ã€‚ - - - - proxy_authentication - - - Proxy login required - 代ç†ä¼ºæœå™¨å¿…須登入 - - - - Proxy requires authentication - 代ç†ä¼ºæœå™¨éœ€è¦èªè­‰ - - - - Proxy: - 代ç†ä¼ºæœå™¨: - - - - Placeholder for proxy address - 代ç†ä¼ºæœå™¨ä½å€çš„ä½”ä½ç¬¦è™Ÿ - - - - Realm: - 領域: - - - - Placeholder for proxy realm - 代ç†ä¼ºæœå™¨é ˜åŸŸçš„ä½”ä½ç¬¦è™Ÿ - - - - Username - 使用者å稱 - - - - Password - 密碼 - - - - selectLicenseDialog - - - Select a license - 鏿“‡æŽˆæ¬Š - - - - About... - 關於... - - - - License name: - 許å¯è­‰å稱: - - - - Path to license file: - 授權檔案路徑: - - - - (if required by license) - (如果根據許å¯è­‰è¦æ±‚) - - - - Browse... - ç€è¦½... - - - - Create... - 建立... - - - - select_toolbar_dialog - - - - - - Select Toolbar - 鏿“‡å·¥å…·åˆ— - - - - Select a toolbar to add this macro to: - 鏿“‡è¦åŠ å…¥æ­¤å·¨é›†çš„å·¥å…·åˆ—: - - - - Ask every time - æ¯æ¬¡éƒ½è©¢å• - - - - toolbar_button - - - - Add button? - 添加按鈕? - - - - Add a toolbar button for this macro? - 鏿“‡è¦åŠ å…¥æ­¤å·¨é›†çš„å·¥å…·åˆ—æŒ‰éˆ• ? - - - - Yes - 是 - - - - No - å¦ - - - - Never - æ±ºä¸ - - - - AddonsInstaller - - - Starting up... - 啟動中... - - - - Worker process {} is taking a long time to stop... - 工作行程 {} æ­£åœ¨èŠ±è²»è¼ƒé•·æ™‚é–“åœæ­¢... - - - - Previous cache process was interrupted, restarting... - - å…ˆå‰å¿«å–è¡Œç¨‹è¢«ä¸­æ–·ï¼Œæ­£åœ¨é‡æ–°å•Ÿå‹•... - - - - Custom repo list changed, forcing recache... - - è‡ªè¨‚å„²å­˜åº«åˆ—è¡¨å·²æ›´æ”¹ï¼Œæ­£åœ¨å¼·åˆ¶é‡æ–°å¿«å–... - - - - - Addon manager - 附加元件管ç†å“¡ - - - - You must restart FreeCAD for changes to take effect. - æ‚¨å¿…é ˆé‡æ–°å•Ÿå‹• FreeCAD 以使更改生效。 - - - - Restart now - ç¾åœ¨é‡æ–°å•Ÿå‹• - - - - Restart later - ç¨å¾Œé‡æ–°å•Ÿå‹• - - - - - Refresh local cache - åˆ·æ–°æœ¬åœ°ç«¯å¿«å– - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - æ›´æ–°å¿«å–... - - - - - Checking for updates... - 檢查更新... - - - - Temporary installation of macro failed. - 巨集的暫存安è£å¤±æ•—。 - - - - - Close - 關閉 - - - - Update all addons - 更新所有附加元件 - - - - Check for updates - 檢查更新 - - - - Python dependencies... - Python ç›¸ä¾æ€§... - - - - Developer tools... - 開發者工具... - - - - Apply %n available update(s) - 套用 %n å¯ç”¨æ›´æ–° - - - - No updates available - 沒有å¯ç”¨æ›´æ–° - - - - - - Cannot launch a new installer until the previous one has finished. - 在å‰ä¸€å€‹å®‰è£ç¨‹å¼å®Œæˆä¹‹å‰ç„¡æ³•啟動新的安è£ç¨‹å¼ã€‚ - - - - - - - Maintainer - 維護者 - - - - - - - Author - 作者 - - - - New Python Version Detected - 嵿¸¬åˆ°æ–°çš„ Python 版本 - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - 這似乎是第一次使用這個版本的 Python 與附加元件管ç†å“¡ã€‚æ‚¨æ˜¯å¦æƒ³è¦ç‚ºå…¶å®‰è£ç›¸åŒçš„自動安è£ç›¸ä¾å¥—件? - - - - Processing, please wait... - 處ç†ä¸­ï¼Œè«‹ç¨å€™... - - - - - Update - æ›´æ–° - - - - Updating... - 正在更新... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - 無法匯入 QtNetwork -- 該套件似乎未安è£åœ¨æ‚¨çš„系統上。您的供應商å¯èƒ½æä¾›äº†æ­¤ç›¸ä¾æ€§å¥—件(通常被稱為 "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - 無法將指定的代ç†ä¼ºæœå™¨åŸ  '{}' 轉æ›ç‚ºåŸ çš„編號 - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - åƒæ•¸éŒ¯èª¤ï¼šè¨­å®šäº’斥代ç†ä¼ºæœå™¨é¸é …。é‡ç½®ç‚ºé è¨­å€¼ã€‚ - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - åƒæ•¸éŒ¯èª¤ï¼šæŒ‡ç¤ºä½¿ç”¨è€…代ç†ä¼ºæœå™¨ï¼Œä½†ä¸¦æœªæä¾›ã€‚é‡ç½®ç‚ºé è¨­å€¼ã€‚ - - - - Addon Manager: Unexpected {} response from server - 附加元件管ç†å“¡ï¼šå¾žä¼ºæœå™¨æ”¶åˆ°æ„外的 {} 回應 - - - - Error with encrypted connection - 加密連線出ç¾éŒ¯èª¤ - - - - - - Confirm remove - 確èªç§»é™¤ - - - - Are you sure you want to uninstall {}? - 您確定è¦è§£é™¤å®‰è£ {} 嗎? - - - - - - Removing Addon - 移除附加元件 - - - - Removing {} - 正在刪除 {} - - - - - Uninstall complete - 解除安è£å®Œæˆ - - - - - Uninstall failed - 解除安è£å¤±æ•— - - - - Version {version} installed on {date} - 版本 {version} 已於 {date} å®‰è£ - - - - Version {version} installed - 版本 {version} å·²å®‰è£ - - - - Installed on {date} - å®‰è£æ–¼ {date} - - - - - - - Installed - å·±å®‰è£ - - - - Currently on branch {}, name changed to {} - ç›®å‰åœ¨åˆ†æ”¯ {},å稱已更改為 {} - - - - Git tag '{}' checked out, no updates possible - 已檢查 Git 標籤 '{}',無法進行更新 - - - - Update check in progress - 正在檢查更新 - - - - Installation location - 安è£ä½ç½® - - - - Repository URL - å„²å­˜åº«ç¶²å€ - - - - Changed to branch '{}' -- please restart to use Addon. - 已切æ›è‡³åˆ†æ”¯ '{}' -- è«‹é‡æ–°å•Ÿå‹•以使用附加元件。 - - - - This Addon has been updated. Restart FreeCAD to see changes. - é€™å€‹é™„åŠ å…ƒä»¶å·²ç¶“æ›´æ–°ã€‚è«‹é‡æ–°å•Ÿå‹• FreeCAD 以查看變更。 - - - - Disabled - å·²åœç”¨ - - - - Currently on branch {}, update available to version {} - ç›®å‰åœ¨åˆ†æ”¯ {},有å¯ç”¨çš„æ›´æ–°è‡³ç‰ˆæœ¬ {} - - - - Update available to version {} - å¯å‡ç´šè‡³ç‰ˆæœ¬ {} - - - - This is the latest version available - 這是目å‰å¯ç”¨çš„æœ€æ–°ç‰ˆæœ¬ - - - - WARNING: This addon is obsolete - è­¦å‘Šï¼šæ­¤é™„åŠ å…ƒä»¶å·²éŽæ™‚ - - - - WARNING: This addon is Python 2 only - 警告:此附加元件僅支æŒPython 2 - - - - WARNING: This addon requires FreeCAD {} - è­¦å‘Šï¼šæ­¤é™„åŠ å…ƒä»¶éœ€è¦ FreeCAD {} - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - 警告:此附加元件目å‰å·²å®‰è£ï¼Œä½†æ˜¯è¢«åœç”¨ã€‚使用 '啟用' æŒ‰éˆ•ä»¥é‡æ–°å•Ÿç”¨ã€‚ - - - - This Addon will be enabled next time you restart FreeCAD. - æ­¤é™„åŠ å…ƒä»¶å°‡æœƒåœ¨æ‚¨é‡æ–°èµ·å‹• FreeCAD 後啟用。 - - - - This Addon will be disabled next time you restart FreeCAD. - æ­¤é™„åŠ å…ƒä»¶å°‡æœƒåœ¨æ‚¨é‡æ–°èµ·å‹• FreeCAD 後åœç”¨ã€‚ - - - - - - Success - æˆåŠŸ - - - - Install - å®‰è£ - - - - Uninstall - è§£é™¤å®‰è£ - - - - Enable - 啟用 - - - - Disable - åœç”¨ - - - - - Check for update - 檢查更新 - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - 執行 - - - - Change branch... - 變更分支... - - - - Return to package list - 返回套件列表 - - - - Checking connection - 正在檢查連線 - - - - Checking for connection to GitHub... - 正在檢查通往 GitHub 之連線... - - - - Connection failed - 連線失敗 - - - - Missing dependency - 缺少相ä¾å¥—ä»¶ - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - 無法匯入 QtNetwork - è«‹åƒé–±å ±å‘Šæª¢è¦–以了解細節。附加元件管ç†å“¡ä¸å¯ç”¨ã€‚ - - - - Other... - For providing a license other than one listed - å…¶ä»–... - - - - Select the corresponding license file in your Addon - 鏿“‡é™„åŠ å…ƒä»¶ä¸­ç›¸å°æ‡‰çš„æŽˆæ¬Šæª”案 - - - - Location for new license file - 新授權檔案的ä½ç½® - - - - Received {} response code from server - 由伺æœå™¨æ”¶åˆ° {} 回應碼 - - - - Failed to install macro {} - 安è£å·¨é›† {} 失敗 - - - - Failed to create installation manifest file: - - ç„¡æ³•å»ºç«‹å®‰è£æ¸…單檔案: - - - - - Unrecognized content kind '{}' - 未識別的內容種類 '{}' - - - - Unable to locate icon at {} - 無法在 {} ä½ç½®æ‰¾åˆ°åœ–示 - - - - Select an icon file for this content item - 鏿“‡ä¸€å€‹ç”¨æ–¼æ­¤å…§å®¹é …目的圖示檔案 - - - - - - {} is not a subdirectory of {} - {} 䏿˜¯ {} 的一個å­ç›®éŒ„ - - - - Select the subdirectory for this content item - 鏿“‡ä¸€å€‹ç”¨æ–¼æ­¤å…§å®¹é …目的å­ç›®éŒ„ - - - - Automatic - 自動 - - - - - Workbench - å·¥ä½œå° - - - - Addon - 附加元件 - - - - Python - Python - - - - Yes - 是 - - - - Internal Workbench - å…§éƒ¨å·¥ä½œå° - - - - External Addon - 外部附加元件 - - - - Python Package - Python 套件 - - - - - Other... - å…¶ä»–... - - - - Too many to list - 太多以至於無法列出 - - - - - - - - - Missing Requirement - ç¼ºå°‘è¦æ±‚ - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - 附加元件 '{}' éœ€è¦ '{}',但在您的 FreeCAD 版本中ä¸å¯ç”¨ã€‚ - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - 附加元件 '{}' 需è¦åº•下工作å°ï¼Œä½†åœ¨æ‚¨çš„ FreeCAD 版本中ä¸å¯ç”¨ã€‚ - - - - Press OK to install anyway. - 按 OK 以進行安è£ã€‚ - - - - - Incompatible Python version - ä¸ç›¸å®¹çš„ Python 版本 - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - æ­¤é™„åŠ å…ƒä»¶éœ€è¦æœªå®‰è£çš„ Python 套件,無法自動安è£ã€‚è¦ä½¿ç”¨æ­¤å·¥ä½œå°ï¼Œæ‚¨å¿…須手動安è£ä»¥ä¸‹ Python 套件: - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - 此附加元件 (或其一相ä¾å…ƒä»¶) éœ€è¦ Python {}.{}, 而您的系統正在執行 {}.{}. 安è£å–消. - - - - Optional dependency on {} ignored because it is not in the allow-list - å¯é¸ç›¸ä¾æ€§ {} 被忽略因其ä¸åœ¨å¯å…許清單中 - - - - - Installing dependencies - 正在安è£ç›¸ä¾æ€§ - - - - - Cannot execute Python - 無法執行 Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - è‡ªå‹•å®šä½æ‚¨çš„ Python å¯åŸ·è¡Œæª”å¤±æ•—ï¼Œæˆ–è€…è¨­ç½®çš„è·¯å¾‘ä¸æ­£ç¢ºã€‚請檢查附加元件管ç†å“¡å好設定中 Python 路徑的設置。 - - - - Dependencies could not be installed. Continue with installation of {} anyway? - ç›¸ä¾æ€§å¥—件無法被安è£ã€‚無論如何繼續 {} 的安è£ä½œæ¥­ï¼Ÿ - - - - - Cannot execute pip - 無法執行 pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - 無法執行 pip,å¯èƒ½æ˜¯å› ç‚ºæ‚¨çš„ Python 安è£ç¼ºå°‘ pipã€‚è«‹ç¢ºä¿æ‚¨çš„ç³»çµ±å·²å®‰è£ pip,然後å†è©¦ä¸€æ¬¡ã€‚失敗的指令是: - - - - - Continue with installation of {} anyway? - ä¸ç®¡æ€Žæ¨£ç¹¼çºŒå®‰è£ {} ? - - - - - Package installation failed - 套件安è£å¤±æ•— - - - - See Report View for detailed failure log. - 詳細的失敗日誌請查看報告檢視。 - - - - Installing Addon - 安è£é™„加元件 - - - - Installing FreeCAD Addon '{}' - å®‰è£ FreeCAD 附加元件 '{}' - - - - Cancelling - æ­£åœ¨å–æ¶ˆ - - - - Cancelling installation of '{}' - å–æ¶ˆå®‰è£ '{}' - - - - {} was installed successfully - {} å·²æˆåŠŸå®‰è£ - - - - - Installation Failed - 安è£å¤±æ•— - - - - Failed to install {} - {} 安è£å¤±æ•— - - - - - Create new toolbar - 建立新工具列 - - - - - A macro installed with the FreeCAD Addon Manager - 使用 FreeCAD 附加元件管ç†å“¡å®‰è£çš„巨集 - - - - - Run - Indicates a macro that can be 'run' - 執行 - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - 無法自 GitHub 讀å–資料:請檢查您的網路連線與代ç†ä¼ºæœå™¨è¨­å®šä¸¦ä¸”冿¬¡å˜—試。 - - - - XML failure while reading metadata from file {} - è®€å–æª”案 {} 中的後設資料時發生 XML 錯誤 - - - - Invalid metadata in file {} - 在檔案 {} 中無效的後設資料 - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - 警告:在 package.xml å¾Œè¨­è³‡æ–™ä¸­æŒ‡å®šçš„è·¯å¾‘èˆ‡ç•¶å‰æª¢æŸ¥å‡ºçš„分支ä¸åŒ¹é…。 - - - - Name - å稱 - - - - Class - 類別 (Class) - - - - Description - 說明 - - - - Subdirectory - å­ç›®éŒ„ - - - - Files - 檔案 - - - - Select the folder containing your Addon - 鏿“‡å…§å«ä½ çš„附加元件之資料夾 - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - 沒有 Vermin å¥—ä»¶ï¼Œæ­£åœ¨å–æ¶ˆæ“作。 - - - - Scanning Addon for Python version compatibility - 掃æé™„加元件以檢查 Python 版本的相容性 - - - - Minimum Python Version Detected - 嵿¸¬åˆ°çš„æœ€ä½Ž Python 版本 - - - - Vermin auto-detected a required version of Python 3.{} - Vermin 自動檢測到所需的 Python 3.{} 版本 - - - - Install Vermin? - å®‰è£ Vermin 套件? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - è‡ªå‹•åµæ¸¬æ­¤é™„加元件所需的 Python 版本需è¦ä½¿ç”¨ Vermin 套件 -(https://pypi.org/project/vermin/)ã€‚ç¢ºå®šå®‰è£ ? - - - - Attempting to install Vermin from PyPi - 試圖從 PyPi å®‰è£ Vermin 套件 - - - - - Installation failed - 安è£å¤±æ•— - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - å®‰è£ Vermin 套件失敗 - 檢查報告檢視以看細節。 - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - 安è£å¾Œç„¡æ³•匯入 vermin - 無法掃瞄附加元件。 - - - - Select an icon file for this package - 鏿“‡ä¸€å€‹ç”¨æ–¼æ­¤å¥—件的圖示檔案 - - - - Filter is valid - éŽæ¿¾å™¨æœ‰æ•ˆ - - - - Filter regular expression is invalid - éŽæ¿¾å™¨æ­£è¦è¡¨ç¤ºå¼ç„¡æ•ˆ - - - - Search... - æœå°‹... - - - - Click for details about package {} - 點擊查看套件 {} 詳細資料 - - - - Click for details about workbench {} - é»žæ“ŠæŸ¥çœ‹å·¥ä½œå° {} 詳細資料 - - - - Click for details about macro {} - 點擊查看巨集 {} 詳細資料 - - - - Maintainers: - 維護者: - - - - Tags - 標籤 - - - - {} ★ on GitHub - 在 GitHub 上的星數 {} ★ - - - - No ★, or not on GitHub - 沒有星星 ★,或ä¸å­˜åœ¨ GitHub 上 - - - - Created - 已建立 - - - - Updated - 已更新 - - - - Score: - 分數: - - - - - Up-to-date - 最新 - - - - - - - - Update available - 有å¯ç”¨æ›´æ–° - - - - - Pending restart - 等待é‡å•Ÿ - - - - - DISABLED - 已被åœç”¨ - - - - Installed version - 已安è£ç‰ˆæœ¬ - - - - Unknown version - 未知版本 - - - - Installed on - 安è£åœ¨ - - - - Available version - å¯ç”¨ç‰ˆæœ¬ - - - - Filter by... - 便“š...éŽæ¿¾ - - - - Addon Type - 附加元件類型 - - - - - Any - 任何 - - - - Macro - 巨集 - - - - Preference Pack - å好設定包 - - - - Installation Status - 安è£ç‹€æ…‹ - - - - Not installed - æœªå®‰è£ - - - - Filter - éŽæ¿¾å™¨ - - - - DANGER: Developer feature - å±éšªï¼šé–‹ç™¼è€…功能 - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - å±éšªï¼šåˆ†æ”¯åˆ‡æ›æ˜¯é‡å°é–‹ç™¼äººå“¡å’Œæ¸¬è©¦ç‰ˆæœ¬çš„,å¯èƒ½å°Žè‡´æå£žã€ä¸å‘後相容的文件ã€ä¸ç©©å®šæ€§ã€å´©æ½°ï¼Œå’Œ/或宇宙的æå‰ç†±æ­»ã€‚您確定è¦ç¹¼çºŒå—Žï¼Ÿ - - - - There are local changes - 這些是本地更改 - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - 警告:此存儲庫具有未æäº¤çš„æœ¬åœ°æ›´æ”¹ã€‚您確定è¦åˆ‡æ›åˆ†æ”¯ï¼ˆå°‡æ›´æ”¹å¸¶å…¥æ–°åˆ†æ”¯ï¼‰å—Žï¼Ÿ - - - - Local - Table header for local git ref name - 本地 - - - - Remote tracking - Table header for git remote tracking branch name - é ç«¯è¿½è¹¤ - - - - Last Updated - Table header for git update date - 上次更新 - - - - Installation of Python package {} failed - å®‰è£ Python 套件 {} 失敗 - - - - Installation of optional package failed - 安è£å¯é¸å¥—件失敗 - - - - Installing required dependency {} - å®‰è£æ‰€éœ€çš„ç›¸ä¾æ€§å¥—ä»¶ {} - - - - Installation of Addon {} failed - 安è£é™„加元件 {} 失敗 - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - 解碼附加元件的檔案 {} 失敗 '{}' - - - - Any dependency information in this file will be ignored - æ­¤æª”æ¡ˆä¸­çš„ä»»ä½•ç›¸ä¾æ€§è³‡è¨Šå°‡æœƒè¢«å¿½ç•¥ - - - - Unable to open macro wiki page at {} - 無法打開巨集維基é é¢ {} - - - - Unable to fetch the code of this macro. - 無法å–得這個巨集的程å¼ç¢¼ã€‚ - - - - Unable to retrieve a description from the wiki for macro {} - 無法從維基ç²å–巨集 {} çš„æè¿° - - - - Unable to open macro code URL {} - 無法打開巨集程å¼ç¢¼çš„ç¶²å€ {} - - - - Unable to fetch macro-specified file {} from {} - 無法從 {} æ“·å–巨集指定的檔案 {} - - - - Could not locate macro-specified file {} (expected at {}) - 無法找到巨集指定的檔案 {}ï¼ˆé æœŸåœ¨ {}) - - - - {}: Unrecognized internal workbench '{}' - {}ï¼šæœªè­˜åˆ¥çš„å…§éƒ¨å·¥ä½œå° '{}' - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - 附加元件開發者警告:給附加元件{} ({}) 之 package.xml 檔中的儲存庫網å€é›†èˆ‡æˆªå–自 ({}) 的網å€ä¸åŒ¹é… - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - 附加元件開發者警告:給附加元件{} ({}) 之 package.xml 檔中的儲存庫分支集與截å–自 ({}) 的分支ä¸åŒ¹é… - - - - - Got an error when trying to import {} - 當試著匯入 {} 時發生錯誤 - - - - An unknown error occurred - 發生未知的錯誤 - - - - Could not find addon {} to remove it. - 找ä¸åˆ°è¦ç§»é™¤çš„附加元件 {}。 - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - 無法執行附加元件的 uninstall.py 腳本。繼續進行解除安è£... - - - - Removed extra installed file {} - å·²ç§»é™¤å¤šé¤˜å·²å®‰è£æª”案 {} - - - - Error while trying to remove extra installed file {} - 當試著移除é¡å¤–å·²å®‰è£æª”案 {} 時發生錯誤 - - - - Error while trying to remove macro file {}: - 當試著移除巨集檔 {} 時發生錯誤: - - - - Failed to connect to GitHub. Check your connection and proxy settings. - 連接到 GitHub 失敗。請檢查您的連線與代ç†ä¼ºæœå™¨è¨­å®šã€‚ - - - - WARNING: Duplicate addon {} ignored - 警告:é‡è¤‡çš„附加元件 {} 被忽略 - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - 自 GitHub 更新巨集時發生錯誤,試著進行乾淨檢查... - - - - Attempting to do a clean checkout... - ä¼åœ–進行一個乾淨的檢查... - - - - Clean checkout succeeded - 乾淨檢查æˆåŠŸ - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - 無法從 GitHub 更新巨集 - 請嘗試清除附加元件管ç†å“¡çš„å¿«å–。 - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - 連接到維基時出ç¾éŒ¯èª¤ï¼ŒFreeCAD ç›®å‰ç„¡æ³•檢索維基巨集列表 - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - ç”± {name} 讀å–後設資料失敗 - - - - Failed to fetch code for macro '{name}' - 無法擷å–巨集 '{name}' 的程å¼ç¢¼ - - - - Addon Manager: a worker process failed to complete while fetching {name} - 附加元件管ç†å“¡ï¼šåœ¨æ“·å– {name} æ™‚ï¼Œå·¥ä½œè¡Œç¨‹æœªèƒ½å®Œæˆ - - - - Out of {num_macros} macros, {num_failed} timed out while processing - 在 {num_macros} 個巨集中,有 {num_failed} å€‹åœ¨è™•ç†æ™‚超時。 - - - - Addon Manager: a worker process failed to halt ({name}) - 附加元件管ç†å“¡ï¼šåœ¨åœæ­¢ ({name}) æ™‚ï¼Œå·¥ä½œè¡Œç¨‹æœªèƒ½å®Œæˆ - - - - Timeout while fetching metadata for macro {} - 在擷å–巨集 {} 的後設資料時超時 - - - - Failed to kill process for macro {}! - - 無法終止巨集 {} çš„è¡Œç¨‹ï¼ - - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - 無法從 {} ç²å–附加元件統計資料 — 僅以字æ¯é †åºæŽ’åºå°‡æ˜¯æº–確的 - - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - 無法從 '{}' ç²å–附加元件分數 — 按分數排åºå°‡å¤±æ•— - - - - - Repository URL - Preferences header for custom repositories - å„²å­˜åº«ç¶²å€ - - - - Branch name - Preferences header for custom repositories - 分支å稱 - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - å‚™ä»½åŽŸå§‹ç›®éŒ„ä¸¦é‡æ–°å…‹éš† - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Git 分支é‡å‘½å失敗,出ç¾ä»¥ä¸‹è¨Šæ¯ï¼š - - - - Installing - 安è£ä¸­ - - - - Succeeded - æˆåŠŸ - - - - Failed - 失敗 - - - - Update was cancelled - æ›´æ–°å·²å–æ¶ˆ - - - - some addons may have been updated - æŸäº›é™„加元件å¯èƒ½å·²ç¶“被更新了 - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - 從 FreeCAD 巨集食譜維基載入 {} 的資訊... - - - - Loading page for {} from {}... - 從 {} 載入 {} çš„é é¢... - - - - Failed to download data from {} -- received response code {}. - 無法從 {} 下載資料 — 收到回應碼 {}。 - - - - Composite view - 組åˆè¦–圖 - - - - Expanded view - 擴展視圖 - - - - Compact view - 精簡視圖 - - - - Alphabetical - Sort order - 按字æ¯é †åºçš„ - - - - Last Updated - Sort order - 上次更新 - - - - Date Created - Sort order - 建立日期 - - - - GitHub Stars - Sort order - GitHub的星星數 - - - - Score - Sort order - 得分 - - - - Std_AddonMgr - - - &Addon manager - &附加元件管ç†å“¡ - - - - Manage external workbenches, macros, and preference packs - 管ç†å¤–部工作å°ã€å·¨é›†å’Œå好設定套件 - - - - AddonInstaller - - - Finished removing {} - 完æˆç§»é™¤ {} - - - - Failed to remove some files - 移除æŸäº›æª”案失敗 - - - - Addons installer - - - Finished updating the following addons - å·²å®Œæˆæ›´æ–°åº•下附加元件 - - - - Workbench - - - Auto-Created Macro Toolbar - 自動建立之巨集工具列 - - - - QObject - - - Addon Manager - 附加元件管ç†å“¡ - - - diff --git a/src/Mod/AddonManager/TODO.md b/src/Mod/AddonManager/TODO.md deleted file mode 100644 index b1d3e7735f..0000000000 --- a/src/Mod/AddonManager/TODO.md +++ /dev/null @@ -1,8 +0,0 @@ -# Addon Manager Future Work - -* Reduce coupling between data and UI, switching logical groupings of widgets into a MVC or similar framework. - * Particularly in the addons list -* Implement a server-side cache of Addon metadata. -* Implement an "offline mode" that does not attempt to use remote data for anything. -* When installing a Preference Pack, offer to apply it once installed, and to undo after that. -* Better support "headless" mode, with no GUI. diff --git a/src/Mod/AddonManager/TestAddonManagerApp.py b/src/Mod/AddonManager/TestAddonManagerApp.py deleted file mode 100644 index 12392ea2c5..0000000000 --- a/src/Mod/AddonManager/TestAddonManagerApp.py +++ /dev/null @@ -1,100 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import addonmanager_freecad_interface as fci - -# Unit tests for the Addon Manager module -from AddonManagerTest.app.test_utilities import ( - TestUtilities as AddonManagerTestUtilities, -) -from AddonManagerTest.app.test_addon import ( - TestAddon as AddonManagerTestAddon, -) -from AddonManagerTest.app.test_cache import ( - TestCache as AddonManagerTestCache, -) -from AddonManagerTest.app.test_macro import ( - TestMacro as AddonManagerTestMacro, -) -from AddonManagerTest.app.test_git import ( - TestGit as AddonManagerTestGit, -) -from AddonManagerTest.app.test_installer import ( - TestAddonInstaller as AddonManagerTestAddonInstaller, - TestMacroInstaller as AddonManagerTestMacroInstaller, -) -from AddonManagerTest.app.test_dependency_installer import ( - TestDependencyInstaller as AddonManagerTestDependencyInstaller, -) -from AddonManagerTest.app.test_uninstaller import ( - TestAddonUninstaller as AddonManagerTestAddonUninstaller, - TestMacroUninstaller as AddonManagerTestMacroUninstaller, -) -from AddonManagerTest.app.test_freecad_interface import ( - TestConsole as AddonManagerTestConsole, - TestParameters as AddonManagerTestParameters, - TestDataPaths as AddonManagerTestDataPaths, -) -from AddonManagerTest.app.test_metadata import ( - TestDependencyType as AddonManagerTestDependencyType, - TestMetadataReader as AddonManagerTestMetadataReader, - TestMetadataReaderIntegration as AddonManagerTestMetadataReaderIntegration, - TestUrlType as AddonManagerTestUrlType, - TestVersion as AddonManagerTestVersion, - TestMetadataAuxiliaryFunctions as AddonManagerTestMetadataAuxiliaryFunctions, -) - - -class TestListTerminator: - pass - - -# Basic usage mostly to get static analyzers to stop complaining about unused imports -try: - import FreeCAD -except ImportError: - FreeCAD = None -loaded_gui_tests = [ - AddonManagerTestUtilities, - AddonManagerTestAddon, - AddonManagerTestCache, - AddonManagerTestMacro, - AddonManagerTestGit, - AddonManagerTestAddonInstaller, - AddonManagerTestMacroInstaller, - AddonManagerTestDependencyInstaller, - AddonManagerTestAddonUninstaller, - AddonManagerTestMacroUninstaller, - AddonManagerTestConsole, - AddonManagerTestParameters, - AddonManagerTestDataPaths, - AddonManagerTestDependencyType, - AddonManagerTestMetadataReader, - AddonManagerTestMetadataReaderIntegration, - AddonManagerTestUrlType, - AddonManagerTestVersion, - AddonManagerTestMetadataAuxiliaryFunctions, - TestListTerminator, # Needed to prevent the last test from running twice -] -for test in loaded_gui_tests: - fci.Console.PrintLog(f"Loaded tests from {test.__name__}\n") diff --git a/src/Mod/AddonManager/TestAddonManagerGui.py b/src/Mod/AddonManager/TestAddonManagerGui.py deleted file mode 100644 index 25202537f1..0000000000 --- a/src/Mod/AddonManager/TestAddonManagerGui.py +++ /dev/null @@ -1,65 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -import addonmanager_freecad_interface as fci - -# Unit test for the Addon Manager module GUI -from AddonManagerTest.gui.test_gui import TestGui as AddonManagerTestGui - -from AddonManagerTest.gui.test_workers_utility import ( - TestWorkersUtility as AddonManagerTestWorkersUtility, -) -from AddonManagerTest.gui.test_workers_startup import ( - TestWorkersStartup as AddonManagerTestWorkersStartup, -) -from AddonManagerTest.gui.test_installer_gui import ( - TestInstallerGui as AddonManagerTestInstallerGui, -) -from AddonManagerTest.gui.test_installer_gui import ( - TestMacroInstallerGui as AddonManagerTestMacroInstallerGui, -) -from AddonManagerTest.gui.test_update_all_gui import ( - TestUpdateAllGui as AddonManagerTestUpdateAllGui, -) -from AddonManagerTest.gui.test_uninstaller_gui import ( - TestUninstallerGUI as AddonManagerTestUninstallerGUI, -) - - -class TestListTerminator: - pass - - -# Basic usage mostly to get static analyzers to stop complaining about unused imports -loaded_gui_tests = [ - AddonManagerTestGui, - AddonManagerTestWorkersUtility, - AddonManagerTestWorkersStartup, - AddonManagerTestInstallerGui, - AddonManagerTestMacroInstallerGui, - AddonManagerTestUpdateAllGui, - AddonManagerTestUninstallerGUI, - TestListTerminator, # Needed to prevent the last test from running twice -] -for test in loaded_gui_tests: - fci.Console.PrintLog(f"Loaded tests from {test.__name__}\n") diff --git a/src/Mod/AddonManager/Widgets/CMakeLists.txt b/src/Mod/AddonManager/Widgets/CMakeLists.txt deleted file mode 100644 index 939e257e2e..0000000000 --- a/src/Mod/AddonManager/Widgets/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -SET(AddonManagerWidget_SRCS - __init__.py - addonmanager_colors.py - addonmanager_widget_addon_buttons.py - addonmanager_widget_filter_selector.py - addonmanager_widget_global_buttons.py - addonmanager_widget_package_details_view.py - addonmanager_widget_progress_bar.py - addonmanager_widget_readme_browser.py - addonmanager_widget_search.py - addonmanager_widget_view_control_bar.py - addonmanager_widget_view_selector.py -) - -SOURCE_GROUP("" FILES ${AddonManagerWidget_SRCS}) - -ADD_CUSTOM_TARGET(AddonManagerWidget ALL - SOURCES ${AddonManagerWidget_SRCS} -) - -fc_copy_sources(AddonManagerWidget "${CMAKE_BINARY_DIR}/Mod/AddonManager/Widgets" ${AddonManagerWidget_SRCS}) - -INSTALL( - FILES - ${AddonManagerWidget_SRCS} - DESTINATION - Mod/AddonManager/Widgets -) diff --git a/src/Mod/AddonManager/Widgets/__init__.py b/src/Mod/AddonManager/Widgets/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Mod/AddonManager/Widgets/addonmanager_colors.py b/src/Mod/AddonManager/Widgets/addonmanager_colors.py deleted file mode 100644 index 7d08a07421..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_colors.py +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -from enum import Enum, auto - -import FreeCADGui -from PySide import QtGui - - -def is_darkmode() -> bool: - """Heuristics to determine if we are in a darkmode stylesheet""" - pl = FreeCADGui.getMainWindow().palette() - return pl.color(QtGui.QPalette.Window).lightness() < 128 - - -def warning_color_string() -> str: - """A shade of red, adapted to darkmode if possible. Targets a minimum 7:1 contrast ratio.""" - return "rgb(255,105,97)" if is_darkmode() else "rgb(215,0,21)" - - -def bright_color_string() -> str: - """A shade of green, adapted to darkmode if possible. Targets a minimum 7:1 contrast ratio.""" - return "rgb(48,219,91)" if is_darkmode() else "rgb(36,138,61)" - - -def attention_color_string() -> str: - """A shade of orange, adapted to darkmode if possible. Targets a minimum 7:1 contrast ratio.""" - return "rgb(255,179,64)" if is_darkmode() else "rgb(255,149,0)" diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py deleted file mode 100644 index e5ffc3fdc1..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py +++ /dev/null @@ -1,118 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a QWidget-derived class for displaying the single-addon buttons.""" - -from enum import Enum, auto - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(_: str, text: str): - return text - - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore, QtGui, QtWidgets - - -class ButtonBarDisplayMode(Enum): - TextOnly = auto() - IconsOnly = auto() - TextAndIcons = auto() - - -class WidgetAddonButtons(QtWidgets.QWidget): - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.display_mode = ButtonBarDisplayMode.TextAndIcons - self._setup_ui() - self._set_icons() - self.retranslateUi(None) - - def set_display_mode(self, mode: ButtonBarDisplayMode): - """NOTE: Not really implemented yet -- TODO: Implement this functionality""" - if mode == self.display_mode: - return - self._setup_ui() - self._set_icons() - self.retranslateUi(None) - - def _setup_ui(self): - if self.layout(): - self.setLayout(None) # TODO: Check this - self.horizontal_layout = QtWidgets.QHBoxLayout() - self.horizontal_layout.setContentsMargins(0, 0, 0, 0) - self.back = QtWidgets.QToolButton(self) - self.install = QtWidgets.QPushButton(self) - self.uninstall = QtWidgets.QPushButton(self) - self.enable = QtWidgets.QPushButton(self) - self.disable = QtWidgets.QPushButton(self) - self.update = QtWidgets.QPushButton(self) - self.run_macro = QtWidgets.QPushButton(self) - self.change_branch = QtWidgets.QPushButton(self) - self.check_for_update = QtWidgets.QPushButton(self) - self.horizontal_layout.addWidget(self.back) - self.horizontal_layout.addStretch() - self.horizontal_layout.addWidget(self.check_for_update) - self.horizontal_layout.addWidget(self.install) - self.horizontal_layout.addWidget(self.uninstall) - self.horizontal_layout.addWidget(self.enable) - self.horizontal_layout.addWidget(self.disable) - self.horizontal_layout.addWidget(self.update) - self.horizontal_layout.addWidget(self.run_macro) - self.horizontal_layout.addWidget(self.change_branch) - self.setLayout(self.horizontal_layout) - - def set_show_back_button(self, show: bool) -> None: - self.back.setVisible(show) - - def _set_icons(self): - self.back.setIcon(QtGui.QIcon.fromTheme("back", QtGui.QIcon(":/icons/button_left.svg"))) - - def retranslateUi(self, _): - self.check_for_update.setText(translate("AddonsInstaller", "Check for update")) - self.install.setText(translate("AddonsInstaller", "Install")) - self.uninstall.setText(translate("AddonsInstaller", "Uninstall")) - self.disable.setText(translate("AddonsInstaller", "Disable")) - self.enable.setText(translate("AddonsInstaller", "Enable")) - self.update.setText(translate("AddonsInstaller", "Update")) - self.run_macro.setText(translate("AddonsInstaller", "Run")) - self.change_branch.setText(translate("AddonsInstaller", "Change branch...")) - self.back.setToolTip(translate("AddonsInstaller", "Return to package list")) diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py deleted file mode 100644 index bb07ee3a28..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py +++ /dev/null @@ -1,259 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a QWidget-derived class for displaying the view selection buttons.""" - -from enum import IntEnum - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(_: str, text: str): - return text - - -# Get whatever version of PySide we can -try: - from PySide import QtCore, QtWidgets # Use the FreeCAD wrapper -except ImportError: - try: - from PySide6 import QtCore, QtWidgets # Outside FreeCAD, try Qt6 first - except ImportError: - from PySide2 import QtCore, QtWidgets # Fall back to Qt5 - - -class FilterType(IntEnum): - """There are currently two sections in this drop down, for two different types of filters.""" - - PACKAGE_CONTENTS = 0 - INSTALLATION_STATUS = 1 - - -class StatusFilter(IntEnum): - """Predefined filters for status""" - - ANY = 0 - INSTALLED = 1 - NOT_INSTALLED = 2 - UPDATE_AVAILABLE = 3 - - -class ContentFilter(IntEnum): - """Predefined filters for addon content type""" - - ANY = 0 - WORKBENCH = 1 - MACRO = 2 - PREFERENCE_PACK = 3 - BUNDLE = 4 - OTHER = 5 - - -class Filter: - def __init__(self): - self.status_filter = StatusFilter.ANY - self.content_filter = ContentFilter.ANY - - -class WidgetFilterSelector(QtWidgets.QComboBox): - """A label and menu for selecting what sort of addons are displayed""" - - filter_changed = QtCore.Signal(object) # technically, actually class Filter - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.addon_type_index = 0 - self.installation_status_index = 0 - self.extra_padding = 64 - self._setup_ui() - self._setup_connections() - self.retranslateUi(None) - self.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents) - - def _setup_ui(self): - self._build_menu() - - def _build_menu(self): - self.clear() - self.addItem(translate("AddonsInstaller", "Filter by...")) - self.insertSeparator(self.count()) - self.addItem(translate("AddonsInstaller", "Addon Type")) - self.addon_type_index = self.count() - 1 - self.addItem( - translate("AddonsInstaller", "Any"), (FilterType.PACKAGE_CONTENTS, ContentFilter.ANY) - ) - self.addItem( - translate("AddonsInstaller", "Workbench"), - (FilterType.PACKAGE_CONTENTS, ContentFilter.WORKBENCH), - ) - self.addItem( - translate("AddonsInstaller", "Macro"), - (FilterType.PACKAGE_CONTENTS, ContentFilter.MACRO), - ) - self.addItem( - translate("AddonsInstaller", "Preference Pack"), - (FilterType.PACKAGE_CONTENTS, ContentFilter.PREFERENCE_PACK), - ) - self.addItem( - translate("AddonsInstaller", "Bundle"), - (FilterType.PACKAGE_CONTENTS, ContentFilter.BUNDLE), - ) - self.addItem( - translate("AddonsInstaller", "Other"), - (FilterType.PACKAGE_CONTENTS, ContentFilter.OTHER), - ) - self.insertSeparator(self.count()) - self.addItem(translate("AddonsInstaller", "Installation Status")) - self.installation_status_index = self.count() - 1 - self.addItem( - translate("AddonsInstaller", "Any"), (FilterType.INSTALLATION_STATUS, StatusFilter.ANY) - ) - self.addItem( - translate("AddonsInstaller", "Not installed"), - (FilterType.INSTALLATION_STATUS, StatusFilter.NOT_INSTALLED), - ) - self.addItem( - translate("AddonsInstaller", "Installed"), - (FilterType.INSTALLATION_STATUS, StatusFilter.INSTALLED), - ) - self.addItem( - translate("AddonsInstaller", "Update available"), - (FilterType.INSTALLATION_STATUS, StatusFilter.UPDATE_AVAILABLE), - ) - model: QtCore.QAbstractItemModel = self.model() - for row in range(model.rowCount()): - if row <= self.addon_type_index: - model.item(row).setEnabled(False) - elif row < self.installation_status_index: - item = model.item(row) - item.setCheckState(QtCore.Qt.Unchecked) - elif row == self.installation_status_index: - model.item(row).setEnabled(False) - else: - item = model.item(row) - item.setCheckState(QtCore.Qt.Unchecked) - - for row in range(model.rowCount()): - data = self.itemData(row) - if data: - item = model.item(row) - if data[0] == FilterType.PACKAGE_CONTENTS and data[1] == ContentFilter.ANY: - item.setCheckState(QtCore.Qt.Checked) - elif data[0] == FilterType.INSTALLATION_STATUS and data[1] == StatusFilter.ANY: - item.setCheckState(QtCore.Qt.Checked) - else: - item.setCheckState(QtCore.Qt.Unchecked) - - def set_contents_filter(self, contents_filter: ContentFilter): - model = self.model() - for row in range(model.rowCount()): - item = model.item(row) - user_data = self.itemData(row) - if user_data and user_data[0] == FilterType.PACKAGE_CONTENTS: - if user_data[1] == contents_filter: - item.setCheckState(QtCore.Qt.Checked) - else: - item.setCheckState(QtCore.Qt.Unchecked) - self._update_first_row_text() - - def set_status_filter(self, status_filter: StatusFilter): - model = self.model() - for row in range(model.rowCount()): - item = model.item(row) - user_data = self.itemData(row) - if user_data and user_data[0] == FilterType.INSTALLATION_STATUS: - if user_data[1] == status_filter: - item.setCheckState(QtCore.Qt.Checked) - else: - item.setCheckState(QtCore.Qt.Unchecked) - self._update_first_row_text() - - def _setup_connections(self): - self.activated.connect(self._selected) - - def _adjust_dropdown_width(self): - max_width = 0 - font_metrics = self.fontMetrics() - for index in range(self.count()): - width = font_metrics.horizontalAdvance(self.itemText(index)) - max_width = max(max_width, width) - self.view().setMinimumWidth(max_width + self.extra_padding) - - def retranslateUi(self, _): - self._build_menu() - self._adjust_dropdown_width() - - def _selected(self, row: int): - if row == 0: - return - if row == self.installation_status_index or row == self.addon_type_index: - self.setCurrentIndex(0) - return - model = self.model() - selected_data = self.itemData(row) - if not selected_data: - return - selected_row_type = selected_data[0] - - for row in range(model.rowCount()): - item = model.item(row) - user_data = self.itemData(row) - if user_data and user_data[0] == selected_row_type: - if user_data[1] == selected_data[1]: - item.setCheckState(QtCore.Qt.Checked) - else: - item.setCheckState(QtCore.Qt.Unchecked) - self._emit_current_filter() - self.setCurrentIndex(0) - self._update_first_row_text() - - def _emit_current_filter(self): - model = self.model() - new_filter = Filter() - for row in range(model.rowCount()): - item = model.item(row) - data = self.itemData(row) - if data and item.checkState() == QtCore.Qt.Checked: - if data[0] == FilterType.INSTALLATION_STATUS: - new_filter.status_filter = data[1] - elif data[0] == FilterType.PACKAGE_CONTENTS: - new_filter.content_filter = data[1] - self.filter_changed.emit(new_filter) - - def _update_first_row_text(self): - model = self.model() - state1 = "" - state2 = "" - for row in range(model.rowCount()): - item = model.item(row) - if item.checkState() == QtCore.Qt.Checked: - if not state1: - state1 = item.text() - else: - state2 = item.text() - break - model.item(0).setText(translate("AddonsInstaller", "Filter") + f": {state1}, {state2}") diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py deleted file mode 100644 index 67833201bd..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py +++ /dev/null @@ -1,110 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a QWidget-derived class for displaying a set of buttons that affect the Addon -Manager as a whole (rather than a specific Addon). Typically inserted at the bottom of the Addon -Manager main window.""" - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(_: str, text: str, details: str = "", n: int = 0): - return text - - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtGui, QtWidgets - - -class WidgetGlobalButtonBar(QtWidgets.QWidget): - """A QWidget-derived class for displaying a set of buttons that affect the Addon Manager as a - whole (rather than a specific Addon).""" - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.horizontal_layout = None - self.refresh_local_cache = None - self.update_all_addons = None - self.check_for_updates = None - self.python_dependencies = None - self.developer_tools = None - self.close = None - self._update_ui() - self.retranslateUi(None) - self._set_icons() - - def _update_ui(self): - self.horizontal_layout = QtWidgets.QHBoxLayout() - self.refresh_local_cache = QtWidgets.QPushButton(self) - self.update_all_addons = QtWidgets.QPushButton(self) - self.check_for_updates = QtWidgets.QPushButton(self) - self.python_dependencies = QtWidgets.QPushButton(self) - self.developer_tools = QtWidgets.QPushButton(self) - self.close = QtWidgets.QPushButton(self) - self.horizontal_layout.addWidget(self.refresh_local_cache) - self.horizontal_layout.addWidget(self.update_all_addons) - self.horizontal_layout.addWidget(self.check_for_updates) - self.horizontal_layout.addWidget(self.python_dependencies) - self.horizontal_layout.addWidget(self.developer_tools) - self.horizontal_layout.addStretch() - self.horizontal_layout.addWidget(self.close) - self.setLayout(self.horizontal_layout) - - def _set_icons(self): - self.update_all_addons.setIcon(QtGui.QIcon(":/icons/button_valid.svg")) - self.check_for_updates.setIcon(QtGui.QIcon(":/icons/view-refresh.svg")) - self.close.setIcon(QtGui.QIcon.fromTheme("close", QtGui.QIcon(":/icons/process-stop.svg"))) - - def retranslateUi(self, _): - self.refresh_local_cache.setText(translate("AddonsInstaller", "Close")) - self.update_all_addons.setText(translate("AddonsInstaller", "Update all addons")) - self.check_for_updates.setText(translate("AddonsInstaller", "Check for updates")) - self.python_dependencies.setText(translate("AddonsInstaller", "Python dependencies...")) - self.developer_tools.setText(translate("AddonsInstaller", "Developer tools...")) - self.close.setText(translate("AddonsInstaller", "Close")) - - def set_number_of_available_updates(self, updates: int): - if updates > 0: - self.update_all_addons.setEnabled(True) - self.update_all_addons.setText( - translate("AddonsInstaller", "Apply %n available update(s)", "", updates) - ) - else: - self.update_all_addons.setEnabled(False) - self.update_all_addons.setText(translate("AddonsInstaller", "No updates available")) diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py deleted file mode 100644 index 0ce79da106..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py +++ /dev/null @@ -1,361 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 The FreeCAD Project Association AISBL * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -from dataclasses import dataclass -from enum import Enum, auto -import os -from typing import Optional - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(_: str, text: str): - return text - - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore, QtWidgets - -from .addonmanager_widget_addon_buttons import WidgetAddonButtons -from .addonmanager_widget_readme_browser import WidgetReadmeBrowser -from .addonmanager_colors import warning_color_string, attention_color_string, bright_color_string - - -class MessageType(Enum): - Message = auto() - Warning = auto() - Error = auto() - - -@dataclass -class UpdateInformation: - unchecked: bool = True - check_in_progress: bool = False - update_available: bool = False - detached_head: bool = False - version: str = "" - tag: str = "" - branch: Optional[str] = None - - -@dataclass -class WarningFlags: - obsolete: bool = False - python2: bool = False - required_freecad_version: Optional[str] = None - non_osi_approved = False - non_fsf_libre = False - - -class PackageDetailsView(QtWidgets.QWidget): - """The view class for the package details""" - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.button_bar = None - self.readme_browser = None - self.message_label = None - self.location_label = None - self.url_label = None - self.installed = False - self.disabled = False - self.update_info = UpdateInformation() - self.warning_flags = WarningFlags() - self.installed_version = None - self.installed_branch = None - self.installed_timestamp = None - self.can_disable = True - self._setup_ui() - - def _setup_ui(self): - self.vertical_layout = QtWidgets.QVBoxLayout(self) - self.button_bar = WidgetAddonButtons(self) - self.readme_browser = WidgetReadmeBrowser(self) - self.message_label = QtWidgets.QLabel(self) - self.location_label = QtWidgets.QLabel(self) - self.url_label = QtWidgets.QLabel(self) - self.url_label.setOpenExternalLinks(True) - self.location_label.setOpenExternalLinks(True) - self.vertical_layout.addWidget(self.button_bar) - self.vertical_layout.addWidget(self.message_label) - self.vertical_layout.addWidget(self.location_label) - self.vertical_layout.addWidget(self.url_label) - self.vertical_layout.addWidget(self.readme_browser) - self.button_bar.hide() # Start with no bar - - def set_location(self, location: Optional[str]): - if location is not None: - location_path = os.path.normpath(location) - text = ( - f"{translate('AddonsInstaller', 'Installation location')}: " - f'{location_path}' - ) - self.location_label.setText(text) - self.location_label.show() - else: - self.location_label.hide() - - def set_url(self, url: Optional[str]): - if url is not None: - text = ( - translate("AddonsInstaller", "Repository URL") - + ': ' - + url - + "" - ) - self.url_label.setText(text) - self.url_label.show() - else: - self.url_label.hide() - - def set_installed( - self, - installed: bool, - on_date: Optional[str] = None, - version: Optional[str] = None, - branch: Optional[str] = None, - ): - self.installed = installed - self.installed_timestamp = on_date - self.installed_version = version - self.installed_branch = branch - if not self.installed: - self.set_location(None) - self._sync_ui_state() - - def set_update_available(self, info: UpdateInformation): - self.update_info = info - self._sync_ui_state() - - def set_disabled(self, disabled: bool): - self.disabled = disabled - self._sync_ui_state() - - def allow_disabling(self, allow: bool): - self.can_disable = allow - self._sync_ui_state() - - def allow_running(self, show: bool): - self.button_bar.run_macro.setVisible(show) - - def set_warning_flags(self, flags: WarningFlags): - self.warning_flags = flags - self._sync_ui_state() - - def set_new_disabled_status(self, disabled: bool): - """If the user just changed the enabled/disabled state of the addon, display a message - indicating that will not take place until restart. Do not call except in a case of a - state change during this run.""" - - if disabled: - message = translate( - "AddonsInstaller", "This Addon will be disabled next time you restart FreeCAD." - ) - else: - message = translate( - "AddonsInstaller", "This Addon will be enabled next time you restart FreeCAD." - ) - self.message_label.setText(f"

    {message}

    ") - self.message_label.setStyleSheet("color:" + attention_color_string()) - - def set_new_branch(self, branch: str): - """If the user just changed branches, update the message to show that a restart is - needed.""" - message_string = "

    " - message_string += translate( - "AddonsInstaller", "Changed to branch '{}' -- please restart to use Addon." - ).format(branch) - message_string += "

    " - self.message_label.setText(message_string) - self.message_label.setStyleSheet("color:" + attention_color_string()) - - def set_updated(self): - """If the user has just updated the addon but not yet restarted, show an indication that - we are awaiting a restart.""" - message = translate( - "AddonsInstaller", "This Addon has been updated. Restart FreeCAD to see changes." - ) - self.message_label.setText(f"

    {message}

    ") - self.message_label.setStyleSheet("color:" + attention_color_string()) - - def _sync_ui_state(self): - self._sync_button_state() - self._create_status_label_text() - - def _sync_button_state(self): - self.button_bar.install.setVisible(not self.installed) - self.button_bar.uninstall.setVisible(self.installed) - if not self.installed: - self.button_bar.disable.hide() - self.button_bar.enable.hide() - self.button_bar.update.hide() - self.button_bar.check_for_update.hide() - else: - self.button_bar.update.setVisible(self.update_info.update_available) - if self.update_info.detached_head: - self.button_bar.check_for_update.hide() - else: - self.button_bar.check_for_update.setVisible(not self.update_info.update_available) - if self.can_disable: - self.button_bar.enable.setVisible(self.disabled) - self.button_bar.disable.setVisible(not self.disabled) - else: - self.button_bar.enable.hide() - self.button_bar.disable.hide() - - def _create_status_label_text(self): - if self.installed: - installation_details = self._get_installation_details_string() - update_details = self._get_update_status_string() - message_text = f"{installation_details} {update_details}" - if self.disabled: - message_text += " [" + translate("AddonsInstaller", "Disabled") + "]" - self.message_label.setText(f"

    {message_text}

    ") - if self.disabled: - self.message_label.setStyleSheet("color:" + warning_color_string()) - elif self.update_info.update_available: - self.message_label.setStyleSheet("color:" + attention_color_string()) - else: - self.message_label.setStyleSheet("color:" + bright_color_string()) - self.message_label.show() - elif self._there_are_warnings_to_show(): - warnings = self._get_warning_string() - self.message_label.setText(f"

    {warnings}

    ") - self.message_label.setStyleSheet("color:" + warning_color_string()) - self.message_label.show() - else: - self.message_label.hide() - - def _get_installation_details_string(self) -> str: - version = self.installed_version - date = "" - installed_version_string = "" - if self.installed_timestamp: - date = QtCore.QLocale().toString( - QtCore.QDateTime.fromSecsSinceEpoch(int(round(self.installed_timestamp, 0))), - QtCore.QLocale.ShortFormat, - ) - if version and date: - installed_version_string += ( - translate("AddonsInstaller", "Version {version} installed on {date}").format( - version=version, date=date - ) - + ". " - ) - elif version: - installed_version_string += ( - translate("AddonsInstaller", "Version {version} installed") + "." - ).format(version=version) - elif date: - installed_version_string += ( - translate("AddonsInstaller", "Installed on {date}") + "." - ).format(date=date) - else: - installed_version_string += translate("AddonsInstaller", "Installed") + "." - return installed_version_string - - def _get_update_status_string(self) -> str: - if self.update_info.check_in_progress: - return translate("AddonsInstaller", "Update check in progress") + "." - elif self.update_info.unchecked: - return "" - if self.update_info.detached_head: - return ( - translate( - "AddonsInstaller", "Git tag '{}' checked out, no updates possible" - ).format(self.update_info.tag) - + "." - ) - if self.update_info.update_available: - if self.installed_branch and self.update_info.branch: - if self.installed_branch != self.update_info.branch: - return ( - translate( - "AddonsInstaller", "Currently on branch {}, name changed to {}" - ).format(self.installed_branch, self.update_info.branch) - + "." - ) - if self.update_info.version: - return ( - translate( - "AddonsInstaller", - "Currently on branch {}, update available to version {}", - ).format(self.installed_branch, str(self.update_info.version).strip()) - + "." - ) - return translate("AddonsInstaller", "Update available") + "." - if self.update_info.version: - return ( - translate("AddonsInstaller", "Update available to version {}").format( - str(self.update_info.version).strip() - ) - + "." - ) - return translate("AddonsInstaller", "Update available") + "." - return translate("AddonsInstaller", "This is the latest version available") + "." - - def _there_are_warnings_to_show(self) -> bool: - if self.disabled: - return True - if ( - self.warning_flags.obsolete - or self.warning_flags.python2 - or self.warning_flags.required_freecad_version - ): - return True - return False # TODO: Someday support optional warnings on license types - - def _get_warning_string(self) -> str: - if self.installed and self.disabled: - return translate( - "AddonsInstaller", - "WARNING: This addon is currently installed, but disabled. Use the 'enable' " - "button to re-enable.", - ) - if self.warning_flags.obsolete: - return translate("AddonsInstaller", "WARNING: This addon is obsolete") - if self.warning_flags.python2: - return translate("AddonsInstaller", "WARNING: This addon is Python 2 only") - if self.warning_flags.required_freecad_version: - return translate("AddonsInstaller", "WARNING: This addon requires FreeCAD {}").format( - self.warning_flags.required_freecad_version - ) - return "" diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py deleted file mode 100644 index 1e9c0a1f20..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py +++ /dev/null @@ -1,168 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a QWidget-derived class for displaying the cache load status.""" - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(_: str, text: str): - return text - - -# Get whatever version of PySide we can -try: - from PySide import QtCore, QtGui, QtWidgets # Use the FreeCAD wrapper -except ImportError: - try: - from PySide6 import QtCore, QtGui, QtWidgets # Outside FreeCAD, try Qt6 first - except ImportError: - from PySide2 import QtCore, QtGui, QtWidgets # Fall back to Qt5 - -from dataclasses import dataclass - -_TOTAL_INCREMENTS = 1000 - - -class Progress: - """Represents progress through a process composed of multiple sub-tasks.""" - - def __init__( - self, - *, - status_text: str = "", - number_of_tasks: int = 1, - current_task: int = 0, - current_task_progress: float = 0.0, - ): - if number_of_tasks < 1: - raise ValueError(f"Number of tasks must be at least one, not {number_of_tasks}") - if current_task < 0 or current_task >= number_of_tasks: - raise ValueError( - "Current task must be between 0 and the number of tasks " - f"({number_of_tasks}), not {current_task}" - ) - if current_task_progress < 0.0: - current_task_progress = 0.0 - elif current_task_progress > 100.0: - current_task_progress = 100.0 - self.status_text: str = status_text - self._number_of_tasks: int = number_of_tasks - self._current_task: int = current_task - self._current_task_progress: float = current_task_progress - - @property - def number_of_tasks(self): - return self._number_of_tasks - - @number_of_tasks.setter - def number_of_tasks(self, value: int): - if not isinstance(value, int): - raise TypeError("Number of tasks must be an integer") - if value < 1: - raise ValueError("Number of tasks must be at least one") - self._number_of_tasks = value - - @property - def current_task(self): - """The current task (zero-indexed, always less than the number of tasks)""" - return self._current_task - - @current_task.setter - def current_task(self, value: int): - if not isinstance(value, int): - raise TypeError("Current task must be an integer") - if value < 0: - raise ValueError("Current task must be at least zero") - if value >= self._number_of_tasks: - raise ValueError("Current task must be less than the total number of tasks") - self._current_task = value - - @property - def current_task_progress(self): - """Current task progress, guaranteed to be in the range [0.0, 100.0]. Attempts to set a - value outside that range are clamped to the range.""" - return self._current_task_progress - - @current_task_progress.setter - def current_task_progress(self, value: float): - """Set the current task's progress. Rather than raising an exception when the value is - outside the expected range of [0,100], clamp the task progress to allow for some - floating point imprecision in its calculation.""" - if value < 0.0: - value = 0.0 - elif value > 100.0: - value = 100.0 - self._current_task_progress = value - - def next_task(self) -> None: - """Increment the task counter and reset the progress""" - self.current_task += 1 - self.current_task_progress = 0.0 - - def overall_progress(self) -> float: - """Gets the overall progress as a fractional value in the range [0, 1]""" - base = self._current_task / self._number_of_tasks - fraction = self._current_task_progress / (100.0 * self._number_of_tasks) - return base + fraction - - -class WidgetProgressBar(QtWidgets.QWidget): - """A multipart progress bar widget, including a stop button and a status label.""" - - stop_clicked = QtCore.Signal() - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.vertical_layout = None - self.horizontal_layout = None - self.progress_bar = None - self.status_label = None - self.stop_button = None - self._setup_ui() - - def _setup_ui(self): - self.vertical_layout = QtWidgets.QVBoxLayout(self) - self.horizontal_layout = QtWidgets.QHBoxLayout() - self.progress_bar = QtWidgets.QProgressBar(self) - self.status_label = QtWidgets.QLabel(self) - self.stop_button = QtWidgets.QToolButton(self) - self.progress_bar.setMaximum(_TOTAL_INCREMENTS) - self.stop_button.clicked.connect(self.stop_clicked) - self.stop_button.setIcon( - QtGui.QIcon.fromTheme("stop", QtGui.QIcon(":/icons/debug-stop.svg")) - ) - self.vertical_layout.addLayout(self.horizontal_layout) - self.vertical_layout.addWidget(self.status_label) - self.horizontal_layout.addWidget(self.progress_bar) - self.horizontal_layout.addWidget(self.stop_button) - self.vertical_layout.setContentsMargins(0, 0, 0, 0) - self.horizontal_layout.setContentsMargins(0, 0, 0, 0) - - def set_progress(self, progress: Progress) -> None: - self.status_label.setText(progress.status_text) - self.progress_bar.setValue(progress.overall_progress() * _TOTAL_INCREMENTS) diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_readme_browser.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_readme_browser.py deleted file mode 100644 index fade43283d..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_readme_browser.py +++ /dev/null @@ -1,132 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 The FreeCAD Project Association AISBL * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** -import re - -import FreeCAD - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore, QtGui, QtWidgets - -from typing import Optional - - -class WidgetReadmeBrowser(QtWidgets.QTextBrowser): - """A QTextBrowser widget that emits signals for each requested image resource, allowing an external controller - to load and re-deliver those images. Once all resources have been re-delivered, the original data is redisplayed - with the images in-line. Call setUrl prior to calling setMarkdown or setHtml to ensure URLs are resolved - correctly.""" - - load_resource = QtCore.Signal(str) # Str is a URL to a resource - follow_link = QtCore.Signal(str) # Str is a URL to another page - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.image_map = {} - self.url = "" - self.stop = False - self.setOpenExternalLinks(True) - - def setUrl(self, url: str): - """Set the base URL of the page. Used to resolve relative URLs in the page source.""" - self.url = url - - def setMarkdown(self, md: str): - """Provides an optional fallback to the markdown library for older versions of Qt (prior to 5.15) that did not - have native markdown support. Lacking that, plaintext is displayed.""" - geometry = self.geometry() - if hasattr(super(), "setMarkdown"): - - super().setMarkdown(self._clean_markdown(md)) - else: - try: - import markdown - - html = markdown.markdown(md) - self.setHtml(html) - except ImportError: - self.setText(md) - FreeCAD.Console.Warning( - "Qt < 5.15 and no `import markdown` -- falling back to plain text display\n" - ) - self.setGeometry(geometry) - - def _clean_markdown(self, md: str): - # Remove some HTML tags ( for now just img and br, which are the most common offenders that break rendering ) - br_re = re.compile(r"") - img_re = re.compile(r"]+)(?:'|\").*?\/?>") - - cleaned = br_re.sub(r"\n", md) - cleaned = img_re.sub(r"[html tag removed]", cleaned) - - return cleaned - - def set_resource(self, resource_url: str, image: Optional[QtGui.QImage]): - """Once a resource has been fetched (or the fetch has failed), this method should be used to inform the widget - that the resource has been loaded. Note that the incoming image is scaled to 97% of the widget width if it is - larger than that.""" - self.image_map[resource_url] = self._ensure_appropriate_width(image) - - def loadResource(self, resource_type: int, name: QtCore.QUrl) -> object: - """Callback for resource loading. Called automatically by underlying Qt - code when external resources are needed for rendering. In particular, - here it is used to download and cache (in RAM) the images needed for the - README and Wiki pages.""" - if resource_type == QtGui.QTextDocument.ImageResource and not self.stop: - full_url = self._create_full_url(name.toString()) - if full_url not in self.image_map: - self.load_resource.emit(full_url) - self.image_map[full_url] = None - return self.image_map[full_url] - elif resource_type == QtGui.QTextDocument.MarkdownResource: - self.follow_link.emit(name.toString()) - return self.toMarkdown() - elif resource_type == QtGui.QTextDocument.HtmlResource: - self.follow_link.emit(name.toString()) - return self.toHtml() - return super().loadResource(resource_type, name) - - def _ensure_appropriate_width(self, image: QtGui.QImage) -> QtGui.QImage: - ninety_seven_percent = self.width() * 0.97 - if image.width() < ninety_seven_percent: - return image - return image.scaledToWidth(ninety_seven_percent) - - def _create_full_url(self, url: str) -> str: - if url.startswith("http"): - return url - if not self.url: - return url - lhs, slash, _ = self.url.rpartition("/") - return lhs + slash + url diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py deleted file mode 100644 index 339f31fcdf..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py +++ /dev/null @@ -1,104 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a QWidget-derived class for displaying the view selection buttons.""" - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(_: str, text: str): - return text - - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore, QtGui, QtWidgets - - -class WidgetSearch(QtWidgets.QWidget): - """A widget for selecting the Addon Manager's primary view mode""" - - search_changed = QtCore.Signal(str) - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self._setup_ui() - self._setup_connections() - self.retranslateUi(None) - - def _setup_ui(self): - self.horizontal_layout = QtWidgets.QHBoxLayout() - self.horizontal_layout.setContentsMargins(0, 0, 0, 0) - self.filter_line_edit = QtWidgets.QLineEdit(self) - self.filter_line_edit.setClearButtonEnabled(True) - self.horizontal_layout.addWidget(self.filter_line_edit) - self.filter_validity_label = QtWidgets.QLabel(self) - self.horizontal_layout.addWidget(self.filter_validity_label) - self.filter_validity_label.hide() # This widget starts hidden - self.setLayout(self.horizontal_layout) - - def _setup_connections(self): - self.filter_line_edit.textChanged.connect(self.set_text_filter) - - def set_text_filter(self, text_filter: str) -> None: - """Set the current filter. If the filter is valid, this will emit a filter_changed - signal. text_filter may be regular expression.""" - - if text_filter: - test_regex = QtCore.QRegularExpression(text_filter) - if test_regex.isValid(): - self.filter_validity_label.setToolTip( - translate("AddonsInstaller", "Filter is valid") - ) - icon = QtGui.QIcon.fromTheme("ok", QtGui.QIcon(":/icons/edit_OK.svg")) - self.filter_validity_label.setPixmap(icon.pixmap(16, 16)) - else: - self.filter_validity_label.setToolTip( - translate("AddonsInstaller", "Filter regular expression is invalid") - ) - icon = QtGui.QIcon.fromTheme("cancel", QtGui.QIcon(":/icons/edit_Cancel.svg")) - self.filter_validity_label.setPixmap(icon.pixmap(16, 16)) - self.filter_validity_label.show() - else: - self.filter_validity_label.hide() - self.search_changed.emit(text_filter) - - def retranslateUi(self, _): - self.filter_line_edit.setPlaceholderText( - QtCore.QCoreApplication.translate("AddonsInstaller", "Search...", None) - ) diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py deleted file mode 100644 index 3d44a18954..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py +++ /dev/null @@ -1,169 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a class derived from QWidget for displaying the bar at the top of the addons list.""" - -from enum import IntEnum, auto - -try: - import FreeCAD -except ImportError: - FreeCAD = None - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore, QtGui, QtWidgets -from .addonmanager_widget_view_selector import WidgetViewSelector -from .addonmanager_widget_filter_selector import WidgetFilterSelector -from .addonmanager_widget_search import WidgetSearch - -translate = QtCore.QCoreApplication.translate - - -class SortOptions(IntEnum): - _SortRoleOffset = 100 - Alphabetical = QtCore.Qt.UserRole + _SortRoleOffset + 0 - LastUpdated = QtCore.Qt.UserRole + _SortRoleOffset + 1 - DateAdded = QtCore.Qt.UserRole + _SortRoleOffset + 2 - Stars = QtCore.Qt.UserRole + _SortRoleOffset + 3 - Score = QtCore.Qt.UserRole + _SortRoleOffset + 4 - - -default_sort_order = { - SortOptions.Alphabetical: QtCore.Qt.AscendingOrder, - SortOptions.LastUpdated: QtCore.Qt.DescendingOrder, - SortOptions.DateAdded: QtCore.Qt.DescendingOrder, - SortOptions.Stars: QtCore.Qt.DescendingOrder, - SortOptions.Score: QtCore.Qt.DescendingOrder, -} - - -class WidgetViewControlBar(QtWidgets.QWidget): - """A bar containing a view selection widget, a filter widget, and a search widget""" - - view_changed = QtCore.Signal(int) - filter_changed = QtCore.Signal(object) - search_changed = QtCore.Signal(str) - sort_changed = QtCore.Signal(int) - sort_order_changed = QtCore.Signal(QtCore.Qt.SortOrder) - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.has_rankings = False - self._setup_ui() - self._setup_connections() - self.retranslateUi(None) - self.sort_order = QtCore.Qt.AscendingOrder - self._set_sort_order_icon() - - def _setup_ui(self): - self.horizontal_layout = QtWidgets.QHBoxLayout() - self.horizontal_layout.setContentsMargins(0, 0, 0, 0) - self.view_selector = WidgetViewSelector(self) - self.filter_selector = WidgetFilterSelector(self) - self.sort_selector = QtWidgets.QComboBox(self) - self.sort_order_button = QtWidgets.QToolButton(self) - self.sort_order_button.setIcon( - QtGui.QIcon.fromTheme("ascending", QtGui.QIcon(":/icons/sort_ascending.svg")) - ) - self.search = WidgetSearch(self) - self.horizontal_layout.addWidget(self.view_selector) - self.horizontal_layout.addWidget(self.filter_selector) - self.horizontal_layout.addWidget(self.sort_selector) - self.horizontal_layout.addWidget(self.sort_order_button) - self.horizontal_layout.addWidget(self.search) - self.setLayout(self.horizontal_layout) - - def _sort_order_clicked(self): - if self.sort_order == QtCore.Qt.AscendingOrder: - self.set_sort_order(QtCore.Qt.DescendingOrder) - else: - self.set_sort_order(QtCore.Qt.AscendingOrder) - self.sort_order_changed.emit(self.sort_order) - - def set_sort_order(self, order: QtCore.Qt.SortOrder) -> None: - self.sort_order = order - self._set_sort_order_icon() - - def _set_sort_order_icon(self): - if self.sort_order == QtCore.Qt.AscendingOrder: - self.sort_order_button.setIcon( - QtGui.QIcon.fromTheme( - "view-sort-ascending", QtGui.QIcon(":/icons/sort_ascending.svg") - ) - ) - else: - self.sort_order_button.setIcon( - QtGui.QIcon.fromTheme( - "view-sort-descending", QtGui.QIcon(":/icons/sort_descending.svg") - ) - ) - - def set_rankings_available(self, rankings_available: bool) -> None: - self.has_rankings = rankings_available - self.retranslateUi(None) - - def _setup_connections(self): - self.view_selector.view_changed.connect(self.view_changed.emit) - self.filter_selector.filter_changed.connect(self.filter_changed.emit) - self.search.search_changed.connect(self.search_changed.emit) - self.sort_selector.currentIndexChanged.connect(self._sort_changed) - self.sort_order_button.clicked.connect(self._sort_order_clicked) - - def _sort_changed(self, index: int): - sort_role = self.sort_selector.itemData(index) - if sort_role is None: - sort_role = SortOptions.Alphabetical - self.set_sort_order(default_sort_order[sort_role]) - self.sort_changed.emit(sort_role) - self.sort_order_changed.emit(self.sort_order) - - def retranslateUi(self, _=None): - self.sort_selector.clear() - self.sort_selector.addItem( - translate("AddonsInstaller", "Alphabetical", "Sort order"), SortOptions.Alphabetical - ) - self.sort_selector.addItem( - translate("AddonsInstaller", "Last Updated", "Sort order"), SortOptions.LastUpdated - ) - self.sort_selector.addItem( - translate("AddonsInstaller", "Date Created", "Sort order"), SortOptions.DateAdded - ) - self.sort_selector.addItem( - translate("AddonsInstaller", "GitHub Stars", "Sort order"), SortOptions.Stars - ) - if self.has_rankings: - self.sort_selector.addItem( - translate("AddonsInstaller", "Score", "Sort order"), SortOptions.Score - ) diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py deleted file mode 100644 index 7a65a0f655..0000000000 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py +++ /dev/null @@ -1,161 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Defines a QWidget-derived class for displaying the view selection buttons.""" - -from enum import IntEnum - -try: - import FreeCAD - - translate = FreeCAD.Qt.translate -except ImportError: - FreeCAD = None - - def translate(context: str, text: str): - return text - - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore, QtGui, QtWidgets - - -class AddonManagerDisplayStyle(IntEnum): - """The display mode of the Addon Manager""" - - COMPACT = 0 - EXPANDED = 1 - COMPOSITE = 2 - - -class WidgetViewSelector(QtWidgets.QWidget): - """A widget for selecting the Addon Manager's primary view mode""" - - view_changed = QtCore.Signal(int) - - def __init__(self, parent: QtWidgets.QWidget = None): - super().__init__(parent) - self.horizontal_layout = None - self.composite_button = None - self.expanded_button = None - self.compact_button = None - self._setup_ui() - self._setup_connections() - - def set_current_view(self, view: AddonManagerDisplayStyle): - """Set the current selection. Does NOT emit a view_changed signal, only changes the - interface display.""" - self.compact_button.setChecked(False) - self.expanded_button.setChecked(False) - self.composite_button.setChecked(False) - if view == AddonManagerDisplayStyle.COMPACT: - self.compact_button.setChecked(True) - elif view == AddonManagerDisplayStyle.EXPANDED: - self.expanded_button.setChecked(True) - elif view == AddonManagerDisplayStyle.COMPOSITE: - self.composite_button.setChecked(True) - else: - if FreeCAD is not None: - FreeCAD.Console.PrintWarning(f"Unrecognized display style {view}") - - def _setup_ui(self): - self.horizontal_layout = QtWidgets.QHBoxLayout() - self.horizontal_layout.setContentsMargins(0, 0, 0, 0) - self.horizontal_layout.setSpacing(2) - self.compact_button = QtWidgets.QToolButton(self) - self.compact_button.setObjectName("compact_button") - self.compact_button.setIcon( - QtGui.QIcon.fromTheme("back", QtGui.QIcon(":/icons/compact_view.svg")) - ) - self.compact_button.setCheckable(True) - self.compact_button.setAutoExclusive(True) - - self.expanded_button = QtWidgets.QToolButton(self) - self.expanded_button.setObjectName("expanded_button") - self.expanded_button.setCheckable(True) - self.expanded_button.setChecked(True) - self.expanded_button.setAutoExclusive(True) - self.expanded_button.setIcon( - QtGui.QIcon.fromTheme("expanded_view", QtGui.QIcon(":/icons/expanded_view.svg")) - ) - - self.composite_button = QtWidgets.QToolButton(self) - self.composite_button.setObjectName("composite_button") - if ( - QtCore.QLibraryInfo.version().majorVersion() == 5 - and QtCore.QLibraryInfo.version().minorVersion() < 15 - ): - self.composite_button.setEnabled(False) - self.composite_button.setCheckable(False) - self.composite_button.setChecked(False) - else: - self.composite_button.setCheckable(True) - self.composite_button.setChecked(True) - self.composite_button.setAutoExclusive(True) - self.composite_button.setIcon( - QtGui.QIcon.fromTheme("composite_button", QtGui.QIcon(":/icons/composite_view.svg")) - ) - self.horizontal_layout.addWidget(self.compact_button) - self.horizontal_layout.addWidget(self.expanded_button) - self.horizontal_layout.addWidget(self.composite_button) - - self.compact_button.clicked.connect( - lambda: self.view_changed.emit(AddonManagerDisplayStyle.COMPACT) - ) - self.expanded_button.clicked.connect( - lambda: self.view_changed.emit(AddonManagerDisplayStyle.EXPANDED) - ) - self.composite_button.clicked.connect( - lambda: self.view_changed.emit(AddonManagerDisplayStyle.COMPOSITE) - ) - - self.setLayout(self.horizontal_layout) - self.retranslateUi(None) - - def _setup_connections(self): - self.compact_button.clicked.connect( - lambda: self.view_changed.emit(AddonManagerDisplayStyle.COMPACT) - ) - self.expanded_button.clicked.connect( - lambda: self.view_changed.emit(AddonManagerDisplayStyle.EXPANDED) - ) - self.composite_button.clicked.connect( - lambda: self.view_changed.emit(AddonManagerDisplayStyle.COMPOSITE) - ) - - def retranslateUi(self, _): - self.composite_button.setToolTip(translate("AddonsInstaller", "Composite view")) - self.expanded_button.setToolTip(translate("AddonsInstaller", "Expanded view")) - self.compact_button.setToolTip(translate("AddonsInstaller", "Compact view")) diff --git a/src/Mod/AddonManager/__init__.py b/src/Mod/AddonManager/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Mod/AddonManager/add_toolbar_button_dialog.ui b/src/Mod/AddonManager/add_toolbar_button_dialog.ui deleted file mode 100644 index bba50c3e53..0000000000 --- a/src/Mod/AddonManager/add_toolbar_button_dialog.ui +++ /dev/null @@ -1,105 +0,0 @@ - - - add_toolbar_button_dialog - - - - 0 - 0 - 257 - 62 - - - - Add button? - - - - - - Add a toolbar button for this macro? - - - true - - - - - - - - - Yes - - - - - - - No - - - - - - - Never - - - - - - - - - - - buttonYes - clicked() - add_toolbar_button_dialog - accept() - - - 47 - 40 - - - 128 - 30 - - - - - buttonNo - clicked() - add_toolbar_button_dialog - reject() - - - 128 - 40 - - - 128 - 30 - - - - - buttonNever - clicked() - add_toolbar_button_dialog - reject() - - - 209 - 40 - - - 128 - 30 - - - - - diff --git a/src/Mod/AddonManager/addonmanager.dox b/src/Mod/AddonManager/addonmanager.dox deleted file mode 100644 index d68ae607e9..0000000000 --- a/src/Mod/AddonManager/addonmanager.dox +++ /dev/null @@ -1,4 +0,0 @@ -/** \defgroup ADDONMANAGER Addon Manager - * \ingroup PYTHONWORKBENCHES - * \brief Application that handles the installation of user-made workbenches and macros - */ diff --git a/src/Mod/AddonManager/addonmanager_cache.py b/src/Mod/AddonManager/addonmanager_cache.py deleted file mode 100644 index a72d290be0..0000000000 --- a/src/Mod/AddonManager/addonmanager_cache.py +++ /dev/null @@ -1,118 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -from datetime import date, timedelta -import hashlib -import os - -import addonmanager_freecad_interface as fci -import addonmanager_utilities as utils - -translate = fci.translate - - -def local_cache_needs_update() -> bool: - """Determine whether we need to update the cache, based on user preference, and previous - cache update status. Returns either True or False.""" - - if not _cache_exists(): - return True - - if _last_update_was_interrupted(reset_status=True): - return True - - if _custom_repo_list_changed(): - return True - - # Figure out our cache update frequency: there is a combo box in the preferences dialog - # with three options: never, daily, and weekly. - days_between_updates = _days_between_updates() - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Addons") - last_cache_update_string = pref.GetString("LastCacheUpdate", "never") - - if last_cache_update_string == "never": - return True - elif days_between_updates > 0: - last_cache_update = date.fromisoformat(last_cache_update_string) - delta_update = timedelta(days=days_between_updates) - if date.today() >= last_cache_update + delta_update: - return True - elif days_between_updates == 0: - return True - - return False - - -def _days_between_updates() -> int: - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Addons") - update_frequency = pref.GetInt("UpdateFrequencyComboEntry", 0) - if update_frequency == 0: - return -1 - elif update_frequency == 1: - return 1 - elif update_frequency == 2: - return 7 - else: - return 0 - - -def _cache_exists() -> bool: - cache_path = fci.getUserCachePath() - am_path = os.path.join(cache_path, "AddonManager") - return os.path.exists(am_path) - - -def _last_update_was_interrupted(reset_status: bool) -> bool: - flag_file = utils.get_cache_file_name("CACHE_UPDATE_INTERRUPTED") - if os.path.exists(flag_file): - if reset_status: - os.remove(flag_file) - fci.Console.PrintMessage( - translate( - "AddonsInstaller", - "Previous cache process was interrupted, restarting...\n", - ) - ) - return True - - -def _custom_repo_list_changed() -> bool: - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Addons") - stored_hash = pref.GetString("CustomRepoHash", "") - custom_repos = pref.GetString("CustomRepositories", "") - if custom_repos: - hasher = hashlib.sha1() - hasher.update(custom_repos.encode("utf-8")) - new_hash = hasher.hexdigest() - else: - new_hash = "" - if new_hash != stored_hash: - pref.SetString("CustomRepoHash", new_hash) - fci.Console.PrintMessage( - translate( - "AddonsInstaller", - "Custom repo list changed, forcing recache...\n", - ) - ) - return True - return False diff --git a/src/Mod/AddonManager/addonmanager_connection_checker.py b/src/Mod/AddonManager/addonmanager_connection_checker.py deleted file mode 100644 index 1b721ce761..0000000000 --- a/src/Mod/AddonManager/addonmanager_connection_checker.py +++ /dev/null @@ -1,125 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""System for checking the network connection status asynchronously.""" - -import FreeCAD - -from PySide import QtCore, QtWidgets - -import NetworkManager -from addonmanager_workers_utility import ConnectionChecker - -translate = FreeCAD.Qt.translate - - -class ConnectionCheckerGUI(QtCore.QObject): - """Determine whether there is an active network connection, showing a progress message if it - starts to take too long, and an error message if the network cannot be accessed.""" - - connection_available = QtCore.Signal() - check_complete = QtCore.Signal() - - def __init__(self): - super().__init__() - - # Check the connection in a new thread, so FreeCAD stays responsive - self.connection_checker = ConnectionChecker() - self.signals_connected = False - - self.connection_message_timer = None - self.connection_check_message = None - - def start(self): - """Start the connection check""" - self.connection_checker.start() - self.connection_checker.success.connect(self._check_succeeded) - self.connection_checker.failure.connect(self._network_connection_failed) - self.signals_connected = True - - # If it takes longer than a half second to check the connection, show a message: - self.connection_message_timer = QtCore.QTimer.singleShot( - 500, self._show_connection_check_message - ) - - def _show_connection_check_message(self): - """Display a message informing the user that the check is in process""" - if not self.connection_checker.isFinished(): - self.connection_check_message = QtWidgets.QMessageBox( - QtWidgets.QMessageBox.Information, - translate("AddonsInstaller", "Checking connection"), - translate("AddonsInstaller", "Checking for connection to GitHub..."), - QtWidgets.QMessageBox.Cancel, - ) - self.connection_check_message.buttonClicked.connect(self.cancel_network_check) - self.connection_check_message.show() - - def cancel_network_check(self, _): - """Cancel the check""" - if not self.connection_checker.isFinished(): - self._disconnect_signals() - self.connection_checker.requestInterruption() - self.connection_checker.wait(500) - self.connection_check_message.close() - self.check_complete.emit() - - def _network_connection_failed(self, message: str) -> None: - """Callback for failed connection check. Displays an error message, then emits the - check_complete signal (but not the connection available signal).""" - # This must run on the main GUI thread - if hasattr(self, "connection_check_message") and self.connection_check_message: - self.connection_check_message.close() - if NetworkManager.HAVE_QTNETWORK: - QtWidgets.QMessageBox.critical( - None, translate("AddonsInstaller", "Connection failed"), message - ) - else: - # pylint: disable=line-too-long - QtWidgets.QMessageBox.critical( - None, - translate("AddonsInstaller", "Missing dependency"), - translate( - "AddonsInstaller", - "Could not import QtNetwork -- see Report View for details. Addon Manager " - "unavailable.", - ), - ) - - self._disconnect_signals() - self.check_complete.emit() - - def _check_succeeded(self): - """Emit both the connection_available and the check_complete signals, in that order.""" - - if hasattr(self, "connection_check_message") and self.connection_check_message: - self.connection_check_message.close() - - self.connection_available.emit() - self._disconnect_signals() - self.check_complete.emit() - - def _disconnect_signals(self): - if self.signals_connected: - self.connection_checker.success.disconnect(self._check_succeeded) - self.connection_checker.failure.disconnect(self._network_connection_failed) - self.signals_connected = False diff --git a/src/Mod/AddonManager/addonmanager_dependency_installer.py b/src/Mod/AddonManager/addonmanager_dependency_installer.py deleted file mode 100644 index edead4ff53..0000000000 --- a/src/Mod/AddonManager/addonmanager_dependency_installer.py +++ /dev/null @@ -1,195 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Class to manage installation of sets of Python dependencies.""" - -import os -import subprocess -from typing import List - -import addonmanager_freecad_interface as fci -from addonmanager_pyside_interface import QObject, Signal, is_interruption_requested - -import addonmanager_utilities as utils -from addonmanager_installer import AddonInstaller, MacroInstaller -from Addon import Addon - -translate = fci.translate - - -class DependencyInstaller(QObject): - """Install Python dependencies using pip. Intended to be instantiated and then moved into a - QThread: connect the run() function to the QThread's started() signal.""" - - no_python_exe = Signal() - no_pip = Signal(str) # Attempted command - failure = Signal(str, str) # Short message, detailed message - finished = Signal(bool) # True if everything completed normally, otherwise false - - def __init__( - self, - addons: List[Addon], - python_requires: List[str], - python_optional: List[str], - location: os.PathLike = None, - ): - """Install the various types of dependencies that might be specified. If an optional - dependency fails this is non-fatal, but other failures are considered fatal. If location - is specified it overrides the FreeCAD user base directory setting: this is used mostly - for testing purposes and shouldn't be set by normal code in most circumstances. - """ - super().__init__() - self.addons = addons - self.python_requires = python_requires - self.python_optional = python_optional - self.location = location - self.required_succeeded = False - self.finished_successfully = False - - def run(self): - """Normally not called directly, but rather connected to the worker thread's started - signal.""" - try: - if self.python_requires or self.python_optional: - if self._verify_pip(): - if not is_interruption_requested(): - self._install_python_packages() - else: - self.required_succeeded = True - if not is_interruption_requested(): - self._install_addons() - self.finished_successfully = self.required_succeeded - except RuntimeError: - pass - self.finished.emit(self.finished_successfully) - - def _install_python_packages(self): - """Install required and optional Python dependencies using pip.""" - - if self.location: - vendor_path = os.path.join(self.location, "AdditionalPythonPackages") - else: - vendor_path = utils.get_pip_target_directory() - if not os.path.exists(vendor_path): - os.makedirs(vendor_path) - - self.required_succeeded = self._install_required(vendor_path) - self._install_optional(vendor_path) - - def _verify_pip(self) -> bool: - """Ensure that pip is working -- returns True if it is, or False if not. Also emits the - no_pip signal if pip cannot execute.""" - try: - proc = self._run_pip(["--version"]) - fci.Console.PrintMessage(proc.stdout + "\n") - if proc.returncode != 0: - return False - except subprocess.CalledProcessError: - call = utils.create_pip_call([]) - self.no_pip.emit(" ".join(call)) - return False - return True - - def _install_required(self, vendor_path: str) -> bool: - """Install the required Python package dependencies. If any fail a failure - signal is emitted and the function exits without proceeding with any additional - installations.""" - for pymod in self.python_requires: - if is_interruption_requested(): - return False - try: - proc = self._run_pip( - [ - "install", - "--target", - vendor_path, - pymod, - ] - ) - fci.Console.PrintMessage(proc.stdout + "\n") - except subprocess.CalledProcessError as e: - fci.Console.PrintError(str(e) + "\n") - self.failure.emit( - translate( - "AddonsInstaller", - "Installation of Python package {} failed", - ).format(pymod), - str(e), - ) - return False - return True - - def _install_optional(self, vendor_path: str): - """Install the optional Python package dependencies. If any fail a message is printed to - the console, but installation of the others continues.""" - for pymod in self.python_optional: - if is_interruption_requested(): - return - try: - proc = self._run_pip( - [ - "install", - "--target", - vendor_path, - pymod, - ] - ) - fci.Console.PrintMessage(proc.stdout + "\n") - except subprocess.CalledProcessError as e: - fci.Console.PrintError( - translate("AddonsInstaller", "Installation of optional package failed") - + ":\n" - + str(e) - + "\n" - ) - - def _run_pip(self, args): - final_args = utils.create_pip_call(args) - return self._subprocess_wrapper(final_args) - - @staticmethod - def _subprocess_wrapper(args) -> subprocess.CompletedProcess: - """Wrap subprocess call so test code can mock it.""" - return utils.run_interruptable_subprocess(args, timeout_secs=120) - - def _install_addons(self): - for addon in self.addons: - if is_interruption_requested(): - return - fci.Console.PrintMessage( - translate("AddonsInstaller", "Installing required dependency {}").format(addon.name) - + "\n" - ) - if addon.macro is None: - installer = AddonInstaller(addon) - else: - installer = MacroInstaller(addon) - result = installer.run() # Run in this thread, which should be off the GUI thread - if not result: - self.failure.emit( - translate("AddonsInstaller", "Installation of Addon {} failed").format( - addon.name - ), - "", - ) - return diff --git a/src/Mod/AddonManager/addonmanager_devmode.py b/src/Mod/AddonManager/addonmanager_devmode.py deleted file mode 100644 index 4888ae6076..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode.py +++ /dev/null @@ -1,699 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Classes to manage "Developer Mode" """ - -import os -import datetime -import subprocess - -import FreeCAD -import FreeCADGui -from freecad.utils import get_python_exe - -from PySide.QtWidgets import ( - QFileDialog, - QListWidgetItem, - QDialog, - QSizePolicy, - QMessageBox, -) -from PySide.QtGui import ( - QIcon, - QPixmap, -) -from PySide.QtCore import Qt -from addonmanager_git import GitManager, NoGitFound - -from addonmanager_devmode_add_content import AddContent -from addonmanager_devmode_validators import NameValidator, VersionValidator -from addonmanager_devmode_predictor import Predictor -from addonmanager_devmode_people_table import PeopleTable -from addonmanager_devmode_licenses_table import LicensesTable -import addonmanager_utilities as utils - -translate = FreeCAD.Qt.translate - -# pylint: disable=too-few-public-methods - -ContentTypeRole = Qt.UserRole -ContentIndexRole = Qt.UserRole + 1 - - -class AddonGitInterface: - """Wrapper to handle the git calls needed by this class""" - - git_manager = None - - def __init__(self, path): - self.git_exists = False - if not AddonGitInterface.git_manager: - try: - AddonGitInterface.git_manager = GitManager() - except NoGitFound: - FreeCAD.Console.PrintLog("No git found, Addon Manager Developer Mode disabled.") - return - - self.path = path - if os.path.exists(os.path.join(path, ".git")): - self.git_exists = True - self.branch = AddonGitInterface.git_manager.current_branch(self.path) - self.remote = AddonGitInterface.git_manager.get_remote(self.path) - - @property - def branches(self): - """The branches available for this repo.""" - if self.git_exists: - return AddonGitInterface.git_manager.get_branches(self.path) - return [] - - @property - def committers(self): - """The committers to this repo, in the last ten commits""" - if self.git_exists: - return AddonGitInterface.git_manager.get_last_committers(self.path, 10) - return [] - - @property - def authors(self): - """The committers to this repo, in the last ten commits""" - if self.git_exists: - return AddonGitInterface.git_manager.get_last_authors(self.path, 10) - return [] - - -# pylint: disable=too-many-instance-attributes - - -class DeveloperMode: - """The main Developer Mode dialog, for editing package.xml metadata graphically.""" - - def __init__(self): - # In the UI we want to show a translated string for the person type, but the underlying - # string must be the one expected by the metadata parser, in English - self.person_type_translation = { - "maintainer": translate("AddonsInstaller", "Maintainer"), - "author": translate("AddonsInstaller", "Author"), - } - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode.ui") - ) - self.people_table = PeopleTable() - self.licenses_table = LicensesTable() - large_size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - large_size_policy.setHorizontalStretch(2) - small_size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - small_size_policy.setHorizontalStretch(1) - self.people_table.widget.setSizePolicy(large_size_policy) - self.licenses_table.widget.setSizePolicy(small_size_policy) - self.dialog.peopleAndLicenseshorizontalLayout.addWidget(self.people_table.widget) - self.dialog.peopleAndLicenseshorizontalLayout.addWidget(self.licenses_table.widget) - self.pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - self.current_mod: str = "" - self.git_interface = None - self.has_toplevel_icon = False - self.metadata = None - - self._setup_dialog_signals() - - self.dialog.displayNameLineEdit.setValidator(NameValidator()) - self.dialog.versionLineEdit.setValidator(VersionValidator()) - self.dialog.minPythonLineEdit.setValidator(VersionValidator()) - - self.dialog.addContentItemToolButton.setIcon( - QIcon.fromTheme("add", QIcon(":/icons/list-add.svg")) - ) - self.dialog.removeContentItemToolButton.setIcon( - QIcon.fromTheme("remove", QIcon(":/icons/list-remove.svg")) - ) - - def show(self, parent=None, path: str = None): - """Show the main dev mode dialog""" - if parent: - self.dialog.setParent(parent) - if path and os.path.exists(path): - self.dialog.pathToAddonComboBox.setEditText(path) - elif self.pref.HasGroup("recentModsList"): - recent_mods_group = self.pref.GetGroup("recentModsList") - entry = recent_mods_group.GetString("Mod0", "") - if entry: - self._populate_dialog(entry) - self._update_recent_mods(entry) - self._populate_combo() - else: - self._clear_all_fields() - else: - self._clear_all_fields() - - result = self.dialog.exec() - if result == QDialog.Accepted: - self._sync_metadata_to_ui() - now = datetime.date.today() - self.metadata.Date = str(now) - self.metadata.write(os.path.join(self.current_mod, "package.xml")) - - def _populate_dialog(self, path_to_repo: str): - """Populate this dialog using the best available parsing of the contents of the repo at - path_to_repo. This is a multi-layered process that starts with any existing package.xml - file or other known metadata files, and proceeds through examining the contents of the - directory structure.""" - self.current_mod = path_to_repo - self._scan_for_git_info(self.current_mod) - - metadata_path = os.path.join(path_to_repo, "package.xml") - if os.path.exists(metadata_path): - try: - self.metadata = FreeCAD.Metadata(metadata_path) - except FreeCAD.Base.XMLBaseException as e: - FreeCAD.Console.PrintError( - translate( - "AddonsInstaller", - "XML failure while reading metadata from file {}", - ).format(metadata_path) - + "\n\n" - + str(e) - + "\n\n" - ) - except FreeCAD.Base.RuntimeError as e: - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "Invalid metadata in file {}").format( - metadata_path - ) - + "\n\n" - + str(e) - + "\n\n" - ) - - self._clear_all_fields() - - if not self.metadata: - self._predict_metadata() - - self.dialog.displayNameLineEdit.setText(self.metadata.Name) - self.dialog.descriptionTextEdit.setPlainText(self.metadata.Description) - self.dialog.versionLineEdit.setText(self.metadata.Version) - self.dialog.minPythonLineEdit.setText(self.metadata.PythonMin) - - self._populate_urls_from_metadata(self.metadata) - self._populate_contents_from_metadata(self.metadata) - - self._populate_icon_from_metadata(self.metadata) - - self.people_table.show(self.metadata) - self.licenses_table.show(self.metadata, self.current_mod) - - def _populate_urls_from_metadata(self, metadata): - """Use the passed metadata object to populate the urls""" - for url in metadata.Urls: - if url["type"] == "website": - self.dialog.websiteURLLineEdit.setText(url["location"]) - elif url["type"] == "repository": - self.dialog.repositoryURLLineEdit.setText(url["location"]) - branch_from_metadata = url["branch"] - branch_from_local_path = self.git_interface.branch - if branch_from_metadata != branch_from_local_path: - # pylint: disable=line-too-long - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "WARNING: Path specified in package.xml metadata does not match currently checked-out branch.", - ) - + "\n" - ) - self.dialog.branchComboBox.setCurrentText(branch_from_metadata) - elif url["type"] == "bugtracker": - self.dialog.bugtrackerURLLineEdit.setText(url["location"]) - elif url["type"] == "readme": - self.dialog.readmeURLLineEdit.setText(url["location"]) - elif url["type"] == "documentation": - self.dialog.documentationURLLineEdit.setText(url["location"]) - elif url["type"] == "discussion": - self.dialog.discussionURLLineEdit.setText(url["location"]) - - def _populate_contents_from_metadata(self, metadata): - """Use the passed metadata object to populate the contents list""" - contents = metadata.Content - self.dialog.contentsListWidget.clear() - for content_type in contents: - counter = 0 - for item in contents[content_type]: - contents_string = f"[{content_type}] " - info = [] - if item.Name: - info.append(translate("AddonsInstaller", "Name") + ": " + item.Name) - if item.Classname: - info.append(translate("AddonsInstaller", "Class") + ": " + item.Classname) - if item.Description: - info.append( - translate("AddonsInstaller", "Description") + ": " + item.Description - ) - if item.Subdirectory: - info.append( - translate("AddonsInstaller", "Subdirectory") + ": " + item.Subdirectory - ) - if item.File: - info.append(translate("AddonsInstaller", "Files") + ": " + ", ".join(item.File)) - contents_string += ", ".join(info) - - item = QListWidgetItem(contents_string) - item.setData(ContentTypeRole, content_type) - item.setData(ContentIndexRole, counter) - self.dialog.contentsListWidget.addItem(item) - counter += 1 - - def _populate_icon_from_metadata(self, metadata): - """Use the passed metadata object to populate the icon fields""" - self.dialog.iconDisplayLabel.setPixmap(QPixmap()) - icon = metadata.Icon - icon_path = None - if icon: - icon_path = os.path.join(self.current_mod, icon.replace("/", os.path.sep)) - self.has_toplevel_icon = True - else: - self.has_toplevel_icon = False - contents = metadata.Content - if "workbench" in contents: - for wb in contents["workbench"]: - icon = wb.Icon - path = wb.Subdirectory - if icon: - icon_path = os.path.join( - self.current_mod, path, icon.replace("/", os.path.sep) - ) - break - - if icon_path and os.path.isfile(icon_path): - icon_data = QIcon(icon_path) - if not icon_data.isNull(): - self.dialog.iconDisplayLabel.setPixmap(icon_data.pixmap(32, 32)) - self.dialog.iconPathLineEdit.setText(icon) - - def _predict_metadata(self): - """If there is no metadata, try to guess at values for it""" - self.metadata = FreeCAD.Metadata() - predictor = Predictor() - self.metadata = predictor.predict_metadata(self.current_mod) - - def _scan_for_git_info(self, path: str): - """Look for branch availability""" - self.git_interface = AddonGitInterface(path) - if self.git_interface.git_exists: - self.dialog.branchComboBox.clear() - for branch in self.git_interface.branches: - if branch and branch.startswith("origin/") and branch != "origin/HEAD": - self.dialog.branchComboBox.addItem(branch[len("origin/") :]) - self.dialog.branchComboBox.setCurrentText(self.git_interface.branch) - - def _clear_all_fields(self): - """Clear out all fields""" - self.dialog.displayNameLineEdit.clear() - self.dialog.descriptionTextEdit.clear() - self.dialog.versionLineEdit.clear() - self.dialog.websiteURLLineEdit.clear() - self.dialog.repositoryURLLineEdit.clear() - self.dialog.bugtrackerURLLineEdit.clear() - self.dialog.readmeURLLineEdit.clear() - self.dialog.documentationURLLineEdit.clear() - self.dialog.discussionURLLineEdit.clear() - self.dialog.minPythonLineEdit.clear() - self.dialog.iconDisplayLabel.setPixmap(QPixmap()) - self.dialog.iconPathLineEdit.clear() - - def _setup_dialog_signals(self): - """Set up the signal and slot connections for the main dialog.""" - - self.dialog.addonPathBrowseButton.clicked.connect(self._addon_browse_button_clicked) - self.dialog.pathToAddonComboBox.editTextChanged.connect(self._addon_combo_text_changed) - self.dialog.detectMinPythonButton.clicked.connect(self._detect_min_python_clicked) - self.dialog.iconBrowseButton.clicked.connect(self._browse_for_icon_clicked) - - self.dialog.addContentItemToolButton.clicked.connect(self._add_content_clicked) - self.dialog.removeContentItemToolButton.clicked.connect(self._remove_content_clicked) - self.dialog.contentsListWidget.itemSelectionChanged.connect(self._content_selection_changed) - self.dialog.contentsListWidget.itemDoubleClicked.connect(self._edit_content) - - self.dialog.versionToTodayButton.clicked.connect(self._set_to_today_clicked) - - # Finally, populate the combo boxes, etc. - self._populate_combo() - - # Disable all the "Remove" buttons until something is selected - self.dialog.removeContentItemToolButton.setDisabled(True) - - def _sync_metadata_to_ui(self): - """Take the data from the UI fields and put it into the stored metadata - object. Only overwrites known data fields: unknown metadata will be retained.""" - - if not self.metadata: - self.metadata = FreeCAD.Metadata() - - self.metadata.Name = self.dialog.displayNameLineEdit.text() - self.metadata.Description = self.dialog.descriptionTextEdit.document().toPlainText() - self.metadata.Version = self.dialog.versionLineEdit.text() - self.metadata.Icon = self.dialog.iconPathLineEdit.text() - - urls = [] - if self.dialog.websiteURLLineEdit.text(): - urls.append({"location": self.dialog.websiteURLLineEdit.text(), "type": "website"}) - if self.dialog.repositoryURLLineEdit.text(): - urls.append( - { - "location": self.dialog.repositoryURLLineEdit.text(), - "type": "repository", - "branch": self.dialog.branchComboBox.currentText(), - } - ) - if self.dialog.bugtrackerURLLineEdit.text(): - urls.append( - { - "location": self.dialog.bugtrackerURLLineEdit.text(), - "type": "bugtracker", - } - ) - if self.dialog.readmeURLLineEdit.text(): - urls.append({"location": self.dialog.readmeURLLineEdit.text(), "type": "readme"}) - if self.dialog.documentationURLLineEdit.text(): - urls.append( - { - "location": self.dialog.documentationURLLineEdit.text(), - "type": "documentation", - } - ) - if self.dialog.discussionURLLineEdit.text(): - urls.append( - { - "location": self.dialog.discussionURLLineEdit.text(), - "type": "discussion", - } - ) - self.metadata.Urls = urls - - if self.dialog.minPythonLineEdit.text(): - self.metadata.PythonMin = self.dialog.minPythonLineEdit.text() - else: - self.metadata.PythonMin = "0.0.0" # Code for "unset" - - # Content, people, and licenses should already be synchronized - - ############################################################################################### - # DIALOG SLOTS - ############################################################################################### - - def _addon_browse_button_clicked(self): - """Launch a modal file/folder selection dialog -- if something is selected, it is - processed by the parsing code and used to fill in the contents of the rest of the - dialog.""" - - start_dir = os.path.join(FreeCAD.getUserAppDataDir(), "Mod") - mod_dir = QFileDialog.getExistingDirectory( - parent=self.dialog, - caption=translate( - "AddonsInstaller", - "Select the folder containing your Addon", - ), - dir=start_dir, - ) - - if mod_dir and os.path.exists(mod_dir): - self.dialog.pathToAddonComboBox.setEditText(mod_dir) - - def _addon_combo_text_changed(self, new_text: str): - """Called when the text is changed, either because it was directly edited, or because - a new item was selected.""" - if new_text == self.current_mod: - # It doesn't look like it actually changed, bail out - return - self.metadata = None - self._clear_all_fields() - if not os.path.exists(new_text): - # This isn't a thing (Yet. Maybe the user is still typing?) - return - self._populate_dialog(new_text) - self._update_recent_mods(new_text) - self._populate_combo() - - def _populate_combo(self): - """Fill in the combo box with the values from the stored recent mods list, selecting the - top one. Does not trigger any signals.""" - combo = self.dialog.pathToAddonComboBox - combo.blockSignals(True) - recent_mods_group = self.pref.GetGroup("recentModsList") - recent_mods = set() - combo.clear() - for i in range(10): - entry_name = f"Mod{i}" - mod = recent_mods_group.GetString(entry_name, "None") - if mod != "None" and mod not in recent_mods and os.path.exists(mod): - recent_mods.add(mod) - combo.addItem(mod) - if recent_mods: - combo.setCurrentIndex(0) - combo.blockSignals(False) - - def _update_recent_mods(self, path): - """Update the list of recent mods, storing at most ten, with path at the top of the - list.""" - recent_mod_paths = [path] - if self.pref.HasGroup("recentModsList"): - recent_mods_group = self.pref.GetGroup("recentModsList") - - # This group has a maximum of ten entries, sorted by last-accessed date - for i in range(0, 10): - entry_name = f"Mod{i}" - entry = recent_mods_group.GetString(entry_name, "") - if entry and entry not in recent_mod_paths and os.path.exists(entry): - recent_mod_paths.append(entry) - - # Remove the whole thing, so we can recreate it from scratch - self.pref.RemGroup("recentModsList") - - if recent_mod_paths: - recent_mods_group = self.pref.GetGroup("recentModsList") - for i, mod in zip(range(10), recent_mod_paths): - entry_name = f"Mod{i}" - recent_mods_group.SetString(entry_name, mod) - - def _add_content_clicked(self): - """Callback: The Add Content button was clicked""" - dlg = AddContent(self.current_mod, self.metadata) - singleton = False - if self.dialog.contentsListWidget.count() == 0: - singleton = True - content_type, new_metadata = dlg.exec(singleton=singleton) - if content_type and new_metadata: - self.metadata.addContentItem(content_type, new_metadata) - self._populate_contents_from_metadata(self.metadata) - - def _remove_content_clicked(self): - """Callback: the remove content button was clicked""" - - item = self.dialog.contentsListWidget.currentItem() - if not item: - return - content_type = item.data(ContentTypeRole) - content_index = item.data(ContentIndexRole) - if self.metadata.Content[content_type] and content_index < len( - self.metadata.Content[content_type] - ): - content_name = self.metadata.Content[content_type][content_index].Name - self.metadata.removeContentItem(content_type, content_name) - self._populate_contents_from_metadata(self.metadata) - - def _content_selection_changed(self): - """Callback: the selected content item changed""" - items = self.dialog.contentsListWidget.selectedItems() - if items: - self.dialog.removeContentItemToolButton.setDisabled(False) - else: - self.dialog.removeContentItemToolButton.setDisabled(True) - - def _edit_content(self, item): - """Callback: a content row was double-clicked""" - dlg = AddContent(self.current_mod, self.metadata) - - content_type = item.data(ContentTypeRole) - content_index = item.data(ContentIndexRole) - - content = self.metadata.Content - metadata = content[content_type][content_index] - old_name = metadata.Name - new_type, new_metadata = dlg.exec(content_type, metadata, len(content) == 1) - if new_type and new_metadata: - self.metadata.removeContentItem(content_type, old_name) - self.metadata.addContentItem(new_type, new_metadata) - self._populate_contents_from_metadata(self.metadata) - - def _set_to_today_clicked(self): - """Callback: the "set to today" button was clicked""" - year = datetime.date.today().year - month = datetime.date.today().month - day = datetime.date.today().day - version_string = f"{year}.{month:>02}.{day:>02}" - self.dialog.versionLineEdit.setText(version_string) - - def _detect_min_python_clicked(self): - if not self._ensure_vermin_loaded(): - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "No Vermin, cancelling operation.", - "NOTE: Vermin is a Python package and proper noun - do not translate", - ) - + "\n" - ) - return - FreeCAD.Console.PrintMessage( - translate("AddonsInstaller", "Scanning Addon for Python version compatibility") - + "...\n" - ) - # pylint: disable=import-outside-toplevel - import vermin - - required_minor_version = 0 - for dir_path, _, filenames in os.walk(self.current_mod): - for filename in filenames: - if filename.endswith(".py"): - with open(os.path.join(dir_path, filename), encoding="utf-8") as f: - contents = f.read() - version_strings = vermin.version_strings(vermin.detect(contents)) - version = version_strings.split(",") - if len(version) >= 2: - # Only care about Py3, and only if there is a dot in the version: - if "." in version[1]: - py3 = version[1].split(".") - major = int(py3[0].strip()) - minor = int(py3[1].strip()) - if major == 3: - FreeCAD.Console.PrintLog( - f"Detected Python 3.{minor} required by {filename}\n" - ) - required_minor_version = max(required_minor_version, minor) - self.dialog.minPythonLineEdit.setText(f"3.{required_minor_version}") - QMessageBox.information( - self.dialog, - translate("AddonsInstaller", "Minimum Python Version Detected"), - translate( - "AddonsInstaller", - "Vermin auto-detected a required version of Python 3.{}", - ).format(required_minor_version), - QMessageBox.Ok, - ) - - def _ensure_vermin_loaded(self) -> bool: - try: - # pylint: disable=import-outside-toplevel,unused-import - import vermin - except ImportError: - # pylint: disable=line-too-long - response = QMessageBox.question( - self.dialog, - translate("AddonsInstaller", "Install Vermin?"), - translate( - "AddonsInstaller", - "Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install?", - ), - QMessageBox.Yes | QMessageBox.Cancel, - ) - if response == QMessageBox.Cancel: - return False - FreeCAD.Console.PrintMessage( - translate("AddonsInstaller", "Attempting to install Vermin from PyPi") + "...\n" - ) - python_exe = get_python_exe() - vendor_path = os.path.join(FreeCAD.getUserAppDataDir(), "AdditionalPythonPackages") - if not os.path.exists(vendor_path): - os.makedirs(vendor_path) - - proc = subprocess.run( - [ - python_exe, - "-m", - "pip", - "install", - "--disable-pip-version-check", - "--target", - vendor_path, - "vermin", - ], - capture_output=True, - check=True, - ) - FreeCAD.Console.PrintMessage(proc.stdout.decode()) - if proc.returncode != 0: - QMessageBox.critical( - self.dialog, - translate("AddonsInstaller", "Installation failed"), - translate( - "AddonsInstaller", - "Failed to install Vermin -- check Report View for details.", - "'Vermin' is the name of a Python package, do not translate", - ), - QMessageBox.Cancel, - ) - return False - try: - # pylint: disable=import-outside-toplevel - import vermin - except ImportError: - QMessageBox.critical( - self.dialog, - translate("AddonsInstaller", "Installation failed"), - translate( - "AddonsInstaller", - "Failed to import vermin after installation -- cannot scan Addon.", - "'vermin' is the name of a Python package, do not translate", - ), - QMessageBox.Cancel, - ) - return False - return True - - def _browse_for_icon_clicked(self): - """Callback: when the "Browse..." button for the icon field is clicked""" - new_icon_path, _ = QFileDialog.getOpenFileName( - parent=self.dialog, - caption=translate( - "AddonsInstaller", - "Select an icon file for this package", - ), - dir=self.current_mod, - ) - - if not new_icon_path: - return - - base_path = self.current_mod.replace("/", os.path.sep) - icon_path = new_icon_path.replace("/", os.path.sep) - if base_path[-1] != os.path.sep: - base_path += os.path.sep - - if not icon_path.startswith(base_path): - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "{} is not a subdirectory of {}").format( - new_icon_path, self.current_mod - ) - + "\n" - ) - return - self.metadata.Icon = new_icon_path[len(base_path) :] - self._populate_icon_from_metadata(self.metadata) diff --git a/src/Mod/AddonManager/addonmanager_devmode_add_content.py b/src/Mod/AddonManager/addonmanager_devmode_add_content.py deleted file mode 100644 index 2907fbc8d4..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_add_content.py +++ /dev/null @@ -1,635 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains a class for adding a single content item, as well as auxiliary classes for -its dependent dialog boxes.""" - -import os -from typing import Optional, Tuple, List - -import FreeCAD -import FreeCADGui - -from Addon import INTERNAL_WORKBENCHES - -from PySide.QtWidgets import ( - QDialog, - QLayout, - QFileDialog, - QTableWidgetItem, - QSizePolicy, -) -from PySide.QtGui import QIcon -from PySide.QtCore import Qt - -from addonmanager_devmode_validators import ( - VersionValidator, - NameValidator, - PythonIdentifierValidator, -) -from addonmanager_devmode_people_table import PeopleTable -from addonmanager_devmode_licenses_table import LicensesTable - -# pylint: disable=too-few-public-methods - -translate = FreeCAD.Qt.translate - - -class AddContent: - """A dialog for adding a single content item to the package metadata.""" - - def __init__(self, path_to_addon: str, toplevel_metadata: FreeCAD.Metadata): - """path_to_addon is the full path to the toplevel directory of this Addon, and - toplevel_metadata is to overall package.xml Metadata object for this Addon. This - information is used to assist the use in filling out the dialog by providing - sensible default values.""" - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_add_content.ui") - ) - # These are in alphabetical order in English, but their actual label may be translated in - # the GUI. Store their underlying type as user data. - self.dialog.addonKindComboBox.setItemData(0, "macro") - self.dialog.addonKindComboBox.setItemData(1, "preferencepack") - self.dialog.addonKindComboBox.setItemData(2, "workbench") - self.dialog.addonKindComboBox.setItemData(3, "bundle") - self.dialog.addonKindComboBox.setItemData(4, "other") - - self.people_table = PeopleTable() - self.licenses_table = LicensesTable() - large_size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - large_size_policy.setHorizontalStretch(2) - small_size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - small_size_policy.setHorizontalStretch(1) - self.people_table.widget.setSizePolicy(large_size_policy) - self.licenses_table.widget.setSizePolicy(small_size_policy) - self.dialog.peopleAndLicenseshorizontalLayout.addWidget(self.people_table.widget) - self.dialog.peopleAndLicenseshorizontalLayout.addWidget(self.licenses_table.widget) - - self.toplevel_metadata = toplevel_metadata - self.metadata = None - self.path_to_addon = path_to_addon.replace("/", os.path.sep) - if self.path_to_addon[-1] != os.path.sep: - self.path_to_addon += os.path.sep # Make sure the path ends with a separator - - self.dialog.iconLabel.hide() # Until we have an icon to display - - self.dialog.iconBrowseButton.clicked.connect(self._browse_for_icon_clicked) - self.dialog.subdirectoryBrowseButton.clicked.connect(self._browse_for_subdirectory_clicked) - self.dialog.tagsButton.clicked.connect(self._tags_clicked) - self.dialog.dependenciesButton.clicked.connect(self._dependencies_clicked) - self.dialog.freecadVersionsButton.clicked.connect(self._freecad_versions_clicked) - - self.dialog.versionLineEdit.setValidator(VersionValidator()) - self.dialog.prefPackNameLineEdit.setValidator(NameValidator()) - self.dialog.displayNameLineEdit.setValidator(NameValidator()) - self.dialog.workbenchClassnameLineEdit.setValidator(PythonIdentifierValidator()) - - def exec( - self, - content_kind: str = "workbench", - metadata: FreeCAD.Metadata = None, - singleton: bool = True, - ) -> Optional[Tuple[str, FreeCAD.Metadata]]: - """Execute the dialog as a modal, returning a new Metadata object if the dialog - is accepted, or None if it is rejected. This metadata object represents a single - new content item. It's returned as a tuple with the object type as the first component, - and the metadata object itself as the second.""" - if metadata: - self.metadata = FreeCAD.Metadata(metadata) # Deep copy - else: - self.metadata = FreeCAD.Metadata() - self.dialog.singletonCheckBox.setChecked(singleton) - if singleton: - # This doesn't happen automatically the first time - self.dialog.otherMetadataGroupBox.hide() - index = self.dialog.addonKindComboBox.findData(content_kind) - if index == -1: - index = 2 # Workbench - FreeCAD.Console.PrintWarning( - translate("AddonsInstaller", "Unrecognized content kind '{}'").format(content_kind) - + "\n" - ) - self.dialog.addonKindComboBox.setCurrentIndex(index) - if metadata: - self._populate_dialog(metadata) - - self.dialog.layout().setSizeConstraint(QLayout.SetFixedSize) - result = self.dialog.exec() - if result == QDialog.Accepted: - return self._generate_metadata() - return None - - def _populate_dialog(self, metadata: FreeCAD.Metadata) -> None: - """Fill in the dialog with the details from the passed metadata object""" - addon_kind = self.dialog.addonKindComboBox.currentData() - if addon_kind == "workbench": - self.dialog.workbenchClassnameLineEdit.setText(metadata.Classname) - elif addon_kind == "macro": - files = self.metadata.File - if files: - self.dialog.macroFileLineEdit.setText(files[0]) - elif addon_kind == "preferencepack": - self.dialog.prefPackNameLineEdit.setText(self.metadata.Name) - elif addon_kind == "bundle" or addon_kind == "other": - pass - else: - raise RuntimeError("Invalid data found for selection") - - # Now set the rest of it - if metadata.Icon: - self._set_icon(metadata.Icon) - elif self.toplevel_metadata.Icon: - if metadata.Subdirectory and metadata.Subdirectory != "./": - self._set_icon("../" + self.toplevel_metadata.Icon) - else: - self._set_icon(self.toplevel_metadata.Icon) - else: - self.dialog.iconLabel.hide() - self.dialog.iconLineEdit.setText("") - - if metadata.Subdirectory: - self.dialog.subdirectoryLineEdit.setText(metadata.Subdirectory) - else: - self.dialog.subdirectoryLineEdit.setText("") - - self.dialog.displayNameLineEdit.setText(metadata.Name) - self.dialog.descriptionTextEdit.setPlainText(metadata.Description) - self.dialog.versionLineEdit.setText(metadata.Version) - - self.people_table.show(metadata) - self.licenses_table.show(metadata, self.path_to_addon) - - def _set_icon(self, icon_relative_path): - """Load the icon and display it, and its path, in the dialog.""" - icon_path = os.path.join(self.path_to_addon, icon_relative_path.replace("/", os.path.sep)) - if os.path.isfile(icon_path): - icon_data = QIcon(icon_path) - if not icon_data.isNull(): - self.dialog.iconLabel.setPixmap(icon_data.pixmap(32, 32)) - self.dialog.iconLabel.show() - else: - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "Unable to locate icon at {}").format(icon_path) + "\n" - ) - self.dialog.iconLineEdit.setText(icon_relative_path) - - def _generate_metadata(self) -> Tuple[str, FreeCAD.Metadata]: - """Create and return a new metadata object based on the contents of the dialog.""" - - if not self.metadata: - self.metadata = FreeCAD.Metadata() - - ########################################################################################## - # Required data: - current_data: str = self.dialog.addonKindComboBox.currentData() - if current_data == "preferencepack": - self.metadata.Name = self.dialog.prefPackNameLineEdit.text() - elif self.dialog.displayNameLineEdit.text(): - self.metadata.Name = self.dialog.displayNameLineEdit.text() - - if current_data == "workbench": - self.metadata.Classname = self.dialog.workbenchClassnameLineEdit.text() - elif current_data == "macro": - self.metadata.File = [self.dialog.macroFileLineEdit.text()] - ########################################################################################## - - self.metadata.Subdirectory = self.dialog.subdirectoryLineEdit.text() - self.metadata.Icon = self.dialog.iconLineEdit.text() - - # Early return if this is the only addon - if self.dialog.singletonCheckBox.isChecked(): - return current_data, self.metadata - - # Otherwise, process the rest of the metadata (display name is already done) - self.metadata.Description = self.dialog.descriptionTextEdit.document().toPlainText() - self.metadata.Version = self.dialog.versionLineEdit.text() - - maintainers = [] - authors = [] - for row in range(self.dialog.peopleTableWidget.rowCount()): - person_type = self.dialog.peopleTableWidget.item(row, 0).data() - name = self.dialog.peopleTableWidget.item(row, 1).text() - email = self.dialog.peopleTableWidget.item(row, 2).text() - if person_type == "maintainer": - maintainers.append({"name": name, "email": email}) - elif person_type == "author": - authors.append({"name": name, "email": email}) - self.metadata.Maintainer = maintainers - self.metadata.Author = authors - - licenses = [] - for row in range(self.dialog.licensesTableWidget.rowCount()): - new_license = { - "name": self.dialog.licensesTableWidget.item(row, 0).text, - "file": self.dialog.licensesTableWidget.item(row, 1).text(), - } - licenses.append(new_license) - self.metadata.License = licenses - - return self.dialog.addonKindComboBox.currentData(), self.metadata - - ############################################################################################### - # DIALOG SLOTS - ############################################################################################### - - def _browse_for_icon_clicked(self): - """Callback: when the "Browse..." button for the icon field is clicked""" - subdir = self.dialog.subdirectoryLineEdit.text() - start_dir = os.path.join(self.path_to_addon, subdir) - new_icon_path, _ = QFileDialog.getOpenFileName( - parent=self.dialog, - caption=translate( - "AddonsInstaller", - "Select an icon file for this content item", - ), - dir=start_dir, - ) - - if not new_icon_path: - return - - base_path = self.path_to_addon.replace("/", os.path.sep) - icon_path = new_icon_path.replace("/", os.path.sep) - if base_path[-1] != os.path.sep: - base_path += os.path.sep - - if not icon_path.startswith(base_path): - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "{} is not a subdirectory of {}").format( - icon_path, base_path - ) - + "\n" - ) - return - self._set_icon(new_icon_path[len(base_path) :]) - self.metadata.Icon = new_icon_path[len(base_path) :] - - def _browse_for_subdirectory_clicked(self): - """Callback: when the "Browse..." button for the subdirectory field is clicked""" - subdir = self.dialog.subdirectoryLineEdit.text() - start_dir = os.path.join(self.path_to_addon, subdir) - new_subdir_path = QFileDialog.getExistingDirectory( - parent=self.dialog, - caption=translate( - "AddonsInstaller", - "Select the subdirectory for this content item", - ), - dir=start_dir, - ) - if not new_subdir_path: - return - if new_subdir_path[-1] != "/": - new_subdir_path += "/" - - # Three legal possibilities: - # 1) This might be the toplevel directory, in which case we want to set - # metadata.Subdirectory to "./" - # 2) This might be a subdirectory with the same name as the content item, in which case - # we don't need to set metadata.Subdirectory at all - # 3) This might be some other directory name, but still contained within the top-level - # directory, in which case we want to set metadata.Subdirectory to the relative path - - # First, reject anything that isn't within the appropriate directory structure: - base_path = self.path_to_addon.replace("/", os.path.sep) - subdir_path = new_subdir_path.replace("/", os.path.sep) - if not subdir_path.startswith(base_path): - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "{} is not a subdirectory of {}").format( - subdir_path, base_path - ) - + "\n" - ) - return - - relative_path = subdir_path[len(base_path) :] - if not relative_path: - relative_path = "./" - elif relative_path[-1] == os.path.sep: - relative_path = relative_path[:-1] - self.dialog.subdirectoryLineEdit.setText(relative_path) - - def _tags_clicked(self): - """Show the tag editor""" - tags = [] - if not self.metadata: - self.metadata = FreeCAD.Metadata() - if self.metadata: - tags = self.metadata.Tag - dlg = EditTags(tags) - new_tags = dlg.exec() - self.metadata.Tag = new_tags - - def _freecad_versions_clicked(self): - """Show the FreeCAD version editor""" - if not self.metadata: - self.metadata = FreeCAD.Metadata() - dlg = EditFreeCADVersions() - dlg.exec(self.metadata) - - def _dependencies_clicked(self): - """Show the dependencies editor""" - if not self.metadata: - self.metadata = FreeCAD.Metadata() - dlg = EditDependencies() - dlg.exec(self.metadata) # Modifies metadata directly - - -class EditTags: - """A dialog to edit tags""" - - def __init__(self, tags: List[str] = None): - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_tags.ui") - ) - self.original_tags = tags - if tags: - self.dialog.lineEdit.setText(", ".join(tags)) - - def exec(self): - """Execute the dialog, returning a list of tags (which may be empty, but still represents - the expected list of tags to be set, e.g. the user may have removed them all). - """ - result = self.dialog.exec() - if result == QDialog.Accepted: - new_tags: List[str] = self.dialog.lineEdit.text().split(",") - clean_tags: List[str] = [] - for tag in new_tags: - clean_tags.append(tag.strip()) - return clean_tags - return self.original_tags - - -class EditDependencies: - """A dialog to edit dependency information""" - - def __init__(self): - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_dependencies.ui") - ) - self.dialog.addDependencyToolButton.setIcon( - QIcon.fromTheme("add", QIcon(":/icons/list-add.svg")) - ) - self.dialog.removeDependencyToolButton.setIcon( - QIcon.fromTheme("remove", QIcon(":/icons/list-remove.svg")) - ) - self.dialog.addDependencyToolButton.clicked.connect(self._add_dependency_clicked) - self.dialog.removeDependencyToolButton.clicked.connect(self._remove_dependency_clicked) - self.dialog.tableWidget.itemDoubleClicked.connect(self._edit_dependency) - self.dialog.tableWidget.itemSelectionChanged.connect(self._current_index_changed) - - self.dialog.removeDependencyToolButton.setDisabled(True) - self.metadata = None - - def exec(self, metadata: FreeCAD.Metadata): - """Execute the dialog""" - self.metadata = FreeCAD.Metadata(metadata) # Make a copy, in case we cancel - row = 0 - for dep in self.metadata.Depend: - dep_type = dep["type"] - dep_name = dep["package"] - dep_optional = dep["optional"] - self._add_row(row, dep_type, dep_name, dep_optional) - row += 1 - result = self.dialog.exec() - if result == QDialog.Accepted: - metadata.Depend = self.metadata.Depend - - def _add_dependency_clicked(self): - """Callback: The add button was clicked""" - dlg = EditDependency() - dep_type, dep_name, dep_optional = dlg.exec() - if dep_name: - row = self.dialog.tableWidget.rowCount() - self._add_row(row, dep_type, dep_name, dep_optional) - self.metadata.addDepend( - {"package": dep_name, "type": dep_type, "optional": dep_optional} - ) - - def _add_row(self, row, dep_type, dep_name, dep_optional): - """Utility function to add a row to the table.""" - translations = { - "automatic": translate("AddonsInstaller", "Automatic"), - "workbench": translate("AddonsInstaller", "Workbench"), - "addon": translate("AddonsInstaller", "Addon"), - "python": translate("AddonsInstaller", "Python"), - } - if dep_type and dep_name: - self.dialog.tableWidget.insertRow(row) - type_item = QTableWidgetItem(translations[dep_type]) - type_item.setData(Qt.UserRole, dep_type) - self.dialog.tableWidget.setItem(row, 0, type_item) - self.dialog.tableWidget.setItem(row, 1, QTableWidgetItem(dep_name)) - if dep_optional: - self.dialog.tableWidget.setItem( - row, 2, QTableWidgetItem(translate("AddonsInstaller", "Yes")) - ) - - def _remove_dependency_clicked(self): - """Callback: The remove button was clicked""" - items = self.dialog.tableWidget.selectedItems() - if items: - row = items[0].row() - dep_type = self.dialog.tableWidget.item(row, 0).data(Qt.UserRole) - dep_name = self.dialog.tableWidget.item(row, 1).text() - dep_optional = bool(self.dialog.tableWidget.item(row, 2)) - self.metadata.removeDepend( - {"package": dep_name, "type": dep_type, "optional": dep_optional} - ) - self.dialog.tableWidget.removeRow(row) - - def _edit_dependency(self, item): - """Callback: the dependency was double-clicked""" - row = item.row() - dlg = EditDependency() - dep_type = self.dialog.tableWidget.item(row, 0).data(Qt.UserRole) - dep_name = self.dialog.tableWidget.item(row, 1).text() - dep_optional = bool(self.dialog.tableWidget.item(row, 2)) - new_dep_type, new_dep_name, new_dep_optional = dlg.exec(dep_type, dep_name, dep_optional) - if dep_type and dep_name: - self.metadata.removeDepend( - {"package": dep_name, "type": dep_type, "optional": dep_optional} - ) - self.metadata.addDepend( - { - "package": new_dep_name, - "type": new_dep_type, - "optional": new_dep_optional, - } - ) - self.dialog.tableWidget.removeRow(row) - self._add_row(row, dep_type, dep_name, dep_optional) - - def _current_index_changed(self): - if self.dialog.tableWidget.selectedItems(): - self.dialog.removeDependencyToolButton.setDisabled(False) - else: - self.dialog.removeDependencyToolButton.setDisabled(True) - - -class EditDependency: - """A dialog to edit a single piece of dependency information""" - - def __init__(self): - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_edit_dependency.ui") - ) - - self.dialog.typeComboBox.addItem( - translate("AddonsInstaller", "Internal Workbench"), "workbench" - ) - self.dialog.typeComboBox.addItem(translate("AddonsInstaller", "External Addon"), "addon") - self.dialog.typeComboBox.addItem(translate("AddonsInstaller", "Python Package"), "python") - - self.dialog.typeComboBox.currentIndexChanged.connect(self._type_selection_changed) - self.dialog.dependencyComboBox.currentIndexChanged.connect( - self._dependency_selection_changed - ) - - # Expect mostly Python dependencies... - self.dialog.typeComboBox.setCurrentIndex(2) - - self.dialog.layout().setSizeConstraint(QLayout.SetFixedSize) - - def exec(self, dep_type="", dep_name="", dep_optional=False) -> Tuple[str, str, bool]: - """Execute the dialog, returning a tuple of the type of dependency (workbench, addon, or - python), the name of the dependency, and a boolean indicating whether this is optional. - """ - - # If we are editing an existing row, set up the dialog: - if dep_type and dep_name: - index = self.dialog.typeComboBox.findData(dep_type) - if index == -1: - raise RuntimeError(f"Invalid dependency type {dep_type}") - self.dialog.typeComboBox.setCurrentIndex(index) - index = self.dialog.dependencyComboBox.findData(dep_name) - if index == -1: - index = self.dialog.dependencyComboBox.findData("other") - self.dialog.dependencyComboBox.setCurrentIndex(index) - self.dialog.lineEdit.setText(dep_name) - self.dialog.optionalCheckBox.setChecked(dep_optional) - - # Run the dialog (modal) - result = self.dialog.exec() - if result == QDialog.Accepted: - dep_type = self.dialog.typeComboBox.currentData() - dep_optional = self.dialog.optionalCheckBox.isChecked() - dep_name = self.dialog.dependencyComboBox.currentData() - if dep_name == "other": - dep_name = self.dialog.lineEdit.text() - return dep_type, dep_name, dep_optional - return "", "", False - - def _populate_internal_workbenches(self): - """Add all known internal FreeCAD Workbenches to the list""" - self.dialog.dependencyComboBox.clear() - for display_name, name in INTERNAL_WORKBENCHES.items(): - self.dialog.dependencyComboBox.addItem(display_name, name) - # No "other" option is supported for this type of dependency - - def _populate_external_addons(self): - """Add all known addons to the list""" - self.dialog.dependencyComboBox.clear() - # pylint: disable=import-outside-toplevel - from AddonManager import INSTANCE as AM_INSTANCE - - repo_dict = {} - # We need a case-insensitive sorting of all repo types, displayed and sorted by their - # display name, but keeping track of their official name as well (stored in the UserRole) - for repo in AM_INSTANCE.item_model.repos: - repo_dict[repo.display_name.lower()] = (repo.display_name, repo.name) - sorted_keys = sorted(repo_dict) - for item in sorted_keys: - self.dialog.dependencyComboBox.addItem(repo_dict[item][0], repo_dict[item][1]) - self.dialog.dependencyComboBox.addItem(translate("AddonsInstaller", "Other..."), "other") - - def _populate_allowed_python_packages(self): - """Add all allowed python packages to the list""" - self.dialog.dependencyComboBox.clear() - # pylint: disable=import-outside-toplevel - from AddonManager import INSTANCE as AM_INSTANCE - - packages = sorted(AM_INSTANCE.allowed_packages) - for package in packages: - self.dialog.dependencyComboBox.addItem(package, package) - self.dialog.dependencyComboBox.addItem(translate("AddonsInstaller", "Other..."), "other") - - def _type_selection_changed(self, _): - """Callback: The type of dependency has been changed""" - selection = self.dialog.typeComboBox.currentData() - if selection == "workbench": - self._populate_internal_workbenches() - elif selection == "addon": - self._populate_external_addons() - elif selection == "python": - self._populate_allowed_python_packages() - else: - raise RuntimeError("Invalid data found for selection") - - def _dependency_selection_changed(self, _): - selection = self.dialog.dependencyComboBox.currentData() - if selection == "other": - self.dialog.lineEdit.show() - self.dialog.otherNote.show() - else: - self.dialog.lineEdit.hide() - self.dialog.otherNote.hide() - - -class EditFreeCADVersions: - """A dialog to edit minimum and maximum FreeCAD version support""" - - def __init__(self): - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_freecad_versions.ui") - ) - - def exec(self, metadata: FreeCAD.Metadata): - """Execute the dialog""" - if metadata.FreeCADMin != "0.0.0": - self.dialog.minVersionLineEdit.setText(metadata.FreeCADMin) - if metadata.FreeCADMax != "0.0.0": - self.dialog.maxVersionLineEdit.setText(metadata.FreeCADMax) - result = self.dialog.exec() - if result == QDialog.Accepted: - if self.dialog.minVersionLineEdit.text(): - metadata.FreeCADMin = self.dialog.minVersionLineEdit.text() - else: - metadata.FreeCADMin = None - if self.dialog.maxVersionLineEdit.text(): - metadata.FreeCADMax = self.dialog.maxVersionLineEdit.text() - else: - metadata.FreeCADMax = None - - -class EditAdvancedVersions: - """A dialog to support mapping specific git branches, tags, or commits to specific - versions of FreeCAD.""" - - def __init__(self): - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_advanced_freecad_versions.ui") - ) - - def exec(self): - """Execute the dialog""" - self.dialog.exec() diff --git a/src/Mod/AddonManager/addonmanager_devmode_license_selector.py b/src/Mod/AddonManager/addonmanager_devmode_license_selector.py deleted file mode 100644 index 2e6441d9f8..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_license_selector.py +++ /dev/null @@ -1,275 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains a class to manage selection of a license for an Addon.""" - -import os -from datetime import date -from typing import Optional, Tuple - -import FreeCAD -import FreeCADGui - -from PySide.QtWidgets import QFileDialog, QDialog -from PySide.QtGui import QDesktopServices -from PySide.QtCore import QUrl, QFile, QIODevice - -try: - from PySide.QtGui import ( - QRegularExpressionValidator, - ) - from PySide.QtCore import QRegularExpression - - RegexWrapper = QRegularExpression - RegexValidatorWrapper = QRegularExpressionValidator -except ImportError: - QRegularExpressionValidator = None - QRegularExpression = None - from PySide.QtGui import ( - QRegExpValidator, - ) - from PySide.QtCore import QRegExp - - RegexWrapper = QRegExp - RegexValidatorWrapper = QRegExpValidator - -translate = FreeCAD.Qt.translate - - -class LicenseSelector: - """Choose from a selection of licenses, or provide your own. Includes the capability to create - the license file itself for a variety of popular open-source licenses, as well as providing - links to opensource.org's page about the various licenses (which often link to other resources). - """ - - licenses = { - "Apache-2.0": ( - "Apache License, Version 2.0", - "https://opensource.org/licenses/Apache-2.0", - ), - "BSD-2-Clause": ( - "The 2-Clause BSD License", - "https://opensource.org/licenses/BSD-2-Clause", - ), - "BSD-3-Clause": ( - "The 3-Clause BSD License", - "https://opensource.org/licenses/BSD-3-Clause", - ), - "CC0-1.0": ( - "No Rights Reserved/Public Domain", - "https://creativecommons.org/choose/zero/", - ), - "GPL-2.0-or-later": ( - "GNU General Public License version 2", - "https://opensource.org/licenses/GPL-2.0", - ), - "GPL-3.0-or-later": ( - "GNU General Public License version 3", - "https://opensource.org/licenses/GPL-3.0", - ), - "LGPL-2.1-or-later": ( - "GNU Lesser General Public License version 2.1", - "https://opensource.org/licenses/LGPL-2.1", - ), - "LGPL-3.0-or-later": ( - "GNU Lesser General Public License version 3", - "https://opensource.org/licenses/LGPL-3.0", - ), - "MIT": ( - "The MIT License", - "https://opensource.org/licenses/MIT", - ), - "MPL-2.0": ( - "Mozilla Public License 2.0", - "https://opensource.org/licenses/MPL-2.0", - ), - } - - def __init__(self, path_to_addon): - self.other_label = translate( - "AddonsInstaller", - "Other...", - "For providing a license other than one listed", - ) - self.path_to_addon = path_to_addon - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_license.ui") - ) - self.pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - for short_code, details in LicenseSelector.licenses.items(): - self.dialog.comboBox.addItem(f"{short_code}: {details[0]}", userData=short_code) - self.dialog.comboBox.addItem(self.other_label) - self.dialog.otherLineEdit.hide() - self.dialog.otherLabel.hide() - - # Connections: - self.dialog.comboBox.currentIndexChanged.connect(self._selection_changed) - self.dialog.aboutButton.clicked.connect(self._about_clicked) - self.dialog.browseButton.clicked.connect(self._browse_clicked) - self.dialog.createButton.clicked.connect(self._create_clicked) - - # Set up the first selection to whatever the user chose last time - short_code = self.pref.GetString("devModeLastSelectedLicense", "LGPL-2.1-or-later") - self.set_license(short_code) - - def exec(self, short_code: str = None, license_path: str = "") -> Optional[Tuple[str, str]]: - """The main method for executing this dialog, as a modal that returns a tuple of the - license's "short code" and optionally the path to the license file. Returns a tuple - of None,None if the user cancels the operation.""" - - if short_code: - self.set_license(short_code) - self.dialog.pathLineEdit.setText(license_path) - result = self.dialog.exec() - if result == QDialog.Accepted: - new_short_code = self.dialog.comboBox.currentData() - new_license_path = self.dialog.pathLineEdit.text() - if not new_short_code: - new_short_code = self.dialog.otherLineEdit.text() - self.pref.SetString("devModeLastSelectedLicense", new_short_code) - return new_short_code, new_license_path - return None - - def set_license(self, short_code): - """Set the currently-selected license.""" - index = self.dialog.comboBox.findData(short_code) - if index != -1: - self.dialog.comboBox.setCurrentIndex(index) - else: - self.dialog.comboBox.setCurrentText(self.other_label) - self.dialog.otherLineEdit.setText(short_code) - - def _selection_changed(self, _: int): - """Callback: when the license selection changes, the UI is updated here.""" - if self.dialog.comboBox.currentText() == self.other_label: - self.dialog.otherLineEdit.clear() - self.dialog.otherLineEdit.show() - self.dialog.otherLabel.show() - self.dialog.aboutButton.setDisabled(True) - else: - self.dialog.otherLineEdit.hide() - self.dialog.otherLabel.hide() - self.dialog.aboutButton.setDisabled(False) - - def _current_short_code(self) -> str: - """Gets the currently-selected license short code""" - short_code = self.dialog.comboBox.currentData() - if not short_code: - short_code = self.dialog.otherLineEdit.text() - return short_code - - def _about_clicked(self): - """Callback: when the About button is clicked, try to launch a system-default web browser - and display the OSI page about the currently-selected license.""" - short_code = self.dialog.comboBox.currentData() - if short_code in LicenseSelector.licenses: - url = LicenseSelector.licenses[short_code][1] - QDesktopServices.openUrl(QUrl(url)) - else: - FreeCAD.Console.PrintWarning( - f"Internal Error: unrecognized license short code {short_code}\n" - ) - - def _browse_clicked(self): - """Callback: browse for an existing license file.""" - start_dir = os.path.join( - self.path_to_addon, - self.dialog.pathLineEdit.text().replace("/", os.path.sep), - ) - license_path, _ = QFileDialog.getOpenFileName( - parent=self.dialog, - caption=translate( - "AddonsInstaller", - "Select the corresponding license file in your Addon", - ), - dir=start_dir, - ) - if license_path: - self._set_path(self.path_to_addon, license_path) - - def _set_path(self, start_dir: str, license_path: str): - """Sets the value displayed in the path widget to the relative path from - start_dir to license_path""" - license_path = license_path.replace("/", os.path.sep) - base_dir = start_dir.replace("/", os.path.sep) - if base_dir[-1] != os.path.sep: - base_dir += os.path.sep - if not license_path.startswith(base_dir): - FreeCAD.Console.PrintError("Selected file not in Addon\n") - # Eventually offer to copy it? - return - relative_path = license_path[len(base_dir) :] - relative_path = relative_path.replace(os.path.sep, "/") - self.dialog.pathLineEdit.setText(relative_path) - - def _create_clicked(self): - """Asks the users for the path to save the new license file to, then copies our internal - copy of the license text to that file.""" - start_dir = os.path.join( - self.path_to_addon, - self.dialog.pathLineEdit.text().replace("/", os.path.sep), - ) - license_path, _ = QFileDialog.getSaveFileName( - parent=self.dialog, - caption=translate( - "AddonsInstaller", - "Location for new license file", - ), - dir=os.path.join(start_dir, "LICENSE"), - ) - if license_path: - self._set_path(start_dir, license_path) - short_code = self._current_short_code() - qf = QFile(f":/licenses/{short_code}.txt") - if qf.exists(): - qf.open(QIODevice.ReadOnly) - byte_data = qf.readAll() - qf.close() - - string_data = str(byte_data, encoding="utf-8") - - if "<%%YEAR%%>" in string_data or "<%%COPYRIGHT HOLDER%%>" in string_data: - info_dlg = FreeCADGui.PySideUic.loadUi( - os.path.join( - os.path.dirname(__file__), - "developer_mode_copyright_info.ui", - ) - ) - info_dlg.yearLineEdit.setValidator( - RegexValidatorWrapper(RegexWrapper("^[12]\\d{3}$")) - ) - info_dlg.yearLineEdit.setText(str(date.today().year)) - result = info_dlg.exec() - if result != QDialog.Accepted: - return # Don't create the file, just bail out - - holder = info_dlg.copyrightHolderLineEdit.text() - year = info_dlg.yearLineEdit.text() - - string_data = string_data.replace("<%%YEAR%%>", year) - string_data = string_data.replace("<%%COPYRIGHT HOLDER%%>", holder) - - with open(license_path, "w", encoding="utf-8") as f: - f.write(string_data) - else: - FreeCAD.Console.PrintError(f"Cannot create license file of type {short_code}\n") diff --git a/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py b/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py deleted file mode 100644 index 26e29c434c..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py +++ /dev/null @@ -1,129 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains a wrapper class for a table listing authors and maintainers""" - -import os - -from PySide.QtWidgets import QTableWidgetItem -from PySide.QtGui import QIcon - -import FreeCAD -import FreeCADGui - -from addonmanager_devmode_license_selector import LicenseSelector - -translate = FreeCAD.Qt.translate - -# pylint: disable=too-few-public-methods - - -class LicensesTable: - """A QTableWidget and associated buttons for managing the list of authors and maintainers.""" - - def __init__(self): - self.widget = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_licenses_table.ui") - ) - - self.widget.addButton.setIcon(QIcon.fromTheme("add", QIcon(":/icons/list-add.svg"))) - self.widget.removeButton.setIcon( - QIcon.fromTheme("remove", QIcon(":/icons/list-remove.svg")) - ) - - self.widget.addButton.clicked.connect(self._add_clicked) - self.widget.removeButton.clicked.connect(self._remove_clicked) - self.widget.tableWidget.itemSelectionChanged.connect(self._selection_changed) - self.widget.tableWidget.itemDoubleClicked.connect(self._edit) - self.metadata = None - self.path_to_addon = "" - - def show(self, metadata, path_to_addon): - """Set up the widget based on incoming metadata""" - self.metadata = metadata - self.path_to_addon = path_to_addon - self._populate_from_metadata() - self.widget.removeButton.setDisabled(True) - self.widget.show() - - def _populate_from_metadata(self): - """Use the passed metadata object to populate the maintainers and authors""" - self.widget.tableWidget.setRowCount(0) - row = 0 - for lic in self.metadata.License: - shortcode = lic["name"] - path = lic["file"] - self._add_row(row, shortcode, path) - row += 1 - - def _add_row(self, row, shortcode, path): - """Add this license to the tableWidget at row given""" - self.widget.tableWidget.insertRow(row) - self.widget.tableWidget.setItem(row, 0, QTableWidgetItem(shortcode)) - self.widget.tableWidget.setItem(row, 1, QTableWidgetItem(path)) - - def _add_clicked(self): - """Callback: the Add License button was clicked""" - dlg = LicenseSelector(self.path_to_addon) - shortcode, path = dlg.exec() - if shortcode and path: - self._add_row(self.widget.tableWidget.rowCount(), shortcode, path) - self.metadata.addLicense(shortcode, path) - - def _remove_clicked(self): - """Callback: the Remove License button was clicked""" - items = self.widget.tableWidget.selectedIndexes() - if items: - # We only support single-selection, so can just pull the row # from - # the first entry - row = items[0].row() - shortcode = self.widget.tableWidget.item(row, 0).text() - path = self.widget.tableWidget.item(row, 1).text() - self.widget.tableWidget.removeRow(row) - self.metadata.removeLicense(shortcode, path) - - def _edit(self, item): - """Callback: a row in the tableWidget was double-clicked""" - row = item.row() - shortcode = self.widget.tableWidget.item(row, 0).text() - path = self.widget.tableWidget.item(row, 1).text() - - dlg = LicenseSelector(self.path_to_addon) - new_shortcode, new_path = dlg.exec(shortcode, path) - - if new_shortcode and new_path: - self.widget.tableWidget.removeRow(row) - self.metadata.removeLicense(new_shortcode, new_path) - - self._add_row(row, new_shortcode, new_path) - self.metadata.addLicense(new_shortcode, new_path) - - self.widget.tableWidget.selectRow(row) - - def _selection_changed(self): - """Callback: the current selection in the tableWidget changed""" - items = self.widget.tableWidget.selectedItems() - if items: - self.widget.removeButton.setDisabled(False) - else: - self.widget.removeButton.setDisabled(True) diff --git a/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py b/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py deleted file mode 100644 index efae4ab928..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py +++ /dev/null @@ -1,184 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Metadata validation functions""" - -from typing import List - -import FreeCAD - -from Addon import Addon -from addonmanager_metadata import Metadata -import NetworkManager - - -class MetadataValidators: - """A collection of tools for validating various pieces of metadata. Prints - validation information to the console.""" - - def validate_all(self, repos): - """Developer tool: check all repos for validity and print report""" - - FreeCAD.Console.PrintMessage("\n\nADDON MANAGER DEVELOPER MODE CHECKS\n") - FreeCAD.Console.PrintMessage("-----------------------------------\n") - - counter = 0 - for addon in repos: - counter += 1 - if addon.metadata is not None: - self.validate_package_xml(addon) - elif addon.repo_type == Addon.Kind.MACRO: - if addon.macro.parsed: - if len(addon.macro.icon) == 0 and len(addon.macro.xpm) == 0: - FreeCAD.Console.PrintMessage( - f"Macro '{addon.name}' does not have an icon\n" - ) - else: - FreeCAD.Console.PrintMessage( - f"Addon '{addon.name}' does not have a package.xml file\n" - ) - - FreeCAD.Console.PrintMessage("-----------------------------------\n\n") - - def validate_package_xml(self, addon: Addon): - """Check the package.xml file for the specified Addon""" - if addon.metadata is None: - return - - # The package.xml standard has some required elements that the basic XML - # reader is not actually checking for. In developer mode, actually make sure - # that all the rules are being followed for each element. - - errors = [] - - errors.extend(self.validate_top_level(addon)) - errors.extend(self.validate_content(addon)) - - if len(errors) > 0: - FreeCAD.Console.PrintError(f"Errors found in package.xml file for '{addon.name}'\n") - for error in errors: - FreeCAD.Console.PrintError(f" * {error}\n") - - def validate_content(self, addon: Addon) -> List[str]: - """Validate the Content items for this Addon""" - errors = [] - contents = addon.metadata.content - - missing_icon = True - if addon.metadata.icon and len(addon.metadata.icon) > 0: - missing_icon = False - else: - if "workbench" in contents: - wb = contents["workbench"][0] - if wb.icon: - missing_icon = False - if missing_icon: - errors.append("No element found, or element is invalid") - - if "workbench" in contents: - for wb in contents["workbench"]: - errors.extend(self.validate_workbench_metadata(wb)) - - if "preferencepack" in contents: - for wb in contents["preferencepack"]: - errors.extend(self.validate_preference_pack_metadata(wb)) - - return errors - - def validate_top_level(self, addon: Addon) -> List[str]: - """Check for the presence of the required top-level elements""" - errors = [] - if not addon.metadata.name or len(addon.metadata.name) == 0: - errors.append("No top-level element found, or element is empty") - if not addon.metadata.version: - errors.append("No top-level element found, or element is invalid") - if not addon.metadata.description or len(addon.metadata.description) == 0: - errors.append( - "No top-level element found, or element " "is invalid" - ) - - maintainers = addon.metadata.maintainer - if len(maintainers) == 0: - errors.append("No top-level found, at least one is required") - for maintainer in maintainers: - if len(maintainer.email) == 0: - errors.append(f"No email address specified for maintainer '{maintainer.name}'") - - licenses = addon.metadata.license - if len(licenses) == 0: - errors.append("No top-level found, at least one is required") - - urls = addon.metadata.url - errors.extend(self.validate_urls(urls)) - return errors - - @staticmethod - def validate_urls(urls) -> List[str]: - """Check the URLs provided by the addon""" - errors = [] - if len(urls) == 0: - errors.append("No elements found, at least a repo url must be provided") - else: - found_repo = False - found_readme = False - for url in urls: - if url.type == "repository": - found_repo = True - if len(url.branch) == 0: - errors.append(" element is missing the 'branch' attribute") - elif url.type == "readme": - found_readme = True - location = url.location - p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(location) - if not p: - errors.append(f"Could not access specified readme at {location}") - else: - p = p.data().decode("utf8") - if "" in p: - pass - else: - errors.append( - f"Readme data found at {location}" - " does not appear to be rendered HTML" - ) - if not found_repo: - errors.append("No repo url specified") - if not found_readme: - errors.append("No readme url specified (not required, but highly recommended)") - return errors - - @staticmethod - def validate_workbench_metadata(workbench: Metadata) -> List[str]: - """Validate the required element(s) for a workbench""" - errors = [] - if not workbench.classname or len(workbench.classname) == 0: - errors.append("No specified for workbench") - return errors - - @staticmethod - def validate_preference_pack_metadata(pack: Metadata) -> List[str]: - """Validate the required element(s) for a preference pack""" - errors = [] - if not pack.name or len(pack.name) == 0: - errors.append("No specified for preference pack") - return errors diff --git a/src/Mod/AddonManager/addonmanager_devmode_people_table.py b/src/Mod/AddonManager/addonmanager_devmode_people_table.py deleted file mode 100644 index 048100bff4..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_people_table.py +++ /dev/null @@ -1,153 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains a wrapper class for a table listing authors and maintainers""" - -import os - -from PySide.QtWidgets import QTableWidgetItem -from PySide.QtGui import QIcon -from PySide.QtCore import Qt - -import FreeCAD -import FreeCADGui - -from addonmanager_devmode_person_editor import PersonEditor - -translate = FreeCAD.Qt.translate - -# pylint: disable=too-few-public-methods - - -class PeopleTable: - """A QTableWidget and associated buttons for managing the list of authors and maintainers.""" - - def __init__(self): - self.widget = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_people_table.ui") - ) - - self.widget.addButton.setIcon(QIcon.fromTheme("add", QIcon(":/icons/list-add.svg"))) - self.widget.removeButton.setIcon( - QIcon.fromTheme("remove", QIcon(":/icons/list-remove.svg")) - ) - - self.widget.addButton.clicked.connect(self._add_clicked) - self.widget.removeButton.clicked.connect(self._remove_clicked) - self.widget.tableWidget.itemSelectionChanged.connect(self._selection_changed) - self.widget.tableWidget.itemDoubleClicked.connect(self._edit) - self.metadata = None - - def show(self, metadata): - """Set up the widget based on incoming metadata""" - self.metadata = metadata - self._populate_from_metadata() - self.widget.removeButton.setDisabled(True) - self.widget.show() - - def _populate_from_metadata(self): - """Use the passed metadata object to populate the maintainers and authors""" - self.widget.tableWidget.setRowCount(0) - row = 0 - for maintainer in self.metadata.Maintainer: - name = maintainer["name"] - email = maintainer["email"] - self._add_row(row, "maintainer", name, email) - row += 1 - for author in self.metadata.Author: - name = author["name"] - email = author["email"] - self._add_row(row, "author", name, email) - row += 1 - - def _add_row(self, row, person_type, name, email): - """Add this person to the tableWidget at row given""" - person_type_translation = { - "maintainer": translate("AddonsInstaller", "Maintainer"), - "author": translate("AddonsInstaller", "Author"), - } - self.widget.tableWidget.insertRow(row) - item = QTableWidgetItem(person_type_translation[person_type]) - item.setData(Qt.UserRole, person_type) - self.widget.tableWidget.setItem(row, 0, item) - self.widget.tableWidget.setItem(row, 1, QTableWidgetItem(name)) - self.widget.tableWidget.setItem(row, 2, QTableWidgetItem(email)) - - def _add_clicked(self): - """Callback: the Add Person button was clicked""" - dlg = PersonEditor() - person_type, name, email = dlg.exec() - if person_type and name: - self._add_row(self.widget.tableWidget.rowCount(), person_type, name, email) - if person_type == "maintainer": - self.metadata.addMaintainer(name, email) - else: - self.metadata.addAuthor(name, email) - - def _remove_clicked(self): - """Callback: the Remove Person button was clicked""" - items = self.widget.tableWidget.selectedIndexes() - if items: - # We only support single-selection, so can just pull the row # from - # the first entry - row = items[0].row() - person_type = self.widget.tableWidget.item(row, 0).data(Qt.UserRole) - name = self.widget.tableWidget.item(row, 1).text() - email = self.widget.tableWidget.item(row, 2).text() - self.widget.tableWidget.removeRow(row) - if person_type == "maintainer": - self.metadata.removeMaintainer(name, email) - else: - self.metadata.removeAuthor(name, email) - - def _edit(self, item): - """Callback: a row in the tableWidget was double-clicked""" - row = item.row() - person_type = self.widget.tableWidget.item(row, 0).data(Qt.UserRole) - name = self.widget.tableWidget.item(row, 1).text() - email = self.widget.tableWidget.item(row, 2).text() - - dlg = PersonEditor() - dlg.setup(person_type, name, email) - new_person_type, new_name, new_email = dlg.exec() - - if new_person_type and new_name: - self.widget.tableWidget.removeRow(row) - if person_type == "maintainer": - self.metadata.removeMaintainer(name, email) - else: - self.metadata.removeAuthor(name, email) - self._add_row(row, new_person_type, new_name, email) - if new_person_type == "maintainer": - self.metadata.addMaintainer(new_name, new_email) - else: - self.metadata.addAuthor(new_name, new_email) - self.widget.tableWidget.selectRow(row) - - def _selection_changed(self): - """Callback: the current selection in the tableWidget changed""" - items = self.widget.tableWidget.selectedItems() - if items: - self.widget.removeButton.setDisabled(False) - else: - self.widget.removeButton.setDisabled(True) diff --git a/src/Mod/AddonManager/addonmanager_devmode_person_editor.py b/src/Mod/AddonManager/addonmanager_devmode_person_editor.py deleted file mode 100644 index 12f5d2a31a..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_person_editor.py +++ /dev/null @@ -1,72 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains a class to handle editing a person (from a Metadata standpoint).""" - -import os -from typing import Tuple # Needed until Py 3.9, when tuple supports this directly - -from PySide.QtWidgets import QDialog - -import FreeCAD -import FreeCADGui - -translate = FreeCAD.Qt.translate - - -class PersonEditor: - """Create or edit a maintainer or author record.""" - - def __init__(self): - - self.dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "developer_mode_people.ui") - ) - self.dialog.comboBox.clear() - self.dialog.comboBox.addItem( - translate("AddonsInstaller", "Maintainer"), userData="maintainer" - ) - self.dialog.comboBox.addItem(translate("AddonsInstaller", "Author"), userData="author") - - def exec(self) -> Tuple[str, str, str]: - """Run the dialog, and return a tuple of the person's record type, their name, and their - email address. Email may be None. If the others are None it's because the user cancelled - the interaction.""" - result = self.dialog.exec() - if result == QDialog.Accepted: - return ( - self.dialog.comboBox.currentData(), - self.dialog.nameLineEdit.text(), - self.dialog.emailLineEdit.text(), - ) - return "", "", "" - - def setup(self, person_type: str = "maintainer", name: str = "", email: str = "") -> None: - """Configure the dialog""" - index = self.dialog.comboBox.findData(person_type) - if index == -1: - FreeCAD.Console.PrintWarning(f"Internal Error: unrecognized person type {person_type}") - index = 0 - self.dialog.comboBox.setCurrentIndex(index) - self.dialog.nameLineEdit.setText(name) - self.dialog.emailLineEdit.setText(email) diff --git a/src/Mod/AddonManager/addonmanager_devmode_predictor.py b/src/Mod/AddonManager/addonmanager_devmode_predictor.py deleted file mode 100644 index 012e0eb6c5..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_predictor.py +++ /dev/null @@ -1,286 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Class to guess metadata based on folder contents. Note that one of the functions -of this file is to guess the license being applied to the new software package based -in its contents. It is up to the user to make the final determination about whether -the selected license is the correct one, and inclusion here shouldn't be construed as -endorsement of any particular license. In addition, the inclusion of those text strings -does not imply a modification to the license for THIS software, which is licensed -under the LGPLv2.1 license (as stated above).""" - -import datetime -import os - -import FreeCAD -from addonmanager_git import initialize_git, GitManager -from addonmanager_utilities import get_readme_url - -translate = FreeCAD.Qt.translate - -# pylint: disable=too-few-public-methods - - -class AddonSlice: - """A tiny class to implement duck-typing for the URL-parsing utility functions""" - - def __init__(self, url, branch): - self.url = url - self.branch = branch - - -class Predictor: - """Guess the appropriate metadata to apply to a project based on various parameters - found in the supplied directory.""" - - def __init__(self): - self.path = None - self.metadata = FreeCAD.Metadata() - self.license_data = None - self.readme_data = None - self.license_file = "" - self.git_manager: GitManager = initialize_git() - if not self.git_manager: - raise Exception("Cannot use Developer Mode without git installed") - - def predict_metadata(self, path: str) -> FreeCAD.Metadata: - """Create a predicted Metadata object based on the contents of the passed-in directory""" - if not os.path.isdir(path): - return None - self.path = path - self._predict_author_info() - self._predict_name() - self._predict_description() - self._predict_contents() - self._predict_icon() - self._predict_urls() - self._predict_license() - self._predict_version() - - return self.metadata - - def _predict_author_info(self): - """Look at the git commit history and attempt to discern maintainer and author - information.""" - - committers = self.git_manager.get_last_committers(self.path) - - # This is a dictionary keyed to the author's name (which can be many - # things, depending on the author) containing two fields, "email" and "count". It - # is common for there to be multiple entries representing the same human being, - # so a passing attempt is made to reconcile: - filtered_committers = {} - for key, committer in committers.items(): - if "github" in key.lower(): - # Robotic merge commit (or other similar), ignore - continue - # Does any other committer share any of these emails? - for other_key, other_committer in committers.items(): - if other_key == key: - continue - for other_email in other_committer["email"]: - if other_email in committer["email"]: - # There is overlap in the two email lists, so this is probably the - # same author, with a different name (username, pseudonym, etc.) - if not committer["aka"]: - committer["aka"] = set() - committer["aka"].add(other_key) - committer["count"] += other_committer["count"] - committer["email"].combine(other_committer["email"]) - committers.pop(other_key) - break - filtered_committers[key] = committer - maintainers = [] - for name, info in filtered_committers.items(): - if "aka" in info: - for other_name in info["aka"]: - # Heuristic: the longer name is more likely to be the actual legal name - if len(other_name) > len(name): - name = other_name - # There is no logical basis to choose one email address over another, so just - # take the first one - email = info["email"][0] - commit_count = info["count"] - maintainers.append({"name": name, "email": email, "count": commit_count}) - - # Sort by count of commits - maintainers.sort(key=lambda i: i["count"], reverse=True) - - self.metadata.Maintainer = maintainers - - def _predict_name(self): - """Predict the name based on the local path name and/or the contents of a - README.md file.""" - - normed_path = self.path.replace(os.path.sep, "/") - path_components = normed_path.split("/") - final_path_component = path_components[-1] - predicted_name = final_path_component.replace("/", "") - self.metadata.Name = predicted_name - - def _predict_description(self): - """Predict the description based on the contents of a README.md file.""" - self._load_readme() - - if not self.readme_data: - return - - lines = self.readme_data.split("\n") - description = "" - for line in lines: - if "#" in line: - continue # Probably not a line of description - if "![" in line: - continue # An image link, probably separate from any description - if not line and description: - break # We're done: this is a blank line, and we've read some data already - if description: - description += " " - description += line - - if description: - self.metadata.Description = description - - def _predict_contents(self): - """Predict the contents based on the contents of the directory.""" - - def _predict_icon(self): - """Predict the icon based on either a class which defines an Icon member, or - the contents of the local directory structure.""" - - def _predict_urls(self): - """Predict the URLs based on git settings""" - - branch = self.git_manager.current_branch(self.path) - remote = self.git_manager.get_remote(self.path) - - addon = AddonSlice(remote, branch) - readme = get_readme_url(addon) - - self.metadata.addUrl("repository", remote, branch) - self.metadata.addUrl("readme", readme) - - def _predict_license(self): - """Predict the license based on any existing license file.""" - - # These are processed in order, so the BSD 3 clause must come before the 2, for example, - # because the only difference between them is the additional clause. - known_strings = { - "Apache-2.0": ( - "Apache License, Version 2.0", - "Apache License\nVersion 2.0, January 2004", - ), - "BSD-3-Clause": ( - "The 3-Clause BSD License", - "3. Neither the name of the copyright holder nor the names of its contributors \ - may be used to endorse or promote products derived from this software without \ - specific prior written permission.", - ), - "BSD-2-Clause": ( - "The 2-Clause BSD License", - "2. Redistributions in binary form must reproduce the above copyright notice, \ - this list of conditions and the following disclaimer in the documentation and/or \ - other materials provided with the distribution.", - ), - "CC0v1": ( - "CC0 1.0 Universal", - "voluntarily elects to apply CC0 to the Work and publicly distribute the Work \ - under its terms", - ), - "GPLv2": ( - "GNU General Public License version 2", - "GNU GENERAL PUBLIC LICENSE\nVersion 2, June 1991", - ), - "GPLv3": ( - "GNU General Public License version 3", - "The GNU General Public License is a free, copyleft license for software and \ - other kinds of works.", - ), - "LGPLv2.1": ( - "GNU Lesser General Public License version 2.1", - "GNU Lesser General Public License\nVersion 2.1, February 1999", - ), - "LGPLv3": ( - "GNU Lesser General Public License version 3", - "GNU LESSER GENERAL PUBLIC LICENSE\nVersion 3, 29 June 2007", - ), - "MIT": ( - "The MIT License", - "including without limitation the rights to use, copy, modify, merge, publish, \ - distribute, sublicense, and/or sell copies of the Software", - ), - "MPL-2.0": ( - "Mozilla Public License 2.0", - "https://opensource.org/licenses/MPL-2.0", - ), - } - self._load_license() - if self.license_data: - for shortcode, test_data in known_strings.items(): - if shortcode.lower() in self.license_data.lower(): - self.metadata.addLicense(shortcode, self.license_file) - return - for test_text in test_data: - # Do the comparison without regard to whitespace or capitalization - if ( - "".join(test_text.split()).lower() - in "".join(self.license_data.split()).lower() - ): - self.metadata.addLicense(shortcode, self.license_file) - return - - def _predict_version(self): - """Default to a CalVer style set to today's date""" - year = datetime.date.today().year - month = datetime.date.today().month - day = datetime.date.today().day - version_string = f"{year}.{month:>02}.{day:>02}" - self.metadata.Version = version_string - - def _load_readme(self): - """Load in any existing readme""" - valid_names = ["README.md", "README.txt", "README"] - for name in valid_names: - full_path = os.path.join(self.path, name) - if os.path.exists(full_path): - with open(full_path, encoding="utf-8") as f: - self.readme_data = f.read() - return - - def _load_license(self): - """Load in any existing license""" - valid_names = [ - "LICENSE", - "LICENCE", - "COPYING", - "LICENSE.txt", - "LICENCE.txt", - "COPYING.txt", - ] - for name in valid_names: - full_path = os.path.join(self.path.replace("/", os.path.sep), name) - if os.path.isfile(full_path): - with open(full_path, encoding="utf-8") as f: - self.license_data = f.read() - self.license_file = name - return diff --git a/src/Mod/AddonManager/addonmanager_devmode_validators.py b/src/Mod/AddonManager/addonmanager_devmode_validators.py deleted file mode 100644 index c4c7e71fda..0000000000 --- a/src/Mod/AddonManager/addonmanager_devmode_validators.py +++ /dev/null @@ -1,166 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Validators used for various line edits""" - -import keyword - -from PySide.QtGui import ( - QValidator, -) - -# QRegularExpressionValidator was only added at the very end of the PySide -# development cycle, so make sure to support the older QRegExp version as well. -try: - from PySide.QtGui import ( - QRegularExpressionValidator, - ) - from PySide.QtCore import QRegularExpression - - RegexWrapper = QRegularExpression - RegexValidatorWrapper = QRegularExpressionValidator -except ImportError: - QRegularExpressionValidator = None - QRegularExpression = None - from PySide.QtGui import ( - QRegExpValidator, - ) - from PySide.QtCore import QRegExp - - RegexWrapper = QRegExp - RegexValidatorWrapper = QRegExpValidator - - -# pylint: disable=too-few-public-methods - - -class NameValidator(QValidator): - """Simple validator to exclude characters that are not valid in filenames.""" - - invalid = '/\\?%*:|"<>' - - def validate(self, value: str, _: int): - """Check the value against the validator""" - for char in value: - if char in NameValidator.invalid: - return QValidator.Invalid - return QValidator.Acceptable - - def fixup(self, value: str) -> str: - """Remove invalid characters from value""" - result = "" - for char in value: - if char not in NameValidator.invalid: - result += char - return result - - -class PythonIdentifierValidator(QValidator): - """Validates whether input is a valid Python identifier.""" - - def validate(self, value: str, _: int): - """The function that does the validation.""" - if not value: - return QValidator.Intermediate - - if not value.isidentifier(): - return QValidator.Invalid # Includes an illegal character of some sort - - if keyword.iskeyword(value): - return QValidator.Intermediate # They can keep typing and it might become valid - - return QValidator.Acceptable - - -class SemVerValidator(RegexValidatorWrapper): - """Implements the officially-recommended regex validator for Semantic version numbers.""" - - # https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string - semver_re = RegexWrapper( - r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)" - + r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)" - + r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?" - + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" - ) - - def __init__(self): - super().__init__() - if hasattr(self, "setRegularExpression"): - self.setRegularExpression(SemVerValidator.semver_re) - else: - self.setRegExp(SemVerValidator.semver_re) - - @classmethod - def check(cls, value: str) -> bool: - """Returns true if value validates, and false if not""" - return cls.semver_re.match(value).hasMatch() - - -class CalVerValidator(RegexValidatorWrapper): - """Implements a basic regular expression validator that makes sure an entry corresponds - to a CalVer version numbering standard.""" - - calver_re = RegexWrapper( - r"^(?P[1-9]\d{3})\.(?P[0-9]{1,2})\.(?P0|[0-9]{0,2})" - + r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)" - + r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?" - + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" - ) - - def __init__(self): - super().__init__() - if hasattr(self, "setRegularExpression"): - self.setRegularExpression(CalVerValidator.calver_re) - else: - self.setRegExp(CalVerValidator.calver_re) - - @classmethod - def check(cls, value: str) -> bool: - """Returns true if value validates, and false if not""" - return cls.calver_re.match(value).hasMatch() - - -class VersionValidator(QValidator): - """Implements the officially-recommended regex validator for Semantic version numbers, and a - decent approximation of the same thing for CalVer-style version numbers.""" - - def __init__(self): - super().__init__() - self.semver = SemVerValidator() - self.calver = CalVerValidator() - - def validate(self, value: str, position: int): - """Called for validation, returns a tuple of the validation state, the value, and the - position.""" - semver_result = self.semver.validate(value, position) - calver_result = self.calver.validate(value, position) - - if semver_result[0] == QValidator.Acceptable: - return semver_result - if calver_result[0] == QValidator.Acceptable: - return calver_result - if semver_result[0] == QValidator.Intermediate: - return semver_result - if calver_result[0] == QValidator.Intermediate: - return calver_result - return QValidator.Invalid, value, position diff --git a/src/Mod/AddonManager/addonmanager_firstrun.py b/src/Mod/AddonManager/addonmanager_firstrun.py deleted file mode 100644 index 2b8cbeb378..0000000000 --- a/src/Mod/AddonManager/addonmanager_firstrun.py +++ /dev/null @@ -1,66 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Class to display a first-run dialog for the Addon Manager""" - -import os - -from PySide import QtCore, QtWidgets -from PySide.QtGui import QPixmap - -import FreeCAD -import FreeCADGui - -import addonmanager_utilities as utils - -# pylint: disable=too-few-public-methods - - -class FirstRunDialog: - """Manage the display of the Addon Manager's first-run dialog, setting up some user - preferences and making sure they are aware that this connects to the internet, downloads - data, and possibly installs things that run code not affiliated with FreeCAD itself.""" - - def __init__(self): - self.pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - self.readWarning = self.pref.GetBool("readWarning2022", False) - - def exec(self) -> bool: - """Display a first-run dialog if needed, and return True to indicate the Addon Manager - should continue loading, or False if the user cancelled the dialog and wants to exit.""" - if not self.readWarning: - warning_dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "first_run.ui") - ) - - # Set signal handlers for accept/reject buttons - warning_dialog.buttonContinue.clicked.connect(warning_dialog.accept) - warning_dialog.buttonQuit.clicked.connect(warning_dialog.reject) - - # Show the dialog and check whether the user accepted or canceled - if warning_dialog.exec() == QtWidgets.QDialog.Accepted: - # Store warning as read/accepted - self.readWarning = True - self.pref.SetBool("readWarning2022", True) - - return self.readWarning diff --git a/src/Mod/AddonManager/addonmanager_freecad_interface.py b/src/Mod/AddonManager/addonmanager_freecad_interface.py deleted file mode 100644 index 5a087a4efe..0000000000 --- a/src/Mod/AddonManager/addonmanager_freecad_interface.py +++ /dev/null @@ -1,291 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2023 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Classes to encapsulate the Addon Manager's interaction with FreeCAD, and to provide -replacements when the Addon Manager is not run from within FreeCAD (e.g. during unit -testing). - -Usage: -from addonmanager_freecad_interface import Console, DataPaths, Preferences -""" - -import json -import logging -import os -import tempfile - -# pylint: disable=too-few-public-methods - -try: - import FreeCAD - - Console = FreeCAD.Console - ParamGet = FreeCAD.ParamGet - Version = FreeCAD.Version - getUserAppDataDir = FreeCAD.getUserAppDataDir - getUserMacroDir = FreeCAD.getUserMacroDir - getUserCachePath = FreeCAD.getUserCachePath - translate = FreeCAD.Qt.translate - loadUi = None - - if FreeCAD.GuiUp: - import FreeCADGui - - if hasattr(FreeCADGui, "PySideUic"): - loadUi = FreeCADGui.PySideUic.loadUi - else: - FreeCADGui = None - -except ImportError: - FreeCAD = None - FreeCADGui = None - getUserAppDataDir = None - getUserCachePath = None - getUserMacroDir = None - - def translate(_context: str, string: str, _desc: str = "") -> str: - return string - - def Version(): - return 1, 1, 0, "dev" - - class ConsoleReplacement: - """If FreeCAD's Console is not available, create a replacement by redirecting FreeCAD - log calls to Python's built-in logging facility.""" - - @staticmethod - def PrintLog(arg: str) -> None: - logging.log(logging.DEBUG, arg) - - @staticmethod - def PrintMessage(arg: str) -> None: - logging.info(arg) - - @staticmethod - def PrintWarning(arg: str) -> None: - logging.warning(arg) - - @staticmethod - def PrintError(arg: str) -> None: - logging.error(arg) - - Console = ConsoleReplacement() - - class ParametersReplacement: - """Proxy for FreeCAD's Parameters when not running within FreeCAD. NOT - serialized, only exists for the duration of the program's execution. Only - provides the functions used by the Addon Manager, this class is not intended - to be a complete replacement for FreeCAD's preferences system.""" - - parameters = {} - - def GetBool(self, name: str, default: bool) -> bool: - return self._Get(name, default) - - def GetInt(self, name: str, default: int) -> int: - return self._Get(name, default) - - def GetFloat(self, name: str, default: float) -> float: - return self._Get(name, default) - - def GetString(self, name: str, default: str) -> str: - return self._Get(name, default) - - def _Get(self, name, default): - return self.parameters[name] if name in self.parameters else default - - def SetBool(self, name: str, value: bool) -> None: - self.parameters[name] = value - - def SetInt(self, name: str, value: int) -> None: - self.parameters[name] = value - - def SetFloat(self, name: str, value: float) -> None: - self.parameters[name] = value - - def SetString(self, name: str, value: str) -> None: - self.parameters[name] = value - - def RemBool(self, name: str) -> None: - self.parameters.pop(name) - - def RemInt(self, name: str) -> None: - self.parameters.pop(name) - - def RemFloat(self, name: str) -> None: - self.parameters.pop(name) - - def RemString(self, name: str) -> None: - self.parameters.pop(name) - - def ParamGet(_: str): - return ParametersReplacement() - - -class DataPaths: - """Provide access to various data storage paths. If not running within FreeCAD, - all paths are temp directories. If not run within FreeCAD, all directories are - deleted when the last reference to this class is deleted.""" - - data_dir = None - mod_dir = None - macro_dir = None - cache_dir = None - home_dir = None - - reference_count = 0 - - def __init__(self): - if FreeCAD: - if self.data_dir is None: - self.data_dir = getUserAppDataDir() - if self.mod_dir is None: - self.mod_dir = os.path.join(getUserAppDataDir(), "Mod") - if self.cache_dir is None: - self.cache_dir = getUserCachePath() - if self.macro_dir is None: - self.macro_dir = getUserMacroDir(True) - if self.home_dir is None: - self.home_dir = FreeCAD.getHomePath() - else: - self.reference_count += 1 - if self.data_dir is None: - self.data_dir = tempfile.mkdtemp() - if self.mod_dir is None: - self.mod_dir = tempfile.mkdtemp() - if self.cache_dir is None: - self.cache_dir = tempfile.mkdtemp() - if self.macro_dir is None: - self.macro_dir = tempfile.mkdtemp() - if self.home_dir is None: - self.home_dir = os.path.join(os.path.dirname(__file__), "..", "..") - - def __del__(self): - self.reference_count -= 1 - if not FreeCAD and self.reference_count <= 0: - paths = [self.data_dir, self.mod_dir, self.cache_dir, self.macro_dir, self.mod_dir] - for path in paths: - try: - os.rmdir(path) - except FileNotFoundError: - pass - self.data_dir = None - self.mod_dir = None - self.cache_dir = None - self.macro_dir = None - - -class Preferences: - """Wrap access to all user preferences. If run within FreeCAD, user preferences are - persistent, otherwise they only exist per-run. All preferences are controlled by a - central JSON file defining their defaults.""" - - preferences_defaults = {} - - def __init__(self, defaults_data=None): - """Set up the preferences, initializing the class statics if necessary. If - defaults_data is provided it is used as the preferences defaults. If it is not - provided, then the defaults are read in from the standard defaults file, - addonmanager_preferences_defaults.json, located in the same directory as this - Python file.""" - if not self.preferences_defaults: - if defaults_data: - self.preferences_defaults = defaults_data - else: - self._load_preferences_defaults() - self.prefs = ParamGet("User parameter:BaseApp/Preferences/Addons") - - def get(self, name: str): - """Get the preference value for the given key""" - if name not in self.preferences_defaults: - raise RuntimeError( - f"Unrecognized preference {name} -- did you add " - + "it to addonmanager_preferences_defaults.json?" - ) - if isinstance(self.preferences_defaults[name], bool): - return self.prefs.GetBool(name, self.preferences_defaults[name]) - if isinstance(self.preferences_defaults[name], int): - return self.prefs.GetInt(name, self.preferences_defaults[name]) - if isinstance(self.preferences_defaults[name], float): - return self.prefs.GetFloat(name, self.preferences_defaults[name]) - if isinstance(self.preferences_defaults[name], str): - return self.prefs.GetString(name, self.preferences_defaults[name]) - # We don't directly support any other types from the JSON file (e.g. arrays) - type_name = type(self.preferences_defaults[name]) - raise RuntimeError(f"Unrecognized type for {name}: {type_name}") - - def set(self, name: str, value): - """Set the preference value for the given key. Must exist (e.g. must be in the - addonmanager_preferences_defaults.json file).""" - if name not in self.preferences_defaults: - raise RuntimeError( - f"Unrecognized preference {name} -- did you add " - + "it to addonmanager_preferences_defaults.json?" - ) - if isinstance(self.preferences_defaults[name], bool): - self.prefs.SetBool(name, value) - elif isinstance(self.preferences_defaults[name], int): - self.prefs.SetInt(name, value) - elif isinstance(self.preferences_defaults[name], float): - self.prefs.SetFloat(name, value) - elif isinstance(self.preferences_defaults[name], str): - self.prefs.SetString(name, value) - else: - # We don't directly support any other types from the JSON file (e.g. arrays) - type_name = type(self.preferences_defaults[name]) - raise RuntimeError(f"Unrecognized type for {name}: {type_name}") - - def rem(self, name: str): - """Remove the preference. Must have an entry in the - addonmanager_preferences_defaults.json file.""" - if name not in self.preferences_defaults: - raise RuntimeError( - f"Unrecognized preference {name} -- did you add " - + "it to addonmanager_preferences_defaults.json?" - ) - if isinstance(self.preferences_defaults[name], bool): - return self.prefs.RemBool(name) - if isinstance(self.preferences_defaults[name], int): - return self.prefs.RemInt(name) - if isinstance(self.preferences_defaults[name], float): - return self.prefs.RemFloat(name) - if isinstance(self.preferences_defaults[name], str): - return self.prefs.RemString(name) - # We don't directly support any other types from the JSON file (e.g. arrays) - type_name = type(self.preferences_defaults[name]) - raise RuntimeError(f"Unrecognized type for {name}: {type_name}") - - @classmethod - def _load_preferences_defaults(cls, filename=None): - """Loads the preferences defaults JSON file from either a specified file, or - from the standard addonmanager_preferences_defaults.json file.""" - - if filename is None: - json_file = os.path.join( - os.path.dirname(__file__), "addonmanager_preferences_defaults.json" - ) - else: - json_file = filename - with open(json_file, "r", encoding="utf-8") as f: - file_contents = f.read() - cls.preferences_defaults = json.loads(file_contents) diff --git a/src/Mod/AddonManager/addonmanager_git.py b/src/Mod/AddonManager/addonmanager_git.py deleted file mode 100644 index 0cce480db8..0000000000 --- a/src/Mod/AddonManager/addonmanager_git.py +++ /dev/null @@ -1,480 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Wrapper around git executable to simplify calling git commands from Python.""" - -# pylint: disable=too-few-public-methods - -import os -import platform -import shutil -import subprocess -from typing import List, Dict, Optional -import time - -import addonmanager_utilities as utils -import addonmanager_freecad_interface as fci - -translate = fci.translate - - -class NoGitFound(RuntimeError): - """Could not locate the git executable on this system.""" - - -class GitFailed(RuntimeError): - """The call to git returned an error of some kind""" - - -def _ref_format_string() -> str: - return ( - "--format=%(refname:lstrip=2)\t%(upstream:lstrip=2)\t%(authordate:rfc)\t%(" - "authorname)\t%(subject)" - ) - - -def _parse_ref_table(text: str): - rows = text.splitlines() - result = [] - for row in rows: - columns = row.split("\t") - result.append( - { - "ref_name": columns[0], - "upstream": columns[1], - "date": columns[2], - "author": columns[3], - "subject": columns[4], - } - ) - return result - - -class GitManager: - """A class to manage access to git: mostly just provides a simple wrapper around - the basic command-line calls. Provides optional asynchronous access to clone and - update.""" - - def __init__(self): - self.git_exe = None - self._find_git() - if not self.git_exe: - raise NoGitFound() - - def clone(self, remote, local_path, args: List[str] = None): - """Clones the remote to the local path""" - final_args = ["clone", "--recurse-submodules"] - if args: - final_args.extend(args) - final_args.extend([remote, local_path]) - self._synchronous_call_git(final_args) - - def async_clone(self, remote, local_path, progress_monitor, args: List[str] = None): - """Clones the remote to the local path, sending periodic progress updates - to the passed progress_monitor. Returns a handle that can be used to - cancel the job.""" - - def checkout(self, local_path, spec, args: List[str] = None): - """Checks out a specific git revision, tag, or branch. Any valid argument to - git checkout can be submitted.""" - old_dir = os.getcwd() - os.chdir(local_path) - final_args = ["checkout"] - if args: - final_args.extend(args) - final_args.append(spec) - self._synchronous_call_git(final_args) - os.chdir(old_dir) - - def dirty(self, local_path: str) -> bool: - """Check for local changes""" - old_dir = os.getcwd() - os.chdir(local_path) - result = False - final_args = ["diff-index", "HEAD"] - try: - stdout = self._synchronous_call_git(final_args) - if stdout: - result = True - except GitFailed: - result = False - os.chdir(old_dir) - return result - - def detached_head(self, local_path: str) -> bool: - """Check for detached head state""" - old_dir = os.getcwd() - os.chdir(local_path) - result = False - final_args = ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "HEAD"] - try: - stdout = self._synchronous_call_git(final_args) - if stdout == "HEAD": - result = True - except GitFailed: - result = False - os.chdir(old_dir) - return result - - def update(self, local_path): - """Fetches and pulls the local_path from its remote""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - self._synchronous_call_git(["fetch"]) - self._synchronous_call_git(["pull"]) - self._synchronous_call_git(["submodule", "update", "--init", "--recursive"]) - except GitFailed as e: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Basic Git update failed with the following message:", - ) - + str(e) - + "\n" - ) - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Backing up the original directory and re-cloning", - ) - + "...\n" - ) - remote = self.get_remote(local_path) - with open(os.path.join(local_path, "ADDON_DISABLED"), "w", encoding="utf-8") as f: - f.write( - "This is a backup of an addon that failed to update cleanly so " - "was re-cloned. It was disabled by the Addon Manager's git update " - "facility and can be safely deleted if the addon is working " - "properly." - ) - os.chdir("..") - os.rename(local_path, local_path + ".backup" + str(time.time())) - self.clone(remote, local_path) - os.chdir(old_dir) - - def status(self, local_path) -> str: - """Gets the v1 porcelain status""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - status = self._synchronous_call_git(["status", "-sb", "--porcelain"]) - except GitFailed as e: - os.chdir(old_dir) - raise e - - os.chdir(old_dir) - return status - - def reset(self, local_path, args: List[str] = None): - """Executes the git reset command""" - old_dir = os.getcwd() - os.chdir(local_path) - final_args = ["reset"] - if args: - final_args.extend(args) - try: - self._synchronous_call_git(final_args) - except GitFailed as e: - os.chdir(old_dir) - raise e - os.chdir(old_dir) - - def async_fetch_and_update(self, local_path, progress_monitor, args=None): - """Same as fetch_and_update, but asynchronous""" - - def update_available(self, local_path) -> bool: - """Returns True if an update is available from the remote, or false if not""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - self._synchronous_call_git(["fetch"]) - status = self._synchronous_call_git(["status", "-sb", "--porcelain"]) - except GitFailed as e: - os.chdir(old_dir) - raise e - os.chdir(old_dir) - return "behind" in status - - def current_tag(self, local_path) -> str: - """Get the name of the currently checked-out tag if HEAD is detached""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - tag = self._synchronous_call_git(["describe", "--tags"]).strip() - except GitFailed as e: - os.chdir(old_dir) - raise e - os.chdir(old_dir) - return tag - - def current_branch(self, local_path) -> str: - """Get the name of the current branch""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - # This only works with git 2.22 and later (June 2019) - # branch = self._synchronous_call_git(["branch", "--show-current"]).strip() - - # This is more universal (albeit more opaque to the reader): - branch = self._synchronous_call_git(["rev-parse", "--abbrev-ref", "HEAD"]).strip() - except GitFailed as e: - os.chdir(old_dir) - raise e - os.chdir(old_dir) - return branch - - def repair(self, remote, local_path): - """Assumes that local_path is supposed to be a local clone of the given - remote, and ensures that it is. Note that any local changes in local_path - will be destroyed. This is achieved by archiving the old path, cloning an - entirely new copy, and then deleting the old directory.""" - - original_cwd = os.getcwd() - - # Make sure we are not currently in that directory, otherwise on Windows the - # "rename" will fail. To guarantee we aren't in it, change to it, then shift - # up one. - os.chdir(local_path) - os.chdir("..") - backup_path = local_path + ".backup" + str(time.time()) - os.rename(local_path, backup_path) - try: - self.clone(remote, local_path) - except GitFailed as e: - fci.Console.PrintError( - translate("AddonsInstaller", "Failed to clone {} into {} using Git").format( - remote, local_path - ) - ) - os.chdir(original_cwd) - raise e - os.chdir(original_cwd) - shutil.rmtree(backup_path, ignore_errors=True) - - def get_remote(self, local_path) -> str: - """Get the repository that this local path is set to fetch from""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - response = self._synchronous_call_git(["remote", "-v", "show"]) - except GitFailed as e: - os.chdir(old_dir) - raise e - lines = response.split("\n") - result = "(unknown remote)" - for line in lines: - if line.endswith("(fetch)"): - # The line looks like: - # origin https://some/sort/of/path (fetch) - - segments = line.split() - if len(segments) == 3: - result = segments[1] - break - fci.Console.PrintWarning("Error parsing the results from git remote -v show:\n") - fci.Console.PrintWarning(line + "\n") - os.chdir(old_dir) - return result - - def get_branches(self, local_path) -> List[str]: - """Get a list of all available branches (local and remote)""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - stdout = self._synchronous_call_git(["branch", "-a", "--format=%(refname:lstrip=2)"]) - except GitFailed as e: - os.chdir(old_dir) - raise e - os.chdir(old_dir) - branches = [] - for branch in stdout.split("\n"): - branches.append(branch) - return branches - - def get_branches_with_info(self, local_path) -> List[Dict[str, str]]: - """Get a list of branches, where each entry is a dictionary with status information about - the branch.""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - stdout = self._synchronous_call_git(["branch", "-a", _ref_format_string()]) - return _parse_ref_table(stdout) - except GitFailed as e: - os.chdir(old_dir) - raise e - - def get_tags_with_info(self, local_path) -> List[Dict[str, str]]: - """Get a list of branches, where each entry is a dictionary with status information about - the branch.""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - stdout = self._synchronous_call_git(["tag", "-l", _ref_format_string()]) - return _parse_ref_table(stdout) - except GitFailed as e: - os.chdir(old_dir) - raise e - - def get_last_committers(self, local_path, n=10): - """Examine the last n entries of the commit history, and return a list of all - the committers, their email addresses, and how many commits each one is - responsible for. - """ - old_dir = os.getcwd() - os.chdir(local_path) - authors = self._synchronous_call_git(["log", f"-{n}", "--format=%cN"]).split("\n") - emails = self._synchronous_call_git(["log", f"-{n}", "--format=%cE"]).split("\n") - os.chdir(old_dir) - - result_dict = {} - for author, email in zip(authors, emails): - if not author or not email: - continue - if author not in result_dict: - result_dict[author] = {} - result_dict[author]["email"] = [email] - result_dict[author]["count"] = 1 - else: - if email not in result_dict[author]["email"]: - # Same author name, new email address -- treat it as the same - # person with a second email, instead of as a whole new person - result_dict[author]["email"].append(email) - result_dict[author]["count"] += 1 - return result_dict - - def get_last_authors(self, local_path, n=10): - """Examine the last n entries of the commit history, and return a list of all - the authors, their email addresses, and how many commits each one is - responsible for. - """ - old_dir = os.getcwd() - os.chdir(local_path) - authors = self._synchronous_call_git(["log", f"-{n}", "--format=%aN"]) - emails = self._synchronous_call_git(["log", f"-{n}", "--format=%aE"]) - os.chdir(old_dir) - - result_dict = {} - for author, email in zip(authors, emails): - if author not in result_dict: - result_dict[author]["email"] = [email] - result_dict[author]["count"] = 1 - else: - if email not in result_dict[author]["email"]: - # Same author name, new email address -- treat it as the same - # person with a second email, instead of as a whole new person - result_dict[author]["email"].append(email) - result_dict[author]["count"] += 1 - return result_dict - - def migrate_branch(self, local_path: str, old_branch: str, new_branch: str) -> None: - """Rename a branch (used when the remote branch name changed). Assumes that "origin" - exists.""" - old_dir = os.getcwd() - os.chdir(local_path) - try: - self._synchronous_call_git(["branch", "-m", old_branch, new_branch]) - self._synchronous_call_git(["fetch", "origin"]) - self._synchronous_call_git(["branch", "--unset-upstream"]) - self._synchronous_call_git(["branch", f"--set-upstream-to=origin/{new_branch}"]) - self._synchronous_call_git(["pull"]) - except GitFailed as e: - fci.Console.PrintWarning( - translate( - "AddonsInstaller", - "Git branch rename failed with the following message:", - ) - + str(e) - + "\n" - ) - os.chdir(old_dir) - raise e - os.chdir(old_dir) - - def _find_git(self): - # Find git. In preference order - # A) The value of the GitExecutable user preference - # B) The executable located in the same directory as FreeCAD and called "git" - # C) The result of a shutil search for your system's "git" executable - prefs = fci.ParamGet("User parameter:BaseApp/Preferences/Addons") - git_exe = prefs.GetString("GitExecutable", "Not set") - if not git_exe or git_exe == "Not set" or not os.path.exists(git_exe): - fc_dir = fci.DataPaths().home_dir - git_exe = os.path.join(fc_dir, "bin", "git") - if "Windows" in platform.system(): - git_exe += ".exe" - - if platform.system() == "Darwin" and not self._xcode_command_line_tools_are_installed(): - return - - if not git_exe or not os.path.exists(git_exe): - git_exe = shutil.which("git") - - if not git_exe or not os.path.exists(git_exe): - return - - prefs.SetString("GitExecutable", git_exe) - self.git_exe = git_exe - - def _xcode_command_line_tools_are_installed(self) -> bool: - """On Macs, there is *always* an executable called "git", but sometimes it's just a - script that tells the user to install XCode's Command Line tools. So the existence of git - on the Mac actually requires us to check for that installation.""" - try: - subprocess.check_output(["xcode-select", "-p"]) - return True - except subprocess.CalledProcessError: - return False - - def _synchronous_call_git(self, args: List[str]) -> str: - """Calls git and returns its output.""" - final_args = [self.git_exe] - final_args.extend(args) - - try: - proc = utils.run_interruptable_subprocess(final_args) - except subprocess.CalledProcessError as e: - raise GitFailed( - f"Git returned a non-zero exit status: {e.returncode}\n" - + f"Called with: {' '.join(final_args)}\n\n" - + f"Returned stderr:\n{e.stderr}" - ) from e - - return proc.stdout - - -def initialize_git() -> Optional[GitManager]: - """If git is enabled, locate the git executable if necessary and return a new - GitManager object. The executable location is saved in user preferences for reuse, - and git can be disabled by setting the disableGit parameter in the Addons - preference group. Returns None if for any of those reasons we aren't using git.""" - - git_manager = None - pref = fci.ParamGet("User parameter:BaseApp/Preferences/Addons") - disable_git = pref.GetBool("disableGit", False) - if not disable_git: - try: - git_manager = GitManager() - except NoGitFound: - pass - return git_manager diff --git a/src/Mod/AddonManager/addonmanager_installer.py b/src/Mod/AddonManager/addonmanager_installer.py deleted file mode 100644 index 059f0fc0c1..0000000000 --- a/src/Mod/AddonManager/addonmanager_installer.py +++ /dev/null @@ -1,579 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Contains the classes to manage Addon installation: intended as a stable API, safe for external -code to call and to rely upon existing. See classes AddonInstaller and MacroInstaller for details. -""" -import json -from datetime import datetime, timezone -from enum import IntEnum, auto -import os -import shutil -from typing import List, Optional -import tempfile -from urllib.parse import urlparse -import zipfile - -import FreeCAD - -from PySide import QtCore - -from Addon import Addon -import addonmanager_utilities as utils -from addonmanager_metadata import get_branch_from_metadata -from addonmanager_git import initialize_git, GitFailed - -if FreeCAD.GuiUp: - import NetworkManager # Requires an event loop - -translate = FreeCAD.Qt.translate - -# pylint: disable=too-few-public-methods - - -class InstallationMethod(IntEnum): - """For packages installed from a git repository, in most cases it is possible to either use git - or to download a zip archive of the addon. For a local repository, a direct copy may be used - instead. If "ANY" is given, the internal code decides which to use.""" - - GIT = auto() - COPY = auto() - ZIP = auto() - ANY = auto() - - -class AddonInstaller(QtCore.QObject): - """The core, non-GUI installer class. Usually instantiated and moved to its own thread, - otherwise it will block the GUI (if the GUI is running). In all cases in this class, the - generic Python 'object' is intended to be an Addon-like object that provides, at a minimum, - a 'name', 'url', and 'branch' attribute. The Addon manager uses the Addon class for this - purpose, but external code may use any other class that meets those criteria. - - Recommended Usage (when running with the GUI up, so you don't block the GUI thread): - - import functools # With the rest of your imports, for functools.partial - - ... - - addon_to_install = MyAddon() # Some class with name, url, and branch attributes - - self.worker_thread = QtCore.QThread() - self.installer = AddonInstaller(addon_to_install) - self.installer.moveToThread(self.worker_thread) - self.installer.success.connect(self.installation_succeeded) - self.installer.failure.connect(self.installation_failed) - self.installer.finished.connect(self.worker_thread.quit) - self.worker_thread.started.connect(self.installer.run) - self.worker_thread.start() # Returns immediately - - # On success, the connections above result in self.installation_succeeded being called, and - # on failure, self.installation_failed is called. - - - Recommended non-GUI usage (blocks until complete): - - addon_to_install = MyAddon() # Some class with name, url, and branch attributes - installer = AddonInstaller(addon_to_install) - installer.run() - - """ - - # Signal: progress_update - # In GUI mode this signal is emitted periodically during long downloads. The two integers are - # the number of bytes downloaded, and the number of bytes expected, respectively. Note that the - # number of bytes expected might be set to 0 to indicate an unknown download size. - progress_update = QtCore.Signal(int, int) - - # Signals: success and failure - # Emitted when the installation process is complete. The object emitted is the object that the - # installation was requested for (usually of class Addon, but any class that provides a name, - # url, and branch attribute can be used). - success = QtCore.Signal(object) - failure = QtCore.Signal(object, str) - - # Finished: regardless of the outcome, this is emitted when all work that is going to be done - # is done (i.e. whatever thread this is running in can quit). - finished = QtCore.Signal() - - allowed_packages = set() - - def __init__(self, addon: Addon, allow_list: List[str] = None): - """Initialize the installer with an optional list of addons. If provided, then installation - by name is supported, as long as the objects in the list contain a "name" and "url" - property. In most use cases it is expected that addons is a List of Addon objects, but that - is not a requirement. An optional allow_list lets calling code override the allowed Python - packages list with a custom list. It is mostly for unit testing purposes.""" - super().__init__() - self.addon_to_install = addon - - self.git_manager = initialize_git() - - if allow_list is not None: - AddonInstaller.allowed_packages = set(allow_list if allow_list is not None else []) - elif not AddonInstaller.allowed_packages: - AddonInstaller._load_local_allowed_packages_list() - AddonInstaller._update_allowed_packages_list() - - basedir = FreeCAD.getUserAppDataDir() - self.installation_path = os.path.join(basedir, "Mod") - self.macro_installation_path = FreeCAD.getUserMacroDir(True) - self.zip_download_index = None - - def run(self, install_method: InstallationMethod = InstallationMethod.ANY) -> bool: - """Install an addon. Returns True if the addon was installed, or False if not. Emits - either success or failure prior to returning.""" - try: - addon_url = self.addon_to_install.url.replace(os.path.sep, "/") - method_to_use = self._determine_install_method(addon_url, install_method) - success = False - if method_to_use == InstallationMethod.ZIP: - success = self._install_by_zip() - elif method_to_use == InstallationMethod.GIT: - success = self._install_by_git() - elif method_to_use == InstallationMethod.COPY: - success = self._install_by_copy() - if ( - hasattr(self.addon_to_install, "contains_workbench") - and self.addon_to_install.contains_workbench() - ): - self.addon_to_install.enable_workbench() - except utils.ProcessInterrupted: - pass - except Exception as e: - FreeCAD.Console.PrintLog(e + "\n") - success = False - if success: - if ( - hasattr(self.addon_to_install, "contains_workbench") - and self.addon_to_install.contains_workbench() - ): - self.addon_to_install.set_status(Addon.Status.PENDING_RESTART) - else: - self.addon_to_install.set_status(Addon.Status.NO_UPDATE_AVAILABLE) - self.finished.emit() - return success - - @classmethod - def _load_local_allowed_packages_list(cls) -> None: - """Read in the local allow-list, in case the remote one is unavailable.""" - cls.allowed_packages.clear() - allow_file = os.path.join(os.path.dirname(__file__), "ALLOWED_PYTHON_PACKAGES.txt") - if os.path.exists(allow_file): - with open(allow_file, encoding="utf8") as f: - lines = f.readlines() - for line in lines: - if line and len(line) > 0 and line[0] != "#": - cls.allowed_packages.add(line.strip().lower()) - - @classmethod - def _update_allowed_packages_list(cls) -> None: - """Get a new remote copy of the allowed packages list from GitHub.""" - FreeCAD.Console.PrintLog( - "Attempting to fetch remote copy of ALLOWED_PYTHON_PACKAGES.txt...\n" - ) - p = utils.blocking_get( - "https://raw.githubusercontent.com/" - "FreeCAD/FreeCAD-addons/master/ALLOWED_PYTHON_PACKAGES.txt" - ) - if p: - FreeCAD.Console.PrintLog( - "Overriding local ALLOWED_PYTHON_PACKAGES.txt with newer remote version\n" - ) - p = p.decode("utf8") - lines = p.split("\n") - cls.allowed_packages.clear() # Unset the locally-defined list - for line in lines: - if line and len(line) > 0 and line[0] != "#": - cls.allowed_packages.add(line.strip().lower()) - else: - FreeCAD.Console.PrintLog( - "Could not fetch remote ALLOWED_PYTHON_PACKAGES.txt, using local copy\n" - ) - - def _determine_install_method( - self, addon_url: str, install_method: InstallationMethod - ) -> Optional[InstallationMethod]: - """Given a URL and preferred installation method, determine the actual installation method - to use. Will return either None, if installation is not possible for the given url and - method, or a specific concrete method (GIT, ZIP, or COPY) based on the inputs.""" - - # If we don't have access to git, and that is the method selected, return early - if not self.git_manager and install_method == InstallationMethod.GIT: - return None - - parse_result = urlparse(addon_url) - is_git_only = parse_result.scheme in ["git", "ssh", "rsync"] - is_remote = parse_result.scheme in ["http", "https", "git", "ssh", "rsync"] - is_zipfile = parse_result.path.lower().endswith(".zip") - - # Can't use "copy" for a remote URL - if is_remote and install_method == InstallationMethod.COPY: - return None - - if is_git_only: - if ( - install_method in (InstallationMethod.GIT, InstallationMethod.ANY) - ) and self.git_manager: - # If it's a git-only URL, only git can be used for the installation - return InstallationMethod.GIT - # So if it's not a git installation, return None - return None - - if is_zipfile: - if install_method == InstallationMethod.GIT: - # Can't use git on zip files - return None - return InstallationMethod.ZIP # Copy just becomes zip - if not is_remote and install_method == InstallationMethod.ZIP: - return None # Can't use zip on local paths that aren't zip files - - # Whatever scheme was passed in appears to be reasonable, return it - if install_method != InstallationMethod.ANY: - return install_method - - # Prefer to copy, if it's local: - if not is_remote: - return InstallationMethod.COPY - - # Prefer git if we have git - if self.git_manager: - return InstallationMethod.GIT - - # Fall back to ZIP in other cases, though this relies on remote hosts falling - # into one of a few particular patterns - return InstallationMethod.ZIP - - def _install_by_copy(self) -> bool: - """Installs the specified url by copying directly from it into the installation - location. addon_url must be copyable using filesystem operations. Any existing files at - that location are overwritten.""" - addon_url = self.addon_to_install.url - if addon_url.startswith("file://"): - addon_url = addon_url[len("file://") :] # Strip off the file:// part - name = self.addon_to_install.name - shutil.copytree(addon_url, os.path.join(self.installation_path, name), dirs_exist_ok=True) - self._finalize_successful_installation() - return True - - def _can_use_update(self) -> bool: - addon = self.addon_to_install - install_path = os.path.join(self.installation_path, self.addon_to_install.name) - if not os.path.isdir(install_path): - return False - if addon.metadata is None or addon.installed_metadata is None: - return True # We can't check if the branch name changed, but the install path exists - old_branch = get_branch_from_metadata(self.addon_to_install.installed_metadata) - new_branch = get_branch_from_metadata(self.addon_to_install.metadata) - if old_branch != new_branch: - return False # Branch name changed, we have to re-clone - return True # Checkout exists, same branch as last time, update OK - - def _install_by_git(self) -> bool: - """Installs the specified url by using git to clone from it. The URL can be local or remote, - but must represent a git repository, and the url must be in a format that git can handle - (git, ssh, rsync, file, or a bare filesystem path).""" - install_path = os.path.join(self.installation_path, self.addon_to_install.name) - try: - if self._can_use_update(): - self.git_manager.update(install_path) - else: - if os.path.isdir(install_path): - utils.rmdir(install_path) - self.git_manager.clone(self.addon_to_install.url, install_path) - self.git_manager.checkout(install_path, self.addon_to_install.branch) - except GitFailed as e: - self.failure.emit(self.addon_to_install, str(e)) - return False - self._finalize_successful_installation() - return True - - def _install_by_zip(self) -> bool: - """Installs the specified url by downloading the file (if it is remote) and unzipping it - into the appropriate installation location. If the GUI is running the download is - asynchronous, and issues periodic updates about how much data has been downloaded.""" - if self.addon_to_install.url.endswith(".zip"): - zip_url = self.addon_to_install.url - else: - zip_url = utils.get_zip_url(self.addon_to_install) - - FreeCAD.Console.PrintLog(f"Downloading ZIP file from {zip_url}...\n") - parse_result = urlparse(zip_url) - is_remote = parse_result.scheme in ["http", "https"] - - if is_remote: - if FreeCAD.GuiUp: - self._run_zip_downloader_in_event_loop(zip_url) - else: - zip_data = utils.blocking_get(zip_url) - with tempfile.NamedTemporaryFile(delete=False) as f: - tempfile_name = f.name - f.write(zip_data) - self._finalize_zip_installation(tempfile_name) - else: - self._finalize_zip_installation(zip_url) - return True - - def _run_zip_downloader_in_event_loop(self, zip_url: str): - """Runs the zip downloader in a private event loop. This function does not exit until the - ZIP download is complete. It requires the GUI to be up, and should not be run on the main - GUI thread.""" - NetworkManager.AM_NETWORK_MANAGER.progress_made.connect(self._update_zip_status) - NetworkManager.AM_NETWORK_MANAGER.progress_complete.connect(self._finish_zip) - self.zip_download_index = NetworkManager.AM_NETWORK_MANAGER.submit_monitored_get(zip_url) - while self.zip_download_index is not None: - if QtCore.QThread.currentThread().isInterruptionRequested(): - break - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) - - def _update_zip_status(self, index: int, bytes_read: int, data_size: int): - """Called periodically when downloading a zip file, emits a signal to display the - download progress.""" - if index == self.zip_download_index: - self.progress_update.emit(bytes_read, data_size) - - def _finish_zip(self, index: int, response_code: int, filename: os.PathLike): - """Once the zip download is finished, unzip it into the correct location. Only called if - the GUI is up, and the NetworkManager was responsible for the download. Do not call - directly.""" - if index != self.zip_download_index: - return - self.zip_download_index = None - if response_code != 200: - self.failure.emit( - self.addon_to_install, - translate("AddonsInstaller", "Received {} response code from server").format( - response_code - ), - ) - return - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - - FreeCAD.Console.PrintLog("ZIP download complete. Installing...\n") - self._finalize_zip_installation(filename) - - def _finalize_zip_installation(self, filename: os.PathLike): - """Given a path to a zipfile, extract that file and put its contents in the correct - location. Has special handling for GitHub's zip structure, which places the data in a - subdirectory of the main directory.""" - - destination = os.path.join(self.installation_path, self.addon_to_install.name) - if os.path.exists(destination): - remove_succeeded = utils.rmdir(destination) - if not remove_succeeded: - FreeCAD.Console.PrintError(f"Failed to remove {destination}, aborting update") - raise RuntimeError(f"Failed to remove outdated Addon from {destination}") - - with zipfile.ZipFile(filename, "r") as zfile: - zfile.extractall(destination) - - # GitHub (and possibly other hosts) put all files in the zip into a subdirectory named - # after the branch. If that is the setup that we just extracted, move all files out of - # that subdirectory. - if self._code_in_branch_subdirectory(destination): - actual_path = os.path.join( - destination, f"{self.addon_to_install.name}-{self.addon_to_install.branch}" - ) - FreeCAD.Console.PrintLog( - f"ZIP installation moving code from {actual_path} to {destination}" - ) - self._move_code_out_of_subdirectory(destination) - - FreeCAD.Console.PrintLog("ZIP installation complete.\n") - self._finalize_successful_installation() - - def _code_in_branch_subdirectory(self, destination: str) -> bool: - test_path = os.path.join(destination, self._expected_subdirectory_name()) - FreeCAD.Console.PrintLog(f"Checking for possible zip sub-path {test_path}...") - if os.path.isdir(test_path): - FreeCAD.Console.PrintLog(f"path exists.\n") - return True - FreeCAD.Console.PrintLog(f"path does not exist.\n") - return False - - def _expected_subdirectory_name(self) -> str: - url = self.addon_to_install.url - if url.endswith(".git"): - url = url[:-4] - _, _, name = url.rpartition("/") - branch = self.addon_to_install.branch - return f"{name}-{branch}" - - def _move_code_out_of_subdirectory(self, destination): - subdirectory = os.path.join(destination, self._expected_subdirectory_name()) - for extracted_filename in os.listdir(os.path.join(destination, subdirectory)): - shutil.move( - os.path.join(destination, subdirectory, extracted_filename), - os.path.join(destination, extracted_filename), - ) - os.rmdir(os.path.join(destination, subdirectory)) - - def _finalize_successful_installation(self): - """Perform any necessary additional steps after installing the addon.""" - self._update_metadata() - self._install_macros() - self.success.emit(self.addon_to_install) - - def _update_metadata(self): - """Loads the package metadata from the Addon's downloaded package.xml file.""" - package_xml = os.path.join( - self.installation_path, self.addon_to_install.name, "package.xml" - ) - - if hasattr(self.addon_to_install, "metadata") and os.path.isfile(package_xml): - self.addon_to_install.load_metadata_file(package_xml) - self.addon_to_install.installed_version = self.addon_to_install.metadata.version - self.addon_to_install.updated_timestamp = os.path.getmtime(package_xml) - - def _install_macros(self): - """For any workbenches, copy FCMacro files into the macro directory. Exclude packages that - have preference packs, otherwise we will litter the macro directory with the pre and post - scripts.""" - if ( - isinstance(self.addon_to_install, Addon) - and self.addon_to_install.contains_preference_pack() - ): - return - - if not os.path.exists(self.macro_installation_path): - os.makedirs(self.macro_installation_path) - - installed_macro_files = [] - for root, _, files in os.walk( - os.path.join(self.installation_path, self.addon_to_install.name) - ): - for f in files: - if f.lower().endswith(".fcmacro"): - src = os.path.join(root, f) - dst = os.path.join(self.macro_installation_path, f) - shutil.copy2(src, dst) - installed_macro_files.append(dst) - if installed_macro_files: - with open( - os.path.join( - self.installation_path, - self.addon_to_install.name, - "AM_INSTALLATION_DIGEST.txt", - ), - "a", - encoding="utf-8", - ) as f: - now = datetime.now(timezone.utc) - f.write( - "# The following files were created outside this installation " - f"path during the installation of this Addon on {now}:\n" - ) - for fcmacro_file in installed_macro_files: - f.write(fcmacro_file + "\n") - - @classmethod - def _validate_object(cls, addon: object): - """Make sure the object has the necessary attributes (name, url, and branch) to be - installed.""" - - if not hasattr(addon, "name") or not hasattr(addon, "url") or not hasattr(addon, "branch"): - raise RuntimeError( - "Provided object does not provide a name, url, and/or branch attribute" - ) - - -class MacroInstaller(QtCore.QObject): - """Install a macro.""" - - # Signals: success and failure - # Emitted when the installation process is complete. The object emitted is the object that the - # installation was requested for (usually of class Addon, but any class that provides a macro - # can be used). - success = QtCore.Signal(object) - failure = QtCore.Signal(object) - - # Finished: regardless of the outcome, this is emitted when all work that is going to be done - # is done (i.e. whatever thread this is running in can quit). - finished = QtCore.Signal() - - def __init__(self, addon: object): - """The provided addon object must have an attribute called "macro", and that attribute must - itself provide a callable "install" method that takes a single string, the path to the - installation location.""" - super().__init__() - self._validate_object(addon) - self.addon_to_install = addon - self.installation_path = FreeCAD.getUserMacroDir(True) - - def run(self) -> bool: - """Install a macro. Returns True if the macro was installed, or False if not. Emits - either success or failure prior to returning.""" - - # To try to ensure atomicity, perform the installation into a temp directory - macro = self.addon_to_install.macro - with tempfile.TemporaryDirectory() as temp_dir: - temp_install_succeeded, error_list = macro.install(temp_dir) - if not temp_install_succeeded: - FreeCAD.Console.PrintError( - translate("AddonsInstaller", "Failed to install macro {}").format(macro.name) - + "\n" - ) - for e in error_list: - FreeCAD.Console.PrintError(e + "\n") - self.failure.emit(self.addon_to_install, "\n".join(error_list)) - self.finished.emit() - return False - - # If it succeeded, move all the files to the macro install location, - # keeping a list of all the files we installed, so they can be removed later - # if this macro is uninstalled. - manifest = [] - for item in os.listdir(temp_dir): - src = os.path.join(temp_dir, item) - dst = os.path.join(self.installation_path, item) - shutil.move(src, dst) - manifest.append(dst) - self._write_installation_manifest(manifest) - self.success.emit(self.addon_to_install) - self.addon_to_install.set_status(Addon.Status.NO_UPDATE_AVAILABLE) - self.finished.emit() - return True - - def _write_installation_manifest(self, manifest): - manifest_file = os.path.join( - self.installation_path, self.addon_to_install.macro.filename + ".manifest" - ) - try: - with open(manifest_file, "w", encoding="utf-8") as f: - f.write(json.dumps(manifest, indent=" ")) - except OSError as e: - FreeCAD.Console.PrintWarning( - translate("AddonsInstaller", "Failed to create installation manifest " "file:\n") - ) - FreeCAD.Console.PrintWarning(manifest_file) - - @classmethod - def _validate_object(cls, addon: object): - """Make sure this object provides an attribute called "macro" with a method called - "install" """ - if ( - not hasattr(addon, "macro") - or addon.macro is None - or not hasattr(addon.macro, "install") - or not callable(addon.macro.install) - ): - raise RuntimeError("Provided object does not provide a macro with an install method") diff --git a/src/Mod/AddonManager/addonmanager_installer_gui.py b/src/Mod/AddonManager/addonmanager_installer_gui.py deleted file mode 100644 index c2139f4f05..0000000000 --- a/src/Mod/AddonManager/addonmanager_installer_gui.py +++ /dev/null @@ -1,815 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Classes to manage the GUI presentation of installing an Addon (e.g. the sequence of dialog boxes -that do dependency resolution, error handling, etc.). See AddonInstallerGUI and MacroInstallerGUI -classes for details.""" - -import os -import sys -from typing import List - -import FreeCAD -import FreeCADGui -from PySide import QtCore, QtWidgets - -from addonmanager_installer import AddonInstaller, MacroInstaller -from addonmanager_dependency_installer import DependencyInstaller -import addonmanager_utilities as utils -from Addon import Addon, MissingDependencies - -translate = FreeCAD.Qt.translate -from PySide.QtCore import QT_TRANSLATE_NOOP - -# pylint: disable=c-extension-no-member,too-few-public-methods,too-many-instance-attributes - - -class AddonInstallerGUI(QtCore.QObject): - """GUI functions (sequence of dialog boxes) for installing an addon interactively. The actual - installation is handled by the AddonInstaller class running in a separate QThread. An instance - of this AddonInstallerGUI class should NOT be run in a separate thread, but on the main GUI - thread. All dialogs are modal.""" - - # External classes are expected to "set and forget" this class, but in the event that some - # action must be taken if the addon is actually installed, this signal is provided. Note that - # this class already provides a "Successful installation" dialog, so external code need not - # do so. - success = QtCore.Signal(object) - - # Emitted once all work has been completed, regardless of success or failure - finished = QtCore.Signal() - - def __init__(self, addon: Addon, addons: List[Addon] = None): - super().__init__() - self.addon_to_install = addon - self.addons = [] if addons is None else addons - self.installer = AddonInstaller(addon) - self.dependency_installer = None - self.install_worker = None - self.dependency_dialog = None - self.dependency_worker_thread = None - self.dependency_installation_dialog = None - self.installing_dialog = None - self.worker_thread = None - - # Set up the installer connections - self.installer.success.connect(self._installation_succeeded) - self.installer.failure.connect(self._installation_failed) - - def __del__(self): - self._stop_thread(self.worker_thread) - self._stop_thread(self.dependency_worker_thread) - - @staticmethod - def _stop_thread(thread: QtCore.QThread): - if thread and hasattr(thread, "quit"): - if thread.isRunning(): - FreeCAD.Console.PrintMessage( - "INTERNAL ERROR: a QThread is still running when it should have finished" - ) - - thread.requestInterruption() - thread.wait(100) - thread.quit() - thread.wait(500) - if thread.isRunning(): - FreeCAD.Console.PrintError( - "INTERNAL ERROR: Thread did not quit() cleanly, using terminate()\n" - ) - thread.terminate() - - def run(self): - """Instructs this class to begin displaying the necessary dialogs to guide a user through - an Addon installation sequence. All dialogs are modal.""" - - # Dependency check - deps = MissingDependencies(self.addon_to_install, self.addons) - - # Python interpreter version check - stop_installation = self._check_python_version(deps) - if stop_installation: - self.finished.emit() - return - - # Required Python - if hasattr(deps, "python_requires") and deps.python_requires: - # Disallowed packages: - stop_installation = self._handle_disallowed_python(deps.python_requires) - if stop_installation: - self.finished.emit() - return - # Allowed but uninstalled is handled below - - # Remove any disallowed packages from the optional list - if hasattr(deps, "python_optional") and deps.python_optional: - self._clean_up_optional(deps) - - # Missing FreeCAD workbenches - if hasattr(deps, "wbs") and deps.wbs: - stop_installation = self._report_missing_workbenches(deps.wbs) - if stop_installation: - self.finished.emit() - return - - # If we have any missing dependencies, display a dialog to the user asking if they want to - # install them. - if deps.external_addons or deps.python_requires or deps.python_optional: - # Recoverable: ask the user if they want to install the missing deps, do so, then - # proceed with the installation - self._resolve_dependencies_then_install(deps) - else: - # No missing deps, just install - self.install() - - def _handle_disallowed_python(self, python_requires: List[str]) -> bool: - """Determine if we are missing any required Python packages that are not in the allowed - packages list. If so, display a message to the user, and return True. Otherwise return - False.""" - - bad_packages = [] - for dep in python_requires: - if dep.lower() not in AddonInstaller.allowed_packages: - bad_packages.append(dep) - - for dep in bad_packages: - python_requires.remove(dep) - - if bad_packages: - # pylint: disable=line-too-long - message = ( - "

    " - + translate( - "AddonsInstaller", - "This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually:", - ) - + "

      " - ) - if len(bad_packages) < 15: - for dep in bad_packages: - message += f"
    • {dep}
    • " - else: - message += "
    • (" + translate("AddonsInstaller", "Too many to list") + ")
    • " - message += "
    " - message += "To ignore this error and install anyway, press OK." - r = QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Missing Requirement"), - message, - QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, - ) - - if r == QtWidgets.QMessageBox.Ok: - # Force the installation to proceed - return False - return True - return False - - def _report_missing_workbenches(self, wbs) -> bool: - """If there are missing workbenches, display a dialog informing the user. Returns True to - stop the installation, or False to proceed.""" - addon_name = self.addon_to_install.name - if len(wbs) == 1: - name = wbs[0] - message = translate( - "AddonsInstaller", - "Addon '{}' requires '{}', which is not available in your copy of FreeCAD.", - ).format(addon_name, name) - else: - # pylint: disable=line-too-long - message = ( - "

    " - + translate( - "AddonsInstaller", - "Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD:", - ).format(addon_name) - + "

      " - ) - for wb in wbs: - message += "
    • " + wb + "
    • " - message += "
    " - message += translate("AddonsInstaller", "Press OK to install anyway.") - r = QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Missing Requirement"), - message, - QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, - ) - return r == QtWidgets.QMessageBox.Cancel - - def _resolve_dependencies_then_install(self, missing) -> None: - """Ask the user how they want to handle dependencies, do that, then install.""" - self.dependency_dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "dependency_resolution_dialog.ui") - ) - - for addon in missing.external_addons: - self.dependency_dialog.listWidgetAddons.addItem(addon) - for mod in missing.python_requires: - self.dependency_dialog.listWidgetPythonRequired.addItem(mod) - for mod in missing.python_optional: - item = QtWidgets.QListWidgetItem(mod) - item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable) - item.setCheckState(QtCore.Qt.Unchecked) - self.dependency_dialog.listWidgetPythonOptional.addItem(item) - - self.dependency_dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Yes).clicked.connect( - self._dependency_dialog_yes_clicked - ) - self.dependency_dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Ignore).clicked.connect( - self._dependency_dialog_ignore_clicked - ) - self.dependency_dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel).setDefault(True) - self.dependency_dialog.exec() - - def _check_python_version(self, missing: MissingDependencies) -> bool: - """Make sure we have a compatible Python version. Returns True to stop the installation - or False to continue.""" - - # For now only look at the minor version, since major is always Python 3 - minor_required = missing.python_min_version["minor"] - if sys.version_info.minor < minor_required: - # pylint: disable=line-too-long - QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Incompatible Python version"), - translate( - "AddonsInstaller", - "This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled.", - ).format( - missing.python_min_version["major"], - missing.python_min_version["minor"], - sys.version_info.major, - sys.version_info.minor, - ), - QtWidgets.QMessageBox.Cancel, - ) - return True - return False - - def _clean_up_optional(self, missing: MissingDependencies): - good_packages = [] - for dep in missing.python_optional: - if dep in self.installer.allowed_packages: - good_packages.append(dep) - else: - FreeCAD.Console.PrintWarning( - translate( - "AddonsInstaller", - "Optional dependency on {} ignored because it is not in the allow-list", - ).format(dep) - + "\n" - ) - missing.python_optional = good_packages - - def _dependency_dialog_yes_clicked(self) -> None: - # Get the lists out of the dialog: - addons = [] - for row in range(self.dependency_dialog.listWidgetAddons.count()): - item = self.dependency_dialog.listWidgetAddons.item(row) - name = item.text() - for repo in self.addons: - if repo.name == name or ( - hasattr(repo, "display_name") and repo.display_name == name - ): - addons.append(repo) - - python_requires = [] - for row in range(self.dependency_dialog.listWidgetPythonRequired.count()): - item = self.dependency_dialog.listWidgetPythonRequired.item(row) - python_requires.append(item.text()) - - python_optional = [] - for row in range(self.dependency_dialog.listWidgetPythonOptional.count()): - item = self.dependency_dialog.listWidgetPythonOptional.item(row) - if item.checkState() == QtCore.Qt.Checked: - python_optional.append(item.text()) - - self._run_dependency_installer(addons, python_requires, python_optional) - - def _run_dependency_installer(self, addons, python_requires, python_optional): - """Run the dependency installer (in a separate thread) for the given dependencies""" - self.dependency_installer = DependencyInstaller(addons, python_requires, python_optional) - self.dependency_installer.no_python_exe.connect(self._report_no_python_exe) - self.dependency_installer.no_pip.connect(self._report_no_pip) - self.dependency_installer.failure.connect(self._report_dependency_failure) - self.dependency_installer.finished.connect(self._dependencies_finished) - - self.dependency_worker_thread = QtCore.QThread(self) - self.dependency_installer.moveToThread(self.dependency_worker_thread) - self.dependency_worker_thread.started.connect(self.dependency_installer.run) - - self.dependency_installation_dialog = QtWidgets.QMessageBox( - QtWidgets.QMessageBox.Information, - translate("AddonsInstaller", "Installing dependencies"), - translate("AddonsInstaller", "Installing dependencies") + "...", - QtWidgets.QMessageBox.Cancel, - parent=utils.get_main_am_window(), - ) - self.dependency_installation_dialog.rejected.connect(self._cancel_dependency_installation) - self.dependency_installation_dialog.show() - self.dependency_worker_thread.start() - - def _report_no_python_exe(self) -> None: - """Callback for the dependency installer failing to locate a Python executable.""" - if self.dependency_installation_dialog is not None: - self.dependency_installation_dialog.hide() - # pylint: disable=line-too-long - result = QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Cannot execute Python"), - translate( - "AddonsInstaller", - "Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python.", - ) - + "\n\n" - + translate( - "AddonsInstaller", - "Dependencies could not be installed. Continue with installation of {} anyway?", - ).format(self.addon_to_install.name), - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - ) - if result == QtWidgets.QMessageBox.Yes: - self.install() - else: - self.finished.emit() - - def _report_no_pip(self, command: str) -> None: - """Callback for the dependency installer failing to access pip.""" - if self.dependency_installation_dialog is not None: - self.dependency_installation_dialog.hide() - # pylint: disable=line-too-long - result = QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Cannot execute pip"), - translate( - "AddonsInstaller", - "Failed to execute pip, which may be missing from your Python installation. Please ensure your system " - "has pip installed and try again. The failed command was:", - ) - + f" \n\n{command}\n\n" - + translate( - "AddonsInstaller", - "Continue with installation of {} anyway?", - ).format(self.addon_to_install.name), - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - ) - if result == QtWidgets.QMessageBox.Yes: - self.install() - else: - self.finished.emit() - - def _report_dependency_failure(self, short_message: str, details: str) -> None: - """Callback for dependency installation failure.""" - if self.dependency_installation_dialog is not None: - self.dependency_installation_dialog.hide() - if self.dependency_installer and hasattr(self.dependency_installer, "finished"): - self.dependency_installer.finished.disconnect(self._report_dependency_success) - FreeCAD.Console.PrintError(details + "\n") - result = QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Package installation failed"), - short_message - + "\n\n" - + translate("AddonsInstaller", "See Report View for detailed failure log.") - + "\n\n" - + translate( - "AddonsInstaller", - "Continue with installation of {} anyway?", - ).format(self.addon_to_install.name), - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - ) - if result == QtWidgets.QMessageBox.Yes: - self.install() - else: - self.finished.emit() - - def _report_dependency_success(self): - """Callback for dependency installation success.""" - if self.dependency_installation_dialog is not None: - self.dependency_installation_dialog.hide() - self.install() - - def _dependencies_finished(self, success: bool): - if success: - self._report_dependency_success() - self.dependency_worker_thread.quit() - - def _dependency_dialog_ignore_clicked(self) -> None: - """Callback for when dependencies are ignored.""" - self.install() - - def _cancel_dependency_installation(self) -> None: - """Cancel was clicked in the dialog. NOTE: Does no cleanup, the state after cancellation is - unknown. In most cases pip can recover from whatever we've done to it.""" - self.dependency_worker_thread.blockSignals(True) - self.dependency_installer.blockSignals(True) - self.dependency_worker_thread.requestInterruption() - self.dependency_installation_dialog.hide() - self.dependency_worker_thread.wait() - self.finished.emit() - - def install(self) -> None: - """Installs or updates a workbench, macro, or package""" - self.worker_thread = QtCore.QThread() - self.installer.moveToThread(self.worker_thread) - self.installer.finished.connect(self.worker_thread.quit) - self.worker_thread.started.connect(self.installer.run) - - self.installing_dialog = QtWidgets.QMessageBox( - QtWidgets.QMessageBox.NoIcon, - translate("AddonsInstaller", "Installing Addon"), - translate("AddonsInstaller", "Installing FreeCAD Addon '{}'").format( - self.addon_to_install.display_name - ), - QtWidgets.QMessageBox.Cancel, - parent=utils.get_main_am_window(), - ) - self.installing_dialog.rejected.connect(self._cancel_addon_installation) - self.installer.finished.connect(self.installing_dialog.hide) - self.installing_dialog.show() - self.worker_thread.start() # Returns immediately - - def _cancel_addon_installation(self): - dlg = QtWidgets.QMessageBox( - QtWidgets.QMessageBox.NoIcon, - translate("AddonsInstaller", "Cancelling"), - translate("AddonsInstaller", "Cancelling installation of '{}'").format( - self.addon_to_install.display_name - ), - QtWidgets.QMessageBox.NoButton, - parent=utils.get_main_am_window(), - ) - dlg.show() - if self.worker_thread.isRunning(): - # Interruption can take a second or more, depending on what was being done. Make sure - # we stay responsive and update the dialog with the text above, etc. - self.worker_thread.requestInterruption() - self.worker_thread.quit() - while self.worker_thread.isRunning(): - self.worker_thread.wait(50) - QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) - path = os.path.join(self.installer.installation_path, self.addon_to_install.name) - if os.path.exists(path): - utils.rmdir(path) - dlg.hide() - self.finished.emit() - - def _installation_succeeded(self): - """Called if the installation was successful.""" - QtWidgets.QMessageBox.information( - utils.get_main_am_window(), - translate("AddonsInstaller", "Success"), - translate("AddonsInstaller", "{} was installed successfully").format( - self.addon_to_install.name - ), - QtWidgets.QMessageBox.Ok, - ) - self.success.emit(self.addon_to_install) - self.finished.emit() - - def _installation_failed(self, addon, message): - """Called if the installation failed.""" - QtWidgets.QMessageBox.critical( - utils.get_main_am_window(), - translate("AddonsInstaller", "Installation Failed"), - translate("AddonsInstaller", "Failed to install {}").format(addon.name) - + "\n" - + message, - QtWidgets.QMessageBox.Cancel, - ) - self.finished.emit() - - -class MacroInstallerGUI(QtCore.QObject): - """Install a macro, providing feedback about the process via dialog boxes, and then offer to - add the macro to a custom toolbar. Should be run on the main GUI thread: this class internally - launches a QThread for the actual installation process.""" - - # Only success should matter to external code: all user interaction is handled via this class - success = QtCore.Signal(object) - - # Emitted once all work has been completed, regardless of success or failure - finished = QtCore.Signal() - - def __init__(self, addon: object): - """The provided addon object must have an attribute called "macro", and that attribute must - itself provide a callable "install" method that takes a single string, the path to the - installation location.""" - super().__init__() - self.addon_to_install = addon - self.worker_thread = None - self.installer = MacroInstaller(self.addon_to_install) - self.addon_params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") - self.toolbar_params = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar") - self.macro_dir = FreeCAD.getUserMacroDir(True) - - def __del__(self): - if self.worker_thread and hasattr(self.worker_thread, "quit"): - self.worker_thread.quit() - self.worker_thread.wait(500) - if self.worker_thread.isRunning(): - FreeCAD.Console.PrintError( - "INTERNAL ERROR: Thread did not quit() cleanly, using terminate()\n" - ) - self.worker_thread.terminate() - - def run(self): - """Perform the installation, including any necessary user interaction via modal dialog - boxes. If installation proceeds successfully to completion, emits the success() signal.""" - - self.worker_thread = QtCore.QThread() - self.installer.moveToThread(self.worker_thread) - self.installer.finished.connect(self.worker_thread.quit) - self.installer.success.connect(self._base_installation_success) - self.worker_thread.started.connect(self.installer.run) - self.worker_thread.start() # Returns immediately - - def _base_installation_success(self): - """Callback for a successful basic macro installation.""" - self.success.emit(self.addon_to_install) - self._ask_to_install_toolbar_button() # Synchronous set of modals - self.finished.emit() - - def _ask_to_install_toolbar_button(self) -> None: - """Presents a dialog to the user asking if they want to install a toolbar button for - a particular macro, and walks through that process if they agree to do so.""" - do_not_show_dialog = self.addon_params.GetBool("dontShowAddMacroButtonDialog", False) - button_exists = self._macro_button_exists() - if not do_not_show_dialog and not button_exists: - add_toolbar_button_dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "add_toolbar_button_dialog.ui") - ) - add_toolbar_button_dialog.buttonYes.clicked.connect(self._install_toolbar_button) - add_toolbar_button_dialog.buttonNever.clicked.connect( - lambda: self.addon_params.SetBool("dontShowAddMacroButtonDialog", True) - ) - add_toolbar_button_dialog.exec() - - def _find_custom_command(self, filename): - """Wrap calls to FreeCADGui.Command.findCustomCommand so it can be faked in testing.""" - return FreeCADGui.Command.findCustomCommand(filename) - - def _macro_button_exists(self) -> bool: - """Returns True if a button already exists for this macro, or False if not.""" - command = self._find_custom_command(self.addon_to_install.macro.filename) - if not command: - return False - toolbar_groups = self.toolbar_params.GetGroups() - for group in toolbar_groups: - toolbar = self.toolbar_params.GetGroup(group) - if toolbar.GetString(command, "*") != "*": - return True - return False - - def _ask_for_toolbar(self, custom_toolbars) -> object: - """Determine what toolbar to add the icon to. The first time it is called it prompts the - user to select or create a toolbar. After that, the prompt is optional and can be configured - via a preference. Returns the pref group for the new toolbar.""" - - # In this one spot, default True: if this is the first time we got to - # this chunk of code, we are always going to ask. - ask = self.addon_params.GetBool("alwaysAskForToolbar", True) - - if ask: - select_toolbar_dialog = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "select_toolbar_dialog.ui") - ) - - select_toolbar_dialog.comboBox.clear() - - for group in custom_toolbars: - ref = self.toolbar_params.GetGroup(group) - name = ref.GetString("Name", "") - if name: - select_toolbar_dialog.comboBox.addItem(name) - else: - FreeCAD.Console.PrintWarning( - f"Custom toolbar {group} does not have a Name element\n" - ) - new_menubar_option_text = translate("AddonsInstaller", "Create new toolbar") - select_toolbar_dialog.comboBox.addItem(new_menubar_option_text) - - result = select_toolbar_dialog.exec() - if result == QtWidgets.QDialog.Accepted: - selection = select_toolbar_dialog.comboBox.currentText() - if select_toolbar_dialog.checkBox.checkState() == QtCore.Qt.Unchecked: - self.addon_params.SetBool("alwaysAskForToolbar", False) - else: - self.addon_params.SetBool("alwaysAskForToolbar", True) - if selection == new_menubar_option_text: - return self._create_new_custom_toolbar() - return self._get_toolbar_with_name(selection) - return None - - # If none of the above code returned... - custom_toolbar_name = self.addon_params.GetString( - "CustomToolbarName", "Auto-Created Macro Toolbar" - ) - toolbar = self._get_toolbar_with_name(custom_toolbar_name) - if not toolbar: - # They told us not to ask, but then the toolbar got deleted... ask anyway! - ask = self.addon_params.RemBool("alwaysAskForToolbar") - return self._ask_for_toolbar(custom_toolbars) - return toolbar - - def _get_toolbar_with_name(self, name: str) -> object: - """Try to find a toolbar with a given name. Returns the preference group for the toolbar - if found, or None if it does not exist.""" - custom_toolbars = self.toolbar_params.GetGroups() - for toolbar in custom_toolbars: - group = self.toolbar_params.GetGroup(toolbar) - group_name = group.GetString("Name", "") - if group_name == name: - return group - return None - - def _create_new_custom_toolbar(self) -> object: - """Create a new custom toolbar and returns its preference group.""" - - # We need two names: the name of the auto-created toolbar, as it will be displayed to the - # user in various menus, and the underlying name of the toolbar group. Both must be - # unique. - - # First, the displayed name - custom_toolbar_name = QT_TRANSLATE_NOOP("Workbench", "Auto-Created Macro Toolbar") - custom_toolbars = self.toolbar_params.GetGroups() - name_taken = self._check_for_toolbar(custom_toolbar_name) - if name_taken: - i = 2 # Don't use (1), start at (2) - while True: - test_name = custom_toolbar_name + f" ({i})" - if not self._check_for_toolbar(test_name): - custom_toolbar_name = test_name - break - i = i + 1 - - # Second, the toolbar preference group name - i = 1 - while True: - new_group_name = "Custom_" + str(i) - if new_group_name not in custom_toolbars: - break - i = i + 1 - - custom_toolbar = self.toolbar_params.GetGroup(new_group_name) - custom_toolbar.SetString("Name", custom_toolbar_name) - custom_toolbar.SetBool("Active", True) - return custom_toolbar - - def _check_for_toolbar(self, toolbar_name: str) -> bool: - """Returns True if the toolbar exists, otherwise False""" - return self._get_toolbar_with_name(toolbar_name) is not None - - def _install_toolbar_button(self) -> None: - """If the user has requested a toolbar button be installed, this function is called - to continue the process and request any additional required information.""" - custom_toolbar_name = self.addon_params.GetString( - "CustomToolbarName", "Auto-Created Macro Toolbar" - ) - - # Default to false here: if the variable hasn't been set, we don't assume - # that we have to ask, because the simplest is to just create a new toolbar - # and never ask at all. - ask = self.addon_params.GetBool("alwaysAskForToolbar", False) - - # See if there is already a custom toolbar for macros: - top_group = self.toolbar_params - custom_toolbars = top_group.GetGroups() - if custom_toolbars: - # If there are already custom toolbars, see if one of them is the one we used last time - found_toolbar = False - for toolbar_name in custom_toolbars: - test_toolbar = self.toolbar_params.GetGroup(toolbar_name) - name = test_toolbar.GetString("Name", "") - if name == custom_toolbar_name: - custom_toolbar = test_toolbar - found_toolbar = True - break - if ask or not found_toolbar: - # We have to ask the user what to do... - custom_toolbar = self._ask_for_toolbar(custom_toolbars) - if custom_toolbar: - custom_toolbar_name = custom_toolbar.GetString("Name") - self.addon_params.SetString("CustomToolbarName", custom_toolbar_name) - else: - # Create a custom toolbar - custom_toolbar = self.toolbar_params.GetGroup("Custom_1") - custom_toolbar.SetString("Name", custom_toolbar_name) - custom_toolbar.SetBool("Active", True) - - if custom_toolbar: - self._install_macro_to_toolbar(custom_toolbar) - else: - FreeCAD.Console.PrintMessage("In the end, no custom toolbar was set, bailing out\n") - - def _install_macro_to_toolbar(self, toolbar: object) -> None: - """Adds an icon for the given macro to the given toolbar.""" - menuText = self.addon_to_install.display_name - tooltipText = f"{self.addon_to_install.display_name}" - if self.addon_to_install.macro.comment: - tooltipText += f"

    {self.addon_to_install.macro.comment}

    " - whatsThisText = self.addon_to_install.macro.comment - else: - whatsThisText = translate( - "AddonsInstaller", "A macro installed with the FreeCAD Addon Manager" - ) - statustipText = ( - translate("AddonsInstaller", "Run", "Indicates a macro that can be 'run'") - + " " - + self.addon_to_install.display_name - ) - if self.addon_to_install.macro.icon: - if os.path.isabs(self.addon_to_install.macro.icon): - pixmapText = os.path.normpath(self.addon_to_install.macro.icon) - else: - pixmapText = os.path.normpath( - os.path.join(self.macro_dir, self.addon_to_install.macro.icon) - ) - elif self.addon_to_install.macro.xpm: - icon_file = os.path.normpath( - os.path.join(self.macro_dir, self.addon_to_install.macro.name + "_icon.xpm") - ) - with open(icon_file, "w", encoding="utf-8") as f: - f.write(self.addon_to_install.macro.xpm) - pixmapText = icon_file - else: - pixmapText = None - - # Add this command to that toolbar - self._create_custom_command( - toolbar, - self.addon_to_install.macro.filename, - menuText, - tooltipText, - whatsThisText, - statustipText, - pixmapText, - ) - - # pylint: disable=too-many-arguments - def _create_custom_command( - self, - toolbar, - filename, - menuText, - tooltipText, - whatsThisText, - statustipText, - pixmapText, - ): - """Wrap createCustomCommand so it can be overridden during testing.""" - # Add this command to that toolbar - command_name = FreeCADGui.Command.createCustomCommand( - filename, - menuText, - tooltipText, - whatsThisText, - statustipText, - pixmapText, - ) - toolbar.SetString(command_name, "FreeCAD") - - # Force the toolbars to be recreated - wb = FreeCADGui.activeWorkbench() - wb.reloadActive() - - def _remove_custom_toolbar_button(self) -> None: - """If this repo contains a macro, look through the custom commands and - see if one is set up for this macro. If so, remove it, including any - toolbar entries.""" - - command = FreeCADGui.Command.findCustomCommand(self.addon_to_install.macro.filename) - if not command: - return - custom_toolbars = FreeCAD.ParamGet("User parameter:BaseApp/Workbench/Global/Toolbar") - toolbar_groups = custom_toolbars.GetGroups() - for group in toolbar_groups: - toolbar = custom_toolbars.GetGroup(group) - if toolbar.GetString(command, "*") != "*": - toolbar.RemString(command) - - FreeCADGui.Command.removeCustomCommand(command) - - # Force the toolbars to be recreated - wb = FreeCADGui.activeWorkbench() - wb.reloadActive() diff --git a/src/Mod/AddonManager/addonmanager_licenses.py b/src/Mod/AddonManager/addonmanager_licenses.py deleted file mode 100644 index 46af254959..0000000000 --- a/src/Mod/AddonManager/addonmanager_licenses.py +++ /dev/null @@ -1,187 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2024 FreeCAD Project Association * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Utilities for working with licenses. Based on SPDX info downloaded from -https://github.com/spdx/license-list-data and stored as part of the FreeCAD repo, loaded into a Qt -resource.""" - -import json - -# Get whatever version of PySide we can -try: - import PySide # Use the FreeCAD wrapper -except ImportError: - try: - import PySide6 # Outside FreeCAD, try Qt6 first - - PySide = PySide6 - except ImportError: - import PySide2 # Fall back to Qt5 (if this fails, Python will kill this module's import) - - PySide = PySide2 - -from PySide import QtCore - -import addonmanager_freecad_interface as fci - - -class SPDXLicenseManager: - """A class that loads a list of licenses from an internal Qt resource and provides access to - some information about those licenses.""" - - def __init__(self): - self.license_data = {} - self._load_license_data() - - def _load_license_data(self): - qf = QtCore.QFile(f":/licenses/spdx.json") - if qf.exists(): - qf.open(QtCore.QIODevice.ReadOnly) - byte_data = qf.readAll() - qf.close() - - string_data = str(byte_data, encoding="utf-8") - raw_license_data = json.loads(string_data) - - self._process_raw_spdx_json(raw_license_data) - - def _process_raw_spdx_json(self, raw_license_data: dict): - """The raw JSON data is a list of licenses, with the ID as an element of the contained - data members. More useful for our purposes is a dictionary with the SPDX IDs as the keys - and the remaining data as the values.""" - for entry in raw_license_data["licenses"]: - self.license_data[entry["licenseId"]] = entry - - def is_osi_approved(self, spdx_id: str) -> bool: - """Check to see if the license is OSI-approved, according to the SPDX database. Returns - False if the license is not in the database, or is not marked as "isOsiApproved".""" - if spdx_id == "UNLICENSED" or spdx_id == "UNLICENCED" or spdx_id.startswith("SEE LIC"): - return False - if spdx_id not in self.license_data: - fci.Console.PrintWarning( - f"WARNING: License ID {spdx_id} is not in the SPDX license " - f"list. The Addon author must correct their metadata.\n" - ) - return False - return ( - "isOsiApproved" in self.license_data[spdx_id] - and self.license_data[spdx_id]["isOsiApproved"] - ) - - def is_fsf_libre(self, spdx_id: str) -> bool: - """Check to see if the license is FSF Free/Libre, according to the SPDX database. Returns - False if the license is not in the database, or is not marked as "isFsfLibre".""" - if spdx_id == "UNLICENSED" or spdx_id == "UNLICENCED" or spdx_id.startswith("SEE LIC"): - return False - if spdx_id not in self.license_data: - fci.Console.PrintWarning( - f"WARNING: License ID {spdx_id} is not in the SPDX license " - f"list. The Addon author must correct their metadata.\n" - ) - return False - return ( - "isFsfLibre" in self.license_data[spdx_id] and self.license_data[spdx_id]["isFsfLibre"] - ) - - def name(self, spdx_id: str) -> str: - if spdx_id == "UNLICENSED": - return "All rights reserved" - if spdx_id.startswith("SEE LIC"): # "SEE LICENSE IN" or "SEE LICENCE IN" - return f"Custom license: {spdx_id}" - if spdx_id not in self.license_data: - return "" - return self.license_data[spdx_id]["name"] - - def url(self, spdx_id: str) -> str: - if spdx_id not in self.license_data: - return "" - return self.license_data[spdx_id]["reference"] - - def details_json_url(self, spdx_id: str): - """The "detailsUrl" entry in the SPDX database, which is a link to a JSON file containing - the details of the license. As of SPDX v3 the fields are: - * isDeprecatedLicenseId - * isFsfLibre - * licenseText - * standardLicenseHeaderTemplate - * standardLicenseTemplate - * name - * licenseId - * standardLicenseHeader - * crossRef - * seeAlso - * isOsiApproved - * licenseTextHtml - * standardLicenseHeaderHtml""" - if spdx_id not in self.license_data: - return "" - return self.license_data[spdx_id]["detailsUrl"] - - def normalize(self, license_string: str) -> str: - """Given a potentially non-compliant license string, attempt to normalize it to match an - SPDX record. Takes a conservative view and tries not to over-expand stated rights (e.g. - it will select 'GPL-3.0-only' rather than 'GPL-3.0-or-later' when given just GPL3).""" - if self.name(license_string): - return license_string - fci.Console.PrintLog( - f"Attempting to normalize non-compliant license '" f"{license_string}'... " - ) - normed = license_string.replace("lgpl", "LGPL").replace("gpl", "GPL") - normed = ( - normed.replace(" ", "-") - .replace("v", "-") - .replace("GPL2", "GPL-2") - .replace("GPL3", "GPL-3") - ) - or_later = "" - if normed.endswith("+"): - normed = normed[:-1] - or_later = "-or-later" - if self.name(normed + or_later): - fci.Console.PrintLog(f"found valid SPDX license ID {normed}\n") - return normed + or_later - # If it still doesn't match, try some other things - while "--" in normed: - normed = normed.replace("--", "-") - - if self.name(normed + or_later): - fci.Console.PrintLog(f"found valid SPDX license ID {normed}\n") - return normed + or_later - normed += ".0" - if self.name(normed + or_later): - fci.Console.PrintLog(f"found valid SPDX license ID {normed}\n") - return normed + or_later - fci.Console.PrintLog(f"failed to normalize (typo in ID or invalid version number??)\n") - return license_string # We failed to normalize this one - - -_LICENSE_MANAGER = None # Internal use only, see get_license_manager() - - -def get_license_manager() -> SPDXLicenseManager: - """Get the license manager. Prevents multiple re-loads of the license list by keeping a - single copy of the manager.""" - global _LICENSE_MANAGER - if _LICENSE_MANAGER is None: - _LICENSE_MANAGER = SPDXLicenseManager() - return _LICENSE_MANAGER diff --git a/src/Mod/AddonManager/addonmanager_macro.py b/src/Mod/AddonManager/addonmanager_macro.py deleted file mode 100644 index 9858076f9c..0000000000 --- a/src/Mod/AddonManager/addonmanager_macro.py +++ /dev/null @@ -1,439 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# *************************************************************************** -# * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * -# * Copyright (c) 2018 Gaël Écorchard * -# * * -# * This file is part of FreeCAD. * -# * * -# * FreeCAD is free software: you can redistribute it and/or modify it * -# * under the terms of the GNU Lesser General Public License as * -# * published by the Free Software Foundation, either version 2.1 of the * -# * License, or (at your option) any later version. * -# * * -# * FreeCAD is distributed in the hope that it will be useful, but * -# * WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with FreeCAD. If not, see * -# * . * -# * * -# *************************************************************************** - -"""Unified handler for FreeCAD macros that can be obtained from different sources.""" - -import os -import re -import io -import codecs -import shutil -from html import unescape -from typing import Dict, Tuple, List, Union, Optional -import urllib.parse - -from addonmanager_macro_parser import MacroParser -import addonmanager_utilities as utils - -import addonmanager_freecad_interface as fci - -translate = fci.translate - - -# @package AddonManager_macro -# \ingroup ADDONMANAGER -# \brief Unified handler for FreeCAD macros that can be obtained from -# different sources -# @{ - - -class Macro: - """This class provides a unified way to handle macros coming from different - sources""" - - # Use a stored class variable for this so that we can override it during testing - blocking_get = None - - # pylint: disable=too-many-instance-attributes - def __init__(self, name): - self.name = name - self.on_wiki = False - self.on_git = False - self.desc = "" - self.comment = "" - self.code = "" - self.url = "" - self.raw_code_url = "" - self.wiki = "" - self.version = "" - self.license = "" - self.date = "" - self.src_filename = "" - self.filename_from_url = "" - self.author = "" - self.icon = "" - self.icon_source = None - self.xpm = "" # Possible alternate icon data - self.other_files = [] - self.parsed = False - self._console = fci.Console - if Macro.blocking_get is None: - Macro.blocking_get = utils.blocking_get - - def __eq__(self, other): - return self.filename == other.filename - - @classmethod - def from_cache(cls, cache_dict: Dict): - """Use data from the cache dictionary to create a new macro, returning a - reference to it.""" - instance = Macro(cache_dict["name"]) - for key, value in cache_dict.items(): - instance.__dict__[key] = value - return instance - - def to_cache(self) -> Dict: - """For cache purposes all public members of the class are returned""" - cache_dict = {} - for key, value in self.__dict__.items(): - if key[0] != "_": - cache_dict[key] = value - return cache_dict - - @property - def filename(self): - """The filename of this macro""" - if self.on_git: - return os.path.basename(self.src_filename) - elif self.filename_from_url: - return self.filename_from_url - return (self.name + ".FCMacro").replace(" ", "_") - - def is_installed(self): - """Returns True if this macro is currently installed (that is, if it exists - in the user macro directory), or False if it is not. Both the exact filename - and the filename prefixed with "Macro", are considered an installation - of this macro. - """ - if self.on_git and not self.src_filename: - return False - return os.path.exists( - os.path.join(fci.DataPaths().macro_dir, self.filename) - ) or os.path.exists(os.path.join(fci.DataPaths().macro_dir, "Macro_" + self.filename)) - - def fill_details_from_file(self, filename: str) -> None: - """Opens the given Macro file and parses it for its metadata""" - with open(filename, errors="replace", encoding="utf-8") as f: - self.code = f.read() - self.fill_details_from_code(self.code) - - def fill_details_from_code(self, code: str) -> None: - """Read the passed-in code and parse it for known metadata elements""" - parser = MacroParser(self.name, code) - for key, value in parser.parse_results.items(): - if value: - self.__dict__[key] = value - self.clean_icon() - self.parsed = True - - def fill_details_from_wiki(self, url): - """For a given URL, download its data and attempt to get the macro's metadata - out of it. If the macro's code is hosted elsewhere, as specified by a - "rawcodeurl" found on the wiki page, that code is downloaded and used as the - source.""" - code = "" - p = Macro.blocking_get(url) - if not p: - self._console.PrintWarning( - translate( - "AddonsInstaller", - "Unable to open macro wiki page at {}", - ).format(url) - + "\n" - ) - return - p = p.decode("utf8") - # check if the macro page has its code hosted elsewhere, download if - # needed - if "rawcodeurl" in p: - code = self._fetch_raw_code(p) - if not code: - code = self._read_code_from_wiki(p) - if not code: - self._console.PrintWarning( - translate("AddonsInstaller", "Unable to fetch the code of this macro.") + "\n" - ) - return - - desc = re.findall( - r"(.*?)", - p.replace("\n", " "), - ) - if desc: - desc = desc[0] - else: - self._console.PrintWarning( - translate( - "AddonsInstaller", - "Unable to retrieve a description from the wiki for macro {}", - ).format(self.name) - + "\n" - ) - desc = "No description available" - self.desc = desc - self.comment, _, _ = desc.partition("", "", self.comment) # Strip any tags - self.url = url - if isinstance(code, list): - code = "".join(code) - self.code = code - self.fill_details_from_code(self.code) - if not self.icon and not self.xpm: - self.parse_wiki_page_for_icon(p) - self.clean_icon() - - if not self.author: - self.author = self.parse_desc("Author: ") - if not self.date: - self.date = self.parse_desc("Last modified: ") - - def _fetch_raw_code(self, page_data) -> Optional[str]: - """Fetch code from the raw code URL specified on the wiki page.""" - code = None - self.raw_code_url = re.findall(r'rawcodeurl.*?href="(http.*?)">', page_data) - if self.raw_code_url: - self.raw_code_url = self.raw_code_url[0] - u2 = Macro.blocking_get(self.raw_code_url) - if not u2: - self._console.PrintWarning( - translate( - "AddonsInstaller", - "Unable to open macro code URL {}", - ).format(self.raw_code_url) - + "\n" - ) - return None - code = u2.decode("utf8") - self._set_filename_from_url(self.raw_code_url) - return code - - def _set_filename_from_url(self, url: str): - lhs, slash, rhs = url.rpartition("/") - if rhs.endswith(".py") or rhs.lower().endswith(".fcmacro"): - self.filename_from_url = rhs - - @staticmethod - def _read_code_from_wiki(p: str) -> Optional[str]: - code = re.findall(r"
    (.*?)
    ", p.replace("\n", "--endl--")) - if code: - # take the biggest code block - code = str(sorted(code, key=len)[-1]) - code = code.replace("--endl--", "\n") - # Clean HTML escape codes. - code = unescape(code) - code = code.replace(b"\xc2\xa0".decode("utf-8"), " ") - return code - - def clean_icon(self): - """Downloads the macro's icon from whatever source is specified and stores a local - copy, potentially updating the internal icon location to that local storage.""" - if self.icon.startswith("http://") or self.icon.startswith("https://"): - self._console.PrintLog(f"Attempting to fetch macro icon from {self.icon}\n") - parsed_url = urllib.parse.urlparse(self.icon) - p = Macro.blocking_get(self.icon) - if p: - cache_path = fci.DataPaths().cache_dir - am_path = os.path.join(cache_path, "AddonManager", "MacroIcons") - os.makedirs(am_path, exist_ok=True) - _, _, filename = parsed_url.path.rpartition("/") - base, _, extension = filename.rpartition(".") - if base.lower().startswith("file:"): - self._console.PrintMessage( - f"Cannot use specified icon for {self.name}, {self.icon} " - "is not a direct download link\n" - ) - self.icon = "" - else: - constructed_name = os.path.join(am_path, base + "." + extension) - with open(constructed_name, "wb") as f: - f.write(p) - self.icon_source = self.icon - self.icon = constructed_name - else: - self._console.PrintLog( - f"MACRO DEVELOPER WARNING: failed to download icon from {self.icon}" - f" for macro {self.name}\n" - ) - self.icon = "" - - def parse_desc(self, line_start: str) -> Union[str, None]: - """Get data from the wiki for the value specified by line_start.""" - components = self.desc.split(">") - for component in components: - if component.startswith(line_start): - end = component.find("<") - return component[len(line_start) : end] - return None - - def install(self, macro_dir: str) -> Tuple[bool, List[str]]: - """Install a macro and all its related files - Returns True if the macro was installed correctly. - Parameters - ---------- - - macro_dir: the directory to install into - """ - - if not self.code: - return False, ["No code"] - if not os.path.isdir(macro_dir): - try: - os.makedirs(macro_dir) - except OSError: - return False, [f"Failed to create {macro_dir}"] - macro_path = os.path.join(macro_dir, self.filename) - try: - with codecs.open(macro_path, "w", "utf-8") as macrofile: - macrofile.write(self.code) - except OSError: - return False, [f"Failed to write {macro_path}"] - # Copy related files, which are supposed to be given relative to - # self.src_filename. - warnings = [] - - self._copy_icon_data(macro_dir, warnings) - success = self._copy_other_files(macro_dir, warnings) - - if warnings or not success > 0: - return False, warnings - - self._console.PrintLog(f"Macro {self.name} was installed successfully.\n") - return True, [] - - def _copy_icon_data(self, macro_dir, warnings): - """Copy any available icon data into the install directory""" - base_dir = os.path.dirname(self.src_filename) - if self.xpm: - xpm_file = os.path.join(base_dir, self.name + "_icon.xpm") - with open(xpm_file, "w", encoding="utf-8") as f: - f.write(self.xpm) - if self.icon: - if os.path.isabs(self.icon): - dst_file = os.path.normpath(os.path.join(macro_dir, os.path.basename(self.icon))) - try: - shutil.copy(self.icon, dst_file) - except OSError: - warnings.append(f"Failed to copy icon to {dst_file}") - elif self.icon not in self.other_files: - self.other_files.append(self.icon) - - def _copy_other_files(self, macro_dir, warnings) -> bool: - """Copy any specified "other files" into the installation directory""" - base_dir = os.path.dirname(self.src_filename) - for other_file in self.other_files: - if not other_file: - continue - if os.path.isabs(other_file): - dst_dir = macro_dir - else: - dst_dir = os.path.join(macro_dir, os.path.dirname(other_file)) - if not os.path.isdir(dst_dir): - try: - os.makedirs(dst_dir) - except OSError: - warnings.append(f"Failed to create {dst_dir}") - return False - if os.path.isabs(other_file): - src_file = other_file - dst_file = os.path.normpath(os.path.join(macro_dir, os.path.basename(other_file))) - else: - src_file = os.path.normpath(os.path.join(base_dir, other_file)) - dst_file = os.path.normpath(os.path.join(macro_dir, other_file)) - self._fetch_single_file(other_file, src_file, dst_file, warnings) - try: - shutil.copy(src_file, dst_file) - except OSError: - warnings.append(f"Failed to copy {src_file} to {dst_file}") - return True # No fatal errors, but some files may have failed to copy - - def _fetch_single_file(self, other_file, src_file, dst_file, warnings): - if not os.path.isfile(src_file): - # If the file does not exist, see if we have a raw code URL to fetch from - if self.raw_code_url: - fetch_url = self.raw_code_url.rsplit("/", 1)[0] + "/" + other_file - self._console.PrintLog(f"Attempting to fetch {fetch_url}...\n") - p = Macro.blocking_get(fetch_url) - if p: - with open(dst_file, "wb") as f: - f.write(p) - else: - self._console.PrintWarning( - translate( - "AddonsInstaller", - "Unable to fetch macro-specified file {} from {}", - ).format(other_file, fetch_url) - + "\n" - ) - else: - warnings.append( - translate( - "AddonsInstaller", - "Could not locate macro-specified file {} (expected at {})", - ).format(other_file, src_file) - ) - - def parse_wiki_page_for_icon(self, page_data: str) -> None: - """Attempt to find the url for the icon in the wiki page. Sets 'self.icon' if - found.""" - - # Method 1: the text "toolbar icon" appears on the page, and provides a direct - # link to an icon - - # pylint: disable=line-too-long - # Try to get an icon from the wiki page itself: - # ToolBar Icon - icon_regex = re.compile(r'.*href="(.*?)">ToolBar Icon', re.IGNORECASE) - wiki_icon = "" - if "ToolBar Icon" in page_data: - f = io.StringIO(page_data) - lines = f.readlines() - for line in lines: - if ">ToolBar Icon<" in line: - match = icon_regex.match(line) - if match: - wiki_icon = match.group(1) - if "file:" not in wiki_icon.lower(): - self.icon = wiki_icon - return - break - - # See if we found an icon, but it wasn't a direct link: - icon_regex = re.compile(r'.*img.*?src="(.*?)"', re.IGNORECASE) - if wiki_icon.startswith("http"): - # It's a File: wiki link. We can load THAT page and get the image from it... - self._console.PrintLog(f"Found a File: link for macro {self.name} -- {wiki_icon}\n") - p = Macro.blocking_get(wiki_icon) - if p: - p = p.decode("utf8") - f = io.StringIO(p) - lines = f.readlines() - trigger = False - for line in lines: - if trigger: - match = icon_regex.match(line) - if match: - wiki_icon = match.group(1) - self.icon = "https://wiki.freecad.org/" + wiki_icon - return - elif "fullImageLink" in line: - trigger = True - - #

    5Pcp|Q&0is7H(}amnuoK$ipe~bXP8raU@9!An-k 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 - - - - AddCustomRepositoryDialog - - - Custom repository - Custom repository - - - - Repository URL - Repository URL - - - - Branch - Branch - - - - CompactView - - - Form - Porma - - - - Icon - Imahe - - - - <b>Package Name</b> - <b>Package Name</b> - - - - Version - Bersyon - - - - Description - Paglalarawan - - - - UpdateAvailable - UpdateAvailable - - - - DependencyDialog - - - Dependencies - Dependencies - - - - Dependency type - Dependency type - - - - Name - Pangalan - - - - Optional? - Optional? - - - - DependencyResolutionDialog - - - Resolve Dependencies - Resolve Dependencies - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - - - - FreeCAD Addons - FreeCAD Addons - - - - Required Python modules - Required Python modules - - - - Optional Python modules - Optional Python modules - - - - DeveloperModeDialog - - - Addon Developer Tools - Addon Developer Tools - - - - Path to Addon - Path to Addon - - - - - Browse... - Browse... - - - - Metadata - Metadata - - - - Primary branch - Primary branch - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - - - - Description - Paglalarawan - - - - Discussion URL - Discussion URL - - - - Icon - Imahe - - - - Bugtracker URL - Bugtracker URL - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - - - - (Optional) - (Optional) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - - - - README URL - README URL - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - - - - Repository URL - Repository URL - - - - Website URL - Website URL - - - - Documentation URL - Documentation URL - - - - Addon Name - Addon Name - - - - Version - Bersyon - - - - (Recommended) - (Recommended) - - - - Minimum Python - Minimum Python - - - - (Optional, only 3.x version supported) - (Optional, only 3.x version supported) - - - - Detect... - Detect... - - - - Addon Contents - Addon Contents - - - - Dialog - - - Addon Manager - Addon Manager - - - - Downloading info... - Downloading info... - - - - Pause cache update - Pause cache update - - - - Refresh local cache - Refresh local cache - - - - Download and apply all available updates - Download and apply all available updates - - - - Update all Addons - Update all Addons - - - - Check for updates - Check for updates - - - - View and update Python package dependencies - View and update Python package dependencies - - - - Python dependencies... - Python dependencies... - - - - Developer tools... - Developer tools... - - - - Close the Addon Manager - Close the Addon Manager - - - - Close - Sarado - - - - Welcome to the Addon Manager - Welcome to the Addon Manager - - - - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - The addons that can be installed here are not officially part of FreeCAD, and are not reviewed by the FreeCAD team. Make sure you know what you are installing! - - - - Download Settings - Download Settings - - - - Automatically check installed Addons for updates - Automatically check installed Addons for updates - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - No proxy - No proxy - - - - System proxy - System proxy - - - - User-defined proxy: - User-defined proxy: - - - - These and other settings are available in the FreeCAD Preferences window. - These and other settings are available in the FreeCAD Preferences window. - - - - Edit Tags - Edit Tags - - - - Comma-separated list of tags describing this item: - Comma-separated list of tags describing this item: - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - EditDependencyDialog - - - Edit Dependency - Edit Dependency - - - - Dependency Type - Dependency Type - - - - Dependency - Dependency - - - - Package name, if "Other..." - Package name, if "Other..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - - - - Optional - Optional - - - - ExpandedView - - - Form - Porma - - - - Icon - Imahe - - - - <h1>Package Name</h1> - <h1>Package Name</h1> - - - - Version - Bersyon - - - - (tags) - (tags) - - - - Description - Paglalarawan - - - - Maintainer - Maintainer - - - - UpdateAvailable - UpdateAvailable - - - - Form - - - - Form - Porma - - - - Licenses - Licenses - - - - License - Lisensya - - - - License file - License file - - - - People - People - - - - Kind - Kind - - - - Name - Pangalan - - - - Email - Email - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Advanced Version Mapping - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - - - - FreeCAD Version - FreeCAD Version - - - - Best-available branch, tag, or commit - Best-available branch, tag, or commit - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Supported FreeCAD Versions - - - - Minimum FreeCAD Version Supported - Minimum FreeCAD Version Supported - - - - - Optional - Optional - - - - Maximum FreeCAD Version Supported - Maximum FreeCAD Version Supported - - - - Advanced version mapping... - Advanced version mapping... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Addon manager options - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates -(this requires the GitPython package installed on your system) - - - - Automatically check for updates at start (requires git) - Automatically check for updates at start (requires git) - - - - Download Macro metadata (approximately 10MB) - Download Macro metadata (approximately 10MB) - - - - - Addons - Addons - - - - Cache update frequency - Cache update frequency - - - - Manual (no automatic updates) - Manual (no automatic updates) - - - - Daily - Daily - - - - Weekly - Weekly - - - - Hide Addons marked Python 2 Only - Hide Addons marked Python 2 Only - - - - Hide Addons marked Obsolete - Hide Addons marked Obsolete - - - - Hide Addons that require a newer version of FreeCAD - Hide Addons that require a newer version of FreeCAD - - - - Custom repositories - Custom repositories - - - - Show option to change branches (requires git) - Show option to change branches (requires git) - - - - Disable git (fall back to ZIP downloads only) - Disable git (fall back to ZIP downloads only) - - - - disableGit - disableGit - - - - Activate Addon Manager options intended for developers of new Addons. - Activate Addon Manager options intended for developers of new Addons. - - - - Addon developer mode - Addon developer mode - - - - developerMode - developerMode - - - - Proxy - Proxy - - - - No proxy - No proxy - - - - User system proxy - User system proxy - - - - User-defined proxy: - User-defined proxy: - - - - Python executable (optional): - Python executable (optional): - - - - The path to the Python executable for package installation with pip. Autodetected if needed and not specified. - The path to the Python executable for package installation with pip. Autodetected if needed and not specified. - - - - git executable (optional): - git executable (optional): - - - - The path to the git executable. Autodetected if needed and not specified. - The path to the git executable. Autodetected if needed and not specified. - - - - Advanced Options - Advanced Options - - - - PackageDetails - - - Form - Porma - - - - Uninstalls a selected macro or workbench - Uninstalls a selected macro or workbench - - - - Install - Install - - - - Uninstall - Uninstall - - - - Update - Update - - - - Run Macro - Run Macro - - - - Change branch - Change branch - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Manage Python Dependencies - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - - - - Package name - Package name - - - - Installed version - Installed version - - - - Available version - Available version - - - - Used by - Used by - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - - - - Update all available - Update all available - - - - SelectFromList - - - Dialog - Diyalogo - - - - TextLabel - TextLabel - - - - UpdateAllDialog - - - Updating Addons - Updating Addons - - - - Updating out-of-date addons... - Updating out-of-date addons... - - - - addContentDialog - - - Content Item - Content Item - - - - Content type: - Content type: - - - - Macro - Makro - - - - Preference Pack - Preference Pack - - - - Workbench - Workbench - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - - - - This is the only item in the Addon - This is the only item in the Addon - - - - Main macro file - Main macro file - - - - The file with the macro's metadata in it - The file with the macro's metadata in it - - - - - - Browse... - Browse... - - - - Preference Pack Name - Preference Pack Name - - - - Workbench class name - Workbench class name - - - - Class that defines "Icon" data member - Class that defines "Icon" data member - - - - Subdirectory - Subdirectory - - - - Optional, defaults to name of content item - Optional, defaults to name of content item - - - - Icon - Imahe - - - - actualIcon - actualIcon - - - - Optional, defaults to inheriting from top-level Addon - Optional, defaults to inheriting from top-level Addon - - - - Tags... - Tags... - - - - Dependencies... - Dependencies... - - - - FreeCAD Versions... - FreeCAD Versions... - - - - Other Metadata - Other Metadata - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - - - - Version - Bersyon - - - - Description - Paglalarawan - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - - - - Set to today (CalVer style) - Set to today (CalVer style) - - - - Display Name - Display Name - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - - - - add_toolbar_button_dialog - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - - change_branch - - - Change Branch - Change Branch - - - - Change to branch or tag: - Change to branch or tag: - - - - copyrightInformationDialog - - - Copyright Information - Copyright Information - - - - Copyright holder: - Copyright holder: - - - - Copyright year: - Copyright year: - - - - personDialog - - - Add Person - Add Person - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - - - - Name: - Pangalan: - - - - Email: - Email: - - - - Email is required for maintainers, and optional for authors. - Email is required for maintainers, and optional for authors. - - - - proxy_authentication - - - Proxy login required - Proxy login required - - - - Proxy requires authentication - Proxy requires authentication - - - - Proxy: - Proxy: - - - - Placeholder for proxy address - Placeholder for proxy address - - - - Realm: - Realm: - - - - Placeholder for proxy realm - Placeholder for proxy realm - - - - Username - Username - - - - Password - Password - - - - selectLicenseDialog - - - Select a license - Select a license - - - - About... - About... - - - - License name: - License name: - - - - Path to license file: - Path to license file: - - - - (if required by license) - (if required by license) - - - - Browse... - Browse... - - - - Create... - Create... - - - - select_toolbar_dialog - - - Select Toolbar - Select Toolbar - - - - Select a toolbar to add this macro to: - Select a toolbar to add this macro to: - - - - Ask every time - Ask every time - - - - toolbar_button - - - Add button? - Add button? - - - - Add a toolbar button for this macro? - Add a toolbar button for this macro? - - - - Yes - Yes - - - - No - No - - - - Never - Never - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_fr.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_fr.qm deleted file mode 100644 index 3ee080dc21c67b17095fbe9ba20e4be04bfe95ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75471 zcmdUY3wT^rwf~+p@1{vxN-5>hA(S@7CM_)%iGcLoLeqvOZ2=XWWG2bb$xN7;v<(&X z0zN=R1s|wf#Rm^j;QG2(@r58Ni0I$TyVAi?4Y9=O4RGDOEF6T&Gm)N~P*{s6l+H!$Xvu7%G!55S&;q!~{SL%IukJm)gd*pS&xvKWriaA!%BT%je7BC`&DB0ch%;P0FD`Z)j1s> zRO*B=bzDB9?chrTq&Tw z?PW^c^(FOK8$Q4LX!X-g4+E~Wdg{xcQ0k*=)w56F{XK6^G`}IQ5{csz3r;x??|+n7 z_4$8Rs{O->ZFLxT(XzzYzhnLf2NU~m_^?t>)Fuu-_MB29XD4nPo~P8?Z%*8P;^Rtv zeoNw0Pipnw)pLOF#h*<4`&S=ViTbxDe);03 zm3r}AHR^_11LFx%Xa&{eNdo@9#d3ee9{( z{qa_%{(4)@!53oQSAMGI`qSF6|Bu$(_-Q;p^W2)-KRl?^(Z8(u$mUOB-@a1wnR{NU z)ZXj#Yhp%w%_D7}RBF$%nnxZkDRt|A*E~9Wrc$rFujU62KZN~#q~=F|d$&@#eKmi6 z-~pu`PSpJQ8PG@Li))^};sW4dNzMPf5O{fX+l<;{j>10uc*gOU-ltT0^NbZ&W|jKR z*Jhmg8>~aEn=$aJN0s`_aRc_@gEQ`V zFYx=4BWHZ={Jc`H8lLgZE587q`pb+z-1M|kmmO7m)JIQMYS%rrM}6%|rJ66RUHnbL zy}x$t&pxiy*(cR*xC85c?FVYlEnkPvv%M}c@Lr|HzFfEXg;?h=|5x2fZ^J&k zXmQ=r#B<==hwE1U7@vRgqPp&;E~UP3LEV`@ew9*J{d?WO-Xm3_;T?4&PoAX`v%XoE z8wMN?KU_Edxm`;A@PE}!6dqEEIZxFc+=X@4+)(%GcVnEFKUVkZyDw5|^yhU~e**aU z-Mi}Ea87Qg6Gl?gKx-dS3BHd3|V2-L0o! z|6YDo-JM@KMh50ltWsSM)!je*E69@QC@#}UEOzYgIpWxsr&wY zpr1qex}Ws?P^tH@jL5Po0$ zW&PVv`vUfHP5pabxmu}P{#Jj>lP_0lVtf7VcipVi^^ewn^go_d>gHATcV3JAc*oZI z2X4Mgsqr_~f9pEHyQ8E2JHj@V!S$NnCr&i`%w|FpeL zsk2_w&~)dQm0JFhh6S?#_gH7c39W~)p5HZW8f#VR4PS4#=rz|to}AM#n4AH6YG@ei zzYBDDWy57ZT@QZfYdCms6Xg8vhHGblUK39@y!j35AV+U&cFe?Q;w zFFTG_>WJGK{v~y+QePXC*GKCczWSecD)stH8XoR?TB(oypy3-curHtdO2ea{dnf4W zZw=o$s!OTClNx@0$#Y75c~`@st&b>`y`$lodme{8`Dw!+R&}ey%+|)aXM7TR>$=9d zKLcI;=CsD+UIRMZ-`?1M&J{}ib8lnUH}L%VA8EYw;!dpVq{gdn`L0qQ>2AEX`3u0` z#>Th)<{t3L(~WN*>;m0h*!aG$JpsA*r^XLHb(c~vyrA)pC!Peq?Q8t_c`KBf^RdQH z-+eFewxIDdU%VFl@=W7rKMFp7X;0&qp27ZnJ>7W!yzeQs{`SWEKLquCRAb`<%dyUP zU)A`?7r%;qzP|DM3pRr;|F!Y^*JGX^jW+)LH(38@Z{x2Y-Ko_3pKSb7J)ZA;xM{}U zUI_kvys7nvpv%`bH_iEIol2;?n&z%PL#a>Q&@}(4TBZKAQ@7ZqtPqJ^;S@Y175jV@I?#4bQ({ zssDVSY53chLGQf0DK~zFN*r-YQz3r^?2+@D_I(WU;@sCYz4~uwDRt~in_mCA;~{qM zZhGUqS3&=LRbG#}vFRWO5J#Q)4iwRcgs#~`s$|}Am`uI^wnQJ0)6A&%9>Ko5%(?kaJ@Zikjz5%+u`LUTx z_Wl%dbLPyK4m_>YMSq$3@<)J|_q}N5;C+xo^K&yteg$~`?ZY##{3f2eZfNGU=UxXo zxOe6oKJlDNw5XZyy5RG$S7yz;=|0H0)N?bReBdsnetON!UtRq-rLO&_nSX5ErPPYg zwA9`Newn+YrLI`UzJ0l+?#ICQU(auucgkr>6~5Op|69P*#&5J7`=dv}U)x(2-GTM~ zCEs%57R)$6H0w)Nz00Nty1dQ(Uz6(ABH_M((;lyfOpaVv}}E63+S?`WqSwU zxc91--uD9jw_MZGR}VP0UD2{<^{7&BTGw(xKlc0K6)i7)^$Q_i{-b61&a0HV^nsTA z?fCu2##=5Oz&h`JsHMc$4?Wm&*}pA@yjj-r=2u+}JL9>QcYPG=DO}p}o*~Th`@>z4v#6DeC(yxiSm(Du++t&d9N&T9r{f}9Tp2Bn2JUeU2KZ7oB zm_KXD4;DgiE}FG;@EOqi{8^{$c|fUmJw5A;yBlCfTrlg*H!Of1{lu&-d-F>D;n`W| z9lt@Tw(Dl4?!&rHxMkMZ*4tq}e|y&JKmQu|3BQxqhrT`Qtw)@!)IYs!*7y3K#J;|N z)^Bp4$M2rjI`3Yr|M>e`kNha+-~W}?6FV{Q>i4%UdF;!u<1TFN_&xCXp(|Tg|K&NQ zy1QFX+j>9jvWr{S-Eo&v|Gl7f$E>Z8zt6OuciY8Etz6UE_aNlyG2d^^d=}&X`mWa8 zob|9zKGiy2o`-P3?!OLncwbxh5lu?{_&$hkk{65&zXSZG74*B%^=h|*+JRfrY^tPK`_5|ql zK-<6lISo5tU)vYnfc<~_thW0GFn{_}ZNEDH3FxOUwf$k^cJRlwZGYKR3wz)yDBlJ9 zXFwvfs&%TUQYxa&cu_2qv z6^0WWVX@kv4yiHqj4G=nUNac4qzV`@k8yJag(()OU23P=hT+p{ zT>tA$Xoqcepe1+h+%|;vK;vWSRG9#kN3i%p zE?3ykcPTDj<6*YOLn)aJVB%`*c3y)xis1(VUI7yd&WZgT{u4Z;06+#$B)z>GCLjP- zz$E!)@oTfI(Tm|ylWLQGHlx<7wQ7T1&dRmP(bQnEV1Z00_h-u^dQF>(naujN8WoEl=(r$qtSrv!!IdP)?@yfnibuxeTzJoG6SJlY@n^iDY3Y>7lqQ z5;cz=CThs-TwF>MH^r1Jtdg`#YB`>A=;Lxly!lZ`NpT3DXMnP@9yg7V4-b7w)ol@Y zaTo%F?6kj7+&hqgtj?4SR#U~y)X>@;h1SFsU;^1|vJ+`4qXi+C=NH3#CI|YUu*`U} zL}(%xL9yNVJ--WzbfQmmM;W6zwmqbUEa{T78kCBt4vJr)=Rvg>Pf-wbfm=o~6F)an zE(#{{P*QbhURs8~MEnfmcSTM2hC9-FG~pV`&)_;Tn2A!6WR(LHBpPBzpv~fyp<{?G9lR=G_EM>}Mp0U*6UPz&? z1EV>uZyk{t&xUzSW4z=Y(w(Nq~MNNR%0OlHf;{i#xND1#57O@@kvQT==* ziM;I}Od>?p01#u16TBDwKRL0GOaEUam+&?HBM9epQz4uIZR9;a+VRGiF8Qces?Fez z!%^3iAVLDvSYpl4JfJA2-pgw;Aqfay3(@eoqLyi}c&vauMbPBw?(XESeCEJdX0Qwn z0KY(8jloud^+IkaWs3V^^!vX)uLX?*Y>FycJG3+@a>wz%sBF@WQP(MO1qB)fGX)KW z6rVFdFE528Et)rT0n37KZGHQVTxJ`?_X$=povTIP9o8(R?932oHq4!kEC*C2t~ch zWl@3=Q}wF}Y?lb35WCGz-7Hi0PmELJBw z1!f0oS(_UhNeyJm*}+sU65MZF>z(XI>suTQV|0?Lg$?ugizo`GVEQ}4+CfK!R8DGl zzJZ~Ar+hc#w`H{j;}2--jUqu@9GWlGCp2P&?AXECsOZ9bVP z7NJoKgM;J6B7}tXakP^F9-*MvoGot|A6T9&7bnOSgSkv9pM+K&+*=qgcXdS@vu8&j zkJ63S2z_cnS_C>Rs7C|T@%-L=VSgpakvrE2vZY*cuH1~Z`H9HKuk{|+-k;t^*%-n) zq=gc<$Os;@Nfc9J=}}6HY7Z)F3cpI%nkF~Ni5TG4Wntmv^&E5r9l)mn;AA>8mdU4K z5l_G%g82h8CtJwVI4Y08-=G%`7cQ4e4#3?Q&KIzak&E03uApg4|3J(+N|KW>IVn&m zv;)A=Xso1Dej9YE^pkdrj$J!8mYYbPl=rzmnw&BnrD);OuO0#li0V%5n2C-kslNa{ zMhDPg8`peALt0QymyOEOc+fLnJYC2Qe2zyV8^#=SrGr}AY6GR9$b>Uah8 z;!7g&H3EEz5@u|Lo1e#4k@x7slh?TAG|#EmxSgF4Z{*e_LKDv0=XRH|hB5nFu9Lr# zr<*Orr>-rRGoxb?XDEQnQu$$eKlx5@A$)SW?y!x=$Mhng%JFe?B>cS~YVqNObm`t0 ztPTM_pru?2KM3q?zRJ8J#f@$yI^GD4C#1HL@17m5h}c2Gk} zDxo&#cm*x@t!}b=LwAdT3a-@!Cn&+ia~IkX3yEtjgA!$2=NwY-2OQ%>=JKvD?FGfOY-=38JUItc@|L}`f7O78?V1DgqTrUj$e2{ugQ?RCdUxja_t zUa?|qVl3NLC=RcHId}<%UV))N3@es(C3l=l=JJRnS~$%2h@xT>EqOE%a7ydJNV;0A z1mkXxLxNX!z&UGeT*+H^@rewIo$t|TO;&w1BNwT3JBiVIg z^Jv)c8;Cm#(#myk&}kGe(?uvIMjuBN8v6Y3K1DzQg;N>4wagLHX^A%qX8%IU8))Sp`f=XjlYM0 zWRekGK{|QOSW?0Fu2(Ob=;1QCA)@&x_l!0&8pR-kL7)BjHYi1$^|wn>B1XlO#s>#8 znRF)I)!c&+f4Z4cu^Za4xm?gMy)gTrZ{S0gQ$^9Cc*{-CXZ9OLjJ5^a)por^BgjR> z1p*?Ls%Cni(J_f6m}3#yrc`0R!fdtCxXy%XU7s2pA%TiP8#!9CYBX`StzB+`n{7sf zL#+pm9CHZ-gqXNotT7$QR@4AAfayCpSew@)N0rIt;@D(M#F)lgo?L@^A$Gf-MQ&Cj z^Tfi0Ol534a(QcFQ%+nmt$Z=ed`ikrd?Y4j+%9t-u(mW^cjDcFlEC_QeKp4x8Mb3X;zm&+}X7tvi<*N2DF58(G*>c!-dU=gZlg zX6>17ndAuLsa|?6n$b@NCpo*=S@8i@ryuHrXZCurb0zo|=Tg2N^zWCi z3^O~MM|M3plS>=X7TF2>(H+0*e_8h(RN=XzH410CR#mv}c!egr1BNe6Wzu(*`W$BUjaXxYK#~+>FUhq$Nn9 zi!B&5FdZng6eT_qN3}1~bSJTyqSjf$`~27V-4%OU!68Ql=9kSa#Z9?fvmu?1y;zhe zNKt7L%?Q|57TfdfG|+Bb=_F*-f?3FPI-_Pssau~*m7)(7HFaOpjRC6XG>*TDHB9gfc#1CdyRF^uV>iFwJLkhq@FBi0JQH$b9=DY-tE z_4o}A3hc*HGBtppn3rRh%7swIxbW`+o9F_Qnj;?l(6vWF=VjGk+(qKl!2`PG&ZB8rk7Ph;YMoZNGveQ#E-QSq(IM#`Co52*ho=jBtt3O5icev8!fQNN7*?0ufbG7V}X0(sW_~VLVXTWW}xL8AT4i+gkuNrv!A3-sF21qx0Lq!gV5$ zXxq?Oq*FJF42M`oE&|YjWy19zXPgtIDxRHUjZ{dgRDNQAY9iWI&&S$sECw-_nt?p5 zI7Og!GNf{gOl_6(u})fF7|*43b{d9L+GVa?DOI){X$mB+j|7`Wqm+Bm1r#IUJp8pC zf0yC*(U;!~bkd=eOuf_q(19F98o`*6lKW>;iB4s8S&|ck{;HW0!a&^CpX;rnS+yH8 znlY$f=-9BzLF)zmjv}7nGYTmdI!RT8Nn4N)#l#h5AS2K&a6zo_NIQejX7j`lPHB#z z&=KR1hMt7LxONJDuCyJ0xxm?KL^$}KJWSGD1@(I=U?tWZKHGh1wtsP3n+2Q0BR;RZ zJyWLWO2YI*Siu%1q{hZFDMY0TIz;akhoxasOKnhTqJ)rdSMmZD3LzS`FPnx9KAM_< z!HrtGlqrI6p)FrZprbHU&LA7Z%DZ&3eM|?zR(Fm~lrYMwu1m{#fvG(*1fQsR-c;5J z>`7gf1Yw0SjHIQzLm5Vz4DN2c5++@3(|g4LJLyf5zKlU}9_}Ldit4(WUHNI4OB51d z^BMEI;&-)_$>>5A?DlS`2fZVn;_nKU&B2GVRbY_}uHF`jdM=KEESk(gZ-n1emI{ev zVt$6ATs#Lq@ymwzt(Xps>n|@5e}dz3VKY(J333KD98?FSyjX26Xb7) ztujcJ@jjB)5GGrXonw}ZJV`g1%W;mfsV*7-c;cRki%bp|$IOLG=B_Vh2o!zSa-onL zNJWO?5m1wPffQ@JHOlYP$wyq0+>|P$uPkSx8ygJcF|0uY4Fz*~*ZRGy72(OQ@BxE~nmo8VD3w>u85c zW!%aF(VjHEO{jDj5Xz?o1&4jK(vR9BXe;-Si8@4mLzO~Q69q69DC|z1>zlXP0opN zPROqfS@ppQk(7dnHB_IX3?rL|8HVhMXA*ejtq2Fe>PL-HDp^L}1j)+f`V$&=NTiIT z{0jN!fns5ACJ)(&EdK!VY5P;fbO|vg_@U)2tH{%Z!SPW@Q~X*xKLgoZwmh*sIao~L zsDzBULgzg*Fd#F?IkMbg1XPdekrZ4egz}lFLD2&xPX@M1R9yrjTiVr%_NC^6Ssp}s zaV?Z%KkS#?>OsqUjT^T1tzEZmh<_ zn}{UWF!z9;(+DI93yX-uBNcVgZVw5E=BGI3L6QjfR>}B|=&7!vyj@39JsV7EPZmTp zXkA4X@)$3nEBU;g-}yi}7equO`2j=(5j}H5rZia0qUIzfvf8b7fcf~-9EPH>@tYS0 z|75~|R92w;icrL$<{86_I2?A`Slhko|F^_v7d? zsSf;_Ipn-v3@tv%IE$HW;-`LlXWj->rsWDLN&qi%8l&4=J-R<+wG9N?-bUJ$zyaa24fF}iwUUBv?Y=iowvG(22R*ZoA927|~ku1>$v*UjGDV}R^x4R$`Cp3K+8>l)aVSFeX zZPiM~cxt3L9YOYu!sS!3F)kGzN)1}$JsWj0-7AUGnZ~6hSM1n@Q)nXVy_jxSvX|BH znKbQm9bL7Bk#WhT`8NDbqmbq%*~0C@tc?f8VEF*^u~GDPY<%?@K!Z0%5Z#ci8xO#K zVrh|HRU|hw!#EK?WzZ5uy&PbT`c2~6X@_CN#-}V3H7~JC=b!qcrCg6GPGB**_*3FD z`|2XF(_;V9V&=Eb1DEwk8lUuF%ISWtRWWrtjT=%3ZCKF|bem|xgeQ}Qffx_vud2tS zFB60G9A0J7c?{->`a{-V=1(d}s5+OU z0!?cMn9lk*rko=iEFc;&h-d`pU2^j9N0GRrmeJ&7PP@{49?BqcffFLEv(*)cQc?)h znqxvv%dF8+y)DR0`3u!dwJ;TpC|wbwM7?|`@0pL}XRI*RnP^MEiybmpN2g2)e6!0PL zB<)?|Ls*u^jJTv?1UT4TjR_Mbl~Gt>b-JlEy6Ae7WmrLOaG=MvyM12QQw}fdYs1f~pyTmhnOY~fvB-$XPq-Y-E2e~eY)(ip*X@)f9e4&SnNES?_BNraD z!Q6uBa?*R{(zXIE{&<&j^9L9TcXm@9It0E3L%HlY)NYpeHy~AUHxon^=Bq;j?@&BlEBpEff&~3xiI(z z_a>PdPG$35$$kj2At|y(a0?8M-V>=(v|lh1NhCtKVpPd-b3dU}(tNcW!x~to5oxfY z-GrrfA4BUypl}?()MRFHWtPfW$>^HccvZ_?uJ)|C7H^OI3 zpA5(7RJ^1Kdhrwz{t+FG5KSqcs$J(OV;CpyMP!v=E@9O?`e!N`OHeK}GY05C@LPT2 zjGGxPng8pswvU2LIF!nlf0+U#{a}5B|*qBQEwDt zONccxdDKfH7$V-rOvG^ z2-%GVy0cPD!WUto5sgG(P+U1t=mcz7`kcChV#);m4Y^jHCKJ?>$8x%?g73q(&DniE zyT>c3fbGKrS}D{x6pdVwx*w<=FCbLHs}OFax>0Y5#hYIxh#c`_j`-M(RU1o?1hEg~ z#TAh}4y&}ml2ErJAy3XGcgv!=LhYomGe%g!L8QIEVVbM0mXBa03*o|Q2t^pi1UOes z69WHy^Qz~InJI3qQbIuEz-R~VoeNk>3OA`vuxmZZ&ApdLYGG(gs{pG34qkpjG<%*O zxojbSl92o*1{)m#>T9VdU}i9A$XOL-0X)$G2%9;b97Sr$XO6}9D|kE>JnBMLgb0Yf z>T=+WDv5H#;m!!-@KfsKnT=Xb7<0zRiGARspfTqtJE4L?7tt#bx!{3m(pHksaNp~b%}U1cIg zBirt6J$?i^7dhRr{$F7_qw9kaz!n(=nmR6k*WtMbbnrYlFrJ{D;!TQ#hyZ^3B}d$)dU~Yo{_}V5Vcnz=A@x!){PMgS8TPI@Byc3 zNxY?(Crf*?V`EVHggGL+6)wuS4mK`aOv^!ug&<>JF;SVwMAlO$v&LajNX(>BD!;w zwCBN%qJ$wCP%Lv6(OtBjjrcdFq%%F8A!(S%uiQ`C%=UPuhsXXAl&-q`muK|F?Clw_ z#I&RZI3iKRS@JvYE)Y(j1RNc7x9B-$Yu;B};l+?y7!j8Mp9|$#VJO-G8@5WiK2mfq zuKqEQ>$ftKzOEH*-f*5J7+s3drA2L&A#aG=W}7U$M|cy6DJ|ME684p-^`Mc$;v15L zu?3>0buuG34Tup;968P3XDuQkA}8sFRYIzuTxZFfOV|h<<&sB(vi#d@$=M?B$N=(m zHX@F0`X|{VZ{i4VpB`=1KKlIkMFC(?<|7_FOAxg7h{VM1Nx`C4CjUsdi#s3WvQW@0 zmO3f{^VrNCJ(>){^A7_;>J!Rqnl!R=L)GZBFfOfxv7l>UkYY4YPJ+bQ6>RNlOq#r* zV|ww-ulz9}g?P8nwb&t0LL0e{m6C-)K*?4d1g8=Q{+?)tBdLV)$%F75V%nRvR|(r7 zYd}d_VCOhsCljP6SFGD|7$BES2}5BOC*!^0VQxfXqH&2~Cz+CzMoWuH zmda@*vmk+L$u#)QfD?S6*j_FcrinQ7?s!DzNz^p$WQ$3a;^O=31?Fx=MW(J7*kd}% zMlQ4;%{UHekx}W1o9b7e^WoV(tX?I~h1ux7P|q5e{ELOTq5Tl&th48koScXRi6v-U z9!pz|rxa>`T3T+|mO{2{7n@YaNS$eo+uX;%Q=y3SNNl1$wHX#eZWllo^f@G#9d~46 z?lu(7(Thk;eq!QY)ML6#SWtI!D>z?uW|H5y)ShT9MmHo-ZZf=vhe^-;#(06$g07sc z9cz=IwDBo8dUaH!qWdOmin(eY8!bqg_T9d+5D+jPaqA0DZq=SJy3-V-m5K;*Th$yZEh z(R4(QmzLZq{nl9qABpkhy6U%56&V%{OyJXtbIlY^0Y%PGFI|i*c(vQ(S`?jcJ#0s@ z=7ifmV3mHfL4nY0(8QJilLRLiD-^2t@53?MLBO7AJ>@;fL4}$$IT?f+oNUGVBt}Sh zf{+R}=%GqHB&?s2$8PYQcpitfEzYKMv5@5Ug6GiU;DT**lw=oh&5zO9n{L26l{kz< zxhUDFHG@9?Jj^b^;F3Fv6}io;;Oodq0aUy!sRJg6deICdCzIF@3%)GCOh38tHM$aw z?Tuh)OE@NSwgsA~@)(!GLLy`&6X#CM+Kz#;=1f53KzD@FKZC24ZV{=^Ekl%IunVbC zkU}6ZN2oGsnoW~W^Z|re=V0_zT%xqD!hsY>324y!AWK-UNY$gD5q-Sn?`fA2ggp(jSV`e0h>Z z_&V6>wbk~LX>mT>y2J4KMMzc$xsK_Ty8{g0cuGG$Eb=TYkLnW^#27K+3LND`1qC1R zO0j2@8Q+UQ^p^*YVt>O=va-g5y%nYSlYA*7N(B?OFI{@-VOlv9Yi!ZfG-XEbne;~Fz_lA9#Jh8$9W)Tx!F4GA~axhMZ<+2nb?q=-OCUi zp`oM%W41^v1(u0ZdXht_X=GhNMZB(ze+qqZVmiyW_=C}wg6hQ*jwGCg z+N>i1NY$m!+O}h~de*e3JtD_i8ER`e>F*o6Vvpu~Ggx~EF}S$3_G?K`s&ZP!aFkeX z+#TUC`IiYyF@q)aCN#*ut8WZB3GoG~-bDxkwC^k6)d7h~ZV6ch;8IXclo3yZz!?HF zHOefUqv0vddFfr~IDkd<5j!(Om~liO>Bvd7MI^qH+D77uNme;BfFtHU1N}h{zilVF zVd3a7PSNS!#F0bx>miu|Cu{lZ6a-RBEsu#E>13xRN<8AuUP+AP z4C*T#LBZagj$kSp-#~}CPM=s2kJL|eEPMIx=B&1sP4Bl|3_X3v9HRcK|3ogvliwDuFwOb*b;W5 zxJ*_mh@53gbxy;W#VOBRXJPoH|nCul-~=m^@$ zMQ-lP{?3aC2o;O%#eJC=Ks_lF3FFlT!$ zRc9^iT2^~&VZ;e6CpMDyfBcyP#-#MAnRvB3FzM2mf)rasD9cX^T1`wD@TES$ahU-% zB}oK12a2RA02@c}vJa*XtrJWjNnjq36s{MK$nf*w5qzg_38nD?cdNwoi2h`4tOvYV zU{UNg;+GoKYaL{_y_MB-`q0bxSe%$U9y`hr*lH*Q33j}eJ|Fy%q~ES~KuHB-=yE)a zGcaA?G(c0|q%DxAGhBlnE~anuT%@De=94RB$m)cT$rYR}QtbA9p7eiYXL!d(m=<`XOE^_JzbIqeXl-N*AJvaQFoM%sogmHWHAIWVPGUZCVp4n0RaXfjeAb~UOiX`M zjVi_sojRi&{lQ$ao803ScF&LBIrSRZv2(O`;6*R_MPucWMFzy^a+#2)=r$t?{NpiP zwk_tYk=aWLauUG|f0MFsSDi)Zfqq_eCY5a+P<9NjV@I=Plq35(C@q8W@7>Al8Cgh8 zv*#cW8ft0h9aO|%FfFwZ)K7FJy>b*G7B4x4m|7&4-aP4!`2#wkbsJtNG0f+vY}Dhd z2JVXUuetBxgz0d1h7WhVzhNMQl3PiHNz71R=3*)i-~q73soXjibAo>I^-HipSO{`L zb1&&-pWa*JqnLmhnTugB(m$z7g0teOh?`Vs^+l7|V2nevP1-GBF_yYE&{sr7$j-KU4F8^;PzWu89FWhZW(blG8|#z@eB z>xm5uiXd(^<2p{1(EJtKl4MTe@FhmI$P+;o{3S)8RE7k9Pv6deN}M@^sO~KkTD|yI zvIzd{f-%VAgf%0zWK$FU&1ip-BpO_Uj77CZk!LciMz@ebLR@wYnd@3Dfp0RE7>2}@ zs|>kQlYrD!RZ2$B0xyZfO;sgnRfHYbNLpkjomV7V{q5+IfnF>)(v7UTz6A<0Rc0b5 zjUpCf6fkCBy%00Cv^qV>Z0E-*aGhF;JO!S}YqAq7fPCfJm%9y>ZzYaLX=^Ixs%43o zp_1#E)R6}|xd|jhKN(Ov1;YY-Pt$wZEgWZqdpdW4_9b9#kX5gfYigtrL!=-%a^6WzRA?`5`#-PKaFOucL(8PLey z<~lu7g0!*ssfhybk&An~l6!Q&Ly}7_yBE>gLV#jQJOM>w>$GJL0cEdaDcN%L*@#|E zHY{avn=}|KkV0?36*{b2${e=SNz;(9R=h)z))J&P9YUXmgA?#UM8$0I26Is&T z4aoV)>D;b!JTcpT5ga1%%*6XN z?aRUl*S}19)$)w|>zBK3G0sk1S_v?jOLyOZT+wnyuOQke+Y$??O+Eo*Vw{OH#dwhk z&JnME93JC9@_LTxm>UArG5C5#BpB>MOVfm*YT4MOC=c8T|A-sN>at3l#j|zNfrlEp zyvM;BWxIB6i-R$GPpe@h@sZf19@&B+N;%heO&Xw;GTCuns#}mK*Y2| z(;vBJJdyh8)v;&~lWYEf1iQ|Vz=N4;61O8AXLiJs&x`#?@S47+UnVb%sdu zuCY#DCk?YL5_Xo|lSf(NLini|D#xjpgEo<4Y>FNOqe<45L_!H+Bv^=lV6iYq=3~jL zI9ie6LGKF%o3ub+peq0;<6yoQ&gb2B9A;%1CJ@<1|RWG zuZTRApfP128Awj12otgC16hgzM2Z%sUyXLEq`F}IX*Iy|)8U%kUgs%y_dJA8%0!sM zE}mbFSaakauBkeIbFhLB=mi9ol3#Be19fmR1Ba5L8>DRL6XqOLW5p^wQ6@Rjqho3 zIB6g4(wmbeyt-8^?=D!OqdZ>(xkjSVVc|y6J(7JR zTRAko%%ZWE{f}K2T1rMK7wS4NnscXH?Y(!nhXj{Pqo}9r&hd;= zIHCAG$!d-1$burDxg?jc<98GbLDt7re^!((wriE(mp+q4e@4Oj>LXsR{}xcNjX_28QgK6TE5P81`txSn>IgdyLpSjLZo~=GxFAgyY_aVI-)4RRN zW$0Z@tWp4WXozV+xVDXwJMjzV=ry=nK$GKH254Q-{9tfHSdFUt;*PW9&}g=d+Iv&& ztZ%$8#a+dupYS9l4uE$Iuu&bYF&!I|-%EHMae!sfp>SR|L*k|!2za`acSg7l;VG&+ zlc?p+xswh2ChQ!5(a@5Rk)sy0%$SfM?NFl|>zsfwz(@*lLZ^h&hH~`8v~LVrrmG0L z9FEZq8mZ9{kWaxaL@NQHm{?+B7lNczF2ok_Tn%ePl<7ELlj?j}%M8jfW*F>rMel_I zl){qFa{Z3-qa*Y#3?BnE6%(2DbWw%Kw-iP$p)#C5rVJv#+V)|;xj$6;IEYQJWRe5e2C)naQ)gLGiT7L-Khd|*;JwjW zlZCB14qo1k5WO#SC2`tR&X-?`?fBE7&VY4tmOdQL`&Y$Rr;#sQR>t=$_=H{Y5oZjX z)$3L8voXOLD+bOY8fUJTJMDRAabgBOnC_KuRRc7`ck?nQcJ|t>2+oC0_xvJKYyA^6y+#1GvX^q=iQ8$2I4bge{fNIKsBxMhQ{WQ`-twjWGv$fi($u6JlL4BKG* zlw!Cd%Wns5b7LgS6Jt8G89r`g1B>v-7eLn2?5}L8<}98jbADgjAK{~%tWSTCi|7JN z+>i26#8E(-*d?_Z>s6Nx=-Asrw@Mt4Ddfi4#>I!TQ=zzNx{24v34)$pbsK~sUj^$? zW+BGg8!e>AbD}dRo4LDcX1^_ODnZqm?+CdH5tp_SS^z|XvU6{XtLA&v;~ZtO&_KU_l-AuFcF4eS&x~G z-yCk)kn>h5*T$6*o~Y_Jcq^E7J*pz4%#t=2*TdjIJEZ!s)^OBrm4SfDnTW-xs2zh5 z67CBBmF#6GY5LsTzv(E9)D5wyNS7bkQZmoaMOYT8An8N^<(l@1*RG^B6}<=qhZsdg z8!ScMAPJvAMn@E$b#AC-OLsLlZz$-3(ETYKrs16Oj90lt%Q7%ppd{`kxSy&}KvbiB ztBx?XS3K^G#iA&N!MuTtQx^c9%3%^NR0~iV9wwoeS+UaGVdUB}4tRvUgS7`&oA`uh zE@C9sGrCY3cRVbI!}vMxsph^i9^kBbXUn_RZ4SC67CQ9H;T0LHyAIfVPicINHy>ou z@sJY-J25joOLtGsA?0S7)qz9K@W1s9&GCaR2WtfLl%k~A8MZ3gXp!716tZ3pU}BB*!@LqChpjc-Sfph+mf;< zev!>Gf$4Y^xxfWbyYv>t)0c9Wp!eRiu2|TQYpCUbf8;=2zWNw~XGFg#oFn!a$z(@) z5T4tOb>qYO@HYYkD20hd!E`O*NMOb8qm9Gp0HtTenx!?`WNU7(ShJ*TX@E)n6=>6~ z6Bild*t5$7ptSSkvF+Q>cx6 zC%JlJ!5+suJEBRFRmU}_EH6`s9BbI*WZ1C>2mvc9hkubA{2e54nV}_mc zruCNed}Ai)q=bW?RgOvhuHiPb0l^+$L(We(j4ZR==VB)P@L9wL9mZk(hD ze+{)$8I3*OMLMy{VpT980Gvw#IEz;jx(LpI+i8itHP|sTcAm4eea^TzcU;5^y>OFW zHnj{CNg+moopYAX*aGERV#H3lSgivy&}f&;wvk$Vp9RzDCZTrV*4|=vl=~`a+}M#9 z`ZOB#2AjLCMUbRNZM5Sx@7%a{L(j%ZwRLP~5EaqyBa$SpgP~%A&SA3I=|Sqn2_ReC zmOi{PAkM%bMG?VBs8Xm=#kUiBK~&cb83_hJh>A8^ZAwPMfz7O zedg+!eHoO>;|958$0=Q_x>k1%fH;@&X5;m#9AZz&j#VpHt?F9&qOR2|mm$3|fhdKM z-BQvJx#UecP%x~QLQoi?roZTww`oN-g7-ABI<$k; z4N|O~o%j}Lpbs&wUBJyoOvccwaj%VoOyL(iz~Mh$5VTS)ogR10SP`!yMnyP+G6ug92~Bu9eAt6jwy8tQ+G0Z z5KG!X#YkKu=NC8`pkva7)NXXQsMDZw6}7}bjaHzRmp|6OwYNLjm&Fy@BJv^Mk?{9S z8#=x)Z#?T{d8ny_PeW7)sf-Do@iEk(q%e3XH6ea8{-tq*@7nw6(uXLNuC8|8_;m>n zrr~#@-7pJlRpPbHRD!^f>~?&G>?3Z)!rlYy4p^Mc+>;q7p>4;c0&qJr9V7+{9=fUQ z9Aq}m7@?dX7-uzk4f)3W)_?Kc0%(X%Sb<)QqdU1LRpbHb6DZp2ePMz%u>c62R@0wT zw6g+6ZRP09RGTy4kd+oc_3L%R;L68ek34O)(?WYE(4+w5&7QMVVl@28Sn{_M@a!ta z3zl8zm~Ob#vYXSD#-^-n+H$k+%;hR%T1HcyrOX(5XzFCYXS3rHD4tel?fQU6wIEb9 zYS9ND{TQAL&Xx!Sl|MaOhlfT+7_#|s9pLx>h*=OdfM<~xcF$s!x?Uql*l?wmT(r#NzQ%Q6KG4;D>$!iWyuMyyCgQ@gg@N)UzS z{dUb(>!3j76RO)mU)*rrmaW_SyOZ1t))Eo*5J%cUYF}F_Wkv^b6Yb04BW>*AOAmU` z@pb#Io$LDWN2WZeWr7bOi4m_5BF+g2F~u~o(GxNacl~A@m9LT6Br@ZDvpE&fK^8A# z**~{VO*D&>sk!acDdLe*OH|5xUTe)fteJIKvxKo^_zUsKO@ce=OK_W2Fu*OEz-TL} zH#Bi7vKnWgWhE(bv4Kb;63MFWA0f?a`LuILZtIuGt4}Pk5*vM&VeR0mT(;?iPC(!m zr})vppIvElSs0`+OX0sDl#4VnHBd3#32rP;7^P#LM*_Z!P05GH!K>(;gkilf@F=>< zq5f<*Rn&DCaH_LKs12MJ#L#FrhiV?WNw@~FEL}l;l%nQ^B>*kUHQPLkPH@j72fB}Z zg7)wefc;(qFna88X+gszjV*{wGHPkzfTc8!oFnmbaA&+{N-_$W51)o-e`uzVhz{2i z7ng=XRWYgP?uZ5uKZ^2+EJ$MHJYuTT7$u>zz?RGD#j%b=S$-zjP{H`ohn2FyM zJQkKYseQ<#^xlHA+8_zOrLiE-FrPysl)6sp6NHh(Jmjaw=l8R)3#C=AO0Y;M#MGuN z7A9p3!I--o%LxJpGd~xzj|QV-*n75mCpBq*p$U3*U-#u;$I5JqZpu+WkxtQ{DS=w* z(6AsNa?Zh%zWie{ip zb>tn~7$G8-jL|$18{KS1rH@ltShf~gYa8+ndjRtWbus+i3*d8Y!6)1GyS1=2&IPoa z@qHiQEF-{1VxU4bx`5tCkZdPQFa}AQej4E=J3SxvWtz87lPSFt=~~UCr3ATpu{Yci zVT>~{UlN*=*cwu20{SVqD59i-%a8T{7dl2P@g#M+$k6A^V5!H%|z$+9sL`-lVH$xbL&An-K3K4 z(#L)ujmd&P=j zc#Pu%UC7_9@VrLz+L_W-bnRzN`O!00q|Tz4Vd|J|8!$lD1Uyq_{o3}6RBX`iAqiKj z-y2P~HCCj62)ApJ zQ1un{ugv zOpX`Hg>QBXR8Oa8GvzF~)NLF^M^^r#c2l7^s!QS;O-Y=6s`gx*0uDaZszU-a)EK#T z2d^8p$t_>Orx$~l8NqcI_eq>gQcRU&w0L9Ko5CDyvxC$6lF^Ock8~#9{UEXq&pk31 z>Y6xaS(mtvE{sy&n`VE21oFO&xsiTTBwPsv1wLP{~H@7cr=4TFL-0O z7^I?^NAYXXb2N5oblb)}7TS~6L85os20UJB0-7y_YXxZk=>r&327Pf=u182CU?SMb z+dOO-Oigu~nlvyZyTEucGp4Q=UdZ0)T|4~jyK#2{i@=yP^NV_y-Tlk=ls7M@HB)wEx`w;LM&vjtsrt+D zZd2cHb>kC(73Q3&TiCa<>y*Daoj9e;=tS=9v`;$5`2EpdJ<3=@kGS85Ex- zpU~W0C3$H4vkeVj#f1uyMIfKpsyhqX2|cL;`tC-v0lPiv-e>CVD7~f$pz!|R3qbF3 z$-@P38YX(oGPhLhgA;ev;*<7}Nz>76kklQWUIdIS<`-HFTjKX{udRa^SRR3sE&&4( z9O6n7B7f*XAbh^+fzcvvCq*YmoSG8glPt25?wg|O`B_LZ$QLu(xE7JreXIuw3LXg_ zF>H^}F1!ydPn-av_~6y8`bUz$TfBKZ+ubc}gxB0KGSd`MCH;(-*V1-me<&_RxC>u} zt2~oE}p~*#Yv3IJ;+vtAlm}w)rX?80KK=0UU*K^ z-P9pVRzXHhEEc9F7dzW*EC0kHp5{b(>=8p~49iGNloem3Dt6|kk;DMnUi@vk{#AAZ zb zGOcZdIxJD79@9wls3^RM?O65(|l<-7% z3=!@pt4NQ0J}pPxC9%zwBw-h>#J@dQms`>D4Ia!${SOw=qtmN{OLo9qDHdQTKsY0c zcgo71b<PaDnSH>4{&H8@f{W(!h+o+`kJTAT|{CwKU| zG)$c&uYBGRn?Nl2x6;J-9s0tztMEUa7wKzbOKmI*BtuqZ+mP(=+K^0rX>Xh6(zp#w zKluw(DJp5)P_Rb%U9JFt0#4#EQt=XEvf9P2_AgdfhI-N!VPWWbs4HVdJHKIi(xyDk z^;dhCftZlS47sWkqP!3PJMVIZ4h7Nkb%x&y{Oi*$QNEDx+|;*8+kq>#A#Kg%wZ4ab zdh5F4AG9u-eR4CNm~>=G>IIX>Sqe*_Pi?h3xGZ#qJNmYEYB|Dt@D6Kz?4vgwA>t06 z1@_Crd0Zu&JcX4yEZ7n(Kp~Hi$|WBaG{>i!^K)$`Xu8vr7n6WdGvT)9VgDf#(2Ox7 z?L*91nXi*)CGSTXC%^l1OHwPkjcyBXQs%(`1brsmG%f0mt&lVGPz0*g-vAX(fo44=8a|t4VObo`cBhS{i>?KQu@gizfy|XP- z2lhh97S{gm$MAkknTF_MBg%zDv}&25r_|v75TvO%JDoT{wBK_CX~IhD6ko%k!*_8K z$3qMH`&$cC{-~@YP=`LlN}OH^F%Af!# znRyHcySSgUy!o9#BGnT#1xN53CdG6Z2z(>*e3?(~4fMl#19f;OWK0}Hh)1`5?%<6) z0da?*s%fE3*A)N5NSAOdPC}0qO8W0KEctA%v`nY7r%rg+!wn%3iLz(;p&>c`&CiWn zB|&qR`Z)$?k%sZyDHUn@$$3cDPq8nUl$Efn5dWu{A+=SE9f`+I=aXgsOepXfrzEx# zS!3)%2x?{2Iw%^@OAFpR){UcW&;&?`=Q9}wk9a_wMMJiC;WTlw&PfhHEQA$21n4K+ z&}uC!7v`Yl9f}DjN~rxk93gym1uQP{5;V_3p#bzwz#c(JI@6hK)g zsaOy2WV|v98$OdfD!(DKks)ar%Su9P(d>FUYy)w`y=<+J*JB-m$KI0>wcKeo(hgZ| zO+A#YK+aI!Ay5PDNC_!W%bl#P27etK^UYMpjO3WAYo4lhIYd{H){bY1M_Q+5OoKzp zdx|1{Yj!`XG?fiMcH&v$T|yWXl&leqn^{g2p?GI#z-_uFP6GRr&IRVU-D0 z&Xr~2IkvvY#8Akslh4v#k^QRP78l-_;|WmgfETBk+8k%WmLN+Tv1*LOYQ_`7CR6zc z)2?x$q<74ISloH7j3!^~!sv25J4uVDRrHDZDXlND+gIEX$6ltf1sPY^&$!*uEJ5~m z{Zt)8xeyJpbyz7Q&C167m5OuHm#g{a+*8@BC;^m2&6gBgP=(sqC*~DJ&))@wfD?Lt z3+8ItgVA@(jihiSM0Zwntj3#sSd|)9i%P4qgu2zz(1d4j3-cnM0!pg5B~)JtghL?O zWSX4979)5dQ6iGN=_)~q>Wh7E_`*wDt>Cb#~|mPuNXuw7>sxzlQU6 z3|s;OU0Y>K5ILn5aoswE0H}|tDZJh;7WjG*gM__RZie23R;b%>#!e5n7&oR+IT}Ug z4?Od4-P6+!*3^%KL)%!L7&YFD)DlQ2Qo2#O!Sj~F10mTAJ4fph@!Y(uD<^8{E2l5k zpY{wFHP}~&iou|*MgeFhl2()@dt!j!Ig3x8BxM;U-3ye6SP|?pAVjx8M6bjeUEtz$ zPnhylRS{>LoSBy?Ef?btuXL%#P^XQXj(O0R>Q1M4t5&U`~v=Gva}zcoI%=Fo-cah;JmiFaiN$c;4wjYAePja(GI# z2bw*iNQ)MP(QO73hOr!MT$5xU83+=yTZ~wf;Gzq~01=;*w5^%j;6+B@uPEYVErN4n z-Uok2d`R=4pjj-gn`>Z1)7`al3I?5=^Fr2=^UJQ3B$#pZo7Io5#np^M*-Q?GZ!R;0 z`x(#+X0N`(Je$XL<~XU08XUHrX4nM{wL5dH2K3aVNg6LlxHF09%Shfk`+D&Qc#ZI-V8@8}uRRWJy{bAxOdVpYTS<^H~%+m|iqV zHYL+CX@k2SOq0c*A-Tg zV0iGENYBHNkWC3K2GMZ0J*lIFqd3%@(VQO+D^(+F3k;DO z<|C0?61B6ncql_JpUf!5N%)}crXpW2nkWbihxabpG|LRh{2G5fDv8u$9QdaFZgwT!8EoryJ|5#=(crGC2%(A7 zIkj2lRm?Jp_PkD~z^EU&Wi%9Mc(|HLnUrFLg7*KXzHQ-K_J6u*TR0TQLxqV88G5^j zrNkB-=(g=eqv@p;wj+I)O3SXHA4iX4ExK3es47!2LD}i&P>G~Etr*HYmIp-sS%2Iv zrK6wmMTk^!Q>b{fn1$V9wF^XVRv&E*$J!RySAQ3kZ-KHs&a57!w-iu=aai9ChN0K0 z11)w?|CJWu3t?+6+8SQ+(Eic|8lq?QpLQ21D@i)P^CU45YLGzS%g!^;1~ig`+7+TS zjh>SC2b%r}Vy=rD9lZHYCgr))=wOYj1o7ATSz-YZxyvvXBS;13v@CHLbD15BG+?Xn zx*wES>w7YehFf~E_t?d9=iS9=cl*bZDM9b%oymD+n5hikqRzpRxdaGNi{ZNMFom=W zISF)fb~$f)UkPWpq}$12XQ%J)}j@-D&SnmahBStdm za_`b6i`dkauoT$>+)kD5T7ba$0&k5{@p$nSYf>RogPVgJwI*h9Lq(rF0BF`1jo(gFQp{ydc`W zx=T6r=yt?QyO=nt)HG{U%Mr-x#m@FO*8rf7x$5;~nvbi0)@*Hg_k%iySRpXT|^c4HcQ5x-<>dTz@+U2S$T=_JEO$GU-+md$MZ7@ivTZwCdX+;e1NuR_*z zW`YI2$MxpWD^{eIMwp(NIUIANdo(OtrUVPAkt}A2L*6rFQVq>9;m{z7lha|=XjnFA zp~11m%%$_rBjFS{A}W0I;gc|ub|C{eT&VuWHJP|h)KXjg#_*WDFrJ5EOyc;3%t*;< z@()7etQVyWmRe3<&wfi4#|a>|&^SmD@es9YH&AakW_FZXugBD+8ja7nP>sPo^9`_* z`!UG??UqLv&obFPI;CR2Lf6_=HnP&v*sIYnor-!k8s>h)iXbwlZm687aHv)!Z|jZ_ zEa*VNtCbw6Z}86B=+gs7NT)Ba7md$En6K`|m_n)Kuu6BVaqR$dpPoM!Im&eNDUk!s z29;6QlAeMg+9pYLP6o*m-?ork#jXqD>}DUa%<@p8t9ta7N5V!9AVu5b588HdHUeqB z+A9@_7zDsitw)+;4&HWYe={DCmGHzFqzd*B6!mTxFfgGd#Mx3b0T;!ajT{!aV5WCy zPMA|Xq(v@=l8#l8n9+{hx)$|#^dHdU4fpPH+#`kNtefNWZ_b*+3Szu6H>l*&(4(xTczgqe1>p|)@GZOzBEa8yK diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_fr.ts b/src/Mod/AddonManager/Resources/translations/AddonManager_fr.ts deleted file mode 100644 index af9baa69b3..0000000000 --- a/src/Mod/AddonManager/Resources/translations/AddonManager_fr.ts +++ /dev/null @@ -1,2483 +0,0 @@ - - - - - AddCustomRepositoryDialog - - - Custom repository - Dépôt personnalisé - - - - Repository URL - URL du dépôt - - - - Branch - Branche - - - - CompactView - - - - Icon - Icône - - - - - <b>Package Name</b> - <b>Nom du paquet</b> - - - - - Version - Version - - - - - Description - Description - - - - Update Available - Mise à jour disponible - - - - UpdateAvailable - Mise à jour disponible - - - - DependencyDialog - - - Dependencies - Dépendances - - - - Dependency type - Type de dépendance - - - - Name - Nom - - - - Optional? - Facultatif ? - - - - DependencyResolutionDialog - - - - Resolve Dependencies - Résoudre les dépendances - - - - This Addon has the following required and optional dependencies. You must install them before this Addon can be used. - -Do you want the Addon Manager to install them automatically? Choose "Ignore" to install the Addon without installing the dependencies. - Cette extension a les dépendances requises et facultatives suivantes. Vous devez les installer avant que cette extension puisse être utilisée. - -Voulez-vous que le gestionnaire des extensions les installe automatiquement ? Choisissez "Ignorer" pour installer l'extension sans installer les dépendances. - - - - FreeCAD Addons - Extensions de FreeCAD - - - - Required Python modules - Modules nécessaires de Python - - - - Optional Python modules - Modules Python facultatifs - - - - DeveloperModeDialog - - - Addon Developer Tools - Outils pour le développeur d'extensions - - - - Path to Addon - Chemin d'accès vers l'extension - - - - - Browse... - Parcourir... - - - - Metadata - Metadonnés - - - - Primary branch - Branche principale - - - - - Explanation of what this Addon provides. Displayed in the Addon Manager. It is not necessary for this to state that this is a FreeCAD Addon. - Explication de ce que cette extension fournit. Affiché dans le gestionnaire des extensions. Il n'est pas nécessaire pour cela d'indiquer qu'il s'agit d'un module FreeCAD. - - - - Description - Description - - - - Discussion URL - URL de discussion - - - - Icon - Icône - - - - Bugtracker URL - URL de suivi des bogues - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Prise en charge des styles Semantic (1.2.3-beta) ou CalVer (2022.08.30) - - - - Set to today (CalVer style) - Régler à aujourd'hui (style CalVer) - - - - - - - (Optional) - (Facultatif) - - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD", and must be a valid directory name on all support operating systems. - Affiché dans la liste des extensions du gestionnaire des extensions. Cela ne doit pas inclure le mot "FreeCAD" et doit être un nom de répertoire valide sur tous les systèmes d'exploitation pris en charge. - - - - README URL - URL du README - - - - TIP: Since this is displayed within FreeCAD, in the Addon Manager, it is not necessary to take up space saying things like "This is a FreeCAD Addon..." -- just say what it does. - ASTUCE : puisque ceci est affiché dans FreeCAD, dans le gestionnaire des extensions, il n'est pas nécessaire de prendre de la place en disant des choses comme "Ceci est une extension de FreeCAD...", dire simplement ce que cela fait. - - - - Repository URL - URL du dépôt - - - - Website URL - URL du site Web - - - - Documentation URL - URL de la documentation - - - - Addon Name - Nom de l’extension - - - - Version - Version - - - - (Recommended) - (Recommandé) - - - - Minimum Python - Version minimum de Python - - - - (Optional, only 3.x version supported) - (Facultatif, seule la version 3.x est prise en charge) - - - - Detect... - Détecter... - - - - Addon Contents - Contenu de l’extension - - - - Dialog - - - Addon Manager - Gestionnaire des extensions - - - - Edit Tags - Modifier les mots-clés - - - - Comma-separated list of tags describing this item: - Liste des mots-clés séparés par des virgules décrivant cet élément : - - - - HINT: Common tags include "Assembly", "FEM", "Mesh", "NURBS", etc. - ASTUCE : les mots-clés les plus courants incluent "Assembly", "FEM", "Mesh", "NURBS", etc. - - - - Add-on Manager: Warning! - Gestionnaire d'extensions : attention ! - - - - The Add-on Manager provides access to an extensive library of useful third-party FreeCAD extensions. No guarantees can be made regarding their safety or functionality. - Le gestionnaire d'extensions donne accès à une vaste bibliothèque d'extensions tierces de FreeCAD. Aucune garantie ne peut être donnée quant à leur sécurité ou leur fonctionnalité. - - - - Continue - Continuer - - - - Cancel - Annuler - - - - EditDependencyDialog - - - Edit Dependency - Modifier la dépendance - - - - Dependency Type - Type de dépendance - - - - Dependency - Dépendance - - - - Package name, if "Other..." - Nom du paquet, si "Autres..." - - - - NOTE: If "Other..." is selected, the package is not in the ALLOWED_PYTHON_PACKAGES.txt file, and will not be automatically installed by the Addon Manager. Submit a PR at <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> to request addition of a package. - REMARQUE : si l'option "Autre..." est sélectionnée, le paquet ne figure pas dans le fichier ALLOWED_PYTHON_PACKAGES.txt et ne sera pas automatiquement installé par le gestionnaire des extensions. Soumettez un PR sur <a href="https://github.com/FreeCAD/FreeCAD-addons">https://github.com/FreeCAD/FreeCAD-addons</a> pour demander l'ajout d'un paquet. - - - - If this is an optional dependency, the Addon Manager will offer to install it (when possible), but will not block installation if the user chooses not to, or cannot, install the package. - S'il s'agit d'une dépendance facultative, le gestionnaire des extensions proposera de l'installer (quand cela est possible) mais ne bloquera pas l'installation si l'utilisateur choisit de ne pas installer le paquet ou s'il ne peut pas le faire. - - - - Optional - Facultatif - - - - ExpandedView - - - - Icon - Icône - - - - - <h1>Package Name</h1> - <h1>Nom du paquet</h1> - - - - - Version - Version - - - - - (tags) - (mots-clés) - - - - - Description - Description - - - - - Maintainer - Mainteneur - - - - Update Available - Mise à jour disponible - - - - labelSort - Trier par libellés - - - - UpdateAvailable - Mise à jour disponible - - - - Form - - - Licenses - Licences - - - - License - Licence - - - - License file - Fichier de licence - - - - People - Personnes - - - - Kind - Type - - - - Name - Nom - - - - Email - E-mail - - - - FreeCADVersionToBranchMapDialog - - - Advanced Version Mapping - Correspondance avancée des versions - - - - Upcoming versions of the FreeCAD Addon Manager will support developers' setting a specific branch or tag for use with a specific version of FreeCAD (e.g. setting a specific tag as the last version of your Addon to support v0.19, etc.) - Les prochaines versions du gestionnaire des extensions de FreeCAD permettront aux développeurs de définir une branche ou un mot-clé spécifique à utiliser avec une version donnée de FreeCAD (par exemple, définir un mot-clé spécifique comme la dernière version de son extension pour supporter la v0.19, etc.) - - - - FreeCAD Version - Version de FreeCAD - - - - Best-available branch, tag, or commit - La meilleure branche, balise ou commit disponible - - - - FreeCADVersionsDialog - - - Supported FreeCAD Versions - Versions de FreeCAD prises en charge - - - - Minimum FreeCAD Version Supported - Version minimale de FreeCAD prise en charge - - - - - Optional - Facultatif - - - - Maximum FreeCAD Version Supported - Version maximale de FreeCAD prise en charge - - - - Advanced version mapping... - Correspondance avancée des versions... - - - - Gui::Dialog::DlgSettingsAddonManager - - - Addon manager options - Options du gestionnaire des extensions - - - - If this option is selected, when launching the Addon Manager, -installed addons will be checked for available updates - Si cette option est sélectionnée, lors du lancement du gestionnaire des extensions, -les extensions installées seront vérifiées pour les mises à jour disponibles. - - - - Automatically check for updates at start (requires Git) - Automatically check for updates at start (requires Git) - - - - Download Macro metadata (approximately 10MB) - Télécharger les métadonnées des macros (environ 10 Mo) - - - - Cache update frequency - Fréquence de mise à jour du cache - - - - Manual (no automatic updates) - Manuel (pas de mises à jour automatiques) - - - - Daily - Quotidien - - - - Weekly - Hebdomadaire - - - - Hide Addons without a license - Masquer les extensions sans licence - - - - Hide Addons with non-FSF Free/Libre license - Masquer les extensions avec une licence non-FSF Free/Libre - - - - Hide Addons with non-OSI-approved license - Masquer les extensions avec une licence non approuvée par l'OSI - - - - Hide Addons marked Python 2 Only - Masquer les extensions marquées d'une version Python 2 uniquement - - - - Hide Addons marked Obsolete - Masquer les extensions marquées comme obsolètes - - - - Hide Addons that require a newer version of FreeCAD - Masquer les extensions qui nécessitent une version plus récente de FreeCAD - - - - Custom repositories - Dépôts personnalisés - - - - Proxy - Proxy - - - - No proxy - Pas de proxy - - - - User system proxy - Proxy du système de l'utilisateur - - - - User-defined proxy: - Proxy défini par l'utilisateur : - - - - Score source URL - URL des scores - - - - The URL for the Addon Score data (see Addon Manager wiki page for formatting and hosting details). - L'URL des données de score de l'extension (voir la page du wiki du gestionnaire des extensions pour les détails de formatage et d'hébergement). - - - - Path to Git executable (optional): - Chemin d'accès vers l'exécutable Git (optionnel) : - - - - The path to the Git executable. Autodetected if needed and not specified. - The path to the Git executable. Autodetected if needed and not specified. - - - - Show option to change branches (requires Git) - Show option to change branches (requires Git) - - - - Disable Git (fall back to ZIP downloads only) - Disable Git (fall back to ZIP downloads only) - - - - Advanced Options - Options avancées - - - - Activate Addon Manager options intended for developers of new Addons. - Activer les options du gestionnaire des extensions destinées aux développeurs des nouvelles extensions. - - - - Addon developer mode - Activer le mode développeur des extensions - - - - PackageDetails - - - Uninstalls a selected macro or workbench - Désinstaller une macro ou un atelier sélectionné - - - - Install - Installer - - - - Uninstall - Désinstaller - - - - Update - Mettre à jour - - - - Run Macro - Lancer la macro - - - - Change branch - Changer de branche - - - - PythonDependencyUpdateDialog - - - Manage Python Dependencies - Gérer les dépendances de Python - - - - The following Python packages have been installed locally by the Addon Manager to satisfy Addon dependencies. Installation location: - Les paquets Python suivants ont été installés localement par le gestionnaire des extensions pour satisfaire les dépendances de l'extension. Emplacement de l'installation : - - - - Package name - Nom du paquet - - - - Installed version - Version installée - - - - Available version - Version disponible - - - - Used by - Utilisé par - - - - An asterisk (*) in the "Used by" column indicates an optional dependency. Note that Used by only records direct imports in the Addon. Other Python packages that those packages depend upon may have been installed as well. - Un astérisque (*) dans la colonne "Utilisé par" indique une dépendance facultative. -Remarque : "Utilisé par" n'enregistre que les importations directes dans l'extension. -D'autres paquets Python dont dépendent ces paquets peuvent également avoir été installés. - - - - Update all available - Mettre tout à jour - - - - SelectFromList - - - Dialog - Fenêtre de dialogue - - - - TextLabel - Étiquette de texte - - - - UpdateAllDialog - - - Updating Addons - Mise à jour des extensions - - - - Updating out-of-date addons... - Mise à jour des extensions obsolètes… - - - - addContentDialog - - - Content Item - Élément de contenu - - - - Content type: - Type de contenu : - - - - Macro - Macro - - - - Preference Pack - Kit de préférences - - - - Workbench - Atelier - - - - If this is the only thing in the Addon, all other metadata can be inherited from the top level, and does not need to be specified here. - Si c'est le seul élément de l'extension, toutes les autres métadonnées peuvent être héritées du niveau supérieur et n'ont pas besoin d'être spécifiées ici. - - - - This is the only item in the Addon - C'est le seul élément de l'extension - - - - Main macro file - Fichier de la macro principale - - - - The file with the macro's metadata in it - Le fichier contenant les métadonnées de la macro - - - - - - Browse... - Parcourir... - - - - Preference Pack Name - Nom du kit de préférences - - - - Workbench class name - Nom de la classe de l'atelier - - - - Class that defines "Icon" data member - Classe qui définit les données membres de "Icône" - - - - Subdirectory - Sous-répertoire - - - - Optional, defaults to name of content item - Optionnel, le nom de l'élément de contenu par défaut - - - - Icon - Icône - - - - Optional, defaults to inheriting from top-level Addon - Optionnel, la valeur par défaut est héritée de l'extension de niveau supérieur - - - - Tags... - Tags... - - - - Dependencies... - Dépendances... - - - - FreeCAD Versions... - Versions de FreeCAD... - - - - Other Metadata - Autres métadonnées - - - - Displayed in the Addon Manager's list of Addons. Should not include the word "FreeCAD". - Affiché dans la liste des extensions du gestionnaire des extensions. Cela ne doit pas inclure le mot "FreeCAD". - - - - Version - Version - - - - Description - Description - - - - Semantic (1.2.3-beta) or CalVer (2022.08.30) styles supported - Prise en charge des styles Semantic (1.2.3-beta) ou CalVer (2022.08.30) - - - - Set to today (CalVer style) - Régler à aujourd'hui (style CalVer) - - - - Display Name - Afficher le nom - - - - Any fields left blank are inherited from the top-level Addon metadata, so technically they are all optional. For Addons with multiple content items, each item should provide a unique Display Name and Description. - Tous les champs laissés vides sont hérités des métadonnées de l'extension de premier niveau, et sont donc techniquement facultatifs. Pour les extensions comportant plusieurs éléments de contenu, chaque élément doit avoir un nom d'affichage et une description uniques. - - - - add_toolbar_button_dialog - - - Add button? - Ajouter un bouton ? - - - - Add a toolbar button for this macro? - Ajouter un bouton de barre d'outils pour cette macro ? - - - - Yes - Oui - - - - No - Non - - - - Never - Jamais - - - - change_branch - - - Change Branch - Changer de branche - - - - Change to branch: - Passer à la branche : - - - - copyrightInformationDialog - - - Copyright Information - Informations sur les droits d'auteur - - - - Copyright holder: - Détenteur des droits d'auteur : - - - - Copyright year: - Année des droits d’auteur : - - - - personDialog - - - Add Person - Ajouter une personne - - - - A maintainer is someone with current commit access on this project. An author is anyone else you'd like to give credit to. - Un mainteneur est quelqu'un qui a un accès régulier aux livraisons sur ce projet. Un auteur est tout autre personne à qui vous souhaitez donner du crédit. - - - - Name: - Nom : - - - - Email: - E-mail : - - - - Email is required for maintainers, and optional for authors. - L'e-mail est requis pour les mainteneurs et facultatif pour les auteurs. - - - - proxy_authentication - - - Proxy login required - Une connexion au proxy est requise - - - - Proxy requires authentication - Ce proxy requiert une authentification - - - - Proxy: - Proxy : - - - - Placeholder for proxy address - Emplacement pour l'adresse du proxy - - - - Realm: - Domaine : - - - - Placeholder for proxy realm - Emplacement pour le domaine du proxy - - - - Username - Nom d'utilisateur - - - - Password - Mot de passe  - - - - selectLicenseDialog - - - Select a license - Sélectionner une licence - - - - About... - À propos... - - - - License name: - Nom de la licence : - - - - Path to license file: - Chemin d’accès au fichier de licence : - - - - (if required by license) - (si requis par la licence) - - - - Browse... - Parcourir... - - - - Create... - Créer... - - - - select_toolbar_dialog - - - - - - Select Toolbar - Sélectionner une barre d'outils - - - - Select a toolbar to add this macro to: - Sélectionner une barre d'outils pour y ajouter cette macro : - - - - Ask every time - Toujours demander - - - - toolbar_button - - - - Add button? - Ajouter un bouton ? - - - - Add a toolbar button for this macro? - Ajouter un bouton de barre d'outils pour cette macro ? - - - - Yes - Oui - - - - No - Non - - - - Never - Jamais - - - - AddonsInstaller - - - Starting up... - Démarrage en cours... - - - - Worker process {} is taking a long time to stop... - Le processus de traitement {} prend beaucoup de temps pour s’arrêter... - - - - Previous cache process was interrupted, restarting... - - Le processus du précédent cache a été interrompu, redémarrage... - - - - Custom repo list changed, forcing recache... - - La liste des dépôts personnalisés a changé, ce qui force à relancer le cache... - - - - Addon manager - Gestionnaire des extensions - - - - You must restart FreeCAD for changes to take effect. - Vous devez redémarrer FreeCAD pour que les modifications soient prises en compte. - - - - Restart now - Redémarrer maintenant - - - - Restart later - Redémarrer plus tard - - - - - Refresh local cache - Rafraîchir le cache local - - - - Creating addon list - Creating addon list - - - - Loading addon list - Loading addon list - - - - Creating macro list - Creating macro list - - - - Updating cache... - Mise à jour du cache... - - - - - Checking for updates... - Recherche de mises à jour... - - - - Temporary installation of macro failed. - L'installation temporaire de la macro a échoué. - - - - - Close - Fermer - - - - Update all addons - Mettre à jour toutes les extensions - - - - Check for updates - Vérifier les mises à jour - - - - Python dependencies... - Dépendances de Python... - - - - Developer tools... - Outils pour les développeurs… - - - - Apply %n available update(s) - Appliquer %n mise(s) à jour disponible(s) - - - - No updates available - Aucune mise à jour disponible - - - - - - Cannot launch a new installer until the previous one has finished. - Impossible de lancer un nouveau programme d'installation tant que le précédent n'est pas terminé. - - - - - - - Maintainer - Mainteneur - - - - - - - Author - Auteur - - - - New Python Version Detected - Une nouvelle version de Python a été trouvée - - - - This appears to be the first time this version of Python has been used with the Addon Manager. Would you like to install the same auto-installed dependencies for it? - Cela semble être la première fois que cette version de Python est utilisée avec le gestionnaire des extensions. Voulez-vous installer les mêmes dépendances auto-installées pour cela ? - - - - Processing, please wait... - En cours de traitement, veuillez patienter... - - - - - Update - Mettre à jour - - - - Updating... - Mise à jour en cours... - - - - Could not import QtNetwork -- it does not appear to be installed on your system. Your provider may have a package for this dependency (often called "python3-pyside2.qtnetwork") - Impossible d'importer QtNetwork : il ne semble pas être installé sur votre système. Votre fournisseur peut avoir un paquet pour cette dépendance (souvent appelé par exemple "python3-pyside2.qtnetwork") - - - - Failed to convert the specified proxy port '{}' to a port number - Impossible de convertir le port du proxy "{}" spécifié en un numéro de port - - - - Parameter error: mutually exclusive proxy options set. Resetting to default. - Erreur de paramètre : des options de proxy mutuellement exclusives ont été définies. Réinitialisation à la valeur par défaut. - - - - Parameter error: user proxy indicated, but no proxy provided. Resetting to default. - Erreur de paramètre : le proxy de l'utilisateur est indiqué, mais aucun proxy n'est fourni. Réinitialisation à la valeur par défaut. - - - - Addon Manager: Unexpected {} response from server - Gestionnaire des extensions : réponse inattendue {} du serveur - - - - Error with encrypted connection - Erreur avec la connexion chiffrée - - - - - - Confirm remove - Confirmer la suppression - - - - Are you sure you want to uninstall {}? - Êtes-vous sûr de vouloir désinstaller {} ? - - - - - - Removing Addon - Suppression de l'extension - - - - Removing {} - Suppression de {} - - - - - Uninstall complete - Désinstallation terminée - - - - - Uninstall failed - Échec de la désinstallation - - - - Version {version} installed on {date} - Version {version} installée le {date} - - - - Version {version} installed - Version {version} installée - - - - Installed on {date} - Installé le {date} - - - - - - - Installed - Installé - - - - Currently on branch {}, name changed to {} - Pour le moment sur la branche {}, le nom a été changé en {} - - - - Git tag '{}' checked out, no updates possible - La balise de git "{}" a été retirée, aucune mise à jour possible. - - - - Update check in progress - Recherche de mise à jour en cours - - - - Installation location - Emplacement de l’installation - - - - Repository URL - URL du dépôt - - - - Changed to branch '{}' -- please restart to use Addon. - A changé pour la branche "{}". Redémarrer pour utiliser l'extension. - - - - This Addon has been updated. Restart FreeCAD to see changes. - Cette extension a été mise à jour. Redémarrer FreeCAD pour voir les changements. - - - - Disabled - Désactivé - - - - Currently on branch {}, update available to version {} - Actuellement sur la branche {}, une mise à jour est disponible vers la version {}. - - - - Update available to version {} - Mise à jour disponible vers la version {} - - - - This is the latest version available - Ceci est la dernière version disponible. - - - - WARNING: This addon is obsolete - ATTENTION : cette extension est obsolète. - - - - WARNING: This addon is Python 2 only - ATTENTION : cette extension est seulement en Python 2. - - - - WARNING: This addon requires FreeCAD {} - ATTENTION : cette extension nécessite FreeCAD {}. - - - - WARNING: This addon is currently installed, but disabled. Use the 'enable' button to re-enable. - ATTENTION : cette extension est actuellement installée mais désactivée. Utilisez le bouton "Activer" pour la réactiver. - - - - This Addon will be enabled next time you restart FreeCAD. - Cette extension sera activée la prochaine fois que vous redémarrerez FreeCAD. - - - - This Addon will be disabled next time you restart FreeCAD. - Cette extension sera désactivée la prochaine fois que vous redémarrerez FreeCAD. - - - - - - Success - Opération réussie - - - - Install - Installer - - - - Uninstall - Désinstaller - - - - Enable - Activer - - - - Disable - Désactiver - - - - - Check for update - Vérifier les mises à jour - - - - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - Branch change succeeded. -Moved -from: {} -to: {} -Please restart to use the new version. - - - - Run - Lancer - - - - Change branch... - Changer de branche... - - - - Return to package list - Retourner à la liste des paquets - - - - Checking connection - Vérification de la connexion - - - - Checking for connection to GitHub... - Vérification de la connexion à GitHub... - - - - Connection failed - La connexion a échoué - - - - Missing dependency - Dépendances manquantes - - - - Could not import QtNetwork -- see Report View for details. Addon Manager unavailable. - Impossible d'importer QtNetwork -- voir la Vue rapport pour plus de détails. Le gestionnaire des extensions n'est pas disponible. - - - - Other... - For providing a license other than one listed - Autre... - - - - Select the corresponding license file in your Addon - Sélectionner le fichier de licence correspondant à votre extension - - - - Location for new license file - Emplacement du nouveau fichier de licence - - - - Received {} response code from server - Réception de {} code de réponse du serveur - - - - Failed to install macro {} - Impossible d'installer la macro {} - - - - Failed to create installation manifest file: - - Impossible de créer le fichier d'information sur l'installation : - - - - Unrecognized content kind '{}' - Type de contenu non reconnu "{}" - - - - Unable to locate icon at {} - Impossible de localiser l'icône à {} - - - - Select an icon file for this content item - Sélectionner un fichier d'icône pour cet élément de contenu. - - - - - - {} is not a subdirectory of {} - {} n'est pas un sous-répertoire de {} - - - - Select the subdirectory for this content item - Sélectionner le sous-répertoire pour cet élément de contenu. - - - - Automatic - Automatique - - - - - Workbench - Atelier - - - - Addon - Extension - - - - Python - Python - - - - Yes - Oui - - - - Internal Workbench - Atelier interne - - - - External Addon - Extension externe - - - - Python Package - Paquet Python - - - - - Other... - Autre... - - - - Too many to list - Trop de valeurs à afficher - - - - - - - - - Missing Requirement - Condition manquante - - - - Addon '{}' requires '{}', which is not available in your copy of FreeCAD. - L'extension "{}" nécessite "{}" qui n'est pas disponible dans votre version de FreeCAD. - - - - Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD: - L'extension "{}" nécessite les ateliers suivants, qui ne sont pas présents dans votre version de FreeCAD : - - - - Press OK to install anyway. - Appuyez sur OK pour installer quand même. - - - - - Incompatible Python version - Version de Python incompatible - - - - This addon requires Python packages that are not installed, and cannot be installed automatically. To use this addon you must install the following Python packages manually: - Cette extension nécessite des paquets Python qui ne sont pas installés et qui ne peuvent pas l'être automatiquement. Pour utiliser cette extension, vous devez installer manuellement les paquets Python suivants : - - - - This Addon (or one of its dependencies) requires Python {}.{}, and your system is running {}.{}. Installation cancelled. - Cette extension (ou l'une de ses dépendances) nécessite Python {}.{}, et votre système fonctionne sous {}.{}. L'installation a été annulée. - - - - Optional dependency on {} ignored because it is not in the allow-list - Dépendance facultative sur {} ignorée parce qu’elle n'est pas dans la liste autorisée - - - - - Installing dependencies - Installation des dépendances - - - - - Cannot execute Python - Impossible de lancer Python - - - - Failed to automatically locate your Python executable, or the path is set incorrectly. Please check the Addon Manager preferences setting for the path to Python. - Impossible de localiser automatiquement votre exécutable en Python ou bien, le chemin d'accès est incorrect. Vérifier le chemin d'accès à Python dans les préférences du gestionnaire des extensions. - - - - Dependencies could not be installed. Continue with installation of {} anyway? - Les dépendances n'ont pas pu être installées. Continuer quand même l'installation de {} ? - - - - - Cannot execute pip - Impossible d'exécuter la commande pip - - - - Failed to execute pip, which may be missing from your Python installation. Please ensure your system has pip installed and try again. The failed command was: - Impossible d'exécuter le pip. Il peut être absent de votre installation Python. Assurez-vous que pip est installé sur votre système et réessayez. La commande qui a échoué était : - - - - - Continue with installation of {} anyway? - Continuer l'installation de {} quand même ? - - - - - Package installation failed - L'installation du paquet a échoué - - - - See Report View for detailed failure log. - Voir la Vue rapport pour pour les logs détaillés des défaillances. - - - - Installing Addon - Installer l'extension - - - - Installing FreeCAD Addon '{}' - Installation de l'extension "{}" - - - - Cancelling - Annulation en cours - - - - Cancelling installation of '{}' - Annulation de l'installation de "{}" - - - - {} was installed successfully - {} a été installé avec succès - - - - - Installation Failed - L'installation a échoué - - - - Failed to install {} - Impossible d'installer {} - - - - - Create new toolbar - Créer une nouvelle barre d'outils - - - - - A macro installed with the FreeCAD Addon Manager - Une macro installée avec le gestionnaire des extensions de FreeCAD - - - - - Run - Indicates a macro that can be 'run' - Exécuter - - - - Unable to read data from GitHub: check your internet connection and proxy settings and try again. - Impossible de lire les données depuis GitHub : vérifiez votre connexion internet et vos paramètres de proxy et réessayez. - - - - XML failure while reading metadata from file {} - Erreur XML lors de la lecture des métadonnées depuis le fichier {} - - - - Invalid metadata in file {} - Métadonnées non valides dans le fichier {} - - - - WARNING: Path specified in package.xml metadata does not match currently checked-out branch. - ATTENTION : le chemin d'accès spécifié dans les métadonnées du package.xml ne correspond pas à la branche actuellement extraite. - - - - Name - Nom - - - - Class - Classe - - - - Description - Description - - - - Subdirectory - Sous-répertoire - - - - Files - Fichiers - - - - Select the folder containing your Addon - Sélectionner le dossier contenant votre extension - - - - No Vermin, cancelling operation. - NOTE: Vermin is a Python package and proper noun - do not translate - Absence du logiciel Vermin, annulation de l’opération. - - - - Scanning Addon for Python version compatibility - Vérification de la compatibilité de l'extension avec la version de Python - - - - Minimum Python Version Detected - Version minimale de Python détectée - - - - Vermin auto-detected a required version of Python 3.{} - Vermin a détecté le besoin d'une version Python 3.{} - - - - Install Vermin? - Installer Vermin ? - - - - Auto-detecting the required version of Python for this Addon requires Vermin (https://pypi.org/project/vermin/). OK to install? - La détection automatique de la version requise de Python pour cette extension nécessite Vermin (https://pypi.org/project/vermin/). D'accord pour l'installer ? - - - - Attempting to install Vermin from PyPi - Tentative d'installation de Vermin à partir de PyPi - - - - - Installation failed - L'installation a échoué - - - - Failed to install Vermin -- check Report View for details. - 'Vermin' is the name of a Python package, do not translate - Impossible d'installer Vermin. Voir la vue rapport pour plus de détails. - - - - Failed to import vermin after installation -- cannot scan Addon. - 'vermin' is the name of a Python package, do not translate - Impossible d'importer Vermin après l'installation. Il n'est pas possible de faire une analyse l'extension. - - - - Select an icon file for this package - Sélectionner un fichier d'icône pour ce paquet - - - - Filter is valid - Le filtre est valide - - - - Filter regular expression is invalid - L'expression régulière du filtre n'est pas valide - - - - Search... - Rechercher... - - - - Click for details about package {} - Cliquer pour plus de détails sur le paquet {} - - - - Click for details about workbench {} - Cliquer pour plus de détails sur l'atelier {} - - - - Click for details about macro {} - Cliquer pour plus de détails sur la macro {} - - - - Maintainers: - Mainteneurs : - - - - Tags - Mots-clés - - - - {} ★ on GitHub - {} ★ sur GitHub - - - - No ★, or not on GitHub - Pas d'★ ou pas sur GitHub - - - - Created - Créé - - - - Updated - Mis à jour - - - - Score: - Score : - - - - - Up-to-date - À jour - - - - - - - - Update available - Mise à jour disponible - - - - - Pending restart - En attente de redémarrage - - - - - DISABLED - DÉSACTIVÉ - - - - Installed version - Version installée - - - - Unknown version - Version inconnue - - - - Installed on - Installé le - - - - Available version - Version disponible - - - - Filter by... - Filtrer par... - - - - Addon Type - Type d'extension - - - - - Any - Tous - - - - Macro - Macro - - - - Preference Pack - Kit de préférences - - - - Installation Status - Statut des installations - - - - Not installed - Non installé - - - - Filter - Filtre - - - - DANGER: Developer feature - DANGER : fonction de développeur - - - - DANGER: Switching branches is intended for developers and beta testers, and may result in broken, non-backwards compatible documents, instability, crashes, and/or the premature heat death of the universe. Are you sure you want to continue? - DANGER : Le passage d'une branche à l'autre est destiné aux développeurs et aux bêta-testeurs, et peut entraîner des documents endommagés et non rétrocompatibles, de l'instabilité, des pannes et/ou la mort prématurée de l'univers... Êtes-vous sûr de vouloir continuer ? - - - - There are local changes - Il y a des changements locaux - - - - WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)? - ATTENTION : ce répertoire contient des modifications locales non validées. Êtes-vous sûr de vouloir changer de branche (en apportant les modifications avec vous) ? - - - - Local - Table header for local git ref name - Locale - - - - Remote tracking - Table header for git remote tracking branch name - Suivi à distance - - - - Last Updated - Table header for git update date - Dernière mise à jour - - - - Installation of Python package {} failed - L'installation du paquet Python {} a échoué - - - - Installation of optional package failed - L'installation du paquet facultatif a échoué - - - - Installing required dependency {} - Installation de la dépendance requise {} - - - - Installation of Addon {} failed - L'installation de l'extension {} a échoué. - - - - Downloaded {} for {} - Downloaded {} for {} - - - - Failed to decode {} file for Addon '{}' - Impossible de décoder le fichier {} pour l'extension "{}" - - - - Any dependency information in this file will be ignored - Toutes les informations de dépendance dans ce fichier seront ignorées - - - - Unable to open macro wiki page at {} - Impossible d'ouvrir la page wiki de la macro {} - - - - Unable to fetch the code of this macro. - Impossible de récupérer le code de cette macro. - - - - Unable to retrieve a description from the wiki for macro {} - Impossible de récupérer une description du wiki pour la macro {} - - - - Unable to open macro code URL {} - Impossible d'ouvrir l'URL du code de la macro {} - - - - Unable to fetch macro-specified file {} from {} - Impossible de récupérer le fichier {} spécifié par la macro à partir de {} - - - - Could not locate macro-specified file {} (expected at {}) - Impossible de localiser le fichier {} spécifié par la macro (attendu à {}) - - - - {}: Unrecognized internal workbench '{}' - {} : atelier interne non reconnu "{}" - - - - Addon Developer Warning: Repository URL set in package.xml file for addon {} ({}) does not match the URL it was fetched from ({}) - Avertissement du développeur de l'extension : l'URL du répertoire défini dans le fichier package.xml pour l'extension {} ({}) ne correspond pas à l'URL depuis laquelle il a été récupéré ({}). - - - - Addon Developer Warning: Repository branch set in package.xml file for addon {} ({}) does not match the branch it was fetched from ({}) - Avertissement du développeur de l'extension : la branche du répertoire définie dans le fichier package.xml pour l'extension {} ({}) ne correspond pas à la branche depuis laquelle il a été récupéré ({}). - - - - - Got an error when trying to import {} - Une erreur s'est produite lors de l'importation de {} - - - - An unknown error occurred - Une erreur inconnue est survenue - - - - Could not find addon {} to remove it. - Impossible de trouver l'extension {} pour la supprimer. - - - - Execution of Addon's uninstall.py script failed. Proceeding with uninstall... - L'exécution du script uninstall.py de l'extension a échoué. Poursuite de la désinstallation... - - - - Removed extra installed file {} - Suppression du fichier {} installé en plus - - - - Error while trying to remove extra installed file {} - Erreur lors de la suppression du fichier {} installé en plus - - - - Error while trying to remove macro file {}: - Erreur lors de la suppression du fichier de la macro {} : - - - - Failed to connect to GitHub. Check your connection and proxy settings. - Impossible de connecter à GitHub. Vérifiez vos paramètres de connexion et de proxy. - - - - WARNING: Duplicate addon {} ignored - ATTENTION : l'extension dupliquée {} est ignorée. - - - - Git is disabled, skipping Git macros - Git is disabled, skipping Git macros - - - - Attempting to change non-Git Macro setup to use Git - - Attempting to change non-Git Macro setup to use Git - - - - - An error occurred updating macros from GitHub, trying clean checkout... - Une erreur est survenue lors de la mise à jour des macros depuis GitHub, en tentant un checkout propre... - - - - Attempting to do a clean checkout... - Tentative de faire un checkout propre... - - - - Clean checkout succeeded - Checkout propre réussi - - - - Failed to update macros from GitHub -- try clearing the Addon Manager's cache. - Impossible de mettre à jour des macros depuis GitHub. Essayez de vider le cache du gestionnaire des extensions. - - - - Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time - Erreur de connexion au wiki : FreeCAD ne peut pas récupérer la liste des macros du wiki pour le moment - - - - Checking {} for update - Checking {} for update - - - - Unable to fetch Git updates for workbench {} - Unable to fetch Git updates for workbench {} - - - - Git status failed for {} - Git status failed for {} - - - - Caching {} macro - Caching {} macro - - - - Caching macros - Caching macros - - - - Failed to read metadata from {name} - Impossible de lire les métadonnées de {name} - - - - Failed to fetch code for macro '{name}' - Impossible de récupérer le code de la macro "{name}" - - - - Addon Manager: a worker process failed to complete while fetching {name} - Gestionnaire des extensions : un processus n'a pas abouti lors de la récupération de {name} - - - - Out of {num_macros} macros, {num_failed} timed out while processing - Sur {num_macros} macros, {num_failed} sont tombées en panne pendant le traitement - - - - Addon Manager: a worker process failed to halt ({name}) - Gestionnaire des extensions : un processus n'a pas pu arrêter ({name}) - - - - Timeout while fetching metadata for macro {} - Délai de récupération des métadonnées de la macro {} - - - - Failed to kill process for macro {}! - - Impossible d'arrêter la macro {} ! - - - - Failed to get Addon statistics from {} -- only sorting alphabetically will be accurate - - Impossible de récupérer les statistiques de l'extension {}, seul le tri par ordre alphabétique sera correct. - - - - Failed to get Addon score from '{}' -- sorting by score will fail - - Impossible de récupérer le score de l'extension de "{}". Le tri par score échouera. - - - - Repository URL - Preferences header for custom repositories - URL du dépôt - - - - Branch name - Preferences header for custom repositories - Nom de la branche - - - - Basic Git update failed with the following message: - Basic Git update failed with the following message: - - - - Backing up the original directory and re-cloning - Sauvegarde du répertoire original et re-clonage - - - - Failed to clone {} into {} using Git - Failed to clone {} into {} using Git - - - - Git branch rename failed with the following message: - Le renommage de la branche git a échoué avec le message suivant : - - - - Installing - Installation en cours - - - - Succeeded - Opération réussie - - - - Failed - Échec - - - - Update was cancelled - Mise à jour annulée - - - - some addons may have been updated - certaines extensions ont peut-être été mises à jour - - - - Loading info for {} from the FreeCAD Macro Recipes wiki... - Chargement des informations pour {} à partir de la page du wiki "Liste des macros de FreeCAD..." - - - - Loading page for {} from {}... - Chargement de la page pour {} depuis {}... - - - - Failed to download data from {} -- received response code {}. - Impossible de télécharger les données de {}. Le code de réponse reçu est {}. - - - - Composite view - Vue composite - - - - Expanded view - Vue étendue - - - - Compact view - Vue compacte - - - - Alphabetical - Sort order - Alphabétique - - - - Last Updated - Sort order - Dernière mise à jour - - - - Date Created - Sort order - Date de création - - - - GitHub Stars - Sort order - Étoiles sous GitHub - - - - Score - Sort order - Score - - - - Std_AddonMgr - - - &Addon manager - &Gestionnaire des extensions - - - - Manage external workbenches, macros, and preference packs - Gérer les ateliers externes, les macros et les kits de préférences - - - - AddonInstaller - - - Finished removing {} - Suppression terminée {} - - - - Failed to remove some files - Impossible de supprimer certains fichiers - - - - Addons installer - - - Finished updating the following addons - Mise à jour terminée des extensions suivantes - - - - Workbench - - - Auto-Created Macro Toolbar - Barre d'outils de macro créée automatiquement - - - - QObject - - - Addon Manager - Gestionnaire des extensions - - - diff --git a/src/Mod/AddonManager/Resources/translations/AddonManager_gl.qm b/src/Mod/AddonManager/Resources/translations/AddonManager_gl.qm deleted file mode 100644 index 0e55c17f87c534ffa44ed90dec02072d953cc9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68368 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