From f3631c8ff1ff7fbc65ea7e9fb07e245b67fd266f Mon Sep 17 00:00:00 2001 From: luz paz Date: Tue, 26 Oct 2021 07:51:06 -0400 Subject: [PATCH 01/68] PD: Expose missing commands to translation in Measure dropdown menu Fixes https://github.com/FreeCAD/FreeCAD-translations/issues/6 --- src/Mod/PartDesign/Gui/Workbench.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index 94cd370dc7..4ae7939dda 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -65,6 +65,8 @@ namespace bp = boost::placeholders; qApp->translate("Gui::TaskView::TaskWatcherCommands", "Create Geometry"); // qApp->translate("Workbench", "Measure"); + qApp->translate("Workbench", "Refresh"); + qApp->translate("Workbench", "Toggle 3D"); qApp->translate("Workbench", "Part Design Helper"); qApp->translate("Workbench", "Part Design Modeling"); #endif From 8b7718f8231f60c24f06d6178fc2b4a615e13375 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Wed, 27 Oct 2021 08:32:10 +0200 Subject: [PATCH 02/68] Draft: Fix merge layers The "Merge layer duplicates" Tree view context menu option for LayerContainers did not work. Additionally: - Using `openTransaction` and `commitTransaction` is required for the `merge_by_name` function but also for the `add_layer` function. Otherwise undo-redo does not work properly. - Have replaced `translate("Draft", ...)` with `_tr(...)`. --- .../Draft/draftviewproviders/view_layer.py | 103 +++++++++--------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/src/Mod/Draft/draftviewproviders/view_layer.py b/src/Mod/Draft/draftviewproviders/view_layer.py index b7231ae1f1..1f88700105 100644 --- a/src/Mod/Draft/draftviewproviders/view_layer.py +++ b/src/Mod/Draft/draftviewproviders/view_layer.py @@ -1,6 +1,7 @@ # *************************************************************************** # * Copyright (c) 2014 Yorik van Havre * # * Copyright (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2021 FreeCAD Developers * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -37,7 +38,7 @@ import FreeCAD as App import FreeCADGui as Gui from draftutils.messages import _msg -from draftutils.translate import translate +from draftutils.translate import _tr from draftobjects.layer import Layer @@ -355,13 +356,13 @@ class ViewProviderLayer: def setupContextMenu(self, vobj, menu): """Set up actions to perform in the context menu.""" action1 = QtGui.QAction(QtGui.QIcon(":/icons/button_right.svg"), - translate("draft", "Activate this layer"), + _tr("Activate this layer"), menu) action1.triggered.connect(self.activate) menu.addAction(action1) action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectGroup.svg"), - translate("draft", "Select layer contents"), + _tr("Select layer contents"), menu) action2.triggered.connect(self.select_contents) menu.addAction(action2) @@ -399,80 +400,76 @@ class ViewProviderLayerContainer: def setupContextMenu(self, vobj, menu): """Set up actions to perform in the context menu.""" action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Layer.svg"), - translate("Draft", "Merge layer duplicates"), + _tr("Merge layer duplicates"), menu) action1.triggered.connect(self.merge_by_name) menu.addAction(action1) action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_NewLayer.svg"), - translate("Draft", "Add new layer"), + _tr("Add new layer"), menu) action2.triggered.connect(self.add_layer) menu.addAction(action2) def merge_by_name(self): - """Merge the layers that have the same name.""" + """Merge the layers that have the same base label.""" if not hasattr(self, "Object") or not hasattr(self.Object, "Group"): return - obj = self.Object + doc = App.ActiveDocument + doc.openTransaction(_tr("Merge layer duplicates")) - layers = list() - for iobj in obj.Group: - if hasattr(iobj, "Proxy") and isinstance(iobj.Proxy, Layer): - layers.append(iobj) + layer_container = self.Object + layers = [] + for obj in layer_container.Group: + if hasattr(obj, "Proxy") and isinstance(obj.Proxy, Layer): + layers.append(obj) - to_delete = list() + to_delete = [] for layer in layers: - # Test the last three characters of the layer's Label to see - # if it's a number, like `'Layer017'` - if (layer.Label[-1].isdigit() - and layer.Label[-2].isdigit() - and layer.Label[-3].isdigit()): - # If the object inside the layer has the same Label - # as the layer, save this object - orig = None - for ol in layer.OutList: - if ol.Label == layer.Label[:-3].strip(): - orig = ol - break + # Remove trailing digits (usually 3 but there might be more) and + # trailing spaces from Label before comparing: + base_label = layer.Label.rstrip("0123456789 ") - # Go into the objects that reference this layer object - # and set the layer property with the previous `orig` - # object found - # Editor: when is this possible? Maybe if a layer is inside - # another layer? Currently the code doesn't allow this - # so maybe this was a previous behavior that was disabled - # in `ViewProviderLayer`. - if orig: - for par in layer.InList: - for prop in par.PropertiesList: - if getattr(par, prop) == layer: - _msg("Changed property '" + prop - + "' of object " + par.Label - + " from " + layer.Label - + " to " + orig.Label) - setattr(par, prop, orig) - to_delete.append(layer) + # Try to find the `'base'` layer: + base = None + for other_layer in layers: + if ((not other_layer in to_delete) # Required if there are duplicate labels. + and other_layer != layer + and other_layer.Label.upper() == base_label.upper()): + base = other_layer + break + + if base: + if layer.Group: + base_group = base.Group + for obj in layer.Group: + if not obj in base_group: + base_group.append(obj) + base.Group = base_group + to_delete.append(layer) + elif layer.Label != base_label: + _msg(_tr("Relabeling layer:") + + " '{}' -> '{}'".format(layer.Label, base_label)) + layer.Label = base_label for layer in to_delete: - if not layer.InList: - _msg("Merging duplicate layer: " + layer.Label) - App.ActiveDocument.removeObject(layer.Name) - elif len(layer.InList) == 1: - first = layer.InList[0] + _msg(_tr("Merging layer:") + " '{}'".format(layer.Label)) + doc.removeObject(layer.Name) - if first.isDerivedFrom("App::DocumentObjectGroup"): - _msg("Merging duplicate layer: " + layer.Label) - App.ActiveDocument.removeObject(layer.Name) - else: - _msg("InList not empty. " - "Unable to delete layer: " + layer.Label) + doc.recompute() + doc.commitTransaction() def add_layer(self): """Creates a new layer""" import Draft + + doc = App.ActiveDocument + doc.openTransaction(_tr("Add new layer")) + Draft.make_layer() - App.ActiveDocument.recompute() + + doc.recompute() + doc.commitTransaction() def __getstate__(self): """Return a tuple of objects to save or None.""" From a624f6a50c873648ff0d653a21ba67417fd77253 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 28 Oct 2021 19:29:59 +0200 Subject: [PATCH 03/68] Draft: Fix angle dimension issue If the end points of the selected edges for an angular dimension were (almost) coincident with their intersection, random angles could be calculated. In essence a floating point inaccuracy issue. --- src/Mod/Draft/draftguitools/gui_dimensions.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_dimensions.py b/src/Mod/Draft/draftguitools/gui_dimensions.py index 45f12e8991..d091568ea8 100644 --- a/src/Mod/Draft/draftguitools/gui_dimensions.py +++ b/src/Mod/Draft/draftguitools/gui_dimensions.py @@ -106,7 +106,7 @@ class Dimension(gui_base_original.Creator): self.arctrack = trackers.arcTracker() self.link = None self.edges = [] - self.pts = [] + self.angles = [] self.angledata = None self.indices = [] self.center = None @@ -397,7 +397,7 @@ class Dimension(gui_base_original.Creator): r = self.point.sub(self.center) self.arctrack.setRadius(r.Length) a = self.arctrack.getAngle(self.point) - pair = DraftGeomUtils.getBoundaryAngles(a, self.pts) + pair = DraftGeomUtils.getBoundaryAngles(a, self.angles) if not (pair[0] < a < pair[1]): self.angledata = [4 * math.pi - pair[0], 2 * math.pi - pair[1]] @@ -504,8 +504,15 @@ class Dimension(gui_base_original.Creator): self.arctrack.setCenter(self.center) self.arctrack.on() for e in self.edges: - for v in e.Vertexes: - self.pts.append(self.arctrack.getAngle(v.Point)) + if e.Length < 0.00003: # Edge must be long enough for the tolerance of 0.00001mm to make sense. + _msg(translate("draft", "Edge too short!")) + self.finish() + return + for i in [0, 1]: + pt = e.Vertexes[i].Point + if pt.isEqual(self.center, 0.00001): # A relatively high tolerance is required. + pt = e.Vertexes[i - 1].Point # Use the other point instead. + self.angles.append(self.arctrack.getAngle(pt)) self.link = [self.link[0], ob] else: _msg(translate("draft", "Edges don't intersect!")) From 7a35afdd8ec2d8d12f2eee3d2ac1e6aad03e6cfa Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 29 Oct 2021 15:59:55 +0200 Subject: [PATCH 04/68] Gui: add class RotationHelper to reduce code duplication of PropertyRotationItem and PropertyPlacementItem --- src/Gui/propertyeditor/PropertyItem.cpp | 240 ++++++++++++++---------- src/Gui/propertyeditor/PropertyItem.h | 33 +++- 2 files changed, 168 insertions(+), 105 deletions(-) diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 519816fcab..d3e9cd8076 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -2094,13 +2094,110 @@ void PropertyMatrixItem::setA44(double A44) // --------------------------------------------------------------- -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyRotationItem) - -PropertyRotationItem::PropertyRotationItem() +RotationHelper::RotationHelper() : init_axis(false) , changed_value(false) , rot_angle(0) , rot_axis(0,0,1) +{ +} + +void RotationHelper::setChanged(bool value) +{ + changed_value = value; +} + +bool RotationHelper::hasChangedAndReset() +{ + if (!changed_value) + return false; + + changed_value = false; + return true; +} + +bool RotationHelper::isAxisInitialized() const +{ + return init_axis; +} + +void RotationHelper::setValue(const Base::Vector3d& axis, double angle) +{ + rot_axis = axis; + rot_angle = angle; + init_axis = true; +} + +void RotationHelper::getValue(Base::Vector3d& axis, double& angle) const +{ + axis = rot_axis; + angle = rot_angle; +} + +double RotationHelper::getAngle(const Base::Rotation& val) const +{ + double angle; + Base::Vector3d dir; + val.getRawValue(dir, angle); + if (dir * this->rot_axis < 0.0) + angle = -angle; + return angle; +} + +Base::Rotation RotationHelper::setAngle(double angle) +{ + Base::Rotation rot; + rot.setValue(this->rot_axis, Base::toRadians(angle)); + changed_value = true; + rot_angle = angle; + return rot; +} + +Base::Vector3d RotationHelper::getAxis() const +{ + // We must store the rotation axis in a member because + // if we read the value from the property we would always + // get a normalized vector which makes it quite unhandy + // to work with + return this->rot_axis; +} + +Base::Rotation RotationHelper::setAxis(const Base::Rotation& value, const Base::Vector3d& axis) +{ + this->rot_axis = axis; + Base::Rotation rot = value; + Base::Vector3d dummy; double angle; + rot.getValue(dummy, angle); + if (dummy * axis < 0.0) + angle = -angle; + rot.setValue(axis, angle); + changed_value = true; + return rot; +} + +void RotationHelper::assignProperty(const Base::Rotation& value, double eps) +{ + double angle; + Base::Vector3d dir; + value.getRawValue(dir, angle); + Base::Vector3d cross = this->rot_axis.Cross(dir); + double len2 = cross.Sqr(); + if (angle != 0) { + // vectors are not parallel + if (len2 > eps) + this->rot_axis = dir; + // vectors point into opposite directions + else if (this->rot_axis.Dot(dir) < 0) + this->rot_axis = -this->rot_axis; + } + this->rot_angle = Base::toDegrees(angle); +} + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyRotationItem) + +PropertyRotationItem::PropertyRotationItem() { m_a = static_cast(PropertyUnitItem::create()); m_a->setParent(this); @@ -2122,12 +2219,9 @@ Base::Quantity PropertyRotationItem::getAngle() const QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return Base::Quantity(0.0); + const Base::Rotation& val = value.value(); - double angle; - Base::Vector3d dir; - val.getRawValue(dir, angle); - if (dir * this->rot_axis < 0.0) - angle = -angle; + double angle = h.getAngle(val); return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); } @@ -2137,20 +2231,13 @@ void PropertyRotationItem::setAngle(Base::Quantity angle) if (!value.canConvert()) return; - Base::Rotation rot; - rot.setValue(this->rot_axis, Base::toRadians(angle.getValue())); - changed_value = true; - rot_angle = angle.getValue(); + Base::Rotation rot = h.setAngle(angle.getValue()); setValue(QVariant::fromValue(rot)); } Base::Vector3d PropertyRotationItem::getAxis() const { - // We must store the rotation axis in a member because - // if we read the value from the property we would always - // get a normalized vector which makes it quite unhandy - // to work with - return this->rot_axis; + return h.getAxis(); } void PropertyRotationItem::setAxis(const Base::Vector3d& axis) @@ -2158,14 +2245,9 @@ void PropertyRotationItem::setAxis(const Base::Vector3d& axis) QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; - this->rot_axis = axis; + Base::Rotation rot = value.value(); - Base::Vector3d dummy; double angle; - rot.getValue(dummy, angle); - if (dummy * axis < 0.0) - angle = -angle; - rot.setValue(axis, angle); - changed_value = true; + rot = h.setAxis(rot, axis); setValue(QVariant::fromValue(rot)); } @@ -2176,20 +2258,7 @@ void PropertyRotationItem::assignProperty(const App::Property* prop) double eps = std::pow(10.0, -2*(decimals()+1)); if (prop->getTypeId().isDerivedFrom(App::PropertyRotation::getClassTypeId())) { const Base::Rotation& value = static_cast(prop)->getValue(); - double angle; - Base::Vector3d dir; - value.getRawValue(dir, angle); - Base::Vector3d cross = this->rot_axis.Cross(dir); - double len2 = cross.Sqr(); - if (angle != 0) { - // vectors are not parallel - if (len2 > eps) - this->rot_axis = dir; - // vectors point into opposite directions - else if (this->rot_axis.Dot(dir) < 0) - this->rot_axis = -this->rot_axis; - } - this->rot_angle = Base::toDegrees(angle); + h.assignProperty(value, eps); } } @@ -2201,13 +2270,13 @@ QVariant PropertyRotationItem::value(const App::Property* prop) const double angle; Base::Vector3d dir; value.getRawValue(dir, angle); - if (!init_axis) { + if (!h.isAxisInitialized()) { if (m_a->hasExpression()) { QString str = m_a->expressionAsString(); - const_cast(this)->rot_angle = str.toDouble(); + angle = str.toDouble(); } else { - const_cast(this)->rot_angle = Base::toDegrees(angle); + angle = Base::toDegrees(angle); } PropertyItem* x = m_d->child(0); @@ -2225,8 +2294,7 @@ QVariant PropertyRotationItem::value(const App::Property* prop) const QString str = z->expressionAsString(); dir.z = str.toDouble(); } - const_cast(this)->rot_axis = dir; - const_cast(this)->init_axis = true; + h.setValue(dir, angle); } return QVariant::fromValue(value); } @@ -2274,16 +2342,18 @@ void PropertyRotationItem::setValue(const QVariant& value) return; // Accept this only if the user changed the axis, angle or position but // not if >this< item loses focus - if (!changed_value) + if (!h.hasChangedAndReset()) return; - changed_value = false; + Base::Vector3d axis; + double angle; + h.getValue(axis, angle); Base::QuantityFormat format(Base::QuantityFormat::Fixed, decimals()); QString data = QString::fromLatin1("App.Rotation(App.Vector(%1,%2,%3),%4)") - .arg(Base::UnitsApi::toNumber(rot_axis.x, format)) - .arg(Base::UnitsApi::toNumber(rot_axis.y, format)) - .arg(Base::UnitsApi::toNumber(rot_axis.z, format)) - .arg(Base::UnitsApi::toNumber(rot_angle, format)); + .arg(Base::UnitsApi::toNumber(axis.x, format)) + .arg(Base::UnitsApi::toNumber(axis.y, format)) + .arg(Base::UnitsApi::toNumber(axis.z, format)) + .arg(Base::UnitsApi::toNumber(angle, format)); setPropertyValue(data); } @@ -2394,7 +2464,7 @@ void PlacementEditor::updateValue(const QVariant& v, bool incr, bool data) PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPlacementItem) -PropertyPlacementItem::PropertyPlacementItem() : init_axis(false), changed_value(false), rot_angle(0), rot_axis(0,0,1) +PropertyPlacementItem::PropertyPlacementItem() { m_a = static_cast(PropertyUnitItem::create()); m_a->setParent(this); @@ -2421,12 +2491,9 @@ Base::Quantity PropertyPlacementItem::getAngle() const QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return Base::Quantity(0.0); + const Base::Placement& val = value.value(); - double angle; - Base::Vector3d dir; - val.getRotation().getRawValue(dir, angle); - if (dir * this->rot_axis < 0.0) - angle = -angle; + double angle = h.getAngle(val.getRotation()); return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); } @@ -2437,21 +2504,14 @@ void PropertyPlacementItem::setAngle(Base::Quantity angle) return; Base::Placement val = value.value(); - Base::Rotation rot; - rot.setValue(this->rot_axis, Base::toRadians(angle.getValue())); + Base::Rotation rot = h.setAngle(angle.getValue()); val.setRotation(rot); - changed_value = true; - rot_angle = angle.getValue(); setValue(QVariant::fromValue(val)); } Base::Vector3d PropertyPlacementItem::getAxis() const { - // We must store the rotation axis in a member because - // if we read the value from the property we would always - // get a normalized vector which makes it quite unhandy - // to work with - return this->rot_axis; + return h.getAxis(); } void PropertyPlacementItem::setAxis(const Base::Vector3d& axis) @@ -2459,16 +2519,11 @@ void PropertyPlacementItem::setAxis(const Base::Vector3d& axis) QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; - this->rot_axis = axis; + Base::Placement val = value.value(); Base::Rotation rot = val.getRotation(); - Base::Vector3d dummy; double angle; - rot.getValue(dummy, angle); - if (dummy * axis < 0.0) - angle = -angle; - rot.setValue(axis, angle); + rot = h.setAxis(rot, axis); val.setRotation(rot); - changed_value = true; setValue(QVariant::fromValue(val)); } @@ -2486,9 +2541,10 @@ void PropertyPlacementItem::setPosition(const Base::Vector3d& pos) QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; + Base::Placement val = value.value(); val.setPosition(pos); - changed_value = true; + h.setChanged(true); setValue(QVariant::fromValue(val)); } @@ -2499,20 +2555,7 @@ void PropertyPlacementItem::assignProperty(const App::Property* prop) double eps = std::pow(10.0, -2*(decimals()+1)); if (prop->getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())) { const Base::Placement& value = static_cast(prop)->getValue(); - double angle; - Base::Vector3d dir; - value.getRotation().getRawValue(dir, angle); - Base::Vector3d cross = this->rot_axis.Cross(dir); - double len2 = cross.Sqr(); - if (angle != 0) { - // vectors are not parallel - if (len2 > eps) - this->rot_axis = dir; - // vectors point into opposite directions - else if (this->rot_axis.Dot(dir) < 0) - this->rot_axis = -this->rot_axis; - } - this->rot_angle = Base::toDegrees(angle); + h.assignProperty(value.getRotation(), eps); } } @@ -2524,13 +2567,13 @@ QVariant PropertyPlacementItem::value(const App::Property* prop) const double angle; Base::Vector3d dir; value.getRotation().getRawValue(dir, angle); - if (!init_axis) { + if (!h.isAxisInitialized()) { if (m_a->hasExpression()) { QString str = m_a->expressionAsString(); - const_cast(this)->rot_angle = str.toDouble(); + angle = str.toDouble(); } else { - const_cast(this)->rot_angle = Base::toDegrees(angle); + angle = Base::toDegrees(angle); } PropertyItem* x = m_d->child(0); @@ -2548,8 +2591,7 @@ QVariant PropertyPlacementItem::value(const App::Property* prop) const QString str = z->expressionAsString(); dir.z = str.toDouble(); } - const_cast(this)->rot_axis = dir; - const_cast(this)->init_axis = true; + h.setValue(dir, angle); } return QVariant::fromValue(value); } @@ -2606,12 +2648,16 @@ void PropertyPlacementItem::setValue(const QVariant& value) return; // Accept this only if the user changed the axis, angle or position but // not if >this< item loses focus - if (!changed_value) + if (!h.hasChangedAndReset()) return; - changed_value = false; + const Base::Placement& val = value.value(); Base::Vector3d pos = val.getPosition(); + Base::Vector3d axis; + double angle; + h.getValue(axis, angle); + Base::QuantityFormat format(Base::QuantityFormat::Fixed, decimals()); QString data = QString::fromLatin1("App.Placement(" "App.Vector(%1,%2,%3)," @@ -2619,10 +2665,10 @@ void PropertyPlacementItem::setValue(const QVariant& value) .arg(Base::UnitsApi::toNumber(pos.x, format)) .arg(Base::UnitsApi::toNumber(pos.y, format)) .arg(Base::UnitsApi::toNumber(pos.z, format)) - .arg(Base::UnitsApi::toNumber(rot_axis.x, format)) - .arg(Base::UnitsApi::toNumber(rot_axis.y, format)) - .arg(Base::UnitsApi::toNumber(rot_axis.z, format)) - .arg(Base::UnitsApi::toNumber(rot_angle, format)); + .arg(Base::UnitsApi::toNumber(axis.x, format)) + .arg(Base::UnitsApi::toNumber(axis.y, format)) + .arg(Base::UnitsApi::toNumber(axis.z, format)) + .arg(Base::UnitsApi::toNumber(angle, format)); setPropertyValue(data); } diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index 20ac165fdb..9483b4d3b6 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef Q_MOC_RUN Q_DECLARE_METATYPE(Base::Vector3f) @@ -657,6 +658,28 @@ private: PropertyFloatItem* m_a44; }; +class RotationHelper +{ +public: + RotationHelper(); + void setChanged(bool); + bool hasChangedAndReset(); + bool isAxisInitialized() const; + void setValue(const Base::Vector3d& axis, double angle); + void getValue(Base::Vector3d& axis, double& angle) const; + double getAngle(const Base::Rotation& val) const; + Base::Rotation setAngle(double); + Base::Vector3d getAxis() const; + Base::Rotation setAxis(const Base::Rotation& value, const Base::Vector3d& axis); + void assignProperty(const Base::Rotation& value, double eps); + +private: + bool init_axis; + bool changed_value; + double rot_angle; + Base::Vector3d rot_axis; +}; + /** * Edit properties of rotation type. * \author Werner Mayer @@ -689,10 +712,7 @@ protected: virtual void setValue(const QVariant&); private: - bool init_axis; - bool changed_value; - double rot_angle; - Base::Vector3d rot_axis; + mutable RotationHelper h; PropertyUnitItem * m_a; PropertyVectorItem* m_d; }; @@ -752,10 +772,7 @@ protected: virtual void setValue(const QVariant&); private: - bool init_axis; - bool changed_value; - double rot_angle; - Base::Vector3d rot_axis; + mutable RotationHelper h; PropertyUnitItem * m_a; PropertyVectorItem* m_d; PropertyVectorDistanceItem* m_p; From 0bd0ec5ed24320d0db16a39be596b5c3fd2a7560 Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Fri, 29 Oct 2021 17:23:48 +0200 Subject: [PATCH 05/68] [PartDesign] Remove useless function overriding Double-click is already handled by PartDesign::ViewProvider::doubleClicked() Overridings in Loft & Pipe brings no specific behavior By removing overridings, behavioral consistency is improved both in ... ... undo commands & body activation management when PartDesign items ... ... are double-clicked --- src/Mod/PartDesign/Gui/ViewProviderLoft.cpp | 5 ----- src/Mod/PartDesign/Gui/ViewProviderLoft.h | 1 - src/Mod/PartDesign/Gui/ViewProviderPipe.cpp | 5 ----- src/Mod/PartDesign/Gui/ViewProviderPipe.h | 1 - 4 files changed, 12 deletions(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp b/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp index 8cbb387b47..6f260f3b78 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp @@ -81,11 +81,6 @@ void ViewProviderLoft::setupContextMenu(QMenu* menu, QObject* receiver, const ch PartDesignGui::ViewProvider::setupContextMenu(menu, receiver, member); } -bool ViewProviderLoft::doubleClicked(void) -{ - return PartDesignGui::setEdit(pcObject); -} - bool ViewProviderLoft::setEdit(int ModNum) { if (ModNum == ViewProvider::Default) diff --git a/src/Mod/PartDesign/Gui/ViewProviderLoft.h b/src/Mod/PartDesign/Gui/ViewProviderLoft.h index dcec346ee3..01f24e76c5 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderLoft.h +++ b/src/Mod/PartDesign/Gui/ViewProviderLoft.h @@ -41,7 +41,6 @@ public: /// grouping handling std::vector claimChildren(void)const; void setupContextMenu(QMenu*, QObject*, const char*); - bool doubleClicked(); virtual bool onDelete(const std::vector &); void highlightReferences(const bool on, bool auxiliary); diff --git a/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp b/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp index 490bddf704..5c875153be 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPipe.cpp @@ -89,11 +89,6 @@ void ViewProviderPipe::setupContextMenu(QMenu* menu, QObject* receiver, const ch PartDesignGui::ViewProvider::setupContextMenu(menu, receiver, member); } -bool ViewProviderPipe::doubleClicked(void) -{ - return PartDesignGui::setEdit(pcObject); -} - bool ViewProviderPipe::setEdit(int ModNum) { if (ModNum == ViewProvider::Default ) setPreviewDisplayMode(true); diff --git a/src/Mod/PartDesign/Gui/ViewProviderPipe.h b/src/Mod/PartDesign/Gui/ViewProviderPipe.h index 7fbf6647ed..e3efe3a695 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPipe.h +++ b/src/Mod/PartDesign/Gui/ViewProviderPipe.h @@ -49,7 +49,6 @@ public: /// grouping handling std::vector claimChildren(void)const; void setupContextMenu(QMenu*, QObject*, const char*); - bool doubleClicked(); virtual bool onDelete(const std::vector &); void highlightReferences(Reference mode, bool on); From 971057539f900aa5592edbe054d2d7719b37fbda Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 29 Oct 2021 20:02:09 +0200 Subject: [PATCH 06/68] Unit test: [skip ci] gimbal lock --- src/Mod/Test/BaseTests.py | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/Mod/Test/BaseTests.py b/src/Mod/Test/BaseTests.py index 61a47a1b44..857e55d41b 100644 --- a/src/Mod/Test/BaseTests.py +++ b/src/Mod/Test/BaseTests.py @@ -244,6 +244,58 @@ class ParameterTestCase(unittest.TestCase): r.invert() self.assertTrue(r.isSame(s)) + # gimbal lock (north pole) + r=FreeCAD.Rotation() + r.setYawPitchRoll(20, 90, 10) + a=r.getYawPitchRoll() + s=FreeCAD.Rotation() + s.setYawPitchRoll(*a) + self.assertAlmostEqual(a[0], 0.0) + self.assertAlmostEqual(a[1], 90.0) + self.assertAlmostEqual(a[2], -10.0) + self.assertTrue(r.isSame(s, 1e-12)) + + # gimbal lock (south pole) + r=FreeCAD.Rotation() + r.setYawPitchRoll(20, -90, 10) + a=r.getYawPitchRoll() + s=FreeCAD.Rotation() + s.setYawPitchRoll(*a) + self.assertAlmostEqual(a[0], 0.0) + self.assertAlmostEqual(a[1], -90.0) + self.assertAlmostEqual(a[2], 30.0) + self.assertTrue(r.isSame(s, 1e-12)) + + def testYawPitchRoll(self): + def getYPR1(yaw, pitch, roll): + r = FreeCAD.Rotation() + r.setYawPitchRoll(yaw, pitch, roll) + return r + def getYPR2(yaw, pitch, roll): + rx = FreeCAD.Rotation() + ry = FreeCAD.Rotation() + rz = FreeCAD.Rotation() + + rx.Axis = FreeCAD.Vector(1,0,0) + ry.Axis = FreeCAD.Vector(0,1,0) + rz.Axis = FreeCAD.Vector(0,0,1) + + rx.Angle = math.radians(roll) + ry.Angle = math.radians(pitch) + rz.Angle = math.radians(yaw) + + return rz.multiply(ry).multiply(rx) + + angles = [] + angles.append((10,10,10)) + angles.append((13,45,-24)) + angles.append((10,-90,20)) + + for i in angles: + r = getYPR1(*i) + s = getYPR2(*i) + self.assertTrue(r.isSame(s, 1e-12)) + def testBounding(self): b=FreeCAD.BoundBox() b.setVoid() From 01d8d26bb4b3c2f8da6717159963a05007149301 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Mon, 2 Aug 2021 11:34:42 +0800 Subject: [PATCH 07/68] Gui: fix document 'modified' status on view property change --- src/Gui/ViewProviderDocumentObject.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Gui/ViewProviderDocumentObject.cpp b/src/Gui/ViewProviderDocumentObject.cpp index 0230117675..ec1e08c199 100644 --- a/src/Gui/ViewProviderDocumentObject.cpp +++ b/src/Gui/ViewProviderDocumentObject.cpp @@ -196,12 +196,19 @@ void ViewProviderDocumentObject::onChanged(const App::Property* prop) // this is undesired behaviour. So, if this change marks the document as // modified then it must be be reversed. if (!testStatus(Gui::ViewStatus::TouchDocument)) { - bool mod = false; - if (pcDocument) - mod = pcDocument->isModified(); + // Note: reverting document modified status like that is not + // appropreiate because we can't tell if there is any other + // property being changed due to the change of Visibility here. + // Temporary setting the Visibility property as 'NoModify' is + // the proper way. + Base::ObjectStatusLocker guard( + App::Property::NoModify, &Visibility); + // bool mod = false; + // if (pcDocument) + // mod = pcDocument->isModified(); getObject()->Visibility.setValue(Visibility.getValue()); - if (pcDocument) - pcDocument->setModified(mod); + // if (pcDocument) + // pcDocument->setModified(mod); } else { getObject()->Visibility.setValue(Visibility.getValue()); @@ -215,7 +222,10 @@ void ViewProviderDocumentObject::onChanged(const App::Property* prop) } } - if (pcDocument && !pcDocument->isModified() && testStatus(Gui::ViewStatus::TouchDocument)) { + if (prop && !prop->testStatus(App::Property::NoModify) + && pcDocument + && !pcDocument->isModified() + && testStatus(Gui::ViewStatus::TouchDocument)) { if (prop) FC_LOG(prop->getFullName() << " changed"); pcDocument->setModified(true); From 414ea71a28f793c4982912a364a3d0b71f8e66f4 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Mon, 2 Aug 2021 11:36:00 +0800 Subject: [PATCH 08/68] Part: fix unnecessary document 'modified' status --- src/Mod/Part/Gui/ViewProviderExt.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index daf355e909..64f92b99e9 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -104,6 +104,7 @@ #include #include #include +#include #include #include @@ -396,6 +397,12 @@ void ViewProviderPartExt::onChanged(const App::Property* prop) // if the object was invisible and has been changed, recreate the visual if (prop == &Visibility && (isUpdateForced() || Visibility.getValue()) && VisualTouched) { updateVisual(); + // updateVisual() may not be triggered by any change (e.g. + // triggered by an external object through forceUpdate()). And + // since DiffuseColor is not changed here either, do not falsly set + // the document modified status + Base::ObjectStatusLocker guard( + App::Property::NoModify, &DiffuseColor); // The material has to be checked again (#0001736) onChanged(&DiffuseColor); } @@ -1292,8 +1299,8 @@ void ViewProviderPartExt::updateVisual() void ViewProviderPartExt::forceUpdate(bool enable) { if(enable) { if(++forceUpdateCount == 1) { - if(!isShow()) - Visibility.touch(); + if(!isShow() && VisualTouched) + updateVisual(); } }else if(forceUpdateCount) --forceUpdateCount; From fc9d3547ad3ae30236cb847acf4ef89aa1216683 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Mon, 2 Aug 2021 11:38:01 +0800 Subject: [PATCH 09/68] App: fix external document loading The problem happens when partial loading is enabled. If document A contains a link to some object in document B, it will load B as partial document with only that object and its necessary dependencies. But if document A contains another link to some object in document C which also has a link to some object in document B, the link in document C may not be restored, because document B is partially loaded without the linked object. This patch will check for this case and reload document B for more objects. See an example reported in https://forum.freecadweb.org/viewtopic.php?p=495078#p495078 --- src/App/Application.cpp | 345 +++++++++++++++++++++++-------------- src/App/Application.h | 26 ++- src/App/Document.cpp | 20 ++- src/App/Document.h | 7 +- src/App/DocumentObserver.h | 8 + src/App/PropertyLinks.cpp | 69 ++++++-- src/Gui/Document.cpp | 2 +- 7 files changed, 311 insertions(+), 166 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index fb2755571f..97c3bce6b5 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -55,6 +55,8 @@ #include #endif +#include + #include "Application.h" #include "Document.h" @@ -99,6 +101,7 @@ #include "Document.h" #include "DocumentObjectGroup.h" #include "DocumentObjectFileIncluded.h" +#include "DocumentObserver.h" #include "InventorObject.h" #include "VRMLObject.h" #include "Annotation.h" @@ -487,6 +490,7 @@ bool Application::closeDocument(const char* name) setActiveDocument((Document*)0); std::unique_ptr delDoc (pos->second); DocMap.erase( pos ); + DocFileMap.erase(FileInfo(delDoc->FileName.getValue()).filePath()); _objCount = -1; @@ -566,8 +570,10 @@ int Application::addPendingDocument(const char *FileName, const char *objName, b return -1; assert(FileName && FileName[0]); assert(objName && objName[0]); - auto ret = _pendingDocMap.emplace(FileName,std::set()); - ret.first->second.emplace(objName); + if(!_docReloadAttempts[FileName].emplace(objName).second) + return -1; + auto ret = _pendingDocMap.emplace(FileName,std::vector()); + ret.first->second.push_back(objName); if(ret.second) { _pendingDocs.push_back(ret.first->first.c_str()); return 1; @@ -623,6 +629,41 @@ Document* Application::openDocument(const char * FileName, bool createView) { return 0; } +Document *Application::getDocumentByPath(const char *path, int checkCanonical) const { + if(!path || !path[0]) + return nullptr; + if(DocFileMap.empty()) { + for(auto &v : DocMap) { + const auto &file = v.second->FileName.getStrValue(); + if(file.size()) + DocFileMap[FileInfo(file.c_str()).filePath()] = v.second; + } + } + auto it = DocFileMap.find(FileInfo(path).filePath()); + if(it != DocFileMap.end()) + return it->second; + + if (!checkCanonical) + return nullptr; + + std::string filepath = FileInfo(path).filePath(); + QString canonicalPath = QFileInfo(QString::fromUtf8(path)).canonicalFilePath(); + for (auto &v : DocMap) { + QFileInfo fi(QString::fromUtf8(v.second->FileName.getValue())); + if (canonicalPath == fi.canonicalFilePath()) { + if (checkCanonical == 1) + return v.second; + bool samePath = (canonicalPath == QString::fromUtf8(filepath.c_str())); + FC_WARN("Identical physical path '" << canonicalPath.toUtf8().constData() << "'\n" + << (samePath?"":" for file '") << (samePath?"":filepath.c_str()) << (samePath?"":"'\n") + << " with existing document '" << v.second->Label.getValue() + << "' in path: '" << v.second->FileName.getValue() << "'"); + break; + } + } + return nullptr; +} + std::vector Application::openDocuments(const std::vector &filenames, const std::vector *paths, const std::vector *labels, @@ -640,6 +681,7 @@ std::vector Application::openDocuments(const std::vector _pendingDocs.clear(); _pendingDocsReopen.clear(); _pendingDocMap.clear(); + _docReloadAttempts.clear(); signalStartOpenDocument(); @@ -649,118 +691,162 @@ std::vector Application::openDocuments(const std::vector for (auto &name : filenames) _pendingDocs.push_back(name.c_str()); - std::map newDocs; + std::map timings; FC_TIME_INIT(t); - for (std::size_t count=0;; ++count) { - const char *name = _pendingDocs.front(); - _pendingDocs.pop_front(); - bool isMainDoc = count < filenames.size(); + std::vector openedDocs; - try { - _objCount = -1; - std::set objNames; - if (_allowPartial) { - auto it = _pendingDocMap.find(name); - if (it != _pendingDocMap.end()) - objNames.swap(it->second); - } + int pass = 0; + do { + std::set newDocs; + for (std::size_t count=0;; ++count) { + std::string name = std::move(_pendingDocs.front()); + _pendingDocs.pop_front(); + bool isMainDoc = (pass == 0 && count < filenames.size()); - FC_TIME_INIT(t1); - DocTiming timing; + try { + _objCount = -1; + std::vector objNames; + if (_allowPartial) { + auto it = _pendingDocMap.find(name); + if (it != _pendingDocMap.end()) { + if(isMainDoc) + it->second.clear(); + else + objNames.swap(it->second); + _pendingDocMap.erase(it); + } + } - const char *path = name; - const char *label = 0; - if (isMainDoc) { - if (paths && paths->size()>count) - path = (*paths)[count].c_str(); + FC_TIME_INIT(t1); + DocTiming timing; - if (labels && labels->size()>count) - label = (*labels)[count].c_str(); - } + const char *path = name.c_str(); + const char *label = 0; + if (isMainDoc) { + if (paths && paths->size()>count) + path = (*paths)[count].c_str(); - auto doc = openDocumentPrivate(path, name, label, isMainDoc, createView, objNames); - FC_DURATION_PLUS(timing.d1,t1); - if (doc) - newDocs.emplace(doc,timing); + if (labels && labels->size()>count) + label = (*labels)[count].c_str(); + } + + auto doc = openDocumentPrivate(path, name.c_str(), label, isMainDoc, createView, std::move(objNames)); + FC_DURATION_PLUS(timing.d1,t1); + if (doc) { + timings[doc].d1 += timing.d1; + newDocs.emplace(doc); + } - if (isMainDoc) - res[count] = doc; - _objCount = -1; - } - catch (const Base::Exception &e) { - if (!errs && isMainDoc) - throw; - if (errs && isMainDoc) - (*errs)[count] = e.what(); - else - Console().Error("Exception opening file: %s [%s]\n", name, e.what()); - } - catch (const std::exception &e) { - if (!errs && isMainDoc) - throw; - if (errs && isMainDoc) - (*errs)[count] = e.what(); - else - Console().Error("Exception opening file: %s [%s]\n", name, e.what()); - } - catch (...) { - if (errs) { if (isMainDoc) - (*errs)[count] = "unknown error"; + res[count] = doc; + _objCount = -1; } - else { - _pendingDocs.clear(); + catch (const Base::Exception &e) { + e.ReportException(); + if (!errs && isMainDoc) + throw; + if (errs && isMainDoc) + (*errs)[count] = e.what(); + else + Console().Error("Exception opening file: %s [%s]\n", name.c_str(), e.what()); + } + catch (const std::exception &e) { + if (!errs && isMainDoc) + throw; + if (errs && isMainDoc) + (*errs)[count] = e.what(); + else + Console().Error("Exception opening file: %s [%s]\n", name.c_str(), e.what()); + } + catch (...) { + if (errs) { + if (isMainDoc) + (*errs)[count] = "unknown error"; + } + else { + _pendingDocs.clear(); + _pendingDocsReopen.clear(); + _pendingDocMap.clear(); + throw; + } + } + + if (_pendingDocs.empty()) { + if(_pendingDocsReopen.empty()) + break; + _pendingDocs = std::move(_pendingDocsReopen); _pendingDocsReopen.clear(); - _pendingDocMap.clear(); - throw; + for(auto &file : _pendingDocs) { + auto doc = getDocumentByPath(file.c_str()); + if(doc) + closeDocument(doc->getName()); + } } } - if (_pendingDocs.empty()) { - if (_pendingDocsReopen.empty()) - break; - _allowPartial = false; - _pendingDocs.swap(_pendingDocsReopen); + ++pass; + _pendingDocMap.clear(); + + std::vector docs; + docs.reserve(newDocs.size()); + for(auto &d : newDocs) { + auto doc = d.getDocument(); + if(!doc) + continue; + // Notify PropertyXLink to attach newly opened documents and restore + // relevant external links + PropertyXLink::restoreDocument(*doc); + docs.push_back(doc); } - } - _pendingDocs.clear(); - _pendingDocsReopen.clear(); - _pendingDocMap.clear(); + Base::SequencerLauncher seq("Postprocessing...", docs.size()); - Base::SequencerLauncher seq("Postprocessing...", newDocs.size()); - - std::vector docs; - docs.reserve(newDocs.size()); - for (auto &v : newDocs) { - // Notify PropertyXLink to attach newly opened documents and restore - // relevant external links - PropertyXLink::restoreDocument(*v.first); - docs.push_back(v.first); - } - - // After external links has been restored, we can now sort the document - // according to their dependency order. - docs = Document::getDependentDocuments(docs, true); - for (auto it=docs.begin(); it!=docs.end();) { - Document *doc = *it; - // It is possible that the newly opened document depends on an existing - // document, which will be included with the above call to - // Document::getDependentDocuments(). Make sure to exclude that. - auto dit = newDocs.find(doc); - if (dit == newDocs.end()) { - it = docs.erase(it); - continue; + // After external links has been restored, we can now sort the document + // according to their dependency order. + try { + docs = Document::getDependentDocuments(docs, true); + } catch (Base::Exception &e) { + e.ReportException(); } - ++it; - FC_TIME_INIT(t1); - // Finalize document restoring with the correct order - doc->afterRestore(true); - FC_DURATION_PLUS(dit->second.d2,t1); - seq.next(); - } + for(auto it=docs.begin(); it!=docs.end();) { + auto doc = *it; + + // It is possible that the newly opened document depends on an existing + // document, which will be included with the above call to + // Document::getDependentDocuments(). Make sure to exclude that. + if(!newDocs.count(doc)) { + it = docs.erase(it); + continue; + } + + auto &timing = timings[doc]; + FC_TIME_INIT(t1); + // Finalize document restoring with the correct order + if(doc->afterRestore(true)) { + openedDocs.push_back(doc); + it = docs.erase(it); + } else { + ++it; + // Here means this is a partial loaded document, and we need to + // reload it fully because of touched objects. The reason of + // reloading a partial document with touched object is because + // partial document is supposed to be readonly, while a + // 'touched' object requires recomputation. And an object may + // become touched during restoring if externally linked + // document time stamp mismatches with the stamp saved. + _pendingDocs.push_back(doc->FileName.getValue()); + _pendingDocMap.erase(doc->FileName.getValue()); + } + FC_DURATION_PLUS(timing.d2,t1); + seq.next(); + } + // Close the document for reloading + for(auto doc : docs) + closeDocument(doc->getName()); + + }while(!_pendingDocs.empty()); // Set the active document using the first successfully restored main // document (i.e. documents explicitly asked for by caller). @@ -771,14 +857,14 @@ std::vector Application::openDocuments(const std::vector } } - for (auto doc : docs) { - auto &timing = newDocs[doc]; - FC_DURATION_LOG(timing.d1, doc->getName() << " restore"); - FC_DURATION_LOG(timing.d2, doc->getName() << " postprocess"); + for (auto &doc : openedDocs) { + auto &timing = timings[doc]; + FC_DURATION_LOG(timing.d1, doc.getDocumentName() << " restore"); + FC_DURATION_LOG(timing.d2, doc.getDocumentName() << " postprocess"); } FC_TIME_LOG(t,"total"); - _isRestoring = false; + signalFinishOpenDocument(); return res; } @@ -786,7 +872,7 @@ std::vector Application::openDocuments(const std::vector Document* Application::openDocumentPrivate(const char * FileName, const char *propFileName, const char *label, bool isMainDoc, bool createView, - const std::set &objNames) + std::vector &&objNames) { FileInfo File(FileName); @@ -797,55 +883,51 @@ Document* Application::openDocumentPrivate(const char * FileName, } // Before creating a new document we check whether the document is already open - std::string filepath = File.filePath(); - QString canonicalPath = QFileInfo(QString::fromUtf8(FileName)).canonicalFilePath(); - for (std::map::iterator it = DocMap.begin(); it != DocMap.end(); ++it) { - // get unique path separators - std::string fi = FileInfo(it->second->FileName.getValue()).filePath(); - if (filepath != fi) { - if (canonicalPath == QFileInfo(QString::fromUtf8(fi.c_str())).canonicalFilePath()) { - bool samePath = (canonicalPath == QString::fromUtf8(FileName)); - FC_WARN("Identical physical path '" << canonicalPath.toUtf8().constData() << "'\n" - << (samePath?"":" for file '") << (samePath?"":FileName) << (samePath?"":"'\n") - << " with existing document '" << it->second->Label.getValue() - << "' in path: '" << it->second->FileName.getValue() << "'"); - } - continue; - } - if(it->second->testStatus(App::Document::PartialDoc) - || it->second->testStatus(App::Document::PartialRestore)) { + auto doc = getDocumentByPath(File.filePath().c_str(), 2); + if(doc) { + if(doc->testStatus(App::Document::PartialDoc) + || doc->testStatus(App::Document::PartialRestore)) { // Here means a document is already partially loaded, but the document // is requested again, either partial or not. We must check if the // document contains the required object if(isMainDoc) { // Main document must be open fully, so close and reopen - closeDocument(it->first.c_str()); - break; - } - - if(_allowPartial) { + closeDocument(doc->getName()); + doc = nullptr; + } else if(_allowPartial) { bool reopen = false; for(auto &name : objNames) { - auto obj = it->second->getObject(name.c_str()); + auto obj = doc->getObject(name.c_str()); if(!obj || obj->testStatus(App::PartialObject)) { reopen = true; + // NOTE: We are about to reload this document with + // extra objects. However, it is possible to repeat + // this process several times, if it is linked by + // multiple documents and each with a different set of + // objects. To partially solve this problem, we do not + // close and reopen the document immediately here, but + // add it to _pendingDocsReopen to delay reloading. + for(auto obj : doc->getObjects()) + objNames.push_back(obj->getNameInDocument()); + _pendingDocMap[doc->FileName.getValue()] = std::move(objNames); break; } } if(!reopen) return 0; } - auto &names = _pendingDocMap[FileName]; - names.clear(); - _pendingDocsReopen.push_back(FileName); - return 0; + + if(doc) { + _pendingDocsReopen.emplace_back(FileName); + return 0; + } } if(!isMainDoc) return 0; - - return it->second; + else if(doc) + return doc; } std::string name; @@ -867,6 +949,8 @@ Document* Application::openDocumentPrivate(const char * FileName, try { // read the document newDoc->restore(File.filePath().c_str(),true,objNames); + if(DocFileMap.size()) + DocFileMap[FileInfo(newDoc->FileName.getValue()).filePath()] = newDoc; return newDoc; } // if the project file itself is corrupt then @@ -1463,6 +1547,7 @@ void Application::slotStartSaveDocument(const App::Document& doc, const std::str void Application::slotFinishSaveDocument(const App::Document& doc, const std::string& filename) { + DocFileMap.clear(); this->signalFinishSaveDocument(doc, filename); } diff --git a/src/App/Application.h b/src/App/Application.h index 506c3a364e..5042df74db 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -120,6 +120,16 @@ public: App::Document* getActiveDocument(void) const; /// Retrieve a named document App::Document* getDocument(const char *Name) const; + /** Retrieve a document based on file path + * + * @param path: file path + * @param checkCanonical: if zero, only match absolute file path. If 1, + * then match by canonical file path, where any intermediate '.' and '..' + * and symlinks are resolved. If 2, then only print warning message if + * there is identical canonical file path found, but will not return the + * matched document. + */ + App::Document* getDocumentByPath(const char *path, int checkCanonical=0) const; /// gets the (internal) name of the document const char * getDocumentName(const App::Document* ) const; /// get a list of all documents in the application @@ -190,6 +200,8 @@ public: boost::signals2::signal signalStartRestoreDocument; /// signal on restoring Document boost::signals2::signal signalFinishRestoreDocument; + /// signal on pending reloading of a partial Document + boost::signals2::signal signalPendingReloadDocument; /// signal on starting to save Document boost::signals2::signal signalStartSaveDocument; /// signal on saved Document @@ -441,7 +453,7 @@ protected: /// open single document only App::Document* openDocumentPrivate(const char * FileName, const char *propFileName, - const char *label, bool isMainDoc, bool createView, const std::set &objNames); + const char *label, bool isMainDoc, bool createView, std::vector &&objNames); /// Helper class for App::Document to signal on close/abort transaction class AppExport TransactionSignaller { @@ -559,13 +571,19 @@ private: std::vector _mImportTypes; std::vector _mExportTypes; std::map DocMap; + mutable std::map DocFileMap; std::map mpcPramManager; std::map &_mConfig; App::Document* _pActiveDoc; - std::deque _pendingDocs; - std::deque _pendingDocsReopen; - std::map > _pendingDocMap; + std::deque _pendingDocs; + std::deque _pendingDocsReopen; + std::map > _pendingDocMap; + + // To prevent infinite recursion of reloading a partial document due a truely + // missing object + std::map > _docReloadAttempts; + bool _isRestoring; bool _allowPartial; bool _isClosingAll; diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 1f108b8df3..f6ec4f46ac 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1866,7 +1866,6 @@ void Document::exportObjects(const std::vector& obj, std:: #define FC_ELEMENT_OBJECT_DEPS "ObjectDeps" #define FC_ATTR_DEP_COUNT "Count" #define FC_ATTR_DEP_OBJ_NAME "Name" -#define FC_ATTR_DEP_COUNT "Count" #define FC_ATTR_DEP_ALLOW_PARTIAL "AllowPartial" #define FC_ELEMENT_OBJECT_DEP "Dep" @@ -2693,7 +2692,7 @@ bool Document::isAnyRestoring() { // Open the document void Document::restore (const char *filename, - bool delaySignal, const std::set &objNames) + bool delaySignal, const std::vector &objNames) { clearUndos(); d->activeObject = 0; @@ -2752,8 +2751,7 @@ void Document::restore (const char *filename, d->partialLoadObjects.emplace(name,true); try { Document::Restore(reader); - } - catch (const Base::Exception& e) { + } catch (const Base::Exception& e) { Base::Console().Error("Invalid Document.xml: %s\n", e.what()); setStatus(Document::RestoreError, true); } @@ -2777,15 +2775,16 @@ void Document::restore (const char *filename, afterRestore(true); } -void Document::afterRestore(bool checkPartial) { +bool Document::afterRestore(bool checkPartial) { Base::FlagToggler<> flag(_IsRestoring,false); if(!afterRestore(d->objectArray,checkPartial)) { FC_WARN("Reload partial document " << getName()); - restore(); - return; + GetApplication().signalPendingReloadDocument(*this); + return false; } GetApplication().signalFinishRestoreDocument(*this); setStatus(Document::Restoring, false); + return true; } bool Document::afterRestore(const std::vector &objArray, bool checkPartial) @@ -2861,9 +2860,12 @@ bool Document::afterRestore(const std::vector &objArray, bool std::string errMsg; if(link && (res=link->checkRestore(&errMsg))) { d->touchedObjs.insert(obj); - if(res==1) + if(res==1 || checkPartial) { FC_WARN(obj->getFullName() << '.' << prop->getName() << ": " << errMsg); - else { + setStatus(Document::LinkStampChanged, true); + if(checkPartial) + return false; + } else { FC_ERR(obj->getFullName() << '.' << prop->getName() << ": " << errMsg); d->addRecomputeLog(errMsg,obj); setStatus(Document::PartialRestore, true); diff --git a/src/App/Document.h b/src/App/Document.h index a4b2285cdc..16e8053fb8 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -74,7 +74,8 @@ public: PartialDoc = 7, AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set TempDoc = 9, // Mark as temporary document without prompt for save - RestoreError = 10 + RestoreError = 10, + LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed }; /** @name Properties */ @@ -195,8 +196,8 @@ public: bool saveCopy(const char* file) const; /// Restore the document from the file in Property Path void restore (const char *filename=0, - bool delaySignal=false, const std::set &objNames={}); - void afterRestore(bool checkPartial=false); + bool delaySignal=false, const std::vector &objNames={}); + bool afterRestore(bool checkPartial=false); bool afterRestore(const std::vector &, bool checkPartial=false); enum ExportStatus { NotExporting, diff --git a/src/App/DocumentObserver.h b/src/App/DocumentObserver.h index c32c780a01..b93373ae2b 100644 --- a/src/App/DocumentObserver.h +++ b/src/App/DocumentObserver.h @@ -62,6 +62,14 @@ public: /*! Assignment operator */ void operator=(const std::string&); + bool operator==(const DocumentT &other) const { + return document == other.document; + } + + bool operator<(const DocumentT &other) const { + return document < other.document; + } + /*! Get a pointer to the document or 0 if it doesn't exist any more. */ Document* getDocument() const; /*! Get the name of the document. */ diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index e78abd3c22..f92879aa4e 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -2458,6 +2458,7 @@ class App::DocInfo : public: typedef boost::signals2::scoped_connection Connection; Connection connFinishRestoreDocument; + Connection connPendingReloadDocument; Connection connDeleteDocument; Connection connSaveDocument; Connection connDeletedObject; @@ -2589,6 +2590,7 @@ public: FC_LOG("deinit " << (pcDoc?pcDoc->getName():filePath())); assert(links.empty()); connFinishRestoreDocument.disconnect(); + connPendingReloadDocument.disconnect(); connDeleteDocument.disconnect(); connSaveDocument.disconnect(); connDeletedObject.disconnect(); @@ -2606,6 +2608,8 @@ public: App::Application &app = App::GetApplication(); connFinishRestoreDocument = app.signalFinishRestoreDocument.connect( boost::bind(&DocInfo::slotFinishRestoreDocument,this,bp::_1)); + connPendingReloadDocument = app.signalPendingReloadDocument.connect( + boost::bind(&DocInfo::slotFinishRestoreDocument,this,bp::_1)); connDeleteDocument = app.signalDeleteDocument.connect( boost::bind(&DocInfo::slotDeleteDocument,this,bp::_1)); connSaveDocument = app.signalSaveDocument.connect( @@ -2617,6 +2621,8 @@ public: else{ for(App::Document *doc : App::GetApplication().getDocuments()) { if(getFullPath(doc->getFileName()) == fullpath) { + if(doc->testStatus(App::Document::PartialDoc) && !doc->getObject(objName)) + break; attach(doc); return; } @@ -2642,22 +2648,36 @@ public: continue; } auto obj = doc->getObject(link->objectName.c_str()); - if(!obj) + if(obj) + link->restoreLink(obj); + else if (doc->testStatus(App::Document::PartialDoc)) { + App::GetApplication().addPendingDocument( + doc->FileName.getValue(), + link->objectName.c_str(), + false); + FC_WARN("reloading partial document '" << doc->FileName.getValue() + << "' due to object " << link->objectName); + } else FC_WARN("object '" << link->objectName << "' not found in document '" << doc->getName() << "'"); - else - link->restoreLink(obj); } for(auto &v : parentLinks) { v.first->setFlag(PropertyLinkBase::LinkRestoring); v.first->aboutToSetValue(); for(auto link : v.second) { auto obj = doc->getObject(link->objectName.c_str()); - if(!obj) + if(obj) + link->restoreLink(obj); + else if (doc->testStatus(App::Document::PartialDoc)) { + App::GetApplication().addPendingDocument( + doc->FileName.getValue(), + link->objectName.c_str(), + false); + FC_WARN("reloading partial document '" << doc->FileName.getValue() + << "' due to object " << link->objectName); + } else FC_WARN("object '" << link->objectName << "' not found in document '" << doc->getName() << "'"); - else - link->restoreLink(obj); } v.first->hasSetValue(); v.first->setFlag(PropertyLinkBase::LinkRestoring,false); @@ -2723,16 +2743,17 @@ public: } } - // time stamp changed, touch the linking document. Unfortunately, there - // is no way to setModfied() for an App::Document. We don't want to touch - // all PropertyXLink for a document, because the linked object is - // potentially unchanged. So we just touch at most one. + // time stamp changed, touch the linking document. std::set docs; for(auto link : links) { auto linkdoc = static_cast(link->getContainer())->getDocument(); auto ret = docs.insert(linkdoc); - if(ret.second && !linkdoc->isTouched()) - link->touch(); + if(ret.second) { + // This will signal the Gui::Document to call setModified(); + FC_LOG("touch document " << linkdoc->getName() + << " on time stamp change of " << link->getFullName()); + linkdoc->Comment.touch(); + } } } @@ -3473,7 +3494,12 @@ PropertyXLink::getDocumentOutList(App::Document *doc) { std::map > ret; for(auto &v : _DocInfoMap) { for(auto link : v.second->links) { - if(!v.second->pcDoc) continue; + if(!v.second->pcDoc + || link->getScope() == LinkScope::Hidden + || link->testStatus(Property::PropTransient) + || link->testStatus(Property::Transient) + || link->testStatus(Property::PropNoPersist)) + continue; auto obj = dynamic_cast(link->getContainer()); if(!obj || !obj->getNameInDocument() || !obj->getDocument()) continue; @@ -3493,6 +3519,11 @@ PropertyXLink::getDocumentInList(App::Document *doc) { continue; auto &docs = ret[v.second->pcDoc]; for(auto link : v.second->links) { + if(link->getScope() == LinkScope::Hidden + || link->testStatus(Property::PropTransient) + || link->testStatus(Property::Transient) + || link->testStatus(Property::PropNoPersist)) + continue; auto obj = dynamic_cast(link->getContainer()); if(obj && obj->getNameInDocument() && obj->getDocument()) docs.insert(obj->getDocument()); @@ -4460,12 +4491,12 @@ void PropertyXLinkContainer::breakLink(App::DocumentObject *obj, bool clear) { } int PropertyXLinkContainer::checkRestore(std::string *msg) const { - if(_LinkRestored) - return 1; - for(auto &v : _XLinks) { - int res = v.second->checkRestore(msg); - if(res) - return res; + if(_LinkRestored) { + for(auto &v : _XLinks) { + int res = v.second->checkRestore(msg); + if(res) + return res; + } } return 0; } diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index 589deecede..813e84a69f 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -1499,7 +1499,7 @@ void Document::slotFinishRestoreDocument(const App::Document& doc) } // reset modified flag - setModified(false); + setModified(doc.testStatus(App::Document::LinkStampChanged)); } void Document::slotShowHidden(const App::Document& doc) From 9885dadfff6bc8fe25ba7eb2cb45e4ddaeae1c33 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Fri, 6 Aug 2021 14:46:56 +0800 Subject: [PATCH 10/68] App: use enum in API Application::getDocumentByPath() --- src/App/Application.cpp | 8 ++++---- src/App/Application.h | 29 +++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 97c3bce6b5..72db851cba 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -629,7 +629,7 @@ Document* Application::openDocument(const char * FileName, bool createView) { return 0; } -Document *Application::getDocumentByPath(const char *path, int checkCanonical) const { +Document *Application::getDocumentByPath(const char *path, PathMatchMode checkCanonical) const { if(!path || !path[0]) return nullptr; if(DocFileMap.empty()) { @@ -643,7 +643,7 @@ Document *Application::getDocumentByPath(const char *path, int checkCanonical) c if(it != DocFileMap.end()) return it->second; - if (!checkCanonical) + if (checkCanonical == MatchAbsolute) return nullptr; std::string filepath = FileInfo(path).filePath(); @@ -651,7 +651,7 @@ Document *Application::getDocumentByPath(const char *path, int checkCanonical) c for (auto &v : DocMap) { QFileInfo fi(QString::fromUtf8(v.second->FileName.getValue())); if (canonicalPath == fi.canonicalFilePath()) { - if (checkCanonical == 1) + if (checkCanonical == MatchCanonical) return v.second; bool samePath = (canonicalPath == QString::fromUtf8(filepath.c_str())); FC_WARN("Identical physical path '" << canonicalPath.toUtf8().constData() << "'\n" @@ -883,7 +883,7 @@ Document* Application::openDocumentPrivate(const char * FileName, } // Before creating a new document we check whether the document is already open - auto doc = getDocumentByPath(File.filePath().c_str(), 2); + auto doc = getDocumentByPath(File.filePath().c_str(), MatchCanonicalWarning); if(doc) { if(doc->testStatus(App::Document::PartialDoc) || doc->testStatus(App::Document::PartialRestore)) { diff --git a/src/App/Application.h b/src/App/Application.h index 5042df74db..738c0e19d7 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -120,16 +120,33 @@ public: App::Document* getActiveDocument(void) const; /// Retrieve a named document App::Document* getDocument(const char *Name) const; + + /// Path matching mode for getDocumentByPath() + enum PathMatchMode { + /// Match by resolving to absolute file path + MatchAbsolute = 0, + /** Match by absolute path first. If not found then match by resolving + * to canonical file path where any intermediate '.' '..' and symlinks + * are resolved. + */ + MatchCanonical = 1, + /** Same as MatchCanonical, but if a document is found by canonical + * path match, which means the document can be resolved using two + * different absolute path, a warning is printed and the found document + * is not returned. This is to allow the caller to intentionally load + * the same physical file as separate documents. + */ + MatchCanonicalWarning = 2, + }; /** Retrieve a document based on file path * * @param path: file path - * @param checkCanonical: if zero, only match absolute file path. If 1, - * then match by canonical file path, where any intermediate '.' and '..' - * and symlinks are resolved. If 2, then only print warning message if - * there is identical canonical file path found, but will not return the - * matched document. + * @param checkCanonical: file path matching mode, @sa PathMatchMode. + * @return Return the document found by matching with the given path */ - App::Document* getDocumentByPath(const char *path, int checkCanonical=0) const; + App::Document* getDocumentByPath(const char *path, + PathMatchMode checkCanonical = MatchAbsolute) const; + /// gets the (internal) name of the document const char * getDocumentName(const App::Document* ) const; /// get a list of all documents in the application From a2fb4a5d6d4a0f3365669b448617567b7e87223a Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Sat, 30 Oct 2021 12:30:45 +0800 Subject: [PATCH 11/68] Minor code change according to suggestions --- src/App/Application.cpp | 18 +++++++++--------- src/App/Application.h | 4 ++-- src/App/Document.h | 2 +- src/Gui/ViewProviderDocumentObject.cpp | 2 +- src/Mod/Part/Gui/ViewProviderExt.cpp | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 72db851cba..d51a6740fc 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -633,7 +633,7 @@ Document *Application::getDocumentByPath(const char *path, PathMatchMode checkCa if(!path || !path[0]) return nullptr; if(DocFileMap.empty()) { - for(auto &v : DocMap) { + for(const auto &v : DocMap) { const auto &file = v.second->FileName.getStrValue(); if(file.size()) DocFileMap[FileInfo(file.c_str()).filePath()] = v.second; @@ -643,15 +643,15 @@ Document *Application::getDocumentByPath(const char *path, PathMatchMode checkCa if(it != DocFileMap.end()) return it->second; - if (checkCanonical == MatchAbsolute) + if (checkCanonical == PathMatchMode::MatchAbsolute) return nullptr; std::string filepath = FileInfo(path).filePath(); QString canonicalPath = QFileInfo(QString::fromUtf8(path)).canonicalFilePath(); - for (auto &v : DocMap) { + for (const auto &v : DocMap) { QFileInfo fi(QString::fromUtf8(v.second->FileName.getValue())); if (canonicalPath == fi.canonicalFilePath()) { - if (checkCanonical == MatchCanonical) + if (checkCanonical == PathMatchMode::MatchCanonical) return v.second; bool samePath = (canonicalPath == QString::fromUtf8(filepath.c_str())); FC_WARN("Identical physical path '" << canonicalPath.toUtf8().constData() << "'\n" @@ -778,7 +778,7 @@ std::vector Application::openDocuments(const std::vector break; _pendingDocs = std::move(_pendingDocsReopen); _pendingDocsReopen.clear(); - for(auto &file : _pendingDocs) { + for(const auto &file : _pendingDocs) { auto doc = getDocumentByPath(file.c_str()); if(doc) closeDocument(doc->getName()); @@ -791,7 +791,7 @@ std::vector Application::openDocuments(const std::vector std::vector docs; docs.reserve(newDocs.size()); - for(auto &d : newDocs) { + for(const auto &d : newDocs) { auto doc = d.getDocument(); if(!doc) continue; @@ -843,7 +843,7 @@ std::vector Application::openDocuments(const std::vector seq.next(); } // Close the document for reloading - for(auto doc : docs) + for(const auto doc : docs) closeDocument(doc->getName()); }while(!_pendingDocs.empty()); @@ -883,7 +883,7 @@ Document* Application::openDocumentPrivate(const char * FileName, } // Before creating a new document we check whether the document is already open - auto doc = getDocumentByPath(File.filePath().c_str(), MatchCanonicalWarning); + auto doc = getDocumentByPath(File.filePath().c_str(), PathMatchMode::MatchCanonicalWarning); if(doc) { if(doc->testStatus(App::Document::PartialDoc) || doc->testStatus(App::Document::PartialRestore)) { @@ -897,7 +897,7 @@ Document* Application::openDocumentPrivate(const char * FileName, doc = nullptr; } else if(_allowPartial) { bool reopen = false; - for(auto &name : objNames) { + for(const auto &name : objNames) { auto obj = doc->getObject(name.c_str()); if(!obj || obj->testStatus(App::PartialObject)) { reopen = true; diff --git a/src/App/Application.h b/src/App/Application.h index 738c0e19d7..0d38fcfdab 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -122,7 +122,7 @@ public: App::Document* getDocument(const char *Name) const; /// Path matching mode for getDocumentByPath() - enum PathMatchMode { + enum class PathMatchMode { /// Match by resolving to absolute file path MatchAbsolute = 0, /** Match by absolute path first. If not found then match by resolving @@ -145,7 +145,7 @@ public: * @return Return the document found by matching with the given path */ App::Document* getDocumentByPath(const char *path, - PathMatchMode checkCanonical = MatchAbsolute) const; + PathMatchMode checkCanonical = PathMatchMode::MatchAbsolute) const; /// gets the (internal) name of the document const char * getDocumentName(const App::Document* ) const; diff --git a/src/App/Document.h b/src/App/Document.h index 16e8053fb8..6d0e7c5ec2 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -75,7 +75,7 @@ public: AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set TempDoc = 9, // Mark as temporary document without prompt for save RestoreError = 10, - LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed + LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed }; /** @name Properties */ diff --git a/src/Gui/ViewProviderDocumentObject.cpp b/src/Gui/ViewProviderDocumentObject.cpp index ec1e08c199..e4cc2bbb2b 100644 --- a/src/Gui/ViewProviderDocumentObject.cpp +++ b/src/Gui/ViewProviderDocumentObject.cpp @@ -197,7 +197,7 @@ void ViewProviderDocumentObject::onChanged(const App::Property* prop) // modified then it must be be reversed. if (!testStatus(Gui::ViewStatus::TouchDocument)) { // Note: reverting document modified status like that is not - // appropreiate because we can't tell if there is any other + // appropriate because we can't tell if there is any other // property being changed due to the change of Visibility here. // Temporary setting the Visibility property as 'NoModify' is // the proper way. diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 64f92b99e9..9bd7037d1f 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -399,7 +399,7 @@ void ViewProviderPartExt::onChanged(const App::Property* prop) updateVisual(); // updateVisual() may not be triggered by any change (e.g. // triggered by an external object through forceUpdate()). And - // since DiffuseColor is not changed here either, do not falsly set + // since DiffuseColor is not changed here either, do not falsely set // the document modified status Base::ObjectStatusLocker guard( App::Property::NoModify, &DiffuseColor); From c5fb91170b2ee9cf1d2d67243b7fdd5ab0e0bb61 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Oct 2021 14:50:00 +0200 Subject: [PATCH 12/68] dist-git: make script working again for Py3 and Linux --- .../CreatePackagingTargets.cmake | 24 +++++++--- src/Tools/makedist.py | 44 +++++++++++++------ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/cMake/FreeCAD_Helpers/CreatePackagingTargets.cmake b/cMake/FreeCAD_Helpers/CreatePackagingTargets.cmake index 60cd19c758..de8b52c6d3 100644 --- a/cMake/FreeCAD_Helpers/CreatePackagingTargets.cmake +++ b/cMake/FreeCAD_Helpers/CreatePackagingTargets.cmake @@ -5,25 +5,37 @@ macro(CreatePackagingTargets) #add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source) add_custom_target(dist-git COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py - --srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} + --bindir=${CMAKE_BINARY_DIR} + --major=${PACKAGE_VERSION_MAJOR} + --minor=${PACKAGE_VERSION_MINOR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target(distdfsg-git COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py - --srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} --dfsg + --bindir=${CMAKE_BINARY_DIR} + --major=${PACKAGE_VERSION_MAJOR} + --minor=${PACKAGE_VERSION_MINOR} + --dfsg WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) - if(CMAKE_COMPILER_IS_GNUCXX OR MINGW) + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX OR MINGW) add_custom_target(distcheck-git COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py - --srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} --check + --bindir=${CMAKE_BINARY_DIR} + --major=${PACKAGE_VERSION_MAJOR} + --minor=${PACKAGE_VERSION_MINOR} + --check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target(distcheckdfsg-git COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py - --srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} --dfsg --check + --bindir=${CMAKE_BINARY_DIR} + --major=${PACKAGE_VERSION_MAJOR} + --minor=${PACKAGE_VERSION_MINOR} + --dfsg + --check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) - endif(CMAKE_COMPILER_IS_GNUCXX OR MINGW) + endif() endmacro(CreatePackagingTargets) diff --git a/src/Tools/makedist.py b/src/Tools/makedist.py index f4118fe68c..c054534fe8 100644 --- a/src/Tools/makedist.py +++ b/src/Tools/makedist.py @@ -5,23 +5,29 @@ # Python script to make source tarballs. # -import sys, os, getopt, tarfile, gzip, time, io, platform, shutil +import sys, os, getopt, tarfile, gzip, time, io, platform, shutil, subprocess def main(): bindir="." + major="0" + minor="0" dfsg=False check=False - wta="" + wta=None try: - opts, args = getopt.getopt(sys.argv[1:], "sb:", ["srcdir=","bindir=","dfsg", "check"]) + opts, args = getopt.getopt(sys.argv[1:], "sb:", ["srcdir=","bindir=","major=","minor=","dfsg", "check"]) except getopt.GetoptError: pass for o, a in opts: if o in ("-s", "--srcdir"): - print("%s is deprecated -- ignoring" % (o)) + print("{} is deprecated -- ignoring".format(o)) if o in ("-b", "--bindir"): bindir = a + if o in ("--major"): + major = a + if o in ("--minor"): + minor = a if o in ("--dfsg"): dfsg = True wta = "--worktree-attributes" @@ -41,14 +47,15 @@ def main(): info=os.popen("git rev-list HEAD").read() revision='%04d' % (info.count('\n')) - verfile = open("%s/src/Build/Version.h" % (bindir), 'r') - verstream = io.StringIO(verfile.read()) + verfile = open("{}/src/Build/Version.h".format(bindir), 'rb') + verstream = io.BytesIO(verfile.read()) verfile.close() - version_minor = verstream.getvalue().split('FCVersionMinor "')[1][:2] + version_major = major + version_minor = minor PACKAGE_NAME = 'freecad' - version = "0.%s.%s" % (version_minor, revision) + version = "{}.{}.{}".format(version_major, version_minor, revision) DIRNAME = "%(p)s-%(v)s" % {'p': PACKAGE_NAME, 'v': version} TARNAME = DIRNAME + '.tar' @@ -61,10 +68,13 @@ def main(): verinfo.size = len(verstream.getvalue()) verinfo.mtime = time.time() - print(("git archive %s --prefix=%s/ HEAD" % (wta, DIRNAME))) + if wta is None: + print(("git archive --prefix={}/ HEAD".format(DIRNAME))) + else: + print(("git archive {} --prefix={}/ HEAD".format(wta, DIRNAME))) + if platform.system() == 'Windows': - os.popen("git archive %s --prefix=%s/ --output=%s HEAD" - % (wta, DIRNAME, TARNAME)).read() + os.popen("git archive {} --prefix={}/ --output={} HEAD".format(wta, DIRNAME, TARNAME)).read() tar = tarfile.TarFile(mode="a", name=TARNAME) tar.addfile(verinfo, verstream) @@ -77,9 +87,15 @@ def main(): tardata.close() os.remove(TARNAME) else: - tardata = os.popen("git archive %s --prefix=%s/ HEAD" - % (wta, DIRNAME)).read() - tarstream = io.StringIO(tardata) + cmd_line = ["git", "archive"] + if not wta is None: + cmd_line.append(wta) + cmd_line.append("--prefix={}/".format(DIRNAME)) + cmd_line.append("HEAD") + + tardata = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out,err = tardata.communicate() + tarstream = io.BytesIO(out) tar = tarfile.TarFile(mode="a", fileobj=tarstream) tar.addfile(verinfo, verstream) From b3a6f21866c124bca7d1371db922d5b26b98cf07 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Oct 2021 17:29:11 +0200 Subject: [PATCH 13/68] Part: [skip ci] add PartGlobal.h with export/import macros --- src/Mod/Part/PartGlobal.h | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/Mod/Part/PartGlobal.h diff --git a/src/Mod/Part/PartGlobal.h b/src/Mod/Part/PartGlobal.h new file mode 100644 index 0000000000..a6d29ec10c --- /dev/null +++ b/src/Mod/Part/PartGlobal.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (c) 2021 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include + +#ifndef PART_GLOBAL_H +#define PART_GLOBAL_H + + +// Part +#ifndef PartExport +#ifdef Part_EXPORTS +# define PartExport FREECAD_DECL_EXPORT +#else +# define PartExport FREECAD_DECL_IMPORT +#endif +#endif + +// PartGui +#ifndef PartGuiExport +#ifdef PartGui_EXPORTS +# define PartGuiExport FREECAD_DECL_EXPORT +#else +# define PartGuiExport FREECAD_DECL_IMPORT +#endif +#endif + +#endif //PART_GLOBAL_H From 717219bcec1d6987cedc4180f8416a0fb0b3e29e Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Oct 2021 17:57:11 +0200 Subject: [PATCH 14/68] Part: [skip ci] include PartGlobal.h in ViewProviderExt.h --- src/Mod/Part/Gui/ViewProviderExt.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index 2cb55c1873..4dcbd6ac5c 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -34,6 +34,7 @@ #include #include #include +#include class TopoDS_Shape; class TopoDS_Edge; From c5b3ee7a72db9d8542618ba479e68cb1abc90f5b Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Oct 2021 17:57:52 +0200 Subject: [PATCH 15/68] Part: in ViewProviderSpline use the ViewProviderSplineExtension to avoid code duplication --- src/Mod/Part/Gui/ViewProviderSpline.cpp | 240 +----------------------- src/Mod/Part/Gui/ViewProviderSpline.h | 47 ++--- 2 files changed, 19 insertions(+), 268 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProviderSpline.cpp b/src/Mod/Part/Gui/ViewProviderSpline.cpp index e9d1ce23c4..fa6d67a912 100644 --- a/src/Mod/Part/Gui/ViewProviderSpline.cpp +++ b/src/Mod/Part/Gui/ViewProviderSpline.cpp @@ -63,10 +63,9 @@ namespace bp = boost::placeholders; PROPERTY_SOURCE(PartGui::ViewProviderSpline, PartGui::ViewProviderPartExt) ViewProviderSpline::ViewProviderSpline() - : pcControlPoints(0) { sPixmap = "Part_Spline_Parametric"; - ADD_PROPERTY(ControlPoints,(false)); + extension.initExtension(this); } ViewProviderSpline::~ViewProviderSpline() @@ -78,243 +77,6 @@ QIcon ViewProviderSpline::getIcon(void) const return Gui::BitmapFactory().pixmap(sPixmap); } -void ViewProviderSpline::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) -{ - ViewProviderPartExt::setupContextMenu(menu, receiver, member); - - // toggle command to display components - Gui::ActionFunction* func = new Gui::ActionFunction(menu); - QAction* act = menu->addAction(QObject::tr("Show control points")); - act->setCheckable(true); - act->setChecked(ControlPoints.getValue()); - func->toggle(act, boost::bind(&ViewProviderSpline::toggleControlPoints, this, bp::_1)); -} - -void ViewProviderSpline::toggleControlPoints(bool on) -{ - ControlPoints.setValue(on); -} - -void ViewProviderSpline::updateData(const App::Property* prop) -{ - ViewProviderPartExt::updateData(prop); - if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId() && strcmp(prop->getName(), "Shape") == 0) { - // update control points if there - if (pcControlPoints) { - Gui::coinRemoveAllChildren(pcControlPoints); - showControlPoints(this->ControlPoints.getValue(), prop); - } - } -} - -void ViewProviderSpline::onChanged(const App::Property* prop) -{ - if (prop == &ControlPoints) { - App::DocumentObject* obj = this->pcObject; - App::Property* shape = obj->getPropertyByName("Shape"); - showControlPoints(ControlPoints.getValue(), shape); - } - else { - ViewProviderPartExt::onChanged(prop); - } -} - -void ViewProviderSpline::showControlPoints(bool show, const App::Property* prop) -{ - if (!pcControlPoints && show) { - pcControlPoints = new SoSwitch(); - pcRoot->addChild(pcControlPoints); - } - - if (pcControlPoints) { - pcControlPoints->whichChild = (show ? SO_SWITCH_ALL : SO_SWITCH_NONE); - } - - if (!show || !pcControlPoints || pcControlPoints->getNumChildren() > 0) - return; - - // ask for the property we are interested in - if (prop && prop->getTypeId() == Part::PropertyPartShape::getClassTypeId()) { - const TopoDS_Shape& shape = static_cast(prop)->getValue(); - if (shape.IsNull()) - return; // empty shape - - for (TopExp_Explorer xp(shape, TopAbs_SHELL); xp.More(); xp.Next()) { - const TopoDS_Shell& shell = TopoDS::Shell(xp.Current()); - for (TopExp_Explorer xp2(shell, TopAbs_FACE); xp2.More(); xp2.Next()) { - const TopoDS_Face& face = TopoDS::Face(xp2.Current()); - showControlPointsOfFace(face); - } - } - for (TopExp_Explorer xp(shape, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) { - const TopoDS_Face& face = TopoDS::Face(xp.Current()); - showControlPointsOfFace(face); - } - for (TopExp_Explorer xp(shape, TopAbs_WIRE, TopAbs_FACE); xp.More(); xp.Next()) { - const TopoDS_Wire& wire = TopoDS::Wire(xp.Current()); - for (TopExp_Explorer xp2(wire, TopAbs_EDGE); xp2.More(); xp2.Next()) { - const TopoDS_Edge& edge = TopoDS::Edge(xp2.Current()); - showControlPointsOfEdge(edge); - } - } - for (TopExp_Explorer xp(shape, TopAbs_EDGE, TopAbs_WIRE); xp.More(); xp.Next()) { - const TopoDS_Edge& edge = TopoDS::Edge(xp.Current()); - showControlPointsOfEdge(edge); - } - } -} - -void ViewProviderSpline::showControlPointsOfEdge(const TopoDS_Edge& edge) -{ - std::list poles, knots; - Standard_Integer nCt=0; - - TopoDS_Edge edge_loc(edge); - TopLoc_Location aLoc; - edge_loc.Location(aLoc); - - BRepAdaptor_Curve curve(edge_loc); - switch (curve.GetType()) - { - case GeomAbs_BezierCurve: - { - Handle(Geom_BezierCurve) hBezier = curve.Bezier(); - nCt = hBezier->NbPoles(); - for (Standard_Integer i = 1; i <= nCt; i++) - poles.push_back(hBezier->Pole(i)); - if (hBezier->IsClosed()) { - nCt++; - poles.push_back(hBezier->Pole(1)); - } - } break; - case GeomAbs_BSplineCurve: - { - Handle(Geom_BSplineCurve) hBSpline = curve.BSpline(); - nCt = hBSpline->NbPoles(); - for (Standard_Integer i = 1; i <= nCt; i++) - poles.push_back(hBSpline->Pole(i)); - if (hBSpline->IsClosed()) { - nCt++; - poles.push_back(hBSpline->Pole(1)); - } - for (Standard_Integer i = hBSpline->FirstUKnotIndex()+1; i <= hBSpline->LastUKnotIndex()-1; i++) - knots.push_back(hBSpline->Value(hBSpline->Knot(i))); - } break; - default: - break; - } - - if (poles.empty()) - return; // nothing to do - - SoCoordinate3 * controlcoords = new SoCoordinate3; - controlcoords->point.setNum(nCt + knots.size()); - - int index=0; - SbVec3f* verts = controlcoords->point.startEditing(); - for (std::list::iterator p = poles.begin(); p != poles.end(); ++p) { - verts[index++].setValue((float)p->X(), (float)p->Y(), (float)p->Z()); - } - for (std::list::iterator k = knots.begin(); k != knots.end(); ++k) { - verts[index++].setValue((float)k->X(), (float)k->Y(), (float)k->Z()); - } - controlcoords->point.finishEditing(); - - - SoFCControlPoints* controlpoints = new SoFCControlPoints(); - controlpoints->numPolesU = nCt; - controlpoints->numPolesV = 1; - - SoSeparator* nodes = new SoSeparator(); - nodes->addChild(controlcoords); - nodes->addChild(controlpoints); - - pcControlPoints->addChild(nodes); -} - -void ViewProviderSpline::showControlPointsOfFace(const TopoDS_Face& face) -{ - std::list knots; - std::vector > poles; - Standard_Integer nCtU=0, nCtV=0; - - TopoDS_Face face_loc(face); - TopLoc_Location aLoc; - face_loc.Location(aLoc); - - BRepAdaptor_Surface surface(face_loc); - switch (surface.GetType()) - { - case GeomAbs_BezierSurface: - { - Handle(Geom_BezierSurface) hBezier = surface.Bezier(); - nCtU = hBezier->NbUPoles(); - nCtV = hBezier->NbVPoles(); - poles.resize(nCtU); - for (Standard_Integer u = 1; u <= nCtU; u++) { - poles[u-1].resize(nCtV); - for (Standard_Integer v = 1; v <= nCtV; v++) - poles[u-1][v-1] = hBezier->Pole(u, v); - } - } break; - case GeomAbs_BSplineSurface: - { - Handle(Geom_BSplineSurface) hBSpline = surface.BSpline(); - nCtU = hBSpline->NbUPoles(); - nCtV = hBSpline->NbVPoles(); - poles.resize(nCtU); - for (Standard_Integer u = 1; u <= nCtU; u++) { - poles[u-1].resize(nCtV); - for (Standard_Integer v = 1; v <= nCtV; v++) - poles[u-1][v-1] = hBSpline->Pole(u, v); - } - - //Standard_Integer nKnU = hBSpline->NbUKnots(); - //Standard_Integer nKnV = hBSpline->NbVKnots(); - for (Standard_Integer u = 1; u <= hBSpline->NbUKnots(); u++) { - for (Standard_Integer v = 1; v <= hBSpline->NbVKnots(); v++) - knots.push_back(hBSpline->Value(hBSpline->UKnot(u), hBSpline->VKnot(v))); - } - } break; - default: - break; - } - - if (poles.empty()) - return; // nothing to do - - SoCoordinate3 * coords = new SoCoordinate3; - coords->point.setNum(nCtU * nCtV + knots.size()); - - int index=0; - SbVec3f* verts = coords->point.startEditing(); - for (std::vector >::iterator u = poles.begin(); u != poles.end(); ++u) { - for (std::vector::iterator v = u->begin(); v != u->end(); ++v) { - verts[index++].setValue((float)v->X(), (float)v->Y(), (float)v->Z()); - } - } - for (std::list::iterator k = knots.begin(); k != knots.end(); ++k) { - verts[index++].setValue((float)k->X(), (float)k->Y(), (float)k->Z()); - } - coords->point.finishEditing(); - - - SoFCControlPoints* control = new SoFCControlPoints(); - control->numPolesU = nCtU; - control->numPolesV = nCtV; - - //if (knots.size() > 0) { - // control->numKnotsU = nKnU; - // control->numKnotsV = nKnV; - //} - - SoSeparator* nodes = new SoSeparator(); - nodes->addChild(coords); - nodes->addChild(control); - - pcControlPoints->addChild(nodes); -} - // ---------------------------------------------------------------------------- EXTENSION_PROPERTY_SOURCE(PartGui::ViewProviderSplineExtension, Gui::ViewProviderExtension) diff --git a/src/Mod/Part/Gui/ViewProviderSpline.h b/src/Mod/Part/Gui/ViewProviderSpline.h index 6861a2cdfe..2786e9fe01 100644 --- a/src/Mod/Part/Gui/ViewProviderSpline.h +++ b/src/Mod/Part/Gui/ViewProviderSpline.h @@ -23,46 +23,19 @@ #ifndef PARTGUI_VIEWPROVIDERPARTSPLINE_H #define PARTGUI_VIEWPROVIDERPARTSPLINE_H -#include "ViewProviderExt.h" +#include #include namespace PartGui { -class PartGuiExport ViewProviderSpline : public ViewProviderPartExt -{ - PROPERTY_HEADER(PartGui::ViewProviderSpline); - -public: - /// constructor - ViewProviderSpline(); - /// destructor - virtual ~ViewProviderSpline(); - - // Display properties - App::PropertyBool ControlPoints; - - QIcon getIcon(void) const; - void updateData(const App::Property* prop); - void setupContextMenu(QMenu* menu, QObject* receiver, const char* member); - -protected: - void onChanged(const App::Property* prop); - void toggleControlPoints(bool); - void showControlPoints(bool, const App::Property* prop); - void showControlPointsOfEdge(const TopoDS_Edge&); - void showControlPointsOfFace(const TopoDS_Face&); - - SoSwitch *pcControlPoints; -}; - class PartGuiExport ViewProviderSplineExtension : public Gui::ViewProviderExtension { EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(PartGui::ViewProviderSplineExtension); public: /// Constructor - ViewProviderSplineExtension(void); + ViewProviderSplineExtension(); virtual ~ViewProviderSplineExtension() = default; App::PropertyBool ControlPoints; @@ -80,6 +53,22 @@ protected: SoSwitch *pcControlPoints; }; +class PartGuiExport ViewProviderSpline : public ViewProviderPartExt +{ + PROPERTY_HEADER(PartGui::ViewProviderSpline); + +public: + /// constructor + ViewProviderSpline(); + /// destructor + virtual ~ViewProviderSpline(); + + QIcon getIcon() const; + +private: + ViewProviderSplineExtension extension; +}; + typedef Gui::ViewProviderExtensionPythonT ViewProviderSplineExtensionPython; } //namespace PartGui From 580a52f75cc765392a6cd30bcaf5c6b0e6f10db5 Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 27 Oct 2021 14:28:25 -0400 Subject: [PATCH 16/68] Draft: Fix superfluous whitespace in translations + misc. typos --- src/Mod/Draft/WorkingPlane.py | 18 +++++++++--------- src/Mod/Draft/draftmake/make_sketch.py | 8 ++++---- src/Mod/Draft/draftobjects/array.py | 4 ++-- src/Mod/Draft/draftobjects/dimension.py | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 3e130699dc..401cc4e055 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -652,14 +652,14 @@ class Plane: if not geom_is_shape: FreeCAD.Console.PrintError(translate( "draft", - "Object without Part.Shape geometry:'{}'\n".format( - obj.ObjectName))) + "Object without Part.Shape geometry:'{}".format( + obj.ObjectName)) + "\n") return False if geom.isNull(): FreeCAD.Console.PrintError(translate( "draft", - "Object with null Part.Shape geometry:'{}'\n".format( - obj.ObjectName))) + "Object with null Part.Shape geometry:'{}".format( + obj.ObjectName)) + "\n") return False if obj.HasSubObjects: shapes.extend(obj.SubObjects) @@ -672,7 +672,7 @@ class Plane: for n in range(len(shapes)): if not DraftGeomUtils.is_planar(shapes[n]): FreeCAD.Console.PrintError(translate( - "draft","'{}' object is not planar\n".format(names[n]))) + "draft", "'{}' object is not planar".format(names[n])) + "\n") return False if not normal: normal = DraftGeomUtils.get_normal(shapes[n]) @@ -683,8 +683,8 @@ class Plane: for n in range(len(shapes)): if not DraftGeomUtils.are_coplanar(shapes[shape_ref], shapes[n]): FreeCAD.Console.PrintError(translate( - "draft","{} and {} aren't coplanar\n".format( - names[shape_ref],names[n]))) + "draft", "{} and {} aren't coplanar".format( + names[shape_ref],names[n])) + "\n") return False else: # suppose all geometries are straight lines or points @@ -693,7 +693,7 @@ class Plane: poly = Part.makePolygon(points) if not DraftGeomUtils.is_planar(poly): FreeCAD.Console.PrintError(translate( - "draft","All Shapes must be coplanar\n")) + "draft", "All Shapes must be coplanar") + "\n") return False normal = DraftGeomUtils.get_normal(poly) else: @@ -701,7 +701,7 @@ class Plane: if not normal: FreeCAD.Console.PrintError(translate( - "draft","Selected Shapes must define a plane\n")) + "draft", "Selected Shapes must define a plane") + "\n") return False # set center of mass diff --git a/src/Mod/Draft/draftmake/make_sketch.py b/src/Mod/Draft/draftmake/make_sketch.py index 52d6fde7e1..f897918e07 100644 --- a/src/Mod/Draft/draftmake/make_sketch.py +++ b/src/Mod/Draft/draftmake/make_sketch.py @@ -100,13 +100,13 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if isinstance(obj,Part.Shape): shape = obj elif not hasattr(obj,'Shape'): - App.Console.PrintError(translate("draft","No shape found\n")) + App.Console.PrintError(translate("draft", "No shape found") + '\n') return None else: shape = obj.Shape if not DraftGeomUtils.is_planar(shape, tol): - App.Console.PrintError(translate("draft","All Shapes must be planar\n")) + App.Console.PrintError(translate("draft", "All Shapes must be planar") + '\n') return None if DraftGeomUtils.get_normal(shape, tol): @@ -121,7 +121,7 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if len(shape_norm_yes) >= 1: for shape in shapes_list[1:]: if not DraftGeomUtils.are_coplanar(shapes_list[0], shape, tol): - App.Console.PrintError(translate("draft","All Shapes must be coplanar\n")) + App.Console.PrintError(translate("draft", "All Shapes must be coplanar") + '\n') return None # define sketch normal normal = DraftGeomUtils.get_normal(shapes_list[0], tol) @@ -132,7 +132,7 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if len(points) >= 2: poly = Part.makePolygon(points) if not DraftGeomUtils.is_planar(poly, tol): - App.Console.PrintError(translate("draft","All Shapes must be coplanar\n")) + App.Console.PrintError(translate("draft","All Shapes must be coplanar") + '\n') return None normal = DraftGeomUtils.get_normal(poly, tol) if not normal: diff --git a/src/Mod/Draft/draftobjects/array.py b/src/Mod/Draft/draftobjects/array.py index 946d474804..8292c60751 100644 --- a/src/Mod/Draft/draftobjects/array.py +++ b/src/Mod/Draft/draftobjects/array.py @@ -287,7 +287,7 @@ class Array(DraftLink): _tip = QT_TRANSLATE_NOOP("App::Property", "A parameter that determines " "how many symmetry planes " - " the circular array will have.") + "the circular array will have.") obj.addProperty("App::PropertyInteger", "Symmetry", "Circular array", @@ -380,7 +380,7 @@ class Array(DraftLink): obj.setPropertyStatus(pr, "Hidden") def execute(self, obj): - """Execture when the object is created or recomputed.""" + """Execute when the object is created or recomputed.""" if not obj.Base: return diff --git a/src/Mod/Draft/draftobjects/dimension.py b/src/Mod/Draft/draftobjects/dimension.py index a7143a655b..bc4bcbecdb 100644 --- a/src/Mod/Draft/draftobjects/dimension.py +++ b/src/Mod/Draft/draftobjects/dimension.py @@ -163,7 +163,7 @@ class DimensionBase(DraftAnnotation): "There are various possibilities:\n" "- An object, and one of its edges.\n" "- An object, and two of its vertices.\n" - "- An arc object, and its edge.\n") + "- An arc object, and its edge.") obj.addProperty("App::PropertyLinkSubList", "LinkedGeometry", "Dimension", From 4dcc03cc7274c31bafd349c220c19d311fbd55da Mon Sep 17 00:00:00 2001 From: luzpaz Date: Thu, 28 Oct 2021 10:17:31 -0400 Subject: [PATCH 17/68] Add requested revision by @chennes Co-authored-by: Chris Hennes --- src/Mod/Draft/draftmake/make_sketch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftmake/make_sketch.py b/src/Mod/Draft/draftmake/make_sketch.py index f897918e07..5a007ffbb1 100644 --- a/src/Mod/Draft/draftmake/make_sketch.py +++ b/src/Mod/Draft/draftmake/make_sketch.py @@ -132,7 +132,7 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if len(points) >= 2: poly = Part.makePolygon(points) if not DraftGeomUtils.is_planar(poly, tol): - App.Console.PrintError(translate("draft","All Shapes must be coplanar") + '\n') + App.Console.PrintError(translate("draft", "All Shapes must be coplanar") + '\n') return None normal = DraftGeomUtils.get_normal(poly, tol) if not normal: From f742cd3c209369c9c7f4836f44c9399ce608aa48 Mon Sep 17 00:00:00 2001 From: luz paz Date: Thu, 28 Oct 2021 10:29:18 -0400 Subject: [PATCH 18/68] Refined code formatting for uniformity --- src/Mod/Draft/draftmake/make_sketch.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftmake/make_sketch.py b/src/Mod/Draft/draftmake/make_sketch.py index 5a007ffbb1..b136c944bc 100644 --- a/src/Mod/Draft/draftmake/make_sketch.py +++ b/src/Mod/Draft/draftmake/make_sketch.py @@ -100,13 +100,15 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if isinstance(obj,Part.Shape): shape = obj elif not hasattr(obj,'Shape'): - App.Console.PrintError(translate("draft", "No shape found") + '\n') + App.Console.PrintError(translate("draft", + "No shape found")+"\n") return None else: shape = obj.Shape if not DraftGeomUtils.is_planar(shape, tol): - App.Console.PrintError(translate("draft", "All Shapes must be planar") + '\n') + App.Console.PrintError(translate("draft", + "All Shapes must be planar")+"\n") return None if DraftGeomUtils.get_normal(shape, tol): @@ -121,7 +123,8 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if len(shape_norm_yes) >= 1: for shape in shapes_list[1:]: if not DraftGeomUtils.are_coplanar(shapes_list[0], shape, tol): - App.Console.PrintError(translate("draft", "All Shapes must be coplanar") + '\n') + App.Console.PrintError(translate("draft", + "All Shapes must be coplanar")+"\n") return None # define sketch normal normal = DraftGeomUtils.get_normal(shapes_list[0], tol) @@ -132,7 +135,8 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, if len(points) >= 2: poly = Part.makePolygon(points) if not DraftGeomUtils.is_planar(poly, tol): - App.Console.PrintError(translate("draft", "All Shapes must be coplanar") + '\n') + App.Console.PrintError(translate("draft", + "All Shapes must be coplanar")+"\n") return None normal = DraftGeomUtils.get_normal(poly, tol) if not normal: From 30a3ccde46f474003b7a1717d0d27788cdc0b5d0 Mon Sep 17 00:00:00 2001 From: luzpaz Date: Fri, 29 Oct 2021 09:24:27 -0400 Subject: [PATCH 19/68] Add requested revision by @chennes Co-authored-by: Chris Hennes --- src/Mod/Draft/WorkingPlane.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 401cc4e055..fa209a0059 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -658,7 +658,7 @@ class Plane: if geom.isNull(): FreeCAD.Console.PrintError(translate( "draft", - "Object with null Part.Shape geometry:'{}".format( + "Object with null Part.Shape geometry:'{}'".format( obj.ObjectName)) + "\n") return False if obj.HasSubObjects: From b488071a55a3dcfa24f7f74626801b12e8733088 Mon Sep 17 00:00:00 2001 From: luzpaz Date: Fri, 29 Oct 2021 09:24:49 -0400 Subject: [PATCH 20/68] Add requested revision by @chennes Co-authored-by: Chris Hennes --- src/Mod/Draft/WorkingPlane.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index fa209a0059..b155d74c13 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -652,7 +652,7 @@ class Plane: if not geom_is_shape: FreeCAD.Console.PrintError(translate( "draft", - "Object without Part.Shape geometry:'{}".format( + "Object without Part.Shape geometry:'{}'".format( obj.ObjectName)) + "\n") return False if geom.isNull(): From 9e8516002b9ced0bada5064b2dc775d022adea73 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Oct 2021 22:28:57 +0200 Subject: [PATCH 21/68] Part: fixes #0004774: Datum plane or line is not available in sketch in another body via binder --- src/Mod/Part/App/Tools.cpp | 66 ++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 18 ++++++++ src/Mod/Part/Gui/ViewProviderExt.cpp | 10 ++++- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index d95e49eaf4..7c6792a2ef 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -25,6 +25,11 @@ # include # include # include +# include +# include +# include +# include +# include # include # include # include @@ -590,3 +595,64 @@ void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std:: } } } + +Handle (Poly_Triangulation) Part::Tools::triangulationOfFace(const TopoDS_Face& face) +{ + TopLoc_Location loc; + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(face, loc); + if (!mesh.IsNull()) + return mesh; + + // If no triangulation exists then the shape is probably infinite + BRepAdaptor_Surface adapt(face); + double u1 = adapt.FirstUParameter(); + double u2 = adapt.LastUParameter(); + double v1 = adapt.FirstVParameter(); + double v2 = adapt.LastVParameter(); + + // recreate a face with a clear boundary + u1 = std::max(-50.0, u1); + u2 = std::min( 50.0, u2); + v1 = std::max(-50.0, v1); + v2 = std::min( 50.0, v2); + + Handle(Geom_Surface) surface = BRep_Tool::Surface(face); + BRepBuilderAPI_MakeFace mkBuilder(surface, u1, u2, v1, v2 +#if OCC_VERSION_HEX >= 0x060502 + , Precision::Confusion() +#endif + ); + + TopoDS_Shape shape = mkBuilder.Shape(); + shape.Location(loc); + + BRepMesh_IncrementalMesh(shape, 0.1); + return BRep_Tool::Triangulation(TopoDS::Face(shape), loc); +} + +Handle(Poly_Polygon3D) Part::Tools::polygonOfEdge(const TopoDS_Edge& edge, TopLoc_Location& loc) +{ + BRepAdaptor_Curve adapt(edge); + double u = adapt.FirstParameter(); + double v = adapt.LastParameter(); + Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, loc); + if (!aPoly.IsNull() && !Precision::IsInfinite(u) && !Precision::IsInfinite(v)) + return aPoly; + + // recreate an edge with a clear range + u = std::max(-50.0, u); + v = std::min( 50.0, v); + + double uv; + Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, uv, uv); + + BRepBuilderAPI_MakeEdge mkBuilder(curve, u, v); + TopoDS_Shape shape = mkBuilder.Shape(); + // why do we have to set the inverted location here? + TopLoc_Location inv = loc.Inverted(); + shape.Location(inv); + + BRepMesh_IncrementalMesh(shape, 0.1); + TopLoc_Location tmp; + return BRep_Tool::Polygon3D(TopoDS::Edge(shape), tmp); +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 425032a12d..3bb543804e 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include class gp_Lin; class gp_Pln; @@ -177,6 +179,22 @@ public: * \param normals */ static void applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals); + /*! + * \brief triangulationOfInfinite + * Returns the triangulation of the face of the tessellated shape. In case the face has infinite lengths + * the triangulation of a limited parameter range is computed. + * \param edge + * \param loc + */ + static Handle (Poly_Triangulation) triangulationOfFace(const TopoDS_Face& face); + /*! + * \brief polygonOfEdge + * Returns the polygon of the edge of the tessellated shape. In case the edge has infinite length + * the polygon of a limited parameter range is computed. + * \param edge + * \param loc + */ + static Handle(Poly_Polygon3D) polygonOfEdge(const TopoDS_Edge& edge, TopLoc_Location& loc); }; } //namespace Part diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index daf355e909..b5025dee0c 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -985,6 +985,9 @@ void ViewProviderPartExt::updateVisual() TopExp::MapShapes(cShape, TopAbs_FACE, faceMap); for (int i=1; i <= faceMap.Extent(); i++) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(faceMap(i)), aLoc); + if (mesh.IsNull()) { + mesh = Part::Tools::triangulationOfFace(TopoDS::Face(faceMap(i))); + } // Note: we must also count empty faces if (!mesh.IsNull()) { numTriangles += mesh->NbTriangles(); @@ -1024,7 +1027,7 @@ void ViewProviderPartExt::updateVisual() // a free edge. int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); + Handle(Poly_Polygon3D) aPoly = Part::Tools::polygonOfEdge(aEdge, aLoc); if (!aPoly.IsNull()) { int nbNodesInEdge = aPoly->NbNodes(); numNodes += nbNodesInEdge; @@ -1058,6 +1061,9 @@ void ViewProviderPartExt::updateVisual() const TopoDS_Face &actFace = TopoDS::Face(faceMap(i)); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); + if (mesh.IsNull()) { + mesh = Part::Tools::triangulationOfFace(actFace); + } if (mesh.IsNull()) { parts[ii] = 0; continue; @@ -1220,7 +1226,7 @@ void ViewProviderPartExt::updateVisual() // handling of the free edge that are not associated to a face int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); + Handle(Poly_Polygon3D) aPoly = Part::Tools::polygonOfEdge(aEdge, aLoc); if (!aPoly.IsNull()) { if (!aLoc.IsIdentity()) { identity = false; From a3a7b5a6a660b55931424598ecc0d1cb183cc402 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 31 Oct 2021 12:33:48 +0100 Subject: [PATCH 22/68] PD: [skip ci] if no active body exists then by default pre-select the first option to create a new body --- src/Mod/PartDesign/Gui/DlgActiveBody.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Mod/PartDesign/Gui/DlgActiveBody.cpp b/src/Mod/PartDesign/Gui/DlgActiveBody.cpp index aa916d6208..9aeb1b6c36 100644 --- a/src/Mod/PartDesign/Gui/DlgActiveBody.cpp +++ b/src/Mod/PartDesign/Gui/DlgActiveBody.cpp @@ -74,6 +74,14 @@ DlgActiveBody::DlgActiveBody(QWidget *parent, App::Document*& doc, // TODO: Any other logic (hover, select effects on view etc.) } + + if (!bodyOfActiveObject) { + // by default select the first item so that the user + // can continue by clicking Ok without further action + QListWidgetItem* first = ui->bodySelect->item(0); + if (first) + first->setSelected(true); + } } void DlgActiveBody::accept() From 9a7bf3abffb7043b706cde699496d61d15ca7a77 Mon Sep 17 00:00:00 2001 From: Jose Luis Cercos-Pita Date: Sun, 31 Oct 2021 23:29:31 +0100 Subject: [PATCH 23/68] Prefer QtWebEngine over QtWebKit --- cMake/FreeCAD_Helpers/SetupQt.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cMake/FreeCAD_Helpers/SetupQt.cmake b/cMake/FreeCAD_Helpers/SetupQt.cmake index 1e5519fe23..230d4198a0 100644 --- a/cMake/FreeCAD_Helpers/SetupQt.cmake +++ b/cMake/FreeCAD_Helpers/SetupQt.cmake @@ -23,9 +23,9 @@ if(BUILD_GUI) elseif(${FREECAD_USE_QTWEBMODULE} MATCHES "Qt WebEngine") find_package(Qt5WebEngineWidgets REQUIRED) else() # Automatic - find_package(Qt5WebKitWidgets QUIET) - if(NOT Qt5WebKitWidgets_FOUND) - find_package(Qt5WebEngineWidgets REQUIRED) + find_package(Qt5WebEngineWidgets QUIET) + if(NOT Qt5WebEngineWidgets_FOUND) + find_package(Qt5WebKitWidgets REQUIRED) endif() endif() endif() From ba2459cddc14f60d459909406789d0471f0030f6 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sun, 31 Oct 2021 23:38:11 -0500 Subject: [PATCH 24/68] [Spreadsheet] Fix missing header context menu --- src/Mod/Spreadsheet/Gui/SheetTableView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp index 634a30e815..e65365c3eb 100644 --- a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp @@ -163,8 +163,8 @@ SheetTableView::SheetTableView(QWidget *parent) auto cellProperties = new QAction(tr("Properties..."), this); addAction(cellProperties); - horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu); - verticalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu); + horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); + verticalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); contextMenu = new QMenu(this); From 13ba2242dee53c5c5d8d390703bde78f4a1413be Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 1 Nov 2021 14:47:26 +0100 Subject: [PATCH 25/68] Gui: [skip ci] allow to set edit mode in cmdSetEdit() --- src/Gui/CommandT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Gui/CommandT.h b/src/Gui/CommandT.h index 64154d8cca..a73095e3fd 100644 --- a/src/Gui/CommandT.h +++ b/src/Gui/CommandT.h @@ -279,11 +279,11 @@ inline void cmdAppObjectShow(const App::DocumentObject* obj) { * in-place editing an object, which may be brought in through linking to an * external group. */ -inline void cmdSetEdit(const App::DocumentObject* obj) { +inline void cmdSetEdit(const App::DocumentObject* obj, int mod = 0) { if (obj && obj->getNameInDocument()) { Gui::Command::doCommand(Gui::Command::Gui, - "Gui.ActiveDocument.setEdit(App.getDocument('%s').getObject('%s'))", - obj->getDocument()->getName(), obj->getNameInDocument()); + "Gui.ActiveDocument.setEdit(App.getDocument('%s').getObject('%s'), %d)", + obj->getDocument()->getName(), obj->getNameInDocument(), mod); } } From 833868bd1394862f6fab079fa74685f09675129a Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 1 Nov 2021 19:32:21 +0100 Subject: [PATCH 26/68] Path: [skip ci] partially fix issue 0004765: [MSVC][Build][Permissive-][std:c++latest] FreeCAD failed to build on MSVC --- src/Mod/Path/App/Area.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 11f11fc63f..d91652788f 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -1230,7 +1230,7 @@ int Area::project(TopoDS_Shape &shape_out, const TopoDS_Shape *work_plane) { FC_TIME_INIT2(t,t1); - Handle_HLRBRep_Algo brep_hlr = NULL; + Handle_HLRBRep_Algo brep_hlr; gp_Dir dir(0,0,1); try { brep_hlr = new HLRBRep_Algo(); From 9def811a3a492849d673fce88b9fd9d3c53b5ae1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Nov 2021 12:57:54 +0100 Subject: [PATCH 27/68] Gui: [skip ci] expose function to Python to enable/disable context-menu of 3d view --- src/Gui/View3DPy.cpp | 19 +++++++++++++++++++ src/Gui/View3DPy.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/Gui/View3DPy.cpp b/src/Gui/View3DPy.cpp index 2ca90e415f..0576eae5da 100644 --- a/src/Gui/View3DPy.cpp +++ b/src/Gui/View3DPy.cpp @@ -115,6 +115,8 @@ void View3DInventorPy::init_type() add_varargs_method("stopAnimating",&View3DInventorPy::stopAnimating,"stopAnimating()"); add_varargs_method("setAnimationEnabled",&View3DInventorPy::setAnimationEnabled,"setAnimationEnabled()"); add_varargs_method("isAnimationEnabled",&View3DInventorPy::isAnimationEnabled,"isAnimationEnabled()"); + add_varargs_method("setPopupMenuEnabled",&View3DInventorPy::setPopupMenuEnabled,"setPopupMenuEnabled()"); + add_varargs_method("isPopupMenuEnabled",&View3DInventorPy::isPopupMenuEnabled,"isPopupMenuEnabled()"); add_varargs_method("dump",&View3DInventorPy::dump,"dump(filename, [onlyVisible=False])"); add_varargs_method("dumpNode",&View3DInventorPy::dumpNode,"dumpNode(node)"); add_varargs_method("setStereoType",&View3DInventorPy::setStereoType,"setStereoType()"); @@ -953,6 +955,23 @@ Py::Object View3DInventorPy::isAnimationEnabled(const Py::Tuple& args) return Py::Boolean(ok ? true : false); } +Py::Object View3DInventorPy::setPopupMenuEnabled(const Py::Tuple& args) +{ + int ok; + if (!PyArg_ParseTuple(args.ptr(), "i", &ok)) + throw Py::Exception(); + _view->getViewer()->setPopupMenuEnabled(ok!=0); + return Py::None(); +} + +Py::Object View3DInventorPy::isPopupMenuEnabled(const Py::Tuple& args) +{ + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + SbBool ok = _view->getViewer()->isPopupMenuEnabled(); + return Py::Boolean(ok ? true : false); +} + Py::Object View3DInventorPy::saveImage(const Py::Tuple& args) { char *cFileName,*cColor="Current",*cComment="$MIBA"; diff --git a/src/Gui/View3DPy.h b/src/Gui/View3DPy.h index 71e2557bad..d84c073c34 100644 --- a/src/Gui/View3DPy.h +++ b/src/Gui/View3DPy.h @@ -87,6 +87,8 @@ public: Py::Object stopAnimating(const Py::Tuple&); Py::Object setAnimationEnabled(const Py::Tuple&); Py::Object isAnimationEnabled(const Py::Tuple&); + Py::Object setPopupMenuEnabled(const Py::Tuple&); + Py::Object isPopupMenuEnabled(const Py::Tuple&); Py::Object dump(const Py::Tuple&); Py::Object dumpNode(const Py::Tuple&); Py::Object setStereoType(const Py::Tuple&); From 1c93d3ee15eb7a161143a114aab8439b0ebd2bc4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Nov 2021 14:52:22 +0100 Subject: [PATCH 28/68] Gui: [skip ci] add method NavigationStyle::syncModifierKeys() to reduce code duplication --- src/Gui/BlenderNavigationStyle.cpp | 10 +--------- src/Gui/CADNavigationStyle.cpp | 10 +--------- src/Gui/GestureNavigationStyle.cpp | 5 ++--- src/Gui/InventorNavigationStyle.cpp | 10 +--------- src/Gui/MayaGestureNavigationStyle.cpp | 4 +--- src/Gui/NavigationStyle.cpp | 15 +++++++++++++++ src/Gui/NavigationStyle.h | 1 + src/Gui/OpenCascadeNavigationStyle.cpp | 10 +--------- src/Gui/OpenSCADNavigationStyle.cpp | 10 +--------- src/Gui/RevitNavigationStyle.cpp | 10 +--------- src/Gui/TouchpadNavigationStyle.cpp | 10 +--------- 11 files changed, 26 insertions(+), 69 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index b5b0cfbc42..7e10aa9e77 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -107,15 +107,7 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index cd8067abb3..c973e56a3d 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -111,15 +111,7 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { diff --git a/src/Gui/GestureNavigationStyle.cpp b/src/Gui/GestureNavigationStyle.cpp index 98a1e3e2a7..7d0732ae54 100644 --- a/src/Gui/GestureNavigationStyle.cpp +++ b/src/Gui/GestureNavigationStyle.cpp @@ -918,9 +918,8 @@ SbBool GestureNavigationStyle::processSoEvent(const SoEvent* const ev) //whatever else, we don't track } } - this->ctrldown = ev->wasCtrlDown(); - this->shiftdown = ev->wasShiftDown(); - this->altdown = ev->wasAltDown(); + + syncModifierKeys(ev); smev.modifiers = (this->button1down ? NS::Event::BUTTON1DOWN : 0) | diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 74062c51b8..2aaad878ff 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -115,15 +115,7 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { diff --git a/src/Gui/MayaGestureNavigationStyle.cpp b/src/Gui/MayaGestureNavigationStyle.cpp index dbb5815a6c..2a34f062e5 100644 --- a/src/Gui/MayaGestureNavigationStyle.cpp +++ b/src/Gui/MayaGestureNavigationStyle.cpp @@ -190,9 +190,7 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - this->ctrldown = ev->wasCtrlDown(); - this->shiftdown = ev->wasShiftDown(); - this->altdown = ev->wasAltDown(); + syncModifierKeys(ev); //before this block, mouse button states in NavigationStyle::buttonXdown reflected those before current event arrived. //track mouse button states if (evIsButton) { diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index 43a4a73045..c923f142ea 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1372,6 +1372,21 @@ void NavigationStyle::clearLog(void) this->log.historysize = 0; } +void NavigationStyle::syncModifierKeys(const SoEvent * const ev) +{ + // Mismatches in state of the modifier keys happens if the user + // presses or releases them outside the viewer window. + if (this->ctrldown != ev->wasCtrlDown()) { + this->ctrldown = ev->wasCtrlDown(); + } + if (this->shiftdown != ev->wasShiftDown()) { + this->shiftdown = ev->wasShiftDown(); + } + if (this->altdown != ev->wasAltDown()) { + this->altdown = ev->wasAltDown(); + } +} + // The viewer is a state machine, and all changes to the current state // are made through this call. void NavigationStyle::setViewingMode(const ViewerMode newmode) diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 659d8f9e03..959500a102 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -213,6 +213,7 @@ protected: void clearLog(void); void addToLog(const SbVec2s pos, const SbTime time); + void syncModifierKeys(const SoEvent * const ev); protected: struct { // tracking mouse movement in a log diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index b554327b66..6f6fa816d4 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -107,15 +107,7 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 0148e46eb3..6106d4eb14 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -107,15 +107,7 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index 977d0c01a2..289af98f9b 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -107,15 +107,7 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index 7b279eefc4..d039c54de9 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -107,15 +107,7 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // give the nodes in the foreground root the chance to handle events (e.g color bar) if (!viewer->isEditing()) { From 0b802eb71742d37ac72e33068e5c5eedc3215556 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Nov 2021 15:32:20 +0100 Subject: [PATCH 29/68] Gui: [skip ci] add method NavigationStyle::handleKeyboardEvent() to achieve consistent handling and reduce code duplication --- src/Gui/BlenderNavigationStyle.cpp | 37 ++----------------- src/Gui/CADNavigationStyle.cpp | 33 ++--------------- src/Gui/InventorNavigationStyle.cpp | 33 ++--------------- src/Gui/NavigationStyle.cpp | 49 ++++++++++++++++++++++++++ src/Gui/NavigationStyle.h | 1 + src/Gui/OpenCascadeNavigationStyle.cpp | 33 ++--------------- src/Gui/OpenSCADNavigationStyle.cpp | 33 ++--------------- src/Gui/RevitNavigationStyle.cpp | 33 ++--------------- src/Gui/TouchpadNavigationStyle.cpp | 41 ++------------------- 9 files changed, 64 insertions(+), 229 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index 7e10aa9e77..b67e8ee6e5 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -118,41 +118,8 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::R: - processed = true; - viewer->resetToHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index c973e56a3d..8b2c690bec 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -122,37 +122,8 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 2aaad878ff..27fdb07399 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -126,37 +126,8 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index c923f142ea..dc66d74beb 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1387,6 +1387,55 @@ void NavigationStyle::syncModifierKeys(const SoEvent * const ev) } } +SbBool NavigationStyle::handleKeyboardEvent(const SoKeyboardEvent * const event, const SbVec2f & posn) +{ + SbBool processed = false; + const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; + switch (event->getKey()) { + case SoKeyboardEvent::LEFT_CONTROL: + case SoKeyboardEvent::RIGHT_CONTROL: + this->ctrldown = press; + break; + case SoKeyboardEvent::LEFT_SHIFT: + case SoKeyboardEvent::RIGHT_SHIFT: + this->shiftdown = press; + break; + case SoKeyboardEvent::LEFT_ALT: + case SoKeyboardEvent::RIGHT_ALT: + this->altdown = press; + break; + case SoKeyboardEvent::H: + processed = true; + viewer->saveHomePosition(); + break; + case SoKeyboardEvent::R: + processed = true; + viewer->resetToHomePosition(); + break; + case SoKeyboardEvent::S: + case SoKeyboardEvent::HOME: + case SoKeyboardEvent::LEFT_ARROW: + case SoKeyboardEvent::UP_ARROW: + case SoKeyboardEvent::RIGHT_ARROW: + case SoKeyboardEvent::DOWN_ARROW: + if (!this->isViewing()) + this->setViewing(true); + break; + case SoKeyboardEvent::PAGE_UP: + processed = true; + doZoom(viewer->getSoRenderManager()->getCamera(), getDelta(), posn); + break; + case SoKeyboardEvent::PAGE_DOWN: + processed = true; + doZoom(viewer->getSoRenderManager()->getCamera(), -getDelta(), posn); + break; + default: + break; + } + + return processed; +} + // The viewer is a state machine, and all changes to the current state // are made through this call. void NavigationStyle::setViewingMode(const ViewerMode newmode) diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 959500a102..5f394c550b 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -214,6 +214,7 @@ protected: void addToLog(const SbVec2s pos, const SbTime time); void syncModifierKeys(const SoEvent * const ev); + SbBool handleKeyboardEvent(const SoKeyboardEvent * const event, const SbVec2f & posn); protected: struct { // tracking mouse movement in a log diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index 6f6fa816d4..376247f83d 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -118,37 +118,8 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 6106d4eb14..4df1eefbe7 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -118,37 +118,8 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index 289af98f9b..df547cd44c 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -118,37 +118,8 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index d039c54de9..4ee5b53e07 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -118,45 +118,8 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { - const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - case SoKeyboardEvent::PAGE_UP: - doZoom(viewer->getSoRenderManager()->getCamera(), getDelta(), posn); - processed = true; - break; - case SoKeyboardEvent::PAGE_DOWN: - doZoom(viewer->getSoRenderManager()->getCamera(), -getDelta(), posn); - processed = true; - break; - default: - break; - } + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); } // Mouse Button / Spaceball Button handling From bec3c797a87c561eb183923797033e935d635474 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Nov 2021 15:57:54 +0100 Subject: [PATCH 30/68] Gui: [skip ci] add method NavigationStyle::getNormalizedPosition() to reduce code duplication --- src/Gui/BlenderNavigationStyle.cpp | 8 +++----- src/Gui/CADNavigationStyle.cpp | 8 +++----- src/Gui/InventorNavigationStyle.cpp | 8 +++----- src/Gui/NavigationStyle.cpp | 10 ++++++++++ src/Gui/NavigationStyle.h | 1 + src/Gui/OpenCascadeNavigationStyle.cpp | 8 +++----- src/Gui/OpenSCADNavigationStyle.cpp | 8 +++----- src/Gui/RevitNavigationStyle.cpp | 8 +++----- src/Gui/TouchpadNavigationStyle.cpp | 8 +++----- 9 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index b67e8ee6e5..b7b6fc1759 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -88,13 +88,11 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index 8b2c690bec..17a590933e 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -92,13 +92,11 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 27fdb07399..1a46fe8439 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -96,13 +96,11 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index dc66d74beb..0a38a210f9 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1372,6 +1372,16 @@ void NavigationStyle::clearLog(void) this->log.historysize = 0; } +SbVec2f NavigationStyle::getNormalizedPosition(const SoEvent * const ev, + const SbViewportRegion & vpRgn) const +{ + const SbVec2s size(vpRgn.getViewportSizePixels()); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), + (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + return posn; +} + void NavigationStyle::syncModifierKeys(const SoEvent * const ev) { // Mismatches in state of the modifier keys happens if the user diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 5f394c550b..af68928008 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -213,6 +213,7 @@ protected: void clearLog(void); void addToLog(const SbVec2s pos, const SbTime time); + SbVec2f getNormalizedPosition(const SoEvent * const ev, const SbViewportRegion & vpRgn) const; void syncModifierKeys(const SoEvent * const ev); SbBool handleKeyboardEvent(const SoKeyboardEvent * const event, const SbVec2f & posn); diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index 376247f83d..62abcebb9f 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -88,13 +88,11 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 4df1eefbe7..7b0c31682a 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -88,13 +88,11 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index df547cd44c..8510dec8f2 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -88,13 +88,11 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index 4ee5b53e07..50d4d69672 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -88,13 +88,11 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); - const SbVec2f prevnormalized = this->lastmouseposition; - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; + const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an From 60467908c8d84cff0d04e36379bdccdcb6f2b8f2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Nov 2021 16:06:21 +0100 Subject: [PATCH 31/68] Gui: [skip ci] code clean-up --- src/Gui/BlenderNavigationStyle.cpp | 16 +------- src/Gui/CADNavigationStyle.cpp | 51 +------------------------- src/Gui/OpenCascadeNavigationStyle.cpp | 4 +- src/Gui/RevitNavigationStyle.cpp | 17 +-------- src/Gui/TouchpadNavigationStyle.cpp | 3 -- 5 files changed, 4 insertions(+), 87 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index b7b6fc1759..c933d30dfb 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -136,10 +136,6 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) this->seekToPoint(pos); // implicitly calls interactiveCountInc() processed = true; } - //else if (press && (this->currentmode == NavigationStyle::IDLE)) { - // this->setViewing(true); - // processed = true; - //} else if (press && (this->currentmode == NavigationStyle::PANNING || this->currentmode == NavigationStyle::ZOOMING)) { newmode = NavigationStyle::DRAGGING; @@ -285,11 +281,6 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) this->lockButton1 = false; processed = true; } - - //if (curmode == NavigationStyle::DRAGGING) { - // if (doSpin()) - // newmode = NavigationStyle::SPINNING; - //} break; case BUTTON1DOWN: case CTRLDOWN|BUTTON1DOWN: @@ -311,9 +302,6 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) } newmode = NavigationStyle::DRAGGING; break; - //case BUTTON1DOWN|BUTTON2DOWN|BUTTON3DOWN: - // newmode = NavigationStyle::ZOOMING; - // break; case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN: case CTRLDOWN|BUTTON3DOWN: newmode = NavigationStyle::ZOOMING; @@ -335,10 +323,8 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) // If not handled in this class, pass on upwards in the inheritance // hierarchy. - if (/*(curmode == NavigationStyle::SELECTION || viewer->isEditing()) && */!processed) + if (!processed) processed = inherited::processSoEvent(ev); - else - return true; return processed; } diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index 17a590933e..a390e0ff3d 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -135,39 +135,11 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) case SoMouseButtonEvent::BUTTON1: this->lockrecenter = true; this->button1down = press; -#if 0 // disable to avoid interferences where this key combination is used, too - if (press && ev->wasShiftDown() && - (this->currentmode != NavigationStyle::SELECTION)) { - this->centerTime = ev->getTime(); - float ratio = vp.getViewportAspectRatio(); - SbViewVolume vv = viewer->getCamera()->getViewVolume(ratio); - this->panningplane = vv.getPlane(viewer->getCamera()->focalDistance.getValue()); - this->lockrecenter = false; - } - else if (!press && ev->wasShiftDown() && - (this->currentmode != NavigationStyle::SELECTION)) { - SbTime tmp = (ev->getTime() - this->centerTime); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // is it just a left click? - if (tmp.getValue() < dci && !this->lockrecenter) { - if (!this->moveToPoint(pos)) { - panToCenter(panningplane, posn); - this->interactiveCountDec(); - } - processed = true; - } - } - else -#endif if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) { newmode = NavigationStyle::SEEK_MODE; this->seekToPoint(pos); // implicitly calls interactiveCountInc() processed = true; } - //else if (press && (this->currentmode == NavigationStyle::IDLE)) { - // this->setViewing(true); - // processed = true; - //} else if (press && (this->currentmode == NavigationStyle::PANNING || this->currentmode == NavigationStyle::ZOOMING)) { newmode = NavigationStyle::DRAGGING; @@ -327,11 +299,6 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) this->lockButton1 = false; processed = true; } - - //if (curmode == NavigationStyle::DRAGGING) { - // if (doSpin()) - // newmode = NavigationStyle::SPINNING; - //} break; case BUTTON1DOWN: // make sure not to change the selection when stopping spinning @@ -364,16 +331,6 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN: newmode = NavigationStyle::ZOOMING; break; - //case CTRLDOWN: - //case CTRLDOWN|BUTTON1DOWN: - //case CTRLDOWN|SHIFTDOWN: - //case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN: - // newmode = NavigationStyle::SELECTION; - // break; - //case BUTTON1DOWN|BUTTON3DOWN: - //case CTRLDOWN|BUTTON3DOWN: - // newmode = NavigationStyle::ZOOMING; - // break; // There are many cases we don't handle that just falls through to // the default case, like SHIFTDOWN, CTRLDOWN, CTRLDOWN|SHIFTDOWN, @@ -385,10 +342,6 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) default: // The default will make a spin stop and otherwise not do // anything. - //if ((curmode != NavigationStyle::SEEK_WAIT_MODE) && - // (curmode != NavigationStyle::SEEK_MODE)) { - // newmode = NavigationStyle::IDLE; - //} break; } @@ -404,10 +357,8 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) // If not handled in this class, pass on upwards in the inheritance // hierarchy. - if (/*(curmode == NavigationStyle::SELECTION || viewer->isEditing()) && */!processed) + if (!processed) processed = inherited::processSoEvent(ev); - else - return true; return processed; } diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index 62abcebb9f..6b42b53003 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -303,10 +303,8 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) // If not handled in this class, pass on upwards in the inheritance // hierarchy. - if (/*(curmode == NavigationStyle::SELECTION || viewer->isEditing()) && */!processed) + if (!processed) processed = inherited::processSoEvent(ev); - else - return true; return processed; } diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index 8510dec8f2..0c22aeeffd 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -136,10 +136,6 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) this->seekToPoint(pos); // implicitly calls interactiveCountInc() processed = true; } - //else if (press && (this->currentmode == NavigationStyle::IDLE)) { - // this->setViewing(true); - // processed = true; - //} else if (press && (this->currentmode == NavigationStyle::PANNING || this->currentmode == NavigationStyle::ZOOMING)) { newmode = NavigationStyle::DRAGGING; @@ -283,11 +279,6 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) this->lockButton1 = false; processed = true; } - - //if (curmode == NavigationStyle::DRAGGING) { - // if (doSpin()) - // newmode = NavigationStyle::SPINNING; - //} break; case BUTTON1DOWN: case CTRLDOWN|BUTTON1DOWN: @@ -309,9 +300,6 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) } newmode = NavigationStyle::DRAGGING; break; - //case BUTTON1DOWN|BUTTON2DOWN|BUTTON3DOWN: - // newmode = NavigationStyle::ZOOMING; - // break; case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN: case CTRLDOWN|BUTTON3DOWN: newmode = NavigationStyle::ZOOMING; @@ -333,10 +321,7 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) // If not handled in this class, pass on upwards in the inheritance // hierarchy. - if (/*(curmode == NavigationStyle::SELECTION || viewer->isEditing()) && */!processed) + if (!processed) processed = inherited::processSoEvent(ev); - else - return true; - return processed; } diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index 50d4d69672..b6fd4b3df4 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -299,8 +299,5 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) // hierarchy. if (!processed) processed = inherited::processSoEvent(ev); - else - return true; - return processed; } From 0d511a6dd227b6d463c533e460657d7bd3380e7b Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Tue, 2 Nov 2021 10:10:28 -0500 Subject: [PATCH 32/68] Spreadsheet: Fix bug in content and alias lineedits The two line edit widgets above the spreadsheet, one for exiting the cell contents and one for editing the alias, were set to use the same editing widget as the individual spreadsheet cells. Once that widget was refactored to handle tab/enter behavior it was no longer the correct widget for those elements. This commit changes them to Gui::ExpressionLineEdit widgets instead, so that the Enter key works correctly for them again. --- src/Mod/Spreadsheet/Gui/Sheet.ui | 8 ++++---- src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/Sheet.ui b/src/Mod/Spreadsheet/Gui/Sheet.ui index 5704291d1e..68aa09998e 100644 --- a/src/Mod/Spreadsheet/Gui/Sheet.ui +++ b/src/Mod/Spreadsheet/Gui/Sheet.ui @@ -27,7 +27,7 @@ - + false @@ -44,7 +44,7 @@ - + false @@ -68,9 +68,9 @@ Spreadsheet.my_alias_name instead of Spreadsheet.B1
SheetTableView.h
- SpreadsheetGui::LineEdit + Gui::ExpressionLineEdit QLineEdit -
SpreadsheetView.h
+
Gui/ExpressionCompleter.h
diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp index 3d2056cb3f..df46121a19 100644 --- a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp @@ -99,10 +99,8 @@ SheetView::SheetView(Gui::Document *pcDocument, App::DocumentObject *docObj, QWi this, SLOT(rowResized(int, int, int))); connect(delegate, &SpreadsheetDelegate::finishedWithKey, this, &SheetView::editingFinishedWithKey); - connect(ui->cellContent, &LineEdit::finishedWithKey, this, [this](int, Qt::KeyboardModifiers) {confirmContentChanged(ui->cellContent->text()); }); - connect(ui->cellContent, &LineEdit::returnPressed, this, [this]() {confirmContentChanged(ui->cellContent->text()); }); - connect(ui->cellAlias, &LineEdit::finishedWithKey, this, [this](int, Qt::KeyboardModifiers) {confirmAliasChanged(ui->cellAlias->text()); }); - connect(ui->cellAlias, &LineEdit::returnPressed, this, [this]() {confirmAliasChanged(ui->cellAlias->text()); }); + connect(ui->cellContent, &ExpressionLineEdit::returnPressed, this, [this]() {confirmContentChanged(ui->cellContent->text()); }); + connect(ui->cellAlias, &ExpressionLineEdit::returnPressed, this, [this]() {confirmAliasChanged(ui->cellAlias->text()); }); connect(ui->cellAlias, &LineEdit::textEdited, this, &SheetView::aliasChanged); columnWidthChangedConnection = sheet->columnWidthChanged.connect(bind(&SheetView::resizeColumn, this, bp::_1, bp::_2)); From 7542673b00997a32692a3b80cbcc4430e5eb7899 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Tue, 2 Nov 2021 17:26:35 +0100 Subject: [PATCH 33/68] FEM: command module, fix regression in the regard of translation added with 5b52840ca5fdbb --- src/Mod/Fem/femcommands/commands.py | 432 ++++++++++++++++++++++------ 1 file changed, 341 insertions(+), 91 deletions(-) diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 782fffc61f..051be66cb3 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -31,17 +31,21 @@ __url__ = "https://www.freecadweb.org" import FreeCAD import FreeCADGui +from FreeCAD import Qt from .manager import CommandManager from femtools.femutils import is_of_type -# Python command definitions +# Python command definitions: # for C++ command definitions see src/Mod/Fem/Command.cpp # TODO, may be even more generic class creation # with type() and identifier instead of class for # the commands which add new document objects. # see https://www.python-course.eu/python3_classes_and_type.php +# Translation: +# some information in the regard of translation can be found in forum post +# https://forum.freecadweb.org/viewtopic.php?f=18&t=62449&p=543845#p543593 class _Analysis(CommandManager): @@ -49,9 +53,12 @@ class _Analysis(CommandManager): def __init__(self): super(_Analysis, self).__init__() - self.menutext = "Analysis container" + self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_Analysis", "Analysis container") self.accel = "S, A" - self.tooltip = "Creates an analysis container with standard solver CalculiX" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_Analysis", + "Creates an analysis container with standard solver CalculiX" + ) self.is_active = "with_document" def Activated(self): @@ -74,8 +81,11 @@ class _ClippingPlaneAdd(CommandManager): def __init__(self): super(_ClippingPlaneAdd, self).__init__() - self.menutext = "Clipping plane on face" - self.tooltip = "Add a clipping plane on a selected face" + self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_ClippingPlaneAdd", "Clipping plane on face") + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ClippingPlaneAdd", + "Add a clipping plane on a selected face" + ) self.is_active = "with_document" def Activated(self): @@ -123,8 +133,14 @@ class _ClippingPlaneRemoveAll(CommandManager): def __init__(self): super(_ClippingPlaneRemoveAll, self).__init__() - self.menutext = "Remove all clipping planes" - self.tooltip = "Remove all clipping planes" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ClippingPlaneRemoveAll", + "Remove all clipping planes" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ClippingPlaneRemoveAll", + "Remove all clipping planes" + ) self.is_active = "with_document" def Activated(self): @@ -143,8 +159,14 @@ class _ConstantVacuumPermittivity(CommandManager): def __init__(self): super(_ConstantVacuumPermittivity, self).__init__() self.pixmap = "fem-solver-analysis-thermomechanical.svg" - self.menutext = "Constant vacuum permittivity" - self.tooltip = "Creates a FEM constant vacuum permittivity to overwrite standard value" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstantVacuumPermittivity", + "Constant vacuum permittivity" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstantVacuumPermittivity", + "Creates a FEM constant vacuum permittivity to overwrite standard value" + ) self.is_active = "with_document" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -156,8 +178,14 @@ class _ConstraintBodyHeatSource(CommandManager): def __init__(self): super(_ConstraintBodyHeatSource, self).__init__() self.pixmap = "FEM_ConstraintHeatflux" # the heatflux icon is used - self.menutext = "Constraint body heat source" - self.tooltip = "Creates a FEM constraint body heat source" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintBodyHeatSource", + "Constraint body heat source" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintBodyHeatSource", + "Creates a FEM constraint body heat source" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -167,8 +195,14 @@ class _ConstraintCentrif(CommandManager): def __init__(self): super(_ConstraintCentrif, self).__init__() - self.menutext = "Constraint centrif" - self.tooltip = "Creates a FEM constraint centrif" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintCentrif", + "Constraint centrif" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintCentrif", + "Creates a FEM constraint centrif" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -178,8 +212,14 @@ class _ConstraintElectrostaticPotential(CommandManager): def __init__(self): super(_ConstraintElectrostaticPotential, self).__init__() - self.menutext = "Constraint electrostatic potential" - self.tooltip = "Creates a FEM constraint electrostatic potential" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintElectrostaticPotential", + "Constraint electrostatic potential" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintElectrostaticPotential", + "Creates a FEM constraint electrostatic potential" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -189,8 +229,14 @@ class _ConstraintFlowVelocity(CommandManager): def __init__(self): super(_ConstraintFlowVelocity, self).__init__() - self.menutext = "Constraint flow velocity" - self.tooltip = "Creates a FEM constraint flow velocity" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintFlowVelocity", + "Constraint flow velocity" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintFlowVelocity", + "Creates a FEM constraint flow velocity" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -200,8 +246,14 @@ class _ConstraintInitialFlowVelocity(CommandManager): def __init__(self): super(_ConstraintInitialFlowVelocity, self).__init__() - self.menutext = "Constraint initial flow velocity" - self.tooltip = "Creates a FEM constraint initial flow velocity" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintInitialFlowVelocity", + "Constraint initial flow velocity" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintInitialFlowVelocity", + "Creates a FEM constraint initial flow velocity" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -211,8 +263,14 @@ class _ConstraintSectionPrint(CommandManager): def __init__(self): super(_ConstraintSectionPrint, self).__init__() - self.menutext = "Constraint sectionprint" - self.tooltip = "Creates a FEM constraint sectionprint" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintSectionPrint", + "Constraint sectionprint" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintSectionPrint", + "Creates a FEM constraint sectionprint" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -222,8 +280,14 @@ class _ConstraintSelfWeight(CommandManager): def __init__(self): super(_ConstraintSelfWeight, self).__init__() - self.menutext = "Constraint self weight" - self.tooltip = "Creates a FEM constraint self weight" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintSelfWeight", + "Constraint self weight" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintSelfWeight", + "Creates a FEM constraint self weight" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -233,8 +297,14 @@ class _ConstraintTie(CommandManager): def __init__(self): super(_ConstraintTie, self).__init__() - self.menutext = "Constraint tie" - self.tooltip = "Creates a FEM constraint tie" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintTie", + "Constraint tie" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintTie", + "Creates a FEM constraint tie" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -244,8 +314,14 @@ class _ElementFluid1D(CommandManager): def __init__(self): super(_ElementFluid1D, self).__init__() - self.menutext = "Fluid section for 1D flow" - self.tooltip = "Creates a FEM fluid section for 1D flow" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementFluid1D", + "Fluid section for 1D flow" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementFluid1D", + "Creates a FEM fluid section for 1D flow" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -255,8 +331,14 @@ class _ElementGeometry1D(CommandManager): def __init__(self): super(_ElementGeometry1D, self).__init__() - self.menutext = "Beam cross section" - self.tooltip = "Creates a FEM beam cross section" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementGeometry1D", + "Beam cross section" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementGeometry1D", + "Creates a FEM beam cross section" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -266,8 +348,14 @@ class _ElementGeometry2D(CommandManager): def __init__(self): super(_ElementGeometry2D, self).__init__() - self.menutext = "Shell plate thickness" - self.tooltip = "Creates a FEM shell plate thickness" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementGeometry2D", + "Shell plate thickness" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementGeometry2D", + "Creates a FEM shell plate thickness" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -277,8 +365,14 @@ class _ElementRotation1D(CommandManager): def __init__(self): super(_ElementRotation1D, self).__init__() - self.menutext = "Beam rotation" - self.tooltip = "Creates a FEM beam rotation" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementRotation1D", + "Beam rotation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ElementRotation1D", + "Creates a FEM beam rotation" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -288,8 +382,14 @@ class _EquationElectrostatic(CommandManager): def __init__(self): super(_EquationElectrostatic, self).__init__() - self.menutext = "Electrostatic equation" - self.tooltip = "Creates a FEM equation for electrostatic" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationElectrostatic", + "Electrostatic equation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationElectrostatic", + "Creates a FEM equation for electrostatic" + ) self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -299,8 +399,14 @@ class _EquationElasticity(CommandManager): def __init__(self): super(_EquationElasticity, self).__init__() - self.menutext = "Elasticity equation" - self.tooltip = "Creates a FEM equation for elasticity" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationElasticity", + "Elasticity equation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationElasticity", + "Creates a FEM equation for elasticity" + ) self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -310,8 +416,14 @@ class _EquationFlow(CommandManager): def __init__(self): super(_EquationFlow, self).__init__() - self.menutext = "Flow equation" - self.tooltip = "Creates a FEM equation for flow" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationFlow", + "Flow equation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationFlow", + "Creates a FEM equation for flow" + ) self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -321,8 +433,14 @@ class _EquationFlux(CommandManager): def __init__(self): super(_EquationFlux, self).__init__() - self.menutext = "Flux equation" - self.tooltip = "Creates a FEM equation for flux" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationFlux", + "Flux equation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationFlux", + "Creates a FEM equation for flux" + ) self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -332,8 +450,14 @@ class _EquationElectricforce(CommandManager): def __init__(self): super(_EquationElectricforce, self).__init__() - self.menutext = "Electricforce equation" - self.tooltip = "Creates a FEM equation for electric forces" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationElectricforce", + "Electricforce equation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationElectricforce", + "Creates a FEM equation for electric forces" + ) self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -343,8 +467,14 @@ class _EquationHeat(CommandManager): def __init__(self): super(_EquationHeat, self).__init__() - self.menutext = "Heat equation" - self.tooltip = "Creates a FEM equation for heat" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationHeat", + "Heat equation" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_EquationHeat", + "Creates a FEM equation for heat" + ) self.is_active = "with_solver_elmer" self.do_activated = "add_obj_on_gui_selobj_noset_edit" @@ -355,8 +485,14 @@ class _Examples(CommandManager): def __init__(self): super(_Examples, self).__init__() self.pixmap = "FemWorkbench" - self.menutext = "Open FEM examples" - self.tooltip = "Open FEM examples" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_Examples", + "Open FEM examples" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_Examples", + "Open FEM examples" + ) self.is_active = "always" def Activated(self): @@ -370,8 +506,14 @@ class _MaterialEditor(CommandManager): def __init__(self): super(_MaterialEditor, self).__init__() self.pixmap = "Arch_Material_Group" - self.menutext = "Material editor" - self.tooltip = "Opens the FreeCAD material editor" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialEditor", + "Material editor" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialEditor", + "Opens the FreeCAD material editor" + ) self.is_active = "always" def Activated(self): @@ -384,8 +526,14 @@ class _MaterialFluid(CommandManager): def __init__(self): super(_MaterialFluid, self).__init__() - self.menutext = "Material for fluid" - self.tooltip = "Creates a FEM material for fluid" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialFluid", + "Material for fluid" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialFluid", + "Creates a FEM material for fluid" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -395,8 +543,14 @@ class _MaterialMechanicalNonlinear(CommandManager): def __init__(self): super(_MaterialMechanicalNonlinear, self).__init__() - self.menutext = "Nonlinear mechanical material" - self.tooltip = "Creates a nonlinear mechanical material" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialMechanicalNonlinear", + "Nonlinear mechanical material" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialMechanicalNonlinear", + "Creates a nonlinear mechanical material" + ) self.is_active = "with_material_solid" def Activated(self): @@ -459,8 +613,14 @@ class _MaterialReinforced(CommandManager): def __init__(self): super(_MaterialReinforced, self).__init__() - self.menutext = "Reinforced material (concrete)" - self.tooltip = "Creates a material for reinforced matrix material such as concrete" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialReinforced", + "Reinforced material (concrete)" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialReinforced", + "Creates a material for reinforced matrix material such as concrete" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -470,9 +630,15 @@ class _MaterialSolid(CommandManager): def __init__(self): super(_MaterialSolid, self).__init__() - self.menutext = "Material for solid" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialSolid", + "Material for solid" + ) self.accel = "M, S" - self.tooltip = "Creates a FEM material for solid" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MaterialSolid", + "Creates a FEM material for solid" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_set_edit" @@ -482,8 +648,14 @@ class _FEMMesh2Mesh(CommandManager): def __init__(self): super(_FEMMesh2Mesh, self).__init__() - self.menutext = "FEM mesh to mesh" - self.tooltip = "Convert the surface of a FEM mesh to a mesh" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_FEMMesh2Mesh", + "FEM mesh to mesh" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_FEMMesh2Mesh", + "Convert the surface of a FEM mesh to a mesh" + ) self.is_active = "with_femmesh_andor_res" def Activated(self): @@ -523,8 +695,14 @@ class _MeshBoundaryLayer(CommandManager): def __init__(self): super(_MeshBoundaryLayer, self).__init__() - self.menutext = "FEM mesh boundary layer" - self.tooltip = "Creates a FEM mesh boundary layer" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshBoundaryLayer", + "FEM mesh boundary layer" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshBoundaryLayer", + "Creates a FEM mesh boundary layer" + ) self.is_active = "with_gmsh_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" @@ -534,8 +712,14 @@ class _MeshClear(CommandManager): def __init__(self): super(_MeshClear, self).__init__() - self.menutext = "Clear FEM mesh" - self.tooltip = "Clear the Mesh of a FEM mesh object" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshClear", + "Clear FEM mesh" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshClear", + "Clear the Mesh of a FEM mesh object" + ) self.is_active = "with_femmesh" def Activated(self): @@ -553,8 +737,14 @@ class _MeshDisplayInfo(CommandManager): def __init__(self): super(_MeshDisplayInfo, self).__init__() - self.menutext = "Display FEM mesh info" - self.tooltip = "Display FEM mesh info" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshDisplayInfo", + "Display FEM mesh info" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshDisplayInfo", + "Display FEM mesh info" + ) self.is_active = "with_femmesh" def Activated(self): @@ -576,8 +766,14 @@ class _MeshGmshFromShape(CommandManager): def __init__(self): super(_MeshGmshFromShape, self).__init__() - self.menutext = "FEM mesh from shape by Gmsh" - self.tooltip = "Create a FEM mesh from a shape by Gmsh mesher" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshGmshFromShape", + "FEM mesh from shape by Gmsh" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshGmshFromShape", + "Create a FEM mesh from a shape by Gmsh mesher" + ) self.is_active = "with_part_feature" def Activated(self): @@ -615,8 +811,14 @@ class _MeshGroup(CommandManager): def __init__(self): super(_MeshGroup, self).__init__() - self.menutext = "FEM mesh group" - self.tooltip = "Creates a FEM mesh group" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshGroup", + "FEM mesh group" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshGroup", + "Creates a FEM mesh group" + ) self.is_active = "with_gmsh_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" @@ -626,8 +828,14 @@ class _MeshNetgenFromShape(CommandManager): def __init__(self): super(_MeshNetgenFromShape, self).__init__() - self.menutext = "FEM mesh from shape by Netgen" - self.tooltip = "Create a FEM mesh from a solid or face shape by Netgen internal mesher" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshNetgenFromShape", + "FEM mesh from shape by Netgen" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshNetgenFromShape", + "Create a FEM mesh from a solid or face shape by Netgen internal mesher" + ) self.is_active = "with_part_feature" def Activated(self): @@ -665,8 +873,14 @@ class _MeshRegion(CommandManager): def __init__(self): super(_MeshRegion, self).__init__() - self.menutext = "FEM mesh region" - self.tooltip = "Creates a FEM mesh region" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshRegion", + "FEM mesh region" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_MeshRegion", + "Creates a FEM mesh region" + ) self.is_active = "with_gmsh_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" @@ -676,9 +890,15 @@ class _ResultShow(CommandManager): def __init__(self): super(_ResultShow, self).__init__() - self.menutext = "Show result" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ResultShow", + "Show result" + ) self.accel = "R, S" - self.tooltip = "Shows and visualizes selected result data" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ResultShow", + "Shows and visualizes selected result data" + ) self.is_active = "with_selresult" def Activated(self): @@ -690,9 +910,15 @@ class _ResultsPurge(CommandManager): def __init__(self): super(_ResultsPurge, self).__init__() - self.menutext = "Purge results" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ResultsPurge", + "Purge results" + ) self.accel = "R, P" - self.tooltip = "Purges all results from active analysis" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ResultsPurge", + "Purges all results from active analysis" + ) self.is_active = "with_results" def Activated(self): @@ -706,9 +932,15 @@ class _SolverCxxtools(CommandManager): def __init__(self): super(_SolverCxxtools, self).__init__() self.pixmap = "FEM_SolverStandard" - self.menutext = "Solver CalculiX Standard" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverCxxtools", + "Solver CalculiX Standard" + ) self.accel = "S, X" - self.tooltip = "Creates a standard FEM solver CalculiX with ccx tools" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverCxxtools", + "Creates a standard FEM solver CalculiX with ccx tools" + ) self.is_active = "with_analysis" def Activated(self): @@ -741,9 +973,15 @@ class _SolverCalculix(CommandManager): def __init__(self): super(_SolverCalculix, self).__init__() self.pixmap = "FEM_SolverStandard" - self.menutext = "Solver CalculiX (new framework)" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverCalculix", + "Solver CalculiX (new framework)" + ) self.accel = "S, C" - self.tooltip = "Creates a FEM solver CalculiX new framework (less result error handling)" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverCalculix", + "Creates a FEM solver CalculiX new framework (less result error handling)" + ) self.is_active = "with_analysis" self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -754,9 +992,15 @@ class _SolverControl(CommandManager): def __init__(self): super(_SolverControl, self).__init__() - self.menutext = "Solver job control" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverControl", + "Solver job control" + ) self.accel = "S, T" - self.tooltip = "Changes solver attributes and runs the calculations for the selected solver" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverControl", + "Changes solver attributes and runs the calculations for the selected solver" + ) self.is_active = "with_solver" def Activated(self): @@ -768,9 +1012,12 @@ class _SolverElmer(CommandManager): def __init__(self): super(_SolverElmer, self).__init__() - self.menutext = "Solver Elmer" + self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_SolverElmer", "Solver Elmer") self.accel = "S, E" - self.tooltip = "Creates a FEM solver Elmer" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverElmer", + "Creates a FEM solver Elmer" + ) self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -781,9 +1028,9 @@ class _SolverMystran(CommandManager): def __init__(self): super(_SolverMystran, self).__init__() self.pixmap = "FEM_SolverStandard" - self.menutext = "Solver Mystran" + self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_SolverMystran", "Solver Mystran") self.accel = "S, M" - self.tooltip = "Creates a FEM solver Mystran" + self.tooltip = Qt.QT_TRANSLATE_NOOP("FEM_SolverMystran", "Creates a FEM solver Mystran") self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" @@ -793,9 +1040,12 @@ class _SolverRun(CommandManager): def __init__(self): super(_SolverRun, self).__init__() - self.menutext = "Run solver calculations" + self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_SolverRun", "Run solver calculations") self.accel = "S, R" - self.tooltip = "Runs the calculations for the selected solver" + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_SolverRun", + "Runs the calculations for the selected solver" + ) self.is_active = "with_solver" def Activated(self): @@ -810,9 +1060,9 @@ class _SolverZ88(CommandManager): def __init__(self): super(_SolverZ88, self).__init__() - self.menutext = "Solver Z88" + self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_SolverZ88", "Solver Z88") self.accel = "S, Z" - self.tooltip = "Creates a FEM solver Z88" + self.tooltip = Qt.QT_TRANSLATE_NOOP("FEM_SolverZ88", "Creates a FEM solver Z88") self.is_active = "with_analysis" self.do_activated = "add_obj_on_gui_noset_edit" From 5b3bf97f2b9e3d8b12765cb06831266e10d7b072 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Nov 2021 19:06:12 +0100 Subject: [PATCH 34/68] Gui: [skip ci] replace getNormalizedPosition() with normalizePixelPos() --- src/Gui/BlenderNavigationStyle.cpp | 4 ++-- src/Gui/CADNavigationStyle.cpp | 4 ++-- src/Gui/InventorNavigationStyle.cpp | 4 ++-- src/Gui/NavigationStyle.cpp | 10 ---------- src/Gui/NavigationStyle.h | 1 - src/Gui/OpenCascadeNavigationStyle.cpp | 4 ++-- src/Gui/OpenSCADNavigationStyle.cpp | 4 ++-- src/Gui/RevitNavigationStyle.cpp | 4 ++-- src/Gui/TouchpadNavigationStyle.cpp | 4 ++-- 9 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index c933d30dfb..81fc6f5202 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -88,11 +88,11 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index a390e0ff3d..53d893f0ff 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -92,11 +92,11 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 1a46fe8439..4c57393cb4 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -96,11 +96,11 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index 0a38a210f9..dc66d74beb 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1372,16 +1372,6 @@ void NavigationStyle::clearLog(void) this->log.historysize = 0; } -SbVec2f NavigationStyle::getNormalizedPosition(const SoEvent * const ev, - const SbViewportRegion & vpRgn) const -{ - const SbVec2s size(vpRgn.getViewportSizePixels()); - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); - return posn; -} - void NavigationStyle::syncModifierKeys(const SoEvent * const ev) { // Mismatches in state of the modifier keys happens if the user diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index af68928008..5f394c550b 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -213,7 +213,6 @@ protected: void clearLog(void); void addToLog(const SbVec2s pos, const SbTime time); - SbVec2f getNormalizedPosition(const SoEvent * const ev, const SbViewportRegion & vpRgn) const; void syncModifierKeys(const SoEvent * const ev); SbBool handleKeyboardEvent(const SoKeyboardEvent * const event, const SbVec2f & posn); diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index 6b42b53003..58501d9d7b 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -88,11 +88,11 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 7b0c31682a..1681ce5281 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -88,11 +88,11 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index 0c22aeeffd..3408929108 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -88,11 +88,11 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index b6fd4b3df4..606412fdd8 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -88,11 +88,11 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) const SoType type(ev->getTypeId()); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2f posn = getNormalizedPosition(ev, vp); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); const SbVec2f prevnormalized = this->lastmouseposition; this->lastmouseposition = posn; - const SbVec2s pos(ev->getPosition()); // Set to true if any event processing happened. Note that it is not // necessary to restrict ourselves to only do one "action" for an From 123b5b5da1df51af9b5322692da5a043fcc2ffe0 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Tue, 2 Nov 2021 23:12:31 -0500 Subject: [PATCH 35/68] Spreadsheet: Remove double-set of value on enter --- src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp index df46121a19..4103c2fd91 100644 --- a/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetView.cpp @@ -312,7 +312,6 @@ void SheetView::editingFinishedWithKey(int key, Qt::KeyboardModifiers modifiers) QModelIndex i = ui->cells->currentIndex(); if (i.isValid()) { - ui->cells->model()->setData(i, QVariant(ui->cellContent->text()), Qt::EditRole); ui->cells->finishEditWithMove(key, modifiers); } } From 56d900c669da2728fab609ed5b4316245c3b7651 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Wed, 3 Nov 2021 09:23:43 -0500 Subject: [PATCH 36/68] Spreadsheet: Display new value, or pending, when dirty If recomputes are turned off, the old behavior was that a cell would display its old property value in the SheetView. The new behavior is that we check to see if the value is actually something that gets computed: if so, show "#PENDING". If not, display the new value, but format it specially to indicate that it's been changed and that a recompute is (eventually) needed. --- src/Mod/Spreadsheet/Gui/SheetModel.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.cpp b/src/Mod/Spreadsheet/Gui/SheetModel.cpp index 341466214f..ed12e8ad44 100644 --- a/src/Mod/Spreadsheet/Gui/SheetModel.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetModel.cpp @@ -277,18 +277,34 @@ QVariant SheetModel::data(const QModelIndex &index, int role) const return QVariant::fromValue(f); } - if (!prop) { + auto dirtyCells = sheet->getCells()->getDirty(); + auto dirty = (dirtyCells.find(CellAddress(row,col)) != dirtyCells.end()); + + if (!prop || dirty) { switch (role) { case Qt::ForegroundRole: { - return QColor(0, 0, 255.0); + return QColor(0, 0, 255.0); // TODO: Remove this hardcoded color, replace with preference } case Qt::TextAlignmentRole: { qtAlignment = Qt::AlignHCenter | Qt::AlignVCenter; return QVariant::fromValue(qtAlignment); } case Qt::DisplayRole: - if(cell->getExpression()) - return QVariant(QLatin1String("#PENDING")); + if(cell->getExpression()) { + std::string str; + if (cell->getStringContent(str)) + if (str.size() > 0 && str[0] == '=') + // If this is a real computed value, indicate that a recompute is + // needed before we can display it + return QVariant(QLatin1String("#PENDING")); + else + // If it's just a simple value, display the new value, but still + // format it as a pending value to indicate to the user that + // a recompute is needed + return QVariant(QString::fromUtf8(str.c_str())); + else + return QVariant(); + } else return QVariant(); default: From 9a9267f922f64d8babe5509066564158fcbfcf66 Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 3 Nov 2021 11:13:10 -0400 Subject: [PATCH 37/68] Mesh: Convert comments from DE->EN Bringing uniformity to documenting FreeCAD --- src/Mod/Mesh/App/Core/Approximation.h | 2 +- src/Mod/Mesh/App/Core/Elements.cpp | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 99d73be059..524fca7d25 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -514,7 +514,7 @@ public: dKoeff[ ct ] = pKoef[ ct ]; } /** - * Destruktor. Deletes the ImpicitSurface instance + * Destructor. Deletes the ImpicitSurface instance * of the WildMagic library */ ~FunctionContainer(){ delete pImplSurf; } diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index bd434698ce..53bc252add 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -180,22 +180,22 @@ MeshFacetArray& MeshFacetArray::operator = (const MeshFacetArray &rclFAry) bool MeshGeomEdge::ContainedByOrIntersectBoundingBox ( const Base::BoundBox3f &rclBB ) const { - // Test, ob alle Eckpunkte der Edge sich auf einer der 6 Seiten der BB befinden + // Test whether all corner points of the Edge are on one of the 6 sides of the BB if ((GetBoundBox() && rclBB) == false) return false; - // Test, ob Edge-BB komplett in BB liegt + // Test whether Edge-BB is completely in BB if (rclBB.IsInBox(GetBoundBox())) return true; - // Test, ob einer der Eckpunkte in BB liegt + // Test whether one of the corner points is in BB for (int i=0;i<2;i++) { if (rclBB.IsInBox(_aclPoints[i])) return true; } - // "echter" Test auf Schnitt + // "real" test for cut if (IntersectBoundingBox(rclBB)) return true; @@ -487,7 +487,7 @@ bool MeshGeomFacet::IsPointOf (const Base::Vector3f &rclPoint, float fDistance) clProjPt.ProjectToPlane(_aclPoints[0], clNorm); - // Kante P0 --> P1 + // Edge P0 --> P1 clEdge = clP1 - clP0; fLP = clProjPt.DistanceToLine(clP0, clEdge); if (fLP > 0.0f) @@ -500,9 +500,9 @@ bool MeshGeomFacet::IsPointOf (const Base::Vector3f &rclPoint, float fDistance) } else return false; - } + } - // Kante P0 --> P2 + // Edge P0 --> P2 clEdge = clP2 - clP0; fLP = clProjPt.DistanceToLine(clP0, clEdge); if (fLP > 0.0f) @@ -515,9 +515,9 @@ bool MeshGeomFacet::IsPointOf (const Base::Vector3f &rclPoint, float fDistance) } else return false; - } + } - // Kante P1 --> P2 + // Edge P1 --> P2 clEdge = clP2 - clP1; fLP = clProjPt.DistanceToLine(clP1, clEdge); if (fLP > 0.0f) @@ -537,7 +537,7 @@ bool MeshGeomFacet::IsPointOf (const Base::Vector3f &rclPoint, float fDistance) bool MeshGeomFacet::IsPointOfFace (const Base::Vector3f& rclP, float fDistance) const { - // effektivere Implementierung als in MeshGeomFacet::IsPointOf + // more effective implementation than in MeshGeomFacet::IsPointOf // Base::Vector3f a(_aclPoints[0].x, _aclPoints[0].y, _aclPoints[0].z); Base::Vector3f b(_aclPoints[1].x, _aclPoints[1].y, _aclPoints[1].z); @@ -907,7 +907,7 @@ bool MeshGeomFacet::Foraminate (const Base::Vector3f &P, const Base::Vector3f &d bool MeshGeomFacet::IntersectPlaneWithLine (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir, Base::Vector3f &rclRes) const { - // berechne den Schnittpunkt Gerade <-> Ebene + // calculate the intersection of the straight line <-> plane if ( fabs(rclDir * GetNormal()) < 1e-3f ) return false; // line and plane are parallel @@ -979,7 +979,7 @@ void MeshGeomFacet::SubSample (float fStep, std::vector &rclPoin Base::Vector3f clVecAC(C - A); Base::Vector3f clVecBC(C - B); - // laengste Achse entspricht AB + // longest axis corresponds to AB float fLenAB = clVecAB.Length(); float fLenAC = clVecAC.Length(); float fLenBC = clVecBC.Length(); From e8016bdb82bbecebdb8c2c51458b389f30a2fe76 Mon Sep 17 00:00:00 2001 From: luz paz Date: Wed, 3 Nov 2021 11:17:05 -0400 Subject: [PATCH 38/68] Mesh: separating translation section in Mesh.qrc --- src/Mod/Mesh/Gui/Resources/Mesh.qrc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mod/Mesh/Gui/Resources/Mesh.qrc b/src/Mod/Mesh/Gui/Resources/Mesh.qrc index 3c358b6c78..5dbfb6d409 100644 --- a/src/Mod/Mesh/Gui/Resources/Mesh.qrc +++ b/src/Mod/Mesh/Gui/Resources/Mesh.qrc @@ -42,6 +42,8 @@ icons/RegularSolids/Mesh_Ellipsoid.svg icons/RegularSolids/Mesh_Sphere.svg icons/RegularSolids/Mesh_Torus.svg + + translations/Mesh_af.qm translations/Mesh_de.qm translations/Mesh_fi.qm From b8ad042986d6b19951413c0a8f7aa992075bc991 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Wed, 3 Nov 2021 14:31:11 -0500 Subject: [PATCH 39/68] Spreadsheet: Fix copy of empty but used cell --- src/Mod/Spreadsheet/App/PropertySheet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index 286b72890f..265f8d7697 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -351,7 +351,7 @@ void PropertySheet::copyCells(Base::Writer& writer, const std::vector& ra writer.incInd(); do { auto cell = getValue(*range); - if (cell) { + if (cell && cell->isUsed()) { cell->save(writer); } else { From 909b035d0b0d5e91e726e8a774c696ea7bdc9f5f Mon Sep 17 00:00:00 2001 From: Uwe Date: Thu, 4 Nov 2021 00:52:08 +0100 Subject: [PATCH 40/68] Squashed commit of the following: commit b5aa19950f09d9a391b189a578073b9920943294 Author: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Tue Nov 2 14:37:19 2021 +0100 Std: Fix OpenSCAD navigation string Holding down SHIFT is not required when zooming with the MMB. --- src/Gui/OpenSCADNavigationStyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 1681ce5281..75b34dac11 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -69,7 +69,7 @@ const char* OpenSCADNavigationStyle::mouseButtons(ViewerMode mode) case NavigationStyle::DRAGGING: return QT_TR_NOOP("Press left mouse button and move mouse"); case NavigationStyle::ZOOMING: - return QT_TR_NOOP("Press SHIFT and middle or right mouse button"); + return QT_TR_NOOP("Press middle mouse button or SHIFT and right mouse button"); default: return "No description"; } From bcab6b5a312439358c35d53ecb85110f90fa5156 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Wed, 3 Nov 2021 19:16:31 -0500 Subject: [PATCH 41/68] Spreadsheet: Prevent marking a cell dirty when the content didn't change --- src/Mod/Spreadsheet/Gui/SheetModel.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Mod/Spreadsheet/Gui/SheetModel.cpp b/src/Mod/Spreadsheet/Gui/SheetModel.cpp index ed12e8ad44..c289dcc121 100644 --- a/src/Mod/Spreadsheet/Gui/SheetModel.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetModel.cpp @@ -547,6 +547,16 @@ bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int try { QString str = value.toString(); + + // Check to see if this is already the value in the cell, and skip the update if so + auto cell = sheet->getCell(address); + if (cell) { + std::string oldContent; + cell->getStringContent(oldContent); + if (str == QString::fromStdString(oldContent)) + return true; + } + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Edit cell")); // Because of possible complication of recursively escaped // characters, let's take a shortcut and bypass the command From 4346fddc9c2997e8442f0e05451d814105c98e53 Mon Sep 17 00:00:00 2001 From: Uwe Date: Thu, 4 Nov 2021 01:30:19 +0100 Subject: [PATCH 42/68] [skip ci] update links in Windows installer until not all issues are sorted out with the new domain this should not be backported to the 0.19 branch --- src/WindowsInstaller/include/declarations.nsh | 4 ++-- src/WindowsInstaller/include/gui.nsh | 2 +- src/WindowsInstaller/lang/dutch.nsh | 2 +- src/WindowsInstaller/lang/english.nsh | 2 +- src/WindowsInstaller/lang/french.nsh | 2 +- src/WindowsInstaller/lang/galician.nsh | 2 +- src/WindowsInstaller/lang/german.nsh | 2 +- src/WindowsInstaller/lang/hungarian.nsh | 2 +- src/WindowsInstaller/lang/indonesian.nsh | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/WindowsInstaller/include/declarations.nsh b/src/WindowsInstaller/include/declarations.nsh index 03e26d9b6a..c63da6e971 100644 --- a/src/WindowsInstaller/include/declarations.nsh +++ b/src/WindowsInstaller/include/declarations.nsh @@ -26,9 +26,9 @@ Configuration and variables of FreeCAD installer !define APP_DIR_USERDATA ${APP_NAME} #!define APP_DIR_USERDATA "${APP_NAME}${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}" !define APP_INFO "${APP_NAME} - Your Own 3D Parametric Modeler" -!define APP_WEBPAGE "https://freecadweb.org/" +!define APP_WEBPAGE "https://freecad.org/" !define APP_WEBPAGE_INFO "${APP_NAME} Website" -!define APP_WIKI "https://www.freecadweb.org/wiki/Main_Page" +!define APP_WIKI "https://www.freecad.org/wiki/Main_Page" !define APP_WIKI_INFO "${APP_NAME} Wiki" !define APP_COPYRIGHT "${APP_NAME} is Copyright © 2001-${COPYRIGHT_YEAR} by the ${APP_NAME} Team" diff --git a/src/WindowsInstaller/include/gui.nsh b/src/WindowsInstaller/include/gui.nsh index ac0d6b5c80..16a285284f 100644 --- a/src/WindowsInstaller/include/gui.nsh +++ b/src/WindowsInstaller/include/gui.nsh @@ -66,7 +66,7 @@ BrandingText " " !define MUI_FINISHPAGE_SHOWREADME_FUNCTION StartFreeCAD !define MUI_FINISHPAGE_SHOWREADME_TEXT $(FinishPageRun) !define MUI_FINISHPAGE_LINK $(TEXT_FINISH_WEBSITE) -!define MUI_FINISHPAGE_LINK_LOCATION "https://freecadweb.org/" +!define MUI_FINISHPAGE_LINK_LOCATION "https://freecad.org/" #!define MUI_PAGE_CUSTOMFUNCTION_SHOW CheckDesktopShortcut !insertmacro MUI_PAGE_FINISH diff --git a/src/WindowsInstaller/lang/dutch.nsh b/src/WindowsInstaller/lang/dutch.nsh index e3cc15322f..07ddce249d 100644 --- a/src/WindowsInstaller/lang/dutch.nsh +++ b/src/WindowsInstaller/lang/dutch.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Dit installatie programma zal FreeCAD op uw syst #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "FreeCAD-Document" diff --git a/src/WindowsInstaller/lang/english.nsh b/src/WindowsInstaller/lang/english.nsh index 138c5aada0..fcf401586c 100644 --- a/src/WindowsInstaller/lang/english.nsh +++ b/src/WindowsInstaller/lang/english.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "This wizard will guide you through the installat #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org/ for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org/ for the latest news, support and tips" #${LangFileString} FileTypeTitle "FreeCAD-Document" diff --git a/src/WindowsInstaller/lang/french.nsh b/src/WindowsInstaller/lang/french.nsh index 5b4132444f..c75e5b9ce5 100644 --- a/src/WindowsInstaller/lang/french.nsh +++ b/src/WindowsInstaller/lang/french.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Cet assistant va vous guider tout au long de l'i #${LangFileString} TEXT_CONFIGURE_PYTHON "Compilation des scripts Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Créer un raccourci sur le bureau" -${LangFileString} TEXT_FINISH_WEBSITE "Consulter les dernières nouvelles, trucs et astuces sur le site freecadweb.org" +${LangFileString} TEXT_FINISH_WEBSITE "Consulter les dernières nouvelles, trucs et astuces sur le site freecad.org" #${LangFileString} FileTypeTitle "Document FreeCAD" diff --git a/src/WindowsInstaller/lang/galician.nsh b/src/WindowsInstaller/lang/galician.nsh index 48d684f2d9..f66e93e863 100644 --- a/src/WindowsInstaller/lang/galician.nsh +++ b/src/WindowsInstaller/lang/galician.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Este asistente vai-no guiar na instalación do F #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "Documento FreeCAD" diff --git a/src/WindowsInstaller/lang/german.nsh b/src/WindowsInstaller/lang/german.nsh index 44e831d58e..dbb04b10df 100644 --- a/src/WindowsInstaller/lang/german.nsh +++ b/src/WindowsInstaller/lang/german.nsh @@ -15,7 +15,7 @@ ${LangFileString} TEXT_WELCOME "Dieser Assistent wird Sie durch die Installation #${LangFileString} TEXT_CONFIGURE_PYTHON "Kompiliere Python Skripte..." ${LangFileString} TEXT_FINISH_DESKTOP "Ein Symbol auf der Arbeitsoberfläche erzeugen" -${LangFileString} TEXT_FINISH_WEBSITE "Besuchen Sie freecadweb.org für aktuelle Neuigkeiten" +${LangFileString} TEXT_FINISH_WEBSITE "Besuchen Sie freecad.org für aktuelle Neuigkeiten" #${LangFileString} FileTypeTitle "FreeCAD-Dokument" diff --git a/src/WindowsInstaller/lang/hungarian.nsh b/src/WindowsInstaller/lang/hungarian.nsh index 5230dc66a4..55e6ac43d5 100644 --- a/src/WindowsInstaller/lang/hungarian.nsh +++ b/src/WindowsInstaller/lang/hungarian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "A varázsló segítségével tudja telepíteni a #${LangFileString} TEXT_CONFIGURE_PYTHON "Python parancsfájlok fordítása..." ${LangFileString} TEXT_FINISH_DESKTOP "Indítóikon létrehozása Asztalon" -${LangFileString} TEXT_FINISH_WEBSITE "Látogasson el a freecadweb.org oldalra az aktuális hírekért, támogatásért és tippekért" +${LangFileString} TEXT_FINISH_WEBSITE "Látogasson el a freecad.org oldalra az aktuális hírekért, támogatásért és tippekért" #${LangFileString} FileTypeTitle "FreeCAD-dokumentum" diff --git a/src/WindowsInstaller/lang/indonesian.nsh b/src/WindowsInstaller/lang/indonesian.nsh index 1b92dd13b3..09282cc38a 100644 --- a/src/WindowsInstaller/lang/indonesian.nsh +++ b/src/WindowsInstaller/lang/indonesian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Program ini akan memandu anda dalam melakukan in #${LangFileString} TEXT_CONFIGURE_PYTHON "Proses kompilasi skrip Python ..." ${LangFileString} TEXT_FINISH_DESKTOP "Membuat pintasan ikon di destop" -${LangFileString} TEXT_FINISH_WEBSITE "Kunjungi freecadweb.org untuk berita terbaru serta dukungan" +${LangFileString} TEXT_FINISH_WEBSITE "Kunjungi freecad.org untuk berita terbaru serta dukungan" #${LangFileString} FileTypeTitle "Dokumen-FreeCAD" From f881330e8e2438aa9f1448d1db5ae01f73609f1f Mon Sep 17 00:00:00 2001 From: Uwe Date: Thu, 4 Nov 2021 01:34:16 +0100 Subject: [PATCH 43/68] [skip ci] update links in Windows installer - missing part until not all issues are sorted out with the new domain this should not be backported to the 0.19 branch --- src/WindowsInstaller/lang/arabic.nsh | 2 +- src/WindowsInstaller/lang/basque.nsh | 2 +- src/WindowsInstaller/lang/catalan.nsh | 2 +- src/WindowsInstaller/lang/czech.nsh | 2 +- src/WindowsInstaller/lang/danish.nsh | 2 +- src/WindowsInstaller/lang/italian.nsh | 2 +- src/WindowsInstaller/lang/japanese.nsh | 2 +- src/WindowsInstaller/lang/norwegian.nsh | 2 +- src/WindowsInstaller/lang/polish.nsh | 2 +- src/WindowsInstaller/lang/portuguese.nsh | 2 +- src/WindowsInstaller/lang/portugueseBR.nsh | 2 +- src/WindowsInstaller/lang/romanian.nsh | 2 +- src/WindowsInstaller/lang/russian.nsh | 2 +- src/WindowsInstaller/lang/slovak.nsh | 2 +- src/WindowsInstaller/lang/spanish.nsh | 2 +- src/WindowsInstaller/lang/swedish.nsh | 2 +- src/WindowsInstaller/lang/turkish.nsh | 2 +- src/WindowsInstaller/lang/ukrainian.nsh | 2 +- src/WindowsInstaller/setup/configure.nsh | 4 ++-- 19 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/WindowsInstaller/lang/arabic.nsh b/src/WindowsInstaller/lang/arabic.nsh index a97346e770..f7771f51af 100644 --- a/src/WindowsInstaller/lang/arabic.nsh +++ b/src/WindowsInstaller/lang/arabic.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "هذا المساعد سوف يرشدك خلال #${LangFileString} TEXT_CONFIGURE_PYTHON "بناء سكربتات بايثون..." ${LangFileString} TEXT_FINISH_DESKTOP "إنشاء اختصار سطح المكتب" -${LangFileString} TEXT_FINISH_WEBSITE "زيارة freecadweb.org لمشاهدة آخر الاخبار, الدعم والأفكار" +${LangFileString} TEXT_FINISH_WEBSITE "زيارة freecad.org لمشاهدة آخر الاخبار, الدعم والأفكار" #${LangFileString} FileTypeTitle "مستند - ليك" diff --git a/src/WindowsInstaller/lang/basque.nsh b/src/WindowsInstaller/lang/basque.nsh index 981d11bf20..7f4bfe2c86 100644 --- a/src/WindowsInstaller/lang/basque.nsh +++ b/src/WindowsInstaller/lang/basque.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Morroi honek $(^NameDA) aplikazioaren instalazio #${LangFileString} TEXT_CONFIGURE_PYTHON "Python script-ak konpilatzen..." ${LangFileString} TEXT_FINISH_DESKTOP "Sortu mahaigaineko lasterbidea" -${LangFileString} TEXT_FINISH_WEBSITE "Bisitatu freecadweb.org azken berriak, aholkuak eta laguntza lortzeko" +${LangFileString} TEXT_FINISH_WEBSITE "Bisitatu freecad.org azken berriak, aholkuak eta laguntza lortzeko" #${LangFileString} FileTypeTitle "FreeCAD-dokumentua" diff --git a/src/WindowsInstaller/lang/catalan.nsh b/src/WindowsInstaller/lang/catalan.nsh index 12a77adc31..2c9c5d32dc 100644 --- a/src/WindowsInstaller/lang/catalan.nsh +++ b/src/WindowsInstaller/lang/catalan.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Aquest assistent us guiarà en la instal·lació #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "Document FreeCAD" diff --git a/src/WindowsInstaller/lang/czech.nsh b/src/WindowsInstaller/lang/czech.nsh index 807cf7c82e..399945e327 100644 --- a/src/WindowsInstaller/lang/czech.nsh +++ b/src/WindowsInstaller/lang/czech.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Tento pomocník vás provede instalací FreeCADu #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "FreeCAD-dokumentů" diff --git a/src/WindowsInstaller/lang/danish.nsh b/src/WindowsInstaller/lang/danish.nsh index 9c43044e6f..9ef681a349 100644 --- a/src/WindowsInstaller/lang/danish.nsh +++ b/src/WindowsInstaller/lang/danish.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Denne guide vil installere FreeCAD på din compu #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "FreeCAD-Dokument" diff --git a/src/WindowsInstaller/lang/italian.nsh b/src/WindowsInstaller/lang/italian.nsh index 589ac1e945..4eff2860c0 100644 --- a/src/WindowsInstaller/lang/italian.nsh +++ b/src/WindowsInstaller/lang/italian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Verrete guidati nell'installazione di $(^NameDA) #${LangFileString} TEXT_CONFIGURE_PYTHON "Compilazione degli script Python in corso..." ${LangFileString} TEXT_FINISH_DESKTOP "Crea icona sul desktop" -${LangFileString} TEXT_FINISH_WEBSITE "Visitate freecadweb.org per ultime novità, aiuto e suggerimenti" +${LangFileString} TEXT_FINISH_WEBSITE "Visitate freecad.org per ultime novità, aiuto e suggerimenti" #${LangFileString} FileTypeTitle "Documento di FreeCAD" diff --git a/src/WindowsInstaller/lang/japanese.nsh b/src/WindowsInstaller/lang/japanese.nsh index b973095539..7320c9cfdc 100644 --- a/src/WindowsInstaller/lang/japanese.nsh +++ b/src/WindowsInstaller/lang/japanese.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "このウィザードが、あなたのFreeCAD #${LangFileString} TEXT_CONFIGURE_PYTHON "Pythonスクリプトをコンパイルしています..." ${LangFileString} TEXT_FINISH_DESKTOP "デスクトップにショートカットを作成する" -${LangFileString} TEXT_FINISH_WEBSITE "freecadweb.orgを開いて最新ニュースやサポート、ヒントなどを入手する" +${LangFileString} TEXT_FINISH_WEBSITE "freecad.orgを開いて最新ニュースやサポート、ヒントなどを入手する" #${LangFileString} FileTypeTitle "FreeCAD文書" diff --git a/src/WindowsInstaller/lang/norwegian.nsh b/src/WindowsInstaller/lang/norwegian.nsh index 6069b9278f..2e3293b4f1 100644 --- a/src/WindowsInstaller/lang/norwegian.nsh +++ b/src/WindowsInstaller/lang/norwegian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Denne veiviseren installerer FreeCAD på datamas #${LangFileString} TEXT_CONFIGURE_PYTHON "Kompilerer Python script..." ${LangFileString} TEXT_FINISH_DESKTOP "Lager snarveg på skrivebordet" -${LangFileString} TEXT_FINISH_WEBSITE "Besøk freecadweb.org for de seneste nyhetene, hjelp og støtte" +${LangFileString} TEXT_FINISH_WEBSITE "Besøk freecad.org for de seneste nyhetene, hjelp og støtte" #${LangFileString} FileTypeTitle "FreeCAD-dokument" diff --git a/src/WindowsInstaller/lang/polish.nsh b/src/WindowsInstaller/lang/polish.nsh index 861959f5a4..8e9ad43d90 100644 --- a/src/WindowsInstaller/lang/polish.nsh +++ b/src/WindowsInstaller/lang/polish.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Kreator przeprowadzi Ciebie przez proces instala #${LangFileString} TEXT_CONFIGURE_PYTHON "Kompilowanie skryptów Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Utwórz skrót na pulpicie" -${LangFileString} TEXT_FINISH_WEBSITE "Odwiedź freecadweb.org by poznać wiadomości i wskazówki lub skorzystać ze wsparcia" +${LangFileString} TEXT_FINISH_WEBSITE "Odwiedź freecad.org by poznać wiadomości i wskazówki lub skorzystać ze wsparcia" #${LangFileString} FileTypeTitle "Dokument FreeCAD" diff --git a/src/WindowsInstaller/lang/portuguese.nsh b/src/WindowsInstaller/lang/portuguese.nsh index df7aa3fbb5..24757e9b59 100644 --- a/src/WindowsInstaller/lang/portuguese.nsh +++ b/src/WindowsInstaller/lang/portuguese.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Este assistente de instalação irá guiá-lo at #${LangFileString} TEXT_CONFIGURE_PYTHON "Compilando os scripts de Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Criar um atalho no ambiente de trabalho" -${LangFileString} TEXT_FINISH_WEBSITE "Visite freecadweb.org para as últimas notícias, suporte e dicas" +${LangFileString} TEXT_FINISH_WEBSITE "Visite freecad.org para as últimas notícias, suporte e dicas" #${LangFileString} FileTypeTitle "Documento FreeCAD" diff --git a/src/WindowsInstaller/lang/portugueseBR.nsh b/src/WindowsInstaller/lang/portugueseBR.nsh index b2925508e4..2658c70d98 100644 --- a/src/WindowsInstaller/lang/portugueseBR.nsh +++ b/src/WindowsInstaller/lang/portugueseBR.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Este assistente guiará você durante a instala #${LangFileString} TEXT_CONFIGURE_PYTHON "Compilando scripts Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Criar atalho na área de trabalho" -${LangFileString} TEXT_FINISH_WEBSITE "Visite freecadweb.org para ver as últimas novidades do FreeCAD!" +${LangFileString} TEXT_FINISH_WEBSITE "Visite freecad.org para ver as últimas novidades do FreeCAD!" #${LangFileString} FileTypeTitle "Documento-FreeCAD" diff --git a/src/WindowsInstaller/lang/romanian.nsh b/src/WindowsInstaller/lang/romanian.nsh index c95950fe2c..2dadf8a9c5 100644 --- a/src/WindowsInstaller/lang/romanian.nsh +++ b/src/WindowsInstaller/lang/romanian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Acest asistent vă va ghida în procesul de inst #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "Document FreeCAD" diff --git a/src/WindowsInstaller/lang/russian.nsh b/src/WindowsInstaller/lang/russian.nsh index 92cc4169fd..879ebce14f 100644 --- a/src/WindowsInstaller/lang/russian.nsh +++ b/src/WindowsInstaller/lang/russian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Этот мастер проведет вас ч #${LangFileString} TEXT_CONFIGURE_PYTHON "Компиляция скриптов Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Создать ярлык на рабочем столе" -${LangFileString} TEXT_FINISH_WEBSITE "Перейти на freecadweb.org за новостями, поддержкой и советами" +${LangFileString} TEXT_FINISH_WEBSITE "Перейти на freecad.org за новостями, поддержкой и советами" #${LangFileString} FileTypeTitle "FreeCAD-Document" diff --git a/src/WindowsInstaller/lang/slovak.nsh b/src/WindowsInstaller/lang/slovak.nsh index 14e0aef61e..910538a125 100644 --- a/src/WindowsInstaller/lang/slovak.nsh +++ b/src/WindowsInstaller/lang/slovak.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Tento sprievodca Vám pomáha inštalovať FreeC #${LangFileString} TEXT_CONFIGURE_PYTHON "Kompilácia Python skriptov..." ${LangFileString} TEXT_FINISH_DESKTOP "Vytvoriť skratku pre pracovnú plochu" -${LangFileString} TEXT_FINISH_WEBSITE "Navštívte freecadweb.org pre posledné novinky, podporu a tipy" +${LangFileString} TEXT_FINISH_WEBSITE "Navštívte freecad.org pre posledné novinky, podporu a tipy" #${LangFileString} FileTypeTitle "FreeCAD dokument" diff --git a/src/WindowsInstaller/lang/spanish.nsh b/src/WindowsInstaller/lang/spanish.nsh index eb6c5a2079..3540bf480b 100644 --- a/src/WindowsInstaller/lang/spanish.nsh +++ b/src/WindowsInstaller/lang/spanish.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Este programa instalará FreeCAD en su ordenador #${LangFileString} TEXT_CONFIGURE_PYTHON "Compilando guiones Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Crear acceso directo en el escritorio" -${LangFileString} TEXT_FINISH_WEBSITE "Visite freecadweb.org para últimas noticias, ayuda y consejos" +${LangFileString} TEXT_FINISH_WEBSITE "Visite freecad.org para últimas noticias, ayuda y consejos" #${LangFileString} FileTypeTitle "Documento FreeCAD" diff --git a/src/WindowsInstaller/lang/swedish.nsh b/src/WindowsInstaller/lang/swedish.nsh index 22bb333d20..0176d07b3f 100644 --- a/src/WindowsInstaller/lang/swedish.nsh +++ b/src/WindowsInstaller/lang/swedish.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Denna guide tar dig igenom installationen av $(^ #${LangFileString} TEXT_CONFIGURE_PYTHON "Kompilerar Pythonskript..." ${LangFileString} TEXT_FINISH_DESKTOP "Skapa skrivbordsgenväg" -${LangFileString} TEXT_FINISH_WEBSITE "Besök freecadweb.org för de senaste nyheterna, support och tips" +${LangFileString} TEXT_FINISH_WEBSITE "Besök freecad.org för de senaste nyheterna, support och tips" #${LangFileString} FileTypeTitle "FreeCAD-dokument" diff --git a/src/WindowsInstaller/lang/turkish.nsh b/src/WindowsInstaller/lang/turkish.nsh index dd1511abcf..12f4eedab2 100644 --- a/src/WindowsInstaller/lang/turkish.nsh +++ b/src/WindowsInstaller/lang/turkish.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "Bu sihirbaz size FreeCAD programını kuracak.$\ #${LangFileString} TEXT_CONFIGURE_PYTHON "Compiling Python scripts..." ${LangFileString} TEXT_FINISH_DESKTOP "Create desktop shortcut" -${LangFileString} TEXT_FINISH_WEBSITE "Visit freecadweb.org for the latest news, support and tips" +${LangFileString} TEXT_FINISH_WEBSITE "Visit freecad.org for the latest news, support and tips" #${LangFileString} FileTypeTitle "FreeCAD-Document" diff --git a/src/WindowsInstaller/lang/ukrainian.nsh b/src/WindowsInstaller/lang/ukrainian.nsh index d1e4f975f2..fac5191ab4 100644 --- a/src/WindowsInstaller/lang/ukrainian.nsh +++ b/src/WindowsInstaller/lang/ukrainian.nsh @@ -14,7 +14,7 @@ ${LangFileString} TEXT_WELCOME "За допомогою цього майстр #${LangFileString} TEXT_CONFIGURE_PYTHON "Обробка скриптів Python..." ${LangFileString} TEXT_FINISH_DESKTOP "Створити значок на стільниці" -${LangFileString} TEXT_FINISH_WEBSITE "Відвідати freecadweb.org, щоб ознайомитися з новинами, довідковими матеріалами та підказками" +${LangFileString} TEXT_FINISH_WEBSITE "Відвідати freecad.org, щоб ознайомитися з новинами, довідковими матеріалами та підказками" #${LangFileString} FileTypeTitle "Документ FreeCAD" diff --git a/src/WindowsInstaller/setup/configure.nsh b/src/WindowsInstaller/setup/configure.nsh index dae07512f0..d42ef4d6bb 100644 --- a/src/WindowsInstaller/setup/configure.nsh +++ b/src/WindowsInstaller/setup/configure.nsh @@ -45,9 +45,9 @@ Section -InstallData WriteRegStr SHCTX ${APP_UNINST_KEY} "DisplayVersion" "${APP_VERSION}" WriteRegStr SHCTX ${APP_UNINST_KEY} "DisplayIcon" "$INSTDIR\${APP_RUN}" WriteRegStr SHCTX ${APP_UNINST_KEY} "URLUpdateInfo" "${APP_WEBPAGE}" - WriteRegStr SHCTX ${APP_UNINST_KEY} "URLInfoAbout" "https://www.freecadweb.org/" + WriteRegStr SHCTX ${APP_UNINST_KEY} "URLInfoAbout" "https://www.freecad.org/" WriteRegStr SHCTX ${APP_UNINST_KEY} "Publisher" "${APP_NAME} Team" - WriteRegStr SHCTX ${APP_UNINST_KEY} "HelpLink" "https://forum.freecadweb.org/" + WriteRegStr SHCTX ${APP_UNINST_KEY} "HelpLink" "https://forum.freecad.org/" WriteRegDWORD SHCTX ${APP_UNINST_KEY} "NoModify" 0x00000001 WriteRegDWORD SHCTX ${APP_UNINST_KEY} "NoRepair" 0x00000001 WriteRegStr SHCTX ${APP_UNINST_KEY} "StartMenu" "$SMPROGRAMS\$StartmenuFolder" From 13dcfa64f6654cc11760a6c276ff04d8769ac2e1 Mon Sep 17 00:00:00 2001 From: Uwe Date: Thu, 4 Nov 2021 02:04:21 +0100 Subject: [PATCH 44/68] [skpi ci] Win installer: update MSVC version --- src/WindowsInstaller/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WindowsInstaller/README.md b/src/WindowsInstaller/README.md index 542f264de7..777ce80e43 100644 --- a/src/WindowsInstaller/README.md +++ b/src/WindowsInstaller/README.md @@ -20,7 +20,7 @@ To build the installer you can do the following: (You can alternatively get nsProcess from https://nsis.sourceforge.io/NsProcess_plugin) 7. Copy all FreeCAD files to the folder "~\FreeCAD" e.g. "C:\FreeCAD\Installer\FreeCAD" -8. If you use a version of FreeCAD that was compiled using another MSVC version than MSVC 2017, +8. If you use a version of FreeCAD that was compiled using another MSVC version than MSVC 2019, copy its distributable DLLs to the folder FILES_DEPS (see step 3). 9. Right-click on the file FreeCAD-installer.nsi and choose "Compile NSIS script" to compile the installer. From 09da245af974c25b035ba3635bbadc99e18f27d6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 4 Nov 2021 10:50:09 +0100 Subject: [PATCH 45/68] App: harmonize API of App::Application * make getHomePath() static and return a std::string * make getExecutableName() static and return a std::string --- src/App/Application.cpp | 8 ++++---- src/App/Application.h | 4 ++-- src/App/ApplicationPy.cpp | 2 +- src/App/Document.cpp | 2 +- src/Gui/Application.cpp | 8 ++++---- src/Gui/ApplicationPy.cpp | 6 +++--- src/Gui/Assistant.cpp | 8 ++++---- src/Gui/BitmapFactory.cpp | 6 +++--- src/Gui/Command.cpp | 2 +- src/Gui/DlgActionsImp.cpp | 2 +- src/Gui/DlgMacroExecuteImp.cpp | 6 +++--- src/Gui/DocumentRecovery.cpp | 2 +- src/Gui/DownloadItem.cpp | 2 +- src/Gui/GuiApplication.cpp | 2 +- src/Gui/MainWindow.cpp | 4 ++-- src/Gui/NetworkRetriever.cpp | 6 +++--- src/Gui/SoFCOffscreenRenderer.cpp | 4 ++-- src/Gui/Splashscreen.cpp | 2 +- src/Gui/WidgetFactory.cpp | 2 +- src/Mod/Import/App/AppImportPy.cpp | 2 +- src/Mod/Import/Gui/AppImportGuiPy.cpp | 2 +- src/Mod/Path/Gui/AppPathGuiPy.cpp | 6 +++--- src/Mod/Raytracing/App/AppRaytracingPy.cpp | 2 +- 23 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index d51a6740fc..faac993af3 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -1040,14 +1040,14 @@ Application::TransactionSignaller::~TransactionSignaller() { } } -const char* Application::getHomePath(void) const +std::string Application::getHomePath() { - return _mConfig["AppHomePath"].c_str(); + return mConfig["AppHomePath"]; } -const char* Application::getExecutableName(void) const +std::string Application::getExecutableName() { - return _mConfig["ExeName"].c_str(); + return mConfig["ExeName"]; } std::string Application::getTempPath() diff --git a/src/App/Application.h b/src/App/Application.h index 0d38fcfdab..fbd20abc7c 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -395,8 +395,8 @@ public: /** @name Application directories */ //@{ - const char* getHomePath(void) const; - const char* getExecutableName(void) const; + static std::string getHomePath(); + static std::string getExecutableName(); /*! Returns the temporary directory. By default, this is set to the system's temporary directory but can be customized by the user. diff --git a/src/App/ApplicationPy.cpp b/src/App/ApplicationPy.cpp index 0eaa6ac788..de213ff32e 100644 --- a/src/App/ApplicationPy.cpp +++ b/src/App/ApplicationPy.cpp @@ -691,7 +691,7 @@ PyObject* Application::sGetHomePath(PyObject * /*self*/, PyObject *args) if (!PyArg_ParseTuple(args, "")) // convert args: Python->C return NULL; // NULL triggers exception - Py::String homedir(GetApplication().getHomePath(),"utf-8"); + Py::String homedir(Application::getHomePath(),"utf-8"); return Py::new_reference_to(homedir); } diff --git a/src/App/Document.cpp b/src/App/Document.cpp index f6ec4f46ac..0c6fceb43f 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1685,7 +1685,7 @@ std::string Document::getTransientDirectoryName(const std::string& uuid, const s std::stringstream s; QCryptographicHash hash(QCryptographicHash::Sha1); hash.addData(filename.c_str(), filename.size()); - s << App::Application::getTempPath() << GetApplication().getExecutableName() + s << App::Application::getTempPath() << App::Application::getExecutableName() << "_Doc_" << uuid << "_" << hash.result().toHex().left(6).constData() << "_" << QCoreApplication::applicationPid(); diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index e0ce35be61..0dc5ed879a 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -1955,13 +1955,13 @@ void Application::runApplication(void) mainApp.setApplicationName(QString::fromUtf8(it->second.c_str())); } else { - mainApp.setApplicationName(QString::fromUtf8(App::GetApplication().getExecutableName())); + mainApp.setApplicationName(QString::fromStdString(App::Application::getExecutableName())); } #ifndef Q_OS_MACX mainApp.setWindowIcon(Gui::BitmapFactory().pixmap(App::Application::Config()["AppIcon"].c_str())); #endif QString plugin; - plugin = QString::fromUtf8(App::GetApplication().getHomePath()); + plugin = QString::fromStdString(App::Application::getHomePath()); plugin += QLatin1String("/plugins"); QCoreApplication::addLibraryPath(plugin); @@ -2127,7 +2127,7 @@ void Application::runApplication(void) // init the Inventor subsystem initOpenInventor(); - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); it = cfg.find("WindowTitle"); if (it != cfg.end()) { @@ -2267,7 +2267,7 @@ void Application::runApplication(void) try { std::stringstream s; - s << App::Application::getTempPath() << App::GetApplication().getExecutableName() + s << App::Application::getTempPath() << App::Application::getExecutableName() << "_" << QCoreApplication::applicationPid() << ".lock"; // open a lock file with the PID Base::FileInfo fi(s.str()); diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index cf23554b0d..82a883cb1f 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -1029,7 +1029,7 @@ PyObject* Application::sAddResPath(PyObject * /*self*/, PyObject *args) PyMem_Free(filePath); if (QDir::isRelativePath(path)) { // Home path ends with '/' - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); path = home + path; } @@ -1048,7 +1048,7 @@ PyObject* Application::sAddLangPath(PyObject * /*self*/, PyObject *args) PyMem_Free(filePath); if (QDir::isRelativePath(path)) { // Home path ends with '/' - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); path = home + path; } @@ -1066,7 +1066,7 @@ PyObject* Application::sAddIconPath(PyObject * /*self*/, PyObject *args) PyMem_Free(filePath); if (QDir::isRelativePath(path)) { // Home path ends with '/' - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); path = home + path; } diff --git a/src/Gui/Assistant.cpp b/src/Gui/Assistant.cpp index f903c7a28f..e905fe8dfd 100644 --- a/src/Gui/Assistant.cpp +++ b/src/Gui/Assistant.cpp @@ -85,8 +85,8 @@ bool Assistant::startAssistant() if (proc->state() != QProcess::Running) { #ifdef Q_OS_WIN QString app; - app = QDir::toNativeSeparators(QString::fromUtf8 - (App::GetApplication().getHomePath()) + QLatin1String("bin/")); + app = QDir::toNativeSeparators(QString::fromStdString + (App::Application::getHomePath()) + QLatin1String("bin/")); #elif defined(Q_OS_MAC) QString app = QCoreApplication::applicationDirPath() + QDir::separator(); #else @@ -95,8 +95,8 @@ bool Assistant::startAssistant() app += QLatin1String("assistant"); // get the name of the executable and the doc path - QString exe = QString::fromUtf8(App::GetApplication().getExecutableName()); - QString doc = QString::fromUtf8(App::Application::getHelpDir().c_str()); + QString exe = QString::fromStdString(App::Application::getExecutableName()); + QString doc = QString::fromStdString(App::Application::getHelpDir()); QString qhc = doc + exe.toLower() + QLatin1String(".qhc"); diff --git a/src/Gui/BitmapFactory.cpp b/src/Gui/BitmapFactory.cpp index bfa5317cf1..2e9ffd7156 100644 --- a/src/Gui/BitmapFactory.cpp +++ b/src/Gui/BitmapFactory.cpp @@ -97,15 +97,15 @@ BitmapFactoryInst& BitmapFactoryInst::instance(void) std::map::const_iterator it; it = App::GetApplication().Config().find("ProgramIcons"); if (it != App::GetApplication().Config().end()) { - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); QString path = QString::fromUtf8(it->second.c_str()); if (QDir(path).isRelative()) { path = QFileInfo(QDir(home), path).absoluteFilePath(); } _pcSingleton->addPath(path); } - _pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromUtf8(App::GetApplication().getHomePath()))); - _pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromUtf8(App::GetApplication().Config()["UserAppData"].c_str()))); + _pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromStdString(App::Application::getHomePath()))); + _pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromStdString(App::Application::getUserAppDataDir()))); _pcSingleton->addPath(QLatin1String(":/icons/")); _pcSingleton->addPath(QLatin1String(":/Icons/")); } diff --git a/src/Gui/Command.cpp b/src/Gui/Command.cpp index cd95d3ae31..3f44c28d87 100644 --- a/src/Gui/Command.cpp +++ b/src/Gui/Command.cpp @@ -1117,7 +1117,7 @@ void MacroCommand::activated(int iMsg) d = QDir(QString::fromUtf8(cMacroPath.c_str())); } else { - QString dirstr = QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro"); + QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); d = QDir(dirstr); } diff --git a/src/Gui/DlgActionsImp.cpp b/src/Gui/DlgActionsImp.cpp index 35aa3b9f0b..f2c85ebb99 100644 --- a/src/Gui/DlgActionsImp.cpp +++ b/src/Gui/DlgActionsImp.cpp @@ -71,7 +71,7 @@ DlgCustomActionsImp::DlgCustomActionsImp( QWidget* parent ) for (unsigned int i=0; iactionMacros->insertItem(0,d[i],QVariant(false)); - QString systemMacroDirStr = QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro"); + QString systemMacroDirStr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); d = QDir(systemMacroDirStr, QLatin1String("*.FCMacro *.py")); if (d.exists()) { for (unsigned int i=0; isetText(0, dir[i]); } - QString dirstr = QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro"); + QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); dir = QDir(dirstr, QLatin1String("*.FCMacro *.py")); ui->systemMacroListBox->clear(); @@ -268,7 +268,7 @@ void DlgMacroExecuteImp::accept() dir =QDir(this->macroPath); } else { - QString dirstr = QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro"); + QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); dir = QDir(dirstr); } @@ -319,7 +319,7 @@ void DlgMacroExecuteImp::on_editButton_clicked() else { //index == 1 system-wide item = ui->systemMacroListBox->currentItem(); - dir.setPath(QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro")); + dir.setPath(QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro")); } if (!item) diff --git a/src/Gui/DocumentRecovery.cpp b/src/Gui/DocumentRecovery.cpp index 4f2d60006e..924c4e32fb 100644 --- a/src/Gui/DocumentRecovery.cpp +++ b/src/Gui/DocumentRecovery.cpp @@ -666,7 +666,7 @@ void DocumentRecoveryHandler::checkForPreviousCrashes(const std::function locks = tmp.entryInfoList(); for (QList::iterator it = locks.begin(); it != locks.end(); ++it) { QString bn = it->baseName(); diff --git a/src/Gui/DownloadItem.cpp b/src/Gui/DownloadItem.cpp index 43e59a26ba..6e87fbc5e8 100644 --- a/src/Gui/DownloadItem.cpp +++ b/src/Gui/DownloadItem.cpp @@ -273,7 +273,7 @@ void DownloadItem::init() QString DownloadItem::getDownloadDirectory() const { - QString exe = QString::fromLatin1(App::GetApplication().getExecutableName()); + QString exe = QString::fromStdString(App::Application::getExecutableName()); QString path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); QString dirPath = QDir(path).filePath(exe); Base::Reference hPath = App::GetApplication().GetUserParameter().GetGroup("BaseApp") diff --git a/src/Gui/GuiApplication.cpp b/src/Gui/GuiApplication.cpp index b254658000..1a9e7e335f 100644 --- a/src/Gui/GuiApplication.cpp +++ b/src/Gui/GuiApplication.cpp @@ -177,7 +177,7 @@ public: , running(false) { timer->setSingleShot(true); - std::string exeName = App::GetApplication().getExecutableName(); + std::string exeName = App::Application::getExecutableName(); serverName = QString::fromStdString(exeName); } diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 35a335e9c3..b0dfe66630 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -1490,7 +1490,7 @@ QPixmap MainWindow::aboutImage() const if (!about_path.empty() && about_image.isNull()) { QString path = QString::fromUtf8(about_path.c_str()); if (QDir(path).isRelative()) { - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); path = QFileInfo(QDir(home), path).absoluteFilePath(); } about_image.load(path); @@ -1517,7 +1517,7 @@ QPixmap MainWindow::splashImage() const if (splash_image.isNull()) { QString path = QString::fromUtf8(splash_path.c_str()); if (QDir(path).isRelative()) { - QString home = QString::fromUtf8(App::GetApplication().getHomePath()); + QString home = QString::fromStdString(App::Application::getHomePath()); path = QFileInfo(QDir(home), path).absoluteFilePath(); } diff --git a/src/Gui/NetworkRetriever.cpp b/src/Gui/NetworkRetriever.cpp index 8ba993e207..38e8528f62 100644 --- a/src/Gui/NetworkRetriever.cpp +++ b/src/Gui/NetworkRetriever.cpp @@ -418,7 +418,7 @@ Action * StdCmdDownloadOnlineHelp::createAction(void) { Action *pcAction; - QString exe = QString::fromLatin1(App::GetApplication().getExecutableName()); + QString exe = QString::fromStdString(App::Application::getExecutableName()); pcAction = new Action(this,getMainWindow()); pcAction->setText(QCoreApplication::translate( this->className(), getMenuText())); @@ -437,7 +437,7 @@ Action * StdCmdDownloadOnlineHelp::createAction(void) void StdCmdDownloadOnlineHelp::languageChange() { if (_pcAction) { - QString exe = QString::fromLatin1(App::GetApplication().getExecutableName()); + QString exe = QString::fromStdString(App::Application::getExecutableName()); _pcAction->setText(QCoreApplication::translate( this->className(), getMenuText())); _pcAction->setToolTip(QCoreApplication::translate( @@ -483,7 +483,7 @@ void StdCmdDownloadOnlineHelp::activated(int iMsg) bool canStart = false; // set output directory - QString path = QString::fromUtf8(App::GetApplication().getHomePath()); + QString path = QString::fromStdString(App::Application::getHomePath()); path += QString::fromLatin1("/doc/"); ParameterGrp::handle hURLGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/OnlineHelp"); path = QString::fromUtf8(hURLGrp->GetASCII( "DownloadLocation", path.toLatin1() ).c_str()); diff --git a/src/Gui/SoFCOffscreenRenderer.cpp b/src/Gui/SoFCOffscreenRenderer.cpp index a54220fac7..01c393fd46 100644 --- a/src/Gui/SoFCOffscreenRenderer.cpp +++ b/src/Gui/SoFCOffscreenRenderer.cpp @@ -166,7 +166,7 @@ void SoFCOffscreenRenderer::writeToImageFile(const char* filename, const char* c img.setText(QLatin1String("Description"), QString::fromUtf8(comment)); img.setText(QLatin1String("Creation Time"), QDateTime::currentDateTime().toString()); img.setText(QLatin1String("Software"), - QString::fromUtf8(App::GetApplication().getExecutableName())); + QString::fromStdString(App::Application::getExecutableName())); } QFile f(QString::fromUtf8(filename)); @@ -296,7 +296,7 @@ std::string SoFCOffscreenRenderer::createMIBA(const SbMatrix& mat) const com << " \n" ; com << " Unknown\n" ; com << " " << QDateTime::currentDateTime().toString().toLatin1().constData() << "\n" ; - com << " " << App::GetApplication().getExecutableName() << " " << major << "." << minor << "\n" ; + com << " " << App::Application::getExecutableName() << " " << major << "." << minor << "\n" ; com << " Unknown\n"; com << " 1.0\n"; com << " \n" ; diff --git a/src/Gui/Splashscreen.cpp b/src/Gui/Splashscreen.cpp index 4b8e5b53fd..c899f92ae9 100644 --- a/src/Gui/Splashscreen.cpp +++ b/src/Gui/Splashscreen.cpp @@ -680,7 +680,7 @@ void AboutDialog::on_copyButton_clicked() QTextStream str(&data); std::map& config = App::Application::Config(); std::map::iterator it; - QString exe = QString::fromLatin1(App::GetApplication().getExecutableName()); + QString exe = QString::fromStdString(App::Application::getExecutableName()); QString major = QString::fromLatin1(config["BuildVersionMajor"].c_str()); QString minor = QString::fromLatin1(config["BuildVersionMinor"].c_str()); diff --git a/src/Gui/WidgetFactory.cpp b/src/Gui/WidgetFactory.cpp index b68456e7a4..241c35f655 100644 --- a/src/Gui/WidgetFactory.cpp +++ b/src/Gui/WidgetFactory.cpp @@ -431,7 +431,7 @@ void PyResource::load(const char* name) // checks whether it's a relative path if (fi.isRelative()) { QString cwd = QDir::currentPath (); - QString home= QDir(QString::fromUtf8(App::GetApplication().getHomePath())).path(); + QString home= QDir(QString::fromStdString(App::Application::getHomePath())).path(); // search in cwd and home path for the file // diff --git a/src/Mod/Import/App/AppImportPy.cpp b/src/Mod/Import/App/AppImportPy.cpp index f76e59bf15..88e7f2be6e 100644 --- a/src/Mod/Import/App/AppImportPy.cpp +++ b/src/Mod/Import/App/AppImportPy.cpp @@ -368,7 +368,7 @@ private: //makeHeader.SetName(new TCollection_HAsciiString((Standard_CString)Utf8Name.c_str())); makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str())); makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str())); - makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName())); + makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::Application::getExecutableName().c_str())); makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model")); IFSelect_ReturnStatus ret = writer.Write(name8bit.c_str()); if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) { diff --git a/src/Mod/Import/Gui/AppImportGuiPy.cpp b/src/Mod/Import/Gui/AppImportGuiPy.cpp index 774c40e2f9..8f855a3a32 100644 --- a/src/Mod/Import/Gui/AppImportGuiPy.cpp +++ b/src/Mod/Import/Gui/AppImportGuiPy.cpp @@ -668,7 +668,7 @@ private: //makeHeader.SetName(new TCollection_HAsciiString((Standard_CString)Utf8Name.c_str())); makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str())); makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str())); - makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName())); + makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::Application::getExecutableName().c_str())); makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model")); IFSelect_ReturnStatus ret = writer.Write(name8bit.c_str()); if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) { diff --git a/src/Mod/Path/Gui/AppPathGuiPy.cpp b/src/Mod/Path/Gui/AppPathGuiPy.cpp index a442244b41..062da3a069 100644 --- a/src/Mod/Path/Gui/AppPathGuiPy.cpp +++ b/src/Mod/Path/Gui/AppPathGuiPy.cpp @@ -82,7 +82,7 @@ private: wc.restoreCursor(); try { - std::string path = App::GetApplication().getHomePath(); + std::string path = App::Application::getHomePath(); path += "Mod/Path/PathScripts/post/"; QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") @@ -149,7 +149,7 @@ private: wc.restoreCursor(); try { - std::string path = App::GetApplication().getHomePath(); + std::string path = App::Application::getHomePath(); path += "Mod/Path/PathScripts/post/"; QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") @@ -225,7 +225,7 @@ private: if (objlist.size() == 0) throw Py::RuntimeError("No object to export"); - std::string path = App::GetApplication().getHomePath(); + std::string path = App::Application::getHomePath(); path += "Mod/Path/PathScripts/post/"; QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_post.py")); std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") diff --git a/src/Mod/Raytracing/App/AppRaytracingPy.cpp b/src/Mod/Raytracing/App/AppRaytracingPy.cpp index 5b124e91fc..dc6a528415 100644 --- a/src/Mod/Raytracing/App/AppRaytracingPy.cpp +++ b/src/Mod/Raytracing/App/AppRaytracingPy.cpp @@ -222,7 +222,7 @@ private: if (! PyArg_ParseTuple(args.ptr(), "ss",&FileName,&DestDir)) throw Py::Exception(); - std::string resName = App::GetApplication().getHomePath(); + std::string resName = App::Application::getHomePath(); resName += "Mod"; resName += PATHSEP ; resName += "Raytracing"; From eac21354fa4b60de2eb074bfb331705681a86fd3 Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Thu, 4 Nov 2021 15:44:40 +0100 Subject: [PATCH 46/68] [Sketcher] Refactor Validate Sketch task UI to decrease confusion --- .../Sketcher/Gui/TaskSketcherValidation.ui | 113 +++++++++++------- 1 file changed, 67 insertions(+), 46 deletions(-) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui index 4cf647b8cf..d451104fd0 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui @@ -6,30 +6,43 @@ 0 0 - 311 - 453 + 266 + 684 Sketcher validation - - + + + + Reversed external geometry + + + + + + Find + + + + + + + Swap endpoints in constraints + + + + + + + + Missing coincidences - - - - Tolerance: - - - - - - @@ -47,6 +60,13 @@ + + + + Tolerance: + + + @@ -54,17 +74,13 @@ - - - - Highlight open vertexes - - + + - + Invalid constraints @@ -94,7 +110,35 @@
- + + + + Open and non-manifold vertexes + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Highlight troublesome vertexes + + + + + + + Degenerated geometry @@ -117,30 +161,7 @@ - - - - Reversed external geometry - - - - - - Find - - - - - - - Swap endpoints in constraints - - - - - - - + Constraint orientation locking From b22f2c656279e90306ae6dbeecd083a67ff3f7af Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Thu, 4 Nov 2021 15:55:12 +0100 Subject: [PATCH 47/68] [Sketcher] Add tooltips in Validate Sketch task UI --- .../Sketcher/Gui/TaskSketcherValidation.ui | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui index d451104fd0..bde339ba91 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui @@ -22,6 +22,9 @@ + + Finds reversed external geometries + Find @@ -29,6 +32,9 @@ + + Fixes found reversed external geometries by swapping their endpoints + Swap endpoints in constraints @@ -39,12 +45,18 @@ + + Fixes found missing coincidences by adding extra coincident constrains + Missing coincidences + + If checked, construction geometries are ignored in the search + Ignore construction geometry @@ -55,6 +67,10 @@ + + Finds and displays missing coincidences found in the sketch +This is done by analyzing the sketch geometries and constraints + Find @@ -75,7 +91,11 @@ - + + + Defines the X/Y tolerance inside which missing coincidences are searched. + + @@ -88,6 +108,9 @@ + + Finds invalid/malformed constrains in the sketch + Find @@ -95,6 +118,9 @@ + + Tries to fix found invalid constraints + Fix @@ -102,6 +128,9 @@ + + Deletes constrains refering to external geometry + Delete constraints to external geom. @@ -130,6 +159,10 @@ + + Highlights open and non-manifold vertexes that could lead to error if sketch is used to generate solids +This is purely based on topological shape of the sketch and not on its geometry/constrain set. + Highlight troublesome vertexes @@ -146,6 +179,9 @@ + + Finds degenerated geometries in the sketch + Find @@ -153,6 +189,9 @@ + + Tries to fix found degenerated geometries + Fix @@ -169,6 +208,9 @@ + + Enables/updates constraint orientation locking + Enable/Update @@ -176,6 +218,9 @@ + + Disables constraint orientation locking + Disable From 8366028e6f5103ed0b3ecc79831ff480e2f81e8c Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 4 Nov 2021 23:21:14 +0100 Subject: [PATCH 48/68] PD: [skip ci] open a transaction when creating a new body with DlgActiveBody --- src/Mod/PartDesign/Gui/DlgActiveBody.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Mod/PartDesign/Gui/DlgActiveBody.cpp b/src/Mod/PartDesign/Gui/DlgActiveBody.cpp index 9aeb1b6c36..fb4841d94f 100644 --- a/src/Mod/PartDesign/Gui/DlgActiveBody.cpp +++ b/src/Mod/PartDesign/Gui/DlgActiveBody.cpp @@ -28,6 +28,7 @@ # include #endif +#include #include #include "DlgActiveBody.h" @@ -92,10 +93,15 @@ void DlgActiveBody::accept() App::DocumentObject* selectedBody = selectedItems[0]->data(Qt::UserRole).value(); - if (selectedBody) + if (selectedBody) { activeBody = makeBodyActive(selectedBody, _doc); - else + } + else { + // A transaction must be created as otherwise the undo/redo is broken + App::GetApplication().setActiveTransaction(QT_TRANSLATE_NOOP("Command", "Add a Body"), true); activeBody = makeBody(_doc); + App::GetApplication().closeActiveTransaction(); + } QDialog::accept(); } From fdcdaebc9b7222c6b498f9ab62bf4decdf3bcc18 Mon Sep 17 00:00:00 2001 From: luz paz Date: Thu, 4 Nov 2021 06:27:24 -0400 Subject: [PATCH 49/68] Fix typos in source comments [skip ci] Found via `codespell -q 3 -L aci,ake,aline,alle,alledges,alocation,als,ang,anid,apoints,ba,beginn,behaviour,bloaded,bottome,byteorder,calculater,cancelled,cancelling,cas,cascade,centimetre,childs,colour,colours,commen,connexion,currenty,dof,doubleclick,dum,eiter,elemente,ende,feld,finde,findf,freez,hist,iff,indicies,initialisation,initialise,initialised,initialises,initialisiert,inout,ist,kilometre,lod,mantatory,methode,metres,millimetre,modell,nd,noe,normale,normaly,nto,numer,oder,ontop,orgin,orginx,orginy,ot,pard,parms,pres,programm,que,recurrance,rougly,seperator,serie,sinc,strack,substraction,te,thist,thru,tread,uint,unter,vertexes,wallthickness,whitespaces -S ./.git,*.po,*.ts,./ChangeLog.txt,./src/3rdParty,./src/Mod/Assembly/App/opendcm,./src/CXX,./src/zipios++,./src/Base/swig*,./src/Mod/Robot/App/kdl_cp,./src/Mod/Import/App/SCL,./src/WindowsInstaller,./src/Doc/FreeCAD.uml,./build/doc/SourceDocu` --- src/App/Application.h | 2 +- src/Mod/Fem/femtaskpanels/task_material_common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App/Application.h b/src/App/Application.h index fbd20abc7c..2e7237ea9e 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -597,7 +597,7 @@ private: std::deque _pendingDocsReopen; std::map > _pendingDocMap; - // To prevent infinite recursion of reloading a partial document due a truely + // To prevent infinite recursion of reloading a partial document due a truly // missing object std::map > _docReloadAttempts; diff --git a/src/Mod/Fem/femtaskpanels/task_material_common.py b/src/Mod/Fem/femtaskpanels/task_material_common.py index 1ce0320928..4ceb7fa941 100644 --- a/src/Mod/Fem/femtaskpanels/task_material_common.py +++ b/src/Mod/Fem/femtaskpanels/task_material_common.py @@ -549,7 +549,7 @@ class _TaskPanel: # for example PoissonRatio value = Units.Quantity(inputfield_text).Value old_value = Units.Quantity(self.material[matProperty]).Value - # value = float(inputfield_text) # this fails on locale with komma + # value = float(inputfield_text) # this fails on locale with comma # https://forum.freecadweb.org/viewtopic.php?f=18&t=56912&p=523313#p523313 if value: if not (1 - variation < float(old_value) / value < 1 + variation): From a2d6c317fd24860f320ffa706ba3334b7bfe4636 Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Thu, 4 Nov 2021 12:06:25 +0100 Subject: [PATCH 50/68] [Examples] Add thumbnail to PDN example --- data/examples/PartDesignExample.FCStd | Bin 36250 -> 40455 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/examples/PartDesignExample.FCStd b/data/examples/PartDesignExample.FCStd index 8e5278bc540dcd22c1981df81e67997cef4abac2..58a01160851a7570e92b2467beccd936eb6aaf92 100644 GIT binary patch delta 14708 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 uw>~ehe@u=S91QI5Im+I-2qGZOAN5mT|G#~n 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 From 648c55c8a08e091bf2284bb9eaa3691f3b1fd28d Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Tue, 2 Nov 2021 19:07:23 +0100 Subject: [PATCH 51/68] [ViewProvider2DObject] Fix typo --- src/Mod/Part/Gui/ViewProvider2DObject.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.h b/src/Mod/Part/Gui/ViewProvider2DObject.h index a6fd7b9221..135265d0b8 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.h +++ b/src/Mod/Part/Gui/ViewProvider2DObject.h @@ -21,8 +21,8 @@ ***************************************************************************/ -#ifndef PARTGUI_IEWPROVIDER2DOBJECT_H -#define PARTGUI_IEWPROVIDER2DOBJECT_H +#ifndef PARTGUI_VIEWPROVIDER2DOBJECT_H +#define PARTGUI_VIEWPROVIDER2DOBJECT_H #include "ViewProvider.h" #include @@ -103,5 +103,5 @@ typedef Gui::ViewProviderPythonFeatureT ViewProvider2DObje } // namespace PartGui -#endif // PARTGUI_IEWPROVIDER2DOBJECT_H +#endif // PARTGUI_VIEWPROVIDER2DOBJECT_H From 76130c85ceb9495c56cfbfa59ac9ef4260c50a40 Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Tue, 2 Nov 2021 19:25:12 +0100 Subject: [PATCH 52/68] [ViewProvider2DObject=>Sketcher] Fix grid visibility management Error in grid visibility equation that makes grid to disappear when saving document in Edit mode --- src/Mod/Part/Gui/ViewProvider2DObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.cpp b/src/Mod/Part/Gui/ViewProvider2DObject.cpp index 3c1ad047a4..a19a47803c 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.cpp +++ b/src/Mod/Part/Gui/ViewProvider2DObject.cpp @@ -274,7 +274,7 @@ void ViewProvider2DObjectGrid::onChanged(const App::Property* prop) ViewProviderPart::onChanged(prop); if (prop == &ShowGrid || prop == &ShowOnlyInEditMode || prop == &Visibility) { - if (ShowGrid.getValue() && Visibility.getValue() && !(ShowOnlyInEditMode.getValue() && !this->isEditing())) + if (ShowGrid.getValue() && ((Visibility.getValue() && !ShowOnlyInEditMode.getValue()) || this->isEditing())) createGrid(); else Gui::coinRemoveAllChildren(GridRoot); From 7cd3930dd8756cac144cf2222ecc3bb2258680d0 Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Tue, 2 Nov 2021 19:46:42 +0100 Subject: [PATCH 53/68] [Sketcher] Removed lines that was introduced to workaround grid visibility management issues --- src/Mod/Sketcher/Gui/TaskSketcherGeneral.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherGeneral.cpp b/src/Mod/Sketcher/Gui/TaskSketcherGeneral.cpp index bebd6a5844..81a2ec0077 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherGeneral.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherGeneral.cpp @@ -264,9 +264,6 @@ void TaskSketcherGeneral::onChangedSketchView(const Gui::ViewProvider& vp, QSignalBlocker block(widget); widget->checkGridView(sketchView->ShowGrid.getValue()); widget->enableGridSettings(sketchView->ShowGrid.getValue()); - if (sketchView->ShowGrid.getValue()) { - sketchView->createGrid(); - } } else if (&sketchView->GridSize == &prop) { QSignalBlocker block(widget); @@ -293,7 +290,6 @@ void TaskSketcherGeneral::onToggleGridView(bool on) Base::ConnectionBlocker block(changedSketchView); sketchView->ShowGrid.setValue(on); widget->enableGridSettings(on); - if (on) sketchView->createGrid(); } void TaskSketcherGeneral::onSetGridSize(double val) From ef100d55e9d50bd74ed8cc505a5d059de02cc146 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 11:10:38 +0100 Subject: [PATCH 54/68] Gui: add support of TinkerCAD navigation style --- src/Gui/CMakeLists.txt | 1 + src/Gui/NavigationStyle.h | 18 ++ src/Gui/SoFCDB.cpp | 1 + src/Gui/TinkerCADNavigationStyle.cpp | 285 +++++++++++++++++++++++++++ 4 files changed, 305 insertions(+) create mode 100644 src/Gui/TinkerCADNavigationStyle.cpp diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index b901e97e8d..8990d7af4f 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -839,6 +839,7 @@ SET(View3D_CPP_SRCS MayaGestureNavigationStyle.cpp OpenCascadeNavigationStyle.cpp OpenSCADNavigationStyle.cpp + TinkerCADNavigationStyle.cpp TouchpadNavigationStyle.cpp GestureNavigationStyle.cpp SplitView3DInventor.cpp diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 5f394c550b..3ef16058d7 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -37,6 +37,7 @@ #include #include #include +#include // forward declarations class SoEvent; @@ -429,6 +430,23 @@ private: SoMouseButtonEvent mouseDownConsumedEvent; }; +class GuiExport TinkerCADNavigationStyle : public UserNavigationStyle { + typedef UserNavigationStyle inherited; + + TYPESYSTEM_HEADER(); + +public: + TinkerCADNavigationStyle(); + ~TinkerCADNavigationStyle(); + const char* mouseButtons(ViewerMode); + +protected: + SbBool processSoEvent(const SoEvent * const ev); + +private: + SoMouseButtonEvent mouseDownConsumedEvent; +}; + } // namespace Gui Q_DECLARE_OPERATORS_FOR_FLAGS(Gui::NavigationStyle::RotationCenterModes) diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index 0dc42462fe..92e9045ad3 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -186,6 +186,7 @@ void Gui::SoFCDB::init() GestureNavigationStyle ::init(); OpenCascadeNavigationStyle ::init(); OpenSCADNavigationStyle ::init(); + TinkerCADNavigationStyle ::init(); GLGraphicsItem ::init(); GLFlagWindow ::init(); diff --git a/src/Gui/TinkerCADNavigationStyle.cpp b/src/Gui/TinkerCADNavigationStyle.cpp new file mode 100644 index 0000000000..524d1eb210 --- /dev/null +++ b/src/Gui/TinkerCADNavigationStyle.cpp @@ -0,0 +1,285 @@ +/*************************************************************************** + * Copyright (c) 2021 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include "InventorAll.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include "NavigationStyle.h" +#include "View3DInventorViewer.h" +#include "Application.h" +#include "MenuManager.h" +#include "MouseSelection.h" + +using namespace Gui; + +// ---------------------------------------------------------------------------------- + +/* TRANSLATOR Gui::TinkerCADNavigationStyle */ + +TYPESYSTEM_SOURCE(Gui::TinkerCADNavigationStyle, Gui::UserNavigationStyle) + +TinkerCADNavigationStyle::TinkerCADNavigationStyle() +{ +} + +TinkerCADNavigationStyle::~TinkerCADNavigationStyle() +{ +} + +const char* TinkerCADNavigationStyle::mouseButtons(ViewerMode mode) +{ + switch (mode) { + case NavigationStyle::SELECTION: + return QT_TR_NOOP("Press left mouse button"); + case NavigationStyle::PANNING: + return QT_TR_NOOP("Press middle mouse button"); + case NavigationStyle::DRAGGING: + return QT_TR_NOOP("Press right mouse button"); + case NavigationStyle::ZOOMING: + return QT_TR_NOOP("Scroll middle mouse button"); + default: + return "No description"; + } +} + +SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev) +{ + // Events when in "ready-to-seek" mode are ignored, except those + // which influence the seek mode itself -- these are handled further + // up the inheritance hierarchy. + if (this->isSeekMode()) { return inherited::processSoEvent(ev); } + // Switch off viewing mode + if (!this->isSeekMode() && !this->isAnimating() && this->isViewing()) + this->setViewing(false); // by default disable viewing mode to render the scene + + const SoType type(ev->getTypeId()); + + const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); + const SbVec2s pos(ev->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); + + const SbVec2f prevnormalized = this->lastmouseposition; + this->lastmouseposition = posn; + + // Set to true if any event processing happened. Note that it is not + // necessary to restrict ourselves to only do one "action" for an + // event, we only need this flag to see if any processing happened + // at all. + SbBool processed = false; + + const ViewerMode curmode = this->currentmode; + ViewerMode newmode = curmode; + + // Mismatches in state of the modifier keys happens if the user + // presses or releases them outside the viewer window. + syncModifierKeys(ev); + + // give the nodes in the foreground root the chance to handle events (e.g color bar) + if (!viewer->isEditing()) { + processed = handleEventInForeground(ev); + if (processed) + return true; + } + + // Keyboard handling + if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { + const SoKeyboardEvent * const event = static_cast(ev); + processed = handleKeyboardEvent(event, posn); + } + + // Mouse Button / Spaceball Button handling + if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) { + const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev; + const int button = event->getButton(); + const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; + SbBool canOpenPopupMenu = false; + + switch (button) { + case SoMouseButtonEvent::BUTTON1: + this->button1down = press; + if (press && (curmode == NavigationStyle::SEEK_WAIT_MODE)) { + newmode = NavigationStyle::SEEK_MODE; + this->seekToPoint(pos); // implicitly calls interactiveCountInc() + processed = true; + } + else if (viewer->isEditing() && (curmode == NavigationStyle::SPINNING)) { + processed = true; + } + // issue #0002433: avoid to swallow the UP event if down the + // scene graph somewhere a dialog gets opened + else if (press) { + SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); + float dci = (float)QApplication::doubleClickInterval()/1000.0f; + // a double-click? + if (tmp.getValue() < dci) { + mouseDownConsumedEvent = *event; + mouseDownConsumedEvent.setTime(ev->getTime()); + processed = true; + } + else { + mouseDownConsumedEvent.setTime(ev->getTime()); + // 'ANY' is used to mark that we don't know yet if it will + // be a double-click event. + mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); + } + } + else if (!press) { + if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { + // now handle the postponed event + inherited::processSoEvent(&mouseDownConsumedEvent); + mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); + } + } + break; + case SoMouseButtonEvent::BUTTON2: + // If we are in edit mode then simply ignore the RMB events + // to pass the event to the base class. + this->button2down = press; + if (press) { + mouseDownConsumedEvent = *event; + mouseDownConsumedEvent.setTime(ev->getTime()); + } + else if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON2) { + SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); + float dci = float(QApplication::doubleClickInterval())/1000.0f; + // time between press and release event + if (tmp.getValue() < dci) { + canOpenPopupMenu = true; + } + } + + // About to start rotating + if (press && (curmode == NavigationStyle::IDLE)) { + // Use this variable to spot move events + saveCursorPosition(ev); + this->centerTime = ev->getTime(); + processed = true; + } + else if (!press && (curmode == NavigationStyle::DRAGGING)) { + if (!viewer->isEditing() && canOpenPopupMenu) { + // If we are in drag mode but mouse hasn't been moved open the context-menu + if (this->isPopupMenuEnabled()) { + this->openPopupMenu(event->getPosition()); + } + } + newmode = NavigationStyle::IDLE; + processed = true; + } + break; + case SoMouseButtonEvent::BUTTON3: + this->button3down = press; + if (press) { + this->centerTime = ev->getTime(); + float ratio = vp.getViewportAspectRatio(); + SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio); + this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue()); + } + else if (curmode == NavigationStyle::PANNING) { + newmode = NavigationStyle::IDLE; + processed = true; + } + break; + default: + break; + } + } + + // Mouse Movement handling + if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) { + const SoLocation2Event * const event = (const SoLocation2Event *) ev; + if (curmode == NavigationStyle::PANNING) { + float ratio = vp.getViewportAspectRatio(); + panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized); + processed = true; + } + else if (curmode == NavigationStyle::DRAGGING) { + this->addToLog(event->getPosition(), event->getTime()); + this->spin(posn); + moveCursorPosition(); + processed = true; + } + } + + // Spaceball & Joystick handling + if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) { + const SoMotion3Event * const event = static_cast(ev); + if (event) + this->processMotionEvent(event); + processed = true; + } + + enum { + BUTTON1DOWN = 1 << 0, + BUTTON3DOWN = 1 << 1, + CTRLDOWN = 1 << 2, + SHIFTDOWN = 1 << 3, + BUTTON2DOWN = 1 << 4 + }; + unsigned int combo = + (this->button1down ? BUTTON1DOWN : 0) | + (this->button2down ? BUTTON2DOWN : 0) | + (this->button3down ? BUTTON3DOWN : 0) | + (this->ctrldown ? CTRLDOWN : 0) | + (this->shiftdown ? SHIFTDOWN : 0); + + switch (combo) { + case 0: + if (curmode == NavigationStyle::SPINNING) { break; } + newmode = NavigationStyle::IDLE; + break; + case BUTTON1DOWN: + newmode = NavigationStyle::SELECTION; + break; + case BUTTON2DOWN: + newmode = NavigationStyle::DRAGGING; + break; + case BUTTON3DOWN: + newmode = NavigationStyle::PANNING; + break; + default: + break; + } + + if (newmode != curmode) { + this->setViewingMode(newmode); + } + + // If not handled in this class, pass on upwards in the inheritance + // hierarchy. + if (!processed) + processed = inherited::processSoEvent(ev); + return processed; +} From 5b023b0af596de62c4d27b59d8d0ea7f1e64cc50 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 12:58:36 +0100 Subject: [PATCH 55/68] Gui: [skip ci] rename handleKeyboardEvent to processKeyboardEvent --- src/Gui/BlenderNavigationStyle.cpp | 2 +- src/Gui/CADNavigationStyle.cpp | 2 +- src/Gui/InventorNavigationStyle.cpp | 2 +- src/Gui/NavigationStyle.cpp | 104 +++++++++++++------------ src/Gui/NavigationStyle.h | 2 +- src/Gui/OpenCascadeNavigationStyle.cpp | 2 +- src/Gui/OpenSCADNavigationStyle.cpp | 2 +- src/Gui/RevitNavigationStyle.cpp | 2 +- src/Gui/TinkerCADNavigationStyle.cpp | 2 +- src/Gui/TouchpadNavigationStyle.cpp | 2 +- 10 files changed, 64 insertions(+), 58 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index 81fc6f5202..eff5b5a43d 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -117,7 +117,7 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index 53d893f0ff..563b4db7f0 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -121,7 +121,7 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 4c57393cb4..543cd8c522 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -125,7 +125,7 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index dc66d74beb..bdb8d5e111 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1387,55 +1387,6 @@ void NavigationStyle::syncModifierKeys(const SoEvent * const ev) } } -SbBool NavigationStyle::handleKeyboardEvent(const SoKeyboardEvent * const event, const SbVec2f & posn) -{ - SbBool processed = false; - const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; - switch (event->getKey()) { - case SoKeyboardEvent::LEFT_CONTROL: - case SoKeyboardEvent::RIGHT_CONTROL: - this->ctrldown = press; - break; - case SoKeyboardEvent::LEFT_SHIFT: - case SoKeyboardEvent::RIGHT_SHIFT: - this->shiftdown = press; - break; - case SoKeyboardEvent::LEFT_ALT: - case SoKeyboardEvent::RIGHT_ALT: - this->altdown = press; - break; - case SoKeyboardEvent::H: - processed = true; - viewer->saveHomePosition(); - break; - case SoKeyboardEvent::R: - processed = true; - viewer->resetToHomePosition(); - break; - case SoKeyboardEvent::S: - case SoKeyboardEvent::HOME: - case SoKeyboardEvent::LEFT_ARROW: - case SoKeyboardEvent::UP_ARROW: - case SoKeyboardEvent::RIGHT_ARROW: - case SoKeyboardEvent::DOWN_ARROW: - if (!this->isViewing()) - this->setViewing(true); - break; - case SoKeyboardEvent::PAGE_UP: - processed = true; - doZoom(viewer->getSoRenderManager()->getCamera(), getDelta(), posn); - break; - case SoKeyboardEvent::PAGE_DOWN: - processed = true; - doZoom(viewer->getSoRenderManager()->getCamera(), -getDelta(), posn); - break; - default: - break; - } - - return processed; -} - // The viewer is a state machine, and all changes to the current state // are made through this call. void NavigationStyle::setViewingMode(const ViewerMode newmode) @@ -1664,6 +1615,61 @@ SbBool NavigationStyle::processMotionEvent(const SoMotion3Event * const ev) return true; } +SbBool NavigationStyle::processKeyboardEvent(const SoKeyboardEvent * const event) +{ + SbBool processed = false; + const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; + switch (event->getKey()) { + case SoKeyboardEvent::LEFT_CONTROL: + case SoKeyboardEvent::RIGHT_CONTROL: + this->ctrldown = press; + break; + case SoKeyboardEvent::LEFT_SHIFT: + case SoKeyboardEvent::RIGHT_SHIFT: + this->shiftdown = press; + break; + case SoKeyboardEvent::LEFT_ALT: + case SoKeyboardEvent::RIGHT_ALT: + this->altdown = press; + break; + case SoKeyboardEvent::H: + processed = true; + viewer->saveHomePosition(); + break; + case SoKeyboardEvent::R: + processed = true; + viewer->resetToHomePosition(); + break; + case SoKeyboardEvent::S: + case SoKeyboardEvent::HOME: + case SoKeyboardEvent::LEFT_ARROW: + case SoKeyboardEvent::UP_ARROW: + case SoKeyboardEvent::RIGHT_ARROW: + case SoKeyboardEvent::DOWN_ARROW: + if (!this->isViewing()) + this->setViewing(true); + break; + case SoKeyboardEvent::PAGE_UP: + { + processed = true; + const SbVec2f posn = normalizePixelPos(event->getPosition()); + doZoom(viewer->getSoRenderManager()->getCamera(), getDelta(), posn); + break; + } + case SoKeyboardEvent::PAGE_DOWN: + { + processed = true; + const SbVec2f posn = normalizePixelPos(event->getPosition()); + doZoom(viewer->getSoRenderManager()->getCamera(), -getDelta(), posn); + break; + } + default: + break; + } + + return processed; +} + void NavigationStyle::setPopupMenuEnabled(const SbBool on) { this->menuenabled = on; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 3ef16058d7..7a6fbfdb9d 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -152,6 +152,7 @@ public: int getViewingMode() const; virtual SbBool processEvent(const SoEvent * const ev); virtual SbBool processMotionEvent(const SoMotion3Event * const ev); + virtual SbBool processKeyboardEvent(const SoKeyboardEvent * const event); void setPopupMenuEnabled(const SbBool on); SbBool isPopupMenuEnabled(void) const; @@ -215,7 +216,6 @@ protected: void addToLog(const SbVec2s pos, const SbTime time); void syncModifierKeys(const SoEvent * const ev); - SbBool handleKeyboardEvent(const SoKeyboardEvent * const event, const SbVec2f & posn); protected: struct { // tracking mouse movement in a log diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index 58501d9d7b..0b79107ea4 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -117,7 +117,7 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 75b34dac11..629eb0be29 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -117,7 +117,7 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index 3408929108..99bf448e4c 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -117,7 +117,7 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/TinkerCADNavigationStyle.cpp b/src/Gui/TinkerCADNavigationStyle.cpp index 524d1eb210..14b540dd7a 100644 --- a/src/Gui/TinkerCADNavigationStyle.cpp +++ b/src/Gui/TinkerCADNavigationStyle.cpp @@ -117,7 +117,7 @@ SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index 606412fdd8..035aa118b0 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -117,7 +117,7 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const event = static_cast(ev); - processed = handleKeyboardEvent(event, posn); + processed = processKeyboardEvent(event); } // Mouse Button / Spaceball Button handling From b1ab5c3b8fd0243195d3ba9d24e6381bb917083d Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 14:00:09 +0100 Subject: [PATCH 56/68] Gui: [skip ci] in MayaGestureNavigationStyle rename mousedownConsumedEvent to mousedownConsumedEvents --- src/Gui/MayaGestureNavigationStyle.cpp | 10 +++++----- src/Gui/NavigationStyle.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Gui/MayaGestureNavigationStyle.cpp b/src/Gui/MayaGestureNavigationStyle.cpp index 2a34f062e5..8c9bd83c6c 100644 --- a/src/Gui/MayaGestureNavigationStyle.cpp +++ b/src/Gui/MayaGestureNavigationStyle.cpp @@ -378,11 +378,11 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev) this->mouseMoveThresholdBroken = false; pan(viewer->getSoRenderManager()->getCamera());//set up panningplane int &cnt = this->mousedownConsumedCount; - this->mousedownConsumedEvent[cnt] = *event;//hopefully, a shallow copy is enough. There are no pointers stored in events, apparently. Will lose a subclass, though. + this->mousedownConsumedEvents[cnt] = *event;//hopefully, a shallow copy is enough. There are no pointers stored in events, apparently. Will lose a subclass, though. cnt++; assert(cnt<=2); - if(cnt>static_cast(sizeof(mousedownConsumedEvent))){ - cnt=sizeof(mousedownConsumedEvent);//we are in trouble + if(cnt>static_cast(sizeof(mousedownConsumedEvents))){ + cnt=sizeof(mousedownConsumedEvents);//we are in trouble } processed = true;//just consume this event, and wait for the move threshold to be broken to start dragging/panning } @@ -396,7 +396,7 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev) if(! processed) { //re-synthesize all previously-consumed mouseDowns, if any. They might have been re-synthesized already when threshold was broken. for( int i=0; i < this->mousedownConsumedCount; i++ ){ - inherited::processSoEvent(& (this->mousedownConsumedEvent[i]));//simulate the previously-comsumed mousedown. + inherited::processSoEvent(& (this->mousedownConsumedEvents[i]));//simulate the previously-comsumed mousedown. } this->mousedownConsumedCount = 0; processed = inherited::processSoEvent(ev);//explicitly, just for clarity that we are sending a full click sequence. @@ -441,7 +441,7 @@ SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev) //no, we are not entering navigation. //re-synthesize all previously-consumed mouseDowns, if any, and propagate this mousemove. for( int i=0; i < this->mousedownConsumedCount; i++ ){ - inherited::processSoEvent(& (this->mousedownConsumedEvent[i]));//simulate the previously-comsumed mousedown. + inherited::processSoEvent(& (this->mousedownConsumedEvents[i]));//simulate the previously-comsumed mousedown. } this->mousedownConsumedCount = 0; processed = inherited::processSoEvent(ev);//explicitly, just for clarity that we are sending a full click sequence. diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 7a6fbfdb9d..9a3b27cd38 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -372,7 +372,7 @@ protected: short mouseMoveThreshold;//setting. Minimum move required to consider it a move (in pixels). bool mouseMoveThresholdBroken;//a flag that the move threshold was surpassed since last mousedown. int mousedownConsumedCount;//a flag for remembering that a mousedown of button1/button2 was consumed. - SoMouseButtonEvent mousedownConsumedEvent[5];//the event that was consumed and is to be refired. 2 should be enough, but just for a case of the maximum 5 buttons... + SoMouseButtonEvent mousedownConsumedEvents[5];//the event that was consumed and is to be refired. 2 should be enough, but just for a case of the maximum 5 buttons... bool testMoveThreshold(const SbVec2s currentPos) const; bool thisClickIsComplex;//a flag that becomes set when a complex clicking pattern is detected (i.e., two or more mouse buttons were down at the same time). From 528ffce5932723e56daa0f36554d64250cc26984 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 14:37:18 +0100 Subject: [PATCH 57/68] Gui: add method NavigationStyle::processClickEvent() to reduce code duplication in sub-classes --- src/Gui/BlenderNavigationStyle.cpp | 26 ++------------------ src/Gui/CADNavigationStyle.cpp | 26 ++------------------ src/Gui/InventorNavigationStyle.cpp | 26 ++------------------ src/Gui/NavigationStyle.cpp | 33 ++++++++++++++++++++++++++ src/Gui/NavigationStyle.h | 20 ++-------------- src/Gui/OpenCascadeNavigationStyle.cpp | 26 ++------------------ src/Gui/OpenSCADNavigationStyle.cpp | 26 ++------------------ src/Gui/RevitNavigationStyle.cpp | 26 ++------------------ src/Gui/TinkerCADNavigationStyle.cpp | 26 ++------------------ src/Gui/TouchpadNavigationStyle.cpp | 26 ++------------------ 10 files changed, 51 insertions(+), 210 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index eff5b5a43d..563b124e86 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -146,30 +146,8 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index 563b4db7f0..c9e351fb2b 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -158,30 +158,8 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 543cd8c522..b9bfe2986d 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -179,30 +179,8 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) processed = true; this->lockrecenter = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index bdb8d5e111..ccfefe15ea 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1670,6 +1670,39 @@ SbBool NavigationStyle::processKeyboardEvent(const SoKeyboardEvent * const event return processed; } +SbBool NavigationStyle::processClickEvent(const SoMouseButtonEvent * const event) +{ + // issue #0002433: avoid to swallow the UP event if down the + // scene graph somewhere a dialog gets opened + SbBool processed = false; + const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; + if (press) { + SbTime tmp = (event->getTime() - mouseDownConsumedEvent.getTime()); + float dci = (float)QApplication::doubleClickInterval()/1000.0f; + // a double-click? + if (tmp.getValue() < dci) { + mouseDownConsumedEvent = *event; + mouseDownConsumedEvent.setTime(event->getTime()); + processed = true; + } + else { + mouseDownConsumedEvent.setTime(event->getTime()); + // 'ANY' is used to mark that we don't know yet if it will + // be a double-click event. + mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); + } + } + else if (!press) { + if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { + // now handle the postponed event + NavigationStyle::processSoEvent(&mouseDownConsumedEvent); + mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); + } + } + + return processed; +} + void NavigationStyle::setPopupMenuEnabled(const SbBool on) { this->menuenabled = on; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 9a3b27cd38..a8a5f58e4f 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -153,6 +153,7 @@ public: virtual SbBool processEvent(const SoEvent * const ev); virtual SbBool processMotionEvent(const SoMotion3Event * const ev); virtual SbBool processKeyboardEvent(const SoKeyboardEvent * const event); + virtual SbBool processClickEvent(const SoMouseButtonEvent * const event); void setPopupMenuEnabled(const SbBool on); SbBool isPopupMenuEnabled(void) const; @@ -227,6 +228,7 @@ protected: View3DInventorViewer* viewer; ViewerMode currentmode; + SoMouseButtonEvent mouseDownConsumedEvent; SbVec2f lastmouseposition; SbVec2s globalPos; SbVec2s localPos; @@ -296,9 +298,6 @@ public: protected: SbBool processSoEvent(const SoEvent * const ev); - -private: - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport CADNavigationStyle : public UserNavigationStyle { @@ -316,7 +315,6 @@ protected: private: SbBool lockButton1; - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport RevitNavigationStyle : public UserNavigationStyle { @@ -334,7 +332,6 @@ protected: private: SbBool lockButton1; - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport BlenderNavigationStyle : public UserNavigationStyle { @@ -352,7 +349,6 @@ protected: private: SbBool lockButton1; - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport MayaGestureNavigationStyle : public UserNavigationStyle { @@ -391,9 +387,6 @@ public: protected: SbBool processSoEvent(const SoEvent * const ev); - -private: - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport OpenCascadeNavigationStyle : public UserNavigationStyle { @@ -408,9 +401,6 @@ public: protected: SbBool processSoEvent(const SoEvent * const ev); - -private: - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport OpenSCADNavigationStyle : public UserNavigationStyle { @@ -425,9 +415,6 @@ public: protected: SbBool processSoEvent(const SoEvent * const ev); - -private: - SoMouseButtonEvent mouseDownConsumedEvent; }; class GuiExport TinkerCADNavigationStyle : public UserNavigationStyle { @@ -442,9 +429,6 @@ public: protected: SbBool processSoEvent(const SoEvent * const ev); - -private: - SoMouseButtonEvent mouseDownConsumedEvent; }; } // namespace Gui diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/OpenCascadeNavigationStyle.cpp index 0b79107ea4..1cbf7b322e 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/OpenCascadeNavigationStyle.cpp @@ -146,30 +146,8 @@ SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/OpenSCADNavigationStyle.cpp index 629eb0be29..c1c1ee1e6b 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/OpenSCADNavigationStyle.cpp @@ -146,30 +146,8 @@ SbBool OpenSCADNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (curmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/RevitNavigationStyle.cpp index 99bf448e4c..6bc4ee8ced 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/RevitNavigationStyle.cpp @@ -146,30 +146,8 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/TinkerCADNavigationStyle.cpp b/src/Gui/TinkerCADNavigationStyle.cpp index 14b540dd7a..50b28e47ad 100644 --- a/src/Gui/TinkerCADNavigationStyle.cpp +++ b/src/Gui/TinkerCADNavigationStyle.cpp @@ -138,30 +138,8 @@ SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (curmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index 035aa118b0..dbb2dc8b6c 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -146,30 +146,8 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) { processed = true; } - // issue #0002433: avoid to swallow the UP event if down the - // scene graph somewhere a dialog gets opened - else if (press) { - SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime()); - float dci = (float)QApplication::doubleClickInterval()/1000.0f; - // a double-click? - if (tmp.getValue() < dci) { - mouseDownConsumedEvent = *event; - mouseDownConsumedEvent.setTime(ev->getTime()); - processed = true; - } - else { - mouseDownConsumedEvent.setTime(ev->getTime()); - // 'ANY' is used to mark that we don't know yet if it will - // be a double-click event. - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } - } - else if (!press) { - if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) { - // now handle the postponed event - inherited::processSoEvent(&mouseDownConsumedEvent); - mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY); - } + else { + processed = processClickEvent(event); } break; case SoMouseButtonEvent::BUTTON2: From 4a1c1c70049c68de08035eab96b523596934ab9b Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 18:16:19 +0100 Subject: [PATCH 58/68] C++11: modernize use nullptr (replaces NULL or 0) --- src/Gui/NavigationStyle.cpp | 65 +++++------- src/Gui/NavigationStyle.h | 22 ++-- src/Gui/Quarter/ContextMenu.cpp | 8 +- src/Gui/Quarter/ContextMenu.h | 2 +- src/Gui/Quarter/DragDropHandler.cpp | 4 +- src/Gui/Quarter/EventFilter.cpp | 2 +- src/Gui/Quarter/ImageReader.cpp | 4 +- src/Gui/Quarter/ImageReader.h | 4 +- src/Gui/Quarter/InputDevice.cpp | 2 +- src/Gui/Quarter/InteractionMode.cpp | 4 +- src/Gui/Quarter/InteractionMode.h | 4 +- src/Gui/Quarter/Keyboard.cpp | 4 +- src/Gui/Quarter/KeyboardP.cpp | 10 +- src/Gui/Quarter/KeyboardP.h | 4 +- src/Gui/Quarter/Mouse.cpp | 6 +- src/Gui/Quarter/NativeEvent.cpp | 2 +- src/Gui/Quarter/QtCoinCompatibility.cpp | 2 +- src/Gui/Quarter/Quarter.cpp | 6 +- src/Gui/Quarter/Quarter.h | 2 +- src/Gui/Quarter/QuarterP.cpp | 14 +-- src/Gui/Quarter/QuarterWidget.cpp | 100 +++++++++--------- src/Gui/Quarter/QuarterWidget.h | 64 +++++------ src/Gui/Quarter/QuarterWidgetP.cpp | 34 +++--- src/Gui/Quarter/QuarterWidgetP.h | 10 +- src/Gui/Quarter/SensorManager.cpp | 12 +-- src/Gui/Quarter/SensorManager.h | 10 +- src/Gui/Quarter/SignalThread.cpp | 8 +- src/Gui/Quarter/SignalThread.h | 10 +- src/Gui/Quarter/SoQTQuarterAdaptor.cpp | 30 +++--- src/Gui/Quarter/SoQTQuarterAdaptor.h | 44 ++++---- src/Gui/Quarter/SpaceNavigatorDevice.cpp | 2 +- src/Gui/Quarter/devices/InputDevice.h | 2 +- src/Gui/Quarter/devices/Keyboard.h | 2 +- src/Gui/Quarter/devices/Mouse.h | 2 +- .../Quarter/devices/SpaceNavigatorDevice.h | 2 +- src/Gui/Quarter/eventhandlers/EventFilter.h | 2 +- 36 files changed, 247 insertions(+), 258 deletions(-) diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index ccfefe15ea..c75ad3869a 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -64,7 +64,7 @@ struct NavigationStyleP { { this->animationsteps = 0; this->animationdelta = 0; - this->animsensor = 0; + this->animsensor = nullptr; this->sensitivity = 2.0f; this->resetcursorpos = false; this->rotationCenterFound = false; @@ -173,7 +173,7 @@ const Base::Type& NavigationStyleEvent::style() const TYPESYSTEM_SOURCE_ABSTRACT(Gui::NavigationStyle,Base::BaseClass) -NavigationStyle::NavigationStyle() : viewer(0), mouseSelection(0) +NavigationStyle::NavigationStyle() : viewer(nullptr), mouseSelection(nullptr) { PRIVATE(this) = new NavigationStyleP(); PRIVATE(this)->animsensor = new SoTimerSensor(NavigationStyleP::viewAnimationCB, this); @@ -261,17 +261,17 @@ void NavigationStyle::finalize() delete[] this->log.time; } -void NavigationStyle::interactiveCountInc(void) +void NavigationStyle::interactiveCountInc() { viewer->interactiveCountInc(); } -void NavigationStyle::interactiveCountDec(void) +void NavigationStyle::interactiveCountDec() { viewer->interactiveCountDec(); } -int NavigationStyle::getInteractiveCount(void) const +int NavigationStyle::getInteractiveCount() const { return viewer->getInteractiveCount(); } @@ -288,7 +288,7 @@ NavigationStyle::OrbitStyle NavigationStyle::getOrbitStyle() const return NavigationStyle::OrbitStyle(projector->getOrbitStyle()); } -SbBool NavigationStyle::isViewing(void) const +SbBool NavigationStyle::isViewing() const { return viewer->isViewing(); } @@ -298,7 +298,7 @@ void NavigationStyle::setViewing(SbBool enable) viewer->setViewing(enable); } -SbBool NavigationStyle::isSeekMode(void) const +SbBool NavigationStyle::isSeekMode() const { return viewer->isSeekMode(); } @@ -321,7 +321,7 @@ void NavigationStyle::seekToPoint(const SbVec3f& scenepos) SbBool NavigationStyle::lookAtPoint(const SbVec2s screenpos) { SoCamera* cam = viewer->getSoRenderManager()->getCamera(); - if (cam == 0) return false; + if (cam == nullptr) return false; SoRayPickAction rpaction(viewer->getSoRenderManager()->getViewportRegion()); rpaction.setPoint(screenpos); @@ -343,7 +343,7 @@ SbBool NavigationStyle::lookAtPoint(const SbVec2s screenpos) void NavigationStyle::lookAtPoint(const SbVec3f& pos) { SoCamera* cam = viewer->getSoRenderManager()->getCamera(); - if (cam == 0) return; + if (cam == nullptr) return; PRIVATE(this)->rotationCenterFound = false; // Find global coordinates of focal point. @@ -401,7 +401,7 @@ void NavigationStyle::lookAtPoint(const SbVec3f& pos) void NavigationStyle::setCameraOrientation(const SbRotation& rot, SbBool moveToCenter) { SoCamera* cam = viewer->getSoRenderManager()->getCamera(); - if (cam == 0) return; + if (cam == nullptr) return; // Find global coordinates of focal point. SbVec3f direction; @@ -611,7 +611,7 @@ void NavigationStyle::viewAll() */ void NavigationStyle::reorientCamera(SoCamera * cam, const SbRotation & rot) { - if (cam == NULL) return; + if (cam == nullptr) return; // Find global coordinates of focal point. SbVec3f direction; @@ -630,7 +630,7 @@ void NavigationStyle::reorientCamera(SoCamera * cam, const SbRotation & rot) void NavigationStyle::panCamera(SoCamera * cam, float aspectratio, const SbPlane & panplane, const SbVec2f & currpos, const SbVec2f & prevpos) { - if (cam == NULL) return; // can happen for empty scenegraph + if (cam == nullptr) return; // can happen for empty scenegraph if (currpos == prevpos) return; // useless invocation @@ -659,7 +659,7 @@ void NavigationStyle::pan(SoCamera* camera) // The plane we're projecting the mouse coordinates to get 3D // coordinates should stay the same during the whole pan // operation, so we should calculate this value here. - if (camera == NULL) { // can happen for empty scenegraph + if (camera == nullptr) { // can happen for empty scenegraph this->panningplane = SbPlane(SbVec3f(0, 0, 1), 0); } else { @@ -689,7 +689,7 @@ void NavigationStyle::panToCenter(const SbPlane & pplane, const SbVec2f & currpo */ void NavigationStyle::zoom(SoCamera * cam, float diffvalue) { - if (cam == NULL) return; // can happen for empty scenegraph + if (cam == nullptr) return; // can happen for empty scenegraph SoType t = cam->getTypeId(); SbName tname = t.getName(); @@ -870,7 +870,7 @@ void NavigationStyle::setRotationCenter(const SbVec3f& cnt) SbVec3f NavigationStyle::getFocalPoint() const { SoCamera* cam = viewer->getSoRenderManager()->getCamera(); - if (cam == 0) + if (cam == nullptr) return SbVec3f(0,0,0); // Find global coordinates of focal point. @@ -887,7 +887,7 @@ SbVec3f NavigationStyle::getFocalPoint() const void NavigationStyle::spin(const SbVec2f & pointerpos) { if (this->log.historysize < 2) return; - assert(this->spinprojector != NULL); + assert(this->spinprojector != nullptr); const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); SbVec2s glsize(vp.getViewportSizePixels()); @@ -965,7 +965,7 @@ void NavigationStyle::spin(const SbVec2f & pointerpos) * \param prevpos previous normalized position of mouse pointer */ void NavigationStyle::spin_simplified(SoCamera* cam, SbVec2f curpos, SbVec2f prevpos){ - assert(this->spinprojector != NULL); + assert(this->spinprojector != nullptr); // 0000333: Turntable camera rotation SbMatrix mat; @@ -1163,7 +1163,7 @@ NavigationStyle::setAnimationEnabled(const SbBool enable) */ SbBool -NavigationStyle::isAnimationEnabled(void) const +NavigationStyle::isAnimationEnabled() const { return this->spinanimatingallowed; } @@ -1172,7 +1172,7 @@ NavigationStyle::isAnimationEnabled(void) const Query if the model in the viewer is currently in spinning mode after a user drag. */ -SbBool NavigationStyle::isAnimating(void) const +SbBool NavigationStyle::isAnimating() const { return this->currentmode == NavigationStyle::SPINNING; } @@ -1195,7 +1195,7 @@ void NavigationStyle::startAnimating(const SbVec3f& axis, float velocity) this->spinRotation = rot; } -void NavigationStyle::stopAnimating(void) +void NavigationStyle::stopAnimating() { if (this->currentmode != NavigationStyle::SPINNING) { return; @@ -1321,7 +1321,7 @@ void NavigationStyle::stopSelection() if (mouseSelection) { mouseSelection->releaseMouseModel(); delete mouseSelection; - mouseSelection = 0; + mouseSelection = nullptr; } } @@ -1367,7 +1367,7 @@ void NavigationStyle::addToLog(const SbVec2s pos, const SbTime time) // This method "clears" the mouse location log, used for spin // animation calculations. -void NavigationStyle::clearLog(void) +void NavigationStyle::clearLog() { this->log.historysize = 0; } @@ -1461,14 +1461,14 @@ SbBool NavigationStyle::processEvent(const SoEvent * const ev) pcPolygon = mouseSelection->getPositions(); selectedRole = mouseSelection->selectedRole(); delete mouseSelection; - mouseSelection = 0; + mouseSelection = nullptr; syncWithEvent(ev); return NavigationStyle::processSoEvent(ev); } else if (hd==AbstractMouseSelection::Cancel) { pcPolygon.clear(); delete mouseSelection; - mouseSelection = 0; + mouseSelection = nullptr; syncWithEvent(ev); return NavigationStyle::processSoEvent(ev); } @@ -1495,11 +1495,8 @@ SbBool NavigationStyle::processEvent(const SoEvent * const ev) SbBool NavigationStyle::processSoEvent(const SoEvent * const ev) { - const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion(); - const SbVec2s size(vp.getViewportSizePixels()); const SbVec2s pos(ev->getPosition()); - const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1), - (float) pos[1] / (float) std::max((int)(size[1] - 1), 1)); + const SbVec2f posn = normalizePixelPos(pos); bool processed = false; //handle mouse wheel zoom @@ -1529,15 +1526,7 @@ void NavigationStyle::syncWithEvent(const SoEvent * const ev) // Mismatches in state of the modifier keys happens if the user // presses or releases them outside the viewer window. - if (this->ctrldown != ev->wasCtrlDown()) { - this->ctrldown = ev->wasCtrlDown(); - } - if (this->shiftdown != ev->wasShiftDown()) { - this->shiftdown = ev->wasShiftDown(); - } - if (this->altdown != ev->wasAltDown()) { - this->altdown = ev->wasAltDown(); - } + syncModifierKeys(ev); // Keyboard handling if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { @@ -1708,7 +1697,7 @@ void NavigationStyle::setPopupMenuEnabled(const SbBool on) this->menuenabled = on; } -SbBool NavigationStyle::isPopupMenuEnabled(void) const +SbBool NavigationStyle::isPopupMenuEnabled() const { return this->menuenabled; } diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index a8a5f58e4f..f35e61f37a 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -116,11 +116,11 @@ public: void setViewer(View3DInventorViewer*); void setAnimationEnabled(const SbBool enable); - SbBool isAnimationEnabled(void) const; + SbBool isAnimationEnabled() const; void startAnimating(const SbVec3f& axis, float velocity); - void stopAnimating(void); - SbBool isAnimating(void) const; + void stopAnimating(); + SbBool isAnimating() const; void setSensitivity(float); float getSensitivity() const; @@ -156,14 +156,14 @@ public: virtual SbBool processClickEvent(const SoMouseButtonEvent * const event); void setPopupMenuEnabled(const SbBool on); - SbBool isPopupMenuEnabled(void) const; + SbBool isPopupMenuEnabled() const; void startSelection(AbstractMouseSelection*); void startSelection(SelectionMode = Lasso); void abortSelection(); void stopSelection(); SbBool isSelecting() const; - const std::vector& getPolygon(SelectionRole* role=0) const; + const std::vector& getPolygon(SelectionRole* role=nullptr) const; void setOrbitStyle(OrbitStyle style); OrbitStyle getOrbitStyle() const; @@ -172,13 +172,13 @@ protected: void initialize(); void finalize(); - void interactiveCountInc(void); - void interactiveCountDec(void); - int getInteractiveCount(void) const; + void interactiveCountInc(); + void interactiveCountDec(); + int getInteractiveCount() const; - SbBool isViewing(void) const; + SbBool isViewing() const; void setViewing(SbBool); - SbBool isSeekMode(void) const; + SbBool isSeekMode() const; void setSeekMode(SbBool enable); SbBool seekToPoint(const SbVec2s screenpos); void seekToPoint(const SbVec3f& scenepos); @@ -213,7 +213,7 @@ protected: void syncWithEvent(const SoEvent * const ev); virtual void openPopupMenu(const SbVec2s& position); - void clearLog(void); + void clearLog(); void addToLog(const SbVec2s pos, const SbTime time); void syncModifierKeys(const SoEvent * const ev); diff --git a/src/Gui/Quarter/ContextMenu.cpp b/src/Gui/Quarter/ContextMenu.cpp index dc28d9500b..88c3535a5e 100644 --- a/src/Gui/Quarter/ContextMenu.cpp +++ b/src/Gui/Quarter/ContextMenu.cpp @@ -58,9 +58,9 @@ ContextMenu::ContextMenu(QuarterWidget * quarterwidget) SoRenderManager * sorendermanager = quarterwidget->getSoRenderManager(); - QActionGroup * rendermodegroup = NULL; - QActionGroup * stereomodegroup = NULL; - QActionGroup * transparencytypegroup = NULL; + QActionGroup * rendermodegroup = nullptr; + QActionGroup * stereomodegroup = nullptr; + QActionGroup * transparencytypegroup = nullptr; foreach (QAction * action, quarterwidget->renderModeActions()) { if (!rendermodegroup) { @@ -138,7 +138,7 @@ ContextMenu::~ContextMenu() } QMenu * -ContextMenu::getMenu(void) const +ContextMenu::getMenu() const { return this->contextmenu; } diff --git a/src/Gui/Quarter/ContextMenu.h b/src/Gui/Quarter/ContextMenu.h index a9965001e3..13603e194d 100644 --- a/src/Gui/Quarter/ContextMenu.h +++ b/src/Gui/Quarter/ContextMenu.h @@ -48,7 +48,7 @@ public: ContextMenu(QuarterWidget * quarterwidget); ~ContextMenu(); - QMenu * getMenu(void) const; + QMenu * getMenu() const; public Q_SLOTS: void changeRenderMode(QAction * action); diff --git a/src/Gui/Quarter/DragDropHandler.cpp b/src/Gui/Quarter/DragDropHandler.cpp index 55b4d9ee43..796295cde8 100644 --- a/src/Gui/Quarter/DragDropHandler.cpp +++ b/src/Gui/Quarter/DragDropHandler.cpp @@ -50,7 +50,7 @@ #include #include -#include +#include namespace SIM { namespace Coin3D { namespace Quarter { @@ -152,7 +152,7 @@ DragDropHandlerP::dropEvent(QDropEvent * event) // attempt to import it root = SoDB::readAll(&in); - if (root == NULL) return; + if (root == nullptr) return; // set new scenegraph this->quarterwidget->setSceneGraph(root); diff --git a/src/Gui/Quarter/EventFilter.cpp b/src/Gui/Quarter/EventFilter.cpp index 695159ceea..faf056d375 100644 --- a/src/Gui/Quarter/EventFilter.cpp +++ b/src/Gui/Quarter/EventFilter.cpp @@ -177,7 +177,7 @@ EventFilter::eventFilter(QObject * obj, QEvent * qevent) Returns mouse position in global coordinates */ const QPoint & -EventFilter::globalMousePosition(void) const +EventFilter::globalMousePosition() const { return PRIVATE(this)->globalmousepos; } diff --git a/src/Gui/Quarter/ImageReader.cpp b/src/Gui/Quarter/ImageReader.cpp index 9d8336e261..75c121db98 100644 --- a/src/Gui/Quarter/ImageReader.cpp +++ b/src/Gui/Quarter/ImageReader.cpp @@ -39,12 +39,12 @@ using namespace SIM::Coin3D::Quarter; -ImageReader::ImageReader(void) +ImageReader::ImageReader() { SbImage::addReadImageCB(ImageReader::readImageCB, this); } -ImageReader::~ImageReader(void) +ImageReader::~ImageReader() { SbImage::removeReadImageCB(ImageReader::readImageCB, this); } diff --git a/src/Gui/Quarter/ImageReader.h b/src/Gui/Quarter/ImageReader.h index a0da5ad526..9d8ad2c186 100644 --- a/src/Gui/Quarter/ImageReader.h +++ b/src/Gui/Quarter/ImageReader.h @@ -43,8 +43,8 @@ namespace SIM { namespace Coin3D { namespace Quarter { class ImageReader { public: - ImageReader(void); - ~ImageReader(void); + ImageReader(); + ~ImageReader(); SbBool readImage(const SbString & filename, SbImage & image) const; diff --git a/src/Gui/Quarter/InputDevice.cpp b/src/Gui/Quarter/InputDevice.cpp index a29d74d7fa..b2cc008b6a 100644 --- a/src/Gui/Quarter/InputDevice.cpp +++ b/src/Gui/Quarter/InputDevice.cpp @@ -48,7 +48,7 @@ using namespace SIM::Coin3D::Quarter; devices. */ -InputDevice::InputDevice(void) : quarter(nullptr) +InputDevice::InputDevice() : quarter(nullptr) { this->mousepos = SbVec2s(0, 0); } diff --git a/src/Gui/Quarter/InteractionMode.cpp b/src/Gui/Quarter/InteractionMode.cpp index d9a0375bcd..f7a577261f 100644 --- a/src/Gui/Quarter/InteractionMode.cpp +++ b/src/Gui/Quarter/InteractionMode.cpp @@ -34,7 +34,7 @@ InteractionMode::setEnabled(bool yes) } bool -InteractionMode::enabled(void) const +InteractionMode::enabled() const { return this->isenabled; } @@ -62,7 +62,7 @@ InteractionMode::setOn(bool on) } bool -InteractionMode::on(void) const +InteractionMode::on() const { return this->altkeydown; } diff --git a/src/Gui/Quarter/InteractionMode.h b/src/Gui/Quarter/InteractionMode.h index 0397b3290f..d2562844b8 100644 --- a/src/Gui/Quarter/InteractionMode.h +++ b/src/Gui/Quarter/InteractionMode.h @@ -54,10 +54,10 @@ public: virtual ~InteractionMode(); void setEnabled(bool yes); - bool enabled(void) const; + bool enabled() const; void setOn(bool on); - bool on(void) const; + bool on() const; protected: virtual bool eventFilter(QObject *, QEvent * event); diff --git a/src/Gui/Quarter/Keyboard.cpp b/src/Gui/Quarter/Keyboard.cpp index b7fbf9f028..e16e4a62f3 100644 --- a/src/Gui/Quarter/Keyboard.cpp +++ b/src/Gui/Quarter/Keyboard.cpp @@ -55,7 +55,7 @@ using namespace SIM::Coin3D::Quarter; #define PRIVATE(obj) obj->pimpl -Keyboard::Keyboard(void) +Keyboard::Keyboard() { PRIVATE(this) = new KeyboardP(this); } @@ -81,7 +81,7 @@ Keyboard::translateEvent(QEvent * event) case QEvent::KeyRelease: return PRIVATE(this)->keyEvent((QKeyEvent *) event); default: - return NULL; + return nullptr; } } diff --git a/src/Gui/Quarter/KeyboardP.cpp b/src/Gui/Quarter/KeyboardP.cpp index 6854ffae7d..1cbc87907c 100644 --- a/src/Gui/Quarter/KeyboardP.cpp +++ b/src/Gui/Quarter/KeyboardP.cpp @@ -44,7 +44,7 @@ KeyboardP::KeyboardP(Keyboard * publ) PUBLIC(this) = publ; this->keyboard = new SoKeyboardEvent; - if (keyboardmap == NULL) { + if (keyboardmap == nullptr) { keyboardmap = new KeyMap; keypadmap = new KeyMap; this->initKeyMap(); @@ -57,7 +57,7 @@ KeyboardP::~KeyboardP() } bool -KeyboardP::debugKeyEvents(void) +KeyboardP::debugKeyEvents() { const char * env = coin_getenv("QUARTER_DEBUG_KEYEVENTS"); return env && (atoi(env) > 0); @@ -103,11 +103,11 @@ KeyboardP::keyEvent(QKeyEvent * qevent) return this->keyboard; } -KeyboardP::KeyMap * KeyboardP::keyboardmap = NULL; -KeyboardP::KeyMap * KeyboardP::keypadmap = NULL; +KeyboardP::KeyMap * KeyboardP::keyboardmap = nullptr; +KeyboardP::KeyMap * KeyboardP::keypadmap = nullptr; void -KeyboardP::initKeyMap(void) +KeyboardP::initKeyMap() { // keyboard keyboardmap->insert(Qt::Key_Shift, SoKeyboardEvent::LEFT_SHIFT); diff --git a/src/Gui/Quarter/KeyboardP.h b/src/Gui/Quarter/KeyboardP.h index e5dfe6a998..fb0e5d2cbd 100644 --- a/src/Gui/Quarter/KeyboardP.h +++ b/src/Gui/Quarter/KeyboardP.h @@ -49,8 +49,8 @@ public: ~KeyboardP(); const SoEvent * keyEvent(QKeyEvent * event); - void initKeyMap(void); - static bool debugKeyEvents(void); + void initKeyMap(); + static bool debugKeyEvents(); typedef QMap KeyMap; static KeyMap * keyboardmap; diff --git a/src/Gui/Quarter/Mouse.cpp b/src/Gui/Quarter/Mouse.cpp index 6667dee6bd..fa182955fc 100644 --- a/src/Gui/Quarter/Mouse.cpp +++ b/src/Gui/Quarter/Mouse.cpp @@ -95,7 +95,7 @@ using namespace SIM::Coin3D::Quarter; #define PRIVATE(obj) obj->pimpl #define PUBLIC(obj) obj->publ -Mouse::Mouse(void) +Mouse::Mouse() { PRIVATE(this) = new MouseP(this); } @@ -131,9 +131,9 @@ Mouse::translateEvent(QEvent * event) return PRIVATE(this)->mouseWheelEvent((QWheelEvent *) event); case QEvent::Resize: PRIVATE(this)->resizeEvent((QResizeEvent *) event); - return NULL; + return nullptr; default: - return NULL; + return nullptr; } } diff --git a/src/Gui/Quarter/NativeEvent.cpp b/src/Gui/Quarter/NativeEvent.cpp index def9b09c02..790f21cd68 100644 --- a/src/Gui/Quarter/NativeEvent.cpp +++ b/src/Gui/Quarter/NativeEvent.cpp @@ -55,7 +55,7 @@ NativeEvent::getEvent() const NativeEvent::NativeEvent() : QEvent(QEvent::User) { - this->rawevent = NULL; + this->rawevent = nullptr; } #endif // !HAVE_SPACENAV_LIB diff --git a/src/Gui/Quarter/QtCoinCompatibility.cpp b/src/Gui/Quarter/QtCoinCompatibility.cpp index 3ffd38cf81..c62431a462 100644 --- a/src/Gui/Quarter/QtCoinCompatibility.cpp +++ b/src/Gui/Quarter/QtCoinCompatibility.cpp @@ -22,7 +22,7 @@ QtCoinCompatibility::QImageToSbImage(const QImage & image, SbImage & sbimage) } SbVec2s size((short) w, (short) h); - sbimage.setValue(size, c, NULL); + sbimage.setValue(size, c, nullptr); unsigned char * buffer = sbimage.getValue(size, c); if (c == 1) { diff --git a/src/Gui/Quarter/Quarter.cpp b/src/Gui/Quarter/Quarter.cpp index 5d48a0f64a..976b02e478 100644 --- a/src/Gui/Quarter/Quarter.cpp +++ b/src/Gui/Quarter/Quarter.cpp @@ -152,7 +152,7 @@ using namespace SIM::Coin3D::Quarter; -static QuarterP * self = NULL; +static QuarterP * self = nullptr; /*! initialize Quarter, and implicitly Coin @@ -182,14 +182,14 @@ Quarter::init(bool initCoin) clean up resources */ void -Quarter::clean(void) +Quarter::clean() { COMPILE_ONLY_BEFORE(2,0,0,"Should not be encapsulated in double Quarter namespace"); assert(self); bool initCoin = self->initCoin; delete self; - self = NULL; + self = nullptr; if (initCoin) { // SoDB::finish() will clean up everything that has been diff --git a/src/Gui/Quarter/Quarter.h b/src/Gui/Quarter/Quarter.h index 1853b5118e..22e538e7c2 100644 --- a/src/Gui/Quarter/Quarter.h +++ b/src/Gui/Quarter/Quarter.h @@ -39,7 +39,7 @@ namespace SIM { namespace Coin3D { namespace Quarter { namespace Quarter { void QUARTER_DLL_API init(bool initCoin = true); - void QUARTER_DLL_API clean(void); + void QUARTER_DLL_API clean(); void QUARTER_DLL_API setTimerEpsilon(double sec); } diff --git a/src/Gui/Quarter/QuarterP.cpp b/src/Gui/Quarter/QuarterP.cpp index fbfd30e380..f227527065 100644 --- a/src/Gui/Quarter/QuarterP.cpp +++ b/src/Gui/Quarter/QuarterP.cpp @@ -4,13 +4,13 @@ #include "KeyboardP.h" using namespace SIM::Coin3D::Quarter; -QuarterP::StateCursorMap * QuarterP::statecursormap = NULL; +QuarterP::StateCursorMap * QuarterP::statecursormap = nullptr; -QuarterP::QuarterP(void) +QuarterP::QuarterP() { this->sensormanager = new SensorManager; this->imagereader = new ImageReader; - assert(QuarterP::statecursormap == NULL); + assert(QuarterP::statecursormap == nullptr); QuarterP::statecursormap = new StateCursorMap; } @@ -20,17 +20,17 @@ QuarterP::~QuarterP() delete this->imagereader; delete this->sensormanager; - assert(QuarterP::statecursormap != NULL); + assert(QuarterP::statecursormap != nullptr); delete QuarterP::statecursormap; // FIXME: Why not use an atexit mechanism for this? - if (KeyboardP::keyboardmap != NULL) { + if (KeyboardP::keyboardmap != nullptr) { KeyboardP::keyboardmap->clear(); KeyboardP::keypadmap->clear(); delete KeyboardP::keyboardmap; delete KeyboardP::keypadmap; - KeyboardP::keyboardmap = NULL; - KeyboardP::keypadmap = NULL; + KeyboardP::keyboardmap = nullptr; + KeyboardP::keypadmap = nullptr; } diff --git a/src/Gui/Quarter/QuarterWidget.cpp b/src/Gui/Quarter/QuarterWidget.cpp index e7034760b9..b3376d851c 100644 --- a/src/Gui/Quarter/QuarterWidget.cpp +++ b/src/Gui/Quarter/QuarterWidget.cpp @@ -52,7 +52,7 @@ #pragma warning(disable : 4267) #endif -#include +#include #include #include @@ -152,7 +152,7 @@ class CustomGLWidget : public QOpenGLWidget { public: QSurfaceFormat myFormat; - CustomGLWidget(const QSurfaceFormat& format, QWidget* parent = 0, const QOpenGLWidget* shareWidget = 0, Qt::WindowFlags f = Qt::WindowFlags()) + CustomGLWidget(const QSurfaceFormat& format, QWidget* parent = nullptr, const QOpenGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()) : QOpenGLWidget(parent, f), myFormat(format) { Q_UNUSED(shareWidget); @@ -308,7 +308,7 @@ QuarterWidget::constructor(const QtGLFormat & format, const QtGLWidget * sharewi PRIVATE(this)->eventfilter = new EventFilter(this); PRIVATE(this)->interactionmode = new InteractionMode(this); - PRIVATE(this)->currentStateMachine = NULL; + PRIVATE(this)->currentStateMachine = nullptr; PRIVATE(this)->headlight = new SoDirectionalLight; PRIVATE(this)->headlight->ref(); @@ -364,10 +364,10 @@ QuarterWidget::~QuarterWidget() delete PRIVATE(this)->currentStateMachine; } PRIVATE(this)->headlight->unref(); - PRIVATE(this)->headlight = NULL; - this->setSceneGraph(NULL); - this->setSoRenderManager(NULL); - this->setSoEventManager(NULL); + PRIVATE(this)->headlight = nullptr; + this->setSceneGraph(nullptr); + this->setSoRenderManager(nullptr); + this->setSoEventManager(nullptr); delete PRIVATE(this)->eventfilter; delete PRIVATE(this); } @@ -418,7 +418,7 @@ QuarterWidget::setHeadlightEnabled(bool onoff) Returns true if the headlight is on, false if it is off */ bool -QuarterWidget::headlightEnabled(void) const +QuarterWidget::headlightEnabled() const { return PRIVATE(this)->headlight->on.getValue(); } @@ -427,7 +427,7 @@ QuarterWidget::headlightEnabled(void) const Returns the light used for the headlight. */ SoDirectionalLight * -QuarterWidget::getHeadlight(void) const +QuarterWidget::getHeadlight() const { return PRIVATE(this)->headlight; } @@ -452,7 +452,7 @@ QuarterWidget::setClearZBuffer(bool onoff) Returns true if the z buffer is cleared before rendering. */ bool -QuarterWidget::clearZBuffer(void) const +QuarterWidget::clearZBuffer() const { return PRIVATE(this)->clearzbuffer; } @@ -477,7 +477,7 @@ QuarterWidget::setClearWindow(bool onoff) Returns true if the rendering buffer is cleared before rendering. */ bool -QuarterWidget::clearWindow(void) const +QuarterWidget::clearWindow() const { return PRIVATE(this)->clearwindow; } @@ -503,7 +503,7 @@ QuarterWidget::setInteractionModeEnabled(bool onoff) Returns true if interaction mode is enabled, false otherwise. */ bool -QuarterWidget::interactionModeEnabled(void) const +QuarterWidget::interactionModeEnabled() const { return PRIVATE(this)->interactionmode->enabled(); } @@ -527,7 +527,7 @@ QuarterWidget::setInteractionModeOn(bool onoff) Returns true if interaction mode is on. */ bool -QuarterWidget::interactionModeOn(void) const +QuarterWidget::interactionModeOn() const { return PRIVATE(this)->interactionmode->on(); } @@ -536,7 +536,7 @@ QuarterWidget::interactionModeOn(void) const Returns the Coin cache context id for this widget. */ uint32_t -QuarterWidget::getCacheContextId(void) const +QuarterWidget::getCacheContextId() const { return PRIVATE(this)->getCacheContextId(); } @@ -562,7 +562,7 @@ QuarterWidget::setTransparencyType(TransparencyType type) \retval The current \ref TransparencyType */ QuarterWidget::TransparencyType -QuarterWidget::transparencyType(void) const +QuarterWidget::transparencyType() const { assert(PRIVATE(this)->sorendermanager); SoGLRenderAction * action = PRIVATE(this)->sorendermanager->getGLRenderAction(); @@ -590,7 +590,7 @@ QuarterWidget::setRenderMode(RenderMode mode) \retval The current \ref RenderMode */ QuarterWidget::RenderMode -QuarterWidget::renderMode(void) const +QuarterWidget::renderMode() const { assert(PRIVATE(this)->sorendermanager); return static_cast(PRIVATE(this)->sorendermanager->getRenderMode()); @@ -618,7 +618,7 @@ QuarterWidget::setStereoMode(StereoMode mode) \retval The current \ref StereoMode */ QuarterWidget::StereoMode -QuarterWidget::stereoMode(void) const +QuarterWidget::stereoMode() const { assert(PRIVATE(this)->sorendermanager); return static_cast(PRIVATE(this)->sorendermanager->getStereoMode()); @@ -636,7 +636,7 @@ the widget is located within, and updated whenever any change occurs, emitting a */ qreal -QuarterWidget::devicePixelRatio(void) const +QuarterWidget::devicePixelRatio() const { return PRIVATE(this)->device_pixel_ratio; } @@ -653,11 +653,11 @@ QuarterWidget::setSceneGraph(SoNode * node) if (PRIVATE(this)->scene) { PRIVATE(this)->scene->unref(); - PRIVATE(this)->scene = NULL; + PRIVATE(this)->scene = nullptr; } - SoCamera * camera = NULL; - SoSeparator * superscene = NULL; + SoCamera * camera = nullptr; + SoSeparator * superscene = nullptr; bool viewall = false; if (node) { @@ -690,7 +690,7 @@ QuarterWidget::setSceneGraph(SoNode * node) Returns pointer to root of scene graph */ SoNode * -QuarterWidget::getSceneGraph(void) const +QuarterWidget::getSceneGraph() const { return PRIVATE(this)->scene; } @@ -702,10 +702,10 @@ void QuarterWidget::setSoRenderManager(SoRenderManager * manager) { bool carrydata = false; - SoNode * scene = NULL; - SoCamera * camera = NULL; + SoNode * scene = nullptr; + SoCamera * camera = nullptr; SbViewportRegion vp; - if (PRIVATE(this)->sorendermanager && (manager != NULL)) { + if (PRIVATE(this)->sorendermanager && (manager != nullptr)) { scene = PRIVATE(this)->sorendermanager->getSceneGraph(); camera = PRIVATE(this)->sorendermanager->getCamera(); vp = PRIVATE(this)->sorendermanager->getViewportRegion(); @@ -735,7 +735,7 @@ QuarterWidget::setSoRenderManager(SoRenderManager * manager) Returns a pointer to the render manager. */ SoRenderManager * -QuarterWidget::getSoRenderManager(void) const +QuarterWidget::getSoRenderManager() const { return PRIVATE(this)->sorendermanager; } @@ -747,10 +747,10 @@ void QuarterWidget::setSoEventManager(SoEventManager * manager) { bool carrydata = false; - SoNode * scene = NULL; - SoCamera * camera = NULL; + SoNode * scene = nullptr; + SoCamera * camera = nullptr; SbViewportRegion vp; - if (PRIVATE(this)->soeventmanager && (manager != NULL)) { + if (PRIVATE(this)->soeventmanager && (manager != nullptr)) { scene = PRIVATE(this)->soeventmanager->getSceneGraph(); camera = PRIVATE(this)->soeventmanager->getCamera(); vp = PRIVATE(this)->soeventmanager->getViewportRegion(); @@ -780,7 +780,7 @@ QuarterWidget::setSoEventManager(SoEventManager * manager) Returns a pointer to the event manager */ SoEventManager * -QuarterWidget::getSoEventManager(void) const +QuarterWidget::getSoEventManager() const { return PRIVATE(this)->soeventmanager; } @@ -789,7 +789,7 @@ QuarterWidget::getSoEventManager(void) const Returns a pointer to the event filter */ EventFilter * -QuarterWidget::getEventFilter(void) const +QuarterWidget::getEventFilter() const { return PRIVATE(this)->eventfilter; } @@ -798,7 +798,7 @@ QuarterWidget::getEventFilter(void) const Reposition the current camera to display the entire scene */ void -QuarterWidget::viewAll(void) +QuarterWidget::viewAll() { const SbName viewallevent("sim.coin3d.coin.navigation.ViewAll"); for (int c = 0; c < PRIVATE(this)->soeventmanager->getNumSoScXMLStateMachines(); ++c) { @@ -816,7 +816,7 @@ QuarterWidget::viewAll(void) Camera typically seeks towards what the mouse is pointing at. */ void -QuarterWidget::seek(void) +QuarterWidget::seek() { const SbName seekevent("sim.coin3d.coin.navigation.Seek"); for (int c = 0; c < PRIVATE(this)->soeventmanager->getNumSoScXMLStateMachines(); ++c) { @@ -830,10 +830,10 @@ QuarterWidget::seek(void) } bool -QuarterWidget::updateDevicePixelRatio(void) { +QuarterWidget::updateDevicePixelRatio() { qreal dev_pix_ratio = 1.0; QWidget* winwidg = window(); - QWindow* win = NULL; + QWindow* win = nullptr; if(winwidg) { win = winwidg->windowHandle(); } @@ -1023,7 +1023,7 @@ bool QuarterWidget::viewportEvent(QEvent* event) render manager and render the scene by calling this method. */ void -QuarterWidget::redraw(void) +QuarterWidget::redraw() { // we're triggering the next paintGL(). Set a flag to remember this // to avoid that we process the delay queue in paintGL() @@ -1050,7 +1050,7 @@ QuarterWidget::redraw(void) Overridden from QGLWidget to render the scenegraph */ void -QuarterWidget::actualRedraw(void) +QuarterWidget::actualRedraw() { PRIVATE(this)->sorendermanager->render(PRIVATE(this)->clearwindow, PRIVATE(this)->clearzbuffer); @@ -1102,7 +1102,7 @@ QuarterWidget::setBackgroundColor(const QColor & color) rendering the scene. */ QColor -QuarterWidget::backgroundColor(void) const +QuarterWidget::backgroundColor() const { SbColor4f bg = PRIVATE(this)->sorendermanager->getBackgroundColor(); @@ -1116,7 +1116,7 @@ QuarterWidget::backgroundColor(void) const Returns the context menu used by the widget. */ QMenu * -QuarterWidget::getContextMenu(void) const +QuarterWidget::getContextMenu() const { return PRIVATE(this)->contextMenu(); } @@ -1125,7 +1125,7 @@ QuarterWidget::getContextMenu(void) const \retval Is context menu enabled? */ bool -QuarterWidget::contextMenuEnabled(void) const +QuarterWidget::contextMenuEnabled() const { return PRIVATE(this)->contextmenuenabled; } @@ -1175,8 +1175,8 @@ void QuarterWidget::removeStateMachine(SoScXMLStateMachine * statemachine) { SoEventManager * em = this->getSoEventManager(); - statemachine->setSceneGraphRoot(NULL); - statemachine->setActiveCamera(NULL); + statemachine->setSceneGraphRoot(nullptr); + statemachine->setActiveCamera(nullptr); em->removeSoScXMLStateMachine(statemachine); } @@ -1184,7 +1184,7 @@ QuarterWidget::removeStateMachine(SoScXMLStateMachine * statemachine) See \ref QWidget::minimumSizeHint */ QSize -QuarterWidget::minimumSizeHint(void) const +QuarterWidget::minimumSizeHint() const { return QSize(50, 50); } @@ -1195,7 +1195,7 @@ QuarterWidget::minimumSizeHint(void) const QuarterWidget, add these actions to the menu. */ QList -QuarterWidget::transparencyTypeActions(void) const +QuarterWidget::transparencyTypeActions() const { return PRIVATE(this)->transparencyTypeActions(); } @@ -1206,7 +1206,7 @@ QuarterWidget::transparencyTypeActions(void) const QuarterWidget, add these actions to the menu. */ QList -QuarterWidget::stereoModeActions(void) const +QuarterWidget::stereoModeActions() const { return PRIVATE(this)->stereoModeActions(); } @@ -1217,7 +1217,7 @@ QuarterWidget::stereoModeActions(void) const QuarterWidget, add these actions to the menu. */ QList -QuarterWidget::renderModeActions(void) const +QuarterWidget::renderModeActions() const { return PRIVATE(this)->renderModeActions(); } @@ -1239,7 +1239,7 @@ QuarterWidget::renderModeActions(void) const Removes any navigationModeFile set. */ void -QuarterWidget::resetNavigationModeFile(void) { +QuarterWidget::resetNavigationModeFile() { this->setNavigationModeFile(QUrl()); } @@ -1276,7 +1276,7 @@ QuarterWidget::setNavigationModeFile(const QUrl & url) if (PRIVATE(this)->currentStateMachine) { this->removeStateMachine(PRIVATE(this)->currentStateMachine); delete PRIVATE(this)->currentStateMachine; - PRIVATE(this)->currentStateMachine = NULL; + PRIVATE(this)->currentStateMachine = nullptr; PRIVATE(this)->navigationModeFile = url; } return; @@ -1287,7 +1287,7 @@ QuarterWidget::setNavigationModeFile(const QUrl & url) } QByteArray filenametmp = filename.toLocal8Bit(); - ScXMLStateMachine * stateMachine = NULL; + ScXMLStateMachine * stateMachine = nullptr; if (filenametmp.startsWith("coin:")){ stateMachine = ScXML::readFile(filenametmp.data()); @@ -1350,7 +1350,7 @@ QuarterWidget::setNavigationModeFile(const QUrl & url) \retval The current navigationModeFile */ const QUrl & -QuarterWidget::navigationModeFile(void) const +QuarterWidget::navigationModeFile() const { return PRIVATE(this)->navigationModeFile; } diff --git a/src/Gui/Quarter/QuarterWidget.h b/src/Gui/Quarter/QuarterWidget.h index d69bf2c5b6..80e781b613 100644 --- a/src/Gui/Quarter/QuarterWidget.h +++ b/src/Gui/Quarter/QuarterWidget.h @@ -81,9 +81,9 @@ class QUARTER_DLL_API QuarterWidget : public QGraphicsView { public: - explicit QuarterWidget(QWidget * parent = 0, const QtGLWidget * sharewidget = 0, Qt::WindowFlags f = Qt::WindowFlags()); - explicit QuarterWidget(QtGLContext * context, QWidget * parent = 0, const QtGLWidget * sharewidget = 0, Qt::WindowFlags f = Qt::WindowFlags()); - explicit QuarterWidget(const QtGLFormat & format, QWidget * parent = 0, const QtGLWidget * shareWidget = 0, Qt::WindowFlags f = Qt::WindowFlags()); + explicit QuarterWidget(QWidget * parent = nullptr, const QtGLWidget * sharewidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + explicit QuarterWidget(QtGLContext * context, QWidget * parent = nullptr, const QtGLWidget * sharewidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + explicit QuarterWidget(const QtGLFormat & format, QWidget * parent = nullptr, const QtGLWidget * shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); virtual ~QuarterWidget(); enum TransparencyType { @@ -117,70 +117,70 @@ public: INTERLEAVED_COLUMNS = SoRenderManager::INTERLEAVED_COLUMNS }; - TransparencyType transparencyType(void) const; - RenderMode renderMode(void) const; - StereoMode stereoMode(void) const; + TransparencyType transparencyType() const; + RenderMode renderMode() const; + StereoMode stereoMode() const; void setBackgroundColor(const QColor & color); - QColor backgroundColor(void) const; + QColor backgroundColor() const; - qreal devicePixelRatio(void) const; + qreal devicePixelRatio() const; - void resetNavigationModeFile(void); + void resetNavigationModeFile(); void setNavigationModeFile(const QUrl & url = QUrl(QString::fromLatin1(DEFAULT_NAVIGATIONFILE))); - const QUrl & navigationModeFile(void) const; + const QUrl & navigationModeFile() const; void setContextMenuEnabled(bool yes); - bool contextMenuEnabled(void) const; - QMenu * getContextMenu(void) const; + bool contextMenuEnabled() const; + QMenu * getContextMenu() const; - bool headlightEnabled(void) const; + bool headlightEnabled() const; void setHeadlightEnabled(bool onoff); - SoDirectionalLight * getHeadlight(void) const; + SoDirectionalLight * getHeadlight() const; - bool clearZBuffer(void) const; + bool clearZBuffer() const; void setClearZBuffer(bool onoff); - bool clearWindow(void) const; + bool clearWindow() const; void setClearWindow(bool onoff); - bool interactionModeEnabled(void) const; + bool interactionModeEnabled() const; void setInteractionModeEnabled(bool onoff); - bool interactionModeOn(void) const; + bool interactionModeOn() const; void setInteractionModeOn(bool onoff); void setStateCursor(const SbName & state, const QCursor & cursor); QCursor stateCursor(const SbName & state); - uint32_t getCacheContextId(void) const; + uint32_t getCacheContextId() const; virtual void setSceneGraph(SoNode * root); - virtual SoNode * getSceneGraph(void) const; + virtual SoNode * getSceneGraph() const; void setSoEventManager(SoEventManager * manager); - SoEventManager * getSoEventManager(void) const; + SoEventManager * getSoEventManager() const; void setSoRenderManager(SoRenderManager * manager); - SoRenderManager * getSoRenderManager(void) const; + SoRenderManager * getSoRenderManager() const; - EventFilter * getEventFilter(void) const; + EventFilter * getEventFilter() const; void addStateMachine(SoScXMLStateMachine * statemachine); void removeStateMachine(SoScXMLStateMachine * statemachine); virtual bool processSoEvent(const SoEvent * event); - virtual QSize minimumSizeHint(void) const; + virtual QSize minimumSizeHint() const; - QList transparencyTypeActions(void) const; - QList stereoModeActions(void) const; - QList renderModeActions(void) const; + QList transparencyTypeActions() const; + QList stereoModeActions() const; + QList renderModeActions() const; public Q_SLOTS: - virtual void viewAll(void); - virtual void seek(void); + virtual void viewAll(); + virtual void seek(); - void redraw(void); + void redraw(); void setRenderMode(RenderMode mode); void setStereoMode(StereoMode mode); @@ -197,8 +197,8 @@ protected: virtual void paintEvent(QPaintEvent*); virtual void resizeEvent(QResizeEvent*); virtual bool viewportEvent(QEvent* event); - virtual void actualRedraw(void); - virtual bool updateDevicePixelRatio(void); + virtual void actualRedraw(); + virtual bool updateDevicePixelRatio(); private: void constructor(const QtGLFormat& format, const QtGLWidget* sharewidget); diff --git a/src/Gui/Quarter/QuarterWidgetP.cpp b/src/Gui/Quarter/QuarterWidgetP.cpp index 4cba6614b3..8c5a84c84f 100644 --- a/src/Gui/Quarter/QuarterWidgetP.cpp +++ b/src/Gui/Quarter/QuarterWidgetP.cpp @@ -57,7 +57,7 @@ #include "ContextMenu.h" #include "QuarterP.h" -#include +#include using namespace SIM::Coin3D::Quarter; @@ -67,19 +67,19 @@ public: SbList widgetlist; }; -static SbList * cachecontext_list = NULL; +static SbList * cachecontext_list = nullptr; QuarterWidgetP::QuarterWidgetP(QuarterWidget * masterptr, const QtGLWidget * sharewidget) : master(masterptr), - scene(NULL), - eventfilter(NULL), - interactionmode(NULL), - sorendermanager(NULL), - soeventmanager(NULL), + scene(nullptr), + eventfilter(nullptr), + interactionmode(nullptr), + sorendermanager(nullptr), + soeventmanager(nullptr), initialsorendermanager(false), initialsoeventmanager(false), - headlight(NULL), - cachecontext(NULL), + headlight(nullptr), + cachecontext(nullptr), contextmenuenabled(true), autoredrawenabled(true), interactionmodeenabled(false), @@ -87,7 +87,7 @@ QuarterWidgetP::QuarterWidgetP(QuarterWidget * masterptr, const QtGLWidget * sha clearwindow(true), addactions(true), device_pixel_ratio(1.0), - contextmenu(NULL) + contextmenu(nullptr) { this->cachecontext = findCacheContext(masterptr, sharewidget); @@ -121,11 +121,11 @@ QuarterWidgetP::searchForCamera(SoNode * root) return (SoCamera *) node; } } - return NULL; + return nullptr; } uint32_t -QuarterWidgetP::getCacheContextId(void) const +QuarterWidgetP::getCacheContextId() const { return this->cachecontext->id; } @@ -133,7 +133,7 @@ QuarterWidgetP::getCacheContextId(void) const QuarterWidgetP_cachecontext * QuarterWidgetP::findCacheContext(QuarterWidget * widget, const QtGLWidget * sharewidget) { - if (cachecontext_list == NULL) { + if (cachecontext_list == nullptr) { // FIXME: static memory leak cachecontext_list = new SbList ; } @@ -257,7 +257,7 @@ QuarterWidgetP::statechangecb(void * userdata, ScXMLStateMachine * statemachine, QList -QuarterWidgetP::transparencyTypeActions(void) const +QuarterWidgetP::transparencyTypeActions() const { if (this->transparencytypeactions.isEmpty()) { this->transparencytypegroup = new QActionGroup(this->master); @@ -277,7 +277,7 @@ QuarterWidgetP::transparencyTypeActions(void) const } QList -QuarterWidgetP::stereoModeActions(void) const +QuarterWidgetP::stereoModeActions() const { if (this->stereomodeactions.isEmpty()) { this->stereomodegroup = new QActionGroup(this->master); @@ -291,7 +291,7 @@ QuarterWidgetP::stereoModeActions(void) const } QList -QuarterWidgetP::renderModeActions(void) const +QuarterWidgetP::renderModeActions() const { if (this->rendermodeactions.isEmpty()) { this->rendermodegroup = new QActionGroup(this->master); @@ -308,7 +308,7 @@ QuarterWidgetP::renderModeActions(void) const #undef ADD_ACTION QMenu * -QuarterWidgetP::contextMenu(void) +QuarterWidgetP::contextMenu() { if (!this->contextmenu) { this->contextmenu = new ContextMenu(this->master); diff --git a/src/Gui/Quarter/QuarterWidgetP.h b/src/Gui/Quarter/QuarterWidgetP.h index 7b5c99dc78..d9373961cb 100644 --- a/src/Gui/Quarter/QuarterWidgetP.h +++ b/src/Gui/Quarter/QuarterWidgetP.h @@ -66,12 +66,12 @@ public: ~QuarterWidgetP(); SoCamera * searchForCamera(SoNode * root); - uint32_t getCacheContextId(void) const; - QMenu * contextMenu(void); + uint32_t getCacheContextId() const; + QMenu * contextMenu(); - QList transparencyTypeActions(void) const; - QList renderModeActions(void) const; - QList stereoModeActions(void) const; + QList transparencyTypeActions() const; + QList renderModeActions() const; + QList stereoModeActions() const; QuarterWidget * const master; SoNode * scene; diff --git a/src/Gui/Quarter/SensorManager.cpp b/src/Gui/Quarter/SensorManager.cpp index 59d2d13b55..5d2ebf115f 100644 --- a/src/Gui/Quarter/SensorManager.cpp +++ b/src/Gui/Quarter/SensorManager.cpp @@ -43,7 +43,7 @@ using namespace SIM::Coin3D::Quarter; -SensorManager::SensorManager(void) +SensorManager::SensorManager() : inherited() { this->mainthreadid = cc_thread_id(); @@ -74,7 +74,7 @@ SensorManager::SensorManager(void) SensorManager::~SensorManager() { // remove the Coin callback before shutting down - SoDB::getSensorManager()->setChangedCallback(NULL, NULL); + SoDB::getSensorManager()->setChangedCallback(nullptr, nullptr); if (this->signalthread->isRunning()) { this->signalthread->stopThread(); @@ -104,7 +104,7 @@ SensorManager::sensorQueueChangedCB(void * closure) } void -SensorManager::sensorQueueChanged(void) +SensorManager::sensorQueueChanged() { SoSensorManager * sensormanager = SoDB::getSensorManager(); assert(sensormanager); @@ -144,7 +144,7 @@ SensorManager::sensorQueueChanged(void) } void -SensorManager::idleTimeout(void) +SensorManager::idleTimeout() { SoDB::getSensorManager()->processTimerQueue(); SoDB::getSensorManager()->processDelayQueue(true); @@ -152,14 +152,14 @@ SensorManager::idleTimeout(void) } void -SensorManager::timerQueueTimeout(void) +SensorManager::timerQueueTimeout() { SoDB::getSensorManager()->processTimerQueue(); this->sensorQueueChanged(); } void -SensorManager::delayTimeout(void) +SensorManager::delayTimeout() { SoDB::getSensorManager()->processTimerQueue(); SoDB::getSensorManager()->processDelayQueue(false); diff --git a/src/Gui/Quarter/SensorManager.h b/src/Gui/Quarter/SensorManager.h index 6344cf93e6..6628ba9e3a 100644 --- a/src/Gui/Quarter/SensorManager.h +++ b/src/Gui/Quarter/SensorManager.h @@ -45,14 +45,14 @@ class SensorManager : public QObject { Q_OBJECT typedef QObject inherited; public: - SensorManager(void); + SensorManager(); ~SensorManager(); public Q_SLOTS: - void idleTimeout(void); - void delayTimeout(void); - void timerQueueTimeout(void); - void sensorQueueChanged(void); + void idleTimeout(); + void delayTimeout(); + void timerQueueTimeout(); + void sensorQueueChanged(); void setTimerEpsilon(double sec); private: diff --git a/src/Gui/Quarter/SignalThread.cpp b/src/Gui/Quarter/SignalThread.cpp index 6d18f8636d..a242286258 100644 --- a/src/Gui/Quarter/SignalThread.cpp +++ b/src/Gui/Quarter/SignalThread.cpp @@ -36,7 +36,7 @@ using namespace SIM::Coin3D::Quarter; -SignalThread::SignalThread(void) +SignalThread::SignalThread() : isstopped(false) { } @@ -46,7 +46,7 @@ SignalThread::~SignalThread() } void -SignalThread::trigger(void) +SignalThread::trigger() { // lock first to make sure the QThread is actually waiting for a signal QMutexLocker ml(&this->mutex); @@ -54,7 +54,7 @@ SignalThread::trigger(void) } void -SignalThread::stopThread(void) +SignalThread::stopThread() { QMutexLocker ml(&this->mutex); this->isstopped = true; @@ -63,7 +63,7 @@ SignalThread::stopThread(void) void -SignalThread::run(void) +SignalThread::run() { QMutexLocker ml(&this->mutex); while (!this->isstopped) { diff --git a/src/Gui/Quarter/SignalThread.h b/src/Gui/Quarter/SignalThread.h index e96117ae0c..718383991b 100644 --- a/src/Gui/Quarter/SignalThread.h +++ b/src/Gui/Quarter/SignalThread.h @@ -44,16 +44,16 @@ namespace SIM { namespace Coin3D { namespace Quarter { class SignalThread : public QThread { Q_OBJECT public: - SignalThread(void); + SignalThread(); virtual ~SignalThread(); - virtual void run(void); - void trigger(void); - void stopThread(void); + virtual void run(); + void trigger(); + void stopThread(); Q_SIGNALS: - void triggerSignal(void); + void triggerSignal(); private: QWaitCondition waitcond; diff --git a/src/Gui/Quarter/SoQTQuarterAdaptor.cpp b/src/Gui/Quarter/SoQTQuarterAdaptor.cpp index 552b055ebe..9d787b3694 100644 --- a/src/Gui/Quarter/SoQTQuarterAdaptor.cpp +++ b/src/Gui/Quarter/SoQTQuarterAdaptor.cpp @@ -168,7 +168,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::init() m_seekdistanceabs = false; m_seekperiod = 2.0f; m_inseekmode = false; - m_storedcamera = 0; + m_storedcamera = nullptr; m_viewingflag = false; pickRadius = 5.0; @@ -298,12 +298,12 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::convertPerspective2Ortho(const So out->height = 2.0f * focaldist * (float)tan(in->heightAngle.getValue() / 2.0); } -SoCamera* SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getCamera(void) const +SoCamera* SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getCamera() const { return getSoRenderManager()->getCamera(); } -const SbViewportRegion & SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getViewportRegion(void) const +const SbViewportRegion & SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getViewportRegion() const { return getSoRenderManager()->getViewportRegion(); } @@ -318,17 +318,17 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setViewing(SbBool enable) if(m_viewingflag) { SoGLRenderAction* action = getSoRenderManager()->getGLRenderAction(); - if(action != NULL) + if(action != nullptr) SoLocateHighlight::turnOffCurrentHighlight(action); } } -SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isViewing(void) const +SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isViewing() const { return m_viewingflag; } -void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountInc(void) +void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountInc() { // Catch problems with missing interactiveCountDec() calls. assert(m_interactionnesting < 100); @@ -338,7 +338,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountInc(void) } } -void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountDec(void) +void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountDec() { if(--m_interactionnesting <= 0) { m_interactionEndCallback.invokeCallbacks(this); @@ -346,7 +346,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::interactiveCountDec(void) } } -int SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getInteractiveCount(void) const +int SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getInteractiveCount() const { return m_interactionnesting; } @@ -372,22 +372,22 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::removeFinishCallback(SIM::Coin3D: } -float SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getSeekDistance(void) const +float SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getSeekDistance() const { return m_seekdistance; } -float SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getSeekTime(void) const +float SIM::Coin3D::Quarter::SoQTQuarterAdaptor::getSeekTime() const { return m_seekperiod; } -SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekMode(void) const +SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekMode() const { return m_inseekmode; } -SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekValuePercentage(void) const +SbBool SIM::Coin3D::Quarter::SoQTQuarterAdaptor::isSeekValuePercentage() const { return m_seekdistanceabs ? false : true; } @@ -541,7 +541,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::seeksensorCB(void* data, SoSensor if(end) thisp->setSeekMode(false); } -void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::saveHomePosition(void) +void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::saveHomePosition() { SoCamera* cam = getSoRenderManager()->getCamera(); if (!cam) { @@ -562,7 +562,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::saveHomePosition(void) m_storedcamera->copyFieldValues(getSoRenderManager()->getCamera()); } -void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetToHomePosition(void) +void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetToHomePosition() { SoCamera* cam = getSoRenderManager()->getCamera(); if (!cam) { @@ -724,7 +724,7 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::paintEvent(QPaintEvent* event) this->framesPerSecond = addFrametime(start); } -void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetFrameCounter(void) +void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetFrameCounter() { this->framecount = 0; this->frametime = 0.0f; diff --git a/src/Gui/Quarter/SoQTQuarterAdaptor.h b/src/Gui/Quarter/SoQTQuarterAdaptor.h index 84956532d4..e9cee0b949 100644 --- a/src/Gui/Quarter/SoQTQuarterAdaptor.h +++ b/src/Gui/Quarter/SoQTQuarterAdaptor.h @@ -47,9 +47,9 @@ typedef void SoQTQuarterAdaptorCB(void* data, SoQTQuarterAdaptor* viewer); class QUARTER_DLL_API SoQTQuarterAdaptor : public QuarterWidget { public: - explicit SoQTQuarterAdaptor(QWidget* parent = 0, const QtGLWidget* sharewidget = 0, Qt::WindowFlags f = Qt::WindowFlags()); - explicit SoQTQuarterAdaptor(const QtGLFormat& format, QWidget* parent = 0, const QtGLWidget* shareWidget = 0, Qt::WindowFlags f = Qt::WindowFlags()); - explicit SoQTQuarterAdaptor(QtGLContext* context, QWidget* parent = 0, const QtGLWidget* sharewidget = 0, Qt::WindowFlags f = Qt::WindowFlags()); + explicit SoQTQuarterAdaptor(QWidget* parent = nullptr, const QtGLWidget* sharewidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + explicit SoQTQuarterAdaptor(const QtGLFormat& format, QWidget* parent = nullptr, const QtGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + explicit SoQTQuarterAdaptor(QtGLContext* context, QWidget* parent = nullptr, const QtGLWidget* sharewidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); virtual ~SoQTQuarterAdaptor(); //the functions available in soqtviewer but missing in quarter @@ -59,38 +59,38 @@ public: QWidget* getGLWidget() const; virtual void setCameraType(SoType type); - SoCamera * getCamera(void) const; + SoCamera * getCamera() const; - const SbViewportRegion & getViewportRegion(void) const; + const SbViewportRegion & getViewportRegion() const; virtual void setViewing(SbBool enable); - SbBool isViewing(void) const; + SbBool isViewing() const; - void interactiveCountInc(void); - void interactiveCountDec(void); - int getInteractiveCount(void) const; + void interactiveCountInc(); + void interactiveCountDec(); + int getInteractiveCount() const; - void addStartCallback(SoQTQuarterAdaptorCB* func, void* data = NULL); - void addFinishCallback(SoQTQuarterAdaptorCB* func, void* data = NULL); - void removeStartCallback(SoQTQuarterAdaptorCB* func, void* data = NULL); - void removeFinishCallback(SoQTQuarterAdaptorCB* func, void* data = NULL); + void addStartCallback(SoQTQuarterAdaptorCB* func, void* data = nullptr); + void addFinishCallback(SoQTQuarterAdaptorCB* func, void* data = nullptr); + void removeStartCallback(SoQTQuarterAdaptorCB* func, void* data = nullptr); + void removeFinishCallback(SoQTQuarterAdaptorCB* func, void* data = nullptr); virtual void setSeekMode(SbBool enable); - SbBool isSeekMode(void) const; + SbBool isSeekMode() const; SbBool seekToPoint(const SbVec2s screenpos); void seekToPoint(const SbVec3f& scenepos); void setSeekTime(const float seconds); - float getSeekTime(void) const; + float getSeekTime() const; void setSeekDistance(const float distance); - float getSeekDistance(void) const; + float getSeekDistance() const; void setSeekValueAsPercentage(const SbBool on); - SbBool isSeekValuePercentage(void) const; + SbBool isSeekValuePercentage() const; - virtual float getPickRadius(void) const {return this->pickRadius;} + virtual float getPickRadius() const {return this->pickRadius;} virtual void setPickRadius(float pickRadius); - virtual void saveHomePosition(void); - virtual void resetToHomePosition(void); + virtual void saveHomePosition(); + virtual void resetToHomePosition(); virtual void setSceneGraph(SoNode* root) { QuarterWidget::setSceneGraph(root); @@ -100,7 +100,7 @@ public: virtual void paintEvent(QPaintEvent*); //this functions still need to be ported - virtual void afterRealizeHook(void) {} //enables spacenav and joystick in soqt, dunno if this is needed + virtual void afterRealizeHook() {} //enables spacenav and joystick in soqt, dunno if this is needed private: void init(); @@ -109,7 +109,7 @@ private: void getCameraCoordinateSystem(SoCamera * camera, SoNode * root, SbMatrix & matrix, SbMatrix & inverse); static void seeksensorCB(void * data, SoSensor * s); void moveCameraScreen(const SbVec2f & screenpos); - void resetFrameCounter(void); + void resetFrameCounter(); SbVec2f addFrametime(double ft); bool m_viewingflag; diff --git a/src/Gui/Quarter/SpaceNavigatorDevice.cpp b/src/Gui/Quarter/SpaceNavigatorDevice.cpp index 14fe49e871..5726845439 100644 --- a/src/Gui/Quarter/SpaceNavigatorDevice.cpp +++ b/src/Gui/Quarter/SpaceNavigatorDevice.cpp @@ -128,7 +128,7 @@ const SoEvent * SpaceNavigatorDevice::translateEvent(QEvent * event) { Q_UNUSED(event); - SoEvent * ret = NULL; + SoEvent * ret = nullptr; #ifdef HAVE_SPACENAV_LIB NativeEvent * ce = dynamic_cast(event); diff --git a/src/Gui/Quarter/devices/InputDevice.h b/src/Gui/Quarter/devices/InputDevice.h index bf2785d1eb..be46a1649a 100644 --- a/src/Gui/Quarter/devices/InputDevice.h +++ b/src/Gui/Quarter/devices/InputDevice.h @@ -47,7 +47,7 @@ class QuarterWidget; class QUARTER_DLL_API InputDevice { public: InputDevice(QuarterWidget * quarter); - InputDevice(void); + InputDevice(); virtual ~InputDevice() {} /*! diff --git a/src/Gui/Quarter/devices/Keyboard.h b/src/Gui/Quarter/devices/Keyboard.h index 8284798881..2299adf3d9 100644 --- a/src/Gui/Quarter/devices/Keyboard.h +++ b/src/Gui/Quarter/devices/Keyboard.h @@ -44,7 +44,7 @@ namespace SIM { namespace Coin3D { namespace Quarter { class QUARTER_DLL_API Keyboard : public InputDevice { public: Keyboard(QuarterWidget* quarter); - Keyboard(void); + Keyboard(); virtual ~Keyboard(); virtual const SoEvent * translateEvent(QEvent * event); diff --git a/src/Gui/Quarter/devices/Mouse.h b/src/Gui/Quarter/devices/Mouse.h index 49405368c2..6ac878063d 100644 --- a/src/Gui/Quarter/devices/Mouse.h +++ b/src/Gui/Quarter/devices/Mouse.h @@ -44,7 +44,7 @@ namespace SIM { namespace Coin3D { namespace Quarter { class QUARTER_DLL_API Mouse : public InputDevice { public: Mouse(QuarterWidget* quarter); - Mouse(void); + Mouse(); virtual ~Mouse(); virtual const SoEvent * translateEvent(QEvent * event); diff --git a/src/Gui/Quarter/devices/SpaceNavigatorDevice.h b/src/Gui/Quarter/devices/SpaceNavigatorDevice.h index 30224f6446..c8f6e8a5b3 100644 --- a/src/Gui/Quarter/devices/SpaceNavigatorDevice.h +++ b/src/Gui/Quarter/devices/SpaceNavigatorDevice.h @@ -43,7 +43,7 @@ namespace SIM { namespace Coin3D { namespace Quarter { class QUARTER_DLL_API SpaceNavigatorDevice : public InputDevice { public: SpaceNavigatorDevice(QuarterWidget* quarter); - SpaceNavigatorDevice(void); + SpaceNavigatorDevice(); virtual ~SpaceNavigatorDevice(); virtual const SoEvent * translateEvent(QEvent * event); diff --git a/src/Gui/Quarter/eventhandlers/EventFilter.h b/src/Gui/Quarter/eventhandlers/EventFilter.h index 68c7cbdf06..5f4f95bd1b 100644 --- a/src/Gui/Quarter/eventhandlers/EventFilter.h +++ b/src/Gui/Quarter/eventhandlers/EventFilter.h @@ -53,7 +53,7 @@ public: void registerInputDevice(InputDevice * device); void unregisterInputDevice(InputDevice * device); - const QPoint & globalMousePosition(void) const; + const QPoint & globalMousePosition() const; protected: bool eventFilter(QObject * obj, QEvent * event); From 916fe37a6b757e3bf6d51fb65ebc412243125d8e Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 21:37:19 +0100 Subject: [PATCH 59/68] Gui: move handling of SoMouseWheelEvent to its own handler function --- src/Gui/GestureNavigationStyle.cpp | 1 + src/Gui/NavigationStyle.cpp | 32 ++++++++++++++++++------------ src/Gui/NavigationStyle.h | 2 ++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Gui/GestureNavigationStyle.cpp b/src/Gui/GestureNavigationStyle.cpp index 7d0732ae54..946efb1dcf 100644 --- a/src/Gui/GestureNavigationStyle.cpp +++ b/src/Gui/GestureNavigationStyle.cpp @@ -72,6 +72,7 @@ #include "GestureNavigationStyle.h" #include +#include #include #include "View3DInventorViewer.h" #include "Application.h" diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index c75ad3869a..fb971292e1 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1495,24 +1495,19 @@ SbBool NavigationStyle::processEvent(const SoEvent * const ev) SbBool NavigationStyle::processSoEvent(const SoEvent * const ev) { - const SbVec2s pos(ev->getPosition()); - const SbVec2f posn = normalizePixelPos(pos); bool processed = false; //handle mouse wheel zoom - if(ev->isOfType(SoMouseWheelEvent::getClassTypeId())){ - doZoom( - viewer->getSoRenderManager()->getCamera(), - static_cast(ev)->getDelta(), - posn - ); - processed = true; + if (ev->isOfType(SoMouseWheelEvent::getClassTypeId())) { + const SoMouseWheelEvent * const event = static_cast(ev); + processed = processWheelEvent(event); } - if (! processed) - return viewer->processSoEventBase(ev); - else - return processed; + if (!processed) { + processed = viewer->processSoEventBase(ev); + } + + return processed; } void NavigationStyle::syncWithEvent(const SoEvent * const ev) @@ -1692,6 +1687,17 @@ SbBool NavigationStyle::processClickEvent(const SoMouseButtonEvent * const event return processed; } +SbBool NavigationStyle::processWheelEvent(const SoMouseWheelEvent * const event) +{ + const SbVec2s pos(event->getPosition()); + const SbVec2f posn = normalizePixelPos(pos); + + //handle mouse wheel zoom + doZoom(viewer->getSoRenderManager()->getCamera(), + event->getDelta(), posn); + return true; +} + void NavigationStyle::setPopupMenuEnabled(const SbBool on) { this->menuenabled = on; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index f35e61f37a..7f493ec55a 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -41,6 +41,7 @@ // forward declarations class SoEvent; +class SoMouseWheelEvent; class SoMotion3Event; class SoQtViewer; class SoCamera; @@ -154,6 +155,7 @@ public: virtual SbBool processMotionEvent(const SoMotion3Event * const ev); virtual SbBool processKeyboardEvent(const SoKeyboardEvent * const event); virtual SbBool processClickEvent(const SoMouseButtonEvent * const event); + virtual SbBool processWheelEvent(const SoMouseWheelEvent * const event); void setPopupMenuEnabled(const SbBool on); SbBool isPopupMenuEnabled() const; From 549e5b56502518d41865465d1e0953e12b10b4d8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 5 Nov 2021 23:49:14 +0100 Subject: [PATCH 60/68] Tux: support of OpenSCAD and TinkerCAD in navigation indicator --- src/Mod/Tux/NavigationIndicatorGui.py | 52 +++++++++++++++++++++++++++ src/Mod/Tux/Resources/Tux.qrc | 11 ++++++ 2 files changed, 63 insertions(+) diff --git a/src/Mod/Tux/NavigationIndicatorGui.py b/src/Mod/Tux/NavigationIndicatorGui.py index 516c17258b..c49048c42c 100644 --- a/src/Mod/Tux/NavigationIndicatorGui.py +++ b/src/Mod/Tux/NavigationIndicatorGui.py @@ -288,6 +288,42 @@ def retranslateUi(): """ + global t9 + t9 = "

OpenSCAD " + text06 + """

+ + + + + + + + + + + + + + + +
""" + text01 + """""" + text02 + """""" + text02 + """""" + text03 + """""" + text04 + """
""" + + global t10 + t10 = "

TinkerCAD " + text06 + """

+ + + + + + + + + + + + + +
""" + text01 + """""" + text02 + """""" + text03 + """""" + text04 + """
""" + menuSettings.setTitle(translate("NavigationIndicator", "Settings")) menuOrbit.setTitle(translate("NavigationIndicator", "Orbit style")) aCompact.setText(translate("NavigationIndicator", "Compact")) @@ -384,6 +420,18 @@ a8.setText("OpenCascade") a8.setData("Gui::OpenCascadeNavigationStyle") a8.setObjectName("Indicator_NavigationOpenCascade") +a9 = QtGui.QAction(gStyle) +a9.setIcon(QtGui.QIcon(":/icons/NavigationOpenSCAD_dark.svg")) +a9.setText("OpenSCAD") +a9.setData("Gui::OpenSCADNavigationStyle") +a9.setObjectName("Indicator_NavigationOpenSCAD") + +a10 = QtGui.QAction(gStyle) +a10.setIcon(QtGui.QIcon(":/icons/NavigationTinkerCAD_dark.svg")) +a10.setText("TinkerCAD") +a10.setData("Gui::TinkerCADNavigationStyle") +a10.setObjectName("Indicator_NavigationTinkerCAD") + menu.addMenu(menuSettings) menu.addSeparator() menu.addAction(a0) @@ -395,6 +443,8 @@ menu.addAction(a5) menu.addAction(a6) menu.addAction(a7) menu.addAction(a8) +menu.addAction(a9) +menu.addAction(a10) def onCompact(): @@ -430,6 +480,8 @@ def onTooltip(): a6.setToolTip(t6) a7.setToolTip(t7) a8.setToolTip(t8) + a9.setToolTip(t9) + a10.setToolTip(t10) p.SetBool("Tooltip", 1) else: for i in gStyle.actions(): diff --git a/src/Mod/Tux/Resources/Tux.qrc b/src/Mod/Tux/Resources/Tux.qrc index e503675307..471f97fcc8 100644 --- a/src/Mod/Tux/Resources/Tux.qrc +++ b/src/Mod/Tux/Resources/Tux.qrc @@ -58,6 +58,17 @@ icons/NavigationOpenInventor_dark.svg icons/NavigationOpenInventor_ZoomAlt.svg icons/NavigationOpenInventor_Zoom.svg + icons/NavigationCAD_dark.svg + icons/NavigationOpenCascade_Select.svg + icons/NavigationOpenCascade_PanAlt.svg + icons/NavigationOpenCascade_PanAlt.svg + icons/NavigationOpenCascade_Select.svg + icons/NavigationGesture_Pan.svg + icons/NavigationCAD_dark.svg + icons/NavigationOpenCascade_Select.svg + icons/NavigationOpenCascade_Zoom.svg + icons/NavigationGesture_Pan.svg + icons/NavigationOpenCascade_PanAlt.svg icons/NavigationRevit_Pan.svg icons/NavigationRevit_Rotate.svg icons/NavigationRevit_light.svg From e30efba754e0b894558be26d7341045647226061 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Fri, 5 Nov 2021 12:13:10 -0400 Subject: [PATCH 61/68] [PartDesign] Fix typo in method name --- src/Mod/PartDesign/Gui/TaskLoftParameters.cpp | 4 ++-- src/Mod/PartDesign/Gui/TaskLoftParameters.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp b/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp index 36cab259a2..0335944e4d 100644 --- a/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp @@ -69,7 +69,7 @@ TaskLoftParameters::TaskLoftParameters(ViewProviderLoft *LoftView,bool /*newObj* connect(ui->buttonRefAdd, SIGNAL(toggled(bool)), this, SLOT(onRefButtonAdd(bool))); connect(ui->buttonRefRemove, SIGNAL(toggled(bool)), - this, SLOT(onRefButtonRemvove(bool))); + this, SLOT(onRefButtonRemove(bool))); connect(ui->checkBoxRuled, SIGNAL(toggled(bool)), this, SLOT(onRuled(bool))); connect(ui->checkBoxClosed, SIGNAL(toggled(bool)), @@ -324,7 +324,7 @@ void TaskLoftParameters::onRefButtonAdd(bool checked) { } } -void TaskLoftParameters::onRefButtonRemvove(bool checked) { +void TaskLoftParameters::onRefButtonRemove(bool checked) { if (checked) { Gui::Selection().clearSelection(); diff --git a/src/Mod/PartDesign/Gui/TaskLoftParameters.h b/src/Mod/PartDesign/Gui/TaskLoftParameters.h index b99a771edf..20e977dd9e 100644 --- a/src/Mod/PartDesign/Gui/TaskLoftParameters.h +++ b/src/Mod/PartDesign/Gui/TaskLoftParameters.h @@ -56,7 +56,7 @@ public: private Q_SLOTS: void onProfileButton(bool); void onRefButtonAdd(bool); - void onRefButtonRemvove(bool); + void onRefButtonRemove(bool); void onClosed(bool); void onRuled(bool); void onDeleteSection(); From 4543c982670a0d6044ebed7812ac7df43feb1c4a Mon Sep 17 00:00:00 2001 From: luzpaz Date: Fri, 5 Nov 2021 19:15:00 -0400 Subject: [PATCH 62/68] MeshPart: fix header uniformity + remove superfluous whitespace (#5135) * MeshPart: fix header uniformity + remove superfluous whitespace --- src/Mod/MeshPart/App/AppMeshPart.cpp | 2 +- src/Mod/MeshPart/App/AppMeshPartPy.cpp | 2 +- src/Mod/MeshPart/App/CurveProjector.cpp | 2 +- src/Mod/MeshPart/App/CurveProjector.h | 2 +- src/Mod/MeshPart/App/MeshAlgos.cpp | 2 +- src/Mod/MeshPart/App/MeshAlgos.h | 2 +- src/Mod/MeshPart/App/PreCompiled.cpp | 2 +- src/Mod/MeshPart/App/PreCompiled.h | 2 +- src/Mod/MeshPart/Gui/AppMeshPartGui.cpp | 2 +- src/Mod/MeshPart/Gui/Command.cpp | 2 +- src/Mod/MeshPart/Gui/MeshFlatteningCommand.py | 22 ++++++ src/Mod/MeshPart/Gui/PreCompiled.cpp | 2 +- src/Mod/MeshPart/Gui/PreCompiled.h | 2 +- src/Mod/MeshPart/Init.py | 9 +-- src/Mod/MeshPart/InitGui.py | 76 ++++++++++--------- 15 files changed, 77 insertions(+), 54 deletions(-) diff --git a/src/Mod/MeshPart/App/AppMeshPart.cpp b/src/Mod/MeshPart/App/AppMeshPart.cpp index fbd6d1da92..e4cc0d004b 100644 --- a/src/Mod/MeshPart/App/AppMeshPart.cpp +++ b/src/Mod/MeshPart/App/AppMeshPart.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/AppMeshPartPy.cpp b/src/Mod/MeshPart/App/AppMeshPartPy.cpp index 489ae76933..a1b96ff51e 100644 --- a/src/Mod/MeshPart/App/AppMeshPartPy.cpp +++ b/src/Mod/MeshPart/App/AppMeshPartPy.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/CurveProjector.cpp b/src/Mod/MeshPart/App/CurveProjector.cpp index e559834e66..5731521aa3 100644 --- a/src/Mod/MeshPart/App/CurveProjector.cpp +++ b/src/Mod/MeshPart/App/CurveProjector.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) Juergen Riegel * + * Copyright (c) 2008 Juergen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/CurveProjector.h b/src/Mod/MeshPart/App/CurveProjector.h index 20d2479fea..5efcd7566d 100644 --- a/src/Mod/MeshPart/App/CurveProjector.h +++ b/src/Mod/MeshPart/App/CurveProjector.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) Juergen Riegel * + * Copyright (c) 2008 Juergen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/MeshAlgos.cpp b/src/Mod/MeshPart/App/MeshAlgos.cpp index 0f1f2439d2..3551766207 100644 --- a/src/Mod/MeshPart/App/MeshAlgos.cpp +++ b/src/Mod/MeshPart/App/MeshAlgos.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) Juergen Riegel * + * Copyright (c) 2008 Juergen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/MeshAlgos.h b/src/Mod/MeshPart/App/MeshAlgos.h index d524f7effd..a0f482421d 100644 --- a/src/Mod/MeshPart/App/MeshAlgos.h +++ b/src/Mod/MeshPart/App/MeshAlgos.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) Juergen Riegel * + * Copyright (c) 2008 Juergen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/PreCompiled.cpp b/src/Mod/MeshPart/App/PreCompiled.cpp index 46269e9671..1e5d389dd2 100644 --- a/src/Mod/MeshPart/App/PreCompiled.cpp +++ b/src/Mod/MeshPart/App/PreCompiled.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/App/PreCompiled.h b/src/Mod/MeshPart/App/PreCompiled.h index 07eac4d2e8..754261f3a7 100644 --- a/src/Mod/MeshPart/App/PreCompiled.h +++ b/src/Mod/MeshPart/App/PreCompiled.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp b/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp index 5bd034c4eb..64aa198feb 100644 --- a/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp +++ b/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/Gui/Command.cpp b/src/Mod/MeshPart/Gui/Command.cpp index 22f2ff929e..f91ff09030 100644 --- a/src/Mod/MeshPart/Gui/Command.cpp +++ b/src/Mod/MeshPart/Gui/Command.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/Gui/MeshFlatteningCommand.py b/src/Mod/MeshPart/Gui/MeshFlatteningCommand.py index ed0d1aec6e..8d09f86c82 100644 --- a/src/Mod/MeshPart/Gui/MeshFlatteningCommand.py +++ b/src/Mod/MeshPart/Gui/MeshFlatteningCommand.py @@ -1,3 +1,25 @@ +#*************************************************************************** +#* Copyright (c) 2017 Lorenz Lechner * +#* * +#* This file is part of the FreeCAD CAx development system. * +#* * +#* This library is free software; you can redistribute it and/or * +#* modify it under the terms of the GNU Library General Public * +#* License as published by the Free Software Foundation; either * +#* version 2 of the License, or (at your option) any later version. * +#* * +#* This library is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this library; see the file COPYING.LIB. If not, * +#* write to the Free Software Foundation, Inc., 59 Temple Place, * +#* Suite 330, Boston, MA 02111-1307, USA * +#* * +#***************************************************************************/ + import Mesh import FreeCAD as App import FreeCADGui as Gui diff --git a/src/Mod/MeshPart/Gui/PreCompiled.cpp b/src/Mod/MeshPart/Gui/PreCompiled.cpp index 46269e9671..1e5d389dd2 100644 --- a/src/Mod/MeshPart/Gui/PreCompiled.cpp +++ b/src/Mod/MeshPart/Gui/PreCompiled.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/Gui/PreCompiled.h b/src/Mod/MeshPart/Gui/PreCompiled.h index 7cef9ef237..9f90acb0d8 100644 --- a/src/Mod/MeshPart/Gui/PreCompiled.h +++ b/src/Mod/MeshPart/Gui/PreCompiled.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Mod/MeshPart/Init.py b/src/Mod/MeshPart/Init.py index c9c37c802b..dd8dea3aee 100644 --- a/src/Mod/MeshPart/Init.py +++ b/src/Mod/MeshPart/Init.py @@ -1,8 +1,8 @@ -# FreeCAD init script of the MeshPart module +# FreeCAD init script of the MeshPart module # (c) 2001 Juergen Riegel #*************************************************************************** -#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 * +#* Copyright (c) 2002 Juergen Riegel * #* * #* This file is part of the FreeCAD CAx development system. * #* * @@ -13,14 +13,13 @@ #* for detail see the LICENCE text file. * #* * #* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * #* GNU Lesser General Public License for more details. * #* * #* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * +#* License along with FreeCAD; if not, write to the Free Software * #* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * #* USA * #* * -#* Juergen Riegel 2002 * #***************************************************************************/ diff --git a/src/Mod/MeshPart/InitGui.py b/src/Mod/MeshPart/InitGui.py index 82a917f2ea..17d0102f1f 100644 --- a/src/Mod/MeshPart/InitGui.py +++ b/src/Mod/MeshPart/InitGui.py @@ -1,4 +1,4 @@ -# MeshPart gui init module +# MeshPart gui init module # (c) 2003 Juergen Riegel # # Gathering all the information to start FreeCAD @@ -6,7 +6,7 @@ # runs when the gui is up #*************************************************************************** -#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 * +#* Copyright (c) 2002 Juergen Riegel * #* * #* This file is part of the FreeCAD CAx development system. * #* * @@ -26,44 +26,46 @@ #* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * #* USA * #* * -#* Juergen Riegel 2002 * #***************************************************************************/ class MeshPartWorkbench ( Workbench ): - "MeshPart workbench object" - Icon = """ - /* XPM */ - static const char *MeshPart_Box[]={ - "16 16 3 1", - ". c None", - "# c #000000", - "a c #c6c642", - "................", - ".......#######..", - "......#aaaaa##..", - ".....#aaaaa###..", - "....#aaaaa##a#..", - "...#aaaaa##aa#..", - "..#aaaaa##aaa#..", - ".########aaaa#..", - ".#aaaaa#aaaaa#..", - ".#aaaaa#aaaa##..", - ".#aaaaa#aaa##...", - ".#aaaaa#aa##....", - ".#aaaaa#a##... .", - ".#aaaaa###......", - ".########.......", - "................"}; - """ - MenuText = "MeshPart" - ToolTip = "MeshPart workbench" + "MeshPart workbench object" + Icon = """ + /* XPM */ + static const char *MeshPart_Box[]={ + "16 16 3 1", + ". c None", + "# c #000000", + "a c #c6c642", + "................", + ".......#######..", + "......#aaaaa##..", + ".....#aaaaa###..", + "....#aaaaa##a#..", + "...#aaaaa##aa#..", + "..#aaaaa##aaa#..", + ".########aaaa#..", + ".#aaaaa#aaaaa#..", + ".#aaaaa#aaaa##..", + ".#aaaaa#aaa##...", + ".#aaaaa#aa##....", + ".#aaaaa#a##... .", + ".#aaaaa###......", + ".########.......", + "................"}; + """ + MenuText = "MeshPart" + ToolTip = "MeshPart workbench" - def Initialize(self): - # load the module - import MeshPartGui - import MeshPart - def GetClassName(self): - return "MeshPartGui::Workbench" -#Gui.addWorkbench(MeshPartWorkbench()) + def Initialize(self): + # load the module + import MeshPartGui + import MeshPart + + + def GetClassName(self): + return "MeshPartGui::Workbench" + +# Gui.addWorkbench(MeshPartWorkbench()) From 6d2aa6acc9f58d8f8cf0d4744d9a0ed86ac18ed5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 6 Nov 2021 14:31:17 +0100 Subject: [PATCH 63/68] Main: [skip ci] partially fix issue 0004765: FreeCAD failed to build on MSVC with std:c++latest --- src/Main/MainCmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Main/MainCmd.cpp b/src/Main/MainCmd.cpp index fa230acacc..ae4e36ffd9 100644 --- a/src/Main/MainCmd.cpp +++ b/src/Main/MainCmd.cpp @@ -108,7 +108,7 @@ int main( int argc, char ** argv ) std::string appName = App::Application::Config()["ExeName"]; std::stringstream msg; msg << "While initializing " << appName << " the following exception occurred: '" << e.what() << "'\n\n"; - msg << "Python is searching for its runtime files in the following directories:\n" << Py_GetPath() << "\n\n"; + msg << "Python is searching for its runtime files in the following directories:\n" << Py_EncodeLocale(Py_GetPath(),nullptr) << "\n\n"; msg << "Python version information:\n" << Py_GetVersion() << "\n"; const char* pythonhome = getenv("PYTHONHOME"); if ( pythonhome ) { From 4f56ee263d34c5058d6de279a35ae7ef61c795d5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 6 Nov 2021 17:48:35 +0100 Subject: [PATCH 64/68] Sketcher: fix some memory leaks --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 16 +++++++++++----- src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp | 2 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 2 ++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index f7d00610ee..ba1496e225 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -555,7 +555,8 @@ public: "conList.append(Sketcher.Constraint('Horizontal',%i))\n" "conList.append(Sketcher.Constraint('Vertical',%i))\n" "conList.append(Sketcher.Constraint('Vertical',%i))\n" - "%s.addConstraint(conList)\n", + "%s.addConstraint(conList)\n" + "del geoList, conList\n", EditCurve[0].x,EditCurve[0].y,EditCurve[1].x,EditCurve[1].y, // line 1 EditCurve[1].x,EditCurve[1].y,EditCurve[2].x,EditCurve[2].y, // line 2 EditCurve[2].x,EditCurve[2].y,EditCurve[3].x,EditCurve[3].y, // line 3 @@ -594,7 +595,8 @@ public: "conList.append(Sketcher.Constraint('Vertical',%i))\n" "conList.append(Sketcher.Constraint('Vertical',%i))\n" "conList.append(Sketcher.Constraint('Symmetric',%i,2,%i,1,%i,1))\n" - "%s.addConstraint(conList)\n", + "%s.addConstraint(conList)\n" + "del geoList, conList\n", EditCurve[0].x,EditCurve[0].y,EditCurve[1].x,EditCurve[1].y, // line 1 EditCurve[1].x,EditCurve[1].y,EditCurve[2].x,EditCurve[2].y, // line 2 EditCurve[2].x,EditCurve[2].y,EditCurve[3].x,EditCurve[3].y, // line 3 @@ -930,7 +932,8 @@ public: "conList.append(Sketcher.Constraint('Equal', %i, %i))\n" "conList.append(Sketcher.Constraint('Equal', %i, %i))\n" "conList.append(Sketcher.Constraint('Equal', %i, %i))\n" - "%s.addConstraint(conList)\n", + "%s.addConstraint(conList)\n" + "del geoList, conList\n", StartPos.x + (signX * radius), StartPos.y + (signY * radius), // center of the arc 1 radius, start, end, // start and end angle of arc1 @@ -984,7 +987,8 @@ public: "conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n" "conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n" "conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n" - "%s.addConstraint(conList)\n", + "%s.addConstraint(conList)\n" + "del geoList, conList\n", StartPos.x, StartPos.y, // point at StartPos EndPos.x, EndPos.y, // point at EndPos Gui::Command::getObjectCmd(sketchgui->getObject()).c_str(), // the sketch @@ -4843,6 +4847,7 @@ public: } cstream << Gui::Command::getObjectCmd(sketchgui->getObject()) << ".addConstraint(conList)\n"; + cstream << "del conList\n"; Gui::Command::doCommand(Gui::Command::Doc, cstream.str().c_str()); @@ -7129,7 +7134,8 @@ public: "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 1))\n" "conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 1))\n" "conList.append(Sketcher.Constraint('Equal', %i, %i))\n" - "%s.addConstraint(conList)\n", + "%s.addConstraint(conList)\n" + "del geoList, conList\n", StartPos.x, StartPos.y, // center of the arc1 r, // radius arc1 start, end, // start and end angle of arc1 diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp index acfb48c942..93ec845a5e 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstraints.cpp @@ -379,7 +379,7 @@ public: class ExpressionDelegate : public QStyledItemDelegate { public: - ExpressionDelegate(QListWidget * _view) : view(_view) { } + ExpressionDelegate(QListWidget * _view) : QStyledItemDelegate(_view), view(_view) { } protected: QPixmap getIcon(const char* name, const QSize& size) const { diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index c3a89f5c12..e22254d2af 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -6376,6 +6376,7 @@ bool ViewProviderSketch::setEdit(int ModNum) " tv.sketchClipPlane(ActiveSketch, ActiveSketch.ViewObject.SectionView)\n" "tv.hide(ActiveSketch)\n" "del(tv)\n" + "del(ActiveSketch)\n" ).arg(QString::fromLatin1(getDocument()->getDocument()->getName()), QString::fromLatin1(getSketchObject()->getNameInDocument()), QString::fromLatin1(Gui::Command::getObjectCmd(editObj).c_str()), @@ -6907,6 +6908,7 @@ void ViewProviderSketch::unsetEdit(int ModNum) " tv.restore()\n" "ActiveSketch.ViewObject.TempoVis = None\n" "del(tv)\n" + "del(ActiveSketch)\n" ).arg(QString::fromLatin1(getDocument()->getDocument()->getName())).arg( QString::fromLatin1(getSketchObject()->getNameInDocument())); QByteArray cmdstr_bytearray = cmdstr.toLatin1(); From 84274f5c805ecc289a78ab731a7e715b47546dc8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 7 Nov 2021 08:27:33 +0100 Subject: [PATCH 65/68] PD: [skip ci] fix ambiguous shortcut overload in TaskDlgPipeParameters --- src/Mod/PartDesign/Gui/TaskPipeParameters.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp b/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp index 66465f3814..6dd611b873 100644 --- a/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPipeParameters.cpp @@ -94,6 +94,7 @@ TaskPipeParameters::TaskPipeParameters(ViewProviderPipe *PipeView, bool /*newObj // Create context menu QAction* remove = new QAction(tr("Remove"), this); remove->setShortcut(QKeySequence::Delete); + remove->setShortcutContext(Qt::WidgetShortcut); #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // display shortcut behind the context menu entry remove->setShortcutVisibleInContextMenu(true); @@ -587,6 +588,7 @@ TaskPipeOrientation::TaskPipeOrientation(ViewProviderPipe* PipeView, bool /*newO // Create context menu QAction* remove = new QAction(tr("Remove"), this); remove->setShortcut(QKeySequence::Delete); + remove->setShortcutContext(Qt::WidgetShortcut); #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // display shortcut behind the context menu entry remove->setShortcutVisibleInContextMenu(true); @@ -902,6 +904,7 @@ TaskPipeScaling::TaskPipeScaling(ViewProviderPipe* PipeView, bool /*newObj*/, QW // Create context menu QAction* remove = new QAction(tr("Remove"), this); remove->setShortcut(QKeySequence::Delete); + remove->setShortcutContext(Qt::WidgetShortcut); #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // display shortcut behind the context menu entry remove->setShortcutVisibleInContextMenu(true); From 0b4405e935bcc668a0f02801891f5022056d3772 Mon Sep 17 00:00:00 2001 From: Uwe Date: Sun, 7 Nov 2021 02:39:11 +0100 Subject: [PATCH 66/68] [PD] simplify Loft code - also two automatic style fixes made by MSVC --- src/Mod/PartDesign/Gui/TaskLoftParameters.cpp | 9 ++++----- src/Mod/PartDesign/Gui/TaskLoftParameters.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp b/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp index 0335944e4d..9ae610ef18 100644 --- a/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp @@ -55,7 +55,7 @@ using namespace Gui; /* TRANSLATOR PartDesignGui::TaskLoftParameters */ -TaskLoftParameters::TaskLoftParameters(ViewProviderLoft *LoftView,bool /*newObj*/, QWidget *parent) +TaskLoftParameters::TaskLoftParameters(ViewProviderLoft *LoftView, bool /*newObj*/, QWidget *parent) : TaskSketchBasedParameters(LoftView, parent, "PartDesign_AdditiveLoft", tr("Loft parameters")) , ui(new Ui_TaskLoftParameters) { @@ -129,16 +129,15 @@ TaskLoftParameters::TaskLoftParameters(ViewProviderLoft *LoftView,bool /*newObj* for (QWidget* child : proxy->findChildren()) child->blockSignals(false); - updateUI(0); + updateUI(); } TaskLoftParameters::~TaskLoftParameters() { } -void TaskLoftParameters::updateUI(int index) +void TaskLoftParameters::updateUI() { - Q_UNUSED(index); } void TaskLoftParameters::onSelectionChanged(const Gui::SelectionChanges& msg) @@ -359,7 +358,7 @@ bool TaskDlgLoftParameters::accept() // TODO Fill this with commands (2015-09-11, Fat-Zer) PartDesign::Loft* pcLoft = static_cast(vp->getObject()); - for(App::DocumentObject* obj : pcLoft->Sections.getValues()) { + for (App::DocumentObject* obj : pcLoft->Sections.getValues()) { FCMD_OBJ_HIDE(obj); } diff --git a/src/Mod/PartDesign/Gui/TaskLoftParameters.h b/src/Mod/PartDesign/Gui/TaskLoftParameters.h index 20e977dd9e..e04011ef4b 100644 --- a/src/Mod/PartDesign/Gui/TaskLoftParameters.h +++ b/src/Mod/PartDesign/Gui/TaskLoftParameters.h @@ -67,7 +67,7 @@ protected: private: void onSelectionChanged(const Gui::SelectionChanges& msg); - void updateUI(int index); + void updateUI(); bool referenceSelected(const Gui::SelectionChanges& msg) const; void removeFromListWidget(QListWidget*w, QString name); void clearButtons(); From 058962362d1f0c2e8c064832755eb3df3fd9b5d7 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sun, 7 Nov 2021 17:13:05 -0600 Subject: [PATCH 67/68] OpenSCAD: Refactor tests to all use the same code path for tempdir generation --- .../OpenSCADTest/app/test_importCSG.py | 166 +++++++----------- 1 file changed, 61 insertions(+), 105 deletions(-) diff --git a/src/Mod/OpenSCAD/OpenSCADTest/app/test_importCSG.py b/src/Mod/OpenSCAD/OpenSCADTest/app/test_importCSG.py index 59759a7c47..24dda152a2 100644 --- a/src/Mod/OpenSCAD/OpenSCADTest/app/test_importCSG.py +++ b/src/Mod/OpenSCAD/OpenSCADTest/app/test_importCSG.py @@ -38,6 +38,7 @@ __url__ = "https://www.freecadweb.org" class TestImportCSG(unittest.TestCase): MODULE = 'test_importCSG' # file name without extension + temp_dir = tempfile.TemporaryDirectory() def setUp(self): @@ -73,113 +74,78 @@ class TestImportCSG(unittest.TestCase): FreeCAD.closeDocument("CSG") + def utility_create_scad(self, scadCode, name): + filename = self.temp_dir.name + os.path.sep + name + ".scad" + print (f"Creating {filename}") + f = open(filename,"w+") + f.write(scadCode) + f.close() + return importCSG.open(filename) + def test_import_sphere(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "sphere.scad" - f = open(filename,"w+") - f.write("sphere(10.0);") - f.close() - doc = importCSG.open(filename) - sphere = doc.getObject("sphere") - self.assertTrue (sphere is not None) - self.assertTrue (sphere.Radius == 10.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("sphere(10.0);","sphere") + sphere = doc.getObject("sphere") + self.assertTrue (sphere is not None) + self.assertTrue (sphere.Radius == 10.0) + FreeCAD.closeDocument(doc.Name) def test_import_cylinder(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "cylinder.scad" - f = open(filename,"w+") - f.write("cylinder(50.0,d=10.0);") - f.close() - doc = importCSG.open(filename) - cylinder = doc.getObject("cylinder") - self.assertTrue (cylinder is not None) - self.assertTrue (cylinder.Radius == 5.0) - self.assertTrue (cylinder.Height == 50.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("cylinder(50.0,d=10.0);","cylinder") + cylinder = doc.getObject("cylinder") + self.assertTrue (cylinder is not None) + self.assertTrue (cylinder.Radius == 5.0) + self.assertTrue (cylinder.Height == 50.0) + FreeCAD.closeDocument(doc.Name) def test_import_cube(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "cube.scad" - f = open(filename,"w+") - f.write("cube([1.0,2.0,3.0]);") - f.close() - doc = importCSG.open(filename) - cube = doc.getObject("cube") - self.assertTrue (cube is not None) - self.assertTrue (cube.Length == 1.0) - self.assertTrue (cube.Width == 2.0) - self.assertTrue (cube.Height == 3.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("cube([1.0,2.0,3.0]);","cube") + cube = doc.getObject("cube") + self.assertTrue (cube is not None) + self.assertTrue (cube.Length == 1.0) + self.assertTrue (cube.Width == 2.0) + self.assertTrue (cube.Height == 3.0) + FreeCAD.closeDocument(doc.Name) def test_import_circle(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "circle.scad" - f = open(filename,"w+") - f.write("circle(10.0);") - f.close() - doc = importCSG.open(filename) - circle = doc.getObject("circle") - self.assertTrue (circle is not None) - self.assertTrue (circle.Radius == 10.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("circle(10.0);","circle") + circle = doc.getObject("circle") + self.assertTrue (circle is not None) + self.assertTrue (circle.Radius == 10.0) + FreeCAD.closeDocument(doc.Name) def test_import_square(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "square.scad" - f = open(filename,"w+") - f.write("square([1.0,2.0]);") - f.close() - doc = importCSG.open(filename) - square = doc.getObject("square") - self.assertTrue (square is not None) - self.assertTrue (square.Length == 1.0) - self.assertTrue (square.Width == 2.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("square([1.0,2.0]);","square") + square = doc.getObject("square") + self.assertTrue (square is not None) + self.assertTrue (square.Length == 1.0) + self.assertTrue (square.Width == 2.0) + FreeCAD.closeDocument(doc.Name) def test_import_text(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "text.scad" - f = open(filename,"w+") - f.write("text(\"X\");") # Keep it short to keep the test fast-ish - f.close() - try: - doc = importCSG.open(filename) - text = doc.getObject("text") - self.assertTrue (text is not None) - FreeCAD.closeDocument(doc.Name) - except Exception: - pass # We may not have the DXF importer available + try: + doc = self.utility_create_scad("text(\"X\");","text") # Keep it short to keep the test fast-ish + text = doc.getObject("text") + self.assertTrue (text is not None) + FreeCAD.closeDocument(doc.Name) + except Exception: + pass # We may not have the DXF importer available def test_import_polygon_nopath(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "polygon_nopath.scad" - f = open(filename,"w+") - f.write("polygon(points=[[0,0],[100,0],[130,50],[30,50]]);") - f.close() - doc = importCSG.open(filename) - polygon = doc.getObject("polygon") - self.assertTrue (polygon is not None) - self.assertAlmostEqual (polygon.Shape.Area, 5000.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("polygon(points=[[0,0],[100,0],[130,50],[30,50]]);","polygon_nopath") + polygon = doc.getObject("polygon") + self.assertTrue (polygon is not None) + self.assertAlmostEqual (polygon.Shape.Area, 5000.0) + FreeCAD.closeDocument(doc.Name) def test_import_polygon_path(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "polygon_path.scad" - f = open(filename,"w+") - f.write("polygon([[0,0],[100,0],[130,50],[30,50]], paths=[[0,1,2,3]]);") - f.close() - doc = importCSG.open(filename) - wire = doc.ActiveObject # With paths, the polygon gets created as a wire... - self.assertTrue (wire is not None) - self.assertAlmostEqual (wire.Shape.Area, 5000.0) - FreeCAD.closeDocument(doc.Name) + doc = self.utility_create_scad("polygon([[0,0],[100,0],[130,50],[30,50]], paths=[[0,1,2,3]]);","polygon_path") + wire = doc.ActiveObject # With paths, the polygon gets created as a wire... + self.assertTrue (wire is not None) + self.assertAlmostEqual (wire.Shape.Area, 5000.0) + FreeCAD.closeDocument(doc.Name) def test_import_polyhedron(self): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + "polyhedron.scad" - f = open(filename,"w+") - f.write( + doc = self.utility_create_scad( """ polyhedron( points=[ [10,10,0],[10,-10,0],[-10,-10,0],[-10,10,0], // the four points at base @@ -187,22 +153,12 @@ polyhedron( faces=[ [0,1,4],[1,2,4],[2,3,4],[3,0,4], // each triangle side [1,0,3],[2,1,3] ] // two triangles for square base ); -""" +""","polyhedron" ) - f.close() - doc = importCSG.open(filename) - polyhedron = doc.ActiveObject # With paths, the polygon gets created as a wire... - self.assertTrue (polyhedron is not None) - self.assertAlmostEqual (polyhedron.Shape.Volume, 1333.3333, 4) - FreeCAD.closeDocument(doc.Name) - - def utility_create_scad(self, scadCode, name): - with tempfile.TemporaryDirectory() as temp_dir: - filename = temp_dir + os.path.sep + name + ".scad" - f = open(filename,"w+") - f.write(scadCode) - f.close() - return importCSG.open(filename) + polyhedron = doc.ActiveObject # With paths, the polygon gets created as a wire... + self.assertTrue (polyhedron is not None) + self.assertAlmostEqual (polyhedron.Shape.Volume, 1333.3333, 4) + FreeCAD.closeDocument(doc.Name) def test_import_difference(self): doc = self.utility_create_scad("difference() { cube(15, center=true); sphere(10); }", "difference") From 02c1277a1d531bc2f8855c684131a813f5f34447 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sun, 7 Nov 2021 21:50:48 -0600 Subject: [PATCH 68/68] OpenSCAD: Minor cleanup of import code --- src/Mod/OpenSCAD/OpenSCADFeatures.py | 257 ++++++++++++++------------- src/Mod/OpenSCAD/importCSG.py | 16 +- 2 files changed, 136 insertions(+), 137 deletions(-) diff --git a/src/Mod/OpenSCAD/OpenSCADFeatures.py b/src/Mod/OpenSCAD/OpenSCADFeatures.py index 93332b67a2..4f3f4d21d8 100644 --- a/src/Mod/OpenSCAD/OpenSCADFeatures.py +++ b/src/Mod/OpenSCAD/OpenSCADFeatures.py @@ -200,13 +200,11 @@ class Resize : self.createGeometry(fp) def createGeometry(self, fp) : - print("Resize create Geometry") import FreeCAD mat = FreeCAD.Matrix() mat.A11 = self.Vector[0] mat.A22 = self.Vector[1] mat.A33 = self.Vector[2] - print(mat) fp.Shape = self.Target.Shape.transformGeometry(mat) def __getstate__(self): @@ -387,7 +385,7 @@ class Frustum: fp.Placement = plm class Twist: - def __init__(self, obj,child=None,h=1.0,angle=0.0,scale=[1.0,1.0]): + def __init__(self, obj, child=None, h=1.0, angle=0.0, scale=[1.0,1.0]): import FreeCAD obj.addProperty("App::PropertyLink","Base","Base", "The base object that must be transformed") @@ -406,10 +404,10 @@ class Twist: self.createGeometry(fp) def onChanged(self, fp, prop): - if prop in ["Angle","Height"]: + if prop in ["Angle","Height","Scale"]: self.createGeometry(fp) - def createGeometry(self,fp): + def createGeometry(self, fp): import FreeCAD,Part,math,sys if fp.Base and fp.Height and fp.Base.Shape.isValid(): solids = [] @@ -443,7 +441,6 @@ class Twist: pipe_shell.add(wire1) pipe_shell.add(wire2) pipe_shell.setAuxiliarySpine(auxiliary_spine,True,0) - print(pipe_shell.getStatus()) assert(pipe_shell.isReady()) pipe_shell.build() faces.extend(pipe_shell.shape().Faces) @@ -534,10 +531,9 @@ class PrismaticToroid: solid = Part.makeSolid (clean_shell) if solid.Volume < 0: solid.reverse() - print (f"Solid volume is {solid.Volume}") solids.append(solid) except Part.OCCError: - print ("Could not create solid: creating compound instead") + FreeCAD.Console.PrintWarning("Could not create solid: creating compound instead") solids.append(Part.Compound(faces)) fp.Shape = Part.Compound(solids) @@ -587,139 +583,146 @@ class CGALFeature: raise ValueError def makeSurfaceVolume(filename): - import FreeCAD,Part,sys + import FreeCAD + import Part + import sys + coords = [] with open(filename) as f1: - coords = [] min_z = sys.float_info.max for line in f1.readlines(): - sline=line.strip() + sline = line.strip() if sline and not sline.startswith('#'): - ycoord=len(coords) - lcoords=[] + ycoord = len(coords) + lcoords = [] for xcoord, num in enumerate(sline.split()): - fnum=float(num) + fnum = float(num) lcoords.append(FreeCAD.Vector(float(xcoord),float(ycoord),fnum)) min_z = min(fnum,min_z) coords.append(lcoords) - - num_rows = len(coords) - num_cols = len(coords[0]) - # OpenSCAD does not spline this surface, so neither do we: just create a bunch of faces, - # using four triangles per quadrilateral - faces = [] - for row in range(num_rows-1): - for col in range(num_cols-1): - a = coords[row+0][col+0] - b = coords[row+0][col+1] - c = coords[row+1][col+1] - d = coords[row+1][col+0] - centroid = 0.25 * (a + b + c + d) - ab = Part.makeLine(a,b) - bc = Part.makeLine(b,c) - cd = Part.makeLine(c,d) - da = Part.makeLine(d,a) + num_rows = len(coords) + if num_rows == 0: + FreeCAD.Console.PrintWarning(f"No data found in surface file {filename}") + return None,0,0 + num_cols = len(coords[0]) - diag_a = Part.makeLine(a, centroid) - diag_b = Part.makeLine(b, centroid) - diag_c = Part.makeLine(c, centroid) - diag_d = Part.makeLine(d, centroid) + # OpenSCAD does not spline this surface, so neither do we: just create a + # bunch of faces, + # using four triangles per quadrilateral + faces = [] + for row in range(num_rows - 1): + for col in range(num_cols - 1): + a = coords[row + 0][col + 0] + b = coords[row + 0][col + 1] + c = coords[row + 1][col + 1] + d = coords[row + 1][col + 0] + centroid = 0.25 * (a + b + c + d) + ab = Part.makeLine(a,b) + bc = Part.makeLine(b,c) + cd = Part.makeLine(c,d) + da = Part.makeLine(d,a) - wire1 = Part.Wire([ab,diag_a,diag_b]) - wire2 = Part.Wire([bc,diag_b,diag_c]) - wire3 = Part.Wire([cd,diag_c,diag_d]) - wire4 = Part.Wire([da,diag_d,diag_a]) + diag_a = Part.makeLine(a, centroid) + diag_b = Part.makeLine(b, centroid) + diag_c = Part.makeLine(c, centroid) + diag_d = Part.makeLine(d, centroid) - try: - face = Part.Face(wire1) - faces.append(face) - face = Part.Face(wire2) - faces.append(face) - face = Part.Face(wire3) - faces.append(face) - face = Part.Face(wire4) - faces.append(face) - except Exception: - print ("Failed to create the face from {},{},{},{}".format(coords[row+0][col+0],\ - coords[row+0][col+1],coords[row+1][col+1],coords[row+1][col+0])) - - last_row = num_rows-1 - last_col = num_cols-1 + wire1 = Part.Wire([ab,diag_a,diag_b]) + wire2 = Part.Wire([bc,diag_b,diag_c]) + wire3 = Part.Wire([cd,diag_c,diag_d]) + wire4 = Part.Wire([da,diag_d,diag_a]) - # Create the face to close off the y-min border: OpenSCAD places the lower surface of the shell - # at 1 unit below the lowest coordinate in the surface - lines = [] - corner1 = FreeCAD.Vector(coords[0][0].x, coords[0][0].y, min_z-1) - lines.append (Part.makeLine(corner1,coords[0][0])) - for col in range(num_cols-1): - a = coords[0][col] - b = coords[0][col+1] - lines.append (Part.makeLine(a, b)) - corner2 = FreeCAD.Vector(coords[0][last_col].x, coords[0][last_col].y, min_z-1) - lines.append (Part.makeLine(corner2,coords[0][last_col])) - lines.append (Part.makeLine(corner1,corner2)) - wire = Part.Wire(lines) - face = Part.Face(wire) - faces.append(face) - - # Create the face to close off the y-max border - lines = [] - corner1 = FreeCAD.Vector(coords[last_row][0].x, coords[last_row][0].y, min_z-1) - lines.append (Part.makeLine(corner1,coords[last_row][0])) - for col in range(num_cols-1): - a = coords[last_row][col] - b = coords[last_row][col+1] - lines.append (Part.makeLine(a, b)) - corner2 = FreeCAD.Vector(coords[last_row][last_col].x, coords[last_row][last_col].y, min_z-1) - lines.append (Part.makeLine(corner2,coords[last_row][last_col])) - lines.append (Part.makeLine(corner1,corner2)) - wire = Part.Wire(lines) - face = Part.Face(wire) - faces.append(face) + try: + face = Part.Face(wire1) + faces.append(face) + face = Part.Face(wire2) + faces.append(face) + face = Part.Face(wire3) + faces.append(face) + face = Part.Face(wire4) + faces.append(face) + except Exception: + FreeCAD.Console.PrintWarning("Failed to create the face from {},{},{},{}".format(coords[row + 0][col + 0],\ + coords[row + 0][col + 1],coords[row + 1][col + 1],coords[row + 1][col + 0])) - # Create the face to close off the x-min border - lines = [] - corner1 = FreeCAD.Vector(coords[0][0].x, coords[0][0].y, min_z-1) - lines.append (Part.makeLine(corner1,coords[0][0])) - for row in range(num_rows-1): - a = coords[row][0] - b = coords[row+1][0] - lines.append (Part.makeLine(a, b)) - corner2 = FreeCAD.Vector(coords[last_row][0].x, coords[last_row][0].y, min_z-1) - lines.append (Part.makeLine(corner2,coords[last_row][0])) - lines.append (Part.makeLine(corner1,corner2)) - wire = Part.Wire(lines) - face = Part.Face(wire) - faces.append(face) + last_row = num_rows - 1 + last_col = num_cols - 1 - # Create the face to close off the x-max border - lines = [] - corner1 = FreeCAD.Vector(coords[0][last_col].x, coords[0][last_col].y, min_z-1) - lines.append (Part.makeLine(corner1,coords[0][last_col])) - for row in range(num_rows-1): - a = coords[row][last_col] - b = coords[row+1][last_col] - lines.append (Part.makeLine(a, b)) - corner2 = FreeCAD.Vector(coords[last_row][last_col].x, coords[last_row][last_col].y, min_z-1) - lines.append (Part.makeLine(corner2,coords[last_row][last_col])) - lines.append (Part.makeLine(corner1,corner2)) - wire = Part.Wire(lines) - face = Part.Face(wire) - faces.append(face) + # Create the face to close off the y-min border: OpenSCAD places the lower + # surface of the shell + # at 1 unit below the lowest coordinate in the surface + lines = [] + corner1 = FreeCAD.Vector(coords[0][0].x, coords[0][0].y, min_z - 1) + lines.append(Part.makeLine(corner1,coords[0][0])) + for col in range(num_cols - 1): + a = coords[0][col] + b = coords[0][col + 1] + lines.append(Part.makeLine(a, b)) + corner2 = FreeCAD.Vector(coords[0][last_col].x, coords[0][last_col].y, min_z - 1) + lines.append(Part.makeLine(corner2,coords[0][last_col])) + lines.append(Part.makeLine(corner1,corner2)) + wire = Part.Wire(lines) + face = Part.Face(wire) + faces.append(face) - # Create a bottom surface to close off the shell - a = FreeCAD.Vector(coords[0][0].x, coords[0][0].y, min_z-1) - b = FreeCAD.Vector(coords[0][last_col].x, coords[0][last_col].y, min_z-1) - c = FreeCAD.Vector(coords[last_row][last_col].x, coords[last_row][last_col].y, min_z-1) - d = FreeCAD.Vector(coords[last_row][0].x, coords[last_row][0].y, min_z-1) - ab = Part.makeLine(a,b) - bc = Part.makeLine(b,c) - cd = Part.makeLine(c,d) - da = Part.makeLine(d,a) - wire = Part.Wire([ab,bc,cd,da]) - face = Part.Face(wire) - faces.append(face) + # Create the face to close off the y-max border + lines = [] + corner1 = FreeCAD.Vector(coords[last_row][0].x, coords[last_row][0].y, min_z - 1) + lines.append(Part.makeLine(corner1,coords[last_row][0])) + for col in range(num_cols - 1): + a = coords[last_row][col] + b = coords[last_row][col + 1] + lines.append(Part.makeLine(a, b)) + corner2 = FreeCAD.Vector(coords[last_row][last_col].x, coords[last_row][last_col].y, min_z - 1) + lines.append(Part.makeLine(corner2,coords[last_row][last_col])) + lines.append(Part.makeLine(corner1,corner2)) + wire = Part.Wire(lines) + face = Part.Face(wire) + faces.append(face) - s = Part.Shell(faces) - solid = Part.Solid(s) - return solid,last_col,last_row + # Create the face to close off the x-min border + lines = [] + corner1 = FreeCAD.Vector(coords[0][0].x, coords[0][0].y, min_z - 1) + lines.append(Part.makeLine(corner1,coords[0][0])) + for row in range(num_rows - 1): + a = coords[row][0] + b = coords[row + 1][0] + lines.append(Part.makeLine(a, b)) + corner2 = FreeCAD.Vector(coords[last_row][0].x, coords[last_row][0].y, min_z - 1) + lines.append(Part.makeLine(corner2,coords[last_row][0])) + lines.append(Part.makeLine(corner1,corner2)) + wire = Part.Wire(lines) + face = Part.Face(wire) + faces.append(face) + + # Create the face to close off the x-max border + lines = [] + corner1 = FreeCAD.Vector(coords[0][last_col].x, coords[0][last_col].y, min_z - 1) + lines.append(Part.makeLine(corner1,coords[0][last_col])) + for row in range(num_rows - 1): + a = coords[row][last_col] + b = coords[row + 1][last_col] + lines.append(Part.makeLine(a, b)) + corner2 = FreeCAD.Vector(coords[last_row][last_col].x, coords[last_row][last_col].y, min_z - 1) + lines.append(Part.makeLine(corner2,coords[last_row][last_col])) + lines.append(Part.makeLine(corner1,corner2)) + wire = Part.Wire(lines) + face = Part.Face(wire) + faces.append(face) + + # Create a bottom surface to close off the shell + a = FreeCAD.Vector(coords[0][0].x, coords[0][0].y, min_z - 1) + b = FreeCAD.Vector(coords[0][last_col].x, coords[0][last_col].y, min_z - 1) + c = FreeCAD.Vector(coords[last_row][last_col].x, coords[last_row][last_col].y, min_z - 1) + d = FreeCAD.Vector(coords[last_row][0].x, coords[last_row][0].y, min_z - 1) + ab = Part.makeLine(a,b) + bc = Part.makeLine(b,c) + cd = Part.makeLine(c,d) + da = Part.makeLine(d,a) + wire = Part.Wire([ab,bc,cd,da]) + face = Part.Face(wire) + faces.append(face) + + s = Part.Shell(faces) + solid = Part.Solid(s) + return solid,last_col,last_row diff --git a/src/Mod/OpenSCAD/importCSG.py b/src/Mod/OpenSCAD/importCSG.py index c59dc778ce..9007750f34 100644 --- a/src/Mod/OpenSCAD/importCSG.py +++ b/src/Mod/OpenSCAD/importCSG.py @@ -79,7 +79,7 @@ def setColorRecursively(obj, color, transp): "Part::Common", "Part::MultiCommon"] if obj.TypeId in boolean_features: for currentObject in obj.OutList: - print(f"Fixing up colors for: {currentObject.FullName}") + if printverbose: print(f"Fixing up colors for: {currentObject.FullName}") if currentObject not in hassetcolor: setColorRecursively(currentObject, color, transp) @@ -767,14 +767,15 @@ def p_linear_extrude_with_transform(p): 'linear_extrude_with_transform : linear_extrude LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE' if printverbose: print("Linear Extrude With Transform") h = float(p[3]['height']) - s = 1.0 + if printverbose: print("Height : ",h) + s = [1.0,1.0] t = 0.0 - if printverbose: print("Twist : ",p[3]) if 'scale' in p[3]: s = [float(p[3]['scale'][0]), float(p[3]['scale'][1])] - print ("Scale: " + str(s)) + if printverbose: print ("Scale: " + str(s)) if 'twist' in p[3]: t = float(p[3]['twist']) + if printverbose: print("Twist : ",t) # Test if null object like from null text if (len(p[6]) == 0) : p[0] = [] @@ -783,7 +784,7 @@ def p_linear_extrude_with_transform(p): obj = fuse(p[6],"Linear Extrude Union") else : obj = p[6][0] - if t != 0.0 or s != 1.0: + if t != 0.0 or s[0] != 1.0 or s[1] != 1.0: newobj = process_linear_extrude_with_transform(obj,h,t,s) else: newobj = process_linear_extrude(obj,h) @@ -1286,11 +1287,7 @@ def p_polyhedron_action(p) : pp =[v2(v[k]) for k in i] # Add first point to end of list to close polygon pp.append(pp[0]) - print("pp") - print(pp) w = Part.makePolygon(pp) - print("w") - print(w) try: f = Part.Face(w) except Exception: @@ -1315,7 +1312,6 @@ def p_projection_action(p) : for shape in p[6]: shape.Shape.tessellate(0.05) bbox.add(shape.Shape.BoundBox) - print (bbox) plane = doc.addObject("Part::Plane","xy_plane_used_for_projection") plane.Length = bbox.XLength plane.Width = bbox.YLength