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