Salome HOME
e6855819a4a9853dc5f9062215183edd0296a8a8
[modules/shaper.git] / src / XGUI / XGUI_OperationMgr.cpp
1 // File:        XGUI_OperationMgr.h
2 // Created:     20 Apr 2014
3 // Author:      Natalia ERMOLAEVA
4
5 #include "XGUI_OperationMgr.h"
6
7 #include "ModuleBase_Operation.h"
8 #include <ModelAPI_Validator.h>
9 #include <ModelAPI_FeatureValidator.h>
10
11 #include <QMessageBox>
12 #include <QApplication>
13 #include <QKeyEvent>
14
15 XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent)
16     : QObject(theParent)
17 {
18   // listen to Escape signal to stop the current operation
19   qApp->installEventFilter(this);
20 }
21
22 XGUI_OperationMgr::~XGUI_OperationMgr()
23 {
24 }
25
26 ModuleBase_Operation* XGUI_OperationMgr::currentOperation() const
27 {
28   return myOperations.count() > 0 ? myOperations.last() : 0;
29 }
30
31 bool XGUI_OperationMgr::hasOperation() const
32 {
33   return (myOperations.count() > 0) && (myOperations.last() != NULL);
34 }
35
36 int XGUI_OperationMgr::operationsCount() const
37 {
38   return myOperations.count();
39 }
40
41 bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
42 {
43   if (!canStartOperation(theOperation))
44     return false;
45
46   myOperations.append(theOperation);
47
48   connect(theOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped()));
49   connect(theOperation, SIGNAL(started()), this, SIGNAL(operationStarted()));
50   connect(theOperation, SIGNAL(resumed()), this, SIGNAL(operationResumed()));
51   connect(theOperation, SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)), this,
52           SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)));
53
54   theOperation->start();
55   validateCurrentOperation();
56   return true;
57 }
58
59 bool XGUI_OperationMgr::abortOperation()
60 {
61   ModuleBase_Operation* aCurrentOp = currentOperation();
62   if (!aCurrentOp || !canStopOperation())
63     return false;
64
65   aCurrentOp->abort();
66   return true;
67 }
68
69 QStringList XGUI_OperationMgr::operationList()
70 {
71   QStringList result;
72   foreach(ModuleBase_Operation* eachOperation, myOperations)
73   {
74     result << eachOperation->id();
75   }
76   return result;
77 }
78
79 void XGUI_OperationMgr::validateOperation(ModuleBase_Operation* theOperation)
80 {
81   //Get operation Id and feature to validate
82   QString anOperationId = theOperation->id();
83   FeaturePtr aFeature = theOperation->feature();
84   //Get validators for the Id
85   PluginManagerPtr aMgr = ModelAPI_PluginManager::get();
86   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
87   std::list<ModelAPI_Validator*> aValidators;
88   aFactory->validators(anOperationId.toStdString(), aValidators);
89   //
90   std::list<ModelAPI_Validator*>::iterator it = aValidators.begin();
91   bool isValid = true;
92   for (; it != aValidators.end(); it++) {
93     const ModelAPI_FeatureValidator* aFeatureValidator =
94         dynamic_cast<const ModelAPI_FeatureValidator*>(*it);
95     if (!aFeatureValidator)
96       continue;
97     if (!aFeatureValidator->isValid(aFeature)) {
98       isValid = false;
99       break;
100     }
101   }
102   emit operationValidated(isValid);
103 }
104
105 void XGUI_OperationMgr::validateCurrentOperation()
106 {
107   if (!hasOperation())
108     return;
109   ModuleBase_Operation* anOperation = currentOperation();
110   validateOperation(currentOperation());
111 }
112
113 bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
114 {
115   if (theEvent->type() == QEvent::KeyRelease) {
116     QKeyEvent* aKeyEvent = (QKeyEvent*) theEvent;
117     if (aKeyEvent && aKeyEvent->key() == Qt::Key_Escape) {
118       // TODO: this is Escape button processing when the property panel has empty content,
119       // but the operation should be stopped by the Enter has been clicked
120       onKeyReleased("", aKeyEvent);
121       return true;
122     }
123   }
124   return QObject::eventFilter(theObject, theEvent);
125 }
126
127 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
128 {
129   theOperation->resume();
130 }
131
132 bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation)
133 {
134   bool aCanStart = true;
135   ModuleBase_Operation* aCurrentOp = currentOperation();
136   if (aCurrentOp) {
137     if (!theOperation->isGranted()) {
138       if (!aCurrentOp->isValid(theOperation)) {
139         if (canStopOperation()) {
140           aCurrentOp->abort();
141         } else {
142           aCanStart = false;
143         }
144       }
145     }
146   }
147   return aCanStart;
148 }
149
150 bool XGUI_OperationMgr::canStopOperation()
151 {
152   ModuleBase_Operation* anOperation = currentOperation();
153   if (anOperation) {
154     if (anOperation->isModified()) {
155       int anAnswer = QMessageBox::question(
156           qApp->activeWindow(), tr("Operation launch"),
157           tr("Previous operation is not finished and will be aborted"), QMessageBox::Ok,
158           QMessageBox::Cancel);
159       return anAnswer == QMessageBox::Ok;
160     }
161   }
162   return true;
163 }
164
165 void XGUI_OperationMgr::onCommitOperation()
166 {
167   ModuleBase_Operation* anOperation = currentOperation();
168   if (anOperation)
169     anOperation->commit();
170 }
171
172 void XGUI_OperationMgr::onAbortOperation()
173 {
174   ModuleBase_Operation* anOperation = currentOperation();
175   if (anOperation && canAbortOperation())
176     anOperation->abort();
177 }
178
179 bool XGUI_OperationMgr::canAbortOperation()
180 {
181   ModuleBase_Operation* anOperation = currentOperation();
182   if (anOperation && anOperation->isModified()) {
183     int anAnswer = QMessageBox::question(
184         qApp->activeWindow(), tr("Cancel operation"),
185         tr("Operation %1 will be cancelled. Continue?").arg(anOperation->id()), QMessageBox::Yes,
186         QMessageBox::No);
187     return anAnswer == QMessageBox::Yes;
188   }
189   return true;
190 }
191
192 void XGUI_OperationMgr::onOperationStopped()
193 {
194   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
195   ModuleBase_Operation* anOperation = currentOperation();
196   if (!aSenderOperation || !anOperation || aSenderOperation != anOperation)
197     return;
198
199   myOperations.removeAll(anOperation);
200   anOperation->deleteLater();
201
202   emit operationStopped(anOperation);
203
204   // get last operation which can be resumed
205   ModuleBase_Operation* aResultOp = 0;
206   QListIterator<ModuleBase_Operation*> anIt(myOperations);
207   anIt.toBack();
208   while (anIt.hasPrevious()) {
209     ModuleBase_Operation* anOp = anIt.previous();
210     if (anOp) {
211       aResultOp = anOp;
212       break;
213     }
214   }
215   if (aResultOp) {
216     resumeOperation(aResultOp);
217     validateCurrentOperation();
218   }
219 }
220
221 void XGUI_OperationMgr::onKeyReleased(const std::string& theName, QKeyEvent* theEvent)
222 {
223   ModuleBase_Operation* anOperation = currentOperation();
224   if (anOperation)
225     anOperation->keyReleased(theName, theEvent);
226 }
227
228 void XGUI_OperationMgr::onWidgetActivated(ModuleBase_ModelWidget* theWidget)
229 {
230   ModuleBase_Operation* anOperation = currentOperation();
231   if (anOperation)
232     anOperation->onWidgetActivated(theWidget);
233 }