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