Salome HOME
PAL10125 - by double click on reference original object becomes selected
[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   delete myRoot;
196   myRoot = obj;
197 }
198
199 /*!
200   Set study name.
201  */
202 void SUIT_Study::setStudyName( const QString& name )
203 {
204   myName = name;
205 }
206
207 /*!
208  * \brief Verifies whether operation can be activated above already started ones
209   * \param theOp - operation to be checked
210   * \return NULL if operation can be activated, pointer to operation which denies
211   * starting tested operation
212 *
213 * Verifies whether operation can be activated above already started ones. This method
214 * is called from SUIT_Study::start() and SUIT_Study::resume() methods.
215 */
216 SUIT_Operation* SUIT_Study::blockingOperation( SUIT_Operation* theOp ) const
217 {
218   if( theOp->isGranted() )
219     return 0;
220
221   Operations tmpOps( myOperations );
222   SUIT_Operation* anOp = 0;
223   for ( anOp = tmpOps.last(); anOp; anOp = tmpOps.prev() )
224   {
225     if ( anOp != 0 && anOp!= theOp && !anOp->isValid( theOp ) )
226       return anOp;
227   }
228
229   return 0;
230 }
231
232 /*!
233  * \brief Starts operation
234   * \param theOp - operation to be started
235   * \param toCheck - if parameters is equal TRUE then checking performed whether
236   * all already started operations allow to start this operation above them (default
237   * value is TRUE
238   * \return TRUE if operation is started, FALSE otherwise
239 *
240 * Verifies whether theOp operation can be started above already started ones (if toCheck
241 * parameter is equal TRUE) and starts it
242 */
243 bool SUIT_Study::start( SUIT_Operation* theOp, const bool toCheck )
244 {
245   if ( !theOp || myOperations.find( theOp ) >= 0 )
246     return false;
247
248   theOp->setExecStatus( SUIT_Operation::Rejected );
249   theOp->setStudy( this );
250
251   if ( !theOp->isReadyToStart() )
252     return false;
253
254   if ( toCheck )
255   {
256     while( SUIT_Operation* anOp = blockingOperation( theOp ) )
257     {
258       int anAnsw = SUIT_MessageBox::warn2( application()->desktop(),
259          tr( "OPERATION_LAUNCH" ), tr( "PREVIOUS_NOT_FINISHED" ),
260          tr( "CONTINUE" ), tr( "CANCEL" ), 0, 1, 1 );
261
262       if( anAnsw == 1 )
263         return false;
264       else
265         anOp->abort();
266     }
267   }
268
269   SUIT_Operation* anOp = activeOperation();
270   if ( anOp )
271   {
272     activeOperation()->suspendOperation();
273     anOp->setState( SUIT_Operation::Suspended );
274   }
275
276   theOp->setState( SUIT_Operation::Running );
277   myOperations.append( theOp );
278   emit theOp->started( theOp );
279   theOp->startOperation();
280   
281   return true;
282 }
283
284 /*!
285  * \brief Aborts operation
286   * \param theOp - operation to be aborted
287   * \return TRUE if operation is aborted successfully
288 *
289 * Verifies whether operation already started and aborts it in this case (sets execution
290 * status to Rejected and stops operation)
291 */
292 bool SUIT_Study::abort( SUIT_Operation* theOp )
293 {
294   if ( !theOp || myOperations.find( theOp ) == -1 )
295     return false;
296
297   theOp->abortOperation();
298   theOp->setExecStatus( SUIT_Operation::Rejected );
299   emit theOp->aborted( theOp );
300   stop( theOp );
301   return true;
302 }
303
304 /*!
305  * \brief Commits operation
306   * \param theOp - operation to be committed
307   * \return TRUE if operation is committed successfully
308 *
309 * Verifies whether operation already started and commits it in this case (sets execution
310 * status to Accepted and stops operation)
311 */
312 bool SUIT_Study::commit( SUIT_Operation* theOp )
313 {
314   if ( !theOp || myOperations.find( theOp ) == -1 )
315     return false;
316
317   theOp->commitOperation();
318   theOp->setExecStatus( SUIT_Operation::Accepted );
319   emit theOp->committed( theOp );
320   stop( theOp );
321   emit studyModified( this );
322   return true;
323 }
324
325 /*!
326  * \brief Commits operation
327   * \param theOp - operation to be committed
328   * \return TRUE if operation is suspended successfully
329 *
330 * Verifies whether operation already started and suspends it in this case. Operations
331 * ususlly are suspended to start other one above them.
332 */
333 bool SUIT_Study::suspend( SUIT_Operation* theOp )
334 {
335   if ( !theOp || myOperations.find( theOp ) == -1 || theOp->state() == SUIT_Operation::Suspended )
336     return false;
337
338   theOp->setState( SUIT_Operation::Suspended );
339   theOp->suspendOperation();
340   emit theOp->suspended( theOp );
341   return true;
342 }
343
344
345 /*!
346  * \brief Resumes operation
347   * \param theOp - operation to be resumed
348   * \return TRUE if operation is aborted successfully
349 *
350 * Verifies whether operation already started but suspended and resumesit in this case.
351 */
352 bool SUIT_Study::resume( SUIT_Operation* theOp )
353 {
354   if ( !theOp || myOperations.find( theOp ) == -1 ||
355        theOp->state() == SUIT_Operation::Running ||
356        blockingOperation( theOp ) != 0 )
357     return false;
358
359   if ( myOperations.count() > 0 )
360     suspend( myOperations.last() );
361
362   theOp->setState( SUIT_Operation::Running );
363   theOp->resumeOperation();
364
365   // Move operation at the end of list in order to sort it in the order of activation.
366   // As result active operation is a last operation of list, operation which was active
367   // before currently active operation is located before it and so on
368   myOperations.remove( theOp );
369   myOperations.append( theOp );
370
371   emit theOp->resumed( theOp );
372   return true;
373 }
374
375 /*!
376  * \brief Stops operation
377   * \param theOp - operation to be stopped
378 *
379 * Stops operation. This private method is called from abort() and commit() ones to perform
380 * common actions when operation is stopped
381 */
382 void SUIT_Study::stop( SUIT_Operation* theOp )
383 {
384   theOp->setState( SUIT_Operation::Waiting );
385   myOperations.remove( theOp );
386
387   // get last operation which can be resumed
388   SUIT_Operation* anOp, *aResultOp = 0;
389   for( anOp = myOperations.last(); anOp; anOp = myOperations.prev() )
390     if ( anOp && anOp != theOp && blockingOperation( anOp ) == 0 )
391     {
392       aResultOp = anOp;
393       break;
394     }
395
396   emit theOp->stopped( theOp );
397   if ( aResultOp )
398     resume( aResultOp );
399 }
400
401 /*!
402  * \brief Get all started operations
403   * \return List of all started operations
404 */
405 const QPtrList<SUIT_Operation>& SUIT_Study::operations() const
406 {
407   return myOperations;
408 }
409
410
411
412
413
414
415
416
417
418