Download src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 17.5 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp
-
curl -L -o TaskDressUpParameters.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp
17.5 kB
| /*************************************************************************** | |
| * Copyright (c) 2012 Jan Rheinländer * | |
| * <jrheinlaender@users.sourceforge.net> * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This library is free software; you can redistribute it and/or * | |
| * modify it under the terms of the GNU Library General Public * | |
| * License as published by the Free Software Foundation; either * | |
| * version 2 of the License, or (at your option) any later version. * | |
| * * | |
| * This library is distributed in the hope that it will be useful, * | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| * GNU Library General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Library General Public * | |
| * License along with this library; see the file COPYING.LIB. If not, * | |
| * write to the Free Software Foundation, Inc., 59 Temple Place, * | |
| * Suite 330, Boston, MA 02111-1307, USA * | |
| * * | |
| ***************************************************************************/ | |
| FC_LOG_LEVEL_INIT("PartDesign", true, true) | |
| using namespace PartDesignGui; | |
| using namespace Gui; | |
| /* TRANSLATOR PartDesignGui::TaskDressUpParameters */ | |
| TaskDressUpParameters::TaskDressUpParameters( | |
| ViewProviderDressUp* DressUpView, | |
| bool selectEdges, | |
| bool selectFaces, | |
| QWidget* parent | |
| ) | |
| : TaskFeatureParameters(DressUpView, parent, DressUpView->featureIcon(), DressUpView->menuName) | |
| , proxy(nullptr) | |
| , deleteAction(nullptr) | |
| , addAllEdgesAction(nullptr) | |
| , allowFaces(selectFaces) | |
| , allowEdges(selectEdges) | |
| , DressUpView(DressUpView) | |
| { | |
| // remember initial transaction ID | |
| App::GetApplication().getActiveTransaction(&transactionID); | |
| selectionMode = none; | |
| } | |
| TaskDressUpParameters::~TaskDressUpParameters() | |
| { | |
| // make sure to remove selection gate in all cases | |
| Gui::Selection().rmvSelectionGate(); | |
| } | |
| void TaskDressUpParameters::setupTransaction() | |
| { | |
| if (DressUpView.expired()) { | |
| return; | |
| } | |
| int tid = 0; | |
| App::GetApplication().getActiveTransaction(&tid); | |
| if (tid && tid == transactionID) { | |
| return; | |
| } | |
| // open a transaction if none is active | |
| std::string n("Edit "); | |
| n += DressUpView->getObject()->Label.getValue(); | |
| transactionID = App::GetApplication().setActiveTransaction(n.c_str()); | |
| } | |
| void TaskDressUpParameters::referenceSelected(const Gui::SelectionChanges& msg, QListWidget* widget) | |
| { | |
| if (strcmp(msg.pDocName, DressUpView->getObject()->getDocument()->getName()) != 0) { | |
| return; | |
| } | |
| Gui::Selection().clearSelection(); | |
| PartDesign::DressUp* pcDressUp = DressUpView->getObject<PartDesign::DressUp>(); | |
| 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; | |
| } | |
| const std::string subName(msg.pSubName); | |
| std::vector<std::string> refs = pcDressUp->Base.getSubValues(); | |
| if (const auto f = std::ranges::find(refs, subName); f != refs.end()) { | |
| refs.erase(f); // it's in the list. Remove it | |
| removeItemFromListWidget(widget, msg.pSubName); | |
| } | |
| else { | |
| refs.push_back(subName); // not yet in the list so we add it | |
| widget->addItem(QString::fromStdString(msg.pSubName)); | |
| } | |
| updateFeature(pcDressUp, refs); | |
| } | |
| void TaskDressUpParameters::addAllEdges(QListWidget* widget) | |
| { | |
| Q_UNUSED(widget) | |
| if (DressUpView.expired()) { | |
| return; | |
| } | |
| PartDesign::DressUp* pcDressUp = DressUpView->getObject<PartDesign::DressUp>(); | |
| App::DocumentObject* base = pcDressUp->Base.getValue(); | |
| if (!base) { | |
| return; | |
| } | |
| int count = Part::Feature::getTopoShape( | |
| base, | |
| Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform | |
| ) | |
| .countSubShapes(TopAbs_EDGE); | |
| auto subValues = pcDressUp->Base.getSubValues(false); | |
| std::size_t len = subValues.size(); | |
| for (int i = 0; i < count; ++i) { | |
| std::string name = "Edge" + std::to_string(i + 1); | |
| if (std::find(subValues.begin(), subValues.begin() + len, name) == subValues.begin() + len) { | |
| subValues.push_back(name); | |
| } | |
| } | |
| if (subValues.size() == len) { | |
| return; | |
| } | |
| try { | |
| setupTransaction(); | |
| pcDressUp->Base.setValue(base, subValues); | |
| } | |
| catch (Base::Exception& e) { | |
| e.reportException(); | |
| } | |
| } | |
| void TaskDressUpParameters::deleteRef(QListWidget* widget) | |
| { | |
| // 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 = DressUpView->getObject<PartDesign::DressUp>(); | |
| 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::updateFeature( | |
| PartDesign::DressUp* pcDressUp, | |
| const std::vector<std::string>& refs | |
| ) | |
| { | |
| 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) | |
| { | |
| // executed when the user double-clicks on any item in the list | |
| // shows the fillets as they are -> useful to switch out of selection mode | |
| Q_UNUSED(item) | |
| wasDoubleClicked = true; | |
| // assure we are not in selection mode | |
| setSelectionMode(none); | |
| // enable next possible single-click event after double-click time passed | |
| QTimer::singleShot( | |
| QApplication::doubleClickInterval(), | |
| this, | |
| &TaskDressUpParameters::itemClickedTimeout | |
| ); | |
| } | |
| void TaskDressUpParameters::setSelection(QListWidgetItem* current) | |
| { | |
| // executed when the user selected an item in the list (but double-clicked it) | |
| // highlights the currently selected item | |
| if (current == nullptr) { | |
| setSelectionMode(none); | |
| return; | |
| } | |
| if (!wasDoubleClicked) { | |
| // we treat it as single-click event once the QApplication double-click time is passed | |
| QTimer::singleShot( | |
| QApplication::doubleClickInterval(), | |
| this, | |
| &TaskDressUpParameters::itemClickedTimeout | |
| ); | |
| // name of the item | |
| std::string subName = current->text().toStdString(); | |
| // get the document name | |
| std::string docName = DressUpView->getObject()->getDocument()->getName(); | |
| // get the name of the body we are in | |
| Part::BodyBase* body = PartDesign::Body::findBodyOf(DressUpView->getObject()); | |
| if (body) { | |
| std::string objName = body->getNameInDocument(); | |
| // Enter selection mode | |
| if (selectionMode == none) { | |
| setSelectionMode(refSel); | |
| } | |
| else { | |
| Gui::Selection().clearSelection(); | |
| } | |
| // highlight the selected item | |
| bool block = this->blockSelection(true); | |
| tryAddSelection(docName, objName, subName); | |
| this->blockSelection(block); | |
| } | |
| } | |
| } | |
| void TaskDressUpParameters::tryAddSelection( | |
| const std::string& doc, | |
| const std::string& obj, | |
| const std::string& sub | |
| ) | |
| { | |
| try { | |
| Gui::Selection().addSelection(doc.c_str(), obj.c_str(), sub.c_str(), 0, 0, 0); | |
| } | |
| catch (const Base::Exception& e) { | |
| e.reportException(); | |
| } | |
| catch (const Standard_Failure& e) { | |
| Base::Console().error("OCC error: %s\n", e.GetMessageString()); | |
| } | |
| } | |
| QString TaskDressUpParameters::startSelectionLabel() | |
| { | |
| return tr("Select"); | |
| } | |
| QString TaskDressUpParameters::stopSelectionLabel() | |
| { | |
| return tr("Confirm Selection"); | |
| } | |
| void TaskDressUpParameters::itemClickedTimeout() | |
| { | |
| // executed after double-click time passed | |
| wasDoubleClicked = false; | |
| } | |
| void TaskDressUpParameters::createAddAllEdgesAction(QListWidget* parentList) | |
| { | |
| // creates a context menu, a shortcut for it and connects it to a slot function | |
| addAllEdgesAction = new QAction(tr("Add All Edges"), this); | |
| addAllEdgesAction->setShortcut(QKeySequence(QStringLiteral("Ctrl+Shift+A"))); | |
| // display shortcut behind the context menu entry | |
| addAllEdgesAction->setShortcutVisibleInContextMenu(true); | |
| parentList->addAction(addAllEdgesAction); | |
| addAllEdgesAction->setStatusTip( | |
| tr("Adds all edges to the list box (only when in add selection mode)") | |
| ); | |
| parentList->setContextMenuPolicy(Qt::ActionsContextMenu); | |
| } | |
| void TaskDressUpParameters::createDeleteAction(QListWidget* parentList) | |
| { | |
| // creates a context menu, a shortcut for it and connects it to a slot function | |
| deleteAction = new QAction(tr("Remove"), this); | |
| deleteAction->setShortcut(Gui::QtTools::deleteKeySequence()); | |
| // display shortcut behind the context menu entry | |
| deleteAction->setShortcutVisibleInContextMenu(true); | |
| parentList->addAction(deleteAction); | |
| parentList->setContextMenuPolicy(Qt::ActionsContextMenu); | |
| } | |
| bool TaskDressUpParameters::event(QEvent* event) | |
| { | |
| if (event->type() == QEvent::ShortcutOverride) { | |
| QKeyEvent* kevent = static_cast<QKeyEvent*>(event); // NOLINT | |
| if (deleteAction && Gui::QtTools::matches(kevent, deleteAction->shortcut())) { | |
| kevent->accept(); | |
| return true; | |
| } | |
| if (addAllEdgesAction && Gui::QtTools::matches(kevent, addAllEdgesAction->shortcut())) { | |
| kevent->accept(); | |
| return true; | |
| } | |
| } | |
| return TaskBox::event(event); | |
| } | |
| void TaskDressUpParameters::keyPressEvent(QKeyEvent* ke) | |
| { | |
| if (deleteAction && deleteAction->isEnabled() | |
| && Gui::QtTools::matches(ke, deleteAction->shortcut())) { | |
| deleteAction->trigger(); | |
| return; | |
| } | |
| if (addAllEdgesAction && addAllEdgesAction->isEnabled() | |
| && Gui::QtTools::matches(ke, addAllEdgesAction->shortcut())) { | |
| addAllEdgesAction->trigger(); | |
| return; | |
| } | |
| TaskBox::keyPressEvent(ke); | |
| } | |
| const std::vector<std::string> TaskDressUpParameters::getReferences() const | |
| { | |
| PartDesign::DressUp* pcDressUp = DressUpView->getObject<PartDesign::DressUp>(); | |
| std::vector<std::string> result = pcDressUp->Base.getSubValues(); | |
| return result; | |
| } | |
| // TODO: This code is identical with TaskTransformedParameters::removeItemFromListWidget() | |
| void TaskDressUpParameters::removeItemFromListWidget(QListWidget* widget, const char* itemstr) | |
| { | |
| QList<QListWidgetItem*> items = widget->findItems(QString::fromLatin1(itemstr), Qt::MatchExactly); | |
| if (!items.empty()) { | |
| for (auto item : items) { | |
| QListWidgetItem* it = widget->takeItem(widget->row(item)); | |
| delete it; | |
| } | |
| } | |
| } | |
| void TaskDressUpParameters::hideOnError() | |
| { | |
| App::DocumentObject* dressup = DressUpView->getObject(); | |
| DressUpView->setErrorState(dressup->isError()); | |
| } | |
| ViewProviderDressUp* TaskDressUpParameters::getDressUpView() const | |
| { | |
| return DressUpView.expired() ? nullptr : DressUpView.get(); | |
| } | |
| Part::Feature* TaskDressUpParameters::getBase() const | |
| { | |
| if (ViewProviderDressUp* vp = getDressUpView()) { | |
| auto dressUp = vp->getObject<PartDesign::DressUp>(); | |
| // Unlikely but this may throw an exception in case we are started to edit an object which | |
| // base feature was deleted. This exception will be likely unhandled inside the dialog and | |
| // pass upper. But an error message inside the report view is better than a SEGFAULT. | |
| // Generally this situation should be prevented in ViewProviderDressUp::setEdit() | |
| return dressUp->getBaseObject(); | |
| } | |
| return nullptr; | |
| } | |
| void TaskDressUpParameters::setSelectionMode(selectionModes mode) | |
| { | |
| if (DressUpView.expired()) { | |
| return; | |
| } | |
| selectionMode = mode; | |
| setButtons(mode); | |
| if (mode == none) { | |
| Gui::Selection().rmvSelectionGate(); | |
| // remove any highlights and selections | |
| DressUpView->highlightReferences(false); | |
| if (previouslyShownViewProvider != nullptr) { | |
| // restore the previously shown view provider | |
| previouslyShownViewProvider->show(); | |
| previouslyShownViewProvider = nullptr; | |
| } | |
| } | |
| else { | |
| AllowSelectionFlags allow; | |
| allow.setFlag(AllowSelection::EDGE, allowEdges); | |
| allow.setFlag(AllowSelection::FACE, allowFaces); | |
| Gui::Selection().addSelectionGate(new ReferenceSelection(this->getBase(), allow)); | |
| DressUpView->highlightReferences(true); | |
| // selection must come from the previous feature, we also need to remember the currently | |
| // shown so we can restore it later | |
| previouslyShownViewProvider = DressUpView->getBodyViewProvider()->getShownViewProvider(); | |
| DressUpView->showPreviousFeature(true); | |
| } | |
| Gui::Selection().clearSelection(); | |
| } | |
| //************************************************************************** | |
| //************************************************************************** | |
| // TaskDialog | |
| //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
| TaskDlgDressUpParameters::TaskDlgDressUpParameters(ViewProviderDressUp* DressUpView) | |
| : TaskDlgFeatureParameters(DressUpView) | |
| , parameter(nullptr) | |
| { | |
| assert(DressUpView); | |
| auto pcDressUp = DressUpView->getObject<PartDesign::DressUp>(); | |
| auto base = pcDressUp->Base.getValue(); | |
| std::vector<std::string> newSubList; | |
| bool changed = false; | |
| auto& shadowSubs = pcDressUp->Base.getShadowSubs(); | |
| for (auto& shadowSub : shadowSubs) { | |
| auto displayName = shadowSub.oldName; | |
| // If there is a missing tag on the shadow sub, take a guess at a new name. | |
| if (boost::starts_with(shadowSub.oldName, Data::MISSING_PREFIX)) { | |
| Part::Feature::guessNewLink(displayName, base, shadowSub.newName.c_str()); | |
| newSubList.emplace_back(displayName); | |
| changed = true; | |
| } | |
| } | |
| if (changed) { | |
| pcDressUp->Base.setValue(base, newSubList); | |
| } | |
| } | |
| TaskDlgDressUpParameters::~TaskDlgDressUpParameters() = default; | |
| //==== calls from the TaskView =============================================================== | |
| bool TaskDlgDressUpParameters::accept() | |
| { | |
| getViewObject<ViewProviderDressUp>()->highlightReferences(false); | |
| std::vector<std::string> refs = parameter->getReferences(); | |
| std::stringstream str; | |
| str << Gui::Command::getObjectCmd(getObject()) << ".Base = (" | |
| << Gui::Command::getObjectCmd(parameter->getBase()) << ",["; | |
| for (const auto& ref : refs) { | |
| str << "\"" << ref << "\","; | |
| } | |
| str << "])"; | |
| Gui::Command::runCommand(Gui::Command::Doc, str.str().c_str()); | |
| return TaskDlgFeatureParameters::accept(); | |
| } | |
| bool TaskDlgDressUpParameters::reject() | |
| { | |
| getViewObject<ViewProviderDressUp>()->highlightReferences(false); | |
| return TaskDlgFeatureParameters::reject(); | |
| } | |