Salome HOME
refs #156: Behavior of the Sketch during edition
[modules/shaper.git] / src / ModuleBase / ModuleBase_Operation.cpp
1 /*
2  * ModuleBase_Operation.cpp
3  *
4  *  Created on: Apr 2, 2014
5  *      Author: sbh
6  */
7
8 #include "ModuleBase_Operation.h"
9
10 #include "ModuleBase_OperationDescription.h"
11 #include "ModuleBase_ModelWidget.h"
12 #include "ModuleBase_WidgetValueFeature.h"
13 #include "ModuleBase_ViewerPrs.h"
14 #include "ModuleBase_IPropertyPanel.h"
15 #include "ModuleBase_ISelection.h"
16
17 #include <ModelAPI_AttributeDouble.h>
18 #include <ModelAPI_Document.h>
19 #include <ModelAPI_Feature.h>
20 #include <ModelAPI_Data.h>
21 #include <ModelAPI_Document.h>
22 #include <ModelAPI_Events.h>
23 #include <ModelAPI_Result.h>
24 #include <ModelAPI_Object.h>
25 #include <ModelAPI_Validator.h>
26 #include <ModelAPI_Session.h>
27
28 #include <GeomAPI_Pnt2d.h>
29
30 #include <Events_Loop.h>
31
32 #ifdef _DEBUG
33 #include <QDebug>
34 #endif
35
36 ModuleBase_Operation::ModuleBase_Operation(const QString& theId, QObject* theParent)
37     : QObject(theParent),
38       myIsEditing(false),
39       myIsModified(false),
40       myPropertyPanel(NULL)
41 {
42   myDescription = new ModuleBase_OperationDescription(theId);
43 }
44
45 ModuleBase_Operation::~ModuleBase_Operation()
46 {
47   delete myDescription;
48 }
49
50 QString ModuleBase_Operation::id() const
51 {
52   return getDescription()->operationId();
53 }
54
55 FeaturePtr ModuleBase_Operation::feature() const
56 {
57   return myFeature;
58 }
59
60 bool ModuleBase_Operation::isValid() const
61 {
62   if (!myFeature)
63     return true; // rename operation
64   //Get validators for the Id
65   SessionPtr aMgr = ModelAPI_Session::get();
66   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
67   return aFactory->validate(myFeature);
68 }
69
70 bool ModuleBase_Operation::isNestedOperationsEnabled() const
71 {
72   return true;
73 }
74
75 void ModuleBase_Operation::storeCustomValue()
76 {
77   if (!myFeature) {
78 #ifdef _DEBUG
79     qDebug() << "ModuleBase_Operation::storeCustom: " <<
80     "trying to store value without opening a transaction.";
81 #endif
82     return;
83   }
84
85   ModuleBase_ModelWidget* aCustom = dynamic_cast<ModuleBase_ModelWidget*>(sender());
86   if (aCustom)
87     aCustom->storeValue();
88 }
89
90 void ModuleBase_Operation::startOperation()
91 {
92   if (!myIsEditing)
93     createFeature();
94 }
95
96 void ModuleBase_Operation::stopOperation()
97 {
98 }
99
100 void ModuleBase_Operation::abortOperation()
101 {
102 }
103
104 void ModuleBase_Operation::commitOperation()
105 {
106 }
107
108 void ModuleBase_Operation::afterCommitOperation()
109 {
110 }
111
112 bool ModuleBase_Operation::canBeCommitted() const
113 {
114   return true;
115 }
116
117 void ModuleBase_Operation::flushUpdated()
118 {
119   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
120 }
121
122 void ModuleBase_Operation::flushCreated()
123 {
124   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
125 }
126
127 FeaturePtr ModuleBase_Operation::createFeature(
128   const bool theFlushMessage, CompositeFeaturePtr theCompositeFeature)
129 {
130   if (theCompositeFeature) {
131     myFeature = theCompositeFeature->addFeature(getDescription()->operationId().toStdString());
132   } else {
133     boost::shared_ptr<ModelAPI_Document> aDoc = document();
134     myFeature = aDoc->addFeature(getDescription()->operationId().toStdString());
135   }
136   if (myFeature) {  // TODO: generate an error if feature was not created
137     myIsModified = true;
138     // Model update should call "execute" of a feature.
139     //myFeature->execute();
140     // Init default values
141     /*QList<ModuleBase_ModelWidget*> aWidgets = getDescription()->modelWidgets();
142      QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
143      for (; anIt != aLast; anIt++) {
144      (*anIt)->storeValue(aFeature);
145      }*/
146   }
147
148   if (theFlushMessage)
149     flushCreated();
150   return myFeature;
151 }
152
153 void ModuleBase_Operation::setFeature(FeaturePtr theFeature)
154 {
155   myFeature = theFeature;
156   myIsEditing = true;
157 }
158
159 bool ModuleBase_Operation::hasObject(ObjectPtr theObj) const
160 {
161   FeaturePtr aFeature = feature();
162   if (aFeature) {
163     if (aFeature == theObj)
164       return true;
165     std::list<ResultPtr> aResults = aFeature->results();
166     std::list<ResultPtr>::const_iterator aIt;
167     for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
168       if ((*aIt) == theObj)
169         return true;
170     }
171   }
172   return false;
173 }
174
175
176 boost::shared_ptr<ModelAPI_Document> ModuleBase_Operation::document() const
177 {
178   return ModelAPI_Session::get()->moduleDocument();
179 }
180
181
182 void ModuleBase_Operation::start()
183 {
184   ModelAPI_Session::get()->startOperation();
185
186   startOperation();
187   emit started();
188 }
189
190 void ModuleBase_Operation::resume()
191 {
192   if (myPropertyPanel)
193     connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
194             this,            SLOT(onWidgetActivated(ModuleBase_ModelWidget*)));
195   emit resumed();
196 }
197
198 void ModuleBase_Operation::abort()
199 {
200   abortOperation();
201   emit aborted();
202   if (myPropertyPanel)
203     disconnect(myPropertyPanel, 0, this, 0);
204
205   stopOperation();
206
207   ModelAPI_Session::get()->abortOperation();
208   emit stopped();
209 }
210
211 bool ModuleBase_Operation::commit()
212 {
213   if (canBeCommitted()) {
214     commitOperation();
215     emit committed();
216
217   if (myPropertyPanel)
218     disconnect(myPropertyPanel, 0, this, 0);
219
220     stopOperation();
221     ModelAPI_Session::get()->finishOperation();
222
223     emit stopped();
224
225     afterCommitOperation();
226     return true;
227   }
228   return false;
229 }
230
231 void ModuleBase_Operation::setRunning(bool theState)
232 {
233   if (!theState) {
234     abort();
235   }
236 }
237
238 bool ModuleBase_Operation::activateByPreselection()
239 {
240   if (!myPropertyPanel)
241     return false;
242   if (myPreSelection.empty())
243     return false;
244   const QList<ModuleBase_ModelWidget*>& aWidgets = myPropertyPanel->modelWidgets();
245   if (aWidgets.empty())
246     return false;
247   
248   ModuleBase_ModelWidget* aWgt;
249   ModuleBase_ViewerPrs aPrs;
250   QList<ModuleBase_ModelWidget*>::const_iterator aWIt;
251   QList<ModuleBase_ViewerPrs>::const_iterator aPIt;
252   for (aWIt = aWidgets.constBegin(), aPIt = myPreSelection.constBegin();
253        (aWIt != aWidgets.constEnd()) && (aPIt != myPreSelection.constEnd());
254        ++aWIt, ++aPIt) {
255     aWgt = (*aWIt);
256     aPrs = (*aPIt);
257     ModuleBase_WidgetValueFeature aValue;
258     aValue.setObject(aPrs.object());
259     if (!aWgt->setValue(&aValue))
260       break;
261   }
262   if (canBeCommitted()) {
263     // if all widgets are filled with selection
264     commit();
265     return true;
266   }
267
268   //ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
269   //if ((myPreSelection.size() > 0) && aActiveWgt) {
270   //  const ModuleBase_ViewerPrs& aPrs = myPreSelection.first();
271   //  ModuleBase_WidgetValueFeature aValue;
272   //  aValue.setObject(aPrs.object());
273   //  if (aActiveWgt->setValue(&aValue)) {
274   //    myPreSelection.removeOne(aPrs);
275   //    myPropertyPanel->activateNextWidget();
276   //  }
277   //  // If preselection is enough to make a valid feature - apply it immediately
278   //}
279   return false;
280 }
281
282 void ModuleBase_Operation::initSelection(ModuleBase_ISelection* theSelection,
283                                          ModuleBase_IViewer* /*theViewer*/)
284 {
285   myPreSelection.clear();
286
287   // Check that the selected result are not results of operation feature
288   QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
289   FeaturePtr aFeature = feature();
290   if (aFeature) {
291     std::list<ResultPtr> aResults = aFeature->results();
292     QList<ObjectPtr> aResList;
293     std::list<ResultPtr>::const_iterator aIt;
294     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt)
295       aResList.append(*aIt);
296
297     foreach (ModuleBase_ViewerPrs aPrs, aSelected) {
298       if ((!aResList.contains(aPrs.object())) && (aPrs.object() != aFeature))
299         myPreSelection.append(aPrs);
300     }
301   } else
302     myPreSelection = aSelected;
303 }
304
305 void ModuleBase_Operation::onWidgetActivated(ModuleBase_ModelWidget* theWidget)
306 {
307   //activateByPreselection();
308   //if (theWidget && myPropertyPanel) {
309   //  myPropertyPanel->activateNextWidget();
310   ////  //emit activateNextWidget(myActiveWidget);
311   //}
312 }
313
314 bool ModuleBase_Operation::setWidgetValue(ObjectPtr theFeature, double theX, double theY)
315 {
316   ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
317   if (!aActiveWgt)
318     return false;
319   ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature();
320   aValue->setObject(theFeature);
321   aValue->setPoint(boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY)));
322   bool isApplyed = aActiveWgt->setValue(aValue);
323
324   delete aValue;
325   myIsModified = (myIsModified || isApplyed);
326   return isApplyed;
327 }
328
329
330 void ModuleBase_Operation::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) 
331
332   myPropertyPanel = theProp; 
333   connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), this,
334           SLOT(onWidgetActivated(ModuleBase_ModelWidget*)));
335 }