Salome HOME
d992333820496c2117ac656e657cec906f0de15b
[modules/gui.git] / src / SUIT / SUIT_Study.cxx
1 #include "SUIT_Study.h"
2
3 #include "SUIT_Desktop.h"
4 #include "SUIT_Operation.h"
5 #include "SUIT_DataObject.h"
6 #include "SUIT_MessageBox.h"
7 #include "SUIT_Application.h"
8 #include <qvaluevector.h>
9
10 /*!\class SUIT_Study
11  * Support study management. Object management. Operation management.
12  */
13
14 /*!Constructor.*/
15 SUIT_Study::SUIT_Study( SUIT_Application* app )
16 : QObject(),
17 myApp( app ),
18 myIsSaved( false ),
19 myIsModified( false ),
20 myName( "" ),
21 myBlockChangeState( false )
22 {
23   static int _id = 0;
24
25   myId = ++_id;
26
27   myRoot = new SUIT_DataObject();
28   myOperations.setAutoDelete( false );
29   myOperations.setAutoDelete( false );
30 }
31
32 /*!Destructor.*/
33 SUIT_Study::~SUIT_Study()
34 {
35   delete myRoot;
36   myRoot = 0;
37 }
38
39 /*!
40  *\retval study id.
41  */
42 int SUIT_Study::id() const
43 {
44   return myId;
45 }
46
47 /*!
48  *\retval root data object.
49  */
50 SUIT_DataObject* SUIT_Study::root() const
51 {
52   return myRoot;
53 }
54
55 /*!
56  *\retval Application.
57  */
58 SUIT_Application* SUIT_Study::application() const
59 {
60   return myApp;
61 }
62
63 /*!
64  *\retval study name
65  */
66 QString SUIT_Study::studyName() const
67 {
68   return myName;
69 }
70
71 /*!
72  *\retval active operation.
73  */
74 SUIT_Operation* SUIT_Study::activeOperation() const
75 {
76   return myOperations.count() > 0 ? myOperations.getLast() : 0;
77 }
78
79 /*!
80  *\retval TRUE - if study saved, else FALSE.
81  */
82 bool SUIT_Study::isSaved() const
83 {
84   return myIsSaved;
85 }
86
87 /*!
88  *\retval TRUE - if study modified, else FALSE.
89  */
90 bool SUIT_Study::isModified() const
91 {
92   return myIsModified;
93 }
94
95 /*!
96  *Close document. NOT IMPLEMENTED.
97  */
98 void SUIT_Study::closeDocument(bool permanently)
99 {
100 }
101
102 void SUIT_Study::createDocument()
103 {
104   /*! Custom document initialization to be performed \n
105    *  within onNewDoc() handler can be put here
106    */
107 }
108
109 /*!
110  * Open document. Sets file name. return true.
111  */
112 bool SUIT_Study::openDocument( const QString& fileName )
113 {
114   myName = fileName;
115   myIsSaved = true;
116   myIsModified = false;
117
118   return true;
119 }
120
121 /*!
122  * Save document as \a fileName. Set file name.
123  */
124 bool SUIT_Study::saveDocumentAs( const QString& fileName )
125 {
126   myName = fileName;
127   myIsSaved = true;
128   myIsModified = false;
129
130   return true;
131 }
132
133 /*!
134  *\retval TRUE - if document saved successful, else FALSE.
135  */
136 bool SUIT_Study::saveDocument()
137 {
138   return saveDocumentAs( myName );
139 }
140
141 /*!
142  *Abort all operations.
143  */
144 void SUIT_Study::abortAllOperations()
145 {
146   myBlockChangeState = true;
147   for( SUIT_Operation* op = myOperations.first(); op; op = myOperations.next() )
148     op->abort();
149   myBlockChangeState = false;
150   myOperations.clear();
151 }
152
153 /*!
154   Update study. NOT IMPLEMENTED HERE.
155  */
156 void SUIT_Study::update()
157 {
158 }
159
160 /*!
161   Emit study modified.
162  */
163 void SUIT_Study::sendChangesNotification()
164 {
165   emit studyModified( this );
166 }
167
168 /*!
169   Set study saved to \a on.
170  */
171 void SUIT_Study::setIsSaved( const bool on )
172 {
173   myIsSaved = on;
174 }
175
176 /*!
177   Set study modified to \a on.
178  */
179 void SUIT_Study::setIsModified( const bool on )
180 {
181   myIsModified = on;
182 }
183
184 /*!
185   Set root object.
186  */
187 void SUIT_Study::setRoot( SUIT_DataObject* obj )
188 {
189   if ( myRoot == obj )
190     return;
191
192   // This is necessary in order not to destroy the complete tree of objects
193   if ( obj )
194     obj->reparentChildren( myRoot );
195
196   delete myRoot;
197   myRoot = obj;
198 }
199
200 /*!
201   Set study name.
202  */
203 void SUIT_Study::setStudyName( const QString& name )
204 {
205   myName = name;
206 }
207
208 /*!
209  * \brief Verifies whether operation can be activated above already started ones
210   * \param theOp - operation to be checked
211   * \return NULL if operation can be activated, pointer to operation which denies
212   * starting tested operation
213 *
214 * Verifies whether operation can be activated above already started ones. This method
215 * is called from SUIT_Study::start() and SUIT_Study::resume() methods.
216 */
217 SUIT_Operation* SUIT_Study::blockingOperation( SUIT_Operation* theOp ) const
218 {
219   if( theOp->isGranted() )
220     return 0;
221
222   Operations tmpOps( myOperations );
223   SUIT_Operation* anOp = 0;
224   for ( anOp = tmpOps.last(); anOp; anOp = tmpOps.prev() )
225   {
226     if ( anOp != 0 && anOp!= theOp && !anOp->isValid( theOp ) )
227       return anOp;
228   }
229
230   return 0;
231 }
232
233 /*!
234  * \brief Starts operation
235   * \param theOp - operation to be started
236   * \param toCheck - if parameters is equal TRUE then checking performed whether
237   * all already started operations allow to start this operation above them (default
238   * value is TRUE
239   * \return TRUE if operation is started, FALSE otherwise
240 *
241 * Verifies whether theOp operation can be started above already started ones (if toCheck
242 * parameter is equal TRUE) and starts it
243 */
244 bool SUIT_Study::start( SUIT_Operation* theOp, const bool toCheck )
245 {
246   if ( !theOp || myOperations.find( theOp ) >= 0 )
247     return false;
248
249   theOp->setExecStatus( SUIT_Operation::Rejected );
250   theOp->setStudy( this );
251
252   if ( !theOp->isReadyToStart() )
253     return false;
254
255   if ( toCheck )
256   {
257     while( SUIT_Operation* anOp = blockingOperation( theOp ) )
258     {
259       int anAnsw = SUIT_MessageBox::warn2( application()->desktop(),
260          tr( "OPERATION_LAUNCH" ), tr( "PREVIOUS_NOT_FINISHED" ),
261          tr( "CONTINUE" ), tr( "CANCEL" ), 0, 1, 1 );
262
263       if( anAnsw == 1 )
264         return false;
265       else
266         anOp->abort();
267     }
268   }
269
270   SUIT_Operation* anOp = activeOperation();
271   if ( anOp )
272   {
273     activeOperation()->suspendOperation();
274     anOp->setState( SUIT_Operation::Suspended );
275   }
276
277   theOp->setState( SUIT_Operation::Running );
278   myOperations.append( theOp );
279   emit theOp->started( theOp );
280   theOp->startOperation();
281   
282   return true;
283 }
284
285 /*!
286  * \brief Aborts operation
287   * \param theOp - operation to be aborted
288   * \return TRUE if operation is aborted successfully
289 *
290 * Verifies whether operation already started and aborts it in this case (sets execution
291 * status to Rejected and stops operation)
292 */
293 bool SUIT_Study::abort( SUIT_Operation* theOp )
294 {
295   if ( !theOp || myOperations.find( theOp ) == -1 )
296     return false;
297
298   theOp->abortOperation();
299   theOp->setExecStatus( SUIT_Operation::Rejected );
300   emit theOp->aborted( theOp );
301   stop( theOp );
302   return true;
303 }
304
305 /*!
306  * \brief Commits operation
307   * \param theOp - operation to be committed
308   * \return TRUE if operation is committed successfully
309 *
310 * Verifies whether operation already started and commits it in this case (sets execution
311 * status to Accepted and stops operation)
312 */
313 bool SUIT_Study::commit( SUIT_Operation* theOp )
314 {
315   if ( !theOp || myOperations.find( theOp ) == -1 )
316     return false;
317
318   theOp->commitOperation();
319   theOp->setExecStatus( SUIT_Operation::Accepted );
320   emit theOp->committed( theOp );
321   stop( theOp );
322   emit studyModified( this );
323   return true;
324 }
325
326 /*!
327  * \brief Commits operation
328   * \param theOp - operation to be committed
329   * \return TRUE if operation is suspended successfully
330 *
331 * Verifies whether operation already started and suspends it in this case. Operations
332 * ususlly are suspended to start other one above them.
333 */
334 bool SUIT_Study::suspend( SUIT_Operation* theOp )
335 {
336   if ( !theOp || myOperations.find( theOp ) == -1 || theOp->state() == SUIT_Operation::Suspended )
337     return false;
338
339   theOp->setState( SUIT_Operation::Suspended );
340   theOp->suspendOperation();
341   emit theOp->suspended( theOp );
342   return true;
343 }
344
345
346 /*!
347  * \brief Resumes operation
348   * \param theOp - operation to be resumed
349   * \return TRUE if operation is aborted successfully
350 *
351 * Verifies whether operation already started but suspended and resumesit in this case.
352 */
353 bool SUIT_Study::resume( SUIT_Operation* theOp )
354 {
355   if ( !theOp || myOperations.find( theOp ) == -1 ||
356        theOp->state() == SUIT_Operation::Running ||
357        blockingOperation( theOp ) != 0 )
358     return false;
359
360   if ( myOperations.count() > 0 )
361     suspend( myOperations.last() );
362
363   theOp->setState( SUIT_Operation::Running );
364   theOp->resumeOperation();
365
366   // Move operation at the end of list in order to sort it in the order of activation.
367   // As result active operation is a last operation of list, operation which was active
368   // before currently active operation is located before it and so on
369   myOperations.remove( theOp );
370   myOperations.append( theOp );
371
372   emit theOp->resumed( theOp );
373   return true;
374 }
375
376 /*!
377  * \brief Stops operation
378   * \param theOp - operation to be stopped
379 *
380 * Stops operation. This private method is called from abort() and commit() ones to perform
381 * common actions when operation is stopped
382 */
383 void SUIT_Study::stop( SUIT_Operation* theOp )
384 {
385   theOp->setState( SUIT_Operation::Waiting );
386   myOperations.remove( theOp );
387
388   // get last operation which can be resumed
389   SUIT_Operation* anOp, *aResultOp = 0;
390   for( anOp = myOperations.last(); anOp; anOp = myOperations.prev() )
391     if ( anOp && anOp != theOp && blockingOperation( anOp ) == 0 )
392     {
393       aResultOp = anOp;
394       break;
395     }
396
397   emit theOp->stopped( theOp );
398   if ( aResultOp )
399     resume( aResultOp );
400 }
401
402 /*!
403  * \brief Get all started operations
404   * \return List of all started operations
405 */
406 const QPtrList<SUIT_Operation>& SUIT_Study::operations() const
407 {
408   return myOperations;
409 }
410
411
412
413
414
415
416
417
418
419