Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[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(activatedByPreselection()),
109           SIGNAL(operationActivatedByPreselection()));
110
111   theOperation->start();
112   onValidateOperation();
113   return true;
114 }
115
116 bool XGUI_OperationMgr::abortAllOperations()
117 {
118   if(!hasOperation()) {
119     return true;
120   } else if (operationsCount() == 1) {
121     onAbortOperation();
122     return true;
123   }
124   QString aMessage = tr("All active operations will be aborted.");
125   int anAnswer = QMessageBox::question(qApp->activeWindow(),
126                                        tr("Abort operation"),
127                                        aMessage,
128                                        QMessageBox::Ok | QMessageBox::Cancel,
129                                        QMessageBox::Cancel);
130   bool result = anAnswer == QMessageBox::Ok;
131   while(result && hasOperation()) {
132     currentOperation()->abort();
133   }
134   return result;
135 }
136
137 bool XGUI_OperationMgr::commitAllOperations()
138 {
139   while (hasOperation()) {
140     if (isApplyEnabled()) {
141       onCommitOperation();
142     } else {
143       currentOperation()->abort();
144     }
145   }
146   return true;
147 }
148
149 void XGUI_OperationMgr::onValidateOperation()
150 {
151   if (!hasOperation())
152     return;
153   ModuleBase_Operation* anOperation = currentOperation();
154   if(anOperation && (!myIsValidationLock)) {
155     setApplyEnabled(anOperation->isValid());
156   }
157 }
158
159 void XGUI_OperationMgr::setApplyEnabled(const bool theEnabled)
160 {
161   myIsApplyEnabled = theEnabled;
162   emit validationStateChanged(theEnabled);
163 }
164
165 bool XGUI_OperationMgr::isApplyEnabled() const
166 {
167   return myIsApplyEnabled;
168 }
169
170 bool XGUI_OperationMgr::canStopOperation()
171 {
172   ModuleBase_Operation* anOperation = currentOperation();
173   if(operationsCount() > 1) //in case of nested (sketch) operation no confirmation needed
174     return true;
175   if (anOperation && anOperation->isModified()) {
176     QString aMessage = tr("%1 operation will be aborted.").arg(anOperation->id());
177     int anAnswer = QMessageBox::question(qApp->activeWindow(),
178                                          tr("Abort operation"),
179                                          aMessage,
180                                          QMessageBox::Ok | QMessageBox::Cancel,
181                                          QMessageBox::Cancel);
182     return anAnswer == QMessageBox::Ok;
183   }
184   return true;
185 }
186
187 bool XGUI_OperationMgr::commitOperation()
188 {
189   if (hasOperation() && currentOperation()->isValid()) {
190     onCommitOperation();
191     return true;
192   }
193   return false;
194 }
195
196 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
197 {
198   theOperation->resume();
199 }
200
201 bool XGUI_OperationMgr::canStartOperation(QString theId)
202 {
203   bool aCanStart = true;
204   ModuleBase_Operation* aCurrentOp = currentOperation();
205   if (aCurrentOp) {
206     if (!aCurrentOp->isGranted(theId)) {
207       if (canStopOperation()) {
208         if (myIsApplyEnabled)
209           aCurrentOp->commit();
210         else
211           aCurrentOp->abort();
212       } else {
213         aCanStart = false;
214       }
215     }
216   }
217   return aCanStart;
218 }
219
220
221 void XGUI_OperationMgr::onCommitOperation()
222 {
223   ModuleBase_Operation* anOperation = currentOperation();
224   if (anOperation)
225     anOperation->commit();
226 }
227
228 void XGUI_OperationMgr::onAbortOperation()
229 {
230   if (hasOperation() && canStopOperation()) {
231     currentOperation()->abort();
232   }
233 }
234
235 void XGUI_OperationMgr::onOperationStarted()
236 {
237   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
238   
239   bool isNestedOk = (myOperations.count() >= 1) && 
240                      myOperations.at(0)->isValid();
241   emit nestedStateChanged(isNestedOk);
242   emit operationStarted(aSenderOperation);
243 }
244
245 void XGUI_OperationMgr::onOperationAborted()
246 {
247   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
248   emit operationAborted(aSenderOperation);
249 }
250
251 void XGUI_OperationMgr::onOperationCommitted()
252 {
253   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
254   emit nestedStateChanged(myOperations.count() >= 1);
255   emit operationCommitted(aSenderOperation);
256 }
257
258 void XGUI_OperationMgr::onOperationResumed()
259 {
260   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
261   emit operationResumed(aSenderOperation);
262 }
263
264 void XGUI_OperationMgr::onOperationStopped()
265 {
266   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
267   ModuleBase_Operation* anOperation = currentOperation();
268   if (!aSenderOperation || !anOperation || aSenderOperation != anOperation)
269     return;
270
271   myOperations.removeAll(anOperation);
272   anOperation->deleteLater();
273
274   emit operationStopped(anOperation);
275
276   // get last operation which can be resumed
277   ModuleBase_Operation* aResultOp = 0;
278   QListIterator<ModuleBase_Operation*> anIt(myOperations);
279   anIt.toBack();
280   while (anIt.hasPrevious()) {
281     ModuleBase_Operation* anOp = anIt.previous();
282     if (anOp) {
283       aResultOp = anOp;
284       break;
285     }
286   }
287   if (aResultOp) {
288     resumeOperation(aResultOp);
289     onValidateOperation();
290   }
291 }
292
293 bool XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent)
294 {
295   // Let the manager decide what to do with the given key combination.
296   ModuleBase_Operation* anOperation = currentOperation();
297   bool isAccepted = true;
298   switch (theEvent->key()) {
299     case Qt::Key_Return:
300     case Qt::Key_Enter: {
301       emit keyEnterReleased();
302       commitOperation();
303     }
304     break;
305     default:
306       isAccepted = false;
307       break;
308   }
309   //if(anOperation) {
310   //  anOperation->keyReleased(theEvent->key());
311   //}
312   return isAccepted;
313 }
314