Merge pull request #8990 from Ondsel-Development/FilletDraftThickness_ui_Consistency
PartDesign: Fillet, Chamfer, Draft, Thickness rework.
This commit is contained in:
@@ -109,7 +109,8 @@ App::DocumentObjectExecReturn *Chamfer::execute()
|
||||
Part::TopoShape TopShape;
|
||||
try {
|
||||
TopShape = getBaseShape();
|
||||
} catch (Base::Exception& e) {
|
||||
}
|
||||
catch (Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
|
||||
@@ -130,9 +131,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
|
||||
|
||||
getContinuousEdges(TopShape, SubNames, FaceNames);
|
||||
|
||||
if (SubNames.empty())
|
||||
return new App::DocumentObjectExecReturn("No edges specified");
|
||||
|
||||
const int chamferType = ChamferType.getValue();
|
||||
const double size = Size.getValue();
|
||||
const double size2 = Size2.getValue();
|
||||
@@ -145,6 +143,13 @@ App::DocumentObjectExecReturn *Chamfer::execute()
|
||||
}
|
||||
|
||||
this->positionByBaseFeature();
|
||||
|
||||
//If no element is selected, then we use a copy of previous feature.
|
||||
if (SubNames.empty()) {
|
||||
this->Shape.setValue(TopShape);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
// create an untransformed copy of the basefeature shape
|
||||
Part::TopoShape baseShape(TopShape);
|
||||
baseShape.setTransform(Base::Matrix4D());
|
||||
|
||||
@@ -102,15 +102,21 @@ App::DocumentObjectExecReturn *Draft::execute()
|
||||
Part::TopoShape TopShape;
|
||||
try {
|
||||
TopShape = getBaseShape();
|
||||
} catch (Base::Exception& e) {
|
||||
}
|
||||
catch (Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
|
||||
// Faces where draft should be applied
|
||||
// Note: Cannot be const reference currently because of BRepOffsetAPI_DraftAngle::Remove() bug, see below
|
||||
std::vector<std::string> SubVals = Base.getSubValuesStartsWith("Face");
|
||||
if (SubVals.empty())
|
||||
return new App::DocumentObjectExecReturn("No faces specified");
|
||||
|
||||
//If no element is selected, then we use a copy of previous feature.
|
||||
if (SubVals.empty()) {
|
||||
this->positionByBaseFeature();
|
||||
this->Shape.setValue(TopShape);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
// Draft angle
|
||||
double angle = Base::toRadians(Angle.getValue());
|
||||
|
||||
@@ -68,7 +68,8 @@ App::DocumentObjectExecReturn *Fillet::execute()
|
||||
Part::TopoShape TopShape;
|
||||
try {
|
||||
TopShape = getBaseShape();
|
||||
} catch (Base::Exception& e) {
|
||||
}
|
||||
catch (Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
std::vector<std::string> SubNames = std::vector<std::string>(Base.getSubValues());
|
||||
@@ -86,9 +87,6 @@ App::DocumentObjectExecReturn *Fillet::execute()
|
||||
|
||||
getContinuousEdges(TopShape, SubNames);
|
||||
|
||||
if (SubNames.empty())
|
||||
return new App::DocumentObjectExecReturn("Fillet not possible on selected shapes");
|
||||
|
||||
double radius = Radius.getValue();
|
||||
|
||||
if(radius <= 0)
|
||||
@@ -96,6 +94,12 @@ App::DocumentObjectExecReturn *Fillet::execute()
|
||||
|
||||
this->positionByBaseFeature();
|
||||
|
||||
//If no element is selected, then we use a copy of previous feature.
|
||||
if (SubNames.empty()) {
|
||||
this->Shape.setValue(TopShape);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
// create an untransformed copy of the base shape
|
||||
Part::TopoShape baseShape(TopShape);
|
||||
baseShape.setTransform(Base::Matrix4D());
|
||||
|
||||
@@ -72,8 +72,22 @@ App::DocumentObjectExecReturn *Thickness::execute()
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
|
||||
TopTools_ListOfShape closingFaces;
|
||||
const std::vector<std::string>& subStrings = Base.getSubValues();
|
||||
|
||||
//If no element is selected, then we use a copy of previous feature.
|
||||
if (subStrings.empty()) {
|
||||
//We must set the placement of the feature in case it's empty.
|
||||
this->positionByBaseFeature();
|
||||
this->Shape.setValue(TopShape);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
/* If the feature was empty at some point, then Placement was set by positionByBaseFeature.
|
||||
* However makeThickSolid apparently requires the placement to be empty, so we have to clear it*/
|
||||
this->Placement.setValue(Base::Placement());
|
||||
|
||||
TopTools_ListOfShape closingFaces;
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = subStrings.begin(); it != subStrings.end(); ++it) {
|
||||
TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(it->c_str()));
|
||||
closingFaces.Append(face);
|
||||
|
||||
@@ -1541,7 +1541,7 @@ bool CmdPartDesignSubtractiveHelix::isActive()
|
||||
//===========================================================================
|
||||
|
||||
bool dressupGetSelected(Gui::Command* cmd, const std::string& which,
|
||||
Gui::SelectionObject &selected, bool &useAllEdges)
|
||||
Gui::SelectionObject &selected, bool &useAllEdges, bool& noSelection)
|
||||
{
|
||||
// No PartDesign feature without Body past FreeCAD 0.16
|
||||
App::Document *doc = cmd->getDocument();
|
||||
@@ -1556,10 +1556,10 @@ bool dressupGetSelected(Gui::Command* cmd, const std::string& which,
|
||||
std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx();
|
||||
|
||||
if (selection.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select an edge, face, or body."));
|
||||
return false;
|
||||
} else if (selection.size() != 1) {
|
||||
noSelection = true;
|
||||
return true;
|
||||
}
|
||||
else if (selection.size() != 1) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select an edge, face, or body from a single body."));
|
||||
return false;
|
||||
@@ -1615,12 +1615,6 @@ bool dressupGetSelected(Gui::Command* cmd, const std::string& which,
|
||||
void finishDressupFeature(const Gui::Command* cmd, const std::string& which,
|
||||
Part::Feature *base, const std::vector<std::string> & SubNames, const bool useAllEdges)
|
||||
{
|
||||
if (SubNames.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QString::fromStdString(which) + QObject::tr(" not possible on selected faces/edges."));
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream str;
|
||||
str << '(' << Gui::Command::getObjectCmd(base) << ",[";
|
||||
for (std::vector<std::string>::const_iterator it = SubNames.begin();it!=SubNames.end();++it){
|
||||
@@ -1656,13 +1650,20 @@ void finishDressupFeature(const Gui::Command* cmd, const std::string& which,
|
||||
void makeChamferOrFillet(Gui::Command* cmd, const std::string& which)
|
||||
{
|
||||
bool useAllEdges = false;
|
||||
bool noSelection = false;
|
||||
Gui::SelectionObject selected;
|
||||
if (!dressupGetSelected ( cmd, which, selected, useAllEdges))
|
||||
if (!dressupGetSelected ( cmd, which, selected, useAllEdges, noSelection))
|
||||
return;
|
||||
|
||||
Part::Feature *base = static_cast<Part::Feature*>(selected.getObject());
|
||||
|
||||
std::vector<std::string> SubNames = std::vector<std::string>(selected.getSubNames());
|
||||
Part::Feature *base;
|
||||
std::vector<std::string> SubNames;
|
||||
if (noSelection) {
|
||||
base = static_cast<Part::Feature*>(PartDesignGui::getBody(true)->Tip.getValue());
|
||||
}
|
||||
else {
|
||||
base = static_cast<Part::Feature*>(selected.getObject());
|
||||
SubNames = std::vector<std::string>(selected.getSubNames());
|
||||
}
|
||||
|
||||
finishDressupFeature (cmd, which, base, SubNames, useAllEdges);
|
||||
}
|
||||
@@ -1746,31 +1747,41 @@ void CmdPartDesignDraft::activated(int iMsg)
|
||||
Q_UNUSED(iMsg);
|
||||
Gui::SelectionObject selected;
|
||||
bool useAllEdges = false;
|
||||
if (!dressupGetSelected ( this, "Draft", selected, useAllEdges))
|
||||
bool noSelection = false;
|
||||
if (!dressupGetSelected ( this, "Draft", selected, useAllEdges, noSelection))
|
||||
return;
|
||||
|
||||
Part::Feature *base = static_cast<Part::Feature*>(selected.getObject());
|
||||
std::vector<std::string> SubNames = std::vector<std::string>(selected.getSubNames());
|
||||
const Part::TopoShape& TopShape = base->Shape.getShape();
|
||||
size_t i = 0;
|
||||
Part::Feature* base;
|
||||
std::vector<std::string> SubNames;
|
||||
if (noSelection) {
|
||||
base = static_cast<Part::Feature*>(PartDesignGui::getBody(true)->Tip.getValue());
|
||||
}
|
||||
else {
|
||||
base = static_cast<Part::Feature*>(selected.getObject());
|
||||
SubNames = std::vector<std::string>(selected.getSubNames());
|
||||
|
||||
// filter out the edges
|
||||
while(i < SubNames.size())
|
||||
{
|
||||
std::string aSubName = static_cast<std::string>(SubNames.at(i));
|
||||
const Part::TopoShape& TopShape = base->Shape.getShape();
|
||||
|
||||
if (aSubName.compare(0, 4, "Face") == 0) {
|
||||
// Check for valid face types
|
||||
TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str()));
|
||||
BRepAdaptor_Surface sf(face);
|
||||
if ((sf.GetType() != GeomAbs_Plane) && (sf.GetType() != GeomAbs_Cylinder) && (sf.GetType() != GeomAbs_Cone))
|
||||
SubNames.erase(SubNames.begin()+i);
|
||||
} else {
|
||||
// empty name or any other sub-element
|
||||
SubNames.erase(SubNames.begin()+i);
|
||||
// filter out the edges
|
||||
size_t i = 0;
|
||||
while (i < SubNames.size())
|
||||
{
|
||||
std::string aSubName = SubNames.at(i);
|
||||
|
||||
if (aSubName.compare(0, 4, "Face") == 0) {
|
||||
// Check for valid face types
|
||||
TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str()));
|
||||
BRepAdaptor_Surface sf(face);
|
||||
if ((sf.GetType() != GeomAbs_Plane) && (sf.GetType() != GeomAbs_Cylinder) && (sf.GetType() != GeomAbs_Cone))
|
||||
SubNames.erase(SubNames.begin() + i);
|
||||
}
|
||||
else {
|
||||
// empty name or any other sub-element
|
||||
SubNames.erase(SubNames.begin() + i);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
finishDressupFeature (this, "Draft", base, SubNames, useAllEdges);
|
||||
@@ -1804,23 +1815,32 @@ void CmdPartDesignThickness::activated(int iMsg)
|
||||
Q_UNUSED(iMsg);
|
||||
Gui::SelectionObject selected;
|
||||
bool useAllEdges = false;
|
||||
if (!dressupGetSelected ( this, "Thickness", selected, useAllEdges))
|
||||
bool noSelection = false;
|
||||
if (!dressupGetSelected ( this, "Thickness", selected, useAllEdges, noSelection))
|
||||
return;
|
||||
|
||||
Part::Feature *base = static_cast<Part::Feature*>(selected.getObject());
|
||||
std::vector<std::string> SubNames = std::vector<std::string>(selected.getSubNames());
|
||||
size_t i = 0;
|
||||
|
||||
// filter out the edges
|
||||
while(i < SubNames.size())
|
||||
{
|
||||
std::string aSubName = static_cast<std::string>(SubNames.at(i));
|
||||
Part::Feature* base;
|
||||
std::vector<std::string> SubNames;
|
||||
if (noSelection) {
|
||||
base = static_cast<Part::Feature*>(PartDesignGui::getBody(true)->Tip.getValue());
|
||||
}
|
||||
else {
|
||||
base = static_cast<Part::Feature*>(selected.getObject());
|
||||
SubNames = std::vector<std::string>(selected.getSubNames());
|
||||
|
||||
if (aSubName.compare(0, 4, "Face") != 0) {
|
||||
// empty name or any other sub-element
|
||||
SubNames.erase(SubNames.begin()+i);
|
||||
// filter out the edges
|
||||
size_t i = 0;
|
||||
while (i < SubNames.size())
|
||||
{
|
||||
std::string aSubName = SubNames.at(i);
|
||||
|
||||
if (aSubName.compare(0, 4, "Face") != 0) {
|
||||
// empty name or any other sub-element
|
||||
SubNames.erase(SubNames.begin() + i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
finishDressupFeature (this, "Thickness", base, SubNames, useAllEdges);
|
||||
|
||||
@@ -62,8 +62,7 @@ TaskChamferParameters::TaskChamferParameters(ViewProviderDressUp *DressUpView, Q
|
||||
|
||||
bool useAllEdges = pcChamfer->UseAllEdges.getValue();
|
||||
ui->checkBoxUseAllEdges->setChecked(useAllEdges);
|
||||
ui->buttonRefAdd->setEnabled(!useAllEdges);
|
||||
ui->buttonRefRemove->setEnabled(!useAllEdges);
|
||||
ui->buttonRefSel->setEnabled(!useAllEdges);
|
||||
ui->listWidgetReferences->setEnabled(!useAllEdges);
|
||||
QMetaObject::invokeMethod(ui->chamferSize, "setFocus", Qt::QueuedConnection);
|
||||
|
||||
@@ -85,15 +84,13 @@ TaskChamferParameters::TaskChamferParameters(ViewProviderDressUp *DressUpView, Q
|
||||
this, &TaskChamferParameters::onAngleChanged);
|
||||
connect(ui->flipDirection, &QCheckBox::toggled,
|
||||
this, &TaskChamferParameters::onFlipDirection);
|
||||
connect(ui->buttonRefAdd, &QToolButton::toggled,
|
||||
this, &TaskChamferParameters::onButtonRefAdd);
|
||||
connect(ui->buttonRefRemove, &QToolButton::toggled,
|
||||
this, &TaskChamferParameters::onButtonRefRemove);
|
||||
connect(ui->buttonRefSel, &QToolButton::toggled,
|
||||
this, &TaskChamferParameters::onButtonRefSel);
|
||||
connect(ui->checkBoxUseAllEdges, &QCheckBox::toggled,
|
||||
this, &TaskChamferParameters::onCheckBoxUseAllEdgesToggled);
|
||||
|
||||
// Create context menu
|
||||
createDeleteAction(ui->listWidgetReferences, ui->buttonRefRemove);
|
||||
createDeleteAction(ui->listWidgetReferences);
|
||||
connect(deleteAction, &QAction::triggered, this, &TaskChamferParameters::onRefDeleted);
|
||||
|
||||
createAddAllEdgesAction(ui->listWidgetReferences);
|
||||
@@ -106,8 +103,10 @@ TaskChamferParameters::TaskChamferParameters(ViewProviderDressUp *DressUpView, Q
|
||||
connect(ui->listWidgetReferences, &QListWidget::itemDoubleClicked,
|
||||
this, &TaskChamferParameters::doubleClicked);
|
||||
|
||||
// the dialog can be called on a broken chamfer, then hide the chamfer
|
||||
hideOnError();
|
||||
if (strings.size() == 0)
|
||||
setSelectionMode(refSel);
|
||||
else
|
||||
hideOnError();
|
||||
}
|
||||
|
||||
void TaskChamferParameters::setUpUI(PartDesign::Chamfer* pcChamfer)
|
||||
@@ -155,119 +154,43 @@ void TaskChamferParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
// executed when the user selected something in the CAD object
|
||||
// adds/deletes the selection accordingly
|
||||
|
||||
if (selectionMode == none)
|
||||
return;
|
||||
|
||||
if (msg.Type == Gui::SelectionChanges::AddSelection) {
|
||||
if (referenceSelected(msg)) {
|
||||
if (selectionMode == refAdd) {
|
||||
ui->listWidgetReferences->addItem(QString::fromStdString(msg.pSubName));
|
||||
// it might be the second one so we can enable the context menu
|
||||
if (ui->listWidgetReferences->count() > 1) {
|
||||
deleteAction->setEnabled(true);
|
||||
deleteAction->setStatusTip(QString());
|
||||
ui->buttonRefRemove->setEnabled(true);
|
||||
ui->buttonRefRemove->setToolTip(tr("Click button to enter selection mode,\nclick again to end selection"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeItemFromListWidget(ui->listWidgetReferences, msg.pSubName);
|
||||
// remove its selection too
|
||||
Gui::Selection().clearSelection();
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
// we must also end the selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
}
|
||||
}
|
||||
// highlight existing references for possible further selections
|
||||
DressUpView->highlightReferences(true);
|
||||
if (selectionMode == refSel) {
|
||||
referenceSelected(msg, ui->listWidgetReferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskChamferParameters::onCheckBoxUseAllEdgesToggled(bool checked)
|
||||
{
|
||||
if(checked)
|
||||
setSelectionMode(none);
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
ui->buttonRefRemove->setEnabled(!checked);
|
||||
ui->buttonRefAdd->setEnabled(!checked);
|
||||
ui->buttonRefSel->setEnabled(!checked);
|
||||
ui->listWidgetReferences->setEnabled(!checked);
|
||||
pcChamfer->UseAllEdges.setValue(checked);
|
||||
pcChamfer->getDocument()->recomputeFeature(pcChamfer);
|
||||
}
|
||||
|
||||
void TaskChamferParameters::clearButtons(const selectionModes notThis)
|
||||
void TaskChamferParameters::setButtons(const selectionModes mode)
|
||||
{
|
||||
if (notThis != refAdd) ui->buttonRefAdd->setChecked(false);
|
||||
if (notThis != refRemove) ui->buttonRefRemove->setChecked(false);
|
||||
DressUpView->highlightReferences(false);
|
||||
ui->buttonRefSel->setChecked(mode == refSel);
|
||||
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr : btnSelectStr);
|
||||
}
|
||||
|
||||
void TaskChamferParameters::onRefDeleted()
|
||||
{
|
||||
// assure we we are not in selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
// delete any selections since the reference(s) might be highlighted
|
||||
Gui::Selection().clearSelection();
|
||||
DressUpView->highlightReferences(false);
|
||||
|
||||
// get the list of items to be deleted
|
||||
QList<QListWidgetItem*> selectedList = ui->listWidgetReferences->selectedItems();
|
||||
|
||||
// if all items are selected, we must stop because one must be kept to avoid that the feature gets broken
|
||||
if (selectedList.count() == ui->listWidgetReferences->model()->rowCount()) {
|
||||
QMessageBox::warning(this, tr("Selection error"), tr("At least one item must be kept."));
|
||||
return;
|
||||
}
|
||||
|
||||
// get the chamfer object
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
App::DocumentObject* base = pcChamfer->Base.getValue();
|
||||
// get all chamfer references
|
||||
std::vector<std::string> refs = pcChamfer->Base.getSubValues();
|
||||
setupTransaction();
|
||||
|
||||
// delete the selection backwards to assure the list index keeps valid for the deletion
|
||||
for (int i = selectedList.count() - 1; i > -1; i--) {
|
||||
// the ref index is the same as the listWidgetReferences index
|
||||
// so we can erase using the row number of the element to be deleted
|
||||
int rowNumber = ui->listWidgetReferences->row(selectedList.at(i));
|
||||
// erase the reference
|
||||
refs.erase(refs.begin() + rowNumber);
|
||||
// remove from the list
|
||||
ui->listWidgetReferences->model()->removeRow(rowNumber);
|
||||
}
|
||||
|
||||
// update the object
|
||||
pcChamfer->Base.setValue(base, refs);
|
||||
// recompute the feature
|
||||
pcChamfer->recomputeFeature();
|
||||
// hide the chamfer if there was a computation error
|
||||
hideOnError();
|
||||
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
}
|
||||
TaskDressUpParameters::deleteRef(ui->listWidgetReferences);
|
||||
}
|
||||
|
||||
void TaskChamferParameters::onAddAllEdges()
|
||||
{
|
||||
TaskDressUpParameters::addAllEdges(ui->listWidgetReferences);
|
||||
ui->buttonRefRemove->setEnabled(true);
|
||||
}
|
||||
|
||||
void TaskChamferParameters::onTypeChanged(int index)
|
||||
{
|
||||
setSelectionMode(none);
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
pcChamfer->ChamferType.setValue(index);
|
||||
ui->stackedWidget->setCurrentIndex(index);
|
||||
@@ -279,6 +202,7 @@ void TaskChamferParameters::onTypeChanged(int index)
|
||||
|
||||
void TaskChamferParameters::onSizeChanged(double len)
|
||||
{
|
||||
setSelectionMode(none);
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcChamfer->Size.setValue(len);
|
||||
@@ -289,6 +213,7 @@ void TaskChamferParameters::onSizeChanged(double len)
|
||||
|
||||
void TaskChamferParameters::onSize2Changed(double len)
|
||||
{
|
||||
setSelectionMode(none);
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcChamfer->Size2.setValue(len);
|
||||
@@ -299,6 +224,7 @@ void TaskChamferParameters::onSize2Changed(double len)
|
||||
|
||||
void TaskChamferParameters::onAngleChanged(double angle)
|
||||
{
|
||||
setSelectionMode(none);
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcChamfer->Angle.setValue(angle);
|
||||
@@ -309,6 +235,7 @@ void TaskChamferParameters::onAngleChanged(double angle)
|
||||
|
||||
void TaskChamferParameters::onFlipDirection(bool flip)
|
||||
{
|
||||
setSelectionMode(none);
|
||||
PartDesign::Chamfer* pcChamfer = static_cast<PartDesign::Chamfer*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcChamfer->FlipDirection.setValue(flip);
|
||||
@@ -391,6 +318,10 @@ void TaskChamferParameters::apply()
|
||||
ui->chamferAngle->apply();
|
||||
break;
|
||||
}
|
||||
|
||||
//Alert user if he created an empty feature
|
||||
if (ui->listWidgetReferences->count() == 0)
|
||||
Base::Console().Warning(tr("Empty chamfer created !\n").toStdString().c_str());
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
|
||||
@@ -55,7 +55,7 @@ private Q_SLOTS:
|
||||
void onCheckBoxUseAllEdgesToggled(bool checked);
|
||||
|
||||
protected:
|
||||
void clearButtons(const selectionModes notThis) override;
|
||||
void setButtons(const selectionModes mode) override;
|
||||
bool event(QEvent *e) override;
|
||||
void changeEvent(QEvent *e) override;
|
||||
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
|
||||
|
||||
@@ -15,36 +15,18 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefAdd">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
<widget class="QToolButton" name="buttonRefSel">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefRemove">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidgetReferences">
|
||||
|
||||
@@ -85,17 +85,15 @@ TaskDraftParameters::TaskDraftParameters(ViewProviderDressUp *DressUpView, QWidg
|
||||
this, &TaskDraftParameters::onAngleChanged);
|
||||
connect(ui->checkReverse, &QCheckBox::toggled,
|
||||
this, &TaskDraftParameters::onReversedChanged);
|
||||
connect(ui->buttonRefAdd, &QToolButton::toggled,
|
||||
this, &TaskDraftParameters::onButtonRefAdd);
|
||||
connect(ui->buttonRefRemove, &QToolButton::toggled,
|
||||
this, &TaskDraftParameters::onButtonRefRemove);
|
||||
connect(ui->buttonRefSel, &QToolButton::toggled,
|
||||
this, &TaskDraftParameters::onButtonRefSel);
|
||||
connect(ui->buttonPlane, &QToolButton::toggled,
|
||||
this, &TaskDraftParameters::onButtonPlane);
|
||||
connect(ui->buttonLine, &QToolButton::toggled,
|
||||
this, &TaskDraftParameters::onButtonLine);
|
||||
|
||||
// Create context menu
|
||||
createDeleteAction(ui->listWidgetReferences, ui->buttonRefRemove);
|
||||
createDeleteAction(ui->listWidgetReferences);
|
||||
connect(deleteAction, &QAction::triggered, this, &TaskDraftParameters::onRefDeleted);
|
||||
|
||||
connect(ui->listWidgetReferences, &QListWidget::currentItemChanged,
|
||||
@@ -113,8 +111,10 @@ TaskDraftParameters::TaskDraftParameters(ViewProviderDressUp *DressUpView, QWidg
|
||||
strings = pcDraft->PullDirection.getSubValues();
|
||||
ui->lineLine->setText(getRefStr(ref, strings));
|
||||
|
||||
// the dialog can be called on a broken draft, then hide the draft
|
||||
hideOnError();
|
||||
if (strings.size() == 0)
|
||||
setSelectionMode(refSel);
|
||||
else
|
||||
hideOnError();
|
||||
}
|
||||
|
||||
void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
@@ -122,39 +122,11 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
// executed when the user selected something in the CAD object
|
||||
// adds/deletes the selection accordingly
|
||||
|
||||
if (selectionMode == none)
|
||||
return;
|
||||
|
||||
if (msg.Type == Gui::SelectionChanges::AddSelection) {
|
||||
if (referenceSelected(msg)) {
|
||||
if (selectionMode == refAdd) {
|
||||
ui->listWidgetReferences->addItem(QString::fromStdString(msg.pSubName));
|
||||
// it might be the second one so we can enable the context menu
|
||||
if (ui->listWidgetReferences->count() > 1) {
|
||||
deleteAction->setEnabled(true);
|
||||
deleteAction->setStatusTip(QString());
|
||||
ui->buttonRefRemove->setEnabled(true);
|
||||
ui->buttonRefRemove->setToolTip(tr("Click button to enter selection mode,\nclick again to end selection"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeItemFromListWidget(ui->listWidgetReferences, msg.pSubName);
|
||||
// remove its selection too
|
||||
Gui::Selection().clearSelection();
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
// we must also end the selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
}
|
||||
}
|
||||
// highlight existing references for possible further selections
|
||||
DressUpView->highlightReferences(true);
|
||||
} else if (selectionMode == plane) {
|
||||
if (selectionMode == refSel) {
|
||||
referenceSelected(msg, ui->listWidgetReferences);
|
||||
}
|
||||
else if (selectionMode == plane) {
|
||||
PartDesign::Draft* pcDraft = static_cast<PartDesign::Draft*>(DressUpView->getObject());
|
||||
std::vector<std::string> planes;
|
||||
App::DocumentObject* selObj;
|
||||
@@ -170,7 +142,8 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
DressUpView->highlightReferences(true);
|
||||
// hide the draft if there was a computation error
|
||||
hideOnError();
|
||||
} else if (selectionMode == line) {
|
||||
}
|
||||
else if (selectionMode == line) {
|
||||
PartDesign::Draft* pcDraft = static_cast<PartDesign::Draft*>(DressUpView->getObject());
|
||||
std::vector<std::string> edges;
|
||||
App::DocumentObject* selObj;
|
||||
@@ -190,19 +163,18 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
}
|
||||
}
|
||||
|
||||
void TaskDraftParameters::clearButtons(const selectionModes notThis)
|
||||
void TaskDraftParameters::setButtons(const selectionModes mode)
|
||||
{
|
||||
if (notThis != refAdd) ui->buttonRefAdd->setChecked(false);
|
||||
if (notThis != refRemove) ui->buttonRefRemove->setChecked(false);
|
||||
if (notThis != line) ui->buttonLine->setChecked(false);
|
||||
if (notThis != plane) ui->buttonPlane->setChecked(false);
|
||||
DressUpView->highlightReferences(false);
|
||||
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr : btnSelectStr);
|
||||
ui->buttonRefSel->setChecked(mode == refSel);
|
||||
ui->buttonLine->setChecked(mode == line);
|
||||
ui->buttonPlane->setChecked(mode == plane);
|
||||
}
|
||||
|
||||
void TaskDraftParameters::onButtonPlane(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
clearButtons(plane);
|
||||
setButtons(plane);
|
||||
hideObject();
|
||||
selectionMode = plane;
|
||||
Gui::Selection().clearSelection();
|
||||
@@ -215,7 +187,7 @@ void TaskDraftParameters::onButtonPlane(bool checked)
|
||||
void TaskDraftParameters::onButtonLine(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
clearButtons(line);
|
||||
setButtons(line);
|
||||
hideObject();
|
||||
selectionMode = line;
|
||||
Gui::Selection().clearSelection();
|
||||
@@ -226,54 +198,7 @@ void TaskDraftParameters::onButtonLine(bool checked)
|
||||
|
||||
void TaskDraftParameters::onRefDeleted(void)
|
||||
{
|
||||
// assure we we are not in selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
// delete any selections since the reference(s) might be highlighted
|
||||
Gui::Selection().clearSelection();
|
||||
DressUpView->highlightReferences(false);
|
||||
|
||||
// get the list of items to be deleted
|
||||
QList<QListWidgetItem*> selectedList = ui->listWidgetReferences->selectedItems();
|
||||
|
||||
// if all items are selected, we must stop because one must be kept to avoid that the feature gets broken
|
||||
if (selectedList.count() == ui->listWidgetReferences->model()->rowCount()) {
|
||||
QMessageBox::warning(this, tr("Selection error"), tr("At least one item must be kept."));
|
||||
return;
|
||||
}
|
||||
|
||||
// get the draft object
|
||||
PartDesign::Draft* pcDraft = static_cast<PartDesign::Draft*>(DressUpView->getObject());
|
||||
App::DocumentObject* base = pcDraft->Base.getValue();
|
||||
// get all draft references
|
||||
std::vector<std::string> refs = pcDraft->Base.getSubValues();
|
||||
setupTransaction();
|
||||
|
||||
// delete the selection backwards to assure the list index keeps valid for the deletion
|
||||
for (int i = selectedList.count() - 1; i > -1; i--) {
|
||||
// the ref index is the same as the listWidgetReferences index
|
||||
// so we can erase using the row number of the element to be deleted
|
||||
int rowNumber = ui->listWidgetReferences->row(selectedList.at(i));
|
||||
// erase the reference
|
||||
refs.erase(refs.begin() + rowNumber);
|
||||
// remove from the list
|
||||
ui->listWidgetReferences->model()->removeRow(rowNumber);
|
||||
}
|
||||
|
||||
// update the object
|
||||
pcDraft->Base.setValue(base, refs);
|
||||
// recompute the feature
|
||||
pcDraft->recomputeFeature();
|
||||
// hide the draft if there was a computation error
|
||||
hideOnError();
|
||||
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
}
|
||||
TaskDressUpParameters::deleteRef(ui->listWidgetReferences);
|
||||
}
|
||||
|
||||
void TaskDraftParameters::getPlane(App::DocumentObject*& obj, std::vector<std::string>& sub) const
|
||||
@@ -296,7 +221,7 @@ void TaskDraftParameters::getLine(App::DocumentObject*& obj, std::vector<std::st
|
||||
|
||||
void TaskDraftParameters::onAngleChanged(double angle)
|
||||
{
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Draft* pcDraft = static_cast<PartDesign::Draft*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcDraft->Angle.setValue(angle);
|
||||
@@ -311,7 +236,7 @@ double TaskDraftParameters::getAngle(void) const
|
||||
}
|
||||
|
||||
void TaskDraftParameters::onReversedChanged(const bool on) {
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Draft* pcDraft = static_cast<PartDesign::Draft*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcDraft->Reversed.setValue(on);
|
||||
@@ -350,6 +275,14 @@ void TaskDraftParameters::changeEvent(QEvent *e)
|
||||
}
|
||||
}
|
||||
|
||||
void TaskDraftParameters::apply()
|
||||
{
|
||||
//Alert user if he created an empty feature
|
||||
if (ui->listWidgetReferences->count() == 0)
|
||||
Base::Console().Warning(tr("Empty draft created !\n").toStdString().c_str());
|
||||
|
||||
TaskDressUpParameters::apply();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
@@ -387,6 +320,8 @@ bool TaskDlgDraftParameters::accept()
|
||||
if (!tobj->isError())
|
||||
parameter->showObject();
|
||||
|
||||
parameter->apply();
|
||||
|
||||
std::vector<std::string> strings;
|
||||
App::DocumentObject* obj;
|
||||
TaskDraftParameters* draftparameter = static_cast<TaskDraftParameters*>(parameter);
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
explicit TaskDraftParameters(ViewProviderDressUp *DressUpView, QWidget *parent=nullptr);
|
||||
~TaskDraftParameters() override;
|
||||
|
||||
void apply() override;
|
||||
|
||||
double getAngle() const;
|
||||
bool getReversed() const;
|
||||
const std::vector<std::string> getFaces() const;
|
||||
@@ -54,7 +56,7 @@ private Q_SLOTS:
|
||||
void onRefDeleted() override;
|
||||
|
||||
protected:
|
||||
void clearButtons(const selectionModes notThis) override;
|
||||
void setButtons(const selectionModes mode) override;
|
||||
bool event(QEvent *e) override;
|
||||
void changeEvent(QEvent *e) override;
|
||||
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
|
||||
|
||||
@@ -15,36 +15,19 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefAdd">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
|
||||
<widget class="QToolButton" name="buttonRefSel">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add face</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefRemove">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove face</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidgetReferences">
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include <Gui/Tools.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
#include <Mod/PartDesign/App/Body.h>
|
||||
#include <Mod/PartDesign/App/FeatureDressUp.h>
|
||||
#include <Mod/PartDesign/Gui/ReferenceSelection.h>
|
||||
|
||||
#include "TaskDressUpParameters.h"
|
||||
@@ -52,6 +51,9 @@ FC_LOG_LEVEL_INIT("PartDesign",true,true)
|
||||
using namespace PartDesignGui;
|
||||
using namespace Gui;
|
||||
|
||||
const QString TaskDressUpParameters::btnPreviewStr = tr("Preview");
|
||||
const QString TaskDressUpParameters::btnSelectStr = tr("Select");
|
||||
|
||||
/* TRANSLATOR PartDesignGui::TaskDressUpParameters */
|
||||
|
||||
TaskDressUpParameters::TaskDressUpParameters(ViewProviderDressUp *DressUpView, bool selectEdges, bool selectFaces, QWidget *parent)
|
||||
@@ -95,122 +97,102 @@ void TaskDressUpParameters::setupTransaction()
|
||||
transactionID = App::GetApplication().setActiveTransaction(n.c_str());
|
||||
}
|
||||
|
||||
bool TaskDressUpParameters::referenceSelected(const Gui::SelectionChanges& msg)
|
||||
void TaskDressUpParameters::referenceSelected(const Gui::SelectionChanges& msg, QListWidget* widget)
|
||||
{
|
||||
if ((msg.Type == Gui::SelectionChanges::AddSelection) && (
|
||||
(selectionMode == refAdd) || (selectionMode == refRemove))) {
|
||||
if (strcmp(msg.pDocName, DressUpView->getObject()->getDocument()->getName()) != 0)
|
||||
return;
|
||||
|
||||
if (strcmp(msg.pDocName, DressUpView->getObject()->getDocument()->getName()) != 0)
|
||||
return false;
|
||||
Gui::Selection().clearSelection();
|
||||
|
||||
PartDesign::DressUp* pcDressUp = static_cast<PartDesign::DressUp*>(DressUpView->getObject());
|
||||
App::DocumentObject* base = this->getBase();
|
||||
PartDesign::DressUp* pcDressUp = static_cast<PartDesign::DressUp*>(DressUpView->getObject());
|
||||
App::DocumentObject* base = this->getBase();
|
||||
|
||||
// TODO: Must we make a copy here instead of assigning to const char* ?
|
||||
const char* fname = base->getNameInDocument();
|
||||
if (strcmp(msg.pObjectName, fname) != 0)
|
||||
return false;
|
||||
// TODO: Must we make a copy here instead of assigning to const char* ?
|
||||
const char* fname = base->getNameInDocument();
|
||||
if (strcmp(msg.pObjectName, fname) != 0)
|
||||
return;
|
||||
|
||||
std::string subName(msg.pSubName);
|
||||
std::vector<std::string> refs = pcDressUp->Base.getSubValues();
|
||||
std::vector<std::string>::iterator f = std::find(refs.begin(), refs.end(), subName);
|
||||
std::string subName(msg.pSubName);
|
||||
std::vector<std::string> refs = pcDressUp->Base.getSubValues();
|
||||
std::vector<std::string>::iterator f = std::find(refs.begin(), refs.end(), subName);
|
||||
|
||||
if (selectionMode == refAdd) {
|
||||
if (f == refs.end())
|
||||
refs.push_back(subName);
|
||||
else
|
||||
return false; // duplicate selection
|
||||
} else {
|
||||
if (f != refs.end())
|
||||
refs.erase(f);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
DressUpView->highlightReferences(false);
|
||||
setupTransaction();
|
||||
pcDressUp->Base.setValue(base, refs);
|
||||
pcDressUp->getDocument()->recomputeFeature(pcDressUp);
|
||||
|
||||
return true;
|
||||
if (f != refs.end()) { //If it's found then it's in the list so we remove it.
|
||||
refs.erase(f);
|
||||
removeItemFromListWidget(widget, msg.pSubName);
|
||||
}
|
||||
else { //if it's not found then it's not yet in the list so we add it.
|
||||
refs.push_back(subName);
|
||||
widget->addItem(QString::fromStdString(msg.pSubName));
|
||||
}
|
||||
|
||||
return false;
|
||||
updateFeature(pcDressUp, refs);
|
||||
}
|
||||
|
||||
void TaskDressUpParameters::addAllEdges(QListWidget* widget)
|
||||
{
|
||||
PartDesign::DressUp* pcDressUp = static_cast<PartDesign::DressUp*>(DressUpView->getObject());
|
||||
if (pcDressUp) {
|
||||
App::DocumentObject* base = pcDressUp->Base.getValue();
|
||||
if (base) {
|
||||
Gui::WaitCursor wait;
|
||||
int count = pcDressUp->getBaseTopoShape().countSubElements("Edge");
|
||||
std::vector<std::string> edgeNames;
|
||||
for (int ii = 0; ii < count; ii++){
|
||||
std::ostringstream edgeName;
|
||||
edgeName << "Edge" << ii+1;
|
||||
edgeNames.push_back(edgeName.str());
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it){
|
||||
if (widget->findItems(QLatin1String(it->c_str()), Qt::MatchExactly).isEmpty()){
|
||||
widget->addItem(QLatin1String(it->c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
pcDressUp->Base.setValue(base, edgeNames);
|
||||
pcDressUp->getDocument()->recomputeFeature(pcDressUp);
|
||||
hideObject();
|
||||
DressUpView->highlightReferences(true);
|
||||
onButtonRefAdd(true);
|
||||
|
||||
if (deleteAction) {
|
||||
deleteAction->setEnabled(widget->count() > 1);
|
||||
}
|
||||
}
|
||||
Gui::WaitCursor wait;
|
||||
int count = pcDressUp->getBaseTopoShape().countSubElements("Edge");
|
||||
std::vector<std::string> edgeNames;
|
||||
for (int ii = 0; ii < count; ii++){
|
||||
std::ostringstream edgeName;
|
||||
edgeName << "Edge" << ii+1;
|
||||
edgeNames.push_back(edgeName.str());
|
||||
}
|
||||
|
||||
//First we need to clear the widget in case the user had faces selected. Else the faces will still be in widget but not in the feature refs!
|
||||
QSignalBlocker block(widget);
|
||||
widget->clear();
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it){
|
||||
widget->addItem(QLatin1String(it->c_str()));
|
||||
}
|
||||
|
||||
updateFeature(pcDressUp, edgeNames);
|
||||
}
|
||||
|
||||
void TaskDressUpParameters::onButtonRefAdd(bool checked)
|
||||
void TaskDressUpParameters::deleteRef(QListWidget* widget)
|
||||
{
|
||||
if (checked) {
|
||||
clearButtons(refAdd);
|
||||
hideObject();
|
||||
selectionMode = refAdd;
|
||||
if (addAllEdgesAction)
|
||||
addAllEdgesAction->setEnabled(true);
|
||||
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 {
|
||||
if (addAllEdgesAction)
|
||||
addAllEdgesAction->setEnabled(false);
|
||||
exitSelectionMode();
|
||||
DressUpView->highlightReferences(false);
|
||||
// delete any selections since the reference(s) being deleted might be highlighted
|
||||
Gui::Selection().clearSelection();
|
||||
|
||||
// get the list of items to be deleted
|
||||
QList<QListWidgetItem*> selectedList = widget->selectedItems();
|
||||
|
||||
PartDesign::DressUp* pcDressUp = static_cast<PartDesign::DressUp*>(DressUpView->getObject());
|
||||
std::vector<std::string> refs = pcDressUp->Base.getSubValues();
|
||||
|
||||
// delete the selection backwards to assure the list index keeps valid for the deletion
|
||||
QSignalBlocker block(widget);
|
||||
for (int i = selectedList.count() - 1; i > -1; i--) {
|
||||
// the ref index is the same as the listWidgetReferences index
|
||||
// so we can erase using the row number of the element to be deleted
|
||||
int rowNumber = widget->row(selectedList.at(i));
|
||||
refs.erase(refs.begin() + rowNumber);
|
||||
widget->model()->removeRow(rowNumber);
|
||||
}
|
||||
|
||||
updateFeature(pcDressUp, refs);
|
||||
}
|
||||
|
||||
void TaskDressUpParameters::onButtonRefRemove(const bool checked)
|
||||
void TaskDressUpParameters::updateFeature(PartDesign::DressUp* pcDressUp, const std::vector<std::string>& refs)
|
||||
{
|
||||
if (checked) {
|
||||
clearButtons(refRemove);
|
||||
hideObject();
|
||||
selectionMode = refRemove;
|
||||
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 {
|
||||
exitSelectionMode();
|
||||
if (selectionMode == refSel)
|
||||
DressUpView->highlightReferences(false);
|
||||
}
|
||||
|
||||
setupTransaction();
|
||||
pcDressUp->Base.setValue(pcDressUp->Base.getValue(), refs);
|
||||
pcDressUp->recomputeFeature();
|
||||
if (selectionMode == refSel)
|
||||
DressUpView->highlightReferences(true);
|
||||
else
|
||||
hideOnError();
|
||||
}
|
||||
|
||||
void TaskDressUpParameters::onButtonRefSel(bool checked)
|
||||
{
|
||||
setSelectionMode(checked ? refSel : none);
|
||||
}
|
||||
|
||||
void TaskDressUpParameters::doubleClicked(QListWidgetItem* item) {
|
||||
@@ -221,14 +203,7 @@ void TaskDressUpParameters::doubleClicked(QListWidgetItem* item) {
|
||||
wasDoubleClicked = true;
|
||||
|
||||
// assure we are not in selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
|
||||
// assure the fillets are shown
|
||||
showObject();
|
||||
// remove any highlights and selections
|
||||
DressUpView->highlightReferences(false);
|
||||
Gui::Selection().clearSelection();
|
||||
setSelectionMode(none);
|
||||
|
||||
// enable next possible single-click event after double-click time passed
|
||||
QTimer::singleShot(QApplication::doubleClickInterval(), this, &TaskDressUpParameters::itemClickedTimeout);
|
||||
@@ -251,15 +226,16 @@ void TaskDressUpParameters::setSelection(QListWidgetItem* current) {
|
||||
if (body) {
|
||||
std::string objName = body->getNameInDocument();
|
||||
|
||||
// hide fillet to see the original edge
|
||||
// (a fillet creates new edges so that the original one is not available)
|
||||
hideObject();
|
||||
// highlight all objects in the list
|
||||
DressUpView->highlightReferences(true);
|
||||
// clear existing selection because only the current item is highlighted, not all selected ones to keep the overview
|
||||
Gui::Selection().clearSelection();
|
||||
// Enter selection mode
|
||||
if (selectionMode == none)
|
||||
setSelectionMode(refSel);
|
||||
else
|
||||
Gui::Selection().clearSelection();
|
||||
|
||||
// highlight the selected item
|
||||
bool block = this->blockSelection(true);
|
||||
Gui::Selection().addSelection(docName.c_str(), objName.c_str(), subName.c_str(), 0, 0, 0);
|
||||
this->blockSelection(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,13 +256,11 @@ void TaskDressUpParameters::createAddAllEdgesAction(QListWidget* parentList)
|
||||
addAllEdgesAction->setShortcutVisibleInContextMenu(true);
|
||||
#endif
|
||||
parentList->addAction(addAllEdgesAction);
|
||||
addAllEdgesAction->setEnabled(false);
|
||||
addAllEdgesAction->setStatusTip(tr("Adds all edges to the list box (active only when in add selection mode)."));
|
||||
parentList->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
}
|
||||
|
||||
|
||||
void TaskDressUpParameters::createDeleteAction(QListWidget* parentList, QWidget* parentButton)
|
||||
void TaskDressUpParameters::createDeleteAction(QListWidget* parentList)
|
||||
{
|
||||
// creates a context menu, a shortcut for it and connects it to a slot function
|
||||
|
||||
@@ -297,13 +271,6 @@ void TaskDressUpParameters::createDeleteAction(QListWidget* parentList, QWidget*
|
||||
deleteAction->setShortcutVisibleInContextMenu(true);
|
||||
#endif
|
||||
parentList->addAction(deleteAction);
|
||||
// if there is only one item, it cannot be deleted
|
||||
if (parentList->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
parentButton->setEnabled(false);
|
||||
parentButton->setToolTip(tr("There must be at least one item"));
|
||||
}
|
||||
parentList->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
}
|
||||
|
||||
@@ -395,12 +362,31 @@ Part::Feature* TaskDressUpParameters::getBase(void) const
|
||||
return pcDressUp->getBaseObject();
|
||||
}
|
||||
|
||||
void TaskDressUpParameters::exitSelectionMode()
|
||||
void TaskDressUpParameters::setSelectionMode(selectionModes mode)
|
||||
{
|
||||
selectionMode = none;
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
selectionMode = mode;
|
||||
setButtons(mode);
|
||||
|
||||
if (mode == none) {
|
||||
showObject();
|
||||
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
|
||||
// remove any highlights and selections
|
||||
DressUpView->highlightReferences(false);
|
||||
}
|
||||
else {
|
||||
hideObject();
|
||||
|
||||
AllowSelectionFlags allow;
|
||||
allow.setFlag(AllowSelection::EDGE, allowEdges);
|
||||
allow.setFlag(AllowSelection::FACE, allowFaces);
|
||||
Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), allow));
|
||||
|
||||
DressUpView->highlightReferences(true);
|
||||
}
|
||||
|
||||
Gui::Selection().clearSelection();
|
||||
showObject();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define GUI_TASKVIEW_TaskDressUpParameters_H
|
||||
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Mod/PartDesign/App/FeatureDressUp.h>
|
||||
|
||||
#include "TaskFeatureParameters.h"
|
||||
#include "ViewProviderDressUp.h"
|
||||
@@ -63,26 +64,27 @@ public:
|
||||
}
|
||||
|
||||
protected Q_SLOTS:
|
||||
void onButtonRefAdd(const bool checked);
|
||||
void onButtonRefRemove(const bool checked);
|
||||
void onButtonRefSel(const bool checked);
|
||||
void doubleClicked(QListWidgetItem* item);
|
||||
void setSelection(QListWidgetItem* current);
|
||||
void itemClickedTimeout();
|
||||
virtual void onRefDeleted(void) = 0;
|
||||
void createDeleteAction(QListWidget* parentList, QWidget* parentButton);
|
||||
void createDeleteAction(QListWidget* parentList);
|
||||
void createAddAllEdgesAction(QListWidget* parentList);
|
||||
|
||||
protected:
|
||||
void exitSelectionMode();
|
||||
bool referenceSelected(const Gui::SelectionChanges& msg);
|
||||
void referenceSelected(const Gui::SelectionChanges& msg, QListWidget* widget);
|
||||
bool wasDoubleClicked = false;
|
||||
bool KeyEvent(QEvent *e);
|
||||
void hideOnError();
|
||||
void addAllEdges(QListWidget* listWidget);
|
||||
void deleteRef(QListWidget* listWidget);
|
||||
void updateFeature(PartDesign::DressUp* pcDressUp, const std::vector<std::string>& refs);
|
||||
|
||||
protected:
|
||||
enum selectionModes { none, refAdd, refRemove, plane, line };
|
||||
virtual void clearButtons(const selectionModes notThis) = 0;
|
||||
enum selectionModes { none, refSel, plane, line };
|
||||
void setSelectionMode(selectionModes mode);
|
||||
virtual void setButtons(const selectionModes mode) = 0;
|
||||
static void removeItemFromListWidget(QListWidget* widget, const char* itemstr);
|
||||
|
||||
ViewProviderDressUp* getDressUpView() const
|
||||
@@ -97,6 +99,9 @@ protected:
|
||||
bool allowFaces, allowEdges;
|
||||
selectionModes selectionMode;
|
||||
int transactionID;
|
||||
|
||||
static const QString btnPreviewStr;
|
||||
static const QString btnSelectStr;
|
||||
};
|
||||
|
||||
/// simulation dialog for the TaskView
|
||||
|
||||
@@ -52,14 +52,12 @@ TaskFilletParameters::TaskFilletParameters(ViewProviderDressUp *DressUpView, QWi
|
||||
// we need a separate container widget to add all controls to
|
||||
proxy = new QWidget(this);
|
||||
ui->setupUi(proxy);
|
||||
|
||||
this->groupLayout()->addWidget(proxy);
|
||||
|
||||
PartDesign::Fillet* pcFillet = static_cast<PartDesign::Fillet*>(DressUpView->getObject());
|
||||
bool useAllEdges = pcFillet->UseAllEdges.getValue();
|
||||
ui->checkBoxUseAllEdges->setChecked(useAllEdges);
|
||||
ui->buttonRefAdd->setEnabled(!useAllEdges);
|
||||
ui->buttonRefRemove->setEnabled(!useAllEdges);
|
||||
ui->buttonRefSel->setEnabled(!useAllEdges);
|
||||
ui->listWidgetReferences->setEnabled(!useAllEdges);
|
||||
double r = pcFillet->Radius.getValue();
|
||||
|
||||
@@ -79,15 +77,13 @@ TaskFilletParameters::TaskFilletParameters(ViewProviderDressUp *DressUpView, QWi
|
||||
|
||||
connect(ui->filletRadius, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this, &TaskFilletParameters::onLengthChanged);
|
||||
connect(ui->buttonRefAdd, &QToolButton::toggled,
|
||||
this, &TaskFilletParameters::onButtonRefAdd);
|
||||
connect(ui->buttonRefRemove, &QToolButton::toggled,
|
||||
this, &TaskFilletParameters::onButtonRefRemove);
|
||||
connect(ui->buttonRefSel, &QToolButton::toggled,
|
||||
this, &TaskFilletParameters::onButtonRefSel);
|
||||
connect(ui->checkBoxUseAllEdges, &QToolButton::toggled,
|
||||
this, &TaskFilletParameters::onCheckBoxUseAllEdgesToggled);
|
||||
|
||||
// Create context menu
|
||||
createDeleteAction(ui->listWidgetReferences, ui->buttonRefRemove);
|
||||
createDeleteAction(ui->listWidgetReferences);
|
||||
connect(deleteAction, &QAction::triggered, this, &TaskFilletParameters::onRefDeleted);
|
||||
|
||||
createAddAllEdgesAction(ui->listWidgetReferences);
|
||||
@@ -100,8 +96,10 @@ TaskFilletParameters::TaskFilletParameters(ViewProviderDressUp *DressUpView, QWi
|
||||
connect(ui->listWidgetReferences, &QListWidget::itemDoubleClicked,
|
||||
this, &TaskFilletParameters::doubleClicked);
|
||||
|
||||
// the dialog can be called on a broken fillet, then hide the fillet
|
||||
hideOnError();
|
||||
if (strings.size() == 0)
|
||||
setSelectionMode(refSel);
|
||||
else
|
||||
hideOnError();
|
||||
}
|
||||
|
||||
void TaskFilletParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
@@ -109,120 +107,43 @@ void TaskFilletParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
// executed when the user selected something in the CAD object
|
||||
// adds/deletes the selection accordingly
|
||||
|
||||
if (selectionMode == none)
|
||||
return;
|
||||
|
||||
if (msg.Type == Gui::SelectionChanges::AddSelection) {
|
||||
if (referenceSelected(msg)) {
|
||||
if (selectionMode == refAdd) {
|
||||
ui->listWidgetReferences->addItem(QString::fromStdString(msg.pSubName));
|
||||
// it might be the second one so we can enable the context menu
|
||||
if (ui->listWidgetReferences->count() > 1) {
|
||||
deleteAction->setEnabled(true);
|
||||
deleteAction->setStatusTip(QString());
|
||||
ui->buttonRefRemove->setEnabled(true);
|
||||
ui->buttonRefRemove->setToolTip(tr("Click button to enter selection mode,\nclick again to end selection"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeItemFromListWidget(ui->listWidgetReferences, msg.pSubName);
|
||||
// remove its selection too
|
||||
Gui::Selection().clearSelection();
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
// we must also end the selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
}
|
||||
}
|
||||
// highlight existing references for possible further selections
|
||||
DressUpView->highlightReferences(true);
|
||||
if (selectionMode == refSel) {
|
||||
referenceSelected(msg, ui->listWidgetReferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskFilletParameters::onCheckBoxUseAllEdgesToggled(bool checked)
|
||||
{
|
||||
if (checked)
|
||||
setSelectionMode(none);
|
||||
PartDesign::Fillet* pcFillet = static_cast<PartDesign::Fillet*>(DressUpView->getObject());
|
||||
ui->buttonRefRemove->setEnabled(!checked);
|
||||
ui->buttonRefAdd->setEnabled(!checked);
|
||||
ui->buttonRefSel->setEnabled(!checked);
|
||||
ui->listWidgetReferences->setEnabled(!checked);
|
||||
pcFillet->UseAllEdges.setValue(checked);
|
||||
pcFillet->getDocument()->recomputeFeature(pcFillet);
|
||||
}
|
||||
|
||||
void TaskFilletParameters::clearButtons(const selectionModes notThis)
|
||||
void TaskFilletParameters::setButtons(const selectionModes mode)
|
||||
{
|
||||
if (notThis != refAdd) ui->buttonRefAdd->setChecked(false);
|
||||
if (notThis != refRemove) ui->buttonRefRemove->setChecked(false);
|
||||
DressUpView->highlightReferences(false);
|
||||
ui->buttonRefSel->setChecked(mode == refSel);
|
||||
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr : btnSelectStr);
|
||||
}
|
||||
|
||||
void TaskFilletParameters::onRefDeleted()
|
||||
{
|
||||
// assure we we are not in selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
// delete any selections since the reference(s) might be highlighted
|
||||
Gui::Selection().clearSelection();
|
||||
DressUpView->highlightReferences(false);
|
||||
|
||||
// get the list of items to be deleted
|
||||
QList<QListWidgetItem*> selectedList = ui->listWidgetReferences->selectedItems();
|
||||
|
||||
// if all items are selected, we must stop because one must be kept to avoid that the feature gets broken
|
||||
if (selectedList.count() == ui->listWidgetReferences->model()->rowCount()){
|
||||
QMessageBox::warning(this, tr("Selection error"), tr("At least one item must be kept."));
|
||||
return;
|
||||
}
|
||||
|
||||
// get the fillet object
|
||||
PartDesign::Fillet* pcFillet = static_cast<PartDesign::Fillet*>(DressUpView->getObject());
|
||||
App::DocumentObject* base = pcFillet->Base.getValue();
|
||||
// get all fillet references
|
||||
std::vector<std::string> refs = pcFillet->Base.getSubValues();
|
||||
setupTransaction();
|
||||
|
||||
// delete the selection backwards to assure the list index keeps valid for the deletion
|
||||
for (int i = selectedList.count()-1; i > -1; i--) {
|
||||
// the ref index is the same as the listWidgetReferences index
|
||||
// so we can erase using the row number of the element to be deleted
|
||||
int rowNumber = ui->listWidgetReferences->row(selectedList.at(i));
|
||||
// erase the reference
|
||||
refs.erase(refs.begin() + rowNumber);
|
||||
// remove from the list
|
||||
ui->listWidgetReferences->model()->removeRow(rowNumber);
|
||||
}
|
||||
|
||||
// update the object
|
||||
pcFillet->Base.setValue(base, refs);
|
||||
// recompute the feature
|
||||
pcFillet->recomputeFeature();
|
||||
// hide the fillet if there was a computation error
|
||||
hideOnError();
|
||||
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
}
|
||||
TaskDressUpParameters::deleteRef(ui->listWidgetReferences);
|
||||
}
|
||||
|
||||
void TaskFilletParameters::onAddAllEdges()
|
||||
{
|
||||
TaskDressUpParameters::addAllEdges(ui->listWidgetReferences);
|
||||
ui->buttonRefRemove->setEnabled(true);
|
||||
}
|
||||
|
||||
void TaskFilletParameters::onLengthChanged(double len)
|
||||
{
|
||||
clearButtons(none);
|
||||
setSelectionMode(none);
|
||||
PartDesign::Fillet* pcFillet = static_cast<PartDesign::Fillet*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcFillet->Radius.setValue(len);
|
||||
@@ -267,6 +188,10 @@ void TaskFilletParameters::apply()
|
||||
|
||||
//Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Fillet changed"));
|
||||
ui->filletRadius->apply();
|
||||
|
||||
//Alert user if he created an empty feature
|
||||
if(ui->listWidgetReferences->count() == 0)
|
||||
Base::Console().Warning(tr("Empty fillet created !\n").toStdString().c_str());
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
|
||||
@@ -49,7 +49,7 @@ private Q_SLOTS:
|
||||
|
||||
protected:
|
||||
double getLength() const;
|
||||
void clearButtons(const selectionModes notThis) override;
|
||||
void setButtons(const selectionModes mode) override;
|
||||
bool event(QEvent *e) override;
|
||||
void changeEvent(QEvent *e) override;
|
||||
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
|
||||
|
||||
@@ -15,36 +15,18 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefAdd">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
<widget class="QToolButton" name="buttonRefSel">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefRemove">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidgetReferences">
|
||||
|
||||
@@ -86,17 +86,15 @@ TaskThicknessParameters::TaskThicknessParameters(ViewProviderDressUp *DressUpVie
|
||||
this, &TaskThicknessParameters::onReversedChanged);
|
||||
connect(ui->checkIntersection, &QCheckBox::toggled,
|
||||
this, &TaskThicknessParameters::onIntersectionChanged);
|
||||
connect(ui->buttonRefAdd, &QToolButton::toggled,
|
||||
this, &TaskThicknessParameters::onButtonRefAdd);
|
||||
connect(ui->buttonRefRemove, &QToolButton::toggled,
|
||||
this, &TaskThicknessParameters::onButtonRefRemove);
|
||||
connect(ui->buttonRefSel, &QToolButton::toggled,
|
||||
this, &TaskThicknessParameters::onButtonRefSel);
|
||||
connect(ui->modeComboBox, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
this, &TaskThicknessParameters::onModeChanged);
|
||||
connect(ui->joinComboBox, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
this, &TaskThicknessParameters::onJoinTypeChanged);
|
||||
|
||||
// Create context menu
|
||||
createDeleteAction(ui->listWidgetReferences, ui->buttonRefRemove);
|
||||
createDeleteAction(ui->listWidgetReferences);
|
||||
connect(deleteAction, &QAction::triggered, this, &TaskThicknessParameters::onRefDeleted);
|
||||
|
||||
connect(ui->listWidgetReferences, &QListWidget::currentItemChanged,
|
||||
@@ -112,8 +110,10 @@ TaskThicknessParameters::TaskThicknessParameters(ViewProviderDressUp *DressUpVie
|
||||
int join = pcThickness->Join.getValue();
|
||||
ui->joinComboBox->setCurrentIndex(join);
|
||||
|
||||
// the dialog can be called on a broken thickness, then hide the thickness
|
||||
hideOnError();
|
||||
if (strings.size() == 0)
|
||||
setSelectionMode(refSel);
|
||||
else
|
||||
hideOnError();
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
@@ -121,104 +121,27 @@ void TaskThicknessParameters::onSelectionChanged(const Gui::SelectionChanges& ms
|
||||
// executed when the user selected something in the CAD object
|
||||
// adds/deletes the selection accordingly
|
||||
|
||||
if (selectionMode == none)
|
||||
return;
|
||||
|
||||
if (msg.Type == Gui::SelectionChanges::AddSelection) {
|
||||
if (referenceSelected(msg)) {
|
||||
if (selectionMode == refAdd) {
|
||||
ui->listWidgetReferences->addItem(QString::fromStdString(msg.pSubName));
|
||||
// it might be the second one so we can enable the context menu
|
||||
if (ui->listWidgetReferences->count() > 1) {
|
||||
deleteAction->setEnabled(true);
|
||||
deleteAction->setStatusTip(QString());
|
||||
ui->buttonRefRemove->setEnabled(true);
|
||||
ui->buttonRefRemove->setToolTip(tr("Click button to enter selection mode,\nclick again to end selection"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeItemFromListWidget(ui->listWidgetReferences, msg.pSubName);
|
||||
// remove its selection too
|
||||
Gui::Selection().clearSelection();
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
// we must also end the selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
}
|
||||
}
|
||||
// highlight existing references for possible further selections
|
||||
DressUpView->highlightReferences(true);
|
||||
if (selectionMode == refSel) {
|
||||
referenceSelected(msg, ui->listWidgetReferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::clearButtons(const selectionModes notThis)
|
||||
void TaskThicknessParameters::setButtons(const selectionModes mode)
|
||||
{
|
||||
if (notThis != refAdd) ui->buttonRefAdd->setChecked(false);
|
||||
if (notThis != refRemove) ui->buttonRefRemove->setChecked(false);
|
||||
DressUpView->highlightReferences(false);
|
||||
ui->buttonRefSel->setChecked(mode == refSel);
|
||||
ui->buttonRefSel->setText(mode == refSel ? btnPreviewStr : btnSelectStr);
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::onRefDeleted(void)
|
||||
{
|
||||
// assure we we are not in selection mode
|
||||
exitSelectionMode();
|
||||
clearButtons(none);
|
||||
// delete any selections since the reference(s) might be highlighted
|
||||
Gui::Selection().clearSelection();
|
||||
DressUpView->highlightReferences(false);
|
||||
|
||||
// get the list of items to be deleted
|
||||
QList<QListWidgetItem*> selectedList = ui->listWidgetReferences->selectedItems();
|
||||
|
||||
// if all items are selected, we must stop because one must be kept to avoid that the feature gets broken
|
||||
if (selectedList.count() == ui->listWidgetReferences->model()->rowCount()) {
|
||||
QMessageBox::warning(this, tr("Selection error"), tr("At least one item must be kept."));
|
||||
return;
|
||||
}
|
||||
|
||||
// get the thickness object
|
||||
PartDesign::Thickness* pcThickness = static_cast<PartDesign::Thickness*>(DressUpView->getObject());
|
||||
App::DocumentObject* base = pcThickness->Base.getValue();
|
||||
// get all thickness references
|
||||
std::vector<std::string> refs = pcThickness->Base.getSubValues();
|
||||
setupTransaction();
|
||||
|
||||
// delete the selection backwards to assure the list index keeps valid for the deletion
|
||||
for (int i = selectedList.count() - 1; i > -1; i--) {
|
||||
// the ref index is the same as the listWidgetReferences index
|
||||
// so we can erase using the row number of the element to be deleted
|
||||
int rowNumber = ui->listWidgetReferences->row(selectedList.at(i));
|
||||
// erase the reference
|
||||
refs.erase(refs.begin() + rowNumber);
|
||||
// remove from the list
|
||||
ui->listWidgetReferences->model()->removeRow(rowNumber);
|
||||
}
|
||||
|
||||
// update the object
|
||||
pcThickness->Base.setValue(base, refs);
|
||||
// recompute the feature
|
||||
pcThickness->recomputeFeature();
|
||||
// hide the thickness if there was a computation error
|
||||
hideOnError();
|
||||
|
||||
// if there is only one item left, it cannot be deleted
|
||||
if (ui->listWidgetReferences->count() == 1) {
|
||||
deleteAction->setEnabled(false);
|
||||
deleteAction->setStatusTip(tr("There must be at least one item"));
|
||||
ui->buttonRefRemove->setEnabled(false);
|
||||
ui->buttonRefRemove->setToolTip(tr("There must be at least one item"));
|
||||
}
|
||||
TaskDressUpParameters::deleteRef(ui->listWidgetReferences);
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::onValueChanged(double angle)
|
||||
{
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Thickness* pcThickness = static_cast<PartDesign::Thickness*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcThickness->Value.setValue(angle);
|
||||
@@ -229,7 +152,7 @@ void TaskThicknessParameters::onValueChanged(double angle)
|
||||
|
||||
void TaskThicknessParameters::onJoinTypeChanged(int join) {
|
||||
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Thickness* pcThickness = static_cast<PartDesign::Thickness*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcThickness->Join.setValue(join);
|
||||
@@ -240,7 +163,7 @@ void TaskThicknessParameters::onJoinTypeChanged(int join) {
|
||||
|
||||
void TaskThicknessParameters::onModeChanged(int mode) {
|
||||
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Thickness* pcThickness = static_cast<PartDesign::Thickness*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcThickness->Mode.setValue(mode);
|
||||
@@ -255,7 +178,7 @@ double TaskThicknessParameters::getValue(void) const
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::onReversedChanged(const bool on) {
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Thickness* pcThickness = static_cast<PartDesign::Thickness*>(DressUpView->getObject());
|
||||
setupTransaction();
|
||||
pcThickness->Reversed.setValue(on);
|
||||
@@ -270,7 +193,7 @@ bool TaskThicknessParameters::getReversed(void) const
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::onIntersectionChanged(const bool on) {
|
||||
clearButtons(none);
|
||||
setButtons(none);
|
||||
PartDesign::Thickness* pcThickness = static_cast<PartDesign::Thickness*>(DressUpView->getObject());
|
||||
pcThickness->Intersection.setValue(on);
|
||||
pcThickness->getDocument()->recomputeFeature(pcThickness);
|
||||
@@ -318,6 +241,12 @@ void TaskThicknessParameters::changeEvent(QEvent *e)
|
||||
}
|
||||
}
|
||||
|
||||
void TaskThicknessParameters::apply()
|
||||
{
|
||||
//Alert user if he created an empty feature
|
||||
if (ui->listWidgetReferences->count() == 0)
|
||||
Base::Console().Warning(tr("Empty thickness created !\n").toStdString().c_str());
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
@@ -360,6 +289,8 @@ bool TaskDlgThicknessParameters::accept()
|
||||
if (!obj->isError())
|
||||
parameter->showObject();
|
||||
|
||||
parameter->apply();
|
||||
|
||||
TaskThicknessParameters* draftparameter = static_cast<TaskThicknessParameters*>(parameter);
|
||||
|
||||
FCMD_OBJ_CMD(obj,"Value = " << draftparameter->getValue());
|
||||
|
||||
@@ -39,6 +39,8 @@ public:
|
||||
explicit TaskThicknessParameters(ViewProviderDressUp *DressUpView, QWidget *parent=nullptr);
|
||||
~TaskThicknessParameters() override;
|
||||
|
||||
void apply() override;
|
||||
|
||||
double getValue(void) const;
|
||||
bool getReversed(void) const;
|
||||
bool getIntersection(void) const;
|
||||
@@ -54,7 +56,7 @@ private Q_SLOTS:
|
||||
void onRefDeleted(void) override;
|
||||
|
||||
protected:
|
||||
void clearButtons(const selectionModes notThis) override;
|
||||
void setButtons(const selectionModes mode) override;
|
||||
bool event(QEvent *e) override;
|
||||
void changeEvent(QEvent *e) override;
|
||||
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
|
||||
|
||||
@@ -15,36 +15,18 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefAdd">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
<widget class="QToolButton" name="buttonRefSel">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add face</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonRefRemove">
|
||||
<property name="toolTip">
|
||||
<string>Click button to enter selection mode,
|
||||
click again to end selection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove face</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidgetReferences">
|
||||
|
||||
Reference in New Issue
Block a user