Salome HOME
65e76b68c56ef4d34b81ee117928c447d25e25f3
[modules/shaper.git] / src / XGUI / XGUI_OperationMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        XGUI_OperationMgr.h
4 // Created:     20 Apr 2014
5 // Author:      Natalia ERMOLAEVA
6
7 #include "XGUI_OperationMgr.h"
8
9 #include "ModuleBase_Operation.h"
10
11 #include <QMessageBox>
12 #include <QApplication>
13 #include <QKeyEvent>
14
15 XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent)
16     : QObject(theParent), myIsValidationLock(false), myIsApplyEnabled(false)
17 {
18 }
19
20 XGUI_OperationMgr::~XGUI_OperationMgr()
21 {
22 }
23
24 ModuleBase_Operation* XGUI_OperationMgr::currentOperation() const
25 {
26   return myOperations.count() > 0 ? myOperations.last() : 0;
27 }
28
29 bool XGUI_OperationMgr::isCurrentOperation(ModuleBase_Operation* theOperation)
30 {
31   if(!hasOperation())
32     return false;
33   return currentOperation() == theOperation;
34 }
35
36 bool XGUI_OperationMgr::hasOperation() const
37 {
38   return !myOperations.isEmpty() && (myOperations.last() != NULL);
39 }
40
41 bool XGUI_OperationMgr::hasOperation(const QString& theId) const
42 {
43   foreach(ModuleBase_Operation* aOp, myOperations) {
44     if (aOp->id() == theId)
45       return true;
46   }
47   return false;
48 }
49
50 ModuleBase_Operation* XGUI_OperationMgr::findOperation(const QString& theId) const
51 {
52   foreach(ModuleBase_Operation* aOp, myOperations) {
53     if (aOp->id() == theId)
54       return aOp;
55   }
56   return 0;
57 }
58
59
60 int XGUI_OperationMgr::operationsCount() const
61 {
62   return myOperations.count();
63 }
64
65 QStringList XGUI_OperationMgr::operationList() const
66 {
67   QStringList result;
68   foreach(ModuleBase_Operation* eachOperation, myOperations) {
69     FeaturePtr aFeature = eachOperation->feature();
70     if(aFeature) {
71       result << QString::fromStdString(aFeature->getKind());
72     }
73   }
74   return result;
75 }
76
77 ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* theOperation) const
78 {
79   int idx = myOperations.lastIndexOf(theOperation);
80   if(idx == -1 || idx == 0) {
81     return NULL;
82   }
83   return myOperations.at(idx - 1);
84 }
85
86 bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
87 {
88   if (theEvent->type() == QEvent::KeyRelease) {
89     QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
90     if(aKeyEvent) {
91       return onKeyReleased(aKeyEvent);
92     }
93   }
94   return QObject::eventFilter(theObject, theEvent);
95 }
96
97 bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
98 {
99   if (hasOperation())
100     currentOperation()->postpone();
101   myOperations.append(theOperation);
102
103   connect(theOperation, SIGNAL(started()), SLOT(onOperationStarted()));
104   connect(theOperation, SIGNAL(aborted()), SLOT(onOperationAborted()));
105   connect(theOperation, SIGNAL(committed()), SLOT(onOperationCommitted()));
106   connect(theOperation, SIGNAL(stopped()), SLOT(onOperationStopped()));
107   connect(theOperation, SIGNAL(resumed()), SLOT(onOperationResumed()));
108   connect(theOperation, SIGNAL(triggered(bool)), SLOT(onOperationTriggered(bool)));
109   connect(theOperation, SIGNAL(activatedByPreselection()),
110           SIGNAL(operationActivatedByPreselection()));
111
112   theOperation->start();
113   onValidateOperation();
114   return true;
115 }
116
117 bool XGUI_OperationMgr::abortAllOperations()
118 {
119   if(!hasOperation()) {
120     return true;
121   } else if (operationsCount() == 1) {
122     onAbortOperation();
123     return true;
124   }
125   QString aMessage = tr("All active operations will be aborted.");
126   int anAnswer = QMessageBox::question(qApp->activeWindow(),
127                                        tr("Abort operation"),
128                                        aMessage,
129                                        QMessageBox::Ok | QMessageBox::Cancel,
130                                        QMessageBox::Cancel);
131   bool result = anAnswer == QMessageBox::Ok;
132   while(result && hasOperation()) {
133     currentOperation()->abort();
134   }
135   return result;
136 }
137
138 bool XGUI_OperationMgr::commitAllOperations()
139 {
140   while (hasOperation()) {
141     if (isApplyEnabled()) {
142       onCommitOperation();
143     } else {
144       currentOperation()->abort();
145     }
146   }
147   return true;
148 }
149
150 void XGUI_OperationMgr::onValidateOperation()
151 {
152   if (!hasOperation())
153     return;
154   ModuleBase_Operation* anOperation = currentOperation();
155   if(anOperation) {
156     setApplyEnabled(!myIsValidationLock && anOperation->isValid());
157   }
158 }
159
160 void XGUI_OperationMgr::setLockValidating(bool toLock)
161 {
162   myIsValidationLock = toLock;
163   onValidateOperation();
164 }
165
166 void XGUI_OperationMgr::setApplyEnabled(const bool theEnabled)
167 {
168   myIsApplyEnabled = theEnabled;
169   emit validationStateChanged(theEnabled);
170 }
171
172 bool XGUI_OperationMgr::isApplyEnabled() const
173 {
174   return myIsApplyEnabled;
175 }
176
177 bool XGUI_OperationMgr::canStopOperation()
178 {
179   ModuleBase_Operation* anOperation = currentOperation();
180   if(operationsCount() > 1) //in case of nested (sketch) operation no confirmation needed
181     return true;
182   if (anOperation && anOperation->isModified()) {
183     QString aMessage = tr("%1 operation will be aborted.").arg(anOperation->id());
184     int anAnswer = QMessageBox::question(qApp->activeWindow(),
185                                          tr("Abort operation"),
186                                          aMessage,
187                                          QMessageBox::Ok | QMessageBox::Cancel,
188                                          QMessageBox::Cancel);
189     return anAnswer == QMessageBox::Ok;
190   }
191   return true;
192 }
193
194 bool XGUI_OperationMgr::commitOperation()
195 {
196   if (hasOperation() && currentOperation()->isValid()) {
197     onCommitOperation();
198     return true;
199   }
200   return false;
201 }
202
203 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
204 {
205   theOperation->resume();
206 }
207
208 bool XGUI_OperationMgr::canStartOperation(QString theId)
209 {
210   bool aCanStart = true;
211   ModuleBase_Operation* aCurrentOp = currentOperation();
212   if (aCurrentOp) {
213     if (!aCurrentOp->isGranted(theId)) {
214       if (canStopOperation()) {
215         if (myIsApplyEnabled)
216           aCurrentOp->commit();
217         else
218           aCurrentOp->abort();
219       } else {
220         aCanStart = false;
221       }
222     }
223   }
224   return aCanStart;
225 }
226
227
228 void XGUI_OperationMgr::onCommitOperation()
229 {
230   ModuleBase_Operation* anOperation = currentOperation();
231   if (anOperation)
232     anOperation->commit();
233 }
234
235 void XGUI_OperationMgr::onAbortOperation()
236 {
237   if (hasOperation() && canStopOperation()) {
238     currentOperation()->abort();
239   }
240 }
241
242 void XGUI_OperationMgr::onOperationStarted()
243 {
244   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
245   
246   bool isNestedOk = (myOperations.count() >= 1) && 
247                      myOperations.at(0)->isValid();
248   emit nestedStateChanged(isNestedOk);
249   emit operationStarted(aSenderOperation);
250 }
251
252 void XGUI_OperationMgr::onOperationAborted()
253 {
254   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
255   emit operationAborted(aSenderOperation);
256 }
257
258 void XGUI_OperationMgr::onOperationCommitted()
259 {
260   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
261   emit nestedStateChanged(myOperations.count() >= 1);
262   emit operationCommitted(aSenderOperation);
263 }
264
265 void XGUI_OperationMgr::onOperationResumed()
266 {
267   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
268   emit operationResumed(aSenderOperation);
269 }
270
271 void XGUI_OperationMgr::onOperationStopped()
272 {
273   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
274   ModuleBase_Operation* anOperation = currentOperation();
275   if (!aSenderOperation || !anOperation || aSenderOperation != anOperation)
276     return;
277
278   myOperations.removeAll(anOperation);
279   anOperation->deleteLater();
280
281   emit operationStopped(anOperation);
282
283   // get last operation which can be resumed
284   ModuleBase_Operation* aResultOp = 0;
285   QListIterator<ModuleBase_Operation*> anIt(myOperations);
286   anIt.toBack();
287   while (anIt.hasPrevious()) {
288     ModuleBase_Operation* anOp = anIt.previous();
289     if (anOp) {
290       aResultOp = anOp;
291       break;
292     }
293   }
294   if (aResultOp) {
295     resumeOperation(aResultOp);
296     onValidateOperation();
297   }
298 }
299
300 void XGUI_OperationMgr::onOperationTriggered(bool theState)
301 {
302   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
303   if (aSenderOperation && !theState) {
304     ModuleBase_Operation* aCurrentOperation = currentOperation();
305     if (aSenderOperation == aCurrentOperation)
306       aCurrentOperation->abort();
307     else {
308       // it is possible to trigger upper operation(e.g. sketch, current is sketch line)
309       // all operation from the current to triggered should also be aborted
310       while(hasOperation()) {
311         ModuleBase_Operation* aCurrentOperation = currentOperation();
312         aCurrentOperation->abort();
313         if(aSenderOperation == aCurrentOperation)
314           break;
315       }
316     }
317   }
318 }
319
320 bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent)
321 {
322   // Let the manager decide what to do with the given key combination.
323   ModuleBase_Operation* anOperation = currentOperation();
324   bool isAccepted = true;
325   switch (theEvent->key()) {
326     case Qt::Key_Return:
327     case Qt::Key_Enter: {
328       emit keyEnterReleased();
329       commitOperation();
330     }
331     break;
332     default:
333       isAccepted = false;
334       break;
335   }
336   //if(anOperation) {
337   //  anOperation->keyReleased(theEvent->key());
338   //}
339   return isAccepted;
340 }
341