X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FXGUI%2FXGUI_OperationMgr.cpp;h=beb73a742bf21ec7a7b4e0378f233924c1ee4c78;hb=50a8df0c6a66da8067b16155e5ae39f8f26a7ebc;hp=9f29412ebda7f1d0e7ff34134d0bc996d9c72d05;hpb=ef735191febeda718b07736db7abdd728a81c17b;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index 9f29412eb..beb73a742 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -1,15 +1,34 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: XGUI_OperationMgr.cpp -// Created: 20 Apr 2014 -// Author: Natalia ERMOLAEVA +// Copyright (C) 2014-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "XGUI_OperationMgr.h" + +#include "XGUI_ActiveControlMgr.h" +#include "XGUI_ActiveControlSelector.h" +#include "XGUI_FacesPanelSelector.h" #include "XGUI_ModuleConnector.h" #include "XGUI_Workshop.h" #include "XGUI_ErrorMgr.h" +#include "XGUI_FacesPanel.h" #include "XGUI_Tools.h" #include "XGUI_ObjectsBrowser.h" +#include "XGUI_ContextMenuMgr.h" #include #include @@ -21,15 +40,19 @@ #include "ModuleBase_OperationFeature.h" #include "ModuleBase_Tools.h" -#include "ModelAPI_CompositeFeature.h" -#include "ModelAPI_Session.h" +#include + +#include +#include #include #include +#include #include #include #include +#include //#define DEBUG_CURRENT_FEATURE @@ -43,7 +66,7 @@ public: /// \param theParent the parent to be deleted when the parent is deleted /// \param theOperationMgr the class to perform deletion XGUI_ShortCutListener(QObject* theParent, XGUI_OperationMgr* theOperationMgr) - : QObject(theParent), myOperationMgr(theOperationMgr) + : QObject(theParent), myOperationMgr(theOperationMgr), myIsActive(false) { qApp->installEventFilter(this); } @@ -56,12 +79,36 @@ public: virtual bool eventFilter(QObject *theObject, QEvent *theEvent) { bool isAccepted = false; - if (myIsActive && theEvent->type() == QEvent::KeyRelease) { - QKeyEvent* aKeyEvent = dynamic_cast(theEvent); - if(aKeyEvent) { - switch (aKeyEvent->key()) { - case Qt::Key_Delete: { - isAccepted = myOperationMgr->onProcessDelete(theObject); + + if (myIsActive) { + // Do not process keys for modal dialogues: all keys has to be processed within the dialog + // There is only one exception: ModuleBase_EditorDialog + QWindow* aWnd = qApp->modalWindow(); + QString aName = "NoModal"; + if (aWnd) { + if (!aWnd->objectName().startsWith("ModuleBase_EditorDialog")) + aName = aWnd->objectName(); + } + if (aName == "NoModal") { + if (theEvent->type() == QEvent::KeyRelease) { + QKeyEvent* aKeyEvent = dynamic_cast(theEvent); + if (aKeyEvent) { + myOperationMgr->setSHIFTPressed(aKeyEvent->modifiers() & Qt::ShiftModifier); + switch (aKeyEvent->key()) { + case Qt::Key_Delete: + isAccepted = myOperationMgr->onProcessDelete(theObject); + break; + default: + isAccepted = myOperationMgr->onKeyReleased(theObject, aKeyEvent); + break; + } + } + } + else if (theEvent->type() == QEvent::KeyPress) { + if (myOperationMgr->hasOperation()) { + QKeyEvent* aKeyEvent = dynamic_cast(theEvent); + myOperationMgr->setSHIFTPressed(aKeyEvent->modifiers() & Qt::ShiftModifier); + isAccepted = myOperationMgr->onKeyPressed(theObject, aKeyEvent); } } } @@ -78,7 +125,7 @@ private: XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent, ModuleBase_IWorkshop* theWorkshop) -: QObject(theParent), myWorkshop(theWorkshop) +: QObject(theParent), myWorkshop(theWorkshop), mySHIFTPressed(false), myActiveMessageBox(0) { /// 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 @@ -128,9 +175,12 @@ bool XGUI_OperationMgr::hasOperation(const QString& theId) const ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const { - foreach(ModuleBase_Operation* aOp, myOperations) { - if (aOp->id() == theId) - return aOp; + QList::const_iterator anIt = myOperations.end(); + while (anIt != myOperations.begin()) { + --anIt; + ModuleBase_Operation* anOperation = *anIt; + if (anOperation->id() == theId) + return anOperation; } return 0; } @@ -145,7 +195,8 @@ QStringList XGUI_OperationMgr::operationList() const { QStringList result; foreach(ModuleBase_Operation* eachOperation, myOperations) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast(eachOperation); + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(eachOperation); if (aFOperation) { FeaturePtr aFeature = aFOperation->feature(); if(aFeature) { @@ -165,18 +216,16 @@ ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* return myOperations.at(idx - 1); } -bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent) +ModuleBase_ModelWidget* XGUI_OperationMgr::activeWidget() const { - bool isAccepted = false; - if (theEvent->type() == QEvent::KeyRelease) { - QKeyEvent* aKeyEvent = dynamic_cast(theEvent); - if(aKeyEvent) - isAccepted = onKeyReleased(theObject, aKeyEvent); + ModuleBase_ModelWidget* anActiveWidget = 0; + ModuleBase_Operation* anOperation = currentOperation(); + if (anOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) + anActiveWidget = aPanel->activeWidget(); } - if (!isAccepted) - isAccepted = QObject::eventFilter(theObject, theEvent); - - return isAccepted; + return anActiveWidget; } bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) @@ -202,7 +251,7 @@ bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) return isStarted; } -bool XGUI_OperationMgr::abortAllOperations() +bool XGUI_OperationMgr::abortAllOperations(const XGUI_MessageKind& theMessageKind) { bool aResult = true; if(!hasOperation()) @@ -210,18 +259,25 @@ bool XGUI_OperationMgr::abortAllOperations() if (operationsCount() == 1) { ModuleBase_Operation* aCurrentOperation = currentOperation(); - if (canStopOperation(aCurrentOperation)) { + if (canStopOperation(aCurrentOperation, theMessageKind)) { abortOperation(aCurrentOperation); } else aResult = false; } else { - aResult = QMessageBox::question(qApp->activeWindow(), - tr("Abort operation"), - tr("All active operations will be aborted."), - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Cancel) == QMessageBox::Ok; + if (theMessageKind == XGUI_AbortOperationMessage) { + myActiveMessageBox = createMessageBox(tr("All active operations will be aborted.")); + aResult = myActiveMessageBox->exec() == QMessageBox::Ok; + myActiveMessageBox = 0; + } + else if (theMessageKind == XGUI_InformationMessage) { + QString aMessage = tr("Please validate all your active operations before saving."); + myActiveMessageBox = createInformationBox(aMessage); + myActiveMessageBox->exec(); + myActiveMessageBox = 0; + aResult = false; // do not perform abort + } while(aResult && hasOperation()) { abortOperation(currentOperation()); } @@ -235,7 +291,7 @@ bool XGUI_OperationMgr::commitAllOperations() while (hasOperation()) { ModuleBase_Operation* anOperation = currentOperation(); if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled()) { - anOperationProcessed = onCommitOperation(); + anOperationProcessed = commitOperation(); } else { abortOperation(anOperation); anOperationProcessed = true; @@ -244,7 +300,7 @@ bool XGUI_OperationMgr::commitAllOperations() (anOperation); if (aFOperation) { FeaturePtr aFeature = aFOperation->feature(); - CompositeFeaturePtr aComposite = + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aFeature); isCompositeCommitted = aComposite.get(); if (isCompositeCommitted) @@ -274,7 +330,8 @@ void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperati { XGUI_ErrorMgr* anErrorMgr = XGUI_Tools::workshop(myWorkshop)->errorMgr(); if (theOperation) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(theOperation); if (aFOperation) anErrorMgr->updateAcceptAllAction(aFOperation->feature()); } @@ -284,35 +341,42 @@ void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperati updateApplyOfOperations(anOperation); } } + // Apply button of the current operation should also be updated + onValidateOperation(); } -bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation) +bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation, + const XGUI_OperationMgr::XGUI_MessageKind& theMessageKind) { //in case of nested (sketch) operation no confirmation needed if (isGrantedOperation(theOperation->id())) return true; if (theOperation && theOperation->isModified()) { - QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id()); - int anAnswer = QMessageBox::question(qApp->activeWindow(), - tr("Abort operation"), - aMessage, - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Cancel); - return anAnswer == QMessageBox::Ok; + ModuleBase_OperationFeature* aOp = dynamic_cast(theOperation); + std::string aContext; + if (aOp) + aContext = aOp->feature()->getKind(); + QString aTitle = Config_Translator::translate(aContext, + theOperation->getDescription()->description().toStdString()).c_str(); + + if (theMessageKind == XGUI_AbortOperationMessage) { + QString aMessage = tr("%1 operation will be aborted.").arg(aTitle); + myActiveMessageBox = createMessageBox(aMessage); + bool aResult = myActiveMessageBox->exec() == QMessageBox::Ok; + myActiveMessageBox = 0; + return aResult; + } + else if (theMessageKind == XGUI_InformationMessage) { + QString aMessage = tr("Please validate your %1 before saving.").arg(aTitle); + myActiveMessageBox = createInformationBox(aMessage); + myActiveMessageBox->exec(); + myActiveMessageBox = 0; + return false; + } } return true; } -bool XGUI_OperationMgr::commitOperation() -{ - //if (hasOperation() && currentOperation()->isValid()) { - // onCommitOperation(); - // return true; - //} - //return false; - return onCommitOperation(); -} - void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation) { theOperation->resume(); @@ -339,15 +403,23 @@ void XGUI_OperationMgr::setCurrentFeature(const FeaturePtr& theFeature) DocumentPtr aDoc = aMgr->activeDocument(); bool aIsOp = aMgr->isOperation(); if (!aIsOp) - aMgr->startOperation(QString("Set current feature: %1").arg(theFeature->getKind().c_str()).toStdString()); + aMgr->startOperation(QString("Set current feature: %1") + .arg(theFeature->getKind().c_str()).toStdString()); aDoc->setCurrentFeature(theFeature, false); +#ifdef DEBUG_CURRENT_FEATURE + qDebug(QString(" document->setCurrentFeature(false) = %1 SET").arg( + ModuleBase_Tools::objectName( + ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); +#endif + if (!aIsOp) aMgr->finishOperation(); } -bool XGUI_OperationMgr::canStartOperation(const QString& theId) +bool XGUI_OperationMgr::canStartOperation(const QString& theId, bool& isCommitted) { bool aCanStart = true; + isCommitted = false; ModuleBase_Operation* aCurrentOp = currentOperation(); if (aCurrentOp) { bool aGranted = aCurrentOp->isGranted(theId); @@ -364,11 +436,8 @@ bool XGUI_OperationMgr::canStartOperation(const QString& theId) } else if (canStopOperation(aCurrentOp)) { // the started operation is granted in the parrent operation, - // e.g. current - Line in Sketch, started Circle - if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled() && aCurrentOp->isModified()) - aCurrentOp->commit(); - else - abortOperation(aCurrentOp); + // e.g. current - Line in Sketch, started Circle + stopOperation(aCurrentOp, isCommitted); } else { aCanStart = false; } @@ -377,10 +446,21 @@ bool XGUI_OperationMgr::canStartOperation(const QString& theId) return aCanStart; } +void XGUI_OperationMgr::stopOperation(ModuleBase_Operation* theOperation, bool& isCommitted) +{ + if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled() && + theOperation->isModified()) { + isCommitted = theOperation->commit(); + } else { + isCommitted = false; + abortOperation(theOperation); + } +} + void XGUI_OperationMgr::abortOperation(ModuleBase_Operation* theOperation) { ModuleBase_Operation* aCurrentOperation = currentOperation(); - if (theOperation == aCurrentOperation) + if (theOperation && (theOperation == aCurrentOperation)) theOperation->abort(); else { // it is possible to trigger upper operation(e.g. sketch, current is sketch line) @@ -395,7 +475,7 @@ void XGUI_OperationMgr::abortOperation(ModuleBase_Operation* theOperation) } } -bool XGUI_OperationMgr::onCommitOperation() +bool XGUI_OperationMgr::commitOperation() { bool isCommitted = false; ModuleBase_Operation* anOperation = currentOperation(); @@ -412,6 +492,11 @@ void XGUI_OperationMgr::onAbortOperation() } } +void XGUI_OperationMgr::onAbortAllOperation() +{ + abortAllOperations(); +} + void XGUI_OperationMgr::onBeforeOperationStarted() { ModuleBase_Operation* aCurrentOperation = dynamic_cast(sender()); @@ -419,43 +504,49 @@ void XGUI_OperationMgr::onBeforeOperationStarted() return; /// Set current feature and remeber old current feature - ModuleBase_OperationFeature* aFOperation = dynamic_cast(aCurrentOperation); + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(aCurrentOperation); if (aFOperation) { SessionPtr aMgr = ModelAPI_Session::get(); DocumentPtr aDoc = aMgr->activeDocument(); - // the parameter of current feature should be false, we should use all feature, not only visible - // in order to correctly save the previous feature of the nested operation, where the + // the parameter of current feature should be false, we should use all feature, not only + // visible in order to correctly save the previous feature of the nested operation, where the // features can be not visible in the tree. The problem case is Edit sketch entitity(line) // in the Sketch, created in ExtrusionCut operation. The entity disappears by commit. // When sketch entity operation started, the sketch should be cashed here as the current. // Otherwise(the flag is true), the ExtrusionCut is cashed, when commit happens, the sketch // is disabled, sketch entity is disabled as extrusion cut is created earliest then sketch. - // As a result the sketch disappears from the viewer. However after commit it is displayed back. + // As a result the sketch disappears from the viewer. + // However after commit it is displayed back. aFOperation->setPreviousCurrentFeature(aDoc->currentFeature(false)); #ifdef DEBUG_CURRENT_FEATURE FeaturePtr aFeature = aFOperation->feature(); QString aKind = aFeature ? aFeature->getKind().c_str() : ""; - qDebug(QString("onBeforeOperationStarted(), edit operation = %1, feature = %2") + qDebug(""); + qDebug(QString("onBeforeOperationStarted() isEditOperation = %1, feature = %2") .arg(aFOperation->isEditOperation()) - .arg(ModuleBase_Tools::objectInfo(aFeature)).toStdString().c_str()); - - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); + .arg(ModuleBase_Tools::objectName(aFeature)).toStdString().c_str()); + qDebug(QString(" document->currentFeature(false) = %1 : DO: setPreviousCurrentFeature").arg( + ModuleBase_Tools::objectName(aDoc->currentFeature(false))).toStdString().c_str()); #endif - if (aFOperation->isEditOperation()) // it should be performed by the feature edit only + if (aFOperation->isEditOperation()) {// it should be performed by the feature edit only // in create operation, the current feature is changed by addFeature() aDoc->setCurrentFeature(aFOperation->feature(), false); - #ifdef DEBUG_CURRENT_FEATURE - qDebug("\tdocument->setCurrentFeature"); - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); + qDebug(QString(" document->setCurrentFeature(false) = %1").arg( + ModuleBase_Tools::objectName(aDoc->currentFeature(false))).toStdString().c_str()); #endif - ModuleBase_IModule* aModule = myWorkshop->module(); - if (aModule) - aModule->beforeOperationStarted(aFOperation); + // this is the only place where flushes must be called after setCurrentFeature for the + // current moment: after this the opertion is not finished, so, the ObjectBrowser + // state may be corrupted (issue #1457) + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID aCreateEvent = aLoop->eventByName(EVENT_OBJECT_CREATED); + aLoop->flush(aCreateEvent); + static Events_ID aDeleteEvent = aLoop->eventByName(EVENT_OBJECT_DELETED); + aLoop->flush(aDeleteEvent); + } } } @@ -463,7 +554,8 @@ void XGUI_OperationMgr::onOperationStarted() { ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); updateApplyOfOperations(aSenderOperation); - emit operationStarted(aSenderOperation); + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + aWorkshop->operationStarted(aSenderOperation); } void XGUI_OperationMgr::onBeforeOperationAborted() @@ -474,6 +566,8 @@ void XGUI_OperationMgr::onBeforeOperationAborted() void XGUI_OperationMgr::onOperationAborted() { ModuleBase_Operation* aSenderOperation = dynamic_cast(sender()); + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + aWorkshop->setStatusBarMessage(""); emit operationAborted(aSenderOperation); } @@ -484,16 +578,18 @@ void XGUI_OperationMgr::onBeforeOperationCommitted() return; /// Restore the previous current feature - ModuleBase_OperationFeature* aFOperation = dynamic_cast(aCurrentOperation); + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(aCurrentOperation); if (aFOperation) { #ifdef DEBUG_CURRENT_FEATURE QString aKind = aFOperation->feature()->getKind().c_str(); - qDebug(QString("onBeforeOperationCommitted(), edit operation = %1, feature = %2") + qDebug(QString("onBeforeOperationCommitted() isEditOperation = %1, feature = %2") .arg(aFOperation->isEditOperation()) - .arg(ModuleBase_Tools::objectInfo(aFOperation->feature())).toStdString().c_str()); - - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); + .arg(ModuleBase_Tools::objectName(aFOperation->feature())).toStdString().c_str()); + qDebug(QString(" document->currentFeature(false) = %1").arg( + ModuleBase_Tools::objectName( + ModelAPI_Session::get()->activeDocument()->currentFeature(false))) + .toStdString().c_str()); #endif if (aFOperation->isEditOperation()) { @@ -501,17 +597,14 @@ void XGUI_OperationMgr::onBeforeOperationCommitted() setCurrentFeature(aFOperation->previousCurrentFeature()); } else { // create operation - // the Top created feature should stays the current. In nested operations, like Line in the Sketch or - // Sketch in ExtrusionCut, a previous feature should be restored on commit. It is performed here + // the Top created feature should stays the current. In nested operations, + // like Line in the Sketch or + // Sketch in ExtrusionCut, a previous feature should be restored on commit. + // It is performed here // in order to perform it in the current transaction without opening a new one. if (myOperations.front() != aFOperation) setCurrentFeature(aFOperation->previousCurrentFeature()); } -#ifdef DEBUG_CURRENT_FEATURE - qDebug("\tdocument->setCurrentFeature"); - qDebug(QString("\tdocument->currentFeature(false) = %1").arg( - ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str()); -#endif ModuleBase_IModule* aModule = myWorkshop->module(); if (aModule) aModule->beforeOperationStopped(aFOperation); @@ -557,8 +650,8 @@ void XGUI_OperationMgr::onOperationStopped() } } if (aResultOp) { - bool isModified = aCurrentOperation->isModified(); - aResultOp->setIsModified(aResultOp->isModified() || isModified); + //bool isModified = aCurrentOperation->isModified(); + //aResultOp->setIsModified(aResultOp->isModified() || isModified); resumeOperation(aResultOp); onValidateOperation(); } @@ -566,10 +659,30 @@ void XGUI_OperationMgr::onOperationStopped() bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent) { + bool isAccepted = false; + // Let the manager decide what to do with the given key combination. ModuleBase_Operation* anOperation = currentOperation(); - bool isAccepted = false; switch (theEvent->key()) { + case Qt::Key_Tab: + case Qt::Key_Backtab: + { + ModuleBase_Operation* aOperation = currentOperation(); + if (aOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) { + QWidget* aFocusedWidget = qApp->focusWidget(); + bool isPPChildObject = aFocusedWidget && isChildObject(aFocusedWidget, aPanel); + if (!isPPChildObject) { + // check for case when the operation is started but property panel is not filled + XGUI_PropertyPanel* aPP = dynamic_cast(aPanel); + aPP->setFocusNextPrevChild(theEvent->key() == Qt::Key_Tab); + isAccepted = true; + } + } + } + } + break; case Qt::Key_Return: case Qt::Key_Enter: { isAccepted = onProcessEnter(theObject); @@ -587,12 +700,17 @@ bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent) aContext->HilightNextDetected(aView); else if ((theEvent->key() == Qt::Key_P)) aContext->HilightPreviousDetected(aView); + aViewer->updateHighlight(); + isAccepted = true; } } - } - break; - break; - default: + } + break; + case Qt::Key_H: + if ((theEvent->modifiers() == Qt::NoModifier)) + myWorkshop->viewer()->hideSelectionHighlight(); + break; + default: isAccepted = false; break; } @@ -602,6 +720,59 @@ bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent) return isAccepted; } +bool XGUI_OperationMgr::onKeyPressed(QObject *theObject, QKeyEvent* theEvent) +{ + // Let the manager decide what to do with the given key combination. + ModuleBase_Operation* anOperation = currentOperation(); + bool isAccepted = false; + switch (theEvent->key()) { + case Qt::Key_Escape: { + // processing in message box + if (myActiveMessageBox) + { + myActiveMessageBox->reject(); + isAccepted = true; + } + // processing in the active widget + ModuleBase_Operation* aOperation = currentOperation(); + if (!isAccepted && aOperation) { + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + if (aPanel) { + ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget(); + if (anActiveWgt) + { + isAccepted = anActiveWgt && anActiveWgt->processAction(ActionEscape); + if (isAccepted) { + ModuleBase_OperationFeature* aFOperation = + dynamic_cast(currentOperation()); + if (aFOperation) + aFOperation->setNeedToBeAborted(true); + } + } + } + } + if (!isAccepted) + { + XGUI_ActiveControlSelector* anActiveSelector = + XGUI_Tools::workshop(myWorkshop)->activeControlMgr()->activeSelector(); + if (anActiveSelector && anActiveSelector->getType() == XGUI_FacesPanelSelector::Type()) + isAccepted = XGUI_Tools::workshop(myWorkshop)->facesPanel()->processAction(ActionEscape); + } + // default Escape button functionality + if (!isAccepted && aOperation) { + onAbortOperation(); + isAccepted = true; + } + } + break; + case Qt::Key_H: + if ((theEvent->modifiers() == Qt::NoModifier)) + myWorkshop->viewer()->showSelectionHighlight(); + break; + } + return isAccepted; +} + bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) { bool isAccepted = false; @@ -610,16 +781,20 @@ bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) if (!aOperation) return isAccepted; ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); - // only property panel enter is processed in order to do not process enter in application dialogs - bool isPPChild = isChildObject(theObject, aPanel); - if (!isPPChild) + if (!aPanel) return isAccepted; + // the next code is obsolete as we want to process Enter in property panel always + // only property panel enter is processed in order to do not process enter in application dialogs + //bool isPPChild = isChildObject(theObject, aPanel); + //if (!isPPChild) + // return isAccepted; ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget(); bool isAborted = false; if (!anActiveWgt) { QWidget* aFocusWidget = aPanel->focusWidget(); - QToolButton* aCancelBtn = aPanel->findChild(PROP_PANEL_CANCEL); + QToolButton* aCancelBtn = + dynamic_cast(aPanel)->findButton(PROP_PANEL_CANCEL); if (aFocusWidget && aCancelBtn && aFocusWidget == aCancelBtn) { abortOperation(aOperation); isAccepted = true; @@ -627,14 +802,18 @@ bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) } } if (!isAborted) { - isAccepted = anActiveWgt && anActiveWgt->processEnter(); + isAccepted = anActiveWgt && anActiveWgt->processAction(ActionEnter); if (!isAccepted) { - isAccepted = myWorkshop->module()->processEnter(anActiveWgt ? anActiveWgt->attributeID() : ""); + 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 + 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; @@ -647,6 +826,12 @@ bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) return isAccepted; } +bool editorControl(QObject* theObject) +{ + QLineEdit* aLineEdit = dynamic_cast(theObject); + return aLineEdit; +} + bool XGUI_OperationMgr::onProcessDelete(QObject* theObject) { bool isAccepted = false; @@ -664,23 +849,48 @@ bool XGUI_OperationMgr::onProcessDelete(QObject* theObject) if (isPPChildObject) { anActiveWgt = aPanel->activeWidget(); if (anActiveWgt) { - isAccepted = anActiveWgt->processDelete(); + isAccepted = anActiveWgt->processAction(ActionDelete); } } } } + if (!isAccepted) + { + XGUI_ActiveControlSelector* anActiveSelector = + XGUI_Tools::workshop(myWorkshop)->activeControlMgr()->activeSelector(); + if (anActiveSelector && anActiveSelector->getType() == XGUI_FacesPanelSelector::Type()) + isAccepted = XGUI_Tools::workshop(myWorkshop)->facesPanel()->processAction(ActionDelete); + } if (!isAccepted) { // after widget, object browser and viewer should process delete /// other widgets such as line edit controls should not lead to /// processing delete by workshop XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser(); QWidget* aViewPort = myWorkshop->viewer()->activeViewPort(); - // property panel child object is processed to process delete performed on Apply button of PP - if (theObject == aBrowser->treeView() || - isChildObject(theObject, aViewPort) || - isPPChildObject) - XGUI_Tools::workshop(myWorkshop)->deleteObjects(); - isAccepted = true; + bool isToDeleteObject = false; + XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop); + XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr(); + if (theObject == aBrowser->treeView()) { + aContextMenuMgr->updateObjectBrowserMenu(); + isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled(); + } + else if (isChildObject(theObject, aViewPort)) { + aContextMenuMgr->updateViewerMenu(); + isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled(); + } + else if (isPPChildObject) { + // property panel child object is processed to process delete performed on Apply button of PP + isToDeleteObject = true; + } + else if (editorControl(theObject)) { + isToDeleteObject = false; /// Line Edit of Rename operation in ObjectBrowser + isAccepted = true; + } + + if (isToDeleteObject) { + aWorkshop->deleteObjects(); + isAccepted = true; + } } return isAccepted; @@ -700,3 +910,25 @@ bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* t } return isPPChild; } + +QMessageBox* XGUI_OperationMgr::createMessageBox(const QString& theMessage) +{ + QMessageBox * aMessageBox = new QMessageBox(QMessageBox::Question, + QObject::tr("Abort operation"), theMessage, QMessageBox::Ok | QMessageBox::Cancel, + qApp->activeWindow()); + aMessageBox->setDefaultButton(QMessageBox::Cancel); + aMessageBox->setEscapeButton(QMessageBox::No); // operation manager should process Esc key + + return aMessageBox; +} + +QMessageBox* XGUI_OperationMgr::createInformationBox(const QString& theMessage) +{ + QMessageBox * aMessageBox = new QMessageBox(QMessageBox::Question, + QObject::tr("Validate operation"), theMessage, QMessageBox::Ok, + qApp->activeWindow()); + aMessageBox->setDefaultButton(QMessageBox::Ok); + aMessageBox->setEscapeButton(QMessageBox::No); // operation manager should process Esc key + + return aMessageBox; +}