+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
// File: XGUI_OperationMgr.h
// Created: 20 Apr 2014
// Author: Natalia ERMOLAEVA
#include "XGUI_OperationMgr.h"
#include "ModuleBase_Operation.h"
-#include <ModelAPI_Validator.h>
-#include <ModelAPI_FeatureValidator.h>
#include <QMessageBox>
#include <QApplication>
#include <QKeyEvent>
XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent)
- : QObject(theParent)
+ : QObject(theParent), myIsValidationLock(false), myIsApplyEnabled(false)
{
- // listen to Escape signal to stop the current operation
- qApp->installEventFilter(this);
}
XGUI_OperationMgr::~XGUI_OperationMgr()
return myOperations.count() > 0 ? myOperations.last() : 0;
}
+bool XGUI_OperationMgr::isCurrentOperation(ModuleBase_Operation* theOperation)
+{
+ if(!hasOperation())
+ return false;
+ return currentOperation() == theOperation;
+}
+
bool XGUI_OperationMgr::hasOperation() const
{
- return (myOperations.count() > 0) && (myOperations.last() != NULL);
+ return !myOperations.isEmpty() && (myOperations.last() != NULL);
}
+bool XGUI_OperationMgr::hasOperation(const QString& theId) const
+{
+ foreach(ModuleBase_Operation* aOp, myOperations) {
+ if (aOp->id() == theId)
+ return true;
+ }
+ return false;
+}
+
+ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const
+{
+ foreach(ModuleBase_Operation* aOp, myOperations) {
+ if (aOp->id() == theId)
+ return aOp;
+ }
+ return 0;
+}
+
+
int XGUI_OperationMgr::operationsCount() const
{
return myOperations.count();
}
-bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
+QStringList XGUI_OperationMgr::operationList() const
{
- if (!canStartOperation(theOperation))
- return false;
+ QStringList result;
+ foreach(ModuleBase_Operation* eachOperation, myOperations) {
+ FeaturePtr aFeature = eachOperation->feature();
+ if(aFeature) {
+ result << QString::fromStdString(aFeature->getKind());
+ }
+ }
+ return result;
+}
+
+ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* theOperation) const
+{
+ int idx = myOperations.lastIndexOf(theOperation);
+ if(idx == -1 || idx == 0) {
+ return NULL;
+ }
+ return myOperations.at(idx - 1);
+}
+bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
+{
+ if (theEvent->type() == QEvent::KeyRelease) {
+ QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
+ if(aKeyEvent) {
+ return onKeyReleased(aKeyEvent);
+ }
+ }
+ return QObject::eventFilter(theObject, theEvent);
+}
+
+bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
+{
+ if (hasOperation())
+ currentOperation()->postpone();
myOperations.append(theOperation);
- connect(theOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped()));
- connect(theOperation, SIGNAL(started()), this, SIGNAL(operationStarted()));
- connect(theOperation, SIGNAL(resumed()), this, SIGNAL(operationResumed()));
- connect(theOperation, SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)), this,
- SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)));
+ connect(theOperation, SIGNAL(started()), SLOT(onOperationStarted()));
+ connect(theOperation, SIGNAL(aborted()), SLOT(onOperationAborted()));
+ connect(theOperation, SIGNAL(committed()), SLOT(onOperationCommitted()));
+ connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped()));
+ connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed()));
+ connect(theOperation, SIGNAL(triggered(bool)), SLOT(onOperationTriggered(bool)));
+ connect(theOperation, SIGNAL(activatedByPreselection()),
+ SIGNAL(operationActivatedByPreselection()));
theOperation->start();
- validateCurrentOperation();
+ onValidateOperation();
return true;
}
-bool XGUI_OperationMgr::abortOperation()
+bool XGUI_OperationMgr::abortAllOperations()
{
- ModuleBase_Operation* aCurrentOp = currentOperation();
- if (!aCurrentOp || !canStopOperation())
- return false;
+ if(!hasOperation()) {
+ return true;
+ } else if (operationsCount() == 1) {
+ onAbortOperation();
+ return true;
+ }
+ QString aMessage = tr("All active operations will be aborted.");
+ int anAnswer = QMessageBox::question(qApp->activeWindow(),
+ tr("Abort operation"),
+ aMessage,
+ QMessageBox::Ok | QMessageBox::Cancel,
+ QMessageBox::Cancel);
+ bool result = anAnswer == QMessageBox::Ok;
+ while(result && hasOperation()) {
+ currentOperation()->abort();
+ }
+ return result;
+}
- aCurrentOp->abort();
+bool XGUI_OperationMgr::commitAllOperations()
+{
+ while (hasOperation()) {
+ if (isApplyEnabled()) {
+ onCommitOperation();
+ } else {
+ currentOperation()->abort();
+ }
+ }
return true;
}
-QStringList XGUI_OperationMgr::operationList()
+void XGUI_OperationMgr::onValidateOperation()
{
- QStringList result;
- foreach(ModuleBase_Operation* eachOperation, myOperations)
- {
- result << eachOperation->id();
+ if (!hasOperation())
+ return;
+ ModuleBase_Operation* anOperation = currentOperation();
+ if(anOperation && (!myIsValidationLock)) {
+ setApplyEnabled(anOperation->isValid());
}
- return result;
}
-void XGUI_OperationMgr::validateOperation(ModuleBase_Operation* theOperation)
+void XGUI_OperationMgr::setApplyEnabled(const bool theEnabled)
{
- //Get operation Id and feature to validate
- QString anOperationId = theOperation->id();
- FeaturePtr aFeature = theOperation->feature();
- //Get validators for the Id
- PluginManagerPtr aMgr = ModelAPI_PluginManager::get();
- ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+ myIsApplyEnabled = theEnabled;
+ emit validationStateChanged(theEnabled);
+}
- bool isValid = aFactory->validate(aFeature);
- emit operationValidated(isValid);
+bool XGUI_OperationMgr::isApplyEnabled() const
+{
+ return myIsApplyEnabled;
}
-void XGUI_OperationMgr::validateCurrentOperation()
+bool XGUI_OperationMgr::canStopOperation()
{
- if (!hasOperation())
- return;
ModuleBase_Operation* anOperation = currentOperation();
- validateOperation(currentOperation());
+ if(operationsCount() > 1) //in case of nested (sketch) operation no confirmation needed
+ return true;
+ if (anOperation && anOperation->isModified()) {
+ QString aMessage = tr("%1 operation will be aborted.").arg(anOperation->id());
+ int anAnswer = QMessageBox::question(qApp->activeWindow(),
+ tr("Abort operation"),
+ aMessage,
+ QMessageBox::Ok | QMessageBox::Cancel,
+ QMessageBox::Cancel);
+ return anAnswer == QMessageBox::Ok;
+ }
+ return true;
}
-bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
+bool XGUI_OperationMgr::commitOperation()
{
- if (theEvent->type() == QEvent::KeyRelease) {
- QKeyEvent* aKeyEvent = (QKeyEvent*) theEvent;
- if (aKeyEvent && aKeyEvent->key() == Qt::Key_Escape) {
- // TODO: this is Escape button processing when the property panel has empty content,
- // but the operation should be stopped by the Enter has been clicked
- onKeyReleased(aKeyEvent);
- return true;
- }
+ if (hasOperation() && currentOperation()->isValid()) {
+ onCommitOperation();
+ return true;
}
- return QObject::eventFilter(theObject, theEvent);
+ return false;
}
void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
theOperation->resume();
}
-bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation)
+bool XGUI_OperationMgr::canStartOperation(QString theId)
{
bool aCanStart = true;
ModuleBase_Operation* aCurrentOp = currentOperation();
if (aCurrentOp) {
- if (!theOperation->isGranted()) {
- if (!aCurrentOp->isValid(theOperation)) {
- if (canStopOperation()) {
+ if (!aCurrentOp->isGranted(theId)) {
+ if (canStopOperation()) {
+ if (myIsApplyEnabled)
+ aCurrentOp->commit();
+ else
aCurrentOp->abort();
- } else {
- aCanStart = false;
- }
+ } else {
+ aCanStart = false;
}
}
}
return aCanStart;
}
-bool XGUI_OperationMgr::canStopOperation()
-{
- ModuleBase_Operation* anOperation = currentOperation();
- if (anOperation) {
- if (anOperation->isModified()) {
- int anAnswer = QMessageBox::question(
- qApp->activeWindow(), tr("Operation launch"),
- tr("Previous operation is not finished and will be aborted"), QMessageBox::Ok,
- QMessageBox::Cancel);
- return anAnswer == QMessageBox::Ok;
- }
- }
- return true;
-}
void XGUI_OperationMgr::onCommitOperation()
{
ModuleBase_Operation* anOperation = currentOperation();
- anOperation->onWidgetActivated(NULL);
if (anOperation)
anOperation->commit();
}
void XGUI_OperationMgr::onAbortOperation()
{
- ModuleBase_Operation* anOperation = currentOperation();
- if (anOperation && canAbortOperation())
- anOperation->abort();
+ if (hasOperation() && canStopOperation()) {
+ currentOperation()->abort();
+ }
}
-bool XGUI_OperationMgr::canAbortOperation()
+void XGUI_OperationMgr::onOperationStarted()
{
- ModuleBase_Operation* anOperation = currentOperation();
- if (anOperation && anOperation->isModified()) {
- int anAnswer = QMessageBox::question(
- qApp->activeWindow(), tr("Cancel operation"),
- tr("Operation %1 will be cancelled. Continue?").arg(anOperation->id()), QMessageBox::Yes,
- QMessageBox::No);
- return anAnswer == QMessageBox::Yes;
- }
- return true;
+ ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+
+ bool isNestedOk = (myOperations.count() >= 1) &&
+ myOperations.at(0)->isValid();
+ emit nestedStateChanged(isNestedOk);
+ emit operationStarted(aSenderOperation);
+}
+
+void XGUI_OperationMgr::onOperationAborted()
+{
+ ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+ emit operationAborted(aSenderOperation);
+}
+
+void XGUI_OperationMgr::onOperationCommitted()
+{
+ ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+ emit nestedStateChanged(myOperations.count() >= 1);
+ emit operationCommitted(aSenderOperation);
+}
+
+void XGUI_OperationMgr::onOperationResumed()
+{
+ ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+ emit operationResumed(aSenderOperation);
}
void XGUI_OperationMgr::onOperationStopped()
}
if (aResultOp) {
resumeOperation(aResultOp);
- validateCurrentOperation();
+ onValidateOperation();
}
}
-void XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent)
+void XGUI_OperationMgr::onOperationTriggered(bool theState)
{
- ModuleBase_Operation* anOperation = currentOperation();
- if (anOperation)
- anOperation->keyReleased(theEvent->key());
+ ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
+ if (aSenderOperation && !theState) {
+ ModuleBase_Operation* aCurrentOperation = currentOperation();
+ if (aSenderOperation == aCurrentOperation)
+ aCurrentOperation->abort();
+ else {
+ // it is possible to trigger upper operation(e.g. sketch, current is sketch line)
+ // all operation from the current to triggered should also be aborted
+ while(hasOperation()) {
+ ModuleBase_Operation* aCurrentOperation = currentOperation();
+ aCurrentOperation->abort();
+ if(aSenderOperation == aCurrentOperation)
+ break;
+ }
+ }
+ }
}
-void XGUI_OperationMgr::onWidgetActivated(ModuleBase_ModelWidget* theWidget)
+bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent)
{
+ // Let the manager decide what to do with the given key combination.
ModuleBase_Operation* anOperation = currentOperation();
- if (anOperation)
- anOperation->onWidgetActivated(theWidget);
+ bool isAccepted = true;
+ switch (theEvent->key()) {
+ case Qt::Key_Return:
+ case Qt::Key_Enter: {
+ emit keyEnterReleased();
+ commitOperation();
+ }
+ break;
+ default:
+ isAccepted = false;
+ break;
+ }
+ //if(anOperation) {
+ // anOperation->keyReleased(theEvent->key());
+ //}
+ return isAccepted;
}
+