From 46a28bd54e9ce0937d87d305202ab6912c1f5cd2 Mon Sep 17 00:00:00 2001 From: nds Date: Mon, 19 Jan 2015 07:56:07 +0300 Subject: [PATCH] Issue #355 Delete: elements of sketch and constraints --- src/Model/Model_Document.cpp | 26 +++- src/ModuleBase/ModuleBase_IModule.h | 12 ++ src/PartSet/PartSet_Module.cpp | 180 +++++++++++++++++++++++++--- src/PartSet/PartSet_Module.h | 32 +++++ src/XGUI/XGUI_ContextMenuMgr.cpp | 27 ++--- src/XGUI/XGUI_ContextMenuMgr.h | 2 +- src/XGUI/XGUI_Workshop.cpp | 17 ++- src/XGUI/XGUI_Workshop.h | 11 +- 8 files changed, 264 insertions(+), 43 deletions(-) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 67339fdf3..d99056747 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -579,17 +579,35 @@ void Model_Document::refsToFeature(FeaturePtr theFeature, const bool isSendError) { // check the feature: it must have no depended objects on it + // the dependencies can be in the feature results std::list::const_iterator aResIter = theFeature->results().cbegin(); for(; aResIter != theFeature->results().cend(); aResIter++) { ResultPtr aResult = (*aResIter); std::shared_ptr aData = std::dynamic_pointer_cast(aResult->data()); - if (aData && !aData->refsToMe().empty()) { - FeaturePtr aFeature = ModelAPI_Feature::feature(aResult); - if (aFeature.get() != NULL) - theRefs.insert(aFeature); + if (aData.get() != NULL) { + const std::set& aRefs = aData->refsToMe(); + std::set::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end(); + for(; aRefIt != aRefLast; aRefIt++) { + FeaturePtr aFeature = std::dynamic_pointer_cast((*aRefIt)->owner()); + if (aFeature.get() != NULL) + theRefs.insert(aFeature); + } + + if (!aRefs.empty()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aResult); + if (aFeature.get() != NULL) + theRefs.insert(aFeature); + } } } + // the dependencies can be in the feature itself + std::shared_ptr aData = + std::dynamic_pointer_cast(theFeature->data()); + if (aData && !aData->refsToMe().empty()) { + theRefs.insert(theFeature); + } + if (!theRefs.empty() && isSendError) { Events_Error::send( "Feature '" + theFeature->data()->name() + "' is used and can not be deleted"); diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index 9420d1e74..88fa049d4 100644 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -17,6 +17,7 @@ class QAction; class QMouseEvent; class QKeyEvent; +class QMenu; class Config_WidgetAPI; class ModuleBase_ModelWidget; class ModuleBase_Operation; @@ -68,6 +69,17 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject /// Realizes some functionality by an operation abort virtual void operationAborted(ModuleBase_Operation* theOperation) {} + /// Add menu atems for viewer into the given menu + /// \param theMenu a popup menu to be shown in the viewer + virtual void addViewerItems(QMenu* theMenu) const {} + + /// Add menu atems for object browser into the given menu + /// \param theMenu a popup menu to be shown in the object browser + virtual void addObjectBrowserItems(QMenu* theMenu) const {}; + + /// Called when it is necessary to update a command state (enable or disable it) + //virtual bool isFeatureEnabled(const QString& theCmdId) const = 0; + /// Creates custom widgets for property panel /// \param theType a type of widget /// \param theParent the parent object diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index b05715c38..df5d23f1e 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -63,6 +63,8 @@ #include #include #include +#include +#include #include #include @@ -95,6 +97,8 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop) ModuleBase_IViewer* aViewer = theWshop->viewer(); connect(aViewer, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)), this, SLOT(onKeyRelease(ModuleBase_IViewWindow*, QKeyEvent*))); + + createActions(); } PartSet_Module::~PartSet_Module() @@ -206,6 +210,25 @@ bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const aCanDisplay = ModuleBase_IModule::canDisplayObject(theObject); } return aCanDisplay; + +void PartSet_Module::addViewerItems(QMenu* theMenu) const +{ + if (isSketchOperationActive()) { + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + QObjectPtrList aObjects = aSelection->selectedPresentations(); + if (aObjects.size() > 0) { + bool hasFeature = false; + foreach(ObjectPtr aObject, aObjects) + { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); + if (aFeature.get() != NULL) { + hasFeature = true; + } + } + if (hasFeature) + theMenu->addAction(action("DELETE_PARTSET_CMD")); + } + } } void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation) @@ -308,30 +331,20 @@ void PartSet_Module::onEnterReleased() void PartSet_Module::onOperationActivatedByPreselection() { ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); - if (!aOperation) - return; - - // Set final definitions if they are necessary - //propertyPanelDefined(aOperation); + if(aOperation && isSketchOperationActive()) { + // Set final definitions if they are necessary + //propertyPanelDefined(aOperation); - /// Commit sketcher operations automatically - FeaturePtr aFeature = aOperation->feature(); - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aFeature); - if (aSPFeature) { + /// Commit sketcher operations automatically aOperation->commit(); } } void PartSet_Module::onNoMoreWidgets() { - ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); - if (aOperation) { - /// Restart sketcher operations automatically - FeaturePtr aFeature = aOperation->feature(); - std::shared_ptr aSPFeature = - std::dynamic_pointer_cast(aFeature); - if (aSPFeature) { + if (isSketchOperationActive()) { + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + if (aOperation) { if (myRestartingMode != RM_Forbided) myRestartingMode = RM_LastFeatureUsed; aOperation->commit(); @@ -404,3 +417,136 @@ QWidget* PartSet_Module::createWidgetByType(const std::string& theType, QWidget* return 0; } +bool PartSet_Module::isSketchOperationActive() const +{ + bool isCurrentSketchOp = false; + ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); + if (aOperation) { + FeaturePtr aFeature = aOperation->feature(); + std::shared_ptr aSPFeature = + std::dynamic_pointer_cast(aFeature); + isCurrentSketchOp = aSPFeature.get() != NULL; + } + return isCurrentSketchOp; +} + +void PartSet_Module::createActions() +{ + QAction* aAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this); + addAction("DELETE_PARTSET_CMD", aAction); +} + +QAction* PartSet_Module::action(const QString& theId) const +{ + if (myActions.contains(theId)) + return myActions[theId]; + return 0; +} + +void PartSet_Module::addAction(const QString& theId, QAction* theAction) +{ + if (myActions.contains(theId)) + qCritical("A command with Id = '%s' already defined!", qPrintable(theId)); + theAction->setData(theId); + connect(theAction, SIGNAL(triggered(bool)), this, SLOT(onAction(bool))); + myActions[theId] = theAction; +} + +void PartSet_Module::onAction(bool isChecked) +{ + QAction* aAction = static_cast(sender()); + QString anId = aAction->data().toString(); + + if (anId == "DELETE_PARTSET_CMD") { + deleteObjects(); + } +} + +void PartSet_Module::deleteObjects() +{ + if (!isSketchOperationActive()) + return; + + XGUI_ModuleConnector* aConnector = dynamic_cast(workshop()); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + + XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr(); + if(anOpMgr->canAbortOperation()) { + ModuleBase_Operation* aCurrentOp = anOpMgr->currentOperation(); + if (aCurrentOp) { + bool isSketchOp = aCurrentOp->id().toStdString() == SketchPlugin_Sketch::ID(); + if (!isSketchOp) + aCurrentOp->abort(); + } + } + + ModuleBase_ISelection* aSel = aConnector->selection(); + QObjectPtrList aSelectedObj = aSel->selectedPresentations(); + + std::set aRefFeatures; + foreach (ObjectPtr aObj, aSelectedObj) + { + //ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); + //if (aPart) { + // TODO: check for what there is this condition. It is placed here historicaly because + // ther is this condition during remove features. + //} else { + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + if (aFeature.get() != NULL) { + aObj->document()->refsToFeature(aFeature, aRefFeatures, false); + } + //} + } + + if (!aRefFeatures.empty()) { + QStringList aRefNames; + std::set::const_iterator anIt = aRefFeatures.begin(), + aLast = aRefFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = (*anIt); + std::string aFName = aFeature->data()->name().c_str(); + std::string aName = (*anIt)->name().c_str(); + aRefNames.append((*anIt)->name().c_str()); + } + QString aNames = aRefNames.join(", "); + + QMainWindow* aDesktop = aWorkshop->desktop(); + QMessageBox::StandardButton aRes = QMessageBox::warning( + aDesktop, tr("Delete features"), + QString(tr("Selected features are used in the following features: %1.\ +These features will be deleted also. Would you like to continue?")).arg(aNames), + QMessageBox::No | QMessageBox::Yes, QMessageBox::No); + if (aRes != QMessageBox::Yes) + return; + } + + SessionPtr aMgr = ModelAPI_Session::get(); + aMgr->startOperation(); + std::set::const_iterator anIt = aRefFeatures.begin(), + aLast = aRefFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aRefFeature = (*anIt); + DocumentPtr aDoc = aRefFeature->document(); + aDoc->removeFeature(aRefFeature); + } + + foreach (ObjectPtr aObj, aSelectedObj) + { + DocumentPtr aDoc = aObj->document(); + //ResultPartPtr aPart = std::dynamic_pointer_cast(aObj); + //if (aPart) { + // if (aDoc == aMgr->activeDocument()) { + // aDoc->close(); + // } + //} else { + //FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); + FeaturePtr aFeature = ModelAPI_Feature::feature(aObj); + if (aFeature.get() != NULL) { + aDoc->removeFeature(aFeature); + } + //} + } + aWorkshop->displayer()->updateViewer(); + //myDisplayer->updateViewer(); + aMgr->finishOperation(); +} diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index 326866c9f..f58c4738b 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -26,6 +27,8 @@ class ModuleBase_Operation; class ModuleBase_IViewWindow; +class QAction; + /** * \ingroup Modules * Implementation of Partset module @@ -82,12 +85,19 @@ public: /// if it is a sketch operation /// \param theObject a model object virtual bool canDisplayObject(const ObjectPtr& theObject) const; + /// Add menu atems for viewer into the given menu + /// \param theMenu a popup menu to be shown in the viewer + virtual void addViewerItems(QMenu* theMenu) const; public slots: /// SLOT, that is called by no more widget signal emitted by property panel /// Set a specific flag to restart the sketcher operation void onNoMoreWidgets(); + /// Processes the context menu action click + /// \param isChecked a state of toggle if the action is checkable + void onAction(bool isChecked); + protected slots: /// Called when previous operation is finished virtual void onSelectionChanged(); @@ -121,6 +131,26 @@ protected slots: /// Breaks sequense of automatically resterted operations void breakOperationSequence(); + /// Check whether there is active opeation and it is the sketch one + /// \return boolean result + bool isSketchOperationActive() const; + + /// Create all actions for context menus. It is called on creation of module + /// Put the created actions into an internal map + void createActions(); + + /// Returns action according to the given ID + /// \param theId an action identifier, it should be uniqued in the bounds of the module + QAction* action(const QString& theId) const; + + /// Add action to the internal map + /// \param theId - string ID of the item + /// \param theAction - action to add + void addAction(const QString& theId, QAction* theAction); + + //! Delete features + void deleteObjects(); + private: QString myLastOperationId; FeaturePtr myLastFeature; @@ -132,6 +162,8 @@ protected slots: Handle(PartSet_GlobalFilter) myDocumentShapeFilter; PartSet_SketcherMgr* mySketchMgr; + + QMap myActions; // the popup menu actions }; #endif diff --git a/src/XGUI/XGUI_ContextMenuMgr.cpp b/src/XGUI/XGUI_ContextMenuMgr.cpp index 8a794d781..b4fa78dab 100644 --- a/src/XGUI/XGUI_ContextMenuMgr.cpp +++ b/src/XGUI/XGUI_ContextMenuMgr.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include #include #include @@ -181,6 +183,11 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const } aMenu->addSeparator(); aMenu->addActions(myWorkshop->objectBrowser()->actions()); + + ModuleBase_IModule* aModule = myWorkshop->module(); + if (aModule) + aModule->addObjectBrowserItems(aMenu); + if (aMenu->actions().size() > 0) { return aMenu; } @@ -244,23 +251,9 @@ void XGUI_ContextMenuMgr::addViewerItems(QMenu* theMenu) const } } - aObjects.clear(); - aObjects = aSelMgr->selection()->selectedPresentations(); - if (aObjects.size() > 0) { - bool hasFeature = true;//false; - foreach(ObjectPtr aObject, aObjects) - { - ResultPtr aRes = std::dynamic_pointer_cast(aObject); - if (aRes) { - hasFeature = true; - } - //FeaturePtr aFeature = std::dynamic_pointer_cast(aObject); - //if (aFeature) - // hasFeature = true; - } - if (hasFeature) - theMenu->addAction(action("DELETE_CMD")); - } + ModuleBase_IModule* aModule = myWorkshop->module(); + if (aModule) + aModule->addViewerItems(theMenu); } void XGUI_ContextMenuMgr::connectObjectBrowser() const diff --git a/src/XGUI/XGUI_ContextMenuMgr.h b/src/XGUI/XGUI_ContextMenuMgr.h index bb620cd73..7fc3d6bfa 100644 --- a/src/XGUI/XGUI_ContextMenuMgr.h +++ b/src/XGUI/XGUI_ContextMenuMgr.h @@ -46,7 +46,7 @@ Q_OBJECT void connectViewer() const; /// Add menu atems for viewer into the given menu (used in SALOME mode) - /// \param theMenu a menu instance + /// \param a popup menu to be shown in the viewer void addViewerItems(QMenu* theMenu) const; signals: diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 4eae59578..2ed8c86f5 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -444,6 +444,11 @@ void XGUI_Workshop::processEvent(const std::shared_ptr& theMessa } } +//****************************************************** +QMainWindow* XGUI_Workshop::desktop() const +{ + return isSalomeMode() ? salomeConnector()->desktop() : myMainWindow; +} //****************************************************** void XGUI_Workshop::onStartWaiting() @@ -1269,7 +1274,7 @@ void XGUI_Workshop::deleteObjects(const QObjectPtrList& theList) // ther is this condition during remove features. } else { FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); - if (aFeature) { + if (aFeature.get() != NULL) { aObj->document()->refsToFeature(aFeature, aRefFeatures, false); } } @@ -1298,6 +1303,15 @@ These features will be deleted also. Would you like to continue?")).arg(aNames), SessionPtr aMgr = ModelAPI_Session::get(); aMgr->startOperation(); + std::set::const_iterator anIt = aRefFeatures.begin(), + aLast = aRefFeatures.end(); + for (; anIt != aLast; anIt++) { + FeaturePtr aRefFeature = (*anIt); + DocumentPtr aDoc = aRefFeature->document(); + aDoc->removeFeature(aRefFeature); + } + + foreach (ObjectPtr aObj, theList) { DocumentPtr aDoc = aObj->document(); @@ -1313,6 +1327,7 @@ These features will be deleted also. Would you like to continue?")).arg(aNames), } } } + myDisplayer->updateViewer(); aMgr->finishOperation(); } diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index 34ce06b91..80aa6d2f8 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -41,6 +41,7 @@ class Config_PointerMessage; class QWidget; class QDockWidget; +class QMainWindow; class ModelAPI_ObjectUpdatedMessage; class ModelAPI_ObjectDeletedMessage; @@ -149,6 +150,10 @@ Q_OBJECT return myModuleConnector; } + /// Returns a desktop + /// \return a desktop instance + QMainWindow* desktop() const; + //! Returns icon name according to feature static QIcon featureIcon(const FeaturePtr& theFeature); @@ -333,9 +338,9 @@ signals: /// \param theOpertion an aborted operation void onOperationAborted(ModuleBase_Operation* theOperation); - /// Process context menu command - /// \param theId id of the command - /// \param isChecked is checked flag + /// Slot, which reacts to the context popup menu call + /// \param theId the data value of the clicked action + /// \param isChecked a state of toggle if the action is checkable void onContextMenuCommand(const QString& theId, bool isChecked); /// Processing of values changed in model widget -- 2.39.2