From 325b31aae3d69617d529605e2c231d40cc704c74 Mon Sep 17 00:00:00 2001 From: donovaly Date: Thu, 20 Feb 2020 01:09:33 +0100 Subject: [PATCH] FEM: change behavior of Force dialog to the one of all other constraint dialogs --- .../Fem/Gui/TaskFemConstraintDisplacement.cpp | 3 - .../Fem/Gui/TaskFemConstraintDisplacement.ui | 6 +- src/Mod/Fem/Gui/TaskFemConstraintForce.cpp | 205 ++++++++++-------- src/Mod/Fem/Gui/TaskFemConstraintForce.h | 8 +- src/Mod/Fem/Gui/TaskFemConstraintForce.ui | 65 +++++- 5 files changed, 184 insertions(+), 103 deletions(-) diff --git a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp index d70e510b6eb2..f8f41daeba89 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.cpp @@ -50,9 +50,6 @@ #include "ui_TaskFemConstraintDisplacement.h" #include #include - - - #include #include diff --git a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.ui b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.ui index 60f973f88766..ee83fbaf0bac 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.ui +++ b/src/Mod/Fem/Gui/TaskFemConstraintDisplacement.ui @@ -9,7 +9,7 @@ 0 0 - 400 + 330 800 @@ -21,7 +21,7 @@ - 400 + 330 800 @@ -37,7 +37,7 @@ - 40 + 10 0 311 743 diff --git a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp index de12d638caa1..8b4be0e92574 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintForce.cpp @@ -82,8 +82,6 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce *C connect(ui->spinForce, SIGNAL(valueChanged(double)), this, SLOT(onForceChanged(double))); - connect(ui->buttonReference, SIGNAL(pressed()), - this, SLOT(onButtonReference())); connect(ui->buttonDirection, SIGNAL(pressed()), this, SLOT(onButtonDirection())); connect(ui->checkReverse, SIGNAL(toggled(bool)), @@ -94,7 +92,6 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce *C // Temporarily prevent unnecessary feature recomputes ui->spinForce->blockSignals(true); ui->listReferences->blockSignals(true); - ui->buttonReference->blockSignals(true); ui->buttonDirection->blockSignals(true); ui->checkReverse->blockSignals(true); @@ -123,10 +120,13 @@ TaskFemConstraintForce::TaskFemConstraintForce(ViewProviderFemConstraintForce *C ui->spinForce->blockSignals(false); ui->listReferences->blockSignals(false); - ui->buttonReference->blockSignals(false); ui->buttonDirection->blockSignals(false); ui->checkReverse->blockSignals(false); + //Selection buttons + connect(ui->btnAdd, SIGNAL(clicked()), this, SLOT(addToSelection())); + connect(ui->btnRemove, SIGNAL(clicked()), this, SLOT(removeFromSelection())); + updateUI(); } @@ -137,105 +137,141 @@ void TaskFemConstraintForce::updateUI() onButtonReference(true); return; } - - std::string ref = ui->listReferences->item(0)->text().toStdString(); - int pos = ref.find_last_of(":"); - if (ref.substr(pos+1, 6) == "Vertex") - ui->labelForce->setText(tr("Point load")); - else if (ref.substr(pos+1, 4) == "Edge") - ui->labelForce->setText(tr("Line load")); - else if (ref.substr(pos+1, 4) == "Face") - ui->labelForce->setText(tr("Area load")); } -void TaskFemConstraintForce::onSelectionChanged(const Gui::SelectionChanges& msg) +void TaskFemConstraintForce::addToSelection() { - if (msg.Type == Gui::SelectionChanges::AddSelection) { - // Don't allow selection in other document - if (strcmp(msg.pDocName, ConstraintView->getObject()->getDocument()->getName()) != 0) - return; + std::vector selection = Gui::Selection().getSelectionEx(); //gets vector of selected objects of active document + if (selection.size() == 0) { + QMessageBox::warning(this, tr("Selection error"), tr("Nothing selected!")); + return; + } - if (!msg.pSubName || msg.pSubName[0] == '\0') - return; - std::string subName(msg.pSubName); + Fem::ConstraintForce* pcConstraint = static_cast(ConstraintView->getObject()); + std::vector Objects = pcConstraint->References.getValues(); + std::vector SubElements = pcConstraint->References.getSubValues(); - if (selectionMode == selnone) + for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) {//for every selected object + if (static_cast(it->getTypeName()).substr(0, 4).compare(std::string("Part")) != 0) { + QMessageBox::warning(this, tr("Selection error"), tr("Selected object is not a part!")); return; + } - std::vector references(1,subName); - Fem::ConstraintForce* pcConstraint = static_cast(ConstraintView->getObject()); - App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(msg.pObjectName); - Part::Feature* feat = static_cast(obj); - TopoDS_Shape ref = feat->Shape.getShape().getSubShape(subName.c_str()); - - if (selectionMode == selref) { - std::vector Objects = pcConstraint->References.getValues(); - std::vector SubElements = pcConstraint->References.getSubValues(); - - // Ensure we don't have mixed reference types - if (SubElements.size() > 0) { - if (subName.substr(0,4) != SubElements.front().substr(0,4)) { - QMessageBox::warning(this, tr("Selection error"), tr("Mixed shape types are not possible. Use a second constraint instead")); - return; - } - } - else { - if ((subName.substr(0,4) != "Face") && (subName.substr(0,4) != "Edge") && (subName.substr(0,6) != "Vertex")) { - QMessageBox::warning(this, tr("Selection error"), tr("Only faces, edges and vertices can be picked")); - return; + std::vector subNames = it->getSubNames(); + App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(it->getFeatName()); + for (unsigned int subIt = 0; subIt < (subNames.size()); ++subIt) {// for every selected sub element + bool addMe = true; + for (std::vector::iterator itr = std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); + itr != SubElements.end(); + itr = std::find(++itr, SubElements.end(), subNames[subIt])) + {// for every sub element in selection that matches one in old list + if (obj == Objects[std::distance(SubElements.begin(), itr)]) {//if selected sub element's object equals the one in old list then it was added before so don't add + addMe = false; } } - - // Avoid duplicates - std::size_t pos = 0; - for (; pos < Objects.size(); pos++) { - if (obj == Objects[pos]) { + // limit constraint such that only vertexes or faces or edges can be used depending on what was selected first + std::string searchStr(""); + if (subNames[subIt].find("Vertex") != std::string::npos) + searchStr = "Vertex"; + else if (subNames[subIt].find("Edge") != std::string::npos) + searchStr = "Edge"; + else + searchStr = "Face"; + for (unsigned int iStr = 0; iStr < (SubElements.size()); ++iStr) { + if ((SubElements[iStr].find(searchStr) == std::string::npos) && (SubElements.size() > 0)) { + QString msg = tr("Only one type of selection (vertex,face or edge) per constraint allowed!"); + QMessageBox::warning(this, tr("Selection error"), msg); + addMe = false; break; } } - - if (pos != Objects.size()) { - if (subName == SubElements[pos]) { - return; - } + if (addMe) { + disconnect(ui->listReferences, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, SLOT(setSelection(QListWidgetItem*))); + Objects.push_back(obj); + SubElements.push_back(subNames[subIt]); + ui->listReferences->addItem(makeRefText(obj, subNames[subIt])); + connect(ui->listReferences, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, SLOT(setSelection(QListWidgetItem*))); } + } + } + //Update UI + pcConstraint->References.setValues(Objects, SubElements); + updateUI(); +} - // add the new reference - Objects.push_back(obj); - SubElements.push_back(subName); - pcConstraint->References.setValues(Objects,SubElements); - ui->listReferences->addItem(makeRefText(obj, subName)); +void TaskFemConstraintForce::removeFromSelection() +{ + std::vector selection = Gui::Selection().getSelectionEx(); //gets vector of selected objects of active document + if (selection.size() == 0) { + QMessageBox::warning(this, tr("Selection error"), tr("Nothing selected!")); + return; + } - // Turn off reference selection mode - onButtonReference(false); + Fem::ConstraintForce* pcConstraint = static_cast(ConstraintView->getObject()); + std::vector Objects = pcConstraint->References.getValues(); + std::vector SubElements = pcConstraint->References.getSubValues(); + std::vector itemsToDel; + for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) {//for every selected object + if (static_cast(it->getTypeName()).substr(0, 4).compare(std::string("Part")) != 0) { + QMessageBox::warning(this, tr("Selection error"), tr("Selected object is not a part!")); + return; } - else if (selectionMode == seldir) { - if (subName.substr(0,4) == "Face") { - if (!Fem::Tools::isPlanar(TopoDS::Face(ref))) { - QMessageBox::warning(this, tr("Selection error"), tr("Only planar faces can be picked")); - return; - } - } - else if (subName.substr(0,4) == "Edge") { - if (!Fem::Tools::isLinear(TopoDS::Edge(ref))) { - QMessageBox::warning(this, tr("Selection error"), tr("Only linear edges can be picked")); - return; + + std::vector subNames = it->getSubNames(); + App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(it->getFeatName()); + + for (unsigned int subIt = 0; subIt < (subNames.size()); ++subIt) {// for every selected sub element + for (std::vector::iterator itr = std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); + itr != SubElements.end(); + itr = std::find(++itr, SubElements.end(), subNames[subIt])) + {// for every sub element in selection that matches one in old list + if (obj == Objects[std::distance(SubElements.begin(), itr)]) {//if selected sub element's object equals the one in old list then it was added before so mark for deletion + itemsToDel.push_back(std::distance(SubElements.begin(), itr)); } } - else { - QMessageBox::warning(this, tr("Selection error"), tr("Only faces and edges can be picked")); - return; - } - pcConstraint->Direction.setValue(obj, references); - ui->lineDirection->setText(makeRefText(obj, subName)); - - // Turn off direction selection mode - onButtonDirection(false); } + } + + std::sort(itemsToDel.begin(), itemsToDel.end()); + while (itemsToDel.size() > 0) { + Objects.erase(Objects.begin() + itemsToDel.back()); + SubElements.erase(SubElements.begin() + itemsToDel.back()); + itemsToDel.pop_back(); + } + + //Update UI + disconnect(ui->listReferences, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, SLOT(setSelection(QListWidgetItem*))); - Gui::Selection().clearSelection(); - updateUI(); + ui->listReferences->clear(); + for (unsigned int j = 0; j < Objects.size(); j++) { + ui->listReferences->addItem(makeRefText(Objects[j], SubElements[j])); } + connect(ui->listReferences, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, SLOT(setSelection(QListWidgetItem*))); + + pcConstraint->References.setValues(Objects, SubElements); + updateUI(); +} + +void TaskFemConstraintForce::setSelection(QListWidgetItem* item) { + std::string s = item->text().toStdString(); + std::string docName = ConstraintView->getObject()->getDocument()->getName(); + + std::string delimiter = ":"; + + size_t pos = 0; + std::string objName; + std::string subName; + pos = s.find(delimiter); + objName = s.substr(0, pos); + s.erase(0, pos + delimiter.length()); + subName = s; + + Gui::Selection().clearSelection(); + Gui::Selection().addSelection(docName.c_str(), objName.c_str(), subName.c_str(), 0, 0, 0); } void TaskFemConstraintForce::onForceChanged(double f) @@ -245,10 +281,7 @@ void TaskFemConstraintForce::onForceChanged(double f) } void TaskFemConstraintForce::onReferenceDeleted() { - int row = ui->listReferences->currentIndex().row(); - TaskFemConstraint::onReferenceDeleted(row); - ui->listReferences->model()->removeRow(row); - ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); + TaskFemConstraintForce::removeFromSelection(); //OvG: On right-click face is automatically selected, so just remove } void TaskFemConstraintForce::onButtonDirection(const bool pressed) { diff --git a/src/Mod/Fem/Gui/TaskFemConstraintForce.h b/src/Mod/Fem/Gui/TaskFemConstraintForce.h index 42ac2fd52fcb..d255b0dd9194 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintForce.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintForce.h @@ -33,6 +33,7 @@ #include "ViewProviderFemConstraintForce.h" #include +#include class Ui_TaskFemConstraintForce; @@ -53,9 +54,8 @@ class TaskFemConstraintForce : public TaskFemConstraint public: TaskFemConstraintForce(ViewProviderFemConstraintForce *ConstraintView,QWidget *parent = 0); virtual ~TaskFemConstraintForce(); - double getForce(void) const; - virtual const std::string getReferences() const; + const std::string getReferences() const; const std::string getDirectionName(void) const; const std::string getDirectionObject(void) const; bool getReverse(void) const; @@ -65,13 +65,15 @@ private Q_SLOTS: void onForceChanged(double); void onButtonDirection(const bool pressed = true); void onCheckReverse(bool); + void addToSelection(); + void removeFromSelection(); + void setSelection(QListWidgetItem* item); protected: bool event(QEvent *e); virtual void changeEvent(QEvent *e); private: - virtual void onSelectionChanged(const Gui::SelectionChanges& msg); void updateUI(); private: diff --git a/src/Mod/Fem/Gui/TaskFemConstraintForce.ui b/src/Mod/Fem/Gui/TaskFemConstraintForce.ui index 006f5f4b4930..fd2146f0092a 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintForce.ui +++ b/src/Mod/Fem/Gui/TaskFemConstraintForce.ui @@ -6,23 +6,72 @@ 0 0 - 257 - 233 + 330 + 350 + + + 3 + 35 + + + + + 330 + 350 + + + + + 400 + 800 + + - Form + Prescribed Force - + - Add reference + Select multiple face(s), click Add or Remove - + + + + + Add + + + + + + + Remove + + + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + @@ -34,8 +83,8 @@ - - + + 500.000000000000000