From c8fda889a258fc3913afefb713131c4af844f113 Mon Sep 17 00:00:00 2001 From: IMback Date: Thu, 8 Aug 2019 10:38:30 +0200 Subject: [PATCH 1/8] Peck retract height default changed from 10mm to opStartDepth+1 Peck depth default changed to tool dia*0.75 Fields changed to QuanitiySpinBoxes Insure travel between regions is always performed at safe height Make Peck and Dwell exclusive in GUI Restore name of RetractHeight Use SetupSheet for all numerical properties --- .../Resources/panels/PageOpDrillingEdit.ui | 83 +++++++++++-------- src/Mod/Path/PathScripts/PathDrilling.py | 46 ++++++---- src/Mod/Path/PathScripts/PathDrillingGui.py | 50 +++++++++-- src/Mod/Path/PathScripts/PathGui.py | 5 ++ src/Mod/Path/PathScripts/PathOpGui.py | 1 + 5 files changed, 128 insertions(+), 57 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpDrillingEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpDrillingEdit.ui index c4d2e3530b6f..b1ad210bb334 100644 --- a/src/Mod/Path/Gui/Resources/panels/PageOpDrillingEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/PageOpDrillingEdit.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 255 + 572 + 299 @@ -49,55 +49,75 @@ - - + + - Dwell + Use Tip Length - - - - 0 sec + + + + false - - sec + + Time - - - - mm + + + + false + + + Depth - - + + + + false + - Retract Height + Retract - + + + + false + + + + Peck - - - - mm + + + + Dwell - - - - Use Tip Length + + + + false + + + + + + + false @@ -121,18 +141,15 @@ - Gui::InputField - QLineEdit -
Gui/InputField.h
+ Gui::QuantitySpinBox + QDoubleSpinBox +
Gui/QuantitySpinBox.h
toolController - retractHeight peckEnabled - peckDepth dwellEnabled - dwellTime useTipLength diff --git a/src/Mod/Path/PathScripts/PathDrilling.py b/src/Mod/Path/PathScripts/PathDrilling.py index 70b3306832d2..ee58d3e3358e 100644 --- a/src/Mod/Path/PathScripts/PathDrilling.py +++ b/src/Mod/Path/PathScripts/PathDrilling.py @@ -43,7 +43,7 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "http://www.freecadweb.org" __doc__ = "Path Drilling operation." -__contributors__ = "russ4262 (Russell Johnson)" +__contributors__ = "russ4262 (Russell Johnson), IMBack!" __created__ = "2014" __scriptVersion__ = "1c testing" __lastModified__ = "2019-06-25 14:49 CST" @@ -77,10 +77,9 @@ def initCircularHoleOperation(self, obj): obj.addProperty("App::PropertyFloat", "DwellTime", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "The time to dwell between peck cycles")) obj.addProperty("App::PropertyBool", "DwellEnabled", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "Enable dwell")) obj.addProperty("App::PropertyBool", "AddTipLength", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "Calculate the tip length and subtract from final depth")) - obj.addProperty("App::PropertyEnumeration", "ReturnLevel", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "Controls how tool retracts Default=G98")) - obj.ReturnLevel = ['G98', 'G99'] # this is the direction that the Contour runs - - obj.addProperty("App::PropertyDistance", "RetractHeight", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "The height where feed starts and height during retract tool when path is finished")) + obj.addProperty("App::PropertyEnumeration", "ReturnLevel", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "Controls how tool retracts Default=G99")) + obj.ReturnLevel = ['G99', 'G98'] # Canned Cycle Return Level + obj.addProperty("App::PropertyDistance", "RetractHeight", "Drill", QtCore.QT_TRANSLATE_NOOP("App::Property", "The height where feed starts and height during retract tool when path is finished while in a peck operation")) # Rotation related properties if not hasattr(obj, 'EnableRotation'): @@ -116,20 +115,14 @@ def circularHoleExecute(self, obj, holes): self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) - # ml: I'm not sure whey these were here, they seem redundant - # # rapid to first hole location, with spindle still retracted: - # p0 = holes[0] - # self.commandlist.append(Path.Command('G0', {'X': p0['x'], 'Y': p0['y'], 'F': self.horizRapid})) - # # move tool to clearance plane - # self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) - for p in holes: cmd = "G81" cmdParams = {} cmdParams['Z'] = p['trgtDep'] - tiplength cmdParams['F'] = self.vertFeed - cmdParams['R'] = obj.RetractHeight.Value + cmdParams['R'] = obj.SafeHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: + cmdParams['R'] = obj.RetractHeight.Value cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: @@ -172,23 +165,45 @@ def circularHoleExecute(self, obj, holes): self.commandlist.append(Path.Command('G0', {axisOfRot: angle, 'F': self.axialRapid})) self.commandlist.append(Path.Command('G0', {'X': p['x'], 'Y': p['y'], 'F': self.horizRapid})) self.commandlist.append(Path.Command('G1', {'Z': p['stkTop'], 'F': self.vertFeed})) - + # Perform and cancel canned drilling cycle self.commandlist.append(Path.Command(cmd, params)) self.commandlist.append(Path.Command('G80')) + + # shift axis and angle values if obj.EnableRotation != 'Off': lastAxis = axisOfRot lastAngle = angle + elif obj.PeckEnabled and obj.PeckDepth.Value > 0 and obj.RetractHeight.Value != obj.SafeHeight.Value: + self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value})) if obj.EnableRotation != 'Off': self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) self.commandlist.append(Path.Command('G0', {lastAxis: 0.0, 'F': self.axialRapid})) + def opSetDefaultValues(self, obj, job): '''opSetDefaultValues(obj, job) ... set default value for RetractHeight''' - obj.RetractHeight = 10.0 + + parentJob = PathUtils.findParentJob(obj) + + if hasattr(parentJob.SetupSheet, 'RetractHeight'): + obj.RetractHeight = parentJob.SetupSheet.RetractHeight + elif self.applyExpression(obj, 'RetractHeight', 'OpStartDepth+1mm'): + obj.RetractHeight = 10 + + if hasattr(parentJob.SetupSheet, 'PeckDepth'): + obj.PeckDepth = parentJob.SetupSheet.PeckDepth + elif self.applyExpression(obj, 'PeckDepth', 'OpToolDiameter*0.75'): + obj.PeckDepth = 1 + + if hasattr(parentJob.SetupSheet, 'DwellTime'): + obj.DwellTime = parentJob.SetupSheet.DwellTime + else: + obj.DwellTime = 1 + obj.ReverseDirection = False obj.InverseAngle = False obj.B_AxisErrorOverride = False @@ -196,7 +211,6 @@ def opSetDefaultValues(self, obj, job): # Initial setting for EnableRotation is taken from Job SetupSheet # User may override on per-operation basis as needed. - parentJob = PathUtils.findParentJob(obj) if hasattr(parentJob.SetupSheet, 'SetupEnableRotation'): obj.EnableRotation = parentJob.SetupSheet.SetupEnableRotation else: diff --git a/src/Mod/Path/PathScripts/PathDrillingGui.py b/src/Mod/Path/PathScripts/PathDrillingGui.py index 3415e76f0a46..8b053ec6eb6d 100644 --- a/src/Mod/Path/PathScripts/PathDrillingGui.py +++ b/src/Mod/Path/PathScripts/PathDrillingGui.py @@ -36,6 +36,7 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "http://www.freecadweb.org" __doc__ = "UI and Command for Path Drilling Operation." +__contributors__ = "IMBack!" LOGLEVEL = False @@ -48,17 +49,49 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): '''Controller for the drilling operation's page''' + + def initPage(self, obj): + self.peckDepthSpinBox = PathGui.QuantitySpinBox(self.form.peckDepth, obj, 'PeckDepth') + self.peckRetractSpinBox = PathGui.QuantitySpinBox(self.form.peckRetractHeight, obj, 'RetractHeight') + self.dwellTimeSpinBox = PathGui.QuantitySpinBox(self.form.dwellTime, obj, 'DwellTime') + + def registerSignalHandlers(self, obj): + self.form.peckEnabled.toggled.connect(self.form.peckDepth.setEnabled) + self.form.peckEnabled.toggled.connect(self.form.peckRetractHeight.setEnabled) + self.form.peckEnabled.toggled.connect(self.form.peckDepthLabel.setEnabled) + self.form.peckEnabled.toggled.connect(self.form.retractLabel.setEnabled) + self.form.peckEnabled.toggled.connect(self.form.dwellEnabled.setDisabled) + + self.form.dwellEnabled.toggled.connect(self.form.dwellTime.setEnabled) + self.form.dwellEnabled.toggled.connect(self.form.dwellTimelabel.setEnabled) + self.form.dwellEnabled.toggled.connect(self.form.peckEnabled.setDisabled) + + if self.form.peckEnabled.isChecked(): + self.form.dwellEnabled.setEnabled(False) + self.form.peckDepth.setEnabled(True) + self.form.peckRetractHeight.setEnabled(True) + self.form.peckDepthLabel.setEnabled(True) + self.form.retractLabel.setEnabled(True) + elif self.form.dwellEnabled.isChecked(): + self.form.peckEnabled.setEnabled(False) + self.form.dwellTime.setEnabled(True) + self.form.dwellTimelabel.setEnabled(True) def getForm(self): '''getForm() ... return UI''' return FreeCADGui.PySideUic.loadUi(":/panels/PageOpDrillingEdit.ui") + + def updateQuantitySpinBoxes(self, index = None): + self.peckDepthSpinBox.updateSpinBox() + self.peckRetractSpinBox.updateSpinBox() + self.dwellTimeSpinBox.updateSpinBox() def getFields(self, obj): '''setFields(obj) ... update obj's properties with values from the UI''' PathLog.track() - PathGui.updateInputField(obj, 'PeckDepth', self.form.peckDepth) - PathGui.updateInputField(obj, 'RetractHeight', self.form.retractHeight) - PathGui.updateInputField(obj, 'DwellTime', self.form.dwellTime) + self.peckDepthSpinBox.updateProperty() + self.peckRetractSpinBox.updateProperty() + self.dwellTimeSpinBox.updateProperty() if obj.DwellEnabled != self.form.dwellEnabled.isChecked(): obj.DwellEnabled = self.form.dwellEnabled.isChecked() @@ -72,10 +105,7 @@ def getFields(self, obj): def setFields(self, obj): '''setFields(obj) ... update UI with obj properties' values''' PathLog.track() - - self.form.peckDepth.setText(FreeCAD.Units.Quantity(obj.PeckDepth.Value, FreeCAD.Units.Length).UserString) - self.form.retractHeight.setText(FreeCAD.Units.Quantity(obj.RetractHeight.Value, FreeCAD.Units.Length).UserString) - self.form.dwellTime.setText(str(obj.DwellTime)) + self.updateQuantitySpinBoxes() if obj.DwellEnabled: self.form.dwellEnabled.setCheckState(QtCore.Qt.Checked) @@ -98,7 +128,7 @@ def getSignalsForUpdate(self, obj): '''getSignalsForUpdate(obj) ... return list of signals which cause the receiver to update the model''' signals = [] - signals.append(self.form.retractHeight.editingFinished) + signals.append(self.form.peckRetractHeight.editingFinished) signals.append(self.form.peckDepth.editingFinished) signals.append(self.form.dwellTime.editingFinished) signals.append(self.form.dwellEnabled.stateChanged) @@ -107,6 +137,10 @@ def getSignalsForUpdate(self, obj): signals.append(self.form.toolController.currentIndexChanged) return signals + + def updateData(self, obj, prop): + if prop in ['PeckDepth', 'RetractHeight'] and not prop in ['Base', 'Disabled']: + self.updateQuantitySpinBoxes() Command = PathOpGui.SetupOperation('Drilling', PathDrilling.Create, diff --git a/src/Mod/Path/PathScripts/PathGui.py b/src/Mod/Path/PathScripts/PathGui.py index cd00faac57f2..ed2e9e757d2e 100644 --- a/src/Mod/Path/PathScripts/PathGui.py +++ b/src/Mod/Path/PathScripts/PathGui.py @@ -122,6 +122,11 @@ def expression(self): if self.valid: return self.widget.property('expression') return '' + + def setMinimum(self, quantity): + if self.valid: + value = quantity.Value if hasattr(quantity, 'Value') else quantity + self.widget.setProperty('setMinimum', value) def updateSpinBox(self, quantity=None): '''updateSpinBox(quantity=None) ... update the display value of the spin box. diff --git a/src/Mod/Path/PathScripts/PathOpGui.py b/src/Mod/Path/PathScripts/PathOpGui.py index ac037a578c8f..c350c68e877d 100644 --- a/src/Mod/Path/PathScripts/PathOpGui.py +++ b/src/Mod/Path/PathScripts/PathOpGui.py @@ -354,6 +354,7 @@ def setupToolController(self, obj, combo): controllers = PathUtils.getToolControllers(self.obj) labels = [c.Label for c in controllers] combo.blockSignals(True) + combo.clear() combo.addItems(labels) combo.blockSignals(False) From 4f8af51864a057e1f468fef1307851dbd931fe67 Mon Sep 17 00:00:00 2001 From: IMback Date: Thu, 8 Aug 2019 19:29:26 +0200 Subject: [PATCH 2/8] Restore R parameter behavior --- src/Mod/Path/PathScripts/PathDrilling.py | 9 +++------ src/Mod/Path/PathScripts/PathDrillingGui.py | 8 +++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathDrilling.py b/src/Mod/Path/PathScripts/PathDrilling.py index ee58d3e3358e..8ab8b713c946 100644 --- a/src/Mod/Path/PathScripts/PathDrilling.py +++ b/src/Mod/Path/PathScripts/PathDrilling.py @@ -114,15 +114,14 @@ def circularHoleExecute(self, obj, holes): holes = PathUtils.sort_jobs(holes, ['x', 'y']) self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) - + for p in holes: cmd = "G81" cmdParams = {} cmdParams['Z'] = p['trgtDep'] - tiplength cmdParams['F'] = self.vertFeed - cmdParams['R'] = obj.SafeHeight.Value + cmdParams['R'] = obj.RetractHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: - cmdParams['R'] = obj.RetractHeight.Value cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: @@ -168,7 +167,7 @@ def circularHoleExecute(self, obj, holes): # Perform and cancel canned drilling cycle self.commandlist.append(Path.Command(cmd, params)) - self.commandlist.append(Path.Command('G80')) + self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value})) @@ -176,8 +175,6 @@ def circularHoleExecute(self, obj, holes): if obj.EnableRotation != 'Off': lastAxis = axisOfRot lastAngle = angle - elif obj.PeckEnabled and obj.PeckDepth.Value > 0 and obj.RetractHeight.Value != obj.SafeHeight.Value: - self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value})) if obj.EnableRotation != 'Off': self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) diff --git a/src/Mod/Path/PathScripts/PathDrillingGui.py b/src/Mod/Path/PathScripts/PathDrillingGui.py index 8b053ec6eb6d..a8eacaf96109 100644 --- a/src/Mod/Path/PathScripts/PathDrillingGui.py +++ b/src/Mod/Path/PathScripts/PathDrillingGui.py @@ -57,21 +57,19 @@ def initPage(self, obj): def registerSignalHandlers(self, obj): self.form.peckEnabled.toggled.connect(self.form.peckDepth.setEnabled) - self.form.peckEnabled.toggled.connect(self.form.peckRetractHeight.setEnabled) - self.form.peckEnabled.toggled.connect(self.form.peckDepthLabel.setEnabled) - self.form.peckEnabled.toggled.connect(self.form.retractLabel.setEnabled) self.form.peckEnabled.toggled.connect(self.form.dwellEnabled.setDisabled) self.form.dwellEnabled.toggled.connect(self.form.dwellTime.setEnabled) self.form.dwellEnabled.toggled.connect(self.form.dwellTimelabel.setEnabled) self.form.dwellEnabled.toggled.connect(self.form.peckEnabled.setDisabled) + self.form.peckRetractHeight.setEnabled(True) + self.form.retractLabel.setEnabled(True) + if self.form.peckEnabled.isChecked(): self.form.dwellEnabled.setEnabled(False) self.form.peckDepth.setEnabled(True) - self.form.peckRetractHeight.setEnabled(True) self.form.peckDepthLabel.setEnabled(True) - self.form.retractLabel.setEnabled(True) elif self.form.dwellEnabled.isChecked(): self.form.peckEnabled.setEnabled(False) self.form.dwellTime.setEnabled(True) From 1002ea9ad5c067fc26988f0db18e92107202abe5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 26 Aug 2019 14:08:53 +0200 Subject: [PATCH 3/8] add CMakeLists.txt.user to ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7cb7c65ab6b3..98e73eaa8c1b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ ui_*.h moc_*.cpp Makefile CMakeCache.txt +CMakeLists.txt.user config.h install_manifest.txt /bin/ From c499184359704d3d2be87a68c2de22d58e113224 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Sun, 25 Aug 2019 19:07:19 -0400 Subject: [PATCH 4/8] [Gui]Add options for page size, lineWidth and background --- src/Gui/SoFCVectorizeSVGAction.cpp | 27 +++++++++++++++++++-------- src/Gui/SoFCVectorizeSVGAction.h | 10 ++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/Gui/SoFCVectorizeSVGAction.cpp b/src/Gui/SoFCVectorizeSVGAction.cpp index e36a366a9a8e..893e0f2190a0 100644 --- a/src/Gui/SoFCVectorizeSVGAction.cpp +++ b/src/Gui/SoFCVectorizeSVGAction.cpp @@ -31,6 +31,7 @@ #include #include +#include #include "SoFCVectorizeSVGAction.h" using namespace Gui; @@ -306,7 +307,7 @@ void SoFCVectorizeSVGActionP::printTriangle(const SbVec3f * v, const SbColor * c << "; stroke:#" << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8) << ";" << std::endl - << " stroke-width:1.0;" << std::endl + << " stroke-width:" << publ->getLineWidth() << ";" << std::endl << " stroke-linecap:round;stroke-linejoin:round\"/>" << std::endl; } @@ -350,8 +351,9 @@ void SoFCVectorizeSVGActionP::printLine(const SoVectorizeLine * item) const << "x1=\"" << v[0][0] << "\" y1=\"" << v[0][1] << "\" " << "x2=\"" << v[1][0] << "\" y2=\"" << v[1][1] << "\" " << "stroke=\"#" - << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8) - << "\" stroke-width=\"1px\" />\n"; + << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8) << "\"" + << " stroke-linecap=\"square\" " + << " stroke-width=\"" << publ->getLineWidth() << "\" />\n"; } void SoFCVectorizeSVGActionP::printPoint(const SoVectorizePoint * item) const @@ -375,7 +377,10 @@ void SoFCVectorizeSVGAction::initClass(void) SO_ACTION_INIT_CLASS(SoFCVectorizeSVGAction, SoVectorizeAction); } -SoFCVectorizeSVGAction::SoFCVectorizeSVGAction() +SoFCVectorizeSVGAction::SoFCVectorizeSVGAction() : + m_backgroundState(true), + m_lineWidth(1.0), + m_usemm(false) { SO_ACTION_CONSTRUCTOR(SoFCVectorizeSVGAction); this->setOutput(new SoSVGVectorOutput); @@ -400,12 +405,18 @@ void SoFCVectorizeSVGAction::printHeader(void) const str << "" << std::endl; str << "getOrientation() == LANDSCAPE) + if (this->getOrientation() == LANDSCAPE) { SbSwap(size[0], size[1]); - str << " width=\"" << size[0] << "\" height=\"" << size[1] << "\">" << std::endl; + } + if (getUseMM()) { + str << " width=\"" << size[0] << "mm\" height=\"" << size[1] << "mm\""<< std::endl; + str << " viewBox=\"0 0 " << size[0] << " " << size[1] << "\">" << std::endl; + } else { //original code used px + str << " width=\"" << size[0] << "\" height=\"" << size[1] << "\">" << std::endl; + } str << "" << std::endl; } @@ -447,7 +458,7 @@ void SoFCVectorizeSVGAction::printBackground(void) const str << " style=\"fill:#" << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8) << ";fill-opacity:1;fill-rule:evenodd;stroke:none;" - "stroke-width:1px;stroke-linecap:butt;stroke-linejoin:" + "stroke-width:" << getLineWidth() << ";stroke-linecap:butt;stroke-linejoin:" "miter;stroke-opacity:1\" />\n"; str << "" << std::endl; } diff --git a/src/Gui/SoFCVectorizeSVGAction.h b/src/Gui/SoFCVectorizeSVGAction.h index bf6a750fc5e2..9728d1342324 100644 --- a/src/Gui/SoFCVectorizeSVGAction.h +++ b/src/Gui/SoFCVectorizeSVGAction.h @@ -62,6 +62,13 @@ class GuiExport SoFCVectorizeSVGAction : public SoVectorizeAction { static void initClass(void); SoSVGVectorOutput * getSVGOutput(void) const; + virtual void setBackgroundState(bool b) { m_backgroundState = b; } + virtual bool getBackgroundState(void) const { return m_backgroundState; } + virtual void setLineWidth(double w) { m_lineWidth = w; } + virtual double getLineWidth(void) const { return m_lineWidth; } + virtual void setUseMM(bool b) { m_usemm = b; } + virtual bool getUseMM(void) const { return m_usemm; } + protected: virtual void printHeader(void) const; virtual void printFooter(void) const; @@ -72,6 +79,9 @@ class GuiExport SoFCVectorizeSVGAction : public SoVectorizeAction { private: SoFCVectorizeSVGActionP* p; friend class SoFCVectorizeSVGActionP; + bool m_backgroundState; + double m_lineWidth; + bool m_usemm; }; } // namespace Gui From d60a03d9cd7adde57290d19ec64ef778785c04c6 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 25 Aug 2019 10:27:24 +1000 Subject: [PATCH 5/8] Refactor exportIFC to not use global preferences --- src/Mod/Arch/exportIFC.py | 143 +++++++++++++++++--------------------- src/Mod/Arch/importIFC.py | 2 +- 2 files changed, 65 insertions(+), 80 deletions(-) diff --git a/src/Mod/Arch/exportIFC.py b/src/Mod/Arch/exportIFC.py index 019fe55d9923..eaed5a81ac66 100644 --- a/src/Mod/Arch/exportIFC.py +++ b/src/Mod/Arch/exportIFC.py @@ -52,8 +52,6 @@ # # This module provides tools to export IFC files. -DEBUG = False # Set to True to see debug messages. Otherwise, totally silent - if open.__module__ in ['__builtin__','io']: pyopen = open # pyopen is use in exporter to open a file in Arch @@ -116,54 +114,38 @@ def getPreferences(): """retrieves IFC preferences""" - global DEBUG, PREFIX_NUMBERS, SKIP, SEPARATE_OPENINGS - global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS - global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES - global FORCE_BREP, IMPORT_PROPERTIES, STORE_UID, SERIALIZE - global SPLIT_LAYERS, EXPORT_2D, FULL_PARAMETRIC, FITVIEW_ONIMPORT - global ADD_DEFAULT_SITE, ADD_DEFAULT_STOREY, ADD_DEFAULT_BUILDING p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") + if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False): import FreeCADGui FreeCADGui.showPreferences("Import-Export",0) - 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) - if MERGE_MODE_ARCH > 0: - SEPARATE_OPENINGS = False - GET_EXTRUSIONS = False - if not SEPARATE_OPENINGS: - SKIP.append("IfcOpeningElement") - CREATE_CLONES = p.GetBool("ifcCreateClones",True) - FORCE_BREP = p.GetBool("ifcExportAsBrep",False) - IMPORT_PROPERTIES = p.GetBool("ifcImportProperties",False) - STORE_UID = p.GetBool("ifcStoreUid",True) - SERIALIZE = p.GetBool("ifcSerialize",False) - SPLIT_LAYERS = p.GetBool("ifcSplitLayers",False) - EXPORT_2D = p.GetBool("ifcExport2D",True) - FULL_PARAMETRIC = p.GetBool("IfcExportFreeCADProperties",False) - FITVIEW_ONIMPORT = p.GetBool("ifcFitViewOnImport",False) - ADD_DEFAULT_SITE = p.GetBool("IfcAddDefaultSite",False) - ADD_DEFAULT_STOREY = p.GetBool("IfcAddDefaultStorey",False) - ADD_DEFAULT_BUILDING = p.GetBool("IfcAddDefaultBuilding",True) + 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",False), + 'ADD_DEFAULT_STOREY': p.GetBool("IfcAddDefaultStorey",False), + 'ADD_DEFAULT_BUILDING': p.GetBool("IfcAddDefaultBuilding",True) + } + + return preferences # ************************************************************************************************ # ********** export IFC **************** -def export(exportList,filename,colors=None): +def export(exportList,filename,colors=None,preferences=None): - """export(exportList,filename,colors=None) -- exports FreeCAD contents to an IFC file. + """export(exportList,filename,colors=None,preferences=None) -- exports FreeCAD contents to an IFC file. colors is an optional dictionary of objName:shapeColorTuple or objName:diffuseColorList elements to be used in non-GUI mode if you want to be able to export colors.""" - getPreferences() + if preferences is None: + preferences = getPreferences() try: global ifcopenshell @@ -189,7 +171,7 @@ def export(exportList,filename,colors=None): schema = ["IFC4", "IFC2X3"][FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("IfcVersion",0)] else: schema = "IFC2X3" - if DEBUG: print("Exporting an",schema,"file...") + if preferences['DEBUG']: print("Exporting an",schema,"file...") template = template.replace("$ifcschema",schema) template = template.replace("$owner",owner) template = template.replace("$company",FreeCAD.ActiveDocument.Company) @@ -224,7 +206,7 @@ def export(exportList,filename,colors=None): objectslist = [obj for obj in objectslist if obj not in annotations] objectslist = Arch.pruneIncluded(objectslist,strict=True) objectslist = [obj for obj in objectslist if Draft.getType(obj) not in ["Dimension","Material","MaterialContainer","WorkingPlaneProxy"]] - if FULL_PARAMETRIC: + if preferences['FULL_PARAMETRIC']: objectslist = Arch.getAllChildren(objectslist) contextCreator = exportIFCHelper.ContextCreator(ifcfile, objectslist) @@ -254,7 +236,7 @@ def export(exportList,filename,colors=None): # build clones table - if CREATE_CLONES: + if preferences['CREATE_CLONES']: for o in objectslist: b = Draft.getCloneBase(o,strict=True) if b: @@ -292,7 +274,7 @@ def export(exportList,filename,colors=None): if not uid: uid = ifcopenshell.guid.new() # storing the uid for further use - if STORE_UID and hasattr(obj,"IfcData"): + if preferences['STORE_UID'] and hasattr(obj,"IfcData"): d = obj.IfcData d["IfcUID"] = uid obj.IfcData = d @@ -347,7 +329,7 @@ def export(exportList,filename,colors=None): if len(ifcaxes) > 2: w = ifcaxes[2] if u and v: - if DEBUG: print(str(count).ljust(3)," : ", ifctype, " (",str(len(ifcpols)),"axes ) : ",name) + if preferences['DEBUG']: print(str(count).ljust(3)," : ", ifctype, " (",str(len(ifcpols)),"axes ) : ",name) xvc = ifcbin.createIfcDirection((1.0,0.0,0.0)) zvc = ifcbin.createIfcDirection((0.0,0.0,1.0)) ovc = ifcbin.createIfcCartesianPoint((0.0,0.0,0.0)) @@ -375,12 +357,12 @@ def export(exportList,filename,colors=None): # getting the representation - representation,placement,shapetype = getRepresentation(ifcfile,context,obj,forcebrep=(brepflag or FORCE_BREP),colors=colors) + representation,placement,shapetype = getRepresentation(ifcfile,context,obj,forcebrep=(brepflag or preferences['FORCE_BREP']),colors=colors,preferences=preferences) if getstd: if isStandardCase(obj,ifctype): ifctype += "StandardCase" - if DEBUG: print(str(count).ljust(3)," : ", ifctype, " (",shapetype,") : ",name) + if preferences['DEBUG']: print(str(count).ljust(3)," : ", ifctype, " (",shapetype,") : ",name) # setting the arguments @@ -417,8 +399,8 @@ def export(exportList,filename,colors=None): if hasattr(obj,"Additions") and (shapetype in ["extrusion","no shape"]): for o in obj.Additions: - r2,p2,c2 = getRepresentation(ifcfile,context,o,colors=colors) - if DEBUG: print(" adding ",c2," : ",o.Label) + r2,p2,c2 = getRepresentation(ifcfile,context,o,colors=colors,preferences=preferences) + if preferences['DEBUG']: print(" adding ",c2," : ",o.Label) l = o.Label if six.PY2: l = l.encode("utf8") @@ -454,8 +436,8 @@ def export(exportList,filename,colors=None): guests.append(o) if hasattr(obj,"Subtractions") and (shapetype in ["extrusion","no shape"]): for o in obj.Subtractions + guests: - r2,p2,c2 = getRepresentation(ifcfile,context,o,subtraction=True,colors=colors) - if DEBUG: print(" subtracting ",c2," : ",o.Label) + r2,p2,c2 = getRepresentation(ifcfile,context,o,subtraction=True,colors=colors,preferences=preferences) + if preferences['DEBUG']: print(" subtracting ",c2," : ",o.Label) l = o.Label if six.PY2: l = l.encode("utf8") @@ -494,7 +476,7 @@ def export(exportList,filename,colors=None): psets = {} for key,value in obj.IfcProperties.items(): - pset, pname, ptype, pvalue = getPropertyData(key,value) + pset, pname, ptype, pvalue = getPropertyData(key,value,preferences) p = ifcbin.createIfcPropertySingleValue(str(pname),str(ptype),pvalue) psets.setdefault(pset,[]).append(p) for pname,props in psets.items(): @@ -565,7 +547,7 @@ def export(exportList,filename,colors=None): for cat in propertiesDic: props = [] for prop in propertiesDic[cat]: - if DEBUG: + if preferences['DEBUG']: print("key",prop["key"],type(prop["key"])) print("tp",prop["tp"],type(prop["tp"])) print("val",prop["val"],type(prop["val"])) @@ -593,7 +575,7 @@ def export(exportList,filename,colors=None): if obj.IfcData: ifcprop = True - #if DEBUG : print(" adding ifc attributes") + #if preferences['DEBUG'] : print(" adding ifc attributes") props = [] for key in obj.IfcData: if not (key in ["attributes", "complex_attributes", "IfcUID", "FlagForceBrep"]): @@ -609,7 +591,7 @@ def export(exportList,filename,colors=None): val = "(".join(r[1:]) val = val.strip("'") val = val.strip('"') - #if DEBUG: print(" property ",key," : ",val.encode("utf8"), " (", str(tp), ")") + #if preferences['DEBUG']: print(" property ",key," : ",val.encode("utf8"), " (", str(tp), ")") if tp in ["IfcLabel","IfcText","IfcIdentifier",'IfcDescriptiveMeasure']: if six.PY2: val = val.encode("utf8") @@ -641,7 +623,7 @@ def export(exportList,filename,colors=None): ) if not ifcprop: - #if DEBUG : print("no ifc properties to export") + #if preferences['DEBUG'] : print("no ifc properties to export") pass # Quantities @@ -676,7 +658,7 @@ def export(exportList,filename,colors=None): [product],eltq ) - if FULL_PARAMETRIC: + if preferences['FULL_PARAMETRIC']: # exporting all the object properties @@ -737,7 +719,7 @@ def export(exportList,filename,colors=None): itype = "IfcText" ivalue = "FreeCADLink_" + t.Name else: - if DEBUG: print("Unable to encode property ",prop," of type ",ptype) + if preferences['DEBUG']: print("Unable to encode property ",prop," of type ",ptype) if itype: # TODO add description if realm == "Gui": @@ -870,7 +852,7 @@ def export(exportList,filename,colors=None): childfloors ) buildings.append(b) - if not defaulthost and not ADD_DEFAULT_STOREY: + if not defaulthost and not preferences['ADD_DEFAULT_STOREY']: defaulthost = b # sites @@ -892,8 +874,8 @@ def export(exportList,filename,colors=None): # add default site, building and storey as required if not sites: - if ADD_DEFAULT_SITE: - if DEBUG: print("No site found. Adding default site") + if preferences['ADD_DEFAULT_SITE']: + if preferences['DEBUG']: print("No site found. Adding default site") sites = [ifcfile.createIfcSite( ifcopenshell.guid.new(), history,"Default Site", @@ -918,8 +900,8 @@ def export(exportList,filename,colors=None): project,sites ) if not buildings: - if ADD_DEFAULT_BUILDING: - if DEBUG: print("No building found. Adding default building") + if preferences['ADD_DEFAULT_BUILDING']: + if preferences['DEBUG']: print("No building found. Adding default building") buildings = [ifcfile.createIfcBuilding( ifcopenshell.guid.new(), history, @@ -973,7 +955,7 @@ def export(exportList,filename,colors=None): untreated.append(v) if untreated: if not defaulthost: - if ADD_DEFAULT_STOREY: + if preferences['ADD_DEFAULT_STOREY']: defaulthost = ifcfile.createIfcBuildingStorey( ifcopenshell.guid.new(), history, @@ -986,9 +968,10 @@ def export(exportList,filename,colors=None): "ELEMENT", None ) - # if ADD_DEFAULT_STOREY is on, we need a building to host it, regardless of ADD_DEFAULT_BUILDING + # if preferences['ADD_DEFAULT_STOREY'] is on, we need a building + # to host it, regardless of preferences['ADD_DEFAULT_BUILDING'] if not buildings: - if DEBUG: print("No building found. Adding default building") + if preferences['DEBUG']: print("No building found. Adding default building") buildings = [ifcfile.createIfcBuilding( ifcopenshell.guid.new(), history, @@ -1041,7 +1024,7 @@ def export(exportList,filename,colors=None): ) else: # no default host: aggregate unassigned objects directly under the IfcProject - WARNING: NON STANDARD - if DEBUG: print("WARNING - Default building generation is disabled. You are producing a non-standard file.") + if preferences['DEBUG']: print("WARNING - Default building generation is disabled. You are producing a non-standard file.") ifcfile.createIfcRelAggregates( ifcopenshell.guid.new(), history, @@ -1098,9 +1081,9 @@ def export(exportList,filename,colors=None): # 2D objects annos = {} - if EXPORT_2D: + if preferences['EXPORT_2D']: curvestyles = {} - if annotations and DEBUG: print("exporting 2D objects...") + if annotations and preferences['DEBUG']: print("exporting 2D objects...") for anno in annotations: xvc = ifcbin.createIfcDirection((1.0,0.0,0.0)) zvc = ifcbin.createIfcDirection((0.0,0.0,1.0)) @@ -1253,7 +1236,7 @@ def export(exportList,filename,colors=None): remaining = [anno for anno in annos.values() if anno not in swallowed] if remaining: if not defaulthost: - if ADD_DEFAULT_STOREY: + if preferences['ADD_DEFAULT_STOREY']: defaulthost = ifcfile.createIfcBuildingStorey( ifcopenshell.guid.new(), history, @@ -1266,7 +1249,9 @@ def export(exportList,filename,colors=None): "ELEMENT", None ) - # if ADD_DEFAULT_STOREY is on, we need a building to host it, regardless of ADD_DEFAULT_BUILDING + # if preferences['ADD_DEFAULT_STOREY'] is on, we need a + # building to host it, regardless of + # preferences['ADD_DEFAULT_BUILDING'] if not buildings: buildings = [ifcfile.createIfcBuilding( ifcopenshell.guid.new(), @@ -1307,7 +1292,7 @@ def export(exportList,filename,colors=None): buildings[0], [defaulthost] ) - elif ADD_DEFAULT_BUILDING: + elif preferences['ADD_DEFAULT_BUILDING']: if not buildings: defaulthost = ifcfile.createIfcBuilding( ifcopenshell.guid.new(), @@ -1360,19 +1345,19 @@ def export(exportList,filename,colors=None): remaining ) - if DEBUG: print("writing ",filename,"...") + if preferences['DEBUG']: print("writing ",filename,"...") filename = decode(filename) ifcfile.write(filename) - if STORE_UID: + if preferences['STORE_UID']: # some properties might have been changed FreeCAD.ActiveDocument.recompute() os.remove(templatefile) - if DEBUG and ifcbin.compress: + if preferences['DEBUG'] and ifcbin.compress: f = pyopen(filename,"r") s = len(f.read().split("\n")) f.close() @@ -1383,7 +1368,7 @@ def export(exportList,filename,colors=None): # ************************************************************************************************ # ********** helper for export IFC ************** -def getPropertyData(key,value): +def getPropertyData(key,value,preferences): # in 0.18, properties in IfcProperties dict are stored as "key":"pset;;type;;value" or "key":"type;;value" # in 0.19, key = name;;pset, value = ptype;;value (because there can be several props with same name) @@ -1404,10 +1389,10 @@ def getPropertyData(key,value): ptype = value[0] pvalue = value[1] else: - if DEBUG:print(" unable to export property:",pname,value) + if preferences['DEBUG']:print(" unable to export property:",pname,value) return pset, pname, ptype, None - #if DEBUG: print(" property ",pname," : ",pvalue.encode("utf8"), " (", str(ptype), ") in ",pset) + #if preferences['DEBUG']: print(" property ",pname," : ",pvalue.encode("utf8"), " (", str(ptype), ") in ",pset) if ptype in ["IfcLabel","IfcText","IfcIdentifier",'IfcDescriptiveMeasure']: if six.PY2: pvalue = pvalue.encode("utf8") @@ -1432,7 +1417,7 @@ def getPropertyData(key,value): except: if six.PY2: pvalue = pvalue.encode("utf8") - if DEBUG:print(" warning: unable to export property as numeric value:",pname,pvalue) + if preferences['DEBUG']:print(" warning: unable to export property as numeric value:",pname,pvalue) # print('pset: {}, pname: {}, ptype: {}, pvalue: {}'.format(pset, pname, ptype, pvalue)) return pset, pname, ptype, pvalue @@ -1700,7 +1685,7 @@ def getProfile(ifcfile,p): return profile -def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1,colors=None): +def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1,colors=None,preferences=None): """returns an IfcShapeRepresentation object or None""" @@ -1857,7 +1842,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess from ifcopenshell import geom serialized = False - if hasattr(geom,"serialise") and obj.isDerivedFrom("Part::Feature") and SERIALIZE: + if hasattr(geom,"serialise") and obj.isDerivedFrom("Part::Feature") and preferences['SERIALIZE']: if obj.Shape.Faces: sh = obj.Shape.copy() sh.Placement = obj.getGlobalPlacement() @@ -1890,7 +1875,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess dataset = fcshape.Solids else: dataset = fcshape.Shells - #if DEBUG: print("Warning! object contains no solids") + #if preferences['DEBUG']: print("Warning! object contains no solids") for fcsolid in dataset: fcsolid.scale(0.001) # to meters diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index eea34da79fde..90d91cf87d00 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -192,7 +192,7 @@ def open(filename,skip=[],only=[],root=None): def insert(filename,docname,skip=[],only=[],root=None,preferences=None): - """insert(filename,docname,skip=[],only=[],root=None): imports the contents of an IFC file. + """insert(filename,docname,skip=[],only=[],root=None,preferences=None): imports the contents of an IFC file. skip can contain a list of ids of objects to be skipped, only can restrict the import to certain object ids (will also get their children) and root can be used to import only the derivates of a certain element type (default = ifcProduct).""" From 92895f7940073232a781973701aa6a3b2dd08665 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 26 Aug 2019 14:01:15 -0300 Subject: [PATCH 6/8] Draft: Fixed regression in snapping --- src/Mod/Draft/DraftSnap.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 5445521bc892..d31a14d5cc32 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -324,9 +324,14 @@ def snapToObject(self, lastpoint, active, constrain, eline, point, oldActive): if (not self.maxEdges) or (len(shape.Edges) <= self.maxEdges): if "Edge" in comp: # we are snapping to an edge - en = int(comp[4:])-1 - if len(shape.Edges) > en: - edge = shape.Edges[en] + edge = None + if shape.ShapeType == "Edge": + edge = shape + else: + en = int(comp[4:])-1 + if len(shape.Edges) > en: + edge = shape.Edges[en] + if edge: snaps.extend(self.snapToEndpoints(edge)) snaps.extend(self.snapToMidpoint(edge)) snaps.extend(self.snapToPerpendicular(edge,lastpoint)) From e9cbbb38fffad76987a5021ee1da1674eb0bcff5 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 26 Aug 2019 14:16:19 -0300 Subject: [PATCH 7/8] Draft: Fixed tooltips --- src/Mod/Draft/DraftGui.py | 3 +++ src/Mod/Draft/DraftTools.py | 22 ++++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 03d72e23f2d7..fb2c42deb6e8 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -1144,6 +1144,7 @@ def offsetUi(self): self.isCopy.setChecked(p.GetBool("OffsetCopyMode",False)) self.occOffset.show() self.labelRadius.setText(translate("draft","Distance")) + self.radiusValue.setToolTip(translate("draft", "Offset distance")) self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) todo.delay(self.radiusValue.setFocus,None) self.radiusValue.selectAll() @@ -1214,6 +1215,7 @@ def trimUi(self,title=translate("draft","Trim")): self.taskUi(title) self.radiusUi() self.labelRadius.setText(translate("draft","Distance")) + self.radiusValue.setToolTip(translate("draft", "Trim distance")) self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) todo.delay(self.radiusValue.setFocus,None) self.radiusValue.selectAll() @@ -1221,6 +1223,7 @@ def trimUi(self,title=translate("draft","Trim")): def radiusUi(self): self.hideXYZ() self.labelRadius.setText(translate("draft", "Radius")) + self.radiusValue.setToolTip(translate("draft", "Radius of Circle")) self.labelRadius.show() self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) self.radiusValue.show() diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 831b51f9662f..7755ae9d620a 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1532,14 +1532,16 @@ def action(self,arg): if self.closedCircle: self.drawArc() else: - self.ui.labelRadius.setText("Start angle") + self.ui.labelRadius.setText(translate("draft","Start angle")) + self.ui.radiusValue.setToolTip(translate("draft","Start angle")) self.ui.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Angle).UserString) self.linetrack.p1(self.center) self.linetrack.on() self.step = 2 FreeCAD.Console.PrintMessage(translate("draft", "Pick start angle")+"\n") elif (self.step == 2): # choose first angle - self.ui.labelRadius.setText("Aperture") + self.ui.labelRadius.setText(translate("draft","Aperture angle")) + self.ui.radiusValue.setToolTip(translate("draft","Aperture angle")) self.step = 3 # scale center->point vector for proper display # u = DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad) obsolete? @@ -1649,14 +1651,16 @@ def numericRadius(self,rad): else: self.step = 2 self.arctrack.setCenter(self.center) - self.ui.labelRadius.setText(translate("draft", "Start Angle")) + self.ui.labelRadius.setText(translate("draft", "Start angle")) + self.ui.radiusValue.setToolTip(translate("draft", "Start angle")) self.linetrack.p1(self.center) self.linetrack.on() self.ui.radiusValue.setText("") self.ui.radiusValue.setFocus() FreeCAD.Console.PrintMessage(translate("draft", "Pick start angle")+"\n") elif (self.step == 2): - self.ui.labelRadius.setText(translate("draft", "Aperture")) + self.ui.labelRadius.setText(translate("draft", "Aperture angle")) + self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) self.firstangle = math.radians(rad) if DraftVecUtils.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) else: u = DraftVecUtils.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) @@ -2892,6 +2896,7 @@ def set_center(self): self.ui.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Angle).UserString) self.ui.hasFill.hide() self.ui.labelRadius.setText(translate("draft","Base angle")) + self.ui.radiusValue.setToolTip(translate("draft","The base angle you wish to start the rotation from")) self.arctrack.setCenter(self.center) for ghost in self.ghosts: ghost.center(self.center) @@ -2902,6 +2907,7 @@ def set_center(self): def set_start_point(self): self.ui.labelRadius.setText(translate("draft","Rotation")) + self.ui.radiusValue.setToolTip(translate("draft", "The amount of rotation you wish to perform. The final angle will be the base angle plus this amount.")) self.rad = DraftVecUtils.dist(self.point,self.center) self.arctrack.on() self.arctrack.setStartPoint(self.point) @@ -3029,6 +3035,7 @@ def numericInput(self,numx,numy,numz): self.ui.radiusUi() self.ui.hasFill.hide() self.ui.labelRadius.setText(translate("draft","Base angle")) + self.ui.radiusValue.setToolTip(translate("draft","The base angle you wish to start the rotation from")) self.step = 1 FreeCAD.Console.PrintMessage(translate("draft", "Pick base angle")+"\n") @@ -3036,6 +3043,7 @@ def numericRadius(self,rad): """this function gets called by the toolbar when valid radius have been entered there""" if (self.step == 1): self.ui.labelRadius.setText(translate("draft","Rotation")) + self.ui.radiusValue.setToolTip(translate("draft","The amount of rotation you wish to perform. The final angle will be the base angle plus this amount.")) self.firstangle = math.radians(rad) self.arctrack.setStartAngle(self.firstangle) self.arctrack.on() @@ -3904,7 +3912,8 @@ def redraw(self,point,snapped=None,shift=False,alt=False,real=None): dist = v1.sub(self.newpoint).Length ghost.p1(self.newpoint) ghost.p2(v2) - self.ui.labelRadius.setText("Distance") + self.ui.labelRadius.setText(translate("draft","Distance")) + self.ui.radiusValue.setToolTip(translate("draft", "The offset distance")) if real: if self.force: ray = self.newpoint.sub(v1) @@ -3917,7 +3926,8 @@ def redraw(self,point,snapped=None,shift=False,alt=False,real=None): ang1 = DraftVecUtils.angle(v2.sub(center)) ang2 = DraftVecUtils.angle(point.sub(center)) self.newpoint=Vector.add(center,DraftVecUtils.rotate(Vector(rad,0,0),-ang2)) - self.ui.labelRadius.setText("Angle") + self.ui.labelRadius.setText(translate("draft","Angle")) + self.ui.radiusValue.setToolTip(translate("draft", "The offset angle")) dist = math.degrees(-ang2) # if ang1 > ang2: ang1,ang2 = ang2,ang1 #print("last calculated:",math.degrees(-ang1),math.degrees(-ang2)) From 3dac114f9fe8b55b1e41b429e72ee6dbe6925116 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 26 Aug 2019 15:39:22 -0300 Subject: [PATCH 8/8] Arch: Solved bug in Structure --- src/Mod/Arch/ArchIFC.py | 5 +++-- src/Mod/Arch/ArchStructure.py | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchIFC.py b/src/Mod/Arch/ArchIFC.py index d5b2616dded5..87c6737a40ab 100644 --- a/src/Mod/Arch/ArchIFC.py +++ b/src/Mod/Arch/ArchIFC.py @@ -30,8 +30,9 @@ def onChanged(self, obj, prop): if prop == "IfcType": self.setupIfcAttributes(obj) self.setupIfcComplexAttributes(obj) - if obj.getGroupOfProperty(prop) == "IFC Attributes": - self.setObjIfcAttributeValue(obj, prop, obj.getPropertyByName(prop)) + if prop in obj.PropertiesList: + if obj.getGroupOfProperty(prop) == "IFC Attributes": + self.setObjIfcAttributeValue(obj, prop, obj.getPropertyByName(prop)) def setupIfcAttributes(self, obj): ifcTypeSchema = self.getIfcTypeSchema(obj.IfcType) diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 051993977fff..b18c787005a4 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -947,12 +947,12 @@ def updateData(self,obj,prop): p.append([n.x,n.y,n.z]) self.coords.point.setValues(0,len(p),p) self.pointset.numPoints.setValue(len(p)) - self.lineset.coordIndex.setValues(0,len(p)+1,range(len(p))+[-1]) + self.lineset.coordIndex.setValues(0,len(p)+1,list(range(len(p)))+[-1]) if hasattr(obj.ViewObject,"NodeType"): if (obj.ViewObject.NodeType == "Area") and (len(p) > 2): self.coords.point.set1Value(len(p),p[0][0],p[0][1],p[0][2]) - self.lineset.coordIndex.setValues(0,len(p)+2,range(len(p)+1)+[-1]) - self.faceset.coordIndex.setValues(0,len(p)+1,range(len(p))+[-1]) + self.lineset.coordIndex.setValues(0,len(p)+2,list(range(len(p)+1))+[-1]) + self.faceset.coordIndex.setValues(0,len(p)+1,list(range(len(p)))+[-1]) elif prop in ["IfcType"]: if hasattr(obj.ViewObject,"NodeType"):