From d81b016b2a1513d1d6c47a0158e2f4e1a4290d10 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 12 Jun 2022 14:03:42 +0200 Subject: [PATCH] PD: several fixes of shape binder: * add action to context-menu to remove an element * use an exclusive button group to avoid to have several buttons pressed at the same time * allow to completely clear the support * when pressing OK/Cancel then operate on the document the shape binder is part of (which isn't necessarily the active document) * remove obsolete parameter from ViewProviderShapeBinder::highlightReferences() --- src/Mod/PartDesign/Gui/TaskShapeBinder.cpp | 260 +++++++++++------- src/Mod/PartDesign/Gui/TaskShapeBinder.h | 12 +- .../Gui/ViewProviderShapeBinder.cpp | 2 +- .../PartDesign/Gui/ViewProviderShapeBinder.h | 3 +- 4 files changed, 171 insertions(+), 106 deletions(-) diff --git a/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp b/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp index 33698cb059..644d9a8e38 100644 --- a/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp +++ b/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp @@ -24,15 +24,17 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include #endif #include #include #include -#include +#include #include #include +#include #include #include @@ -49,35 +51,39 @@ using namespace Gui; //************************************************************************** //************************************************************************** -// Task Parameter +// TaskShapeBinder //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// TODO Review and cleanup the file (2015-09-11, Fat-Zer) - -TaskShapeBinder::TaskShapeBinder(ViewProviderShapeBinder* view, bool /*newObj*/, QWidget* parent) +TaskShapeBinder::TaskShapeBinder(ViewProviderShapeBinder* view, bool newObj, QWidget* parent) : Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("PartDesign_ShapeBinder"), tr("Datum shape parameters"), true, parent) , SelectionObserver(view) , ui(new Ui_TaskShapeBinder) , vp(view) { + std::ignore = newObj; + // we need a separate container widget to add all controls to proxy = new QWidget(this); ui->setupUi(proxy); QMetaObject::connectSlotsByName(this); - connect(ui->buttonRefAdd, SIGNAL(toggled(bool)), - this, SLOT(onButtonRefAdd(bool))); - connect(ui->buttonRefRemove, SIGNAL(toggled(bool)), - this, SLOT(onButtonRefRemove(bool))); - connect(ui->buttonBase, SIGNAL(toggled(bool)), - this, SLOT(onBaseButton(bool))); - + setupButtonGroup(); + setupContextMenu(); this->groupLayout()->addWidget(proxy); - Gui::Document* doc = Gui::Application::Instance->activeDocument(); + updateUI(); +} - //add initial values +TaskShapeBinder::~TaskShapeBinder() +{ +} + +void TaskShapeBinder::updateUI() +{ + Gui::Document* doc = vp->getDocument(); + + //add initial values App::GeoFeature* obj = nullptr; std::vector subs; @@ -85,14 +91,16 @@ TaskShapeBinder::TaskShapeBinder(ViewProviderShapeBinder* view, bool /*newObj*/, if (obj) { ui->baseEdit->setText(QString::fromStdString(obj->Label.getStrValue())); - ui->baseEdit->setReadOnly(true); } + // Allow to clear the Support + ui->baseEdit->setClearButtonEnabled(true); + connect(ui->baseEdit, &QLineEdit::textChanged, + this, &TaskShapeBinder::supportChanged); + for (auto sub : subs) ui->listWidgetReferences->addItem(QString::fromStdString(sub)); - //make sure the user sees all important things: the base feature to select edges and the - //spine/auxiliary spine they already selected if (obj) { auto* svp = doc->getViewProvider(obj); if (svp) { @@ -100,13 +108,124 @@ TaskShapeBinder::TaskShapeBinder(ViewProviderShapeBinder* view, bool /*newObj*/, svp->setVisible(true); } } - - updateUI(); } -void TaskShapeBinder::updateUI() +void TaskShapeBinder::setupButtonGroup() { + buttonGroup = new ButtonGroup(this); + buttonGroup->setExclusive(true); + buttonGroup->addButton(ui->buttonRefAdd, + TaskShapeBinder::refAdd); + buttonGroup->addButton(ui->buttonRefRemove, + TaskShapeBinder::refRemove); + buttonGroup->addButton(ui->buttonBase, + TaskShapeBinder::refObjAdd); + connect(buttonGroup, qOverload(&QButtonGroup::buttonToggled), + this, &TaskShapeBinder::onButtonToggled); +} + +void TaskShapeBinder::setupContextMenu() +{ + // Create context menu + QAction* remove = new QAction(tr("Remove"), this); + remove->setShortcut(QKeySequence::Delete); + remove->setShortcutContext(Qt::WidgetShortcut); +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + // display shortcut behind the context menu entry + remove->setShortcutVisibleInContextMenu(true); +#endif + ui->listWidgetReferences->addAction(remove); + connect(remove, &QAction::triggered, this, &TaskShapeBinder::deleteItem); + ui->listWidgetReferences->setContextMenuPolicy(Qt::ActionsContextMenu); +} + +void TaskShapeBinder::supportChanged(const QString& text) +{ + if (!vp.expired() && text.isEmpty()) { + PartDesign::ShapeBinder* binder = static_cast(vp->getObject()); + binder->Support.setValue(nullptr, nullptr); + vp->highlightReferences(false); + vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); + ui->listWidgetReferences->clear(); + } +} + +void TaskShapeBinder::onButtonToggled(QAbstractButton *button, bool checked) +{ + int id = buttonGroup->id(button); + + if (checked) { + Gui::Selection().clearSelection(); + selectionMode = static_cast(id); + } + else { + Gui::Selection().clearSelection(); + if (selectionMode == static_cast(id)) + selectionMode = TaskShapeBinder::none; + } + + switch (id) { + case TaskShapeBinder::refAdd: + case TaskShapeBinder::refRemove: + if (!vp.expired()) + vp->highlightReferences(true); + break; + case TaskShapeBinder::refObjAdd: + break; + default: + break; + } +} + +void TaskShapeBinder::changeEvent(QEvent*) +{ +} + +void TaskShapeBinder::deleteItem() +{ + if (vp.expired()) + return; + + // Delete the selected spine + int row = ui->listWidgetReferences->currentRow(); + QListWidgetItem* item = ui->listWidgetReferences->takeItem(row); + if (item) { + QByteArray data = item->text().toLatin1(); + delete item; + + // search inside the list of sub-elements + App::GeoFeature* obj = nullptr; + std::vector subs; + + PartDesign::ShapeBinder* binder = static_cast(vp->getObject()); + PartDesign::ShapeBinder::getFilteredReferences(&binder->Support, obj, subs); + + std::string subname = data.constData(); + std::vector::iterator it = std::find(subs.begin(), subs.end(), subname); + + // if something was found, delete it and update the support + if (it != subs.end()) { + subs.erase(it); + binder->Support.setValue(obj, subs); + + vp->highlightReferences(false); + vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); + + clearButtons(); + } + } +} + +void TaskShapeBinder::removeFromListWidget(QListWidget* widget, QString itemstr) +{ + QList items = widget->findItems(itemstr, Qt::MatchExactly); + if (!items.empty()) { + for (QList::const_iterator i = items.begin(); i != items.end(); i++) { + QListWidgetItem* it = widget->takeItem(widget->row(*i)); + delete it; + } + } } void TaskShapeBinder::onSelectionChanged(const Gui::SelectionChanges& msg) @@ -124,19 +243,16 @@ void TaskShapeBinder::onSelectionChanged(const Gui::SelectionChanges& msg) if (msg.Type == Gui::SelectionChanges::AddSelection) { if (referenceSelected(msg)) { if (selectionMode == refAdd) { - QString sub = QString::fromStdString(msg.pSubName); + QString sub = QString::fromUtf8(msg.pSubName); if (!sub.isEmpty()) - ui->listWidgetReferences->addItem(QString::fromStdString(msg.pSubName)); + ui->listWidgetReferences->addItem(sub); setObjectLabel(msg); } else if (selectionMode == refRemove) { - QString sub = QString::fromStdString(msg.pSubName); + QString sub = QString::fromUtf8(msg.pSubName); if (!sub.isEmpty()) - removeFromListWidget(ui->listWidgetReferences, QString::fromUtf8(msg.pSubName)); - else { - ui->baseEdit->clear(); - } + removeFromListWidget(ui->listWidgetReferences, sub); } else if (selectionMode == refObjAdd) { ui->listWidgetReferences->clear(); @@ -146,77 +262,23 @@ void TaskShapeBinder::onSelectionChanged(const Gui::SelectionChanges& msg) clearButtons(); if (!vp.expired()) { - vp->highlightReferences(false, false); + vp->highlightReferences(false); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } } + clearButtons(); exitSelectionMode(); } } -TaskShapeBinder::~TaskShapeBinder() -{ -} - -void TaskShapeBinder::changeEvent(QEvent*) -{ -} - -void TaskShapeBinder::onButtonRefAdd(bool checked) { - - if (checked) { - //clearButtons(refAdd); - //hideObject(); - Gui::Selection().clearSelection(); - selectionMode = refAdd; - vp->highlightReferences(true, false); - } -} - -void TaskShapeBinder::onButtonRefRemove(bool checked) { - - if (checked) { - //clearButtons(refRemove); - //hideObject(); - Gui::Selection().clearSelection(); - selectionMode = refRemove; - - if (!vp.expired()) - vp->highlightReferences(true, false); - } -} - -void TaskShapeBinder::onBaseButton(bool checked) { - - if (checked) { - //clearButtons(refRemove); - //hideObject(); - Gui::Selection().clearSelection(); - selectionMode = refObjAdd; - //DressUpView->highlightReferences(true); - } -} - -void TaskShapeBinder::removeFromListWidget(QListWidget* widget, QString itemstr) { - - QList items = widget->findItems(itemstr, Qt::MatchExactly); - if (!items.empty()) { - for (QList::const_iterator i = items.begin(); i != items.end(); i++) { - QListWidgetItem* it = widget->takeItem(widget->row(*i)); - delete it; - } - } -} - bool TaskShapeBinder::referenceSelected(const SelectionChanges& msg) const { if (vp.expired()) return false; if ((msg.Type == Gui::SelectionChanges::AddSelection) && ( - (selectionMode == refAdd) || (selectionMode == refRemove) - || (selectionMode == refObjAdd))) { + (selectionMode == refAdd) || (selectionMode == refRemove) || (selectionMode == refObjAdd))) { if (strcmp(msg.pDocName, vp->getObject()->getDocument()->getName()) != 0) return false; @@ -315,7 +377,7 @@ void TaskShapeBinder::accept() //************************************************************************** //************************************************************************** -// TaskDialog +// TaskDlgShapeBinder //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgShapeBinder::TaskDlgShapeBinder(ViewProviderShapeBinder* view, bool newObj) @@ -333,19 +395,18 @@ TaskDlgShapeBinder::~TaskDlgShapeBinder() } -//==== calls from the TaskView =============================================================== - - bool TaskDlgShapeBinder::accept() { try { - parameter->accept(); + if (!vp.expired()) { + parameter->accept(); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); - if (!vp->getObject()->isValid()) - throw Base::RuntimeError(vp->getObject()->getStatusString()); - Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); - Gui::Command::commitCommand(); + Gui::cmdAppDocument(vp->getObject(), "recompute()"); + if (!vp->getObject()->isValid()) + throw Base::RuntimeError(vp->getObject()->getStatusString()); + Gui::cmdGuiDocument(vp->getObject(), "resetEdit()"); + Gui::Command::commitCommand(); + } } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromUtf8(e.what())); @@ -357,10 +418,13 @@ bool TaskDlgShapeBinder::accept() bool TaskDlgShapeBinder::reject() { - // roll back the done things - Gui::Command::abortCommand(); - Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + if (!vp.expired()) { + App::Document* doc = vp->getObject()->getDocument(); + // roll back the done things (deletes 'vp') + Gui::Command::abortCommand(); + Gui::cmdGuiDocument(doc, "resetEdit()"); + Gui::cmdAppDocument(doc, "recompute()"); + } return true; } diff --git a/src/Mod/PartDesign/Gui/TaskShapeBinder.h b/src/Mod/PartDesign/Gui/TaskShapeBinder.h index 9683bc17de..3590e59a91 100644 --- a/src/Mod/PartDesign/Gui/TaskShapeBinder.h +++ b/src/Mod/PartDesign/Gui/TaskShapeBinder.h @@ -38,6 +38,7 @@ class Property; } namespace Gui { +class ButtonGroup; class ViewProvider; } @@ -55,11 +56,6 @@ public: void accept(); -private Q_SLOTS: - void onButtonRefAdd(bool checked); - void onButtonRefRemove(bool checked); - void onBaseButton(bool checked); - protected: enum selectionModes { none, refAdd, refRemove, refObjAdd }; void changeEvent(QEvent *e); @@ -69,9 +65,14 @@ protected: bool referenceSelected(const Gui::SelectionChanges& msg) const; private: + void setupButtonGroup(); + void setupContextMenu(); void onSelectionChanged(const Gui::SelectionChanges& msg); + void onButtonToggled(QAbstractButton *button, bool checked); void updateUI(); + void supportChanged(const QString&); void clearButtons(); + void deleteItem(); void exitSelectionMode(); bool supportShow = false; @@ -79,6 +80,7 @@ private: private: QWidget* proxy; std::unique_ptr ui; + Gui::ButtonGroup *buttonGroup; Gui::WeakPtrT vp; }; diff --git a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp index c6c9dcfd2d..fefdab856e 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp @@ -128,7 +128,7 @@ void ViewProviderShapeBinder::unsetEdit(int ModNum) { PartGui::ViewProviderPart::unsetEdit(ModNum); } -void ViewProviderShapeBinder::highlightReferences(const bool on, bool /*auxiliary*/) +void ViewProviderShapeBinder::highlightReferences(bool on) { App::GeoFeature* obj = nullptr; std::vector subs; diff --git a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h index abb17ddf83..6af3f70e8b 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h +++ b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h @@ -29,7 +29,6 @@ namespace PartDesignGui { -// TODO may be derive from something else e.g. ViewProviderGeometryObject (2015-09-11, Fat-Zer) class PartDesignGuiExport ViewProviderShapeBinder : public PartGui::ViewProviderPart { PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderShapeBinder); @@ -40,7 +39,7 @@ public: virtual ~ViewProviderShapeBinder(); void setupContextMenu(QMenu*, QObject*, const char*) override; - void highlightReferences(const bool on, bool auxiliary); + void highlightReferences(bool on); protected: virtual bool setEdit(int ModNum) override;