Merge branch 'master' of https://github.com/FreeCAD/FreeCAD into toolbit-gui

This commit is contained in:
Patrick F
2020-04-09 21:55:28 +02:00
80 changed files with 7157 additions and 4022 deletions
+7
View File
@@ -856,6 +856,13 @@ void InventorBuilder::addCylinder(float radius, float height)
<< Base::blanks(indent) << "}\n";
}
void InventorBuilder::addSphere(float radius)
{
result << Base::blanks(indent) << "Sphere {\n"
<< Base::blanks(indent) << " radius " << radius << "\n"
<< Base::blanks(indent) << "}\n";
}
void InventorBuilder::addBoundingBox(const Vector3f& pt1, const Vector3f& pt2, short lineWidth,
float color_r,float color_g,float color_b)
{
+1
View File
@@ -301,6 +301,7 @@ public:
int numUControlPoints, int numVControlPoints,
const std::vector<float>& uKnots, const std::vector<float>& vKnots);
void addCylinder(float radius, float height);
void addSphere(float radius);
//@}
/** @name Bounding Box handling */
+2
View File
@@ -258,7 +258,9 @@ public:
static PyObject* sRunCommand (PyObject *self,PyObject *args);
static PyObject* sAddCommand (PyObject *self,PyObject *args);
static PyObject* sGetCommandInfo (PyObject *self,PyObject *args);
static PyObject* sListCommands (PyObject *self,PyObject *args);
static PyObject* sGetCommandShortcut (PyObject *self,PyObject *args);
static PyObject* sIsCommandActive (PyObject *self,PyObject *args);
static PyObject* sUpdateCommands (PyObject *self,PyObject *args);
+73
View File
@@ -144,6 +144,12 @@ PyMethodDef Application::Methods[] = {
{"listCommands", (PyCFunction) Application::sListCommands, METH_VARARGS,
"listCommands() -> list of strings\n\n"
"Returns a list of all commands known to FreeCAD."},
{"getCommandInfo", (PyCFunction) Application::sGetCommandInfo, METH_VARARGS,
"getCommandInfo(string) -> list of strings\n\n"
"Usage: menuText,tooltipText,whatsThisText,statustipText,pixmapText,shortcutText = getCommandInfo(string)"},
{"getCommandShortcut", (PyCFunction) Application::sGetCommandShortcut, METH_VARARGS,
"getCommandShortcut(string) -> string\n\n"
"Returns string representing shortcut key accelerator for command."},
{"updateCommands", (PyCFunction) Application::sUpdateCommands, METH_VARARGS,
"updateCommands\n\n"
"Update all command active status"},
@@ -1273,6 +1279,73 @@ PyObject* Application::sUpdateCommands(PyObject * /*self*/, PyObject *args)
Py_Return;
}
PyObject* Application::sGetCommandShortcut(PyObject * /*self*/, PyObject *args)
{
char* pName;
if (!PyArg_ParseTuple(args, "s", &pName))
return NULL;
Command* cmd = Application::Instance->commandManager().getCommandByName(pName);
if (cmd) {
#if PY_MAJOR_VERSION >= 3
PyObject* str = PyUnicode_FromString(cmd->getAccel() ? cmd->getAccel() : "");
#else
PyObject* str = PyString_FromString(cmd->getAccel() ? cmd->getAccel() : "");
#endif
return str;
}
else {
PyErr_Format(Base::BaseExceptionFreeCADError, "No such command '%s'", pName);
return 0;
}
}
PyObject* Application::sGetCommandInfo(PyObject * /*self*/, PyObject *args)
{
char* pName;
if (!PyArg_ParseTuple(args, "s", &pName))
return NULL;
Command* cmd = Application::Instance->commandManager().getCommandByName(pName);
if (cmd) {
PyObject* pyList = PyList_New(6);
const char* menuTxt = cmd->getMenuText();
const char* tooltipTxt = cmd->getToolTipText();
const char* whatsThisTxt = cmd->getWhatsThis();
const char* statustipTxt = cmd->getStatusTip();
const char* pixMapTxt = cmd->getPixmap();
const char* shortcutTxt = cmd->getAccel();
#if PY_MAJOR_VERSION >= 3
PyObject* strMenuTxt = PyUnicode_FromString(menuTxt ? menuTxt : "");
PyObject* strTooltipTxt = PyUnicode_FromString(tooltipTxt ? tooltipTxt : "");
PyObject* strWhatsThisTxt = PyUnicode_FromString(whatsThisTxt ? whatsThisTxt : "");
PyObject* strStatustipTxt = PyUnicode_FromString(statustipTxt ? statustipTxt : "");
PyObject* strPixMapTxt = PyUnicode_FromString(pixMapTxt ? pixMapTxt : "");
PyObject* strShortcutTxt = PyUnicode_FromString(shortcutTxt ? shortcutTxt : "");
#else
PyObject* strMenuTxt = PyString_FromString(menuTxt ? menuTxt : "");
PyObject* strTooltipTxt = PyString_FromString(tooltipTxt ? tooltipTxt : "");
PyObject* strWhatsThisTxt = PyString_FromString(whatsThisTxt ? whatsThisTxt : "");
PyObject* strStatustipTxt = PyString_FromString(statustipTxt ? statustipTxt : "");
PyObject* strPixMapTxt = PyString_FromString(pixMapTxt ? pixMapTxt : "");
PyObject* strShortcutTxt = PyString_FromString(shortcutTxt ? shortcutTxt : "");
#endif
PyList_SetItem(pyList, 0, strMenuTxt);
PyList_SetItem(pyList, 1, strTooltipTxt);
PyList_SetItem(pyList, 2, strWhatsThisTxt);
PyList_SetItem(pyList, 3, strStatustipTxt);
PyList_SetItem(pyList, 4, strPixMapTxt);
PyList_SetItem(pyList, 5, strShortcutTxt);
return pyList;
}
else {
PyErr_Format(Base::BaseExceptionFreeCADError, "No such command '%s'", pName);
return 0;
}
}
PyObject* Application::sListCommands(PyObject * /*self*/, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
+38 -12
View File
@@ -190,15 +190,17 @@ class _ArchPipe(ArchComponent.Component):
pl = obj.PropertiesList
if not "Diameter" in pl:
obj.addProperty("App::PropertyLength", "Diameter", "Pipe", QT_TRANSLATE_NOOP("App::Property","The diameter of this pipe, if not based on a profile"))
obj.addProperty("App::PropertyLength", "Diameter", "Pipe", QT_TRANSLATE_NOOP("App::Property","The diameter of this pipe, if not based on a profile"))
if not "Length" in pl:
obj.addProperty("App::PropertyLength", "Length", "Pipe", QT_TRANSLATE_NOOP("App::Property","The length of this pipe, if not based on an edge"))
obj.addProperty("App::PropertyLength", "Length", "Pipe", QT_TRANSLATE_NOOP("App::Property","The length of this pipe, if not based on an edge"))
if not "Profile" in pl:
obj.addProperty("App::PropertyLink", "Profile", "Pipe", QT_TRANSLATE_NOOP("App::Property","An optional closed profile to base this pipe on"))
obj.addProperty("App::PropertyLink", "Profile", "Pipe", QT_TRANSLATE_NOOP("App::Property","An optional closed profile to base this pipe on"))
if not "OffsetStart" in pl:
obj.addProperty("App::PropertyLength", "OffsetStart", "Pipe", QT_TRANSLATE_NOOP("App::Property","Offset from the start point"))
obj.addProperty("App::PropertyLength", "OffsetStart", "Pipe", QT_TRANSLATE_NOOP("App::Property","Offset from the start point"))
if not "OffsetEnd" in pl:
obj.addProperty("App::PropertyLength", "OffsetEnd", "Pipe", QT_TRANSLATE_NOOP("App::Property","Offset from the end point"))
obj.addProperty("App::PropertyLength", "OffsetEnd", "Pipe", QT_TRANSLATE_NOOP("App::Property","Offset from the end point"))
if not "WallThickness" in pl:
obj.addProperty("App::PropertyLength", "WallThickness","Pipe", QT_TRANSLATE_NOOP("App::Property","The wall thickness of this pipe, if not based on a profile"))
self.Type = "Pipe"
def onDocumentRestored(self,obj):
@@ -231,7 +233,11 @@ class _ArchPipe(ArchComponent.Component):
FreeCAD.Console.PrintError(translate("Arch","Unable to build the profile")+"\n")
return
# move and rotate the profile to the first point
delta = w.Vertexes[0].Point-p.CenterOfMass
if hasattr(p,"CenterOfMass"):
c = p.CenterOfMass
else:
c = p.BoundBox.Center
delta = w.Vertexes[0].Point-c
p.translate(delta)
import Draft
if Draft.getType(obj.Base) == "BezCurve":
@@ -240,12 +246,30 @@ class _ArchPipe(ArchComponent.Component):
v1 = w.Vertexes[1].Point-w.Vertexes[0].Point
v2 = DraftGeomUtils.getNormal(p)
rot = FreeCAD.Rotation(v2,v1)
p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
p.rotate(c,rot.Axis,math.degrees(rot.Angle))
shapes = []
try:
sh = w.makePipeShell([p],True,False,2)
if p.Faces:
for f in p.Faces:
sh = w.makePipeShell([f.OuterWire],True,False,2)
for shw in f.Wires:
if shw.hashCode() != f.OuterWire.hashCode():
sh2 = w.makePipeShell([shw],True,False,2)
sh = sh.cut(sh2)
shapes.append(sh)
elif p.Wires:
for pw in p.Wires:
sh = w.makePipeShell([pw],True,False,2)
shapes.append(sh)
except:
FreeCAD.Console.PrintError(translate("Arch","Unable to build the pipe")+"\n")
else:
if len(shapes) == 0:
return
elif len(shapes) == 1:
sh = shapes[0]
else:
sh = Part.makeCompound(shapes)
obj.Shape = sh
if obj.Base:
obj.Length = w.Length
@@ -279,17 +303,19 @@ class _ArchPipe(ArchComponent.Component):
if not obj.Profile.getLinkedObject().isDerivedFrom("Part::Part2DObject"):
FreeCAD.Console.PrintError(translate("Arch","The profile is not a 2D Part")+"\n")
return
if len(obj.Profile.Shape.Wires) != 1:
FreeCAD.Console.PrintError(translate("Arch","Too many wires in the profile")+"\n")
return
if not obj.Profile.Shape.Wires[0].isClosed():
FreeCAD.Console.PrintError(translate("Arch","The profile is not closed")+"\n")
return
p = obj.Profile.Shape.Wires[0]
p = obj.Profile.Shape
else:
if obj.Diameter.Value == 0:
return
p = Part.Wire([Part.Circle(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),obj.Diameter.Value/2).toShape()])
if obj.WallThickness.Value and (obj.WallThickness.Value < obj.Diameter.Value/2):
p2 = Part.Wire([Part.Circle(FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),(obj.Diameter.Value/2-obj.WallThickness.Value)).toShape()])
p = Part.Face(p)
p2 = Part.Face(p2)
p = p.cut(p2)
return p
+39 -5
View File
@@ -301,14 +301,40 @@ class _Rebar(ArchComponent.Component):
if self.clone(obj):
return
if not obj.Base:
FreeCAD.Console.PrintError(
"No Base, return without a rebar shape for {}.\n"
.format(obj.Name)
)
return
if not obj.Base.Shape:
FreeCAD.Console.PrintError(
"No Shape in Base, return without a rebar shape for {}.\n"
.format(obj.Name)
)
return
if not obj.Base.Shape.Wires:
if obj.Base.Shape.Faces:
FreeCAD.Console.PrintError(
"Faces in Shape of Base, return without a rebar shape for {}.\n"
.format(obj.Name)
)
return
if not obj.Base.Shape.Edges:
FreeCAD.Console.PrintError(
"No Edges in Shape of Base, return without a rebar shape for {}.\n"
.format(obj.Name)
)
return
if not obj.Diameter.Value:
FreeCAD.Console.PrintError(
"No Diameter Value, return without a rebar shape for {}.\n"
.format(obj.Name)
)
return
if not obj.Amount:
FreeCAD.Console.PrintError(
"No Amount, return without a rebar shape for {}.\n"
.format(obj.Name)
)
return
father = obj.Host
fathershape = None
@@ -322,13 +348,22 @@ class _Rebar(ArchComponent.Component):
if hasattr(father,'Shape'):
fathershape = father.Shape
wire = obj.Base.Shape.Wires[0]
import Part
# corner cases:
# compound from more Wires
# compound without Wires but with multiple Edges
# Does they make sense? If yes handle them.
# Does it makes sense to handle Shapes with Faces or even Solids?
if not obj.Base.Shape.Wires and len(obj.Base.Shape.Edges) == 1:
wire = Part.Wire(obj.Base.Shape.Edges[0])
else:
wire = obj.Base.Shape.Wires[0]
if hasattr(obj,"Rounding"):
#print(obj.Rounding)
if obj.Rounding:
radius = obj.Rounding * obj.Diameter.Value
import DraftGeomUtils
wire = DraftGeomUtils.filletWire(wire,radius)
from DraftGeomUtils import filletWire
wire = filletWire(wire,radius)
bpoint, bvec = self.getBaseAndAxis(wire)
if not bpoint:
return
@@ -362,7 +397,6 @@ class _Rebar(ArchComponent.Component):
if length:
obj.Length = length
pl = obj.Placement
import Part
circle = Part.makeCircle(obj.Diameter.Value/2,bpoint,bvec)
circle = Part.Wire(circle)
try:
+9
View File
@@ -784,6 +784,15 @@ class _CommandWindow:
self.librarypresets.append([wtype+" - "+subtype+" - "+os.path.splitext(subfile)[0],os.path.join(subdir,subfile)])
else:
librarypath = None
# check for existing presets
presetdir = os.path.join(FreeCAD.getUserAppDataDir(),"Arch")
for tp in ["Windows","Doors"]:
wdir = os.path.join(presetdir,tp)
if os.path.exists(wdir):
for wfile in os.listdir(wdir):
if wfile.lower().endswith(".fcstd"):
self.librarypresets.append([tp[:-1]+" - "+wfile[:-6],wfile])
# presets box
labelp = QtGui.QLabel(translate("Arch","Preset"))
+2 -2
View File
@@ -77,12 +77,12 @@ void AssemblyExport initAssembly()
// call PyType_Ready, otherwise we run into a segmentation fault, later on.
// This function is responsible for adding inherited slots from a type's base class.
// Item hirachy
// Item hierarchy
Assembly::Item ::init();
Assembly::Product ::init();
Assembly::ProductRef ::init();
// constraint hirachy
// constraint hierarchy
Assembly::Constraint ::init();
Assembly::ConstraintGroup ::init();
}
+3
View File
@@ -17,6 +17,7 @@ SET(Draft_SRCS_base
WorkingPlane.py
getSVG.py
TestDraft.py
TestDraftGui.py
)
SET(Draft_import
@@ -79,6 +80,7 @@ SET(Draft_GUI_tools
draftguitools/gui_circulararray.py
draftguitools/gui_orthoarray.py
draftguitools/gui_polararray.py
draftguitools/gui_planeproxy.py
draftguitools/gui_selectplane.py
draftguitools/gui_arrays.py
draftguitools/gui_snaps.py
@@ -94,6 +96,7 @@ SET(Draft_task_panels
drafttaskpanels/task_orthoarray.py
drafttaskpanels/task_polararray.py
drafttaskpanels/task_scale.py
drafttaskpanels/task_selectplane.py
drafttaskpanels/task_shapestring.py
drafttaskpanels/README.md
)
+116 -116
View File
@@ -1,174 +1,173 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* Copyright (c) 2009, 2010 Yorik van Havre <[email protected]> *
#* Copyright (c) 2009, 2010 Ken Cline <[email protected]> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by 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 *
#* *
#***************************************************************************
#from __future__ import division
__title__="FreeCAD Draft Workbench"
__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, Dmitry Chigrin, Daniel Falck"
__url__ = "https://www.freecadweb.org"
# ***************************************************************************
# * Copyright (c) 2009, 2010 Yorik van Havre <[email protected]> *
# * Copyright (c) 2009, 2010 Ken Cline <[email protected]> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by 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 *
# * *
# ***************************************************************************
"""Provide the Draft Workbench public programming interface.
The Draft module offers tools to create and manipulate 2D objects.
The functions in this file must be usable without requiring the
graphical user interface.
These functions can be used as the backend for the graphical commands
defined in `DraftTools.py`.
"""
## \addtogroup DRAFT
# \brief Create and manipulate basic 2D objects
#
# This module offers a range of tools to create and manipulate basic 2D objects
# This module offers tools to create and manipulate basic 2D objects
#
# The module allows to create 2D geometric objects such as line, rectangle, circle,
# etc, modify these objects by moving, scaling or rotating them, and offers a couple of
# other utilities to manipulate further these objects, such as decompose them (downgrade)
# into smaller elements.
# The module allows to create 2D geometric objects such as line, rectangle,
# circle, etc., modify these objects by moving, scaling or rotating them,
# and offers a couple of other utilities to manipulate further these objects,
# such as decompose them (downgrade) into smaller elements.
#
# The functionality of the module is divided into GUI tools, usable from the
# FreeCAD interface, and corresponding python functions, that can perform the same
# operation programmatically.
# visual interface, and corresponding python functions, that can perform
# the same operation programmatically.
#
# @{
"""The Draft module offers a range of tools to create and manipulate basic 2D objects"""
import FreeCAD, math, sys, os, DraftVecUtils, WorkingPlane
import DraftGeomUtils
import draftutils.translate
from FreeCAD import Vector
import math
import sys
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
from FreeCAD import Vector
import DraftVecUtils
import WorkingPlane
from draftutils.translate import translate
if FreeCAD.GuiUp:
import FreeCADGui, Draft_rc
from PySide import QtCore
import FreeCADGui
import Draft_rc
gui = True
#from DraftGui import translate
# To prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
else:
# def QT_TRANSLATE_NOOP(ctxt,txt):
# return txt
#print("FreeCAD Gui not present. Draft module will have some features disabled.")
gui = False
translate = draftutils.translate.translate
__title__ = "FreeCAD Draft Workbench"
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
"Dmitry Chigrin, Daniel Falck")
__url__ = "https://www.freecadweb.org"
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Backwards compatibility
#---------------------------------------------------------------------------
import DraftLayer
_VisGroup = DraftLayer.Layer
_ViewProviderVisGroup = DraftLayer.ViewProviderLayer
makeLayer = DraftLayer.makeLayer
# ---------------------------------------------------------------------------
from DraftLayer import Layer as _VisGroup
from DraftLayer import ViewProviderLayer as _ViewProviderVisGroup
from DraftLayer import makeLayer
# import DraftFillet
# Fillet = DraftFillet.Fillet
# makeFillet = DraftFillet.makeFillet
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# General functions
#---------------------------------------------------------------------------
import draftutils.utils
import draftutils.gui_utils
# ---------------------------------------------------------------------------
from draftutils.utils import ARROW_TYPES as arrowtypes
arrowtypes = draftutils.utils.ARROW_TYPES
from draftutils.utils import stringencodecoin
from draftutils.utils import string_encode_coin
stringencodecoin = draftutils.utils.string_encode_coin
string_encode_coin = draftutils.utils.string_encode_coin
from draftutils.utils import typecheck
from draftutils.utils import type_check
typecheck = draftutils.utils.type_check
type_check = draftutils.utils.type_check
from draftutils.utils import getParamType
from draftutils.utils import get_param_type
getParamType = draftutils.utils.get_param_type
get_param_type = draftutils.utils.get_param_type
from draftutils.utils import getParam
from draftutils.utils import get_param
getParam = draftutils.utils.get_param
get_param = draftutils.utils.get_param
from draftutils.utils import setParam
from draftutils.utils import set_param
setParam = draftutils.utils.set_param
set_param = draftutils.utils.set_param
from draftutils.utils import precision
from draftutils.utils import tolerance
from draftutils.utils import epsilon
precision = draftutils.utils.precision
tolerance = draftutils.utils.tolerance
epsilon = draftutils.utils.epsilon
from draftutils.utils import getRealName
from draftutils.utils import get_real_name
getRealName = draftutils.utils.get_real_name
get_real_name = draftutils.utils.get_real_name
from draftutils.utils import getType
from draftutils.utils import get_type
getType = draftutils.utils.get_type
get_type = draftutils.utils.get_type
from draftutils.utils import getObjectsOfType
from draftutils.utils import get_objects_of_type
getObjectsOfType = draftutils.utils.get_objects_of_type
get_objects_of_type = draftutils.utils.get_objects_of_type
from draftutils.utils import isClone
from draftutils.utils import is_clone
get3DView = draftutils.gui_utils.get_3d_view
get_3d_view = draftutils.gui_utils.get_3d_view
from draftutils.utils import getGroupNames
from draftutils.utils import get_group_names
isClone = draftutils.utils.is_clone
is_clone = draftutils.utils.is_clone
from draftutils.utils import ungroup
getGroupNames = draftutils.utils.get_group_names
get_group_names = draftutils.utils.get_group_names
from draftutils.utils import getGroupContents
from draftutils.utils import get_group_contents
ungroup = draftutils.utils.ungroup
from draftutils.utils import printShape
from draftutils.utils import print_shape
autogroup = draftutils.gui_utils.autogroup
from draftutils.utils import compareObjects
from draftutils.utils import compare_objects
dimSymbol = draftutils.gui_utils.dim_symbol
dim_symbol = draftutils.gui_utils.dim_symbol
from draftutils.utils import shapify
dimDash = draftutils.gui_utils.dim_dash
dim_dash = draftutils.gui_utils.dim_dash
from draftutils.utils import loadSvgPatterns
from draftutils.utils import load_svg_patterns
shapify = draftutils.utils.shapify
from draftutils.utils import svgpatterns
from draftutils.utils import svg_patterns
getGroupContents = draftutils.utils.get_group_contents
get_group_contents = draftutils.utils.get_group_contents
from draftutils.utils import getMovableChildren
from draftutils.utils import get_movable_children
removeHidden = draftutils.gui_utils.remove_hidden
remove_hidden = draftutils.gui_utils.remove_hidden
from draftutils.gui_utils import get3DView
from draftutils.gui_utils import get_3d_view
printShape = draftutils.utils.print_shape
print_shape = draftutils.utils.print_shape
from draftutils.gui_utils import autogroup
compareObjects = draftutils.utils.compare_objects
compare_objects = draftutils.utils.compare_objects
from draftutils.gui_utils import dimSymbol
from draftutils.gui_utils import dim_symbol
formatObject = draftutils.gui_utils.format_object
format_object = draftutils.gui_utils.format_object
from draftutils.gui_utils import dimDash
from draftutils.gui_utils import dim_dash
getSelection = draftutils.gui_utils.get_selection
get_selection = draftutils.gui_utils.get_selection
from draftutils.gui_utils import removeHidden
from draftutils.gui_utils import remove_hidden
getSelectionEx = draftutils.gui_utils.get_selection_ex
get_selection_ex = draftutils.gui_utils.get_selection_ex
from draftutils.gui_utils import formatObject
from draftutils.gui_utils import format_object
select = draftutils.gui_utils.select
from draftutils.gui_utils import getSelection
from draftutils.gui_utils import get_selection
loadSvgPatterns = draftutils.utils.load_svg_patterns
load_svg_patterns = draftutils.utils.load_svg_patterns
from draftutils.gui_utils import getSelectionEx
from draftutils.gui_utils import get_selection_ex
svgpatterns = draftutils.utils.svg_patterns
svg_patterns = draftutils.utils.svg_patterns
from draftutils.gui_utils import select
loadTexture = draftutils.gui_utils.load_texture
load_texture = draftutils.gui_utils.load_texture
getMovableChildren = draftutils.utils.get_movable_children
get_movable_children = draftutils.utils.get_movable_children
from draftutils.gui_utils import loadTexture
from draftutils.gui_utils import load_texture
def makeCircle(radius, placement=None, face=None, startangle=None, endangle=None, support=None):
@@ -715,7 +714,7 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Arra
_Array(obj)
obj.Base = baseobject
if arg6:
if isinstance(arg1, (int, float)):
if isinstance(arg1, (int, float, FreeCAD.Units.Quantity)):
obj.ArrayType = "circular"
obj.RadialDistance = arg1
obj.TangentialDistance = arg2
@@ -3875,6 +3874,7 @@ class _ViewProviderDimension(_ViewProviderDraft):
return mode
def is_linked_to_circle(self):
import DraftGeomUtils
_obj = self.Object
if _obj.LinkedGeometry and len(_obj.LinkedGeometry) == 1:
lobj = _obj.LinkedGeometry[0][0]
File diff suppressed because it is too large Load Diff
+92 -71
View File
@@ -1,50 +1,69 @@
# -*- coding: utf8 -*-
#***************************************************************************
#* Copyright (c) 2009, 2010 Yorik van Havre <[email protected]> *
#* Copyright (c) 2009, 2010 Ken Cline <[email protected]> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
__title__="FreeCAD Draft Workbench GUI Tools"
__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, Dmitry Chigrin"
__url__ = "https://www.freecadweb.org"
# ***************************************************************************
# * Copyright (c) 2009, 2010 Yorik van Havre <[email protected]> *
# * Copyright (c) 2009, 2010 Ken Cline <[email protected]> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by 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 *
# * *
# ***************************************************************************
"""Provide GUI commands of the Draft Workbench.
This module loads all graphical commands of the Draft Workbench,
that is, those actions that can be called from menus and buttons.
This module must be imported only when the graphical user interface
is available, for example, during the workbench definition in `IntiGui.py`.
"""
## @package DraftTools
# \ingroup DRAFT
# \brief GUI Commands of the Draft workbench
# \brief Provide GUI commands of the Draft workbench.
#
# This module contains all the FreeCAD commands
# of the Draft module
# This module contains all the graphical commands of the Draft workbench,
# that is, those actions that can be called from menus and buttons.
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Generic stuff
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
import math
import sys
from PySide import QtCore, QtGui
from pivy import coin
import sys, FreeCAD, FreeCADGui, WorkingPlane, math, Draft, Draft_rc, DraftVecUtils
import FreeCAD
import FreeCADGui
from FreeCAD import Vector
from PySide import QtCore,QtGui
import DraftGui
from draftutils.todo import todo
import Draft
import Draft_rc
import DraftGui # Initializes the DraftToolBar class
import DraftVecUtils
import WorkingPlane
from draftutils.todo import ToDo
from draftutils.translate import translate
import draftguitools.gui_snapper as gui_snapper
import draftguitools.gui_trackers as trackers
from pivy import coin
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
True if DraftGui.__name__ else False
__title__ = "FreeCAD Draft Workbench GUI Tools"
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
"Dmitry Chigrin")
__url__ = "https://www.freecadweb.org"
if not hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper = gui_snapper.Snapper()
@@ -52,20 +71,19 @@ if not hasattr(FreeCADGui, "Snapper"):
if not hasattr(FreeCAD, "DraftWorkingPlane"):
FreeCAD.DraftWorkingPlane = WorkingPlane.plane()
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Commands that have been migrated to their own modules
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
import draftguitools.gui_edit
import draftguitools.gui_selectplane
import draftguitools.gui_planeproxy
# import DraftFillet
import drafttaskpanels.task_shapestring as task_shapestring
import drafttaskpanels.task_scale as task_scale
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Preflight stuff
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# update the translation engine
FreeCADGui.updateLocale()
@@ -86,10 +104,9 @@ MODCONSTRAIN = MODS[Draft.getParam("modconstrain",0)]
MODSNAP = MODS[Draft.getParam("modsnap",1)]
MODALT = MODS[Draft.getParam("modalt",2)]
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# General functions
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
def formatUnit(exp,unit="mm"):
'''returns a formatting string to set a number to the correct unit'''
return FreeCAD.Units.Quantity(exp,FreeCAD.Units.Length).UserString
@@ -221,12 +238,9 @@ def setMod(args,mod,state):
args["AltDown"] = state
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Base Class
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
class DraftTool:
"""The base class of all Draft Tools"""
@@ -296,7 +310,7 @@ class DraftTool:
pass
self.call = None
if self.commitList:
todo.delayCommit(self.commitList)
ToDo.delayCommit(self.commitList)
self.commitList = []
def commit(self,name,func):
@@ -334,10 +348,9 @@ class DraftTool:
return qr,sup,points,fil
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Geometry constructors
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
def redraw3DView():
"""redraw3DView(): forces a redraw of 3d view."""
try:
@@ -463,7 +476,7 @@ class Line(Creator):
# object already deleted, for some reason
pass
else:
todo.delay(self.doc.removeObject,old)
ToDo.delay(self.doc.removeObject, old)
self.obj = None
def undolast(self):
@@ -575,7 +588,7 @@ class Wire(Line):
pts = pts.replace("Vector","FreeCAD.Vector")
rems = ["FreeCAD.ActiveDocument.removeObject(\""+o.Name+"\")" for o in FreeCADGui.Selection.getSelection()]
FreeCADGui.addModule("Draft")
todo.delayCommit([(translate("draft","Convert to Wire"),
ToDo.delayCommit([(translate("draft", "Convert to Wire"),
['wire = Draft.makeWire(['+pts+'])']+rems+['Draft.autogroup(wire)',
'FreeCAD.ActiveDocument.recompute()'])])
return
@@ -665,7 +678,7 @@ class BSpline(Line):
if self.obj:
# remove temporary object, if any
old = self.obj.Name
todo.delay(self.doc.removeObject,old)
ToDo.delay(self.doc.removeObject, old)
if (len(self.node) > 1):
try:
# building command string
@@ -785,7 +798,7 @@ class BezCurve(Line):
if self.obj:
# remove temporary object, if any
old = self.obj.Name
todo.delay(self.doc.removeObject,old)
ToDo.delay(self.doc.removeObject, old)
if (len(self.node) > 1):
try:
# building command string
@@ -944,7 +957,7 @@ class CubicBezCurve(Line):
if self.obj:
# remove temporary object, if any
old = self.obj.Name
todo.delay(self.doc.removeObject,old)
ToDo.delay(self.doc.removeObject, old)
if closed == False :
cleannd=(len(self.node)-1) % self.degree
if cleannd == 0 : self.node = self.node[0:-3]
@@ -2225,14 +2238,22 @@ class Dimension(Creator):
if not self.cont:
self.finish()
class ShapeString(Creator):
"""This class creates a shapestring feature."""
"""The Draft_ShapeString FreeCAD command definition."""
def GetResources(self):
return {'Pixmap' : 'Draft_ShapeString',
'Accel' : "S, S",
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "Shape from text..."),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "Creates text string in shapes.")}
"""Set icon, menu and tooltip."""
_menu = "Shape from text"
_tooltip = ("Creates a shape from a text string by choosing "
"a specific font and a placement.\n"
"The closed shapes can be used for extrusions "
"and boolean operations.")
d = {'Pixmap': 'Draft_ShapeString',
'Accel': "S, S",
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", _menu),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", _tooltip)}
return d
def Activated(self):
name = translate("draft","ShapeString")
@@ -2248,7 +2269,7 @@ class ShapeString(Creator):
pass
self.task = task_shapestring.ShapeStringTaskPanel()
self.task.sourceCmd = self
todo.delay(FreeCADGui.Control.showDialog,self.task)
ToDo.delay(FreeCADGui.Control.showDialog, self.task)
else:
self.dialog = None
self.text = ''
@@ -2408,7 +2429,7 @@ class Move(Modifier):
ghost.finalize()
if cont and self.ui:
if self.ui.continueMode:
todo.delayAfter(self.Activated,[])
ToDo.delayAfter(self.Activated, [])
Modifier.finish(self)
def action(self,arg):
@@ -2750,7 +2771,7 @@ class Rotate(Modifier):
ghost.finalize()
if cont and self.ui:
if self.ui.continueMode:
todo.delayAfter(self.Activated,[])
ToDo.delayAfter(self.Activated, [])
Modifier.finish(self)
if self.doc:
self.doc.recompute()
@@ -4133,9 +4154,9 @@ class Scale(Modifier):
self.view.removeEventCallback("SoEvent",self.call)
self.task = task_scale.ScaleTaskPanel()
self.task.sourceCmd = self
todo.delay(FreeCADGui.Control.showDialog,self.task)
todo.delay(self.task.xValue.selectAll,None)
todo.delay(self.task.xValue.setFocus,None)
ToDo.delay(FreeCADGui.Control.showDialog, self.task)
ToDo.delay(self.task.xValue.selectAll, None)
ToDo.delay(self.task.xValue.setFocus, None)
for ghost in self.ghosts:
ghost.on()
elif len(self.node) == 2:
@@ -4788,7 +4809,7 @@ class Point(Creator):
['point = Draft.makePoint('+str(self.stack[0][0])+','+str(self.stack[0][1])+','+str(self.stack[0][2])+')',
'Draft.autogroup(point)',
'FreeCAD.ActiveDocument.recompute()']))
todo.delayCommit(commitlist)
ToDo.delayCommit(commitlist)
FreeCADGui.Snapper.off()
self.finish()
@@ -4856,7 +4877,7 @@ class Draft_Clone(Modifier):
def finish(self,close=False):
Modifier.finish(self,close=False)
if self.moveAfterCloning:
todo.delay(FreeCADGui.runCommand,"Draft_Move")
ToDo.delay(FreeCADGui.runCommand, "Draft_Move")
class ToggleGrid():
+32 -33
View File
@@ -1,19 +1,3 @@
## \defgroup DRAFTVECUTILS DraftVecUtils
# \ingroup UTILITIES
# \brief Vector math utilities used in Draft workbench
#
# Vector math utilities used primarily in the Draft workbench
# but which can also be used in other workbenches and in macros.
"""\defgroup DRAFTVECUTILS DraftVecUtils
\ingroup UTILITIES
\brief Vector math utilities used in Draft workbench
Vector math utilities used primarily in the Draft workbench
but which can also be used in other workbenches and in macros.
"""
# Check code with
# flake8 --ignore=E226,E266,E401,W503
# ***************************************************************************
# * Copyright (c) 2009, 2010 Yorik van Havre <[email protected]> *
# * Copyright (c) 2009, 2010 Ken Cline <[email protected]> *
@@ -35,19 +19,32 @@ but which can also be used in other workbenches and in macros.
# * USA *
# * *
# ***************************************************************************
"""Provide vector math utilities used in the Draft workbench.
Vector math utilities used primarily in the Draft workbench
but which can also be used in other workbenches and in macros.
"""
## \defgroup DRAFTVECUTILS DraftVecUtils
# \ingroup UTILITIES
# \brief Vector math utilities used in Draft workbench
#
# Vector math utilities used primarily in the Draft workbench
# but which can also be used in other workbenches and in macros.
# Check code with
# flake8 --ignore=E226,E266,E401,W503
import math
import sys
import FreeCAD
from FreeCAD import Vector
import draftutils.messages as messages
__title__ = "FreeCAD Draft Workbench - Vector library"
__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline"
__url__ = "https://www.freecadweb.org"
## \addtogroup DRAFTVECUTILS
# @{
import sys
import math, FreeCAD
from FreeCAD import Vector, Matrix
from FreeCAD import Console as FCC
# Python 2 has two integer types, int and long.
# In Python 3 there is no 'long' anymore, so make it 'int'.
try:
@@ -57,6 +54,9 @@ except NameError:
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
## \addtogroup DRAFTVECUTILS
# @{
def precision():
"""Get the number of decimal numbers used for precision.
@@ -97,16 +97,15 @@ def typecheck(args_and_types, name="?"):
Defaults to `'?'`. The name of the check.
Raises
-------
------
TypeError
If the first element in the tuple is not an instance of the second
element.
"""
for v, t in args_and_types:
if not isinstance(v, t):
_msg = ("typecheck[" + str(name) + "]: "
+ str(v) + " is not " + str(t) + "\n")
FCC.PrintWarning(_msg)
_msg = "typecheck[{0}]: {1} is not {2}".format(name, v, t)
messages._wrn(_msg)
raise TypeError("fcvec." + str(name))
@@ -208,7 +207,7 @@ def equals(u, v):
The second vector.
Returns
------
-------
bool
`True` if the vectors are within the precision, `False` otherwise.
"""
@@ -497,9 +496,9 @@ def rotate(u, angle, axis=Vector(0, 0, 1)):
ys = y * s
zs = z * s
m = Matrix(c + x*x*t, xyt - zs, xzt + ys, 0,
xyt + zs, c + y*y*t, yzt - xs, 0,
xzt - ys, yzt + xs, c + z*z*t, 0)
m = FreeCAD.Matrix(c + x*x*t, xyt - zs, xzt + ys, 0,
xyt + zs, c + y*y*t, yzt - xs, 0,
xzt - ys, yzt + xs, c + z*z*t, 0)
return m.multiply(u)
@@ -547,7 +546,7 @@ def getRotation(vector, reference=Vector(1, 0, 0)):
def isNull(vector):
"""Returns `False` if each of the components of the vector is zero.
"""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
+34 -29
View File
@@ -1,31 +1,36 @@
#***************************************************************************
#* Copyright (c) 2009 Yorik van Havre <[email protected]> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * Copyright (c) 2009 Yorik van Havre <[email protected]> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by 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 *
# * *
# ***************************************************************************
"""Initialization file of the workbench, non-GUI."""
import FreeCAD as App
# add Import/Export types
App.addImportType("Autodesk DXF 2D (*.dxf)","importDXF")
App.addImportType("SVG as geometry (*.svg)","importSVG")
App.addImportType("Open CAD Format (*.oca *.gcad)","importOCA")
App.addImportType("Common airfoil data (*.dat)","importAirfoilDAT")
App.addExportType("Autodesk DXF 2D (*.dxf)","importDXF")
App.addExportType("Flattened SVG (*.svg)","importSVG")
App.addExportType("Open CAD Format (*.oca)","importOCA")
App.addImportType("Autodesk DWG 2D (*.dwg)","importDWG")
App.addExportType("Autodesk DWG 2D (*.dwg)","importDWG")
App.addImportType("Autodesk DXF 2D (*.dxf)", "importDXF")
App.addImportType("SVG as geometry (*.svg)", "importSVG")
App.addImportType("Open CAD Format (*.oca *.gcad)", "importOCA")
App.addImportType("Common airfoil data (*.dat)", "importAirfoilDAT")
App.addExportType("Autodesk DXF 2D (*.dxf)", "importDXF")
App.addExportType("Flattened SVG (*.svg)", "importSVG")
App.addExportType("Open CAD Format (*.oca)", "importOCA")
App.addImportType("Autodesk DWG 2D (*.dwg)", "importDWG")
App.addExportType("Autodesk DWG 2D (*.dwg)", "importDWG")
App.__unit_test__ += ["TestDraft"]
+4 -2
View File
@@ -1,4 +1,3 @@
"""Initialization of the Draft workbench (graphical interface)."""
# ***************************************************************************
# * Copyright (c) 2009 Yorik van Havre <[email protected]> *
# * *
@@ -19,7 +18,10 @@
# * USA *
# * *
# ***************************************************************************
"""Initialization of the Draft workbench (graphical interface)."""
import os
import FreeCAD
import FreeCADGui
@@ -173,4 +175,4 @@ FreeCADGui.addPreferencePage(":/ui/preferences-dwg.ui", QT_TRANSLATE_NOOP("Draft
FreeCADGui.addPreferencePage(":/ui/preferences-svg.ui", QT_TRANSLATE_NOOP("Draft", "Import-Export"))
FreeCADGui.addPreferencePage(":/ui/preferences-oca.ui", QT_TRANSLATE_NOOP("Draft", "Import-Export"))
FreeCAD.__unit_test__ += ["TestDraft"]
FreeCAD.__unit_test__ += ["TestDraftGui"]
+1
View File
@@ -55,6 +55,7 @@
<file>icons/Draft_Offset.svg</file>
<file>icons/Draft_PathArray.svg</file>
<file>icons/Draft_PathLinkArray.svg</file>
<file>icons/Draft_PlaneProxy.svg</file>
<file>icons/Draft_Point.svg</file>
<file>icons/Draft_PointArray.svg</file>
<file>icons/Draft_PolarArray.svg</file>
@@ -0,0 +1,436 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
id="svg3612"
height="64px"
width="64px">
<defs
id="defs3614">
<linearGradient
id="linearGradient3809">
<stop
id="stop3811"
offset="0"
style="stop-color:#06989a;stop-opacity:1" />
<stop
id="stop3813"
offset="1"
style="stop-color:#34e0e2;stop-opacity:1" />
</linearGradient>
<radialGradient
r="34.345188"
fy="672.79736"
fx="225.26402"
cy="672.79736"
cx="225.26402"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
gradientUnits="userSpaceOnUse"
id="radialGradient3684"
xlink:href="#linearGradient3144-6" />
<linearGradient
id="linearGradient3144-6">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3146-9" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3148-2" />
</linearGradient>
<radialGradient
r="34.345188"
fy="672.79736"
fx="225.26402"
cy="672.79736"
cx="225.26402"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
gradientUnits="userSpaceOnUse"
id="radialGradient3686"
xlink:href="#linearGradient3144-6" />
<linearGradient
id="linearGradient3701">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3703" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3705" />
</linearGradient>
<radialGradient
r="34.345188"
fy="672.79736"
fx="225.26402"
cy="672.79736"
cx="225.26402"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
gradientUnits="userSpaceOnUse"
id="radialGradient3688"
xlink:href="#linearGradient3144-6" />
<linearGradient
id="linearGradient3708">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3710" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3712" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3144-6"
id="radialGradient3723"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
cx="225.26402"
cy="672.79736"
fx="225.26402"
fy="672.79736"
r="34.345188" />
<linearGradient
y2="115.01974"
x2="654.80023"
y1="77.046234"
x1="696.67322"
gradientTransform="matrix(0.2210246,-0.5789261,-0.71699693,-0.35346705,519.98085,464.19243)"
gradientUnits="userSpaceOnUse"
id="linearGradient3934"
xlink:href="#linearGradient3864-0-0" />
<linearGradient
id="linearGradient3864-0-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-5-7" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-7-6" />
</linearGradient>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="30.27434"
x2="619.30328"
y1="44.024342"
x1="597.77283"
id="linearGradient3942"
xlink:href="#linearGradient3377" />
<linearGradient
id="linearGradient3377">
<stop
style="stop-color:#ffaa00;stop-opacity:1;"
offset="0"
id="stop3379" />
<stop
style="stop-color:#faff2b;stop-opacity:1;"
offset="1"
id="stop3381" />
</linearGradient>
<linearGradient
y2="139.40982"
x2="650.70459"
y1="77.046234"
x1="696.67322"
gradientTransform="matrix(0.2210246,-0.5789261,-0.71699693,-0.35346705,536.41251,472.3612)"
gradientUnits="userSpaceOnUse"
id="linearGradient3657"
xlink:href="#linearGradient3864-0" />
<linearGradient
id="linearGradient3864-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-5" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-7" />
</linearGradient>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="10"
x2="22"
y1="52"
x1="34"
id="linearGradient3815"
xlink:href="#linearGradient3791-6" />
<linearGradient
id="linearGradient6349">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop6351" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop6353" />
</linearGradient>
<linearGradient
id="linearGradient3377-3">
<stop
style="stop-color:#0019a3;stop-opacity:1;"
offset="0"
id="stop3379-6" />
<stop
style="stop-color:#0069ff;stop-opacity:1;"
offset="1"
id="stop3381-7" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3377-3"
id="linearGradient3383"
x1="901.1875"
y1="1190.875"
x2="1267.9062"
y2="1190.875"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,1,2199.356,0)" />
<radialGradient
xlink:href="#linearGradient6349"
id="radialGradient6355"
cx="1103.6399"
cy="1424.4465"
fx="1103.6399"
fy="1424.4465"
r="194.40614"
gradientTransform="matrix(-1.4307499,-1.3605156e-7,-1.202713e-8,0.1264801,2674.7488,1244.2826)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3791-6">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3793-7" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3795-5" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3791-6"
id="linearGradient3820"
x1="939.98767"
y1="1097.5122"
x2="893.2572"
y2="989.77716"
gradientUnits="userSpaceOnUse" />
<linearGradient
y2="989.77716"
x2="893.2572"
y1="1097.5122"
x1="939.98767"
gradientUnits="userSpaceOnUse"
id="linearGradient3834-6"
xlink:href="#linearGradient3791-6"
gradientTransform="matrix(1.251547,0,0,1.2214422,104.06364,54.837797)" />
<linearGradient
xlink:href="#linearGradient3791-6"
id="linearGradient911"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.17119448,0,0,0.16707656,-190.70037,-126.91093)"
x1="939.98767"
y1="1097.5122"
x2="893.2572"
y2="1049.63" />
<linearGradient
xlink:href="#linearGradient3791-6"
id="linearGradient926"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.251547,0,0,1.2214422,104.06352,186.42979)"
x1="939.98773"
y1="989.77716"
x2="893.2572"
y2="941.8949" />
<linearGradient
id="linearGradient3354">
<stop
style="stop-color:#2157c7;stop-opacity:1;"
offset="0"
id="stop3356" />
<stop
style="stop-color:#6daaff;stop-opacity:1;"
offset="1"
id="stop3358" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0,-1.4500001,1.4705882,0,-15.05882,91.45)"
y2="36.079998"
x2="21.689653"
y1="29.279999"
x1="56.172409"
gradientUnits="userSpaceOnUse"
id="linearGradient3036"
xlink:href="#linearGradient3895" />
<linearGradient
id="linearGradient3895">
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="0"
id="stop3897" />
<stop
style="stop-color:#204a87;stop-opacity:1;"
offset="1"
id="stop3899" />
</linearGradient>
<linearGradient
y2="36.079998"
x2="21.689653"
y1="29.279999"
x1="56.172409"
gradientTransform="matrix(0,-0.58000003,0.58823527,0,13.176471,38.379999)"
gradientUnits="userSpaceOnUse"
id="linearGradient3918-3"
xlink:href="#linearGradient3895" />
<linearGradient
y2="36.079998"
x2="21.689653"
y1="29.279999"
x1="56.172409"
gradientTransform="matrix(0.58000003,0,0,0.58823527,25.620001,13.176471)"
gradientUnits="userSpaceOnUse"
id="linearGradient3029-6"
xlink:href="#linearGradient3895" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3154"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,-0.58000003,0.58823527,0,-64.65713,39.527336)"
x1="45.482754"
y1="11.599999"
x2="-23.482759"
y2="52.400002" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3156"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.58000003,0,0,0.58823527,-39.453602,14.323808)"
x1="31.689651"
y1="-2.0000007"
x2="-9.6896563"
y2="66" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3158"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.58000003,0,0,0.58823527,-52.2136,14.323808)"
x1="-9.6896563"
y1="-2.0000007"
x2="31.689651"
y2="66" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3160"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,0.58000003,0.58823527,0,-64.65713,26.767338)"
x1="-23.482759"
y1="11.599999"
x2="45.482754"
y2="52.400002" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3936"
x1="20"
y1="12"
x2="44"
y2="52"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-77.833601,1.147337)" />
</defs>
<path
style="fill:url(#linearGradient3815);fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 35,3 9,16 v 45 h 4 L 51.020744,40.40543 51,3 Z"
id="path3305" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3,19 35,3"
id="path3190" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 35.5,5 11,17.2 V 59 h 1.5 L 49,39.2 V 5 Z"
id="path3305-1" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3,43 61,11"
id="path3190-7" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 13,61 61,35"
id="path3190-9" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 51,61 61,55"
id="path3190-1" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 9,3 V 61"
id="path3224" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 31,3 V 61"
id="path3224-4" />
<path
id="rect3170"
d="M 19,25 43,13 V 33 L 19,45 Z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
style="fill:#16d0d2;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 51,3 V 61"
id="path3224-7" />
<metadata
id="metadata5520">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="" />
<dc:date>Mon Oct 10 13:44:52 2011 +0000</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[wmayer]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Draft/Resources/icons/Draft_PlaneProxy.svg</dc:identifier>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson, vocx</dc:title>
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag>
<rdf:li>rectangle</rdf:li>
<rdf:li>grid</rdf:li>
<rdf:li>plane</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>A rectangle sitting on a plane aligned to a grid that is going into the page from the left to the right; color variation</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="matrix(0.1378133,0,0,0.1378133,-299.23059,-137.20541)"
id="g4351" />
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

+18 -22
View File
@@ -1,12 +1,3 @@
"""Unit tests for the Draft workbench.
From the terminal, run the following:
FreeCAD -t TestDraft
From within FreeCAD, run the following:
import Test, TestDraft
Test.runTestsFromModule(TestDraft)
"""
# ***************************************************************************
# * Copyright (c) 2013 Yorik van Havre <[email protected]> *
# * Copyright (c) 2019 Eliud Cabrera Castillo <[email protected]> *
@@ -30,6 +21,17 @@ Test.runTestsFromModule(TestDraft)
# * USA *
# * *
# ***************************************************************************
"""Unit tests for the Draft workbench, non-GUI only.
From the terminal, run the following:
FreeCAD -t TestDraft
From within FreeCAD, run the following:
import Test, TestDraft
Test.runTestsFromModule(TestDraft)
For the GUI-only tests see TestDraftGui.
"""
# ===========================================================================
# The unit tests can be run from the operating system terminal, or from
@@ -94,20 +96,17 @@ Test.runTestsFromModule(TestDraft)
# Import tests
from drafttests.test_import import DraftImport as DraftTest01
from drafttests.test_import_gui import DraftGuiImport as DraftTest02
from drafttests.test_import_tools import DraftImportTools as DraftTest03
from drafttests.test_pivy import DraftPivy as DraftTest04
# Objects tests
from drafttests.test_creation import DraftCreation as DraftTest05
from drafttests.test_modification import DraftModification as DraftTest06
from drafttests.test_creation import DraftCreation as DraftTest02
from drafttests.test_modification import DraftModification as DraftTest03
# Handling of file formats tests
from drafttests.test_svg import DraftSVG as DraftTest07
from drafttests.test_dxf import DraftDXF as DraftTest08
from drafttests.test_dwg import DraftDWG as DraftTest09
from drafttests.test_oca import DraftOCA as DraftTest10
from drafttests.test_airfoildat import DraftAirfoilDAT as DraftTest11
from drafttests.test_svg import DraftSVG as DraftTest04
from drafttests.test_dxf import DraftDXF as DraftTest05
from drafttests.test_dwg import DraftDWG as DraftTest06
from drafttests.test_oca import DraftOCA as DraftTest07
from drafttests.test_airfoildat import DraftAirfoilDAT as DraftTest08
# Use the modules so that code checkers don't complain (flake8)
True if DraftTest01 else False
@@ -118,6 +117,3 @@ True if DraftTest05 else False
True if DraftTest06 else False
True if DraftTest07 else False
True if DraftTest08 else False
True if DraftTest09 else False
True if DraftTest10 else False
True if DraftTest11 else False
+105
View File
@@ -0,0 +1,105 @@
# ***************************************************************************
# * Copyright (c) 2013 Yorik van Havre <[email protected]> *
# * Copyright (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
# * 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 Draft workbench, GUI only.
From the terminal, run the following:
FreeCAD -t TestDraftGui
From within FreeCAD, run the following:
import Test, TestDraftGui
Test.runTestsFromModule(TestDraftGui)
For the non-GUI tests see TestDraft.
"""
# ===========================================================================
# The unit tests can be run from the operating system terminal, or from
# within FreeCAD itself.
#
# The tests can be run using the full 'FreeCAD' executable
# or the console only 'FreeCADCmd' executable. In the latter case
# some functions cannot be tested as the view providers (visual properties)
# are not available.
#
# ===========================================================================
# In the following, first the command to run the test from the operating
# system terminal is listed, followed by the commands to run the test
# from the Python console within FreeCAD.
#
# ===========================================================================
# Run all Draft tests
# ----
# FreeCAD -t TestDraft
#
# >>> import Test, TestDraft
# >>> Test.runTestsFromModule(TestDraft)
#
# ===========================================================================
# Run tests from a specific module (all classes within this module)
# ----
# FreeCAD -t drafttests.test_creation
#
# >>> import Test, drafttests.test_creation
# >>> Test.runTestsFromModule(drafttests.test_creation)
#
# ===========================================================================
# Run tests from a specific class within a module
# ----
# FreeCAD -t drafttests.test_creation.DraftCreation
#
# >>> import Test, drafttests.test_creation
# >>> Test.runTestsFromClass(drafttests.test_creation.DraftCreation)
#
# ===========================================================================
# Run a specific unit test from a class within a module
# ----
# FreeCAD -t drafttests.test_creation.DraftCreation.test_line
#
# >>> import unittest
# >>> one_test = "drafttests.test_creation.DraftCreation.test_line"
# >>> all_tests = unittest.TestLoader().loadTestsFromName(one_test)
# >>> unittest.TextTestRunner().run(all_tests)
# ===========================================================================
# When the full test is run
# FreeCAD -t TestDraft
#
# all classes that are found in this file are run.
#
# We import the classes from submodules. These classes contain
# the actual unit tests.
#
# The classes will be run in alphabetical order. So, to force
# a particular order of testing we import them with a name
# that follows a defined alphanumeric sequence.
# Import tests
from drafttests.test_import_gui import DraftGuiImport as DraftTestGui01
from drafttests.test_import_tools import DraftImportTools as DraftTestGui02
from drafttests.test_pivy import DraftPivy as DraftTestGui03
# Use the modules so that code checkers don't complain (flake8)
True if DraftTestGui01 else False
True if DraftTestGui02 else False
True if DraftTestGui03 else False
+104 -61
View File
@@ -1,20 +1,3 @@
## @package WorkingPlane
# \ingroup DRAFT
# \brief This module handles the Working Plane and grid of the Draft module.
#
# This module provides the plane class which provides a virtual working plane
# in FreeCAD and a couple of utility functions.
"""@package WorkingPlane
\ingroup DRAFT
\brief This module handles the working plane and grid of the Draft Workbench.
This module provides the plane class which provides a virtual working plane
in FreeCAD and a couple of utility functions.
The working plane is mostly intended to be used in the Draft Workbench
to draw 2D objects in various orientations, not only in the standard XY,
YZ, and XZ planes.
"""
# ***************************************************************************
# * Copyright (c) 2009, 2010 Ken Cline <[email protected]> *
# * *
@@ -35,64 +18,87 @@ YZ, and XZ planes.
# * USA *
# * *
# ***************************************************************************
"""Provide the working plane code and utilities for the Draft Workbench.
This module provides the plane class which provides a virtual working plane
in FreeCAD and a couple of utility functions.
The working plane is mostly intended to be used in the Draft Workbench
to draw 2D objects in various orientations, not only in the standard XY,
YZ, and XZ planes.
"""
## @package WorkingPlane
# \ingroup DRAFT
# \brief This module handles the Working Plane and grid of the Draft module.
#
# This module provides the plane class which provides a virtual working plane
# in FreeCAD and a couple of utility functions.
import FreeCAD, math, DraftVecUtils
import math
import FreeCAD
import DraftVecUtils
from FreeCAD import Vector
from FreeCAD import Console as FCC
__title__ = "FreeCAD Working Plane utility"
__author__ = "Ken Cline"
__url__ = "https://www.freecadweb.org"
class plane:
class Plane:
"""A WorkPlane object.
Parameters
----------
u: Base::Vector3, optional
An axis (vector) that helps define the working plane.
It defaults to `(1, 0, 0)`, or the +X axis.
v: Base::Vector3, optional
An axis (vector) that helps define the working plane.
It defaults to `(0, 1, 0)`, or the +Y axis.
w: Base::Vector3, optional
An axis that is supposed to be perpendicular to `u` and `v`;
it is redundant.
It defaults to `(0, 0, 1)`, or the +Z axis.
pos: Base::Vector3, optional
A point through which the plane goes through.
It defaults to the origin `(0, 0, 0)`.
Attributes
----------
doc : App::Document
doc: App::Document
The active document. Reset view when `doc` changes.
weak : bool
weak: bool
It is `True` if the plane has been defined by `setup()`
or has been reset. A weak plane can be changed
(it is the "auto" mode), while a strong plane will keep
its position until weakened (it is "locked")
u : Base::Vector3
u: Base::Vector3
An axis (vector) that helps define the working plane.
v : Base::Vector3
v: Base::Vector3
An axis (vector) that helps define the working plane.
axis : Base::Vector3
axis: Base::Vector3
A vector that is supposed to be perpendicular to `u` and `v`;
it is helpful although redundant.
position : Base::Vector3
position: Base::Vector3
A point, which the plane goes through,
that helps define the working plane.
stored : bool
stored: bool
A placeholder for a stored state.
"""
def __init__(self,
u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1),
pos=Vector(0, 0, 0)):
"""Initialize the working plane.
Parameters
----------
u : Base::Vector3, optional
An axis (vector) that helps define the working plane.
It defaults to `(1, 0, 0)`, or the +X axis.
v : Base::Vector3, optional
An axis (vector) that helps define the working plane.
It defaults to `(0, 1, 0)`, or the +Y axis.
w : Base::Vector3, optional
An axis that is supposed to be perpendicular to `u` and `v`;
it is redundant.
It defaults to `(0, 0, 1)`, or the +Z axis.
pos : Base::Vector3, optional
A point through which the plane goes through.
It defaults to the origin `(0, 0, 0)`.
"""
# keep track of active document. Reset view when doc changes.
self.doc = None
self.weak = True
@@ -122,6 +128,7 @@ class plane:
----------
p : Base::Vector3
The external point to consider.
direction : Base::Vector3, optional
The unit vector that indicates the direction of the distance.
@@ -326,8 +333,8 @@ class plane:
offsetVector.multiply(offset)
self.position = point.add(offsetVector)
self.weak = False
# FCC.PrintMessage("(position = " + str(self.position) + ")\n")
# FCC.PrintMessage(self.__repr__() + "\n")
# Console.PrintMessage("(position = " + str(self.position) + ")\n")
# Console.PrintMessage(self.__repr__() + "\n")
def alignToPointAndAxis_SVG(self, point, axis, offset=0):
"""Align the working plane to a point and an axis (vector).
@@ -436,14 +443,14 @@ class plane:
# spat_vec = self.u.cross(self.v)
# spat_res = spat_vec.dot(axis)
# FCC.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")
# Console.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")
offsetVector = Vector(axis)
offsetVector.multiply(offset)
self.position = point.add(offsetVector)
self.weak = False
# FCC.PrintMessage("(position = " + str(self.position) + ")\n")
# FCC.PrintMessage(self.__repr__() + "\n")
# Console.PrintMessage("(position = " + str(self.position) + ")\n")
# Console.PrintMessage(self.__repr__() + "\n")
def alignToCurve(self, shape, offset=0):
"""Align plane to curve. NOT YET IMPLEMENTED.
@@ -631,7 +638,7 @@ class plane:
When the interface is not loaded it should fail and print
a message, `FreeCAD.Console.PrintError()`.
See also
See Also
--------
alignToFace, alignToCurve
"""
@@ -652,7 +659,7 @@ class plane:
return False
def setup(self, direction=None, point=None, upvec=None, force=False):
"""Setup the working plane if it exists but is undefined.
"""Set up the working plane if it exists but is undefined.
If `direction` and `point` are present,
it calls `alignToPointAndAxis(point, direction, 0, upvec)`.
@@ -704,7 +711,7 @@ class plane:
# perpendicular to the current view
self.alignToPointAndAxis(Vector(0, 0, 0),
vdir.negative(), 0, upvec)
except:
except Exception:
pass
if force:
self.weak = False
@@ -719,6 +726,39 @@ class plane:
self.doc = None
self.weak = True
def setTop(self):
"""sets the WP to top position and updates the GUI"""
self.alignToPointAndAxis(FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(0, 0, 1), 0.0)
if FreeCAD.GuiUp:
import FreeCADGui
from draftutils.translate import translate
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.setGrid()
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.wplabel.setText(translate("draft", "Top"))
def setFront(self):
"""sets the WP to front position and updates the GUI"""
self.alignToPointAndAxis(FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(0, 1, 0), 0.0)
if FreeCAD.GuiUp:
import FreeCADGui
from draftutils.translate import translate
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.setGrid()
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.wplabel.setText(translate("draft", "Front"))
def setSide(self):
"""sets the WP to top position and updates the GUI"""
self.alignToPointAndAxis(FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(-1, 0, 0), 0.0)
if FreeCAD.GuiUp:
import FreeCADGui
from draftutils.translate import translate
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.setGrid()
if hasattr(FreeCADGui,"draftToolBar"):
FreeCADGui.draftToolBar.wplabel.setText(translate("draft", "Side"))
def getRotation(self):
"""Return a placement describing the plane orientation only.
@@ -878,7 +918,7 @@ class plane:
Base::Vector3
The relative coordinates of the point from the plane.
See also
See Also
--------
getGlobalCoords, getLocalRot, getGlobalRot
@@ -944,7 +984,7 @@ class plane:
Base::Vector3
The coordinates of the point from the absolute origin.
See also
See Also
--------
getLocalCoords, getLocalRot, getGlobalRot
@@ -999,7 +1039,7 @@ class plane:
The relative coordinates of the point from the plane,
if the plane had its `position` at the global origin.
See also
See Also
--------
getLocalCoords, getGlobalCoords, getGlobalRot
"""
@@ -1039,7 +1079,7 @@ class plane:
Base::Vector3
The coordinates of the point from the absolute origin.
See also
See Also
--------
getGlobalCoords, getLocalCoords, getLocalRot
"""
@@ -1144,7 +1184,7 @@ class plane:
Angle between the `u` vector, and a projected vector
on the global horizontal plane.
See also
See Also
--------
DraftVecUtils.angle
"""
@@ -1156,6 +1196,9 @@ class plane:
return DraftVecUtils.angle(self.u, proj, norm)
plane = Plane
def getPlacementFromPoints(points):
"""Return a placement from a list of 3 or 4 points.
@@ -1185,7 +1228,7 @@ def getPlacementFromPoints(points):
defined by `points`,
or `None` is it fails to use the points.
See also
See Also
--------
getPlacement
"""
@@ -1198,7 +1241,7 @@ def getPlacementFromPoints(points):
pl.axis = (points[3].sub(points[0]).normalize())
else:
pl.axis = ((pl.u).cross(pl.v)).normalize()
except:
except Exception:
return None
p = pl.getPlacement()
del pl
@@ -1229,14 +1272,14 @@ def getPlacementFromFace(face, rotated=False):
defined by `face`,
or `None` if it fails to use `face`.
See also
See Also
--------
alignToFace, getPlacement
"""
pl = plane()
try:
pl.alignToFace(face)
except:
except Exception:
return None
p = pl.getPlacement(rotated)
del pl
+6
View File
@@ -0,0 +1,6 @@
"""Commands that require the graphical user interface to work.
These GUI commands are called by buttons, menus, contextual menus,
toolbars, or other ways that require graphical widgets.
They are normally loaded in the workbench's `InitGui.py`.
"""
+11 -8
View File
@@ -1,8 +1,3 @@
"""Provide the Draft ArrayTools command to group the other array tools."""
## @package gui_arrays
# \ingroup DRAFT
# \brief Provide the Draft ArrayTools command to group the other array tools.
# ***************************************************************************
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -25,9 +20,14 @@
# * USA *
# * *
# ***************************************************************************
"""Provide the Draft ArrayTools command to group the other array tools."""
## @package gui_arrays
# \ingroup DRAFT
# \brief Provide the Draft ArrayTools command to group the other array tools.
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
from PySide.QtCore import QT_TRANSLATE_NOOP
class ArrayGroupCommand:
@@ -49,8 +49,11 @@ class ArrayGroupCommand:
'ToolTip': QT_TRANSLATE_NOOP("Arch", _tooltip)}
def IsActive(self):
"""Be active only when a document is active."""
return App.ActiveDocument is not None
"""Return True when this command should be available."""
if App.ActiveDocument:
return True
else:
return False
Gui.addCommand('Draft_ArrayTools', ArrayGroupCommand())
+10 -10
View File
@@ -1,9 +1,3 @@
"""This module provides the Base object for all Draft Gui commands.
"""
## @package gui_base
# \ingroup DRAFT
# \brief This module provides the Base object for all Draft Gui commands.
# ***************************************************************************
# * (c) 2009 Yorik van Havre <[email protected]> *
# * (c) 2010 Ken Cline <[email protected]> *
@@ -28,10 +22,14 @@
# * USA *
# * *
# ***************************************************************************
"""Provide the Base object for all Draft Gui commands."""
## @package gui_base
# \ingroup DRAFT
# \brief This module provides the Base object for all Draft Gui commands.
import FreeCAD as App
import FreeCADGui as Gui
import DraftGui
import draftutils.todo as todo
class GuiCommandBase:
@@ -52,7 +50,7 @@ class GuiCommandBase:
Each string in the list of strings represents a Python instruction
which will be executed in a delayed fashion
by `DraftGui.todo.delayCommit()`
by `todo.ToDo.delayCommit()`
::
list1 = ["a = FreeCAD.Vector()",
"pl = FreeCAD.Placement()",
@@ -69,6 +67,7 @@ class GuiCommandBase:
>>> pl = FreeCAD.Placement()
>>> Draft.autogroup(obj)
"""
def __init__(self):
self.call = None
self.commit_list = []
@@ -78,7 +77,8 @@ class GuiCommandBase:
self.planetrack = None
def IsActive(self):
if Gui.ActiveDocument:
"""Return True when this command should be available."""
if App.ActiveDocument:
return True
else:
return False
@@ -102,7 +102,7 @@ class GuiCommandBase:
pass
self.call = None
if self.commit_list:
DraftGui.todo.delayCommit(self.commit_list)
todo.ToDo.delayCommit(self.commit_list)
self.commit_list = []
def commit(self, name, func):
@@ -1,9 +1,3 @@
"""This module provides the Draft CircularArray tool.
"""
## @package gui_circulararray
# \ingroup DRAFT
# \brief This module provides the Draft CircularArray tool.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -26,41 +20,28 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the Draft CircularArray tool."""
## @package gui_circulararray
# \ingroup DRAFT
# \brief This module provides the Draft CircularArray tool.
from pivy import coin
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
import Draft
import DraftGui
import Draft_rc
from . import gui_base
from draftguitools import gui_base
from drafttaskpanels import task_circulararray
import draftutils.todo as todo
if App.GuiUp:
from PySide.QtCore import QT_TRANSLATE_NOOP
# import DraftTools
from DraftGui import translate
# from DraftGui import displayExternal
from pivy import coin
else:
def QT_TRANSLATE_NOOP(context, text):
return text
def translate(context, text):
return text
def _tr(text):
"""Function to translate with the context set"""
return translate("Draft", text)
# So the resource file doesn't trigger errors from code checkers (flake8)
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
class GuiCommandCircularArray(gui_base.GuiCommandBase):
"""Gui command for the CircularArray tool"""
"""Gui command for the CircularArray tool."""
def __init__(self):
super().__init__()
@@ -74,6 +55,7 @@ class GuiCommandCircularArray(gui_base.GuiCommandBase):
self.point = App.Vector()
def GetResources(self):
"""Set icon, menu and tooltip."""
_msg = ("Creates copies of a selected object, "
"and places the copies in a circular pattern.\n"
"The properties of the array can be further modified after "
@@ -85,7 +67,7 @@ class GuiCommandCircularArray(gui_base.GuiCommandBase):
return d
def Activated(self):
"""This is called when the command is executed.
"""Execute when the command is called.
We add callbacks that connect the 3D view with
the widgets of the task panel.
@@ -103,10 +85,10 @@ class GuiCommandCircularArray(gui_base.GuiCommandBase):
# of the interface, to be able to call a function from within it.
self.ui.source_command = self
# Gui.Control.showDialog(self.ui)
DraftGui.todo.delay(Gui.Control.showDialog, self.ui)
todo.ToDo.delay(Gui.Control.showDialog, self.ui)
def move(self, event_cb):
"""This is a callback for when the mouse pointer moves in the 3D view.
"""Execute as a callback when the pointer moves in the 3D view.
It should automatically update the coordinates in the widgets
of the task panel.
@@ -119,7 +101,7 @@ class GuiCommandCircularArray(gui_base.GuiCommandBase):
self.ui.display_point(self.point)
def click(self, event_cb=None):
"""This is a callback for when the mouse pointer clicks on the 3D view.
"""Execute as a callback when the pointer clicks on the 3D view.
It should act as if the Enter key was pressed, or the OK button
was pressed in the task panel.
@@ -136,7 +118,7 @@ class GuiCommandCircularArray(gui_base.GuiCommandBase):
self.ui.accept()
def completed(self):
"""This is called when the command is terminated.
"""Execute when the command is terminated.
We should remove the callbacks that were added to the 3D view
and then close the task panel.
@@ -146,10 +128,8 @@ class GuiCommandCircularArray(gui_base.GuiCommandBase):
self.view.removeEventCallbackPivy(self.mouse_event,
self.callback_click)
if Gui.Control.activeDialog():
Gui.Snapper.off()
Gui.Control.closeDialog()
super().finish()
if App.GuiUp:
Gui.addCommand('Draft_CircularArray', GuiCommandCircularArray())
Gui.addCommand('Draft_CircularArray', GuiCommandCircularArray())
File diff suppressed because it is too large Load Diff
+15 -35
View File
@@ -1,8 +1,3 @@
"""Provide the Draft OrthoArray tool."""
## @package gui_orthoarray
# \ingroup DRAFT
# \brief Provide the Draft OrthoArray tool.
# ***************************************************************************
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -25,36 +20,23 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the Draft OrthoArray GuiCommand."""
## @package gui_orthoarray
# \ingroup DRAFT
# \brief Provides the Draft OrthoArray GuiCommand.
from pivy import coin
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
import Draft
import DraftGui
import Draft_rc
from . import gui_base
from draftguitools import gui_base
from drafttaskpanels import task_orthoarray
import draftutils.todo as todo
if App.GuiUp:
from PySide.QtCore import QT_TRANSLATE_NOOP
# import DraftTools
from draftutils.translate import translate
# from DraftGui import displayExternal
from pivy import coin
else:
def QT_TRANSLATE_NOOP(context, text):
return text
def translate(context, text):
return text
def _tr(text):
"""Translate the text with the context set."""
return translate("Draft", text)
# So the resource file doesn't trigger errors from code checkers (flake8)
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
@@ -85,7 +67,7 @@ class GuiCommandOrthoArray(gui_base.GuiCommandBase):
return d
def Activated(self):
"""Execute this when the command is called.
"""Execute when the command is called.
We add callbacks that connect the 3D view with
the widgets of the task panel.
@@ -103,10 +85,10 @@ class GuiCommandOrthoArray(gui_base.GuiCommandBase):
# of the interface, to be able to call a function from within it.
self.ui.source_command = self
# Gui.Control.showDialog(self.ui)
DraftGui.todo.delay(Gui.Control.showDialog, self.ui)
todo.ToDo.delay(Gui.Control.showDialog, self.ui)
def click(self, event_cb=None):
"""Run callback for when the mouse pointer clicks on the 3D view.
"""Execute as a callback when the pointer clicks on the 3D view.
It should act as if the Enter key was pressed, or the OK button
was pressed in the task panel.
@@ -123,7 +105,7 @@ class GuiCommandOrthoArray(gui_base.GuiCommandBase):
self.ui.accept()
def completed(self):
"""Run when the command is terminated.
"""Execute when the command is terminated.
We should remove the callbacks that were added to the 3D view
and then close the task panel.
@@ -133,10 +115,8 @@ class GuiCommandOrthoArray(gui_base.GuiCommandBase):
self.view.removeEventCallbackPivy(self.mouse_event,
self.callback_click)
if Gui.Control.activeDialog():
Gui.Snapper.off()
Gui.Control.closeDialog()
super().finish()
if App.GuiUp:
Gui.addCommand('Draft_OrthoArray', GuiCommandOrthoArray())
Gui.addCommand('Draft_OrthoArray', GuiCommandOrthoArray())
@@ -0,0 +1,79 @@
# ***************************************************************************
# * Copyright (c) 2019 Yorik van Havre <[email protected]> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by 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 Draft WorkingPlaneProxy tool."""
## @package gui_planeproxy
# \ingroup DRAFT
# \brief This module provides the Draft WorkingPlaneProxy tool.
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
import Draft_rc
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
__title__ = "FreeCAD Draft Workbench GUI Tools - Working plane-related tools"
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
"Dmitry Chigrin")
__url__ = "https://www.freecadweb.org"
class Draft_WorkingPlaneProxy:
"""The Draft_WorkingPlaneProxy command definition."""
def GetResources(self):
"""Set icon, menu and tooltip."""
_menu = "Create working plane proxy"
_tip = ("Creates a proxy object from the current working plane.\n"
"Once the object is created double click it in the tree view "
"to restore the camera position and objects' visibilities.\n"
"Then you can use it to save a different camera position "
"and objects' states any time you need.")
d = {'Pixmap': 'Draft_PlaneProxy',
'MenuText': QT_TRANSLATE_NOOP("Draft_SetWorkingPlaneProxy",
_menu),
'ToolTip': QT_TRANSLATE_NOOP("Draft_SetWorkingPlaneProxy",
_tip)}
return d
def IsActive(self):
"""Return True when this command should be available."""
if Gui.ActiveDocument:
return True
else:
return False
def Activated(self):
"""Execute when the command is called."""
if hasattr(App, "DraftWorkingPlane"):
App.ActiveDocument.openTransaction("Create WP proxy")
Gui.addModule("Draft")
_cmd = "Draft.makeWorkingPlaneProxy("
_cmd += "FreeCAD.DraftWorkingPlane.getPlacement()"
_cmd += ")"
Gui.doCommand(_cmd)
App.ActiveDocument.commitTransaction()
App.ActiveDocument.recompute()
Gui.addCommand('Draft_WorkingPlaneProxy', Draft_WorkingPlaneProxy())
+18 -38
View File
@@ -1,9 +1,3 @@
"""This module provides the Draft PolarArray tool.
"""
## @package gui_polararray
# \ingroup DRAFT
# \brief This module provides the Draft PolarArray tool.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -26,41 +20,28 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the Draft PolarArray tool."""
## @package gui_polararray
# \ingroup DRAFT
# \brief This module provides the Draft PolarArray tool.
from pivy import coin
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
import Draft
import DraftGui
import Draft_rc
from . import gui_base
from draftguitools import gui_base
from drafttaskpanels import task_polararray
import draftutils.todo as todo
if App.GuiUp:
from PySide.QtCore import QT_TRANSLATE_NOOP
# import DraftTools
from DraftGui import translate
# from DraftGui import displayExternal
from pivy import coin
else:
def QT_TRANSLATE_NOOP(context, text):
return text
def translate(context, text):
return text
def _tr(text):
"""Function to translate with the context set"""
return translate("Draft", text)
# So the resource file doesn't trigger errors from code checkers (flake8)
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
class GuiCommandPolarArray(gui_base.GuiCommandBase):
"""Gui command for the PolarArray tool"""
"""Gui command for the PolarArray tool."""
def __init__(self):
super().__init__()
@@ -74,6 +55,7 @@ class GuiCommandPolarArray(gui_base.GuiCommandBase):
self.point = App.Vector()
def GetResources(self):
"""Set icon, menu and tooltip."""
_msg = ("Creates copies of a selected object, "
"and places the copies in a polar pattern.\n"
"The properties of the array can be further modified after "
@@ -85,7 +67,7 @@ class GuiCommandPolarArray(gui_base.GuiCommandBase):
return d
def Activated(self):
"""This is called when the command is executed.
"""Execute when the command is called.
We add callbacks that connect the 3D view with
the widgets of the task panel.
@@ -103,10 +85,10 @@ class GuiCommandPolarArray(gui_base.GuiCommandBase):
# of the interface, to be able to call a function from within it.
self.ui.source_command = self
# Gui.Control.showDialog(self.ui)
DraftGui.todo.delay(Gui.Control.showDialog, self.ui)
todo.ToDo.delay(Gui.Control.showDialog, self.ui)
def move(self, event_cb):
"""This is a callback for when the mouse pointer moves in the 3D view.
"""Execute as a callback when the pointer moves in the 3D view.
It should automatically update the coordinates in the widgets
of the task panel.
@@ -119,7 +101,7 @@ class GuiCommandPolarArray(gui_base.GuiCommandBase):
self.ui.display_point(self.point)
def click(self, event_cb=None):
"""This is a callback for when the mouse pointer clicks on the 3D view.
"""Execute as a callback when the pointer clicks on the 3D view.
It should act as if the Enter key was pressed, or the OK button
was pressed in the task panel.
@@ -136,7 +118,7 @@ class GuiCommandPolarArray(gui_base.GuiCommandBase):
self.ui.accept()
def completed(self):
"""This is called when the command is terminated.
"""Execute when the command is terminated.
We should remove the callbacks that were added to the 3D view
and then close the task panel.
@@ -146,10 +128,8 @@ class GuiCommandPolarArray(gui_base.GuiCommandBase):
self.view.removeEventCallbackPivy(self.mouse_event,
self.callback_click)
if Gui.Control.activeDialog():
Gui.Snapper.off()
Gui.Control.closeDialog()
super().finish()
if App.GuiUp:
Gui.addCommand('Draft_PolarArray', GuiCommandPolarArray())
Gui.addCommand('Draft_PolarArray', GuiCommandPolarArray())
+159 -147
View File
@@ -1,4 +1,3 @@
# -*- coding: utf8 -*-
# ***************************************************************************
# * Copyright (c) 2019 Yorik van Havre <[email protected]> *
# * *
@@ -19,23 +18,33 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the Draft SelectPlane tool."""
## @package gui_selectplane
# \ingroup DRAFT
# \brief This module provides the Draft SelectPlane tool.
__title__ = "FreeCAD Draft Workbench GUI Tools - Working plane-related tools"
__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, Dmitry Chigrin"
__url__ = "https://www.freecadweb.org"
import math
from pivy import coin
from PySide import QtGui
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import FreeCADGui
import math
import Draft
import Draft_rc
import DraftVecUtils
import drafttaskpanels.task_selectplane as task_selectplane
from draftutils.todo import todo
from draftutils.messages import _msg
from draftutils.translate import translate
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc.__name__ else False
def QT_TRANSLATE_NOOP(ctx,txt): return txt
__title__ = "FreeCAD Draft Workbench GUI Tools - Working plane-related tools"
__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
"Dmitry Chigrin")
__url__ = "https://www.freecadweb.org"
class Draft_SelectPlane:
@@ -48,10 +57,15 @@ class Draft_SelectPlane:
def GetResources(self):
"""Set icon, menu and tooltip."""
return {'Pixmap' : 'Draft_SelectPlane',
'Accel' : "W, P",
'MenuText': QT_TRANSLATE_NOOP("Draft_SelectPlane", "SelectPlane"),
'ToolTip' : QT_TRANSLATE_NOOP("Draft_SelectPlane", "Select a working plane for geometry creation")}
_msg = ("Select the face of solid body to create a working plane "
"on which to sketch Draft objects.\n"
"You may also select a three vertices or "
"a Working Plane Proxy.")
d = {'Pixmap': 'Draft_SelectPlane',
'Accel': "W, P",
'MenuText': QT_TRANSLATE_NOOP("Draft_SelectPlane", "SelectPlane"),
'ToolTip': QT_TRANSLATE_NOOP("Draft_SelectPlane", _msg)}
return d
def IsActive(self):
"""Return True when this command should be available."""
@@ -61,34 +75,33 @@ class Draft_SelectPlane:
return False
def Activated(self):
"""Execute this when the command is called."""
# reset variables
"""Execute when the command is called."""
# Reset variables
self.view = Draft.get3DView()
self.wpButton = FreeCADGui.draftToolBar.wplabel
FreeCAD.DraftWorkingPlane.setup()
# write current WP if states are empty
# Write current WP if states are empty
if not self.states:
p = FreeCAD.DraftWorkingPlane
self.states.append([p.u, p.v, p.axis, p.position])
m = translate("draft", "Pick a face, 3 vertices or a WP Proxy to define the drawing plane")
FreeCAD.Console.PrintMessage(m+"\n")
m = translate("draft", "Pick a face, 3 vertices "
"or a WP Proxy to define the drawing plane")
_msg(m)
from PySide import QtCore,QtGui
# create UI panel
# Create task panel
FreeCADGui.Control.closeDialog()
self.taskd = SelectPlane_TaskPanel()
self.taskd = task_selectplane.SelectPlaneTaskPanel()
# fill values
self.taskd.form.checkCenter.setChecked(self.param.GetBool("CenterPlaneOnView",False))
q = FreeCAD.Units.Quantity(self.param.GetFloat("gridSpacing",1.0),FreeCAD.Units.Length)
# Fill values
self.taskd.form.checkCenter.setChecked(self.param.GetBool("CenterPlaneOnView", False))
q = FreeCAD.Units.Quantity(self.param.GetFloat("gridSpacing", 1.0), FreeCAD.Units.Length)
self.taskd.form.fieldGridSpacing.setText(q.UserString)
self.taskd.form.fieldGridMainLine.setValue(self.param.GetInt("gridEvery",10))
self.taskd.form.fieldSnapRadius.setValue(self.param.GetInt("snapRange",8))
self.taskd.form.fieldGridMainLine.setValue(self.param.GetInt("gridEvery", 10))
self.taskd.form.fieldSnapRadius.setValue(self.param.GetInt("snapRange", 8))
# set icons
# Set icons
self.taskd.form.setWindowIcon(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"))
self.taskd.form.buttonTop.setIcon(QtGui.QIcon(":/icons/view-top.svg"))
self.taskd.form.buttonFront.setIcon(QtGui.QIcon(":/icons/view-front.svg"))
@@ -99,7 +112,7 @@ class Draft_SelectPlane:
self.taskd.form.buttonCenter.setIcon(QtGui.QIcon(":/icons/view-fullscreen.svg"))
self.taskd.form.buttonPrevious.setIcon(QtGui.QIcon(":/icons/edit-undo.svg"))
# connect slots
# Connect slots
self.taskd.form.buttonTop.clicked.connect(self.onClickTop)
self.taskd.form.buttonFront.clicked.connect(self.onClickFront)
self.taskd.form.buttonSide.clicked.connect(self.onClickSide)
@@ -112,57 +125,59 @@ class Draft_SelectPlane:
self.taskd.form.fieldGridMainLine.valueChanged.connect(self.onSetMainline)
self.taskd.form.fieldSnapRadius.valueChanged.connect(self.onSetSnapRadius)
# try to find a WP from the current selection
# Try to find a WP from the current selection
if self.handle():
return
# try other method
# Try another method
if FreeCAD.DraftWorkingPlane.alignToSelection():
FreeCADGui.Selection.clearSelection()
self.display(FreeCAD.DraftWorkingPlane.axis)
self.finish()
return
# rock 'n roll!
# Execute the actual task panel
FreeCADGui.Control.showDialog(self.taskd)
self.call = self.view.addEventCallback("SoEvent", self.action)
def finish(self,close=False):
def finish(self, close=False):
"""Execute when the command is terminated."""
# Store values
self.param.SetBool("CenterPlaneOnView",
self.taskd.form.checkCenter.isChecked())
# store values
self.param.SetBool("CenterPlaneOnView",self.taskd.form.checkCenter.isChecked())
# terminate coin callbacks
# Terminate coin callbacks
if self.call:
try:
self.view.removeEventCallback("SoEvent",self.call)
self.view.removeEventCallback("SoEvent", self.call)
except RuntimeError:
# the view has been deleted already
# The view has been deleted already
pass
self.call = None
# reset everything else
# Reset everything else
FreeCADGui.Control.closeDialog()
FreeCAD.DraftWorkingPlane.restore()
FreeCADGui.ActiveDocument.resetEdit()
return True
def reject(self):
"""Execute when clicking the Cancel button."""
self.finish()
return True
def action(self, arg):
"""Set the callbacks for the view."""
if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE":
self.finish()
if arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
# coin detection happens before the selection got a chance of being updated, so we must delay
todo.delay(self.checkSelection,None)
# Coin detection happens before the selection
# got a chance of being updated, so we must delay
todo.delay(self.checkSelection, None)
def checkSelection(self):
"""Check the selection, if there is a handle, finish the command."""
if self.handle():
self.finish()
@@ -175,18 +190,19 @@ class Draft_SelectPlane:
FreeCAD.DraftWorkingPlane.alignToEdges(sel.Object.Shape.Edges)
self.display(FreeCAD.DraftWorkingPlane.axis)
return True
elif Draft.getType(sel.Object) in ["WorkingPlaneProxy","BuildingPart"]:
FreeCAD.DraftWorkingPlane.setFromPlacement(sel.Object.Placement,rebase=True)
elif Draft.getType(sel.Object) in ("WorkingPlaneProxy",
"BuildingPart"):
FreeCAD.DraftWorkingPlane.setFromPlacement(sel.Object.Placement, rebase=True)
FreeCAD.DraftWorkingPlane.weak = False
if hasattr(sel.Object.ViewObject,"AutoWorkingPlane"):
if hasattr(sel.Object.ViewObject, "AutoWorkingPlane"):
if sel.Object.ViewObject.AutoWorkingPlane:
FreeCAD.DraftWorkingPlane.weak = True
if hasattr(sel.Object.ViewObject,"CutView") and hasattr(sel.Object.ViewObject,"AutoCutView"):
if hasattr(sel.Object.ViewObject, "CutView") and hasattr(sel.Object.ViewObject, "AutoCutView"):
if sel.Object.ViewObject.AutoCutView:
sel.Object.ViewObject.CutView = True
if hasattr(sel.Object.ViewObject,"RestoreView"):
if hasattr(sel.Object.ViewObject, "RestoreView"):
if sel.Object.ViewObject.RestoreView:
if hasattr(sel.Object.ViewObject,"ViewData"):
if hasattr(sel.Object.ViewObject, "ViewData"):
if len(sel.Object.ViewObject.ViewData) >= 12:
d = sel.Object.ViewObject.ViewData
camtype = "orthographic"
@@ -194,16 +210,15 @@ class Draft_SelectPlane:
if d[12] == 1:
camtype = "perspective"
c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
from pivy import coin
if isinstance(c,coin.SoOrthographicCamera):
if isinstance(c, coin.SoOrthographicCamera):
if camtype == "perspective":
FreeCADGui.ActiveDocument.ActiveView.setCameraType("Perspective")
elif isinstance(c,coin.SoPerspectiveCamera):
elif isinstance(c, coin.SoPerspectiveCamera):
if camtype == "orthographic":
FreeCADGui.ActiveDocument.ActiveView.setCameraType("Orthographic")
c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
c.position.setValue([d[0],d[1],d[2]])
c.orientation.setValue([d[3],d[4],d[5],d[6]])
c.position.setValue([d[0], d[1], d[2]])
c.orientation.setValue([d[3], d[4], d[5], d[6]])
c.nearDistance.setValue(d[7])
c.farDistance.setValue(d[8])
c.aspectRatio.setValue(d[9])
@@ -212,9 +227,9 @@ class Draft_SelectPlane:
c.height.setValue(d[11])
else:
c.heightAngle.setValue(d[11])
if hasattr(sel.Object.ViewObject,"RestoreState"):
if hasattr(sel.Object.ViewObject, "RestoreState"):
if sel.Object.ViewObject.RestoreState:
if hasattr(sel.Object.ViewObject,"VisibilityMap"):
if hasattr(sel.Object.ViewObject, "VisibilityMap"):
if sel.Object.ViewObject.VisibilityMap:
for k,v in sel.Object.ViewObject.VisibilityMap.items():
o = FreeCADGui.ActiveDocument.getObject(k)
@@ -226,7 +241,7 @@ class Draft_SelectPlane:
self.wpButton.setToolTip(translate("draft", "Current working plane")+": "+self.wpButton.text())
return True
elif Draft.getType(sel.Object) == "SectionPlane":
FreeCAD.DraftWorkingPlane.setFromPlacement(sel.Object.Placement,rebase=True)
FreeCAD.DraftWorkingPlane.setFromPlacement(sel.Object.Placement, rebase=True)
FreeCAD.DraftWorkingPlane.weak = False
self.display(FreeCAD.DraftWorkingPlane.axis)
self.wpButton.setText(sel.Object.Label)
@@ -239,7 +254,7 @@ class Draft_SelectPlane:
self.display(FreeCAD.DraftWorkingPlane.axis)
return True
elif sel.SubElementNames[0] == "Plane":
FreeCAD.DraftWorkingPlane.setFromPlacement(sel.Object.Placement,rebase=True)
FreeCAD.DraftWorkingPlane.setFromPlacement(sel.Object.Placement, rebase=True)
self.display(FreeCAD.DraftWorkingPlane.axis)
return True
elif len(sel.SubElementNames) == 3:
@@ -263,7 +278,7 @@ class Draft_SelectPlane:
import Part
for s in sel:
for so in s.SubObjects:
if isinstance(so,Part.Vertex):
if isinstance(so, Part.Vertex):
subs.append(so)
if len(subs) == 3:
FreeCAD.DraftWorkingPlane.alignTo3Points(subs[0].Point,
@@ -275,25 +290,31 @@ class Draft_SelectPlane:
return False
def getCenterPoint(self, x, y, z):
"""Get the center point."""
if not self.taskd.form.checkCenter.isChecked():
return FreeCAD.Vector()
v = FreeCAD.Vector(x,y,z)
cam1 = FreeCAD.Vector(FreeCADGui.ActiveDocument.ActiveView.getCameraNode().position.getValue().getValue())
v = FreeCAD.Vector(x, y, z)
view = FreeCADGui.ActiveDocument.ActiveView
camera = view.getCameraNode()
cam1 = FreeCAD.Vector(camera.position.getValue().getValue())
cam2 = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
vcam1 = DraftVecUtils.project(cam1,v)
vcam1 = DraftVecUtils.project(cam1, v)
a = vcam1.getAngle(cam2)
if a < 0.0001:
return FreeCAD.Vector()
d = vcam1.Length
L = d/math.cos(a)
vcam2 = DraftVecUtils.scaleTo(cam2,L)
vcam2 = DraftVecUtils.scaleTo(cam2, L)
cp = cam1.add(vcam2)
return cp
def tostr(self, v):
"""Make a string from a vector or tuple."""
return "FreeCAD.Vector("+str(v[0])+","+str(v[1])+","+str(v[2])+")"
string = "FreeCAD.Vector("
string += str(v[0]) + ", "
string += str(v[1]) + ", "
string += str(v[2]) + ")"
return string
def getOffset(self):
"""Return the offset value as a float in mm."""
@@ -305,48 +326,66 @@ class Draft_SelectPlane:
return o
def onClickTop(self):
o = str(self.getOffset())
FreeCADGui.doCommandGui(self.ac+"("+self.tostr(self.getCenterPoint(0,0,1))+","+self.tostr((0,0,1))+","+o+")")
"""Execute when pressing the top button."""
offset = str(self.getOffset())
_cmd = self.ac
_cmd += "("
_cmd += self.tostr(self.getCenterPoint(0, 0, 1)) + ", "
_cmd += self.tostr((0, 0, 1)) + ", "
_cmd += offset
_cmd += ")"
FreeCADGui.doCommandGui(_cmd)
self.display('Top')
self.finish()
def onClickFront(self):
o = str(self.getOffset())
FreeCADGui.doCommandGui(self.ac+"("+self.tostr(self.getCenterPoint(0,-1,0))+","+self.tostr((0,-1,0))+","+o+")")
"""Execute when pressing the front button."""
offset = str(self.getOffset())
_cmd = self.ac
_cmd += "("
_cmd += self.tostr(self.getCenterPoint(0, -1, 0)) + ", "
_cmd += self.tostr((0, -1, 0)) + ", "
_cmd += offset
_cmd += ")"
FreeCADGui.doCommandGui(_cmd)
self.display('Front')
self.finish()
def onClickSide(self):
o = str(self.getOffset())
FreeCADGui.doCommandGui(self.ac+"("+self.tostr(self.getCenterPoint(1,0,0))+","+self.tostr((1,0,0))+","+o+")")
"""Execute when pressing the side button."""
offset = str(self.getOffset())
_cmd = self.ac
_cmd += "("
_cmd += self.tostr(self.getCenterPoint(1, 0, 0)) + ", "
_cmd += self.tostr((1, 0, 0)) + ", "
_cmd += offset
_cmd += ")"
FreeCADGui.doCommandGui(_cmd)
self.display('Side')
self.finish()
def onClickAlign(self):
"""Execute when pressing the align."""
FreeCADGui.doCommandGui("FreeCAD.DraftWorkingPlane.setup(force=True)")
d = self.view.getViewDirection().negative()
self.display(d)
self.finish()
def onClickAuto(self):
"""Execute when pressing the auto button."""
FreeCADGui.doCommandGui("FreeCAD.DraftWorkingPlane.reset()")
self.display('Auto')
self.finish()
def onClickMove(self):
"""Execute when pressing the move button."""
sel = FreeCADGui.Selection.getSelectionEx()
if sel:
verts = []
import Part
for s in sel:
for so in s.SubObjects:
if isinstance(so,Part.Vertex):
if isinstance(so, Part.Vertex):
verts.append(so)
if len(verts) == 1:
target = verts[0].Point
@@ -358,13 +397,13 @@ class Draft_SelectPlane:
c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
p = FreeCAD.Vector(c.position.getValue().getValue())
d = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
pp = FreeCAD.DraftWorkingPlane.projectPoint(p,d)
pp = FreeCAD.DraftWorkingPlane.projectPoint(p, d)
FreeCAD.DraftWorkingPlane.position = pp
self.display(pp)
self.finish()
def onClickCenter(self):
"""Execute when pressing the center button."""
c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
r = FreeCAD.DraftWorkingPlane.getRotation().Rotation.Q
c.orientation.setValue(r)
@@ -377,7 +416,7 @@ class Draft_SelectPlane:
self.finish()
def onClickPrevious(self):
"""Execute when pressing the previous button."""
p = FreeCAD.DraftWorkingPlane
if len(self.states) > 1:
self.states.pop() # discard the last one
@@ -389,32 +428,32 @@ class Draft_SelectPlane:
FreeCADGui.Snapper.setGrid()
self.finish()
def onSetGridSize(self,text):
def onSetGridSize(self, text):
"""Execute when setting the grid size."""
try:
q = FreeCAD.Units.Quantity(text)
except:
except Exception:
pass
else:
self.param.SetFloat("gridSpacing",q.Value)
if hasattr(FreeCADGui,"Snapper"):
self.param.SetFloat("gridSpacing", q.Value)
if hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper.setGrid()
def onSetMainline(self,i):
def onSetMainline(self, i):
"""Execute when setting main line grid spacing."""
if i > 1:
self.param.SetInt("gridEvery",i)
if hasattr(FreeCADGui,"Snapper"):
self.param.SetInt("gridEvery", i)
if hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper.setGrid()
def onSetSnapRadius(self,i):
self.param.SetInt("snapRange",i)
def onSetSnapRadius(self, i):
"""Execute when setting the snap radius."""
self.param.SetInt("snapRange", i)
if hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper.showradius()
def display(self,arg):
"""Set the text of the working plane button."""
def display(self, arg):
"""Set the text of the working plane button in the toolbar."""
o = self.getOffset()
if o:
if o > 0:
@@ -423,63 +462,36 @@ class Draft_SelectPlane:
suffix = ' -O'
else:
suffix = ''
vdir = FreeCAD.DraftWorkingPlane.axis
vdir = '('+str(vdir.x)[:4]+','+str(vdir.y)[:4]+','+str(vdir.z)[:4]+')'
vdir = " "+translate("draft","Dir")+": "+vdir
if type(arg).__name__ == 'str':
self.wpButton.setText(arg+suffix)
_vdir = FreeCAD.DraftWorkingPlane.axis
vdir = '('
vdir += str(_vdir.x)[:4] + ','
vdir += str(_vdir.y)[:4] + ','
vdir += str(_vdir.z)[:4]
vdir += ')'
vdir = " " + translate("draft", "Dir") + ": " + vdir
if type(arg).__name__ == 'str':
self.wpButton.setText(arg + suffix)
if o != 0:
o = " "+translate("draft","Offset")+": "+str(o)
o = " " + translate("draft", "Offset") + ": " + str(o)
else:
o = ""
self.wpButton.setToolTip(translate("draft", "Current working plane")+": "+self.wpButton.text()+o+vdir)
_tool = translate("draft", "Current working plane") + ": "
_tool += self.wpButton.text() + o + vdir
self.wpButton.setToolTip(_tool)
elif type(arg).__name__ == 'Vector':
plv = '('+str(arg.x)[:6]+','+str(arg.y)[:6]+','+str(arg.z)[:6]+')'
self.wpButton.setText(translate("draft","Custom"))
self.wpButton.setToolTip(translate("draft", "Current working plane")+": "+plv+vdir)
plv = '('
plv += str(arg.x)[:6] + ','
plv += str(arg.y)[:6] + ','
plv += str(arg.z)[:6]
plv += ')'
self.wpButton.setText(translate("draft", "Custom"))
_tool = translate("draft", "Current working plane")
_tool += ": " + plv + vdir
self.wpButton.setToolTip(_tool)
p = FreeCAD.DraftWorkingPlane
self.states.append([p.u, p.v, p.axis, p.position])
FreeCADGui.doCommandGui("FreeCADGui.Snapper.setGrid()")
class SelectPlane_TaskPanel:
"""The task panel definition of the Draft_SelectPlane command."""
def __init__(self):
import Draft_rc
self.form = FreeCADGui.PySideUic.loadUi(":/ui/TaskSelectPlane.ui")
def getStandardButtons(self):
return 2097152 # int(QtGui.QDialogButtonBox.Close)
class Draft_SetWorkingPlaneProxy():
"""The Draft_SetWorkingPlaneProxy FreeCAD command definition"""
def GetResources(self):
"""Set icon, menu and tooltip."""
return {'Pixmap': 'Draft_SelectPlane',
'MenuText': QT_TRANSLATE_NOOP("Draft_SetWorkingPlaneProxy", "Create Working Plane Proxy"),
'ToolTip': QT_TRANSLATE_NOOP("Draft_SetWorkingPlaneProxy", "Creates a proxy object from the current working plane")}
def IsActive(self):
"""Return True when this command should be available."""
if FreeCADGui.ActiveDocument:
return True
else:
return False
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCAD, "DraftWorkingPlane"):
FreeCAD.ActiveDocument.openTransaction("Create WP proxy")
FreeCADGui.addModule("Draft")
FreeCADGui.doCommand("Draft.makeWorkingPlaneProxy(FreeCAD.DraftWorkingPlane.getPlacement())")
FreeCAD.ActiveDocument.recompute()
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.addCommand('Draft_SelectPlane', Draft_SelectPlane())
FreeCADGui.addCommand('Draft_SetWorkingPlaneProxy', Draft_SetWorkingPlaneProxy())
File diff suppressed because it is too large Load Diff
+68 -67
View File
@@ -1,9 +1,3 @@
"""Provide the Draft_Snap commands used by the snapping mechanism in Draft."""
## @package gui_snaps
# \ingroup DRAFT
# \brief Provide the Draft_Snap commands used by the snapping mechanism
# in Draft.
# ***************************************************************************
# * (c) 2009, 2010 Yorik van Havre <[email protected]> *
# * (c) 2009, 2010 Ken Cline <[email protected]> *
@@ -28,9 +22,16 @@
# * USA *
# * *
# ***************************************************************************
import FreeCADGui
"""Provide the Draft_Snap commands used by the snapping mechanism in Draft."""
## @package gui_snaps
# \ingroup DRAFT
# \brief Provide the Draft_Snap commands used by the snapping mechanism
# in Draft.
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCADGui as Gui
class Draft_Snap_Lock:
"""Command to activate or deactivate all snap commands."""
@@ -47,12 +48,12 @@ class Draft_Snap_Lock:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "masterbutton"):
FreeCADGui.Snapper.masterbutton.toggle()
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "masterbutton"):
Gui.Snapper.masterbutton.toggle()
FreeCADGui.addCommand('Draft_Snap_Lock', Draft_Snap_Lock())
Gui.addCommand('Draft_Snap_Lock', Draft_Snap_Lock())
class Draft_Snap_Midpoint:
@@ -68,14 +69,14 @@ class Draft_Snap_Midpoint:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonmidpoint":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Midpoint', Draft_Snap_Midpoint())
Gui.addCommand('Draft_Snap_Midpoint', Draft_Snap_Midpoint())
class Draft_Snap_Perpendicular:
@@ -93,14 +94,14 @@ class Draft_Snap_Perpendicular:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonperpendicular":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Perpendicular', Draft_Snap_Perpendicular())
Gui.addCommand('Draft_Snap_Perpendicular', Draft_Snap_Perpendicular())
class Draft_Snap_Grid:
@@ -115,14 +116,14 @@ class Draft_Snap_Grid:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtongrid":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Grid', Draft_Snap_Grid())
Gui.addCommand('Draft_Snap_Grid', Draft_Snap_Grid())
class Draft_Snap_Intersection:
@@ -140,14 +141,14 @@ class Draft_Snap_Intersection:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonintersection":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Intersection', Draft_Snap_Intersection())
Gui.addCommand('Draft_Snap_Intersection', Draft_Snap_Intersection())
class Draft_Snap_Parallel:
@@ -163,14 +164,14 @@ class Draft_Snap_Parallel:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonparallel":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Parallel', Draft_Snap_Parallel())
Gui.addCommand('Draft_Snap_Parallel', Draft_Snap_Parallel())
class Draft_Snap_Endpoint:
@@ -186,14 +187,14 @@ class Draft_Snap_Endpoint:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonendpoint":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Endpoint', Draft_Snap_Endpoint())
Gui.addCommand('Draft_Snap_Endpoint', Draft_Snap_Endpoint())
class Draft_Snap_Angle:
@@ -208,14 +209,14 @@ class Draft_Snap_Angle:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonangle":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Angle', Draft_Snap_Angle())
Gui.addCommand('Draft_Snap_Angle', Draft_Snap_Angle())
class Draft_Snap_Center:
@@ -230,14 +231,14 @@ class Draft_Snap_Center:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtoncenter":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Center', Draft_Snap_Center())
Gui.addCommand('Draft_Snap_Center', Draft_Snap_Center())
class Draft_Snap_Extension:
@@ -253,14 +254,14 @@ class Draft_Snap_Extension:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonextension":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Extension', Draft_Snap_Extension())
Gui.addCommand('Draft_Snap_Extension', Draft_Snap_Extension())
class Draft_Snap_Near:
@@ -275,14 +276,14 @@ class Draft_Snap_Near:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonpassive":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Near', Draft_Snap_Near())
Gui.addCommand('Draft_Snap_Near', Draft_Snap_Near())
class Draft_Snap_Ortho:
@@ -297,14 +298,14 @@ class Draft_Snap_Ortho:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonortho":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Ortho', Draft_Snap_Ortho())
Gui.addCommand('Draft_Snap_Ortho', Draft_Snap_Ortho())
class Draft_Snap_Special:
@@ -320,14 +321,14 @@ class Draft_Snap_Special:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonspecial":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Special', Draft_Snap_Special())
Gui.addCommand('Draft_Snap_Special', Draft_Snap_Special())
class Draft_Snap_Dimensions:
@@ -343,14 +344,14 @@ class Draft_Snap_Dimensions:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonDimensions":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_Dimensions', Draft_Snap_Dimensions())
Gui.addCommand('Draft_Snap_Dimensions', Draft_Snap_Dimensions())
class Draft_Snap_WorkingPlane:
@@ -368,11 +369,11 @@ class Draft_Snap_WorkingPlane:
def Activated(self):
"""Execute this when the command is called."""
if hasattr(FreeCADGui, "Snapper"):
if hasattr(FreeCADGui.Snapper, "toolbarButtons"):
for b in FreeCADGui.Snapper.toolbarButtons:
if hasattr(Gui, "Snapper"):
if hasattr(Gui.Snapper, "toolbarButtons"):
for b in Gui.Snapper.toolbarButtons:
if b.objectName() == "SnapButtonWorkingPlane":
b.toggle()
FreeCADGui.addCommand('Draft_Snap_WorkingPlane', Draft_Snap_WorkingPlane())
Gui.addCommand('Draft_Snap_WorkingPlane', Draft_Snap_WorkingPlane())
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
"""Functions and classes that define custom scripted objects.
These classes define a custom object which is based on one of the core
objects defined in C++. The custom object inherits some basic properties,
and new properties are added.
Most Draft objects are based on Part::Part2DObject.
"""
+46 -22
View File
@@ -1,8 +1,3 @@
"""Provides the object code for Draft Arc_3Points."""
## @package arc_3points
# \ingroup DRAFT
# \brief Provides the object code for Draft Arc_3Points.
# ***************************************************************************
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -25,14 +20,21 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the object code for Draft Arc_3Points."""
## @package arc_3points
# \ingroup DRAFT
# \brief Provides the object code for Draft Arc_3Points.
import math
import FreeCAD as App
import Part
import Draft
from draftutils.messages import _msg, _err, _log
import draftutils.utils as utils
from draftutils.messages import _msg, _err
from draftutils.translate import _tr
if App.GuiUp:
import draftutils.gui_utils as gui_utils
import draftutils.gui_utils as gui_utils
def make_arc_3points(points, placement=None, face=False,
@@ -109,40 +111,62 @@ def make_arc_3points(points, placement=None, face=False,
Normally it returns a parametric Draft object (`Part::Part2DObject`).
If `primitive` is `True`, it returns a basic `Part::Feature`.
"""
_log("make_arc_3points")
_msg(16 * "-")
_msg(_tr("Arc by 3 points"))
_name = "make_arc_3points"
utils.print_header(_name, "Arc by 3 points")
if not isinstance(points, (list, tuple)):
_err(_tr("Wrong input: must be list or tuple of three points."))
try:
utils.type_check([(points, (list, tuple))], name=_name)
except TypeError:
_err(_tr("Points: ") + "{}".format(points))
_err(_tr("Wrong input: "
"must be list or tuple of three points exactly."))
return None
if len(points) != 3:
_err(_tr("Wrong input: must be three points."))
_err(_tr("Points: ") + "{}".format(points))
_err(_tr("Wrong input: "
"must be list or tuple of three points exactly."))
return None
if placement is not None:
if not isinstance(placement, App.Placement):
_err(_tr("Wrong input: incorrect placement"))
try:
utils.type_check([(placement, App.Placement)], name=_name)
except TypeError:
_err(_tr("Placement: ") + "{}".format(placement))
_err(_tr("Wrong input: incorrect type of placement."))
return None
p1, p2, p3 = points
_edge = Part.Arc(p1, p2, p3)
_msg("p1: {}".format(p1))
_msg("p2: {}".format(p2))
_msg("p3: {}".format(p3))
try:
utils.type_check([(p1, App.Vector),
(p2, App.Vector),
(p3, App.Vector)], name=_name)
except TypeError:
_err(_tr("Wrong input: incorrect type of points."))
return None
try:
_edge = Part.Arc(p1, p2, p3)
except Part.OCCError as error:
_err(_tr("Cannot generate shape: ") + "{}".format(error))
return None
edge = _edge.toShape()
radius = edge.Curve.Radius
center = edge.Curve.Center
_msg("p1: {}".format(p1))
_msg("p2: {}".format(p2))
_msg("p3: {}".format(p3))
_msg(_tr("Radius: ") + "{}".format(radius))
_msg(_tr("Center: ") + "{}".format(center))
if primitive:
_msg(_tr("Create primitive object"))
obj = App.ActiveDocument.addObject("Part::Feature", "Arc")
obj.Shape = edge
_msg(_tr("Primitive object"))
return obj
rot = App.Rotation(edge.Curve.XAxis,
@@ -168,8 +192,8 @@ def make_arc_3points(points, placement=None, face=False,
_msg(_tr("Face: True"))
if support:
_msg(_tr("Support: ") + "{}".format(support))
obj.MapMode = map_mode
_msg(_tr("Map mode: " + "{}".format(map_mode)))
obj.MapMode = map_mode
if placement:
obj.AttachmentOffset.Base = placement.Base
obj.AttachmentOffset.Rotation = original_placement.Rotation
+117 -13
View File
@@ -1,9 +1,3 @@
"""This module provides the object code for Draft CircularArray.
"""
## @package circulararray
# \ingroup DRAFT
# \brief This module provides the object code for Draft CircularArray.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -26,20 +20,130 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the object code for Draft CircularArray."""
## @package circulararray
# \ingroup DRAFT
# \brief This module provides the object code for Draft CircularArray.
import FreeCAD as App
import Draft
import draftutils.utils as utils
from draftutils.messages import _msg, _err
from draftutils.translate import _tr
def make_circular_array(obj,
r_distance=100, tan_distance=100,
axis=App.Vector(0, 0, 1), center=App.Vector(0, 0, 0),
number=2, symmetry=1,
use_link=False):
axis=App.Vector(0, 0, 1), center=App.Vector(0, 0, 0),
use_link=True):
"""Create a circular array from the given object.
Parameters
----------
obj: Part::Feature
Any type of object that has a `Part::TopoShape`
that can be duplicated.
r_distance: float, optional
It defaults to `100`.
Radial distance to the next ring of circular arrays.
tan_distance: float, optional
It defaults to `100`.
The tangential distance between two elements located
in the same circular ring.
The tangential distance together with the radial distance
determine how many copies are created.
number: int, optional
It defaults to 2.
The number of layers or rings of repeated objects.
The original object stays at the center, and is counted
as a layer itself. So, if you want at least one layer of circular
copies, this number must be at least 2.
symmetry: int, optional
It defaults to 1.
It indicates how many lines of symmetry the entire circular pattern
has. That is, with 1, the array is symmetric only after a full
360 degrees rotation.
When it is 2, the array is symmetric at 0 and 180 degrees.
When it is 3, the array is symmetric at 0, 120, and 240 degrees.
When it is 4, the array is symmetric at 0, 90, 180, and 270 degrees.
Et cetera.
axis: Base::Vector3, optional
It defaults to `App.Vector(0, 0, 1)` or the `+Z` axis.
The unit vector indicating the axis of rotation.
center: Base::Vector3, optional
It defaults to `App.Vector(0, 0, 0)` or the global origin.
The point through which the `axis` passes to define
the axis of rotation.
use_link: bool, optional
It defaults to `True`.
If it is `True` the produced copies are not `Part::TopoShape` copies,
but rather `App::Link` objects.
The Links repeat the shape of the original `obj` exactly,
and therefore the resulting array is more memory efficient.
Also, when `use_link` is `True`, the `Fuse` property
of the resulting array does not work; the array doesn't
contain separate shapes, it only has the original shape repeated
many times, so there is nothing to fuse together.
If `use_link` is `False` the original shape is copied many times.
In this case the `Fuse` property is able to fuse
all copies into a single object, if they touch each other.
Returns
-------
Part::FeaturePython
A scripted object with `Proxy.Type='Array'`.
Its `Shape` is a compound of the copies of the original object.
"""
obj = Draft.makeArray(obj,
arg1=r_distance, arg2=tan_distance,
arg3=axis, arg4=center, arg5=number, arg6=symmetry,
use_link=use_link)
return obj
_name = "make_circular_array"
utils.print_header(_name, _tr("Circular array"))
_msg("r_distance: {}".format(r_distance))
_msg("tan_distance: {}".format(tan_distance))
try:
utils.type_check([(r_distance, (int, float, App.Units.Quantity)),
(tan_distance, (int, float, App.Units.Quantity))],
name=_name)
except TypeError:
_err(_tr("Wrong input: must be a number or quantity."))
return None
_msg("number: {}".format(number))
_msg("symmetry: {}".format(symmetry))
try:
utils.type_check([(number, int),
(symmetry, int)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be an integer number."))
return None
_msg("axis: {}".format(axis))
_msg("center: {}".format(center))
try:
utils.type_check([(axis, App.Vector),
(center, App.Vector)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be a vector."))
return None
_msg("use_link: {}".format(bool(use_link)))
new_obj = Draft.makeArray(obj,
arg1=r_distance, arg2=tan_distance,
arg3=axis, arg4=center,
arg5=number, arg6=symmetry,
use_link=use_link)
return new_obj
+376 -22
View File
@@ -1,8 +1,3 @@
"""Provide the object code for Draft Array."""
## @package orthoarray
# \ingroup DRAFT
# \brief Provide the object code for Draft Array.
# ***************************************************************************
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -25,9 +20,16 @@
# * USA *
# * *
# ***************************************************************************
"""Provide the object code for Draft Array."""
## @package orthoarray
# \ingroup DRAFT
# \brief Provide the object code for Draft Array.
import FreeCAD as App
import Draft
import draftutils.utils as utils
from draftutils.messages import _msg, _wrn, _err
from draftutils.translate import _tr
def make_ortho_array(obj,
@@ -37,24 +39,376 @@ def make_ortho_array(obj,
n_x=2,
n_y=2,
n_z=1,
use_link=False):
"""Create an orthogonal array from the given object."""
obj = Draft.makeArray(obj,
arg1=v_x, arg2=v_y, arg3=v_z,
arg4=n_x, arg5=n_y, arg6=n_z,
use_link=use_link)
return obj
use_link=True):
"""Create an orthogonal array from the given object.
Parameters
----------
obj: Part::Feature
Any type of object that has a `Part::TopoShape`
that can be duplicated.
This means most 2D and 3D objects produced
with any workbench.
v_x, v_y, v_z: Base::Vector3, optional
The vector indicating the vector displacement between two elements
in the specified orthogonal direction X, Y, Z.
By default:
::
v_x = App.Vector(10, 0, 0)
v_y = App.Vector(0, 10, 0)
v_z = App.Vector(0, 0, 10)
Given that this is a vectorial displacement
the next object can appear displaced in one, two or three axes
at the same time.
For example
::
v_x = App.Vector(10, 5, 0)
means that the next element in the X direction will be displaced
10 mm in X, 5 mm in Y, and 0 mm in Z.
A traditional "rectangular" array is obtained when
the displacement vector only has its corresponding component,
like in the default case.
If these values are entered as single numbers instead
of vectors, the single value is expanded into a vector
of the corresponding direction, and the other components are assumed
to be zero.
For example
::
v_x = 15
v_y = 10
v_z = 1
becomes
::
v_x = App.Vector(15, 0, 0)
v_y = App.Vector(0, 10, 0)
v_z = App.Vector(0, 0, 1)
n_x, n_y, n_z: int, optional
The number of copies in the specified orthogonal direction X, Y, Z.
This number includes the original object, therefore, it must be
at least 1.
The values of `n_x` and `n_y` default to 2,
while `n_z` defaults to 1.
This means the array by default is a planar array.
use_link: bool, optional
It defaults to `True`.
If it is `True` the produced copies are not `Part::TopoShape` copies,
but rather `App::Link` objects.
The Links repeat the shape of the original `obj` exactly,
and therefore the resulting array is more memory efficient.
Also, when `use_link` is `True`, the `Fuse` property
of the resulting array does not work; the array doesn't
contain separate shapes, it only has the original shape repeated
many times, so there is nothing to fuse together.
If `use_link` is `False` the original shape is copied many times.
In this case the `Fuse` property is able to fuse
all copies into a single object, if they touch each other.
Returns
-------
Part::FeaturePython
A scripted object with `Proxy.Type='Array'`.
Its `Shape` is a compound of the copies of the original object.
See Also
--------
make_ortho_array2d, make_rect_array, make_rect_array2d
"""
_name = "make_ortho_array"
utils.print_header(_name, _tr("Orthogonal array"))
_msg("v_x: {}".format(v_x))
_msg("v_y: {}".format(v_y))
_msg("v_z: {}".format(v_z))
try:
utils.type_check([(v_x, (int, float, App.Vector)),
(v_y, (int, float, App.Vector)),
(v_z, (int, float, App.Vector))],
name=_name)
except TypeError:
_err(_tr("Wrong input: must be a number or vector."))
return None
_text = "Input: single value expanded to vector."
if not isinstance(v_x, App.Vector):
v_x = App.Vector(v_x, 0, 0)
_wrn(_tr(_text))
if not isinstance(v_y, App.Vector):
v_y = App.Vector(0, v_y, 0)
_wrn(_tr(_text))
if not isinstance(v_z, App.Vector):
v_z = App.Vector(0, 0, v_z)
_wrn(_tr(_text))
_msg("n_x: {}".format(n_x))
_msg("n_y: {}".format(n_y))
_msg("n_z: {}".format(n_z))
try:
utils.type_check([(n_x, int),
(n_y, int),
(n_z, int)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be an integer number."))
return None
_text = ("Input: number of elements must be at least 1. "
"It is set to 1.")
if n_x < 1:
_wrn(_tr(_text))
n_x = 1
if n_y < 1:
_wrn(_tr(_text))
n_y = 1
if n_z < 1:
_wrn(_tr(_text))
n_z = 1
_msg("use_link: {}".format(bool(use_link)))
new_obj = Draft.makeArray(obj,
arg1=v_x, arg2=v_y, arg3=v_z,
arg4=n_x, arg5=n_y, arg6=n_z,
use_link=use_link)
return new_obj
def make_ortho_array2(obj,
v_x=App.Vector(10, 0, 0),
v_y=App.Vector(0, 10, 0),
def make_ortho_array2d(obj,
v_x=App.Vector(10, 0, 0),
v_y=App.Vector(0, 10, 0),
n_x=2,
n_y=2,
use_link=True):
"""Create a 2D orthogonal array from the given object.
This works the same as `make_ortho_array`.
The Z component is ignored so it only considers vector displacements
in X and Y directions.
Parameters
----------
obj: Part::Feature
Any type of object that has a `Part::TopoShape`
that can be duplicated.
This means most 2D and 3D objects produced
with any workbench.
v_x, v_y: Base::Vector3, optional
Vectorial displacement of elements
in the corresponding X and Y directions.
See `make_ortho_array`.
n_x, n_y: int, optional
Number of elements
in the corresponding X and Y directions.
See `make_ortho_array`.
use_link: bool, optional
If it is `True`, create `App::Link` array.
See `make_ortho_array`.
Returns
-------
Part::FeaturePython
A scripted object with `Proxy.Type='Array'`.
Its `Shape` is a compound of the copies of the original object.
See Also
--------
make_ortho_array, make_rect_array, make_rect_array2d
"""
_name = "make_ortho_array2d"
utils.print_header(_name, _tr("Orthogonal array 2D"))
_msg("v_x: {}".format(v_x))
_msg("v_y: {}".format(v_y))
try:
utils.type_check([(v_x, (int, float, App.Vector)),
(v_y, (int, float, App.Vector))],
name=_name)
except TypeError:
_err(_tr("Wrong input: must be a number or vector."))
return None
_text = "Input: single value expanded to vector."
if not isinstance(v_x, App.Vector):
v_x = App.Vector(v_x, 0, 0)
_wrn(_tr(_text))
if not isinstance(v_y, App.Vector):
v_y = App.Vector(0, v_y, 0)
_wrn(_tr(_text))
_msg("n_x: {}".format(n_x))
_msg("n_y: {}".format(n_y))
try:
utils.type_check([(n_x, int),
(n_y, int)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be an integer number."))
return None
_text = ("Input: number of elements must be at least 1. "
"It is set to 1.")
if n_x < 1:
_wrn(_tr(_text))
n_x = 1
if n_y < 1:
_wrn(_tr(_text))
n_y = 1
_msg("use_link: {}".format(bool(use_link)))
new_obj = Draft.makeArray(obj,
arg1=v_x, arg2=v_y,
arg3=n_x, arg4=n_y,
use_link=use_link)
return new_obj
def make_rect_array(obj,
d_x=10,
d_y=10,
d_z=10,
n_x=2,
n_y=2,
n_z=1,
use_link=True):
"""Create a rectangular array from the given object.
This function wraps around `make_ortho_array`
to produce strictly rectangular arrays, in which
the displacement vectors `v_x`, `v_y`, and `v_z`
only have their respective components in X, Y, and Z.
Parameters
----------
obj: Part::Feature
Any type of object that has a `Part::TopoShape`
that can be duplicated.
This means most 2D and 3D objects produced
with any workbench.
d_x, d_y, d_z: Base::Vector3, optional
Displacement of elements in the corresponding X, Y, and Z directions.
n_x, n_y, n_z: int, optional
Number of elements in the corresponding X, Y, and Z directions.
use_link: bool, optional
If it is `True`, create `App::Link` array.
See `make_ortho_array`.
Returns
-------
Part::FeaturePython
A scripted object with `Proxy.Type='Array'`.
Its `Shape` is a compound of the copies of the original object.
See Also
--------
make_ortho_array, make_ortho_array2d, make_rect_array2d
"""
_name = "make_rect_array"
utils.print_header(_name, _tr("Rectangular array"))
_msg("d_x: {}".format(d_x))
_msg("d_y: {}".format(d_y))
_msg("d_z: {}".format(d_z))
try:
utils.type_check([(d_x, (int, float)),
(d_y, (int, float)),
(d_z, (int, float))],
name=_name)
except TypeError:
_err(_tr("Wrong input: must be a number."))
return None
new_obj = make_ortho_array(obj,
v_x=App.Vector(d_x, 0, 0),
v_y=App.Vector(0, d_y, 0),
v_z=App.Vector(0, 0, d_z),
n_x=n_x,
n_y=n_y,
n_z=n_z,
use_link=use_link)
return new_obj
def make_rect_array2d(obj,
d_x=10,
d_y=10,
n_x=2,
n_y=2,
use_link=False):
"""Create a 2D orthogonal array from the given object."""
obj = Draft.makeArray(obj,
arg1=v_x, arg2=v_y,
arg3=n_x, arg4=n_y,
use_link=use_link)
return obj
use_link=True):
"""Create a 2D rectangular array from the given object.
This function wraps around `make_ortho_array2d`
to produce strictly rectangular arrays, in which
the displacement vectors `v_x` and `v_y`
only have their respective components in X and Y.
Parameters
----------
obj: Part::Feature
Any type of object that has a `Part::TopoShape`
that can be duplicated.
This means most 2D and 3D objects produced
with any workbench.
d_x, d_y: Base::Vector3, optional
Displacement of elements in the corresponding X and Y directions.
n_x, n_y: int, optional
Number of elements in the corresponding X and Y directions.
use_link: bool, optional
If it is `True`, create `App::Link` array.
See `make_ortho_array`.
Returns
-------
Part::FeaturePython
A scripted object with `Proxy.Type='Array'`.
Its `Shape` is a compound of the copies of the original object.
See Also
--------
make_ortho_array, make_ortho_array2d, make_rect_array
"""
_name = "make_rect_array2d"
utils.print_header(_name, _tr("Rectangular array 2D"))
_msg("d_x: {}".format(d_x))
_msg("d_y: {}".format(d_y))
try:
utils.type_check([(d_x, (int, float)),
(d_y, (int, float))],
name=_name)
except TypeError:
_err(_tr("Wrong input: must be a number."))
return None
new_obj = make_ortho_array2d(obj,
v_x=App.Vector(d_x, 0, 0),
v_y=App.Vector(0, d_y, 0),
n_x=n_x,
n_y=n_y,
use_link=use_link)
return new_obj
+82 -12
View File
@@ -1,9 +1,3 @@
"""This module provides the object code for Draft PolarArray.
"""
## @package polararray
# \ingroup DRAFT
# \brief This module provides the object code for Draft PolarArray.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -26,17 +20,93 @@
# * USA *
# * *
# ***************************************************************************
"""Provide the object code for Draft PolarArray."""
## @package polararray
# \ingroup DRAFT
# \brief This module provides the object code for Draft PolarArray.
import FreeCAD as App
import Draft
import draftutils.utils as utils
from draftutils.messages import _msg, _err
from draftutils.translate import _tr
def make_polar_array(obj,
center=App.Vector(0, 0, 0), angle=180, number=4,
use_link=False):
number=4, angle=360, center=App.Vector(0, 0, 0),
use_link=True):
"""Create a polar array from the given object.
Parameters
----------
obj: Part::Feature
Any type of object that has a `Part::TopoShape`
that can be duplicated.
This means most 2D and 3D objects produced
with any workbench.
number: int, optional
It defaults to 4.
The number of copies produced in the circular pattern.
angle: float, optional
It defaults to 360.
The magnitude in degrees swept by the polar pattern.
center: Base::Vector3, optional
It defaults to the origin `App.Vector(0, 0, 0)`.
The vector indicating the center of rotation of the array.
use_link: bool, optional
It defaults to `True`.
If it is `True` the produced copies are not `Part::TopoShape` copies,
but rather `App::Link` objects.
The Links repeat the shape of the original `obj` exactly,
and therefore the resulting array is more memory efficient.
Also, when `use_link` is `True`, the `Fuse` property
of the resulting array does not work; the array doesn't
contain separate shapes, it only has the original shape repeated
many times, so there is nothing to fuse together.
If `use_link` is `False` the original shape is copied many times.
In this case the `Fuse` property is able to fuse
all copies into a single object, if they touch each other.
Returns
-------
Part::FeaturePython
A scripted object with `Proxy.Type='Array'`.
Its `Shape` is a compound of the copies of the original object.
"""
obj = Draft.makeArray(obj,
arg1=center, arg2=angle, arg3=number,
use_link=use_link)
return obj
_name = "make_polar_array"
utils.print_header(_name, _tr("Polar array"))
_msg("Number: {}".format(number))
_msg("Angle: {}".format(angle))
_msg("Center: {}".format(center))
try:
utils.type_check([(number, int)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be an integer number."))
return None
try:
utils.type_check([(angle, (int, float))], name=_name)
except TypeError:
_err(_tr("Wrong input: must be a number."))
return None
try:
utils.type_check([(center, App.Vector)], name=_name)
except TypeError:
_err(_tr("Wrong input: must be a vector."))
return None
_msg("use_link: {}".format(bool(use_link)))
new_obj = Draft.makeArray(obj,
arg1=center, arg2=angle, arg3=number,
use_link=use_link)
return new_obj
@@ -0,0 +1,7 @@
"""Classes that define the task panels of GUI commands.
These classes load `.ui` files that will be used in the task panel
of the graphical commands.
The classes define the behavior and callbacks of the different widgets
included in the `.ui` file.
"""
@@ -0,0 +1,50 @@
# ***************************************************************************
# * Copyright (c) 2019 Yorik van Havre <[email protected]> *
# * *
# * 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 *
# * *
# ***************************************************************************
"""Provides the task panel for the Draft SelectPlane tool."""
## @package task_selectplane
# \ingroup DRAFT
# \brief This module provides the task panel code for the SelectPlane tool.
import FreeCADGui as Gui
# As it is right now this code only loads the task panel .ui file.
# All logic on how to use the widgets is located in the GuiCommand class
# itself.
# On the other hand, the newer tools introduced in v0.19 like OrthoArray,
# PolarArray, and CircularArray include the logic and manipulation
# of the widgets in this task panel class.
# In addition, the task panel code launches the actual function
# using the delayed mechanism defined by the `todo.ToDo` class.
# Therefore, at some point this class should be refactored
# to be more similar to OrthoArray and the new tools.
class SelectPlaneTaskPanel:
"""The task panel definition of the Draft_SelectPlane command."""
def __init__(self):
self.form = Gui.PySideUic.loadUi(":/ui/TaskSelectPlane.ui")
def getStandardButtons(self):
"""Execute to set the standard buttons."""
return 2097152 # int(QtGui.QDialogButtonBox.Close)
+7 -1
View File
@@ -1 +1,7 @@
#
"""Classes and functions used to test the workbench.
These classes are called by the unit test launcher
that is defined in `Init.py` and `InitGui.py`.
The unit tests are based on the standard `unittest` module.
"""
@@ -24,7 +24,6 @@
"""Unit test for the Draft Workbench, GUI import tests."""
import unittest
import FreeCAD as App
import drafttests.auxiliary as aux
@@ -39,39 +38,23 @@ class DraftGuiImport(unittest.TestCase):
def test_import_gui_draftgui(self):
"""Import Draft TaskView GUI tools."""
module = "DraftGui"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_draft_snap(self):
"""Import Draft snapping."""
module = "draftguitools.gui_snapper"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_draft_tools(self):
"""Import Draft graphical commands."""
module = "DraftTools"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_draft_trackers(self):
"""Import Draft tracker utilities."""
module = "draftguitools.gui_trackers"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
@@ -24,7 +24,6 @@
"""Unit test for the Draft Workbench, tools import tests."""
import unittest
import FreeCAD as App
import drafttests.auxiliary as aux
@@ -39,49 +38,29 @@ class DraftImportTools(unittest.TestCase):
def test_import_gui_draftedit(self):
"""Import Draft Edit."""
module = "draftguitools.gui_edit"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_draftfillet(self):
"""Import Draft Fillet."""
module = "DraftFillet"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_draftlayer(self):
"""Import Draft Layer."""
module = "DraftLayer"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_draftplane(self):
"""Import Draft SelectPlane."""
module = "draftguitools.gui_selectplane"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
def test_import_gui_workingplane(self):
"""Import Draft WorkingPlane."""
module = "WorkingPlane"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
imported = aux._import_test(module)
self.assertTrue(imported, "Problem importing '{}'".format(module))
@@ -433,9 +433,9 @@ class DraftModification(unittest.TestCase):
_msg(" Array")
_msg(" radial_distance={0}, "
"tangential_distance={1}".format(rad_distance, tan_distance))
_msg(" number={0}, symmetry={1}".format(number, symmetry))
_msg(" axis={}".format(axis))
_msg(" center={}".format(center))
_msg(" number={0}, symmetry={1}".format(number, symmetry))
obj = Draft.makeArray(rect,
rad_distance, tan_distance,
axis, center,
+2 -8
View File
@@ -58,14 +58,8 @@ class DraftPivy(unittest.TestCase):
def test_pivy_draw(self):
"""Use Coin (pivy.coin) to draw a cube on the active view."""
module = "pivy.coin"
if not App.GuiUp:
aux._no_gui(module)
self.assertTrue(True)
return
import pivy.coin
cube = pivy.coin.SoCube()
import pivy.coin as coin
cube = coin.SoCube()
_msg(" Draw cube")
Gui.ActiveDocument.ActiveView.getSceneGraph().addChild(cube)
_msg(" Adding cube to the active view scene")
+6
View File
@@ -0,0 +1,6 @@
"""Utility functions that do not require the graphical user interface.
These functions are used throughout the Draft Workbench.
They can be called from any module, whether it uses the graphical
user interface or not.
"""
+109 -104
View File
@@ -1,16 +1,8 @@
"""This module provides GUI utility functions for the Draft Workbench.
This module should contain auxiliary functions which require
the graphical user interface (GUI).
"""
## @package gui_utils
# \ingroup DRAFT
# \brief This module provides utility functions for the Draft Workbench
# ***************************************************************************
# * (c) 2009, 2010 *
# * Yorik van Havre <[email protected]>, Ken Cline <[email protected]> *
# * (c) 2019 Eliud Cabrera Castillo <[email protected]> *
# * (c) 2020 Carlo Pavan <[email protected]> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
@@ -31,24 +23,32 @@ the graphical user interface (GUI).
# * USA *
# * *
# ***************************************************************************
"""Provides GUI utility functions for the Draft Workbench.
This module contains auxiliary functions which can be used
in other modules of the workbench, and which require
the graphical user interface (GUI), as they access the view providers
of the objects or the 3D view.
"""
## @package gui_utils
# \ingroup DRAFT
# \brief This module provides GUI utility functions for the Draft Workbench
import FreeCAD
from .utils import _msg
from .utils import _wrn
# from .utils import _log
from .utils import _tr
from .utils import getParam
from .utils import get_type
import os
import math
import os
import six
if FreeCAD.GuiUp:
import FreeCADGui
import FreeCAD as App
from draftutils.messages import _msg, _wrn
from draftutils.utils import getParam
from draftutils.utils import get_type
from draftutils.translate import _tr, translate
if App.GuiUp:
import FreeCADGui as Gui
from pivy import coin
from PySide import QtGui
# from PySide import QtSvg # for load_texture
# from PySide import QtSvg # for load_texture
def get_3d_view():
@@ -62,13 +62,13 @@ def get_3d_view():
Return `None` if the graphical interface is not available.
"""
if FreeCAD.GuiUp:
v = FreeCADGui.ActiveDocument.ActiveView
if App.GuiUp:
v = Gui.ActiveDocument.ActiveView
if "View3DInventor" in str(type(v)):
return v
# print("Debug: Draft: Warning, not working in active view")
v = FreeCADGui.ActiveDocument.mdiViewsOfType("Gui::View3DInventor")
v = Gui.ActiveDocument.mdiViewsOfType("Gui::View3DInventor")
if v:
return v[0]
@@ -80,10 +80,10 @@ get3DView = get_3d_view
def autogroup(obj):
"""Adds a given object to the defined Draft autogroup, if applicable.
"""Add a given object to the defined Draft autogroup, if applicable.
This function only works if the graphical interface is available.
It checks that the `FreeCAD.draftToolBar` class is available,
It checks that the `App.draftToolBar` class is available,
which contains the group to use to automatically store
new created objects.
@@ -95,53 +95,58 @@ def autogroup(obj):
Parameters
----------
obj : App::DocumentObject
obj: App::DocumentObject
Any type of object that will be stored in the group.
"""
if FreeCAD.GuiUp:
# look for active Arch container
active_arch_obj = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch")
if hasattr(FreeCADGui,"draftToolBar"):
if (hasattr(FreeCADGui.draftToolBar,"autogroup")
and not FreeCADGui.draftToolBar.isConstructionMode()
):
if FreeCADGui.draftToolBar.autogroup is not None:
active_group = FreeCAD.ActiveDocument.getObject(FreeCADGui.draftToolBar.autogroup)
if active_group:
found = False
for o in active_group.Group:
if o.Name == obj.Name:
found = True
if not found:
gr = active_group.Group
gr.append(obj)
active_group.Group = gr
elif active_arch_obj:
active_arch_obj.addObject(obj)
elif FreeCADGui.ActiveDocument.ActiveView.getActiveObject("part", False) is not None:
# add object to active part and change it's placement accordingly
# so object does not jump to different position, works with App::Link
# if not scaled. Modified accordingly to realthunder suggestions
p, parent, sub = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("part", False)
matrix = parent.getSubObject(sub, retType=4)
if matrix.hasScale() == 1:
FreeCAD.Console.PrintMessage(translate("Draft",
"Unable to insert new object into "
"a scaled part")
)
return
inverse_placement = FreeCAD.Placement(matrix.inverse())
if get_type(obj) == 'Point':
# point vector have a kind of placement, so should be
# processed before generic object with placement
point_vector = FreeCAD.Vector(obj.X, obj.Y, obj.Z)
real_point = inverse_placement.multVec(point_vector)
obj.X = real_point.x
obj.Y = real_point.y
obj.Z = real_point.z
elif hasattr(obj,"Placement"):
obj.Placement = FreeCAD.Placement(inverse_placement.multiply(obj.Placement))
p.addObject(obj)
if not App.GuiUp:
return
doc = App.ActiveDocument
view = Gui.ActiveDocument.ActiveView
# Look for active Arch container
active_arch_obj = Gui.ActiveDocument.ActiveView.getActiveObject("Arch")
if hasattr(Gui, "draftToolBar"):
if (hasattr(Gui.draftToolBar, "autogroup")
and not Gui.draftToolBar.isConstructionMode()):
if Gui.draftToolBar.autogroup is not None:
active_group = doc.getObject(Gui.draftToolBar.autogroup)
if active_group:
found = False
for o in active_group.Group:
if o.Name == obj.Name:
found = True
if not found:
gr = active_group.Group
gr.append(obj)
active_group.Group = gr
elif active_arch_obj:
active_arch_obj.addObject(obj)
elif view.getActiveObject("part", False) is not None:
# Add object to active part and change its placement
# accordingly so the object does not jump
# to a different position, works with App::Link if not scaled.
# Modified accordingly to realthunder suggestions
p, parent, sub = view.getActiveObject("part", False)
matrix = parent.getSubObject(sub, retType=4)
if matrix.hasScale() == 1:
_msg(translate("Draft",
"Unable to insert new object into "
"a scaled part"))
return
inverse_placement = App.Placement(matrix.inverse())
if get_type(obj) == 'Point':
# point vector have a kind of placement, so should be
# processed before generic object with placement
point_vector = App.Vector(obj.X, obj.Y, obj.Z)
real_point = inverse_placement.multVec(point_vector)
obj.X = real_point.x
obj.Y = real_point.y
obj.Z = real_point.z
elif hasattr(obj, "Placement"):
place = inverse_placement.multiply(obj.Placement)
obj.Placement = App.Placement(place)
p.addObject(obj)
def dim_symbol(symbol=None, invert=False):
@@ -149,7 +154,7 @@ def dim_symbol(symbol=None, invert=False):
Parameters
----------
symbol : int, optional
symbol: int, optional
It defaults to `None`, in which it gets the value from the parameter
database, `get_param("dimsymbol", 0)`.
@@ -161,7 +166,7 @@ def dim_symbol(symbol=None, invert=False):
* 4, `SoSeparator` with a `SoLineSet`, calling `dim_dash`
* Otherwise, `SoSphere`
invert : bool, optional
invert: bool, optional
It defaults to `False`.
If it is `True` and `symbol=2`, the cone will be rotated
-90 degrees around the Z axis, otherwise the rotation is positive,
@@ -181,7 +186,7 @@ def dim_symbol(symbol=None, invert=False):
return coin.SoSphere()
elif symbol == 1:
marker = coin.SoMarkerSet()
marker.markerIndex = FreeCADGui.getMarkerIndex("circle", 9)
marker.markerIndex = Gui.getMarkerIndex("circle", 9)
return marker
elif symbol == 2:
marker = coin.SoSeparator()
@@ -224,10 +229,10 @@ def dim_dash(p1, p2):
Parameters
----------
p1 : tuple of three floats or Base::Vector3
p1: tuple of three floats or Base::Vector3
A point to define a line vertex.
p2 : tuple of three floats or Base::Vector3
p2: tuple of three floats or Base::Vector3
A point to define a line vertex.
Returns
@@ -258,7 +263,7 @@ def remove_hidden(objectslist):
Parameters
----------
objectslist : list of App::DocumentObject
objectslist: list of App::DocumentObject
List of any type of object.
Returns
@@ -291,19 +296,19 @@ def format_object(target, origin=None):
Parameters
----------
target : App::DocumentObject
target: App::DocumentObject
Any type of scripted object.
This object will adopt the applicable visual properties,
`FontSize`, `TextColor`, `LineWidth`, `PointColor`, `LineColor`,
and `ShapeColor`, defined in the Draft toolbar
(`FreeCADGui.draftToolBar`) or will adopt
(`Gui.draftToolBar`) or will adopt
the properties from the `origin` object.
The `target` is also placed in the construction group
if the construction mode in the Draft toolbar is active.
origin : App::DocumentObject, optional
origin: App::DocumentObject, optional
It defaults to `None`.
If it exists, it will provide the visual properties to assign
to `target`, with the exception of `BoundingBox`, `Proxy`,
@@ -315,11 +320,11 @@ def format_object(target, origin=None):
if not obrep:
return
ui = None
if FreeCAD.GuiUp:
if hasattr(FreeCADGui, "draftToolBar"):
ui = FreeCADGui.draftToolBar
if App.GuiUp:
if hasattr(Gui, "draftToolBar"):
ui = Gui.draftToolBar
if ui:
doc = FreeCAD.ActiveDocument
doc = App.ActiveDocument
if ui.isConstructionMode():
col = fcol = ui.getDefaultColor("constr")
gname = getParam("constructiongroupname", "Construction")
@@ -374,18 +379,18 @@ def format_object(target, origin=None):
formatObject = format_object
def get_selection(gui=FreeCAD.GuiUp):
def get_selection(gui=App.GuiUp):
"""Return the current selected objects.
This function only works if the graphical interface is available
as the selection module only works on the 3D view.
It wraps around `FreeCADGui.Selection.getSelection`
It wraps around `Gui.Selection.getSelection`
Parameters
----------
gui : bool, optional
It defaults to the value of `FreeCAD.GuiUp`, which is `True`
gui: bool, optional
It defaults to the value of `App.GuiUp`, which is `True`
when the interface exists, and `False` otherwise.
This value can be set to `False` to simulate
@@ -400,25 +405,25 @@ def get_selection(gui=FreeCAD.GuiUp):
If the interface is not available, it returns `None`.
"""
if gui:
return FreeCADGui.Selection.getSelection()
return Gui.Selection.getSelection()
return None
getSelection = get_selection
def get_selection_ex(gui=FreeCAD.GuiUp):
def get_selection_ex(gui=App.GuiUp):
"""Return the current selected objects together with their subelements.
This function only works if the graphical interface is available
as the selection module only works on the 3D view.
It wraps around `FreeCADGui.Selection.getSelectionEx`
It wraps around `Gui.Selection.getSelectionEx`
Parameters
----------
gui : bool, optional
It defaults to the value of `FreeCAD.GuiUp`, which is `True`
gui: bool, optional
It defaults to the value of `App.GuiUp`, which is `True`
when the interface exists, and `False` otherwise.
This value can be set to `False` to simulate
@@ -448,14 +453,14 @@ def get_selection_ex(gui=FreeCAD.GuiUp):
if `HasSubObjects` is `False`.
"""
if gui:
return FreeCADGui.Selection.getSelectionEx()
return Gui.Selection.getSelectionEx()
return None
getSelectionEx = get_selection_ex
def select(objs=None, gui=FreeCAD.GuiUp):
def select(objs=None, gui=App.GuiUp):
"""Unselects everything and selects only the given list of objects.
This function only works if the graphical interface is available
@@ -463,29 +468,29 @@ def select(objs=None, gui=FreeCAD.GuiUp):
Parameters
----------
objs : list of App::DocumentObject, optional
objs: list of App::DocumentObject, optional
It defaults to `None`.
Any type of scripted object.
It may be a list of objects or a single object.
gui : bool, optional
It defaults to the value of `FreeCAD.GuiUp`, which is `True`
gui: bool, optional
It defaults to the value of `App.GuiUp`, which is `True`
when the interface exists, and `False` otherwise.
This value can be set to `False` to simulate
when the interface is not available.
"""
if gui:
FreeCADGui.Selection.clearSelection()
Gui.Selection.clearSelection()
if objs:
if not isinstance(objs, list):
objs = [objs]
for obj in objs:
if obj:
FreeCADGui.Selection.addSelection(obj)
Gui.Selection.addSelection(obj)
def load_texture(filename, size=None, gui=FreeCAD.GuiUp):
def load_texture(filename, size=None, gui=App.GuiUp):
"""Return a Coin.SoSFImage to use as a texture for a 2D plane.
This function only works if the graphical interface is available
@@ -494,11 +499,11 @@ def load_texture(filename, size=None, gui=FreeCAD.GuiUp):
Parameters
----------
filename : str
filename: str
A path to a pixel image file (PNG) that can be used as a texture
on the face of an object.
size : tuple of two int, or a single int, optional
size: tuple of two int, or a single int, optional
It defaults to `None`.
If a tuple is given, the two values define the width and height
in pixels to which the loaded image will be scaled.
@@ -510,8 +515,8 @@ def load_texture(filename, size=None, gui=FreeCAD.GuiUp):
CURRENTLY the input `size` parameter IS NOT USED.
It always uses the `QImage` to determine this information.
gui : bool, optional
It defaults to the value of `FreeCAD.GuiUp`, which is `True`
gui: bool, optional
It defaults to the value of `App.GuiUp`, which is `True`
when the interface exists, and `False` otherwise.
This value can be set to `False` to simulate
+17 -16
View File
@@ -1,14 +1,3 @@
"""Provides lists of commands for the Draft Workbench.
This module returns lists of commands, so that the toolbars
can be initialized by Draft, and by other workbenches.
These commands should be defined in `DraftTools`, and in the individual
modules in `draftguitools`.
"""
## @package init_tools
# \ingroup DRAFT
# \brief This module provides lists of commands for the Draft Workbench.
# ***************************************************************************
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -31,6 +20,16 @@ modules in `draftguitools`.
# * USA *
# * *
# ***************************************************************************
"""Provides lists of commands for the Draft Workbench.
This module returns lists of commands, so that the toolbars
can be initialized by Draft, and by other workbenches.
These commands should be defined in `DraftTools`, and in the individual
modules in `draftguitools`.
"""
## @package init_tools
# \ingroup DRAFT
# \brief This module provides lists of commands for the Draft Workbench.
from PySide.QtCore import QT_TRANSLATE_NOOP
@@ -43,12 +42,13 @@ def get_draft_drawing_commands():
"Draft_ArcTools",
"Draft_Circle", "Draft_Ellipse", "Draft_Rectangle",
"Draft_Polygon", "Draft_BSpline", "Draft_BezierTools",
"Draft_Point", "Draft_Facebinder"]
"Draft_Point", "Draft_Facebinder",
"Draft_ShapeString"]
def get_draft_annotation_commands():
"""Return the annotation commands list."""
return ["Draft_Text", "Draft_ShapeString", "Draft_Dimension",
return ["Draft_Text", "Draft_Dimension",
"Draft_Label"]
@@ -61,7 +61,7 @@ def get_draft_modification_commands():
"""Return the modification commands list."""
lst = ["Draft_Move", "Draft_Rotate",
"Draft_Scale", "Draft_Mirror",
"Draft_Offset", "Draft_Trimex",
"Draft_Offset", "Draft_Trimex",
"Draft_Stretch",
"Separator",
"Draft_Clone"]
@@ -74,7 +74,8 @@ def get_draft_modification_commands():
"Separator",
"Draft_WireToBSpline", "Draft_Draft2Sketch",
"Separator",
"Draft_Shape2DView", "Draft_Drawing"]
"Draft_Shape2DView", "Draft_Drawing",
"Draft_WorkingPlaneProxy"]
return lst
@@ -97,7 +98,7 @@ def get_draft_utility_commands():
return ["Draft_Layer", "Draft_Heal", "Draft_FlipDimension",
"Draft_ToggleConstructionMode",
"Draft_ToggleContinueMode", "Draft_Edit",
"Draft_Slope", "Draft_SetWorkingPlaneProxy",
"Draft_Slope", "Draft_WorkingPlaneProxy",
"Draft_AddConstruction"]
+10 -5
View File
@@ -1,8 +1,3 @@
"""Provide message utility functions for the Draft Workbench."""
## @package messages
# \ingroup DRAFT
# \brief Provide message utility functions for the Draft Workbench.
# ***************************************************************************
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
# * *
@@ -25,6 +20,16 @@
# * USA *
# * *
# ***************************************************************************
"""Provide message utility functions for the Draft Workbench.
The Console module has long function names, so we define some shorthands
that are suitable for use in every workbench. These shorthands also include
a newline character at the end of the string, so it doesn't have to be
added manually.
"""
## @package messages
# \ingroup DRAFT
# \brief Provide message utility functions for the Draft Workbench.
import FreeCAD as App
+49 -33
View File
@@ -1,12 +1,3 @@
"""This module provides the ToDo class for the Draft Workbench.
This module provides the ToDo class to delay the commit of commands,
which depends on QtCore.QTimer.
"""
## @package todo
# \ingroup DRAFT
# \brief This module provides the ToDo class for the Draft Workbench.
# ***************************************************************************
# * (c) 2009, Yorik van Havre <[email protected]> *
# * (c) 2019 Eliud Cabrera Castillo <[email protected]> *
@@ -30,20 +21,33 @@ which depends on QtCore.QTimer.
# * USA *
# * *
# ***************************************************************************
"""Provides the ToDo class for the Draft Workbench.
The ToDo class is used to delay the commit of commands for later execution.
This is necessary when a GUI command needs to manipulate the 3D view
in such a way that a callback would crash Coin.
The ToDo class essentially calls `QtCore.QTimer.singleShot`
to execute the instructions stored in internal lists.
"""
## @package todo
# \ingroup DRAFT
# \brief This module provides the ToDo class for the Draft Workbench.
import sys
import six
import sys
import traceback
import FreeCAD
import FreeCADGui
from PySide import QtCore
import FreeCAD
import FreeCADGui
from draftutils.messages import _msg, _wrn, _log
__title__ = "FreeCAD Draft Workbench, Todo class"
__author__ = "Yorik van Havre <[email protected]>"
__url__ = ["http://www.freecadweb.org"]
_DEBUG = 0
_DEBUG_inner = 0
class ToDo:
@@ -114,29 +118,31 @@ class ToDo:
The lists are `itinerary`, `commitlist` and `afteritinerary`.
"""
if _DEBUG:
print("Debug: doing delayed tasks.\n"
"itinerary: {0}\n"
"commitlist: {1}\n"
"afteritinerary: {2}\n".format(todo.itinerary,
todo.commitlist,
todo.afteritinerary))
_msg("Debug: doing delayed tasks.\n"
"itinerary: {0}\n"
"commitlist: {1}\n"
"afteritinerary: {2}\n".format(todo.itinerary,
todo.commitlist,
todo.afteritinerary))
try:
for f, arg in todo.itinerary:
try:
# print("debug: executing", f)
if _DEBUG_inner:
_msg("Debug: executing.\n"
"function: {}\n".format(f))
if arg or (arg is False):
f(arg)
else:
f()
except Exception:
FreeCAD.Console.PrintLog(traceback.format_exc())
_log(traceback.format_exc())
wrn = ("ToDo.doTasks, Unexpected error:\n"
"{0}\n"
"in {1}({2})".format(sys.exc_info()[0], f, arg))
FreeCAD.Console.PrintWarning(wrn)
_wrn(wrn)
except ReferenceError:
print("Debug: ToDo.doTasks: "
"queue contains a deleted object, skipping")
_wrn("Debug: ToDo.doTasks: "
"queue contains a deleted object, skipping")
todo.itinerary = []
if todo.commitlist:
@@ -144,7 +150,9 @@ class ToDo:
if six.PY2:
if isinstance(name, six.text_type):
name = name.encode("utf8")
# print("debug: committing " + str(name))
if _DEBUG_inner:
_msg("Debug: committing.\n"
"name: {}\n".format(name))
try:
name = str(name)
FreeCAD.ActiveDocument.openTransaction(name)
@@ -155,11 +163,11 @@ class ToDo:
func()
FreeCAD.ActiveDocument.commitTransaction()
except Exception:
FreeCAD.Console.PrintLog(traceback.format_exc())
_log(traceback.format_exc())
wrn = ("ToDo.doTasks, Unexpected error:\n"
"{0}\n"
"in {1}".format(sys.exec_info()[0], func))
FreeCAD.Console.PrintWarning(wrn)
"in {1}".format(sys.exc_info()[0], func))
_wrn(wrn)
# Restack Draft screen widgets after creation
if hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper.restack()
@@ -167,17 +175,19 @@ class ToDo:
for f, arg in todo.afteritinerary:
try:
# print("debug: executing", f)
if _DEBUG_inner:
_msg("Debug: executing after.\n"
"function: {}\n".format(f))
if arg:
f(arg)
else:
f()
except Exception:
FreeCAD.Console.PrintLog(traceback.format_exc())
_log(traceback.format_exc())
wrn = ("ToDo.doTasks, Unexpected error:\n"
"{0}\n"
"in {1}({2})".format(sys.exc_info()[0], f, arg))
FreeCAD.Console.PrintWarning(wrn)
_wrn(wrn)
todo.afteritinerary = []
@staticmethod
@@ -207,7 +217,9 @@ class ToDo:
::
f(arg)
"""
# print("debug: delaying", f)
if _DEBUG:
_msg("Debug: delaying.\n"
"function: {}\n".format(f))
if todo.itinerary == []:
QtCore.QTimer.singleShot(0, todo.doTasks)
todo.itinerary.append((f, arg))
@@ -235,7 +247,9 @@ class ToDo:
See the attributes of the `ToDo` class for more information.
"""
# print("debug: delaying commit", cl)
if _DEBUG:
_msg("Debug: delaying commit.\n"
"commitlist: {}\n".format(cl))
QtCore.QTimer.singleShot(0, todo.doTasks)
todo.commitlist = cl
@@ -255,7 +269,9 @@ class ToDo:
Finally, it will build the tuple `(f, arg)`
and append it to the `afteritinerary` list.
"""
# print("debug: delaying", f)
if _DEBUG:
_msg("Debug: delaying after.\n"
"function: {}\n".format(f))
if todo.afteritinerary == []:
QtCore.QTimer.singleShot(0, todo.doTasks)
todo.afteritinerary.append((f, arg))
+46 -46
View File
@@ -1,13 +1,4 @@
# -*- coding: utf-8 -*-
"""This module provides utility functions for the Draft Workbench.
This module should contain auxiliary functions which don't require
the graphical user interface (GUI).
"""
## @package utils
# \ingroup DRAFT
# \brief This module provides utility functions for the Draft Workbench
# ***************************************************************************
# * (c) 2009, 2010 *
# * Yorik van Havre <[email protected]>, Ken Cline <[email protected]> *
@@ -32,52 +23,35 @@ the graphical user interface (GUI).
# * USA *
# * *
# ***************************************************************************
"""Provides utility functions for the Draft Workbench.
This module contains auxiliary functions which can be used
in other modules of the workbench, and which don't require
the graphical user interface (GUI).
"""
## @package utils
# \ingroup DRAFT
# \brief This module provides utility functions for the Draft Workbench
import os
import FreeCAD
from PySide import QtCore
import FreeCAD
import Draft_rc
from draftutils.messages import _msg, _log
from draftutils.translate import _tr
App = FreeCAD
# The module is used to prevent complaints from code checkers (flake8)
True if Draft_rc else False
if App.GuiUp:
# The right translate function needs to be imported here
# from DraftGui import translate
# At the moment it is the same function as without GUI
def translate(context, text):
return text
else:
def translate(context, text):
return text
def _tr(text):
"""Function to translate with the context set."""
return translate("Draft", text)
def _msg(text, end="\n"):
App.Console.PrintMessage(text + end)
def _wrn(text, end="\n"):
App.Console.PrintWarning(text + end)
def _log(text, end="\n"):
App.Console.PrintLog(text + end)
ARROW_TYPES = ["Dot", "Circle", "Arrow", "Tick", "Tick-2"]
arrowtypes = ARROW_TYPES
def string_encode_coin(ustr):
"""Encode a unicode object to be used as a string in coin
"""Encode a unicode object to be used as a string in coin.
Parameters
----------
@@ -132,7 +106,7 @@ def type_check(args_and_types, name="?"):
Defaults to `'?'`. The name of the check.
Raises
-------
------
TypeError
If the first element in the tuple is not an instance of the second
element, it raises `Draft.name`.
@@ -265,7 +239,7 @@ getParam = get_param
def set_param(param, value):
"""Set a Draft parameter with the given value
"""Set a Draft parameter with the given value.
The parameter database is located in the tree
::
@@ -981,7 +955,7 @@ getMovableChildren = get_movable_children
def utf8_decode(text):
"""Decode the input string and return a unicode string.
r"""Decode the input string and return a unicode string.
Python 2:
::
@@ -1017,14 +991,14 @@ def utf8_decode(text):
>>> "".decode("utf-8")
>>> b"".decode("utf-8")
u'A\\xe1'
u'A\xe1'
In Python 2 the unicode string is prefixed with `u`,
and unicode characters are replaced by their two-digit hexadecimal
representation, or four digit unicode escape.
>>> "AáBẃCñ".decode("utf-8")
u'A\\xe1B\\u1e83C\\xf1'
u'A\xe1B\u1e83C\xf1'
In Python 2 it will always return a `unicode` object.
@@ -1045,3 +1019,29 @@ def utf8_decode(text):
return text.decode("utf-8")
except AttributeError:
return text
def print_header(name, description, debug=True):
"""Print a line to the console when something is called, and log it.
Parameters
----------
name: str
The name of the function or class that is being called.
This `name` will be logged in the log file, so if there are problems
the log file can be investigated for clues.
description: str
Arbitrary text that will be printed to the console
when the function or class is called.
debug: bool, optional
It defaults to `True`.
If it is `False` the `description` will not be printed
to the console.
On the other hand the `name` will always be logged.
"""
_log(name)
if debug:
_msg(16 * "-")
_msg(description)
@@ -0,0 +1,7 @@
"""Classes that define the viewproviders of custom scripted objects.
These classes define viewproviders for the custom objects
defined in `draftobjects`.
The viewproviders can be used only when the graphical interface
is available; in console mode the viewproviders are not available.
"""
+33 -35
View File
@@ -1,23 +1,3 @@
## @package importSVG
# \ingroup DRAFT
# \brief SVG file importer & exporter
'''@package importSVG
\ingroup DRAFT
\brief SVG file importer & exporter
This module provides support for importing and exporting SVG files. It
enables importing/exporting objects directly to/from the 3D document, but
doesn't handle the SVG output from the Drawing and TechDraw modules.
Currently it only reads the following entities:
* paths, lines, circular arcs, rects, circles, ellipses, polygons, polylines.
Currently unsupported:
* use, image.
'''
# Check code with
# flake8 --ignore=E226,E266,E401,W503
# ***************************************************************************
# * Copyright (c) 2009 Yorik van Havre <[email protected]> *
# * *
@@ -38,12 +18,29 @@ Currently unsupported:
# * USA *
# * *
# ***************************************************************************
"""Provides support for importing and exporting SVG files.
It enables importing/exporting objects directly to/from the 3D document
but doesn't handle the SVG output from the Drawing and TechDraw modules.
Currently it only reads the following entities:
* paths, lines, circular arcs, rects, circles, ellipses, polygons, polylines.
Currently unsupported:
* use, image.
"""
## @package importSVG
# \ingroup DRAFT
# \brief SVG file importer and exporter
# Check code with
# flake8 --ignore=E226,E266,E401,W503
__title__ = "FreeCAD Draft Workbench - SVG importer/exporter"
__author__ = "Yorik van Havre, Sebastian Hoogen"
__url__ = "https://www.freecadweb.org"
# ToDo:
# TODO:
# ignoring CDATA
# handle image element (external references and inline base64)
# debug Problem with 'Sans' font from Inkscape
@@ -51,27 +48,28 @@ __url__ = "https://www.freecadweb.org"
# implement inheriting fill style from group
# handle relative units
import xml.sax, FreeCAD, os, math, re, Draft, DraftVecUtils
import math
import os
import re
import xml.sax
import FreeCAD
import Draft
import DraftVecUtils
from FreeCAD import Vector
from FreeCAD import Console as FCC
from draftutils.translate import translate
if FreeCAD.GuiUp:
from DraftTools import translate
from PySide import QtGui
else:
def translate(context, txt):
return txt
try:
import FreeCADGui
except ImportError:
gui = False
else:
gui = True
try:
draftui = FreeCADGui.draftToolBar
except AttributeError:
try:
draftui = FreeCADGui.draftToolBar
except AttributeError:
draftui = None
else:
gui = False
draftui = None
# Save the native open function to avoid collisions
+1 -1
View File
@@ -31,7 +31,7 @@
<string notr="true">mm</string>
</property>
<property name="minimum">
<double>0.000000000000000</double>
<double>0.000010000000000</double>
</property>
<property name="maximum">
<double>100000000.000000000000000</double>
+1 -1
View File
@@ -94,7 +94,7 @@ public:
* Computes appropriate bounding box for the given list of objects to be passed to setExtents ()
* @param bboxAction a coin action for traverse the given objects views.
* @param objs the list of objects to traverse, due to we traverse the scene graph, the geo children
* will likely be traveresed too.
* will likely be traversed too.
*/
static SbBox3f getRelevantBoundBox (
SoGetBoundingBoxAction &bboxAction,
-1
View File
@@ -175,7 +175,6 @@ void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) con
body = PartDesignGui::getBodyFor (feature, false, false, assertModern);
// lote of assertion so feature should be marked as a tip
if ( selection.size () == 1 && feature && (
feature->isDerivedFrom ( PartDesign::Body::getClassTypeId () ) ||
( feature->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) && body ) ||
( feature->isDerivedFrom ( Part::Feature::getClassTypeId () ) && body &&
body->BaseFeature.getValue() == feature )
+1 -1
View File
@@ -119,7 +119,7 @@
*
* - \c default is the default value of this parameter. Right now, you must
* supply a default value. Boost.PP has trouble dealing with empty values.
* Remember that a sequence cannot be empty. Neight can tuple. Only array,
* Remember that a sequence cannot be empty. Neither can tuple. Only array,
* something like <tt>(0,())</tt> for an empty array. It is awkward to write,
* and didn't add much functionality I want, hence the restriction of
* non-empty defaults here.
+44 -18
View File
@@ -45,41 +45,68 @@ if LOGLEVEL:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
def updateInputField(obj, prop, widget, onBeforeChange=None):
'''updateInputField(obj, prop, widget) ... update obj's property prop with the value of widget.
The property's value is only assigned if the new value differs from the current value.
This prevents onChanged notifications where the value didn't actually change.
Gui::InputField and Gui::QuantitySpinBox widgets are supported - and the property can
be of type Quantity or Float.
If onBeforeChange is specified it is called before a new value is assigned to the property.
Returns True if a new value was assigned, False otherwise (new value is the same as the current).
'''
The property's value is only assigned if the new value differs from the current value.
This prevents onChanged notifications where the value didn't actually change.
Gui::InputField and Gui::QuantitySpinBox widgets are supported - and the property can
be of type Quantity or Float.
If onBeforeChange is specified it is called before a new value is assigned to the property.
Returns True if a new value was assigned, False otherwise (new value is the same as the current).
'''
value = FreeCAD.Units.Quantity(widget.text()).Value
attr = PathUtil.getProperty(obj, prop)
attrValue = attr.Value if hasattr(attr, 'Value') else attr
isDiff = False
if not PathGeom.isRoughly(attrValue, value):
isDiff = True
else:
if hasattr(obj, 'ExpressionEngine'):
noExpr = True
for (prp, expr) in obj.ExpressionEngine:
if prp == prop:
noExpr = False
PathLog.debug('prop = "expression": {} = "{}"'.format(prp, expr))
value = FreeCAD.Units.Quantity(obj.evalExpression(expr)).Value
if not PathGeom.isRoughly(attrValue, value):
isDiff = True
break
if noExpr:
widget.setReadOnly(False)
widget.setStyleSheet("color: black")
else:
widget.setReadOnly(True)
widget.setStyleSheet("color: gray")
widget.update()
if isDiff:
PathLog.debug("updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, attr, value))
if onBeforeChange:
onBeforeChange(obj)
PathUtil.setProperty(obj, prop, value)
return True
return False
class QuantitySpinBox:
'''Controller class to interface a Gui::QuantitySpinBox.
The spin box gets bound to a given property and supports update in both directions.
QuatitySpinBox(widget, obj, prop, onBeforeChange=None)
widget ... expected to be reference to a Gui::QuantitySpinBox
obj ... document object
prop ... canonical name of the (sub-) property
onBeforeChange ... an optional callback being executed before the value of the property is changed
'''
The spin box gets bound to a given property and supports update in both directions.
QuatitySpinBox(widget, obj, prop, onBeforeChange=None)
widget ... expected to be reference to a Gui::QuantitySpinBox
obj ... document object
prop ... canonical name of the (sub-) property
onBeforeChange ... an optional callback being executed before the value of the property is changed
'''
def __init__(self, widget, obj, prop, onBeforeChange=None):
self.obj = obj
self.widget = widget
self.prop = prop
self.onBeforeChange = onBeforeChange
attr = PathUtil.getProperty(self.obj, self.prop)
if attr is not None:
if hasattr(attr, 'Value'):
@@ -95,7 +122,7 @@ The spin box gets bound to a given property and supports update in both directio
if self.valid:
return self.widget.property('expression')
return ''
def setMinimum(self, quantity):
if self.valid:
value = quantity.Value if hasattr(quantity, 'Value') else quantity
@@ -103,8 +130,8 @@ The spin box gets bound to a given property and supports update in both directio
def updateSpinBox(self, quantity=None):
'''updateSpinBox(quantity=None) ... update the display value of the spin box.
If no value is provided the value of the bound property is used.
quantity can be of type Quantity or Float.'''
If no value is provided the value of the bound property is used.
quantity can be of type Quantity or Float.'''
if self.valid:
if quantity is None:
quantity = PathUtil.getProperty(self.obj, self.prop)
@@ -116,4 +143,3 @@ quantity can be of type Quantity or Float.'''
if self.valid:
return updateInputField(self.obj, self.prop, self.widget, self.onBeforeChange)
return None
+5 -3
View File
@@ -157,8 +157,6 @@ class ViewProvider(object):
else:
return ":/icons/Path-OpActive.svg"
#return self.OpIcon
def getTaskPanelOpPage(self, obj):
'''getTaskPanelOpPage(obj) ... use the stored information to instantiate the receiver op's page controller.'''
mod = importlib.import_module(self.OpPageModule)
@@ -190,6 +188,7 @@ class ViewProvider(object):
action.triggered.connect(self.setEdit)
menu.addAction(action)
class TaskPanelPage(object):
'''Base class for all task panel pages.'''
@@ -377,7 +376,7 @@ class TaskPanelPage(object):
combo.clear()
combo.addItems(options)
combo.blockSignals(False)
if hasattr(obj, 'CoolantMode'):
self.selectInComboBox(obj.CoolantMode, combo)
@@ -704,10 +703,13 @@ class TaskPanelDepthsPage(TaskPanelPage):
def haveStartDepth(self):
return PathOp.FeatureDepths & self.features
def haveFinalDepth(self):
return PathOp.FeatureDepths & self.features and not PathOp.FeatureNoFinalDepth & self.features
def haveFinishDepth(self):
return PathOp.FeatureDepths & self.features and PathOp.FeatureFinishDepth & self.features
def haveStepDown(self):
return PathOp.FeatureStepDown & self. features
+185 -141
View File
@@ -29,6 +29,8 @@
# include <QRegExp>
# include <QShortcut>
# include <QString>
# include <QImage>
# include <QPixmap>
# include <boost/bind.hpp>
#endif
@@ -663,34 +665,34 @@ void TaskSketcherElements::leaveEvent (QEvent * event)
void TaskSketcherElements::slotElementsChanged(void)
{
QIcon Sketcher_Element_Arc_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_Edge") );
QIcon Sketcher_Element_Arc_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_EndPoint") );
QIcon Sketcher_Element_Arc_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_MidPoint") );
QIcon Sketcher_Element_Arc_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_StartingPoint") );
QIcon Sketcher_Element_Circle_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Circle_Edge") );
QIcon Sketcher_Element_Circle_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Circle_MidPoint") );
QIcon Sketcher_Element_Line_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Line_Edge") );
QIcon Sketcher_Element_Line_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Line_EndPoint") );
QIcon Sketcher_Element_Line_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Line_StartingPoint") );
QIcon Sketcher_Element_Point_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Point_StartingPoint") );
QIcon Sketcher_Element_Ellipse_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Ellipse_Edge_2") );
QIcon Sketcher_Element_Ellipse_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Ellipse_CentrePoint") );
QIcon Sketcher_Element_ArcOfEllipse_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_Edge") );
QIcon Sketcher_Element_ArcOfEllipse_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfEllipse_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfEllipse_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_End_Point") );
QIcon Sketcher_Element_ArcOfHyperbola_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_Edge") );
QIcon Sketcher_Element_ArcOfHyperbola_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfHyperbola_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfHyperbola_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_End_Point") );
QIcon Sketcher_Element_ArcOfParabola_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_Edge") );
QIcon Sketcher_Element_ArcOfParabola_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfParabola_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfParabola_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_End_Point") );
QIcon Sketcher_Element_BSpline_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_BSpline_Edge") );
QIcon Sketcher_Element_BSpline_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_BSpline_StartPoint") );
QIcon Sketcher_Element_BSpline_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_BSpline_EndPoint") );
QIcon none( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_SelectionTypeInvalid") );
MultIcon Sketcher_Element_Arc_Edge("Sketcher_Element_Arc_Edge");
MultIcon Sketcher_Element_Arc_EndPoint("Sketcher_Element_Arc_EndPoint");
MultIcon Sketcher_Element_Arc_MidPoint("Sketcher_Element_Arc_MidPoint");
MultIcon Sketcher_Element_Arc_StartingPoint("Sketcher_Element_Arc_StartingPoint");
MultIcon Sketcher_Element_Circle_Edge("Sketcher_Element_Circle_Edge");
MultIcon Sketcher_Element_Circle_MidPoint("Sketcher_Element_Circle_MidPoint");
MultIcon Sketcher_Element_Line_Edge("Sketcher_Element_Line_Edge");
MultIcon Sketcher_Element_Line_EndPoint("Sketcher_Element_Line_EndPoint");
MultIcon Sketcher_Element_Line_StartingPoint("Sketcher_Element_Line_StartingPoint");
MultIcon Sketcher_Element_Point_StartingPoint("Sketcher_Element_Point_StartingPoint");
MultIcon Sketcher_Element_Ellipse_Edge("Sketcher_Element_Ellipse_Edge_2");
MultIcon Sketcher_Element_Ellipse_MidPoint("Sketcher_Element_Ellipse_CentrePoint");
MultIcon Sketcher_Element_ArcOfEllipse_Edge("Sketcher_Element_Elliptical_Arc_Edge");
MultIcon Sketcher_Element_ArcOfEllipse_MidPoint("Sketcher_Element_Elliptical_Arc_Centre_Point");
MultIcon Sketcher_Element_ArcOfEllipse_StartingPoint("Sketcher_Element_Elliptical_Arc_Start_Point");
MultIcon Sketcher_Element_ArcOfEllipse_EndPoint("Sketcher_Element_Elliptical_Arc_End_Point");
MultIcon Sketcher_Element_ArcOfHyperbola_Edge("Sketcher_Element_Hyperbolic_Arc_Edge");
MultIcon Sketcher_Element_ArcOfHyperbola_MidPoint("Sketcher_Element_Hyperbolic_Arc_Centre_Point");
MultIcon Sketcher_Element_ArcOfHyperbola_StartingPoint("Sketcher_Element_Hyperbolic_Arc_Start_Point");
MultIcon Sketcher_Element_ArcOfHyperbola_EndPoint("Sketcher_Element_Hyperbolic_Arc_End_Point");
MultIcon Sketcher_Element_ArcOfParabola_Edge("Sketcher_Element_Parabolic_Arc_Edge");
MultIcon Sketcher_Element_ArcOfParabola_MidPoint("Sketcher_Element_Parabolic_Arc_Centre_Point");
MultIcon Sketcher_Element_ArcOfParabola_StartingPoint("Sketcher_Element_Parabolic_Arc_Start_Point");
MultIcon Sketcher_Element_ArcOfParabola_EndPoint("Sketcher_Element_Parabolic_Arc_End_Point");
MultIcon Sketcher_Element_BSpline_Edge("Sketcher_Element_BSpline_Edge");
MultIcon Sketcher_Element_BSpline_StartingPoint("Sketcher_Element_BSpline_StartPoint");
MultIcon Sketcher_Element_BSpline_EndPoint("Sketcher_Element_BSpline_EndPoint");
MultIcon none("Sketcher_Element_SelectionTypeInvalid");
assert(sketchView);
// Build up ListView with the elements
@@ -707,34 +709,34 @@ void TaskSketcherElements::slotElementsChanged(void)
bool construction = (*it)->Construction;
ui->listWidgetElements->addItem(new ElementItem(
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfHyperbola_Edge :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfHyperbola_StartingPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfHyperbola_EndPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfHyperbola_MidPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfParabola_Edge :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfParabola_StartingPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfParabola_EndPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfParabola_MidPoint :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==0) ? Sketcher_Element_BSpline_Edge :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==1) ? Sketcher_Element_BSpline_StartingPoint :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==2) ? Sketcher_Element_BSpline_EndPoint :
none,
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint.getIcon(construction, false) :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge.getIcon(construction, false) :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint.getIcon(construction, false) :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint.getIcon(construction, false) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge.getIcon(construction, false) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint.getIcon(construction, false) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint.getIcon(construction, false) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint.getIcon(construction, false) :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge.getIcon(construction, false) :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint.getIcon(construction, false) :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge.getIcon(construction, false) :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint.getIcon(construction, false) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge.getIcon(construction, false) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint.getIcon(construction, false) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint.getIcon(construction, false) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint.getIcon(construction, false) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfHyperbola_Edge.getIcon(construction, false) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfHyperbola_StartingPoint.getIcon(construction, false) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfHyperbola_EndPoint.getIcon(construction, false) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfHyperbola_MidPoint.getIcon(construction, false) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfParabola_Edge.getIcon(construction, false) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfParabola_StartingPoint.getIcon(construction, false) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfParabola_EndPoint.getIcon(construction, false) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfParabola_MidPoint.getIcon(construction, false) :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==0) ? Sketcher_Element_BSpline_Edge.getIcon(construction, false) :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==1) ? Sketcher_Element_BSpline_StartingPoint.getIcon(construction, false) :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==2) ? Sketcher_Element_BSpline_EndPoint.getIcon(construction, false) :
none.getIcon(construction, false),
type == Part::GeomPoint::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Point") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Point"))) :
@@ -813,34 +815,34 @@ void TaskSketcherElements::slotElementsChanged(void)
ui->listWidgetElements->addItem(new ElementItem(
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfHyperbola_Edge :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfHyperbola_StartingPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfHyperbola_EndPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfHyperbola_MidPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfParabola_Edge :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfParabola_StartingPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfParabola_EndPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfParabola_MidPoint :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==0) ? Sketcher_Element_BSpline_Edge :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==1) ? Sketcher_Element_BSpline_StartingPoint :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==2) ? Sketcher_Element_BSpline_EndPoint :
none,
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint.External :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge.External :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint.External :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint.External :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge.External :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint.External :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint.External :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint.External :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge.External :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint.External :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge.External :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint.External :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge.External :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint.External :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint.External :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint.External :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfHyperbola_Edge.External :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfHyperbola_StartingPoint.External :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfHyperbola_EndPoint.External :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfHyperbola_MidPoint.External :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfParabola_Edge.External :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfParabola_StartingPoint.External :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfParabola_EndPoint.External :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfParabola_MidPoint.External :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==0) ? Sketcher_Element_BSpline_Edge.External :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==1) ? Sketcher_Element_BSpline_StartingPoint.External :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==2) ? Sketcher_Element_BSpline_EndPoint.External :
none.External,
type == Part::GeomPoint::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Point") + linkname):
(QString::fromLatin1("%1-").arg(i-2)+tr("Point"))) :
@@ -1033,67 +1035,70 @@ void TaskSketcherElements::updateVisibility(int filterindex)
void TaskSketcherElements::updateIcons(int element)
{
QIcon Sketcher_Element_Arc_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_Edge") );
QIcon Sketcher_Element_Arc_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_EndPoint") );
QIcon Sketcher_Element_Arc_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_MidPoint") );
QIcon Sketcher_Element_Arc_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Arc_StartingPoint") );
QIcon Sketcher_Element_Circle_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Circle_Edge") );
QIcon Sketcher_Element_Circle_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Circle_MidPoint") );
QIcon Sketcher_Element_Line_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Line_Edge") );
QIcon Sketcher_Element_Line_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Line_EndPoint") );
QIcon Sketcher_Element_Line_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Line_StartingPoint") );
QIcon Sketcher_Element_Point_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Point_StartingPoint") );
QIcon Sketcher_Element_Ellipse_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Ellipse_Edge_2") );
QIcon Sketcher_Element_Ellipse_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Ellipse_CentrePoint") );
QIcon Sketcher_Element_ArcOfEllipse_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_Edge") );
QIcon Sketcher_Element_ArcOfEllipse_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfEllipse_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfEllipse_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Elliptical_Arc_End_Point") );
QIcon Sketcher_Element_ArcOfHyperbola_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_Edge") );
QIcon Sketcher_Element_ArcOfHyperbola_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfHyperbola_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfHyperbola_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Hyperbolic_Arc_End_Point") );
QIcon Sketcher_Element_ArcOfParabola_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_Edge") );
QIcon Sketcher_Element_ArcOfParabola_MidPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfParabola_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfParabola_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_Parabolic_Arc_End_Point") );
QIcon Sketcher_Element_BSpline_Edge( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_BSpline_Edge") );
QIcon Sketcher_Element_BSpline_StartingPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_BSpline_StartPoint") );
QIcon Sketcher_Element_BSpline_EndPoint( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_BSpline_EndPoint") );
QIcon none( Gui::BitmapFactory().iconFromTheme("Sketcher_Element_SelectionTypeInvalid") );
MultIcon Sketcher_Element_Arc_Edge("Sketcher_Element_Arc_Edge");
MultIcon Sketcher_Element_Arc_EndPoint("Sketcher_Element_Arc_EndPoint");
MultIcon Sketcher_Element_Arc_MidPoint("Sketcher_Element_Arc_MidPoint");
MultIcon Sketcher_Element_Arc_StartingPoint("Sketcher_Element_Arc_StartingPoint");
MultIcon Sketcher_Element_Circle_Edge("Sketcher_Element_Circle_Edge");
MultIcon Sketcher_Element_Circle_MidPoint("Sketcher_Element_Circle_MidPoint");
MultIcon Sketcher_Element_Line_Edge("Sketcher_Element_Line_Edge");
MultIcon Sketcher_Element_Line_EndPoint("Sketcher_Element_Line_EndPoint");
MultIcon Sketcher_Element_Line_StartingPoint("Sketcher_Element_Line_StartingPoint");
MultIcon Sketcher_Element_Point_StartingPoint("Sketcher_Element_Point_StartingPoint");
MultIcon Sketcher_Element_Ellipse_Edge("Sketcher_Element_Ellipse_Edge_2");
MultIcon Sketcher_Element_Ellipse_MidPoint("Sketcher_Element_Ellipse_CentrePoint");
MultIcon Sketcher_Element_ArcOfEllipse_Edge("Sketcher_Element_Elliptical_Arc_Edge");
MultIcon Sketcher_Element_ArcOfEllipse_MidPoint("Sketcher_Element_Elliptical_Arc_Centre_Point");
MultIcon Sketcher_Element_ArcOfEllipse_StartingPoint("Sketcher_Element_Elliptical_Arc_Start_Point");
MultIcon Sketcher_Element_ArcOfEllipse_EndPoint("Sketcher_Element_Elliptical_Arc_End_Point");
MultIcon Sketcher_Element_ArcOfHyperbola_Edge("Sketcher_Element_Hyperbolic_Arc_Edge");
MultIcon Sketcher_Element_ArcOfHyperbola_MidPoint("Sketcher_Element_Hyperbolic_Arc_Centre_Point");
MultIcon Sketcher_Element_ArcOfHyperbola_StartingPoint("Sketcher_Element_Hyperbolic_Arc_Start_Point");
MultIcon Sketcher_Element_ArcOfHyperbola_EndPoint("Sketcher_Element_Hyperbolic_Arc_End_Point");
MultIcon Sketcher_Element_ArcOfParabola_Edge("Sketcher_Element_Parabolic_Arc_Edge");
MultIcon Sketcher_Element_ArcOfParabola_MidPoint("Sketcher_Element_Parabolic_Arc_Centre_Point");
MultIcon Sketcher_Element_ArcOfParabola_StartingPoint("Sketcher_Element_Parabolic_Arc_Start_Point");
MultIcon Sketcher_Element_ArcOfParabola_EndPoint("Sketcher_Element_Parabolic_Arc_End_Point");
MultIcon Sketcher_Element_BSpline_Edge("Sketcher_Element_BSpline_Edge");
MultIcon Sketcher_Element_BSpline_StartingPoint("Sketcher_Element_BSpline_StartPoint");
MultIcon Sketcher_Element_BSpline_EndPoint("Sketcher_Element_BSpline_EndPoint");
MultIcon none("Sketcher_Element_SelectionTypeInvalid");
for (int i=0;i<ui->listWidgetElements->count(); i++) {
Base::Type type = static_cast<ElementItem *>(ui->listWidgetElements->item(i))->GeometryType;
bool construction = static_cast<ElementItem *>(ui->listWidgetElements->item(i))->isConstruction;
bool external = static_cast<ElementItem *>(ui->listWidgetElements->item(i))->isExternal;
ui->listWidgetElements->item(i)->setIcon(
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfHyperbola_Edge :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfHyperbola_StartingPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfHyperbola_EndPoint :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfHyperbola_MidPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfParabola_Edge :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfParabola_StartingPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfParabola_EndPoint :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfParabola_MidPoint :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==0) ? Sketcher_Element_BSpline_Edge :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==1) ? Sketcher_Element_BSpline_StartingPoint :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==2) ? Sketcher_Element_BSpline_EndPoint :
none);
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint.getIcon(construction, external) :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge.getIcon(construction, external) :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint.getIcon(construction, external) :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint.getIcon(construction, external) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge.getIcon(construction, external) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint.getIcon(construction, external) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint.getIcon(construction, external) :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint.getIcon(construction, external) :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge.getIcon(construction, external) :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint.getIcon(construction, external) :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge.getIcon(construction, external) :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint.getIcon(construction, external) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge.getIcon(construction, external) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint.getIcon(construction, external) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint.getIcon(construction, external) :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint.getIcon(construction, external) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfHyperbola_Edge.getIcon(construction, external) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfHyperbola_StartingPoint.getIcon(construction, external) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfHyperbola_EndPoint.getIcon(construction, external) :
(type == Part::GeomArcOfHyperbola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfHyperbola_MidPoint.getIcon(construction, external) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfParabola_Edge.getIcon(construction, external) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfParabola_StartingPoint.getIcon(construction, external) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfParabola_EndPoint.getIcon(construction, external) :
(type == Part::GeomArcOfParabola::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfParabola_MidPoint.getIcon(construction, external) :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==0) ? Sketcher_Element_BSpline_Edge.getIcon(construction, external) :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==1) ? Sketcher_Element_BSpline_StartingPoint.getIcon(construction, external) :
(type == Part::GeomBSplineCurve::getClassTypeId() && element==2) ? Sketcher_Element_BSpline_EndPoint.getIcon(construction, external) :
none.getIcon(construction, external));
}
}
@@ -1105,6 +1110,45 @@ void TaskSketcherElements::changeEvent(QEvent *e)
}
}
TaskSketcherElements::MultIcon::MultIcon(const char* name)
{
int hue, sat, val, alp;
Normal = Gui::BitmapFactory().iconFromTheme(name);
QImage imgConstr(Normal.pixmap(Normal.availableSizes()[0]).toImage());
QImage imgExt(imgConstr);
for(int ix=0 ; ix<imgConstr.width() ; ix++) {
for(int iy=0 ; iy<imgConstr.height() ; iy++) {
QColor clr = QColor::fromRgba(imgConstr.pixel(ix,iy));
clr.getHsv(&hue, &sat, &val, &alp);
if (alp > 127 && hue >= 0) {
if (sat > 127 && (hue > 330 || hue < 30)) {
clr.setHsv((hue + 240) % 360, sat, val, alp);
imgConstr.setPixel(ix, iy, clr.rgba());
clr.setHsv((hue + 300) % 360, sat, val, alp);
imgExt.setPixel(ix, iy, clr.rgba());
}
else if (sat < 64 && val > 192)
{
clr.setHsv(240, (255-sat), val, alp);
imgConstr.setPixel(ix, iy, clr.rgba());
clr.setHsv(300, (255-sat), val, alp);
imgExt.setPixel(ix, iy, clr.rgba());
}
}
}
}
Construction = QIcon(QPixmap::fromImage(imgConstr));
External = QIcon(QPixmap::fromImage(imgExt));
}
QIcon TaskSketcherElements::MultIcon::getIcon(bool construction, bool external) const
{
if (construction && external) return QIcon();
if (construction) return Construction;
if (external) return External;
return Normal;
}
#include "moc_TaskSketcherElements.cpp"
@@ -28,6 +28,7 @@
#include <Gui/Selection.h>
#include <boost/signals2.hpp>
#include <QListWidget>
#include <QIcon>
namespace App {
class Property;
@@ -91,6 +92,18 @@ class TaskSketcherElements : public Gui::TaskView::TaskBox, public Gui::Selectio
{
Q_OBJECT
class MultIcon {
public:
MultIcon(const char*);
QIcon Normal;
QIcon Construction;
QIcon External;
QIcon getIcon(bool construction, bool external) const;
};
public:
TaskSketcherElements(ViewProviderSketch *sketchView);
~TaskSketcherElements();
+1 -1
View File
@@ -1067,7 +1067,7 @@ void PropertySheet::removeDependencies(CellAddress key)
void PropertySheet::recomputeDependants(const App::DocumentObject *owner, const char *propName)
{
// First, search without actual property name for sub-object/link
// references, i.e indirect references. The depenedecies of these
// references, i.e indirect references. The dependencies of these
// references are too complex to track exactly, so we only track the
// top parent object instead, and mark the involved expression
// whenever the top parent changes.
+7
View File
@@ -570,6 +570,13 @@ Base::Vector3d DrawUtil::invertY(Base::Vector3d v)
return result;
}
QPointF DrawUtil::invertY(QPointF v)
{
QPointF result(v.x(), -v.y());
return result;
}
//obs? was used in CSV prototype of Cosmetics
std::vector<std::string> DrawUtil::split(std::string csvLine)
{
+1
View File
@@ -110,6 +110,7 @@ class TechDrawExport DrawUtil {
static std::string shapeToString(TopoDS_Shape s);
static TopoDS_Shape shapeFromString(std::string s);
static Base::Vector3d invertY(Base::Vector3d v);
static QPointF invertY(QPointF p);
static std::vector<std::string> split(std::string csvLine);
static std::vector<std::string> tokenize(std::string csvLine, std::string delimiter = ",$$$,");
static App::Color pyTupleToColor(PyObject* pColor);
-2
View File
@@ -100,8 +100,6 @@ using namespace std;
PROPERTY_SOURCE(TechDraw::DrawViewDetail, TechDraw::DrawViewPart)
DrawViewDetail::DrawViewDetail()
// :
// m_mattingStyle(0)
{
static const char *dgroup = "Detail";
+9
View File
@@ -70,6 +70,8 @@ set(TechDrawGui_MOC_HDRS
QGIWeldSymbol.h
SymbolChooser.h
TaskActiveView.h
TaskDetail.h
QGIGhostHighlight.h
)
fc_wrap_cpp(TechDrawGui_MOC_SRCS ${TechDrawGui_MOC_HDRS})
@@ -103,6 +105,7 @@ set(TechDrawGui_UIC_SRCS
TaskWeldingSymbol.ui
SymbolChooser.ui
TaskActiveView.ui
TaskDetail.ui
)
if(BUILD_QT5)
@@ -203,6 +206,9 @@ SET(TechDrawGui_SRCS
TaskActiveView.h
Grabber3d.cpp
Grabber3d.h
TaskDetail.ui
TaskDetail.cpp
TaskDetail.h
)
SET(TechDrawGuiView_SRCS
@@ -299,6 +305,8 @@ SET(TechDrawGuiView_SRCS
TemplateTextField.cpp
TemplateTextField.h
ZVALUE.h
QGIGhostHighlight.cpp
QGIGhostHighlight.h
)
SET(TechDrawGuiViewProvider_SRCS
ViewProviderPage.cpp
@@ -366,6 +374,7 @@ SET(TechDrawGuiTaskDlgs_SRCS
TaskWeldingSymbol.ui
SymbolChooser.ui
TaskActiveView.ui
TaskDetail.ui
)
SOURCE_GROUP("TaskDialogs" FILES ${TechDrawGuiTaskDlgs_SRCS})
File diff suppressed because it is too large Load Diff
+115
View File
@@ -0,0 +1,115 @@
/***************************************************************************
* Copyright (c) 2020 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QPainter>
#include <QPainterPathStroker>
#include <QStyleOptionGraphicsItem>
#include <QPen>
#include <QColor>
#endif
#include <App/Application.h>
#include <App/Material.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <qmath.h>
#include "Rez.h"
#include "DrawGuiUtil.h"
#include "QGIView.h"
#include "QGIGhostHighlight.h"
using namespace TechDrawGui;
using namespace TechDraw;
QGIGhostHighlight::QGIGhostHighlight()
{
setInteractive(true);
m_dragging = false;
//make the ghost very visible
QFont f(QGIView::getPrefFont());
double fontSize = QGIView::getPrefFontSize();
setFont(f, fontSize);
setReference("drag");
setStyle(Qt::SolidLine);
setColor(prefSelectColor());
setWidth(Rez::guiX(1.0));
setRadius(10.0); //placeholder
}
QGIGhostHighlight::~QGIGhostHighlight()
{
}
QVariant QGIGhostHighlight::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionHasChanged && scene()) {
// nothing to do here?
}
return QGIHighlight::itemChange(change, value);
}
void QGIGhostHighlight::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
// Base::Console().Message("QGIGhostHighlight::mousePress() - %X\n", this);
if ( (event->button() == Qt::LeftButton) &&
(flags() && QGraphicsItem::ItemIsMovable) ) {
m_dragging = true;
event->accept();
}
QGIHighlight::mousePressEvent(event);
}
void QGIGhostHighlight::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
// Base::Console().Message("QGIGhostHighlight::mouseRelease() - pos: %s scenePos: %s\n",
// DrawUtil::formatVector(pos()).c_str(),
// DrawUtil::formatVector(mapToScene(pos())).c_str());
if (m_dragging) {
m_dragging = false;
Q_EMIT positionChange(scenePos());
event->accept();
}
QGIHighlight::mouseReleaseEvent(event);
}
void QGIGhostHighlight::setInteractive(bool state)
{
setFlag(QGraphicsItem::ItemIsSelectable, state);
setFlag(QGraphicsItem::ItemIsMovable, state);
setFlag(QGraphicsItem::ItemSendsScenePositionChanges, state);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, state);
}
//radius should scaled, but not Rez::guix()
void QGIGhostHighlight::setRadius(double r)
{
setBounds(-r, r, r, -r);
}
#include <Mod/TechDraw/Gui/moc_QGIGhostHighlight.cpp>
+66
View File
@@ -0,0 +1,66 @@
/***************************************************************************
* Copyright (c) 2020 WandererFan <wandererfan@gmail.com> *
* *
* 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 TECHDRAWGUI_QGIGHOSTHIGHLIGHT_H
#define TECHDRAWGUI_QGIGHOSTHIGHLIGHT_H
#include <QObject>
#include <QGraphicsScene>
#include <QGraphicsSceneEvent>
#include <QPointF>
#include "QGIHighlight.h"
//a movable, selectable surrogate for detail highlights in QGIVPart
namespace TechDrawGui
{
class TechDrawGuiExport QGIGhostHighlight : public QObject, public QGIHighlight
{
Q_OBJECT
public:
explicit QGIGhostHighlight();
~QGIGhostHighlight();
enum {Type = QGraphicsItem::UserType + 177};
int type() const { return Type;}
void setInteractive(bool state);
void setRadius(double r);
Q_SIGNALS:
void positionChange(QPointF p);
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
bool m_dragging;
private:
};
}
#endif // TECHDRAWGUI_QGIGHOSTHIGHLIGHT_H
+57 -2
View File
@@ -46,19 +46,65 @@ QGIHighlight::QGIHighlight()
{
m_refText = "";
m_refSize = 0.0;
setInteractive(false);
m_circle = new QGraphicsEllipseItem();
addToGroup(m_circle);
m_circle->setFlag(QGraphicsItem::ItemIsSelectable, false);
m_rect = new QGCustomRect();
addToGroup(m_rect);
m_rect->setFlag(QGraphicsItem::ItemIsSelectable, false);
m_reference = new QGCustomText();
addToGroup(m_reference);
m_reference->setFlag(QGraphicsItem::ItemIsSelectable, false);
setWidth(Rez::guiX(0.75));
setStyle(getHighlightStyle());
setColor(getHighlightColor());
}
QGIHighlight::~QGIHighlight()
{
}
//really only want to emit signal at end of movement
//QVariant QGIHighlight::itemChange(GraphicsItemChange change, const QVariant &value)
//{
// if (change == ItemPositionHasChanged && scene()) {
// // nothing to do here
// }
// return QGraphicsItem::itemChange(change, value);
//}
//void QGIHighlight::mousePressEvent(QGraphicsSceneMouseEvent * event)
//{
// Base::Console().Message("QGIHighlight::mousePress() - %X\n", this);
//// if(scene() && m_reference == scene()->mouseGrabberItem()) {
// if ( (event->button() == Qt::LeftButton) &&
// (flags() && QGraphicsItem::ItemIsMovable) ) {
// m_dragging = true;
// }
//// }
// QGIDecoration::mousePressEvent(event);
//}
//void QGIHighlight::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
//{
// Base::Console().Message("QGIHighlight::mouseRelease() - %X grabber: %X\n", this, scene()->mouseGrabberItem());
//// if(scene() && this == scene()->mouseGrabberItem()) {
// if (m_dragging) {
// m_dragging = false;
//// QString itemName = data(0).toString();
// Q_EMIT positionChange(pos());
// return;
// }
//// }
// QGIDecoration::mouseReleaseEvent(event);
//}
void QGIHighlight::draw()
{
prepareGeometryChange();
@@ -100,6 +146,15 @@ void QGIHighlight::makeReference()
}
}
void QGIHighlight::setInteractive(bool state)
{
// setAcceptHoverEvents(state);
setFlag(QGraphicsItem::ItemIsSelectable, state);
setFlag(QGraphicsItem::ItemIsMovable, state);
setFlag(QGraphicsItem::ItemSendsScenePositionChanges, state);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, state);
}
void QGIHighlight::setBounds(double x1,double y1,double x2,double y2)
{
m_start = QPointF(Rez::guiX(x1),Rez::guiX(-y1));
@@ -142,10 +197,9 @@ int QGIHighlight::getHoleStyle()
return style;
}
void QGIHighlight::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
// myOption.state &= ~QStyle::State_Selected;
setTools();
// painter->drawRect(boundingRect()); //good for debugging
@@ -165,3 +219,4 @@ void QGIHighlight::setTools()
m_reference->setDefaultTextColor(m_colCurrent);
}
+13 -3
View File
@@ -25,9 +25,12 @@
#include <QFont>
#include <QPointF>
#include <QObject>
#include <QGraphicsTextItem>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
#include <QGraphicsScene>
#include <QGraphicsSceneEvent>
#include <QPainterPath>
#include <QColor>
@@ -45,19 +48,25 @@ class TechDrawGuiExport QGIHighlight : public QGIDecoration
{
public:
explicit QGIHighlight();
~QGIHighlight() {}
~QGIHighlight();
enum {Type = QGraphicsItem::UserType + 172};
enum {Type = QGraphicsItem::UserType + 176};
int type() const { return Type;}
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
virtual void paint(QPainter * painter,
const QStyleOptionGraphicsItem * option,
QWidget * widget = 0 ) override;
void setBounds(double x1,double y1,double x2,double y2);
void setReference(char* sym);
void setFont(QFont f, double fsize);
virtual void draw();
void setInteractive(bool state);
protected:
/* virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;*/
/* virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;*/
/* virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;*/
QColor getHighlightColor();
Qt::PenStyle getHighlightStyle();
void makeHighlight();
@@ -65,6 +74,7 @@ protected:
void setTools();
int getHoleStyle(void);
/* bool m_dragging;*/
private:
char* m_refText;
+24 -22
View File
@@ -1,26 +1,26 @@
/*
Derived QGraphicsItem Classes type() Values
Derived QGI Classes type() Values
Qt First UserType>> QGraphicsItem::UserType = 65536
QGraphicsItemView : 101
QGraphicsItemViewPart : 102
QGraphicsItemEdge: 103
QGraphicsItemFace: 104
QGraphicsItemVertex: 105
QGraphicsItemViewDimension : 106
QGraphicsItemViewBalloon : 140
QGraphicsItemBalloonLabel : 141
QGraphicsItemDatumLabel : 107
QGraphicsItemViewSection : 108
QGraphicsItemArrow: 109
QGraphicsItemViewCollection : 110
QGraphicsItemViewOrthographic : 113
QGraphicsItemViewAnnotation : 120
QGraphicsItemViewSymbol : 121
QGraphicsItemHatch : 122 //obsolete
QGraphicsItemClip : 123
QGraphicsItemSpreadsheet : 124
QGIView : 101
QGIViewPart : 102
QGIEdge: 103
QGIFace: 104
QGIVertex: 105
QGIViewDimension : 106
QGIViewBalloon : 140
QGIBalloonLabel : 141
QGIDatumLabel : 107
QGIViewSection : 108
QGIArrow: 109
QGIViewCollection : 110
QGIProjGroup : 113
QGIViewAnnotation : 120
QGIViewSymbol : 121
QGIHatch : 122 //obsolete
QGIClip : 123
QGISpreadsheet : 124
QGCustomText: 130
QGCustomSvg: 131
QGCustomClip: 132
@@ -28,9 +28,9 @@ QGCustomRect: 133
QGCustomLabel:135
QGCustomBorder: 136
QGDisplayArea: 137
QGraphicsItemTemplate: 150
QGraphicsItemDrawingTemplate: 151
QGraphicsItemSVGTemplate: 153
QGITemplate: 150
QGIDrawingTemplate: 151
QGISVGTemplate: 153
TemplateTextField: 160
QGIPrimPath: 170
QGICMark: 171
@@ -38,6 +38,8 @@ QGISectionLine: 172
QGIDecoration: 173
QGICenterLine: 174
QGIDimLines: 175
QGIHighlight: 176
QGIGhostHighlight: 177
QGICaption: 180
QGIViewImage: 200
QGCustomImage: 201
+8 -3
View File
@@ -121,6 +121,11 @@ public:
static int calculateFontPixelWidth(const QFont &font);
static const double DefaultFontSizeInMM;
static QString getPrefFont(void);
static double getPrefFontSize(void);
static double getDimFontSize(void);
MDIViewPage* getMDIViewPage(void) const;
virtual void removeChild(QGIView* child);
@@ -145,9 +150,9 @@ protected:
virtual QRectF customChildrenBoundingRect(void) const;
void dumpRect(const char* text, QRectF r);
QString getPrefFont(void);
double getPrefFontSize(void);
double getDimFontSize(void);
/* QString getPrefFont(void);*/
/* double getPrefFontSize(void);*/
/* double getDimFontSize(void);*/
Base::Reference<ParameterGrp> getParmGroupCol(void);
+6
View File
@@ -67,6 +67,11 @@ Base::Vector2d Rez::guiX(Base::Vector3d v, bool planar)
return Base::Vector2d(guiX(v.x), guiX(v.y));
}
QPointF Rez::guiX(QPointF p)
{
return Rez::guiPt(p);
}
//turn Gui side value to App side value
double Rez::appX(double x)
{
@@ -85,6 +90,7 @@ QPointF Rez::appX(QPointF p)
}
//Misc conversions
QPointF Rez::guiPt(QPointF p)
{
+2
View File
@@ -43,6 +43,8 @@ public:
static double guiX(double x);
static Base::Vector3d guiX(Base::Vector3d v);
static Base::Vector2d guiX(Base::Vector3d v, bool planar);
static QPointF guiX(QPointF p);
//turn Gui side value to App side value
static double appX(double x);
static Base::Vector3d appX(Base::Vector3d v);
+585
View File
@@ -0,0 +1,585 @@
/***************************************************************************
* Copyright (c) 2020 Wandererfan <wandererfan@gmail.com *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QGraphicsScene>
#include <QStatusBar>
#endif // #ifndef _PreComp_
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Base/Quantity.h>
#include <Base/UnitsApi.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
#include <Mod/TechDraw/Gui/ui_TaskDetail.h>
#include "DrawGuiStd.h"
#include "QGVPage.h"
#include "QGIView.h"
#include "QGIPrimPath.h"
#include "QGIGhostHighlight.h"
#include "MDIViewPage.h"
#include "ViewProviderPage.h"
#include "Rez.h"
#include "QGIViewPart.h"
#include "TaskDetail.h"
using namespace TechDrawGui;
using namespace TechDraw;
using namespace Gui;
#define CREATEMODE 0
#define EDITMODE 1
//creation ctor
TaskDetail::TaskDetail(TechDraw::DrawViewPart* baseFeat):
ui(new Ui_TaskDetail),
m_detailFeat(nullptr),
m_baseFeat(baseFeat),
m_basePage(nullptr),
m_inProgressLock(false),
m_saveAnchor(Base::Vector3d(0.0, 0.0, 0.0)),
m_saveRadius(0.0),
m_baseName(std::string()),
m_pageName(std::string()),
m_detailName(std::string()),
m_doc(nullptr),
m_mode(CREATEMODE),
m_created(false)
{
if (m_baseFeat == nullptr) {
//should be caught in CMD caller
Base::Console().Error("TaskDetail - bad parameters - base feature. Can not proceed.\n");
return;
}
m_basePage = m_baseFeat->findParentPage();
if (m_basePage == nullptr) {
Base::Console().Error("TaskDetail - bad parameters - base page. Can not proceed.\n");
}
m_baseName = m_baseFeat->getNameInDocument();
m_doc = m_baseFeat->getDocument();
m_pageName = m_basePage->getNameInDocument();
ui->setupUi(this);
Gui::Document* activeGui = Gui::Application::Instance->getDocument(m_doc);
Gui::ViewProvider* vp = activeGui->getViewProvider(m_basePage);
ViewProviderPage* vpp = static_cast<ViewProviderPage*>(vp);
m_mdi = vpp->getMDIViewPage();
m_scene = m_mdi->m_scene;
m_view = m_mdi->getQGVPage();
createDetail();
setUiFromFeat();
setWindowTitle(QObject::tr("New Detail"));
connect(ui->pbDragger, SIGNAL(clicked(bool)),
this, SLOT(onDraggerClicked(bool)));
connect(ui->qsbX, SIGNAL(editingFinished()),
this, SLOT(onXEdit()));
connect(ui->qsbY, SIGNAL(editingFinished()),
this, SLOT(onYEdit()));
connect(ui->qsbRadius, SIGNAL(editingFinished()),
this, SLOT(onRadiusEdit()));
m_ghost = new QGIGhostHighlight();
m_scene->addItem(m_ghost);
m_ghost->hide();
connect(m_ghost, SIGNAL(positionChange(QPointF)),
this, SLOT(onHighlightMoved(QPointF)));
}
//edit ctor
TaskDetail::TaskDetail(TechDraw::DrawViewDetail* detailFeat):
ui(new Ui_TaskDetail),
m_detailFeat(detailFeat),
m_baseFeat(nullptr),
m_basePage(nullptr),
m_inProgressLock(false),
m_saveAnchor(Base::Vector3d(0.0, 0.0, 0.0)),
m_saveRadius(0.0),
m_baseName(std::string()),
m_pageName(std::string()),
m_detailName(std::string()),
m_doc(nullptr),
m_mode(EDITMODE),
m_created(false)
{
if (m_detailFeat == nullptr) {
//should be caught in CMD caller
Base::Console().Error("TaskDetail - bad parameters. Can not proceed.\n");
return;
}
m_doc = m_detailFeat->getDocument();
m_detailName = m_detailFeat->getNameInDocument();
m_basePage = m_detailFeat->findParentPage();
if (m_basePage != nullptr) {
m_pageName = m_basePage->getNameInDocument();
}
App::DocumentObject* baseObj = m_detailFeat->BaseView.getValue();
m_baseFeat = dynamic_cast<TechDraw::DrawViewPart*>(baseObj);
if (m_baseFeat != nullptr) {
m_baseName = m_baseFeat->getNameInDocument();
} else {
Base::Console().Error("TaskDetail - no BaseView. Can not proceed.\n");
return;
}
ui->setupUi(this);
Gui::Document* activeGui = Gui::Application::Instance->getDocument(m_basePage->getDocument());
Gui::ViewProvider* vp = activeGui->getViewProvider(m_basePage);
ViewProviderPage* vpp = static_cast<ViewProviderPage*>(vp);
m_mdi = vpp->getMDIViewPage();
m_scene = m_mdi->m_scene;
m_view = m_mdi->getQGVPage();
saveDetailState();
setUiFromFeat();
setWindowTitle(QObject::tr("Edit Detail"));
connect(ui->pbDragger, SIGNAL(clicked(bool)),
this, SLOT(onDraggerClicked(bool)));
connect(ui->qsbX, SIGNAL(editingFinished()),
this, SLOT(onXEdit()));
connect(ui->qsbY, SIGNAL(editingFinished()),
this, SLOT(onYEdit()));
connect(ui->qsbRadius, SIGNAL(editingFinished()),
this, SLOT(onRadiusEdit()));
connect(ui->aeReference, SIGNAL(editingFinished()),
this, SLOT(onReferenceEdit()));
m_ghost = new QGIGhostHighlight();
m_scene->addItem(m_ghost);
m_ghost->hide();
connect(m_ghost, SIGNAL(positionChange(QPointF)),
this, SLOT(onHighlightMoved(QPointF)));
}
TaskDetail::~TaskDetail()
{
delete ui;
}
void TaskDetail::updateTask()
{
// blockUpdate = true;
// blockUpdate = false;
}
void TaskDetail::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
}
//save the start conditions
void TaskDetail::saveDetailState()
{
// Base::Console().Message("TD::saveDetailState()\n");
TechDraw::DrawViewDetail* dvd = getDetailFeat();
m_saveAnchor = dvd->AnchorPoint.getValue();
m_saveRadius = dvd->Radius.getValue();
m_saved = true;
}
void TaskDetail::restoreDetailState()
{
// Base::Console().Message("TD::restoreDetailState()\n");
TechDraw::DrawViewDetail* dvd = getDetailFeat();
dvd->AnchorPoint.setValue(m_saveAnchor);
dvd->Radius.setValue(m_saveRadius);
}
//***** ui stuff ***************************************************************
void TaskDetail::setUiFromFeat()
{
// Base::Console().Message("TD::setUIFromFeat()\n");
if (m_baseFeat != nullptr) {
std::string baseName = getBaseFeat()->getNameInDocument();
ui->leBaseView->setText(Base::Tools::fromStdString(baseName));
}
Base::Vector3d anchor;
double radius;
TechDraw::DrawViewDetail* detailFeat = getDetailFeat();
QString detailDisplay = QString::fromUtf8(detailFeat->getNameInDocument()) +
QString::fromUtf8(" / ") +
QString::fromUtf8(detailFeat->Label.getValue());
ui->leDetailView->setText(detailDisplay);
anchor = detailFeat->AnchorPoint.getValue();
radius = detailFeat->Radius.getValue();
QString ref = QString::fromUtf8(detailFeat->Reference.getValue());
ui->pbDragger->setText(QString::fromUtf8("Drag Highlight"));
ui->pbDragger->setEnabled(true);
int decimals = Base::UnitsApi::getDecimals();
ui->qsbX->setUnit(Base::Unit::Length);
ui->qsbX->setDecimals(decimals);
ui->qsbY->setUnit(Base::Unit::Length);
ui->qsbY->setDecimals(decimals);
ui->qsbRadius->setDecimals(decimals);
ui->qsbRadius->setUnit(Base::Unit::Length);
ui->qsbX->setValue(anchor.x);
ui->qsbY->setValue(anchor.y);
ui->qsbRadius->setValue(radius);
ui->aeReference->setText(ref);
}
//update ui point fields after tracker finishes
void TaskDetail::updateUi(QPointF p)
{
ui->qsbX->setValue(p.x());
ui->qsbY->setValue(- p.y());
}
void TaskDetail::enableInputFields(bool b)
{
ui->qsbX->setEnabled(b);
ui->qsbY->setEnabled(b);
ui->qsbRadius->setEnabled(b);
ui->aeReference->setEnabled(b);
}
void TaskDetail::onXEdit()
{
updateDetail();
}
void TaskDetail::onYEdit()
{
updateDetail();
}
void TaskDetail::onRadiusEdit()
{
updateDetail();
}
void TaskDetail::onReferenceEdit()
{
updateDetail();
}
void TaskDetail::onDraggerClicked(bool b)
{
Q_UNUSED(b);
ui->pbDragger->setEnabled(false);
enableInputFields(false);
editByHighlight();
return;
}
void TaskDetail::editByHighlight()
{
// Base::Console().Message("TD::editByHighlight()\n");
if (m_ghost == nullptr) {
Base::Console().Error("TaskDetail::editByHighlight - no ghost object\n");
return;
}
m_scene->clearSelection();
m_ghost->setSelected(true);
m_ghost->setPos(getAnchorScene());
m_ghost->draw();
m_ghost->show();
}
//dragEnd is in scene coords.
void TaskDetail::onHighlightMoved(QPointF dragEnd)
{
// Base::Console().Message("TD::onHighlightMoved(%s) - highlight: %X\n",
// DrawUtil::formatVector(dragEnd).c_str(), m_ghost);
ui->pbDragger->setEnabled(true);
double scale = getBaseFeat()->getScale();
double x = Rez::guiX(getBaseFeat()->X.getValue()) * scale;
double y = Rez::guiX(getBaseFeat()->Y.getValue()) * scale;
QPointF basePosScene(x, -y); //base position in scene coords
QPointF anchorDisplace = dragEnd - basePosScene;
QPointF newAnchorPos = Rez::appX(anchorDisplace) / scale;
updateUi(newAnchorPos);
updateDetail();
enableInputFields(true);
m_ghost->setSelected(false);
m_ghost->hide();
}
void TaskDetail::saveButtons(QPushButton* btnOK,
QPushButton* btnCancel)
{
m_btnOK = btnOK;
m_btnCancel = btnCancel;
}
void TaskDetail::enableTaskButtons(bool b)
{
m_btnOK->setEnabled(b);
m_btnCancel->setEnabled(b);
}
//***** Feature create & edit stuff *******************************************
void TaskDetail::createDetail()
{
// Base::Console().Message("TD::createDetail()\n");
Gui::Command::openCommand("Create Detail");
m_detailName = m_doc->getUniqueObjectName("Detail");
Gui::Command::doCommand(Command::Doc,"App.activeDocument().addObject('TechDraw::DrawViewDetail','%s')",
m_detailName.c_str());
App::DocumentObject *docObj = m_doc->getObject(m_detailName.c_str());
TechDraw::DrawViewDetail* dvd = dynamic_cast<TechDraw::DrawViewDetail *>(docObj);
if (!dvd) {
throw Base::TypeError("TaskDetail - new detail not found\n");
}
m_detailFeat = dvd;
dvd->Source.setValues(getBaseFeat()->Source.getValues());
Gui::Command::doCommand(Command::Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",
m_detailName.c_str(),m_baseName.c_str());
Gui::Command::doCommand(Command::Doc,"App.activeDocument().%s.Direction = App.activeDocument().%s.Direction",
m_detailName.c_str(),m_baseName.c_str());
Gui::Command::doCommand(Command::Doc,"App.activeDocument().%s.XDirection = App.activeDocument().%s.XDirection",
m_detailName.c_str(),m_baseName.c_str());
Gui::Command::doCommand(Command::Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",
m_pageName.c_str(), m_detailName.c_str());
Gui::Command::updateActive();
Gui::Command::commitCommand();
getBaseFeat()->requestPaint();
m_created = true;
}
void TaskDetail::updateDetail()
{
// Base::Console().Message("TD::updateDetail()\n");
Gui::Command::openCommand("Update Detail");
double x = ui->qsbX->rawValue();
double y = ui->qsbY->rawValue();
Base::Vector3d temp(x, y, 0.0);
TechDraw::DrawViewDetail* detailFeat = getDetailFeat();
detailFeat->AnchorPoint.setValue(temp);
double radius = ui->qsbRadius->rawValue();
detailFeat->Radius.setValue(radius);
QString qRef = ui->aeReference->text();
std::string ref = Base::Tools::toStdString(qRef);
detailFeat->Reference.setValue(ref);
detailFeat->recomputeFeature();
getBaseFeat()->requestPaint();
Gui::Command::updateActive();
Gui::Command::commitCommand();
}
//***** Getters ****************************************************************
//get the current Anchor highlight position in scene coords
QPointF TaskDetail::getAnchorScene()
{
TechDraw::DrawViewPart* dvp = getBaseFeat();
TechDraw::DrawViewDetail* dvd = getDetailFeat();
Base::Vector3d anchorPos = dvd->AnchorPoint.getValue();
double x = dvp->X.getValue();
double y = dvp->Y.getValue();
Base::Vector3d basePos(x, y, 0.0);
Base::Vector3d netPos = basePos + anchorPos;
netPos = Rez::guiX(netPos * dvp->getScale());
QPointF qAnchor(netPos.x, - netPos.y);
return qAnchor;
}
// protects against stale pointers
DrawViewPart* TaskDetail::getBaseFeat()
{
// Base::Console().Message("TD::getBaseFeat()\n");
DrawViewPart* result = nullptr;
if (m_doc != nullptr) {
App::DocumentObject* baseObj = m_doc->getObject(m_baseName.c_str());
if (baseObj != nullptr) {
result = static_cast<DrawViewPart*>(baseObj);
}
}
if (result == nullptr) {
std::string msg = "TaskDetail - base feature " +
m_baseName +
" not found \n";
throw Base::TypeError(msg);
}
return result;
}
// protects against stale pointers
DrawViewDetail* TaskDetail::getDetailFeat()
{
// Base::Console().Message("TD::getDetailFeat()\n");
DrawViewDetail* result = nullptr;
if (m_doc != nullptr) {
App::DocumentObject* detailObj = m_doc->getObject(m_detailName.c_str());
if (detailObj != nullptr) {
result = static_cast<DrawViewDetail*>(detailObj);
}
}
if (result == nullptr) {
std::string msg = "TaskDetail - detail feature " +
m_detailName +
" not found \n";
// throw Base::TypeError("TaskDetail - detail feature not found\n");
throw Base::TypeError(msg);
}
return result;
}
//******************************************************************************
bool TaskDetail::accept()
{
// Base::Console().Message("TD::accept()\n");
Gui::Document* doc = Gui::Application::Instance->getDocument(m_basePage->getDocument());
if (!doc) return false;
getDetailFeat()->requestPaint();
getBaseFeat()->requestPaint();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
return true;
}
bool TaskDetail::reject()
{
// Base::Console().Message("TD::reject()\n");
Gui::Document* doc = Gui::Application::Instance->getDocument(m_basePage->getDocument());
if (!doc) return false;
if (m_mode == CREATEMODE) {
if (m_created) {
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().removeObject('%s')",
m_detailName.c_str());
}
} else {
restoreDetailState();
getDetailFeat()->recomputeFeature();
getBaseFeat()->requestPaint();
}
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().recompute()");
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
return false;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TaskDlgDetail::TaskDlgDetail(TechDraw::DrawViewPart* baseFeat)
: TaskDialog()
{
widget = new TaskDetail(baseFeat);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/techdraw-DetailView"),
widget->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskDlgDetail::TaskDlgDetail(TechDraw::DrawViewDetail* detailFeat)
: TaskDialog()
{
widget = new TaskDetail(detailFeat);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/techdraw-DetailView"),
widget->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskDlgDetail::~TaskDlgDetail()
{
}
void TaskDlgDetail::update()
{
// widget->updateTask();
}
void TaskDlgDetail::modifyStandardButtons(QDialogButtonBox* box)
{
QPushButton* btnOK = box->button(QDialogButtonBox::Ok);
QPushButton* btnCancel = box->button(QDialogButtonBox::Cancel);
widget->saveButtons(btnOK, btnCancel);
}
//==== calls from the TaskView ===============================================================
void TaskDlgDetail::open()
{
}
void TaskDlgDetail::clicked(int)
{
}
bool TaskDlgDetail::accept()
{
widget->accept();
return true;
}
bool TaskDlgDetail::reject()
{
widget->reject();
return true;
}
#include <Mod/TechDraw/Gui/moc_TaskDetail.cpp>
+179
View File
@@ -0,0 +1,179 @@
/***************************************************************************
* Copyright (c) 2020 WandererFan <wandererfan@gmail.com> *
* *
* 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 TECHDRAWGUI_TASKCOSVERTEX_H
#define TECHDRAWGUI_TASKCOSVERTEX_H
#include <App/DocumentObject.h>
#include <Base/Vector3D.h>
#include <Gui/TaskView/TaskView.h>
#include <Gui/TaskView/TaskDialog.h>
#include <Mod/TechDraw/Gui/ui_TaskDetail.h>
//TODO: make this a proper enum
#define TRACKERPICK 0
#define TRACKEREDIT 1
#define TRACKERCANCEL 2
#define TRACKERCANCELEDIT 3
class Ui_TaskDetail;
namespace App {
class DocumentObject;
}
namespace TechDraw
{
class DrawPage;
class DrawView;
class DrawDetail;
class DrawViewPart;
}
namespace TechDrawGui
{
class QGVPage;
class QGIView;
class QGIPrimPath;
class MDIViewPage;
class QGEPath;
class QGIDetail;
class QGIGhostHighlight;
class ViewProviderLeader;
class TaskDetail : public QWidget
{
Q_OBJECT
public:
TaskDetail(TechDraw::DrawViewPart* baseFeat);
TaskDetail(TechDraw::DrawViewDetail* detailFeat);
~TaskDetail();
public Q_SLOTS:
void onDraggerClicked(bool b);
void onHighlightMoved(QPointF newPos);
void onXEdit();
void onYEdit();
void onRadiusEdit();
void onReferenceEdit();
public:
virtual bool accept();
virtual bool reject();
void updateTask();
void saveButtons(QPushButton* btnOK,
QPushButton* btnCancel);
void enableTaskButtons(bool b);
protected:
void changeEvent(QEvent *e);
void startDragger(void);
void createDetail();
void updateDetail();
void editByHighlight();
void blockButtons(bool b);
void setUiFromFeat(void);
void updateUi(QPointF p);
void enableInputFields(bool b);
void saveDetailState();
void restoreDetailState();
QPointF getAnchorScene();
TechDraw::DrawViewPart* getBaseFeat();
TechDraw::DrawViewDetail* getDetailFeat();
private:
Ui_TaskDetail * ui;
bool blockUpdate;
QGIGhostHighlight* m_ghost;
MDIViewPage* m_mdi;
QGraphicsScene* m_scene;
QGVPage* m_view;
TechDraw::DrawViewDetail* m_detailFeat;
TechDraw::DrawViewPart* m_baseFeat;
TechDraw::DrawPage* m_basePage;
QGIView* m_qgParent;
std::string m_qgParentName;
bool m_inProgressLock;
QPushButton* m_btnOK;
QPushButton* m_btnCancel;
Base::Vector3d m_saveAnchor;
double m_saveRadius;
bool m_saved;
QPointF m_dragStart;
std::string m_baseName;
std::string m_pageName;
std::string m_detailName;
App::Document* m_doc;
bool m_mode;
bool m_created;
};
class TaskDlgDetail : public Gui::TaskView::TaskDialog
{
Q_OBJECT
public:
TaskDlgDetail(TechDraw::DrawViewPart* baseFeat);
TaskDlgDetail(TechDraw::DrawViewDetail* detailFeat);
~TaskDlgDetail();
public:
/// is called the TaskView when the dialog is opened
virtual void open();
/// is called by the framework if an button is clicked which has no accept or reject role
virtual void clicked(int);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
/// is called by the framework if the dialog is rejected (Cancel)
virtual bool reject();
/// is called by the framework if the user presses the help button
virtual void helpRequested() { return;}
virtual bool isAllowedAlterDocument(void) const
{ return false; }
void update();
void modifyStandardButtons(QDialogButtonBox* box);
protected:
private:
TaskDetail * widget;
Gui::TaskView::TaskBox* taskbox;
};
} //namespace TechDrawGui
#endif // #ifndef TECHDRAWGUI_TASKCOSVERTEX_H
+296
View File
@@ -0,0 +1,296 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TechDrawGui::TaskDetail</class>
<widget class="QWidget" name="TechDrawGui::TaskDetail">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>405</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Detail Anchor</string>
</property>
<property name="windowIcon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/actions/techdraw-DetailView.svg</normaloff>:/icons/actions/techdraw-DetailView.svg</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>300</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>300</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLineEdit" name="leBaseView">
<property name="enabled">
<bool>false</bool>
</property>
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Base View</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Detail View</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leDetailView">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pbDragger">
<property name="toolTip">
<string>Click to drag detail highlight to new position</string>
</property>
<property name="text">
<string>Drag Highlight</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="2,1,2">
<item row="2" column="2">
<widget class="Gui::QuantitySpinBox" name="qsbRadius">
<property name="toolTip">
<string>size of detail view</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Gui::QuantitySpinBox" name="qsbX">
<property name="toolTip">
<string>x position of detail highlight within view</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::QuantitySpinBox" name="qsbY">
<property name="toolTip">
<string>y position of detail highlight within view</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Radius</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Reference</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::AccelLineEdit" name="aeReference">
<property name="toolTip">
<string>Detail identifier</string>
</property>
<property name="text">
<string>1</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::AccelLineEdit</class>
<extends>QLineEdit</extends>
<header>Gui/Widgets.h</header>
</customwidget>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="Resources/TechDraw.qrc"/>
</resources>
<connections/>
</ui>
+1 -1
View File
@@ -376,7 +376,7 @@ void TaskWeldingSymbol::onFlipSidesClicked()
ui->leOtherTextR->setText(ui->leArrowTextR->text());
ui->leArrowTextR->setText(tempText);
// one cannot get the path from the icon therfore read out
// one cannot get the path from the icon therefore read out
// the path property
auto tempPathArrow = m_arrowFeat->SymbolFile.getValue();
auto tempPathOther = m_otherFeat->SymbolFile.getValue();
@@ -37,19 +37,29 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Gui/Application.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawLeaderLine.h>
#include <Mod/TechDraw/App/DrawRichAnno.h>
#include <Mod/TechDraw/App/DrawViewMulti.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawWeldSymbol.h>
#include <Mod/TechDraw/App/LineGroup.h>
#include<Mod/TechDraw/App/DrawPage.h>
#include "QGIView.h"
#include "TaskDetail.h"
#include "ViewProviderViewPart.h"
using namespace TechDrawGui;
@@ -166,8 +176,11 @@ void ViewProviderViewPart::onChanged(const App::Property* prop)
void ViewProviderViewPart::attach(App::DocumentObject *pcFeat)
{
TechDraw::DrawViewMulti* dvm = dynamic_cast<TechDraw::DrawViewMulti*>(pcFeat);
TechDraw::DrawViewDetail* dvd = dynamic_cast<TechDraw::DrawViewDetail*>(pcFeat);
if (dvm != nullptr) {
sPixmap = "TechDraw_Tree_Multi";
} else if (dvd != nullptr) {
sPixmap = "actions/techdraw-DetailView";
}
ViewProviderDrawingView::attach(pcFeat);
@@ -232,6 +245,57 @@ std::vector<App::DocumentObject*> ViewProviderViewPart::claimChildren(void) cons
return tmp;
}
}
bool ViewProviderViewPart::setEdit(int ModNum)
{
if (ModNum == ViewProvider::Default ) {
if (Gui::Control().activeDialog()) { //TaskPanel already open!
return false;
}
TechDraw::DrawViewPart* dvp = getViewObject();
TechDraw::DrawViewDetail* dvd = dynamic_cast<TechDraw::DrawViewDetail*>(dvp);
if (dvd != nullptr) {
// clear the selection (convenience)
Gui::Selection().clearSelection();
Gui::Control().showDialog(new TaskDlgDetail(dvd));
// Gui::Selection().clearSelection();
// flush any lingering gui objects
Gui::Selection().addSelection(dvd->getDocument()->getName(),
dvd->getNameInDocument());
Gui::Selection().clearSelection();
Gui::Selection().addSelection(dvd->getDocument()->getName(),
dvd->getNameInDocument());
//Gui.ActiveDocument.resetEdit()
//>>> # Gui.Selection.addSelection('aaStart121','Detail')
//>>> # Gui.Selection.clearSelection()
//>>> # Gui.Selection.addSelection('aaStart121','Detail')
//>>> # Gui.Selection.addSelection('aaStart121','Detail')
//>>> # Gui.Selection.clearSelection()
//>>> # Gui.Selection.addSelection('aaStart121','Detail')
return true;
}
} else {
return ViewProviderDrawingView::setEdit(ModNum);
}
return true;
}
void ViewProviderViewPart::unsetEdit(int ModNum)
{
Q_UNUSED(ModNum);
if (ModNum == ViewProvider::Default) {
Gui::Control().closeDialog();
}
else {
ViewProviderDrawingView::unsetEdit(ModNum);
}
}
bool ViewProviderViewPart::doubleClicked(void)
{
setEdit(ViewProvider::Default);
return true;
}
TechDraw::DrawViewPart* ViewProviderViewPart::getViewObject() const
{
@@ -68,6 +68,9 @@ public:
virtual std::vector<std::string> getDisplayModes(void) const;
virtual bool onDelete(const std::vector<std::string> &);
virtual bool canDelete(App::DocumentObject* obj) const;
virtual bool setEdit(int ModNum);
virtual void unsetEdit(int ModNum);
virtual bool doubleClicked(void);
public:
virtual void onChanged(const App::Property *prop);