]> SALOME platform Git repositories - modules/gui.git/blob - src/SUIT/SUIT_Study.cxx
Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/gui.git] / src / SUIT / SUIT_Study.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "SUIT_Study.h"
20
21 #include "SUIT_Desktop.h"
22 #include "SUIT_Operation.h"
23 #include "SUIT_DataObject.h"
24 #include "SUIT_MessageBox.h"
25 #include "SUIT_Application.h"
26 #include <qvaluevector.h>
27
28 /*!\class SUIT_Study
29  * Support study management. Object management. Operation management.
30  */
31
32 /*!Constructor.*/
33 SUIT_Study::SUIT_Study( SUIT_Application* app )
34 : QObject(),
35 myApp( app ),
36 myIsSaved( false ),
37 myIsModified( false ),
38 myName( "" ),
39 myBlockChangeState( false )
40 {
41   static int _id = 0;
42
43   myId = ++_id;
44
45   myRoot = new SUIT_DataObject();
46   myOperations.setAutoDelete( false );
47   myOperations.setAutoDelete( false );
48 }
49
50 /*!Destructor.*/
51 SUIT_Study::~SUIT_Study()
52 {
53   delete myRoot;
54   myRoot = 0;
55 }
56
57 /*!
58  *\retval study id.
59  */
60 int SUIT_Study::id() const
61 {
62   return myId;
63 }
64
65 /*!
66  *\retval root data object.
67  */
68 SUIT_DataObject* SUIT_Study::root() const
69 {
70   return myRoot;
71 }
72
73 /*!
74  *\retval Application.
75  */
76 SUIT_Application* SUIT_Study::application() const
77 {
78   return myApp;
79 }
80
81 /*!
82  *\retval study name
83  */
84 QString SUIT_Study::studyName() const
85 {
86   return myName;
87 }
88
89 /*!
90  *\retval active operation.
91  */
92 SUIT_Operation* SUIT_Study::activeOperation() const
93 {
94   return myOperations.count() > 0 ? myOperations.getLast() : 0;
95 }
96
97 /*!
98  *\retval TRUE - if study saved, else FALSE.
99  */
100 bool SUIT_Study::isSaved() const
101 {
102   return myIsSaved;
103 }
104
105 /*!
106  *\retval TRUE - if study modified, else FALSE.
107  */
108 bool SUIT_Study::isModified() const
109 {
110   return myIsModified;
111 }
112
113 /*!
114  *Close document. NOT IMPLEMENTED.
115  */
116 void SUIT_Study::closeDocument(bool permanently)
117 {
118 }
119
120 /*!
121   Custom document initialization to be performed \n
122    within onNewDoc() handler can be put here
123 */
124 void SUIT_Study::createDocument()
125 {
126 }
127
128 /*!
129  * Open document. Sets file name. return true.
130  */
131 bool SUIT_Study::openDocument( const QString& fileName )
132 {
133   myName = fileName;
134   myIsSaved = true;
135   myIsModified = false;
136
137   return true;
138 }
139
140 /*!
141  * Save document as \a fileName. Set file name.
142  */
143 bool SUIT_Study::saveDocumentAs( const QString& fileName )
144 {
145   myName = fileName;
146   myIsSaved = true;
147   myIsModified = false;
148
149   return true;
150 }
151
152 /*!
153  *\retval TRUE - if document saved successful, else FALSE.
154  */
155 bool SUIT_Study::saveDocument()
156 {
157   return saveDocumentAs( myName );
158 }
159
160 /*!
161  *Abort all operations.
162  */
163 void SUIT_Study::abortAllOperations()
164 {
165   myBlockChangeState = true;
166   for( SUIT_Operation* op = myOperations.first(); op; op = myOperations.next() )
167     op->abort();
168   myBlockChangeState = false;
169   myOperations.clear();
170 }
171
172 /*!
173   Update study. NOT IMPLEMENTED HERE.
174  */
175 void SUIT_Study::update()
176 {
177 }
178
179 /*!
180   Emit study modified.
181  */
182 void SUIT_Study::sendChangesNotification()
183 {
184   emit studyModified( this );
185 }
186
187 /*!
188   Set study saved to \a on.
189  */
190 void SUIT_Study::setIsSaved( const bool on )
191 {
192   myIsSaved = on;
193 }
194
195 /*!
196   Set study modified to \a on.
197  */
198 void SUIT_Study::setIsModified( const bool on )
199 {
200   myIsModified = on;
201 }
202
203 /*!
204   Set study modified to \a on.
205  */
206 void SUIT_Study::Modified()
207 {
208   setIsModified( TRUE );
209   sendChangesNotification();
210 }
211
212 /*!
213   Set root object.
214  */
215 void SUIT_Study::setRoot( SUIT_DataObject* obj )
216 {
217   if ( myRoot == obj )
218     return;
219
220   // This is necessary in order not to destroy the complete tree of objects
221   if ( obj )
222     obj->reparentChildren( myRoot );
223
224   delete myRoot;
225   myRoot = obj;
226 }
227
228 /*!
229   Set study name.
230  */
231 void SUIT_Study::setStudyName( const QString& name )
232 {
233   myName = name;
234 }
235
236 /*!
237  * \brief Verifies whether operation can be activated above already started ones
238   * \param theOp - operation to be checked
239   * \return NULL if operation can be activated, pointer to operation which denies
240   * starting tested operation
241 *
242 * Verifies whether operation can be activated above already started ones. This method
243 * is called from SUIT_Study::start() and SUIT_Study::resume() methods.
244 */
245 SUIT_Operation* SUIT_Study::blockingOperation( SUIT_Operation* theOp ) const
246 {
247   if( theOp->isGranted() )
248     return 0;
249
250   Operations tmpOps( myOperations );
251   SUIT_Operation* anOp = 0;
252   for ( anOp = tmpOps.last(); anOp; anOp = tmpOps.prev() )
253   {
254     if ( anOp != 0 && anOp!= theOp && !anOp->isValid( theOp ) )
255       return anOp;
256   }
257
258   return 0;
259 }
260
261 /*!
262  * \brief Starts operation
263   * \param theOp - operation to be started
264   * \param toCheck - if parameters is equal TRUE then checking performed whether
265   * all already started operations allow to start this operation above them (default
266   * value is TRUE
267   * \return TRUE if operation is started, FALSE otherwise
268 *
269 * Verifies whether theOp operation can be started above already started ones (if toCheck
270 * parameter is equal TRUE) and starts it
271 */
272 bool SUIT_Study::start( SUIT_Operation* theOp, const bool toCheck )
273 {
274   if ( !theOp || myOperations.find( theOp ) >= 0 )
275     return false;
276
277   theOp->setExecStatus( SUIT_Operation::Rejected );
278   theOp->setStudy( this );
279
280   if ( !theOp->isReadyToStart() )
281     return false;
282
283   if ( toCheck )
284   {
285     while( SUIT_Operation* anOp = blockingOperation( theOp ) )
286     {
287       int anAnsw = SUIT_MessageBox::warn2( application()->desktop(),
288                                            tr( "OPERATION_LAUNCH" ), tr( "PREVIOUS_NOT_FINISHED" ),
289                                            tr( "CONTINUE" ), tr( "CANCEL" ), 0, 1, 1 );
290
291       if ( anAnsw == 1 )
292         return false;
293       else
294         anOp->abort();
295     }
296   }
297
298   SUIT_Operation* anOp = activeOperation();
299   if ( anOp )
300   {
301     activeOperation()->suspendOperation();
302     anOp->setState( SUIT_Operation::Suspended );
303   }
304
305   theOp->setState( SUIT_Operation::Running );
306   myOperations.append( theOp );
307  
308   emit theOp->started( theOp );
309   operationStarted( theOp );
310   theOp->startOperation();
311
312   return true;
313 }
314
315 /*!
316  * \brief Aborts operation
317   * \param theOp - operation to be aborted
318   * \return TRUE if operation is aborted successfully
319 *
320 * Verifies whether operation already started and aborts it in this case (sets execution
321 * status to Rejected and stops operation)
322 */
323 bool SUIT_Study::abort( SUIT_Operation* theOp )
324 {
325   if ( !theOp || myOperations.find( theOp ) == -1 )
326     return false;
327
328   theOp->setExecStatus( SUIT_Operation::Rejected );
329
330   theOp->abortOperation();
331   operationAborted( theOp );
332   emit theOp->aborted( theOp );
333
334   stop( theOp );
335
336   return true;
337 }
338
339 /*!
340  * \brief Commits operation
341   * \param theOp - operation to be committed
342   * \return TRUE if operation is committed successfully
343 *
344 * Verifies whether operation already started and commits it in this case (sets execution
345 * status to Accepted and stops operation)
346 */
347 bool SUIT_Study::commit( SUIT_Operation* theOp )
348 {
349   if ( !theOp || myOperations.find( theOp ) == -1 )
350     return false;
351
352   theOp->setExecStatus( SUIT_Operation::Accepted );
353
354   theOp->commitOperation();
355   operationCommited( theOp );
356   emit theOp->committed( theOp );
357
358   stop( theOp );
359
360   emit studyModified( this );
361
362   return true;
363 }
364
365 /*!
366  * \brief Commits operation
367   * \param theOp - operation to be committed
368   * \return TRUE if operation is suspended successfully
369 *
370 * Verifies whether operation already started and suspends it in this case. Operations
371 * ususlly are suspended to start other one above them.
372 */
373 bool SUIT_Study::suspend( SUIT_Operation* theOp )
374 {
375   if ( !theOp || myOperations.find( theOp ) == -1 || theOp->state() == SUIT_Operation::Suspended )
376     return false;
377
378   theOp->setState( SUIT_Operation::Suspended );
379   theOp->suspendOperation();
380   emit theOp->suspended( theOp );
381   return true;
382 }
383
384
385 /*!
386  * \brief Resumes operation
387   * \param theOp - operation to be resumed
388   * \return TRUE if operation is aborted successfully
389 *
390 * Verifies whether operation already started but suspended and resumesit in this case.
391 */
392 bool SUIT_Study::resume( SUIT_Operation* theOp )
393 {
394   if ( !theOp || myOperations.find( theOp ) == -1 ||
395        theOp->state() == SUIT_Operation::Running ||
396        blockingOperation( theOp ) != 0 )
397     return false;
398
399   if ( myOperations.count() > 0 )
400     suspend( myOperations.last() );
401
402   theOp->setState( SUIT_Operation::Running );
403   theOp->resumeOperation();
404
405   // Move operation at the end of list in order to sort it in the order of activation.
406   // As result active operation is a last operation of list, operation which was active
407   // before currently active operation is located before it and so on
408   myOperations.remove( theOp );
409   myOperations.append( theOp );
410
411   emit theOp->resumed( theOp );
412   return true;
413 }
414
415 /*!
416  * \brief Stops operation
417   * \param theOp - operation to be stopped
418 *
419 * Stops operation. This private method is called from abort() and commit() ones to perform
420 * common actions when operation is stopped
421 */
422 void SUIT_Study::stop( SUIT_Operation* theOp )
423 {
424   theOp->setState( SUIT_Operation::Waiting );
425   myOperations.remove( theOp );
426
427   // get last operation which can be resumed
428   SUIT_Operation* anOp, *aResultOp = 0;
429   for ( anOp = myOperations.last(); anOp; anOp = myOperations.prev() )
430   {
431     if ( anOp && anOp != theOp && blockingOperation( anOp ) == 0 )
432     {
433       aResultOp = anOp;
434       break;
435     }
436   }
437
438   theOp->stopOperation();
439   operationStopped( theOp );
440   emit theOp->stopped( theOp );
441
442   if ( aResultOp )
443     resume( aResultOp );
444 }
445
446 /*!
447  * \brief Get all started operations
448   * \return List of all started operations
449 */
450 const QPtrList<SUIT_Operation>& SUIT_Study::operations() const
451 {
452   return myOperations;
453 }
454
455 /*!
456  * \brief Perform some actions when operation starting
457 */
458 void SUIT_Study::operationStarted( SUIT_Operation* op )
459 {
460   if ( !op )
461     return;
462
463   if ( op->testFlags( SUIT_Operation::Transaction ) )
464     op->openTransaction();
465 }
466
467 /*!
468  * \brief Perform some actions when operation aborted
469 */
470 void SUIT_Study::operationAborted( SUIT_Operation* op )
471 {
472   if ( op->testFlags( SUIT_Operation::Transaction ) )
473     op->abortTransaction();
474 }
475
476 /*!
477  * \brief Perform some actions when operation commited
478 */
479 void SUIT_Study::operationCommited( SUIT_Operation* op )
480 {
481   if ( op->testFlags( SUIT_Operation::Transaction ) )
482     op->commitTransaction( op->operationName() );
483 }
484
485 /*!
486  * \brief Perform some actions when operation stopped
487 */
488 void SUIT_Study::operationStopped( SUIT_Operation* )
489 {
490 }
491
492 /*!
493  * \brief Opens transaction for data modifications.
494 */
495 bool SUIT_Study::openTransaction()
496 {
497   return true;
498 }
499
500 /*!
501  * \brief Aborts transaction and all performed data modifications.
502 */
503 bool SUIT_Study::abortTransaction()
504 {
505   return true;
506 }
507
508 /*!
509  * \brief Commits transaction and all performed data modifications.
510 */
511 bool SUIT_Study::commitTransaction( const QString& )
512 {
513   return true;
514 }
515
516 /*!
517  * \brief Returns TRUE if transaction is opened.
518 */
519 bool SUIT_Study::hasTransaction() const
520 {
521   return false;
522 }
523  
524 /*!
525  * \brief Restores the study state.
526  */
527 void SUIT_Study::restoreState(int savePoint)
528 {
529   // Redefined in SalomeApp_Study.
530   // Called from SALOME_Session_i::restoreVisualState(CORBA::Long theSavePoint)
531 }