From 6f07011b6c40404ca1d37361516163f33064bebe Mon Sep 17 00:00:00 2001 From: nds Date: Wed, 13 Jan 2016 08:36:42 +0300 Subject: [PATCH] Improve multi-selector control to provide "Delete" key processing. Shortcut can not be used for it because there is a conflict in Qt which one should be performed. So, OperationMgr processes it from property panel and application on the whole(qApp->installEventFilter(this)). --- src/ModuleBase/ModuleBase_ModelWidget.cpp | 5 ++ src/ModuleBase/ModuleBase_ModelWidget.h | 5 +- .../ModuleBase_WidgetMultiSelector.cpp | 60 +++++++++++-------- .../ModuleBase_WidgetMultiSelector.h | 5 +- src/PartSet/PartSet_OperationPrs.cpp | 4 +- src/XGUI/XGUI_ContextMenuMgr.cpp | 1 - src/XGUI/XGUI_Displayer.cpp | 8 +-- src/XGUI/XGUI_OperationMgr.cpp | 57 ++++++++++++++---- src/XGUI/XGUI_OperationMgr.h | 9 ++- 9 files changed, 107 insertions(+), 47 deletions(-) diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index 86fe765da..939505967 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -279,6 +279,11 @@ bool ModuleBase_ModelWidget::processEnter() return false; } +bool ModuleBase_ModelWidget::processDelete() +{ + return false; +} + bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent) { QWidget* aWidget = qobject_cast(theObject); diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index 9f7c99980..79e4b1e17 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -183,9 +183,12 @@ Q_OBJECT /// \return Current Editing mode bool isEditingMode() const { return myIsEditing; } - /// Returns true if the event is processed. + /// Returns true if the event is processed. The default implementation is empty, returns false. virtual bool processEnter(); + /// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processDelete(); + /// Sends Update and Redisplay for the given object /// \param theObj is updating object static void updateObject(ObjectPtr theObj); diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp index 714e4ef7f..6fa8eae78 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -148,7 +148,6 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen myListControl->addAction(myCopyAction); myDeleteAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this); - myDeleteAction->setShortcut(QKeySequence::Delete); myDeleteAction->setEnabled(false); connect(myDeleteAction, SIGNAL(triggered(bool)), SLOT(onDeleteItem())); myListControl->addAction(myDeleteAction); @@ -329,6 +328,40 @@ bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_Vie return aValid; } +//******************************************************************** +bool ModuleBase_WidgetMultiSelector::processDelete() +{ + // find attribute indices to delete + std::set anAttributeIds; + getSelectedAttributeIndices(anAttributeIds); + + // refill attribute by the items which indices are not in the list of ids + bool aDone = false; + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); + if (aSelectionListAttr.get()) { + aDone = !anAttributeIds.empty(); + aSelectionListAttr->remove(anAttributeIds); + } + else { + AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); + if (aRefListAttr.get()) { + aDone = !anAttributeIds.empty(); + aRefListAttr->remove(anAttributeIds); + } + } + if (aDone) { + // update object is necessary to flush update signal. It leads to objects references map update + // and the operation presentation will not contain deleted items visualized as parameters of + // the feature. + updateObject(myFeature); + + restoreValue(); + myWorkshop->setSelected(getAttributeSelection()); + myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeAllObjects, true); + } + return true; // if the delete should be processed outsize, the method should return isDone +} + //******************************************************************** QList ModuleBase_WidgetMultiSelector::getControls() const { @@ -475,30 +508,7 @@ void ModuleBase_WidgetMultiSelector::onCopyItem() //******************************************************************** void ModuleBase_WidgetMultiSelector::onDeleteItem() { - // find attribute indices to delete - std::set anAttributeIds; - getSelectedAttributeIndices(anAttributeIds); - - // refill attribute by the items which indices are not in the list of ids - bool aDone = false; - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - aDone = !anAttributeIds.empty(); - aSelectionListAttr->remove(anAttributeIds); - } - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); - if (aRefListAttr.get()) { - aDone = !anAttributeIds.empty(); - aRefListAttr->remove(anAttributeIds); - } - } - if (aDone) { - restoreValue(); - myWorkshop->setSelected(getAttributeSelection()); - - myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeAllObjects, true); - } + processDelete(); } //******************************************************************** diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.h b/src/ModuleBase/ModuleBase_WidgetMultiSelector.h index bebc59c91..591d842ad 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.h @@ -81,7 +81,10 @@ class MODULEBASE_EXPORT ModuleBase_WidgetMultiSelector : public ModuleBase_Widge /// \return a boolean value virtual bool isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs); - public slots: + /// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processDelete(); + +public slots: /// Slot is called on selection type changed void onSelectionTypeChanged(); diff --git a/src/PartSet/PartSet_OperationPrs.cpp b/src/PartSet/PartSet_OperationPrs.cpp index 9b41b2eff..cbf29b38b 100755 --- a/src/PartSet/PartSet_OperationPrs.cpp +++ b/src/PartSet/PartSet_OperationPrs.cpp @@ -13,6 +13,8 @@ #include "ModuleBase_Tools.h" #include "ModuleBase_IModule.h" +#include +#include #include #include @@ -79,8 +81,6 @@ bool PartSet_OperationPrs::hasShapes() return !myFeatureShapes.empty() || !myFeatureResults.empty(); } -#include -#include void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager, const Handle(Prs3d_Presentation)& thePresentation, const Standard_Integer theMode) diff --git a/src/XGUI/XGUI_ContextMenuMgr.cpp b/src/XGUI/XGUI_ContextMenuMgr.cpp index 940901ce4..ea453bb49 100644 --- a/src/XGUI/XGUI_ContextMenuMgr.cpp +++ b/src/XGUI/XGUI_ContextMenuMgr.cpp @@ -62,7 +62,6 @@ void XGUI_ContextMenuMgr::createActions() aDesktop->addAction(aAction); addAction("DELETE_CMD", aAction); - aAction->setShortcut(Qt::Key_Delete); aAction->setShortcutContext(Qt::ApplicationShortcut); aAction = new QAction(QIcon(":pictures/rename_edit.png"), tr("Rename"), this); diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 2c24b774a..29b8b997b 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -501,8 +501,8 @@ void XGUI_Displayer::setSelected(const QList& theValues, if (aContext.IsNull()) return; if (aContext->HasOpenedContext()) { - aContext->UnhilightSelected(); - aContext->ClearSelected(); + aContext->UnhilightSelected(false); + aContext->ClearSelected(false); foreach (ModuleBase_ViewerPrs aPrs, theValues) { const TopoDS_Shape& aShape = aPrs.shape(); if (!aShape.IsNull()) { @@ -525,8 +525,8 @@ void XGUI_Displayer::setSelected(const QList& theValues, } } } else { - aContext->UnhilightCurrents(); - aContext->ClearCurrents(); + aContext->UnhilightCurrents(false); + aContext->ClearCurrents(false); foreach (ModuleBase_ViewerPrs aPrs, theValues) { ObjectPtr anObject = aPrs.object(); ResultPtr aResult = std::dynamic_pointer_cast(anObject); diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index 15f90b947..dff53bd91 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -35,6 +35,10 @@ XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent, ModuleBase_IWorkshop* theWorkshop) : QObject(theParent), myWorkshop(theWorkshop) { + /// we need to install filter to the application in order to react to 'Delete' key button + /// this key can not be a short cut for a corresponded action because we need to set + /// the actions priority + qApp->installEventFilter(this); } XGUI_OperationMgr::~XGUI_OperationMgr() @@ -108,13 +112,17 @@ ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent) { + bool isAccepted = false; if (theEvent->type() == QEvent::KeyRelease) { QKeyEvent* aKeyEvent = dynamic_cast(theEvent); if(aKeyEvent) { - return onKeyReleased(aKeyEvent); + isAccepted = onKeyReleased(aKeyEvent); } } - return QObject::eventFilter(theObject, theEvent); + if (!isAccepted) + isAccepted = QObject::eventFilter(theObject, theEvent); + + return isAccepted; } bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) @@ -499,11 +507,9 @@ void XGUI_OperationMgr::onOperationStopped() bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) { - QObject* aSender = sender(); - // Let the manager decide what to do with the given key combination. ModuleBase_Operation* anOperation = currentOperation(); - bool isAccepted = true; + bool isAccepted = false; switch (theEvent->key()) { case Qt::Key_Return: case Qt::Key_Enter: { @@ -525,7 +531,10 @@ bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) } } } - + case Qt::Key_Delete: { + isAccepted = onProcessDelete(); + } + break; break; default: isAccepted = false; @@ -539,26 +548,32 @@ bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent) bool XGUI_OperationMgr::onProcessEnter() { - bool isAccepted = true; + bool isAccepted = false; ModuleBase_Operation* aOperation = currentOperation(); ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); - ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); + ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget(); bool isAborted = false; - if (!aActiveWgt) { + if (!anActiveWgt) { QWidget* aFocusWidget = aPanel->focusWidget(); QToolButton* aCancelBtn = aPanel->findChild(PROP_PANEL_CANCEL); if (aFocusWidget && aCancelBtn && aFocusWidget == aCancelBtn) { abortOperation(aOperation); + isAccepted = true; isAborted = true; } } if (!isAborted) { - if (!aActiveWgt || !aActiveWgt->processEnter()) { - if (!myWorkshop->module()->processEnter(aActiveWgt ? aActiveWgt->attributeID() : "")) { + isAccepted = anActiveWgt && anActiveWgt->processEnter(); + if (!isAccepted) { + isAccepted = myWorkshop->module()->processEnter(anActiveWgt ? anActiveWgt->attributeID() : ""); + if (!isAccepted) { + /// functionality is similar to Apply click ModuleBase_OperationFeature* aFOperation = dynamic_cast(currentOperation()); if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) { + // key released is emitted to apply the current value to the model if it was modified in PP emit keyEnterReleased(); commitOperation(); + isAccepted = true; } else isAccepted = false; @@ -568,6 +583,26 @@ bool XGUI_OperationMgr::onProcessEnter() return isAccepted; } +bool XGUI_OperationMgr::onProcessDelete() +{ + bool isAccepted = false; + ModuleBase_Operation* aOperation = currentOperation(); + ModuleBase_ModelWidget* anActiveWgt = 0; + if (aOperation) { + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + if (aPanel) + anActiveWgt = aPanel->activeWidget(); + } + if (anActiveWgt) + isAccepted = anActiveWgt->processDelete(); + if (!isAccepted) { + workshop()->deleteObjects(); + isAccepted = true; + } + + return isAccepted; +} + XGUI_Workshop* XGUI_OperationMgr::workshop() const { XGUI_ModuleConnector* aConnector = dynamic_cast(myWorkshop); diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index e7e715128..b87501c4b 100755 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -162,12 +162,17 @@ protected: // TEMPORARY /// \param theEvent the mouse event bool onKeyReleased(QKeyEvent* theEvent); + protected slots: /// The functionaly, that should be done by enter click - /// Fistly the active widget processes it, then module. If no one do not + /// Fistly the active widget processes it, then module. If no one does not /// process it, the current operation is committed bool onProcessEnter(); - protected slots: + /// The functionaly, that should be done by delete click + /// Fistly the active widget processes it, then workshop. If no one does not + /// process it, do nothing + bool onProcessDelete(); + /// Slot that is called by an operation stop. Removes the stopped operation form the stack. /// If there is a suspended operation, restart it. void onOperationStopped(); -- 2.39.2