PD: cleanup the mess with boolean arguments and replace them with a bitmask

This commit is contained in:
wmayer
2021-12-03 14:46:19 +01:00
parent 9135b5ec90
commit b165947625
16 changed files with 113 additions and 56 deletions

View File

@@ -226,6 +226,7 @@ SET(PartDesignGuiModule_SRCS
Command.cpp
CommandPrimitive.cpp
CommandBody.cpp
EnumFlags.h
Resources/PartDesign.qrc
PreCompiled.cpp
PreCompiled.h

View File

@@ -0,0 +1,51 @@
/***************************************************************************
* Copyright (c) 2021 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTDESIGNGUI_ENUMFLAGS_H
#define PARTDESIGNGUI_ENUMFLAGS_H
#include <QFlags>
namespace PartDesignGui {
// https://wiggling-bits.net/using-enum-classes-as-type-safe-bitmasks/
// https://www.boost.org/doc/libs/1_66_0/boost/detail/bitmask.hpp
// https://stackoverflow.com/questions/1448396/how-to-use-enums-as-flags-in-c
enum class AllowSelection {
NONE = 0,
EDGE = 1 << 0, /**< Allow picking edges */
FACE = 1 << 1, /**< Allow picking faces */
PLANAR = 1 << 2, /**< Allow only linear edges and planar faces */
CIRCLE = 1 << 3, /**< Allow picking circular edges (incl arcs) */
POINT = 1 << 4, /**< Allow picking datum points */
OTHERBODY = 1 << 5, /**< Allow picking objects from another body in the same part */
WHOLE = 1 << 6 /**< Allow whole object selection */
};
Q_DECLARE_FLAGS(AllowSelectionFlags, AllowSelection)
} //namespace PartDesignGui
Q_DECLARE_OPERATORS_FOR_FLAGS(PartDesignGui::AllowSelectionFlags)
#endif // PARTDESIGNGUI_ENUMFLAGS_H

View File

@@ -90,9 +90,9 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
// Enable selection from origin of current part/
if ( pObj->getTypeId().isDerivedFrom(App::OriginFeature::getClassTypeId()) ) {
bool fits = false;
if ( plane && pObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ) {
if ( type.testFlag(AllowSelection::FACE) && pObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ) {
fits = true;
} else if ( edge && pObj->getTypeId().isDerivedFrom(App::Line::getClassTypeId()) ) {
} else if ( type.testFlag(AllowSelection::EDGE) && pObj->getTypeId().isDerivedFrom(App::Line::getClassTypeId()) ) {
fits = true;
}
@@ -107,8 +107,9 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
return true;
}
}
} catch (const Base::Exception&)
{ }
}
catch (const Base::Exception&) {
}
}
return false; // The Plane/Axis doesn't fits our needs
}
@@ -117,21 +118,21 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
if (!body) { // Allow selecting Part::Datum features from the active Body
return false;
} else if (!allowOtherBody && !body->hasObject(pObj)) {
} else if (!type.testFlag(AllowSelection::OTHERBODY) && !body->hasObject(pObj)) {
return false;
}
if (plane && (pObj->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())))
if (type.testFlag(AllowSelection::FACE) && (pObj->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())))
return true;
if (edge && (pObj->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())))
if (type.testFlag(AllowSelection::EDGE) && (pObj->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())))
return true;
if (point && (pObj->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())))
if (type.testFlag(AllowSelection::POINT) && (pObj->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())))
return true;
return false;
}
if (!allowOtherBody) {
if (!type.testFlag(AllowSelection::OTHERBODY)) {
if (support == NULL)
return false;
if (pObj != support)
@@ -139,7 +140,7 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
}
// Handle selection of geometry elements
if (!sSubName || sSubName[0] == '\0')
return whole;
return type.testFlag(AllowSelection::WHOLE);
// resolve links if needed
if (!pObj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
@@ -148,12 +149,12 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
if (pObj && pObj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
std::string subName(sSubName);
if (edge && subName.compare(0, 4, "Edge") == 0) {
if (type.testFlag(AllowSelection::EDGE) && subName.compare(0, 4, "Edge") == 0) {
const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue();
TopoDS_Shape sh = shape.getSubShape(subName.c_str());
const TopoDS_Edge& edgeShape = TopoDS::Edge(sh);
if (!edgeShape.IsNull()) {
if (planar) {
if (type.testFlag(AllowSelection::PLANAR)) {
BRepAdaptor_Curve adapt(edgeShape);
if (adapt.GetType() == GeomAbs_Line)
return true;
@@ -162,12 +163,12 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
}
}
}
if (plane && subName.compare(0, 4, "Face") == 0) {
if (type.testFlag(AllowSelection::FACE) && subName.compare(0, 4, "Face") == 0) {
const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue();
TopoDS_Shape sh = shape.getSubShape(subName.c_str());
const TopoDS_Face& face = TopoDS::Face(sh);
if (!face.IsNull()) {
if (planar) {
if (type.testFlag(AllowSelection::PLANAR)) {
BRepAdaptor_Surface adapt(face);
if (adapt.GetType() == GeomAbs_Plane)
return true;
@@ -176,10 +177,10 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
}
}
}
if (point && subName.compare(0, 6, "Vertex") == 0) {
if (type.testFlag(AllowSelection::POINT) && subName.compare(0, 6, "Vertex") == 0) {
return true;
}
if (circle && subName.compare(0, 4, "Edge") == 0) {
if (type.testFlag(AllowSelection::CIRCLE) && subName.compare(0, 4, "Edge") == 0) {
const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue();
TopoDS_Shape sh = shape.getSubShape(subName.c_str());
const TopoDS_Edge& edgeShape = TopoDS::Edge(sh);

View File

@@ -25,33 +25,21 @@
#define GUI_ReferenceSelection_H
#include <Gui/SelectionFilter.h>
#include <Mod/PartDesign/Gui/EnumFlags.h>
namespace PartDesignGui {
class ReferenceSelection : public Gui::SelectionFilterGate
{
// TODO Replace this set of bools with bitwice enum (2015-09-04, Fat-Zer)
const App::DocumentObject* support;
// If set to true, allow picking edges or planes or both
bool edge, plane;
// If set to true, allow only linear edges and planar faces
bool planar;
// If set to true, allow picking datum points
bool point;
// If set to true, allow picking objects from another body in the same part
bool allowOtherBody;
// Allow whole object selection
bool whole;
// Allow picking circular edges (incl arcs)
bool circle;
AllowSelectionFlags type;
public:
ReferenceSelection(const App::DocumentObject* support_,
const bool edge_, const bool plane_, const bool planar_,
const bool point_ = false, bool whole_ = false, bool circle_ = false)
: Gui::SelectionFilterGate((Gui::SelectionFilter*)0),
support(support_), edge(edge_), plane(plane_),
planar(planar_), point(point_), allowOtherBody(true), whole(whole_), circle(circle_)
AllowSelectionFlags type)
: Gui::SelectionFilterGate(static_cast<Gui::SelectionFilter*>(nullptr))
, support(support_)
, type(type)
{
}
/**

View File

@@ -212,7 +212,9 @@ void TaskDraftParameters::onButtonPlane(bool checked)
hideObject();
selectionMode = plane;
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), true, true, true));
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), AllowSelection::EDGE |
AllowSelection::FACE |
AllowSelection::PLANAR));
}
}
@@ -223,7 +225,8 @@ void TaskDraftParameters::onButtonLine(bool checked)
hideObject();
selectionMode = line;
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), true, false, true));
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), AllowSelection::EDGE |
AllowSelection::PLANAR));
}
}

View File

@@ -145,8 +145,11 @@ void TaskDressUpParameters::onButtonRefAdd(bool checked)
clearButtons(refAdd);
hideObject();
selectionMode = refAdd;
AllowSelectionFlags allow;
allow.setFlag(AllowSelection::EDGE, allowEdges);
allow.setFlag(AllowSelection::FACE, allowFaces);
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), allowEdges, allowFaces, false));
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), allow));
DressUpView->highlightReferences(true);
} else {
exitSelectionMode();
@@ -160,8 +163,11 @@ void TaskDressUpParameters::onButtonRefRemove(const bool checked)
clearButtons(refRemove);
hideObject();
selectionMode = refRemove;
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), allowEdges, allowFaces, false));
AllowSelectionFlags allow;
allow.setFlag(AllowSelection::EDGE, allowEdges);
allow.setFlag(AllowSelection::FACE, allowFaces);
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), allow));
DressUpView->highlightReferences(true);
}
else {

View File

@@ -411,7 +411,9 @@ void TaskExtrudeParameters::onDirectionCBChanged(int num)
// to distinguish that this is the direction selection
selectionFace = false;
setDirectionMode(num);
TaskSketchBasedParameters::onSelectReference(true, true, false, true, true);
TaskSketchBasedParameters::onSelectReference(true, AllowSelection::EDGE |
AllowSelection::PLANAR |
AllowSelection::CIRCLE);
}
else {
if (lnk.getValue()) {
@@ -564,7 +566,7 @@ void TaskExtrudeParameters::onButtonFace(const bool pressed)
selectionFace = true;
// only faces are allowed
TaskSketchBasedParameters::onSelectReference(pressed, false, true, false);
TaskSketchBasedParameters::onSelectReference(pressed, AllowSelection::FACE);
// Update button if onButtonFace() is called explicitly
ui->buttonFace->setChecked(pressed);

View File

@@ -426,7 +426,9 @@ void TaskHelixParameters::onAxisChanged(int num)
App::PropertyLinkSub& lnk = *(axesInList[num]);
if (lnk.getValue() == 0) {
// enter reference selection mode
TaskSketchBasedParameters::onSelectReference(true, true, false, true, true);
TaskSketchBasedParameters::onSelectReference(true, AllowSelection::EDGE |
AllowSelection::PLANAR |
AllowSelection::CIRCLE);
return;
}
else {

View File

@@ -333,7 +333,7 @@ void TaskLinearPatternParameters::onDirectionChanged(int /*num*/)
showBase();
selectionMode = reference;
Gui::Selection().clearSelection();
addReferenceSelectionGate(true, true);
addReferenceSelectionGate(AllowSelection::EDGE | AllowSelection::FACE | AllowSelection::PLANAR);
} else {
exitSelectionMode();
pcLinearPattern->Direction.Paste(dirLinks.getCurrentLink());

View File

@@ -246,7 +246,7 @@ void TaskMirroredParameters::onPlaneChanged(int /*num*/)
showBase();
selectionMode = reference;
Gui::Selection().clearSelection();
addReferenceSelectionGate(false, true);
addReferenceSelectionGate(AllowSelection::FACE | AllowSelection::PLANAR);
} else {
exitSelectionMode();
pcMirrored->MirrorPlane.Paste(planeLinks.getCurrentLink());

View File

@@ -324,7 +324,7 @@ void TaskPolarPatternParameters::onAxisChanged(int /*num*/)
showBase();
selectionMode = reference;
Gui::Selection().clearSelection();
addReferenceSelectionGate(true, false, false, false, true);
addReferenceSelectionGate(AllowSelection::EDGE | AllowSelection::CIRCLE);
} else {
exitSelectionMode();
pcPolarPattern->Axis.Paste(axesLinks.getCurrentLink());

View File

@@ -262,7 +262,9 @@ void TaskRevolutionParameters::onAxisChanged(int num)
App::PropertyLinkSub &lnk = *(axesInList[num]);
if (lnk.getValue() == 0) {
// enter reference selection mode
TaskSketchBasedParameters::onSelectReference(true, true, false, true, true);
TaskSketchBasedParameters::onSelectReference(true, AllowSelection::EDGE |
AllowSelection::PLANAR |
AllowSelection::CIRCLE);
} else {
if (!pcRevolution->getDocument()->isIn(lnk.getValue())){
Base::Console().Error("Object was deleted\n");

View File

@@ -112,7 +112,7 @@ void TaskSketchBasedParameters::finishReferenceSelection(App::DocumentObject* pr
}
}
void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool edge, const bool face, const bool planar, const bool circle) {
void TaskSketchBasedParameters::onSelectReference(const bool pressed, AllowSelectionFlags allow) {
// Note: Even if there is no solid, App::Plane and Part::Datum can still be selected
PartDesign::ProfileBased* pcSketchBased = dynamic_cast<PartDesign::ProfileBased*>(vp->getObject());
@@ -123,9 +123,9 @@ void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool
if (pressed) {
startReferenceSelection(pcSketchBased, prevSolid);
Gui::Selection().clearSelection();
Gui::Selection().addSelectionGate
(new ReferenceSelection(prevSolid, edge, face, planar, false, false, circle));
} else {
Gui::Selection().addSelectionGate(new ReferenceSelection(prevSolid, allow));
}
else {
Gui::Selection().rmvSelectionGate();
finishReferenceSelection(pcSketchBased, prevSolid);
}
@@ -135,7 +135,7 @@ void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool
void TaskSketchBasedParameters::exitSelectionMode()
{
onSelectReference(false, false, false, false);
onSelectReference(false, AllowSelection::NONE);
}
QVariant TaskSketchBasedParameters::setUpToFace(const QString& text)

View File

@@ -29,6 +29,7 @@
#include "ViewProvider.h"
#include "TaskFeatureParameters.h"
#include "EnumFlags.h"
namespace App {
class Property;
@@ -53,7 +54,7 @@ protected:
const QString onAddSelection(const Gui::SelectionChanges& msg);
virtual void startReferenceSelection(App::DocumentObject* profile, App::DocumentObject* base);
virtual void finishReferenceSelection(App::DocumentObject* profile, App::DocumentObject* base);
void onSelectReference(const bool pressed, const bool edge, const bool face, const bool planar, const bool circle = false);
void onSelectReference(const bool pressed, AllowSelectionFlags);
void exitSelectionMode();
QVariant setUpToFace(const QString& text);
/// Try to find the name of a feature with the given label.

View File

@@ -410,10 +410,9 @@ void TaskTransformedParameters::exitSelectionMode()
}
}
void TaskTransformedParameters::addReferenceSelectionGate(bool edge, bool face, bool planar, bool whole, bool circle)
void TaskTransformedParameters::addReferenceSelectionGate(AllowSelectionFlags allow)
{
std::unique_ptr<Gui::SelectionFilterGate> gateRefPtr(
new ReferenceSelection(getBaseObject(), edge, face, planar, false, whole, circle));
std::unique_ptr<Gui::SelectionFilterGate> gateRefPtr(new ReferenceSelection(getBaseObject(), allow));
std::unique_ptr<Gui::SelectionFilterGate> gateDepPtr(new NoDependentsSelection(getTopTransformedObject()));
Gui::Selection().addSelectionGate(new CombineSelectionFilterGates(gateRefPtr, gateDepPtr));
}

View File

@@ -27,6 +27,7 @@
#include <QComboBox>
#include <Mod/Part/App/Part2DObject.h>
#include <Mod/PartDesign/Gui/EnumFlags.h>
#include <Gui/TaskView/TaskView.h>
#include <Gui/Selection.h>
@@ -188,7 +189,7 @@ protected:
void hideBase();
void showBase();
void addReferenceSelectionGate(bool edge, bool face, bool planar=true, bool whole=false, bool circle=false);
void addReferenceSelectionGate(AllowSelectionFlags);
bool isViewUpdated() const;
int getUpdateViewTimeout() const;