Salome HOME
Issue #145 behavior on edit constraint corrected
[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 QStringList XGUI_OperationMgr::operationList()
42 {
43   QStringList result;
44   foreach(ModuleBase_Operation* eachOperation, myOperations) {
45     FeaturePtr aFeature = eachOperation->feature();
46     if(aFeature) {
47       result << QString::fromStdString(aFeature->getKind());
48     }
49   }
50   return result;
51 }
52
53 bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
54 {
55   if (theEvent->type() == QEvent::KeyRelease) {
56     QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
57     if(aKeyEvent) {
58       onKeyReleased(aKeyEvent);
59       return true;
60     }
61   }
62   return QObject::eventFilter(theObject, theEvent);
63 }
64
65 bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
66 {
67   if (!canStartOperation(theOperation))
68     return false;
69
70   myOperations.append(theOperation);
71
72   connect(theOperation, SIGNAL(stopped()), this, SLOT(onOperationStopped()));
73   connect(theOperation, SIGNAL(started()), this, SIGNAL(operationStarted()));
74   connect(theOperation, SIGNAL(resumed()), this, SIGNAL(operationResumed()));
75   connect(theOperation, SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)), this,
76           SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)));
77
78   theOperation->start();
79   onValidateOperation();
80   return true;
81 }
82
83 bool XGUI_OperationMgr::abortAllOperations()
84 {
85   if(!hasOperation()) {
86     return true;
87   } else if (operationsCount() == 1) {
88     onAbortOperation();
89     return true;
90   }
91   QString aMessage = tr("All active operations will be aborted.");
92   int anAnswer = QMessageBox::question(qApp->activeWindow(),
93                                        tr("Abort operation"),
94                                        aMessage,
95                                        QMessageBox::Ok | QMessageBox::Cancel,
96                                        QMessageBox::Cancel);
97   bool result = anAnswer == QMessageBox::Ok;
98   while(result && hasOperation()) {
99     currentOperation()->abort();
100   }
101   return result;
102 }
103
104 bool XGUI_OperationMgr::validateOperation(ModuleBase_Operation* theOperation)
105 {
106   //Get operation feature to validate
107   FeaturePtr aFeature = theOperation->feature();
108   //Get validators for the Id
109   SessionPtr aMgr = ModelAPI_Session::get();
110   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
111
112   bool isValid = aFactory->validate(aFeature);
113   emit operationValidated(isValid);
114   return isValid;
115 }
116
117 void XGUI_OperationMgr::onValidateOperation()
118 {
119   if (!hasOperation())
120     return;
121   ModuleBase_Operation* anOperation = currentOperation();
122   validateOperation(currentOperation());
123 }
124
125 bool XGUI_OperationMgr::commitOperation()
126 {
127   if (validateOperation(currentOperation())) {
128     onCommitOperation();
129     return true;
130   }
131   return false;
132 }
133
134 void XGUI_OperationMgr::resumeOperation(ModuleBase_Operation* theOperation)
135 {
136   theOperation->resume();
137 }
138
139 bool XGUI_OperationMgr::canStartOperation(ModuleBase_Operation* theOperation)
140 {
141   bool aCanStart = true;
142   ModuleBase_Operation* aCurrentOp = currentOperation();
143   if (aCurrentOp) {
144     if (!theOperation->isGranted()) {
145       if (!aCurrentOp->isValid(theOperation)) {
146         if (canAbortOperation()) {
147           aCurrentOp->abort();
148         } else {
149           aCanStart = false;
150         }
151       }
152     }
153   }
154   return aCanStart;
155 }
156
157
158 void XGUI_OperationMgr::onCommitOperation()
159 {
160   ModuleBase_Operation* anOperation = currentOperation();
161   if (anOperation)
162     anOperation->commit();
163 }
164
165 void XGUI_OperationMgr::onAbortOperation()
166 {
167   if (hasOperation() && canAbortOperation()) {
168     currentOperation()->abort();
169   }
170 }
171
172 bool XGUI_OperationMgr::canAbortOperation()
173 {
174   ModuleBase_Operation* anOperation = currentOperation();
175   if(operationsCount() > 1) //in case of nested (sketch) operation no confirmation needed
176     return true;
177   if (anOperation && anOperation->isModified()) {
178     QString aMessage = tr("%1 operation will be aborted.").arg(anOperation->id());
179     int anAnswer = QMessageBox::question(qApp->activeWindow(),
180                                          tr("Abort operation"),
181                                          aMessage,
182                                          QMessageBox::Ok | QMessageBox::Cancel,
183                                          QMessageBox::Cancel);
184     return anAnswer == QMessageBox::Ok;
185   }
186   return true;
187 }
188
189 void XGUI_OperationMgr::onOperationStopped()
190 {
191   ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
192   ModuleBase_Operation* anOperation = currentOperation();
193   if (!aSenderOperation || !anOperation || aSenderOperation != anOperation)
194     return;
195
196   myOperations.removeAll(anOperation);
197   anOperation->deleteLater();
198
199   emit operationStopped(anOperation);
200
201   // get last operation which can be resumed
202   ModuleBase_Operation* aResultOp = 0;
203   QListIterator<ModuleBase_Operation*> anIt(myOperations);
204   anIt.toBack();
205   while (anIt.hasPrevious()) {
206     ModuleBase_Operation* anOp = anIt.previous();
207     if (anOp) {
208       aResultOp = anOp;
209       break;
210     }
211   }
212   if (aResultOp) {
213     resumeOperation(aResultOp);
214     onValidateOperation();
215   }
216 }
217
218 void XGUI_OperationMgr::onKeyReleased(QKeyEvent* theEvent)
219 {
220   // Let the manager decide what to do with the given key combination.
221   ModuleBase_Operation* anOperation = currentOperation();
222   bool isRestart = false;
223   switch (theEvent->key()) {
224     case Qt::Key_Escape: {
225       onAbortOperation();
226     }
227       break;
228     case Qt::Key_Return:
229     case Qt::Key_Enter: {
230       if(anOperation) {
231          anOperation->activateNextToCurrentWidget();
232       }
233       commitOperation();
234     }
235       break;
236     default:
237       break;
238   }
239   if(anOperation)
240     anOperation->keyReleased(theEvent->key());
241 }
242
243 void XGUI_OperationMgr::onWidgetActivated(ModuleBase_ModelWidget* theWidget)
244 {
245   ModuleBase_Operation* anOperation = currentOperation();
246   if (anOperation)
247     anOperation->onWidgetActivated(theWidget);
248 }