]> SALOME platform Git repositories - modules/kernel.git/blob - src/SALOMEGUI/QAD_Study.cxx
Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[modules/kernel.git] / src / SALOMEGUI / QAD_Study.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : QAD_Study.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SALOME
27 //  $Header$
28
29 using namespace std;
30 /*!
31   \class QAD_Study QAD_Study.h
32   \brief Study for QAD-based application.
33 */
34
35 #include "QAD.h"
36 #include "QAD_Tools.h"
37 #include "QAD_Desktop.h"
38 #include "QAD_Study.h"
39 #include "QAD_RightFrame.h"
40 #include "QAD_LeftFrame.h"
41 #include "QAD_MessageBox.h"
42 #include "QAD_Application.h"
43 #include "QAD_ObjectBrowser.h"
44 #include "QAD_PyInterp.h"
45 #include "QAD_Config.h"
46  
47 #include "utilities.h"
48
49 #include "SALOME_Selection.h"
50 #include "SALOME_TypeFilter.hxx"
51 #include "SALOME_InteractiveObject.hxx"
52 #include "SALOME_ListIteratorOfListIO.hxx"
53
54 #include <SALOMEconfig.h>
55 #include CORBA_SERVER_HEADER(SALOMEDS)
56
57 // OPEN CASCADE Include
58 #include <Standard_Failure.hxx>
59
60 // QT Include
61 #include <qapplication.h>
62
63 #define MAX_UNDO 10
64 /*!
65     Constructor
66 */
67 QAD_Study::QAD_Study(QAD_Application* app,
68                      SALOMEDS::Study_var aStudy,
69                      const QString& path ) :
70 myOperationState( Undef ),
71 myApp( app ),
72 myActiveStudyFrame( 0 ),
73 myStudyFrameCount( 0 ),
74 myPath( path )
75 {
76     myStudy = aStudy;
77
78     myTitle = QAD_Tools::getFileNameFromPath( path, false );
79
80     myIsActive = false;
81     myIsSaved = false;
82     myIsModified = false;
83     myIsReadOnly = false;
84
85     myStudyFrames.clear();
86     myOperations.clear();
87
88     myStudyFrames.setAutoDelete( true );
89     myOperations.setAutoDelete( true );
90     myChildWidgets.setAutoDelete( true );
91
92     /* create python interpreter */
93     _interp = new QAD_PyInterp();
94     SCRUTE(_interp);
95
96     /* create default selection */
97     //NRI    Selection( "Salome" );
98     Selection( QAD_Application::getDesktop()->getComponentUserName( "KERNEL" ) );
99
100     /* create study frame */
101     myResult = true;
102     createStudyFrame( getNextStudyFrameName() );
103
104     /* set default Undo/Redo limit */
105     QAD_ASSERT_DEBUG_ONLY( !myStudy->_is_nil() );
106     SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
107     SB->UndoLimit( MAX_UNDO );
108 }
109
110 /*!
111     Destructor
112 */
113 QAD_Study::~QAD_Study ()
114 {
115   close();
116   //SRN: added - clear selection in case the study will be loaded again so the title will coincide
117   SALOME_Selection::RemoveSelection( QString(myTitle + "_" + mySelection) );
118 }
119
120 /*!
121   Returns TRUE if Study is created correctly. Returns FALSE otherwise.
122 */
123 bool QAD_Study::getResult()
124 {
125   return myResult;
126 }
127
128
129 //=======================================================================//
130 //                          StudyFrames management                       //
131 //=======================================================================//
132 /*!
133     Adds study frame
134 */
135 void QAD_Study::addStudyFrame(QAD_StudyFrame* sf )
136 {
137   myStudyFrames.append( sf );
138   
139   sf->getRightFrame()->getViewFrame()->setPopupServer( myApp );
140   // Provide the same common popup menu commands for both the Object Browser and 3D viewer
141   sf->getLeftFrame()->getObjectBrowser()->setPopupServer( myApp );
142
143   /* icon of Study Frame */
144   const QPixmap& icon = myApp->getApplicationIcon();
145   if ( !icon.isNull() )
146     sf->setIcon ( icon );
147
148   /* activation */
149   QAD_ASSERT ( connect( sf, SIGNAL(sfStudyFrameActivated(QAD_StudyFrame*) ),
150                         SLOT(onStudyFrameActivated(QAD_StudyFrame*))) );
151
152   /* closing */
153   QAD_ASSERT ( connect( sf,
154                         SIGNAL(sfStudyFrameClosing(QAD_StudyFrame*) ),
155                         this,
156                         SLOT(onLastStudyFrameClosing(QAD_StudyFrame*))) );
157
158   /* set active sf */
159   myActiveStudyFrame = sf;
160 }
161
162 /*!
163     Removes studyframe from the list
164 */
165 void QAD_Study::removeStudyFrame( QAD_StudyFrame* sf )
166 {
167   if (sf) {
168     if (!myStudy->IsEmpty()) {
169       SALOMEDS::SObject_var fatherSF = myStudy->FindObjectID(sf->entry());
170       if (!fatherSF->_is_nil()) {
171         SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
172         aStudyBuilder->RemoveObject(fatherSF);
173       }
174       
175       updateObjBrowser( true );
176     }
177     myStudyFrames.removeRef( sf );
178   }
179 }
180
181 /*!
182   Returns number of study frames
183 */
184 int QAD_Study::getStudyFramesCount() const
185 {
186   return myStudyFrames.count();
187 }
188
189 /*!
190   Returns study frame by its index in list
191 */
192 QAD_StudyFrame* QAD_Study::getStudyFrame( unsigned i )
193 {
194   return myStudyFrames.at(i);
195 }
196
197 /*!
198   Returns study frame by its name or null if not found
199 */
200 QAD_StudyFrame* QAD_Study::getStudyFrameByName ( const QString& name )
201 {
202   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() )
203     {
204       if ( sf->title().compare(name) == 0 ) {
205         return sf;
206       }
207     }
208   return NULL;
209 }
210
211 /*!
212   Returns first study frame in the list
213 */
214 QAD_StudyFrame* QAD_Study::getFirstStudyFrame()
215 {
216   return myStudyFrames.first();
217 }
218
219 /*!
220   Returns last study frame in the list
221 */
222 QAD_StudyFrame* QAD_Study::getLastStudyFrame()
223 {
224   return myStudyFrames.last();
225 }
226
227 /*!
228   Returns the vector of studyframes
229 */
230 const QList<QAD_StudyFrame>& QAD_Study::getStudyFrames() const
231 {
232   return myStudyFrames;
233 }
234
235 /*!
236   Returns the active study frame
237 */
238 QAD_StudyFrame* QAD_Study::getActiveStudyFrame() const
239 {
240   return myActiveStudyFrame;
241 }
242
243 //=======================================================================//
244 //                  Study properties                                     //
245 //=======================================================================//
246 /*!
247   Returns reference to supporting application
248 */
249 QAD_Application* QAD_Study::getApp() const
250 {
251   return myApp;
252 }
253
254 /*!
255   Returns the name of document ( filename without path and extension )
256 */
257 const QString& QAD_Study::getTitle() const
258 {
259   return myTitle;
260 }
261
262 /*!
263     Returns the absolute file path of this document
264 */
265 const QString& QAD_Study::getPath() const
266 {
267   return myPath;
268 }
269
270 /*!
271     Changes the name of document
272 */
273 void QAD_Study::setTitle( const QString& path )
274 {
275   myPath = path;
276
277   QString title = QAD_Tools::getFileNameFromPath( path, false );
278   QAD_ASSERT_DEBUG_ONLY ( !title.isNull() );
279
280   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf ; sf = myStudyFrames.next() )
281     {
282       QString oldName = sf->title();
283       int k = oldName.find( myTitle, 0, false );
284       QString restName = ( oldName.length() > myTitle.length() + k) ?
285         oldName.right(oldName.length() - (myTitle.length() + k) + 1) :
286         QString( "" );
287
288       if ( k != -1 )
289         {
290           QString newName;
291           if ( k == 0 ) {
292             int l = restName.find( "#", 0, false );
293             int ll =  restName.length();
294             newName = title + restName.mid( l, ll-l );
295           } else {
296             newName = oldName.mid(0, k);
297             newName = newName + title + restName;
298           }
299           sf->setTitle( newName );
300         }
301     }
302   myTitle = title;
303
304   Selection( QAD_Application::getDesktop()->getActiveComponent() );
305 }
306
307 /*!
308     Returns whether the document is active
309 */
310 bool QAD_Study::isActive() const
311 {
312   return myIsActive;
313 }
314
315 /*!
316     Returns whether the document is read only
317 */
318 bool QAD_Study::isReadOnly() const 
319 {
320   return myIsReadOnly;
321 }
322
323 /*!
324     Sets read-only property
325 */
326 void QAD_Study::setReadOnly(bool state)
327 {
328   myIsReadOnly = state;
329 }
330
331 //=======================================================================//
332 //                      Study operations                                 //
333 //=======================================================================//
334 /*!
335     Performs specific study frame related actions when it is activated.
336     By default resumes all suspended operations.
337 */
338 void QAD_Study::onStudyFrameActivated( QAD_StudyFrame* activeStudyFrame )
339 {
340   static int IS_FIRST_STUDY = 1;  
341   if(IS_FIRST_STUDY){ //for normally initialize "salome.py and ..."
342     _interp->run("");  IS_FIRST_STUDY = 0;
343   }
344 //  bool found = false;
345   for ( QAD_StudyFrame* studyframe = myStudyFrames.first(); studyframe; studyframe = myStudyFrames.next() ) {
346     if ( studyframe == activeStudyFrame) {              /* one of my study frames */
347 //      found = true;
348 //      if ( !myActiveStudyFrame || myActiveStudyFrame != activeStudyFrame ) {
349         myActiveStudyFrame =  activeStudyFrame;
350         //NRI    if ( !myIsActive ) {
351         myIsActive = true;
352         resumeAllOperations();
353         /* activate application */
354         myApp->onStudyActivated( this );
355         //NRI      }
356 //      }
357 //      return;
358     }
359   }
360 //  if (!found)
361 //    myActiveStudyFrame = 0;
362 }
363
364
365 /*!
366     Performs specific study related actions when it is deactivated.
367     By default suspends all performing operations.
368 */
369 void QAD_Study::onStudyDeactivated()
370 {
371   //  MESSAGE ("QAD_Study::onStudyDeactivated init. "); 
372   myIsActive = false;
373   suspendAllOperations();
374   //  MESSAGE ("QAD_Study::onStudyDeactivated done. "); 
375 }
376
377 /*!
378     Closes all study frames of the study and performs other specific study
379     related actions needed for proper closing of the study
380 */
381 void QAD_Study::close()
382 {
383   if ( !myStudy->_is_nil() )
384     abortAllOperations();
385     /* clear each study frame */
386     for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.first() ) {
387       sf->disconnect();
388       sf->close();
389       qApp->processEvents();
390       qApp->processEvents();
391       removeStudyFrame(sf);
392     }
393
394   /* delete all studyframes */
395   myStudyFrames.clear();
396   myOperations.clear();
397   myChildWidgets.clear();
398
399 //  QWorkspace* ws = QAD_Application::getDesktop()->getMainFrame();
400 //  if (/* !ws->activeWindow() && */ws->windowList().count() > 0 )
401 //    ws->activateWindow(ws->windowList().last());
402 }
403
404 //=======================================================================//
405 //                      Operations management                            //
406 //=======================================================================//
407 /*!
408     Returns number of completed operations
409 */
410 int QAD_Study::getOperationsCount() const
411 {
412     return myOperations.count();
413 }
414
415 /*!
416     Returns the state of the last operation
417 */
418 OperationState QAD_Study::getOperationState() const
419 {
420     return myOperationState;
421 }
422
423 /*!
424     Returns operation by its index in list
425 */
426 QAD_Operation* QAD_Study::getOperation( unsigned i)
427 {
428     return ( myOperations.isEmpty() ? 0 :  myOperations.at(i) );
429 }
430
431 /*!
432     Returns performing operation launched first
433 */
434 QAD_Operation* QAD_Study::getFirstOperation()
435 {
436     return ( myOperations.isEmpty() ? 0 :  myOperations.first() );
437 }
438
439 /*!
440     Returns performing operation launched last
441 */
442 QAD_Operation* QAD_Study::getLastOperation()
443 {
444     return ( myOperations.isEmpty() ? 0 :  myOperations.last() );
445 }
446
447 /*!
448     Aborts all performing operations
449 */
450 void QAD_Study::abortAllOperations()
451 {
452   for ( QAD_Operation* op = myOperations.last(); op;
453         op = myOperations.prev() )
454     op->abort();
455 }
456
457 /*!
458     Resumes all performing operations
459 */
460 void QAD_Study::resumeAllOperations()
461 {
462   for ( QAD_Operation* op = myOperations.first(); op;
463         op = myOperations.next() )
464     op->resume();
465 }
466
467 /*!
468     Suspendes all performing operations
469 */
470 void QAD_Study::suspendAllOperations()
471 {
472   //  MESSAGE ( " QAD_Study::suspendAllOperations init. " )
473   for ( QAD_Operation* op = myOperations.last(); op;
474         op = myOperations.prev() )
475     op->suspend();
476 }
477
478 /*!
479     Initializes the operation and checks its compatibility
480     with another operation in process if any.
481     Returns 'true' if init'ed OK, 'false' otherwise.
482 */
483 bool QAD_Study::initOperation( QAD_Operation* op )
484 {
485     if ( myIsReadOnly )
486     {   /* can't start a non-const operation */
487         if ( op->changesData() )
488         {
489             QAD_MessageBox::error1( QAD_Application::getDesktop(), tr("ERR_ERROR"),
490                                     tr("ERR_DOC_READONLY"), tr("BUT_OK") );
491             return false;
492         }
493     }
494
495     /* Add the new operation
496     */
497     if ( myOperations.isEmpty() )
498         myOperations.append( op );
499     else
500     {
501         /*  Check compatibility of new operation with the existing operations.
502             Since each operations is checked in that way, it's enough to check
503             the last operation only */
504         if ( !getLastOperation()->compatibleWith( op ) )
505         {
506             if ( QAD_MessageBox::warn2( QAD_Application::getDesktop(), tr("WRN_WARNING"),
507                                         tr("QUE_ABORTCURRENTOPERATION"), tr("BUT_YES"),
508                                         tr("BUT_NO"), QAD_YES, QAD_NO, QAD_NO )
509                    == QAD_NO )
510                 return false;
511             getLastOperation()->abort();
512         }
513         myOperations.append( op );
514     }
515     return true;
516 }
517
518 /*!
519     Called when operation was finished.
520     Removes appointed operation from the list and aborted all operations
521     launched after it.
522 */
523 void QAD_Study::clearOperation( QAD_Operation* op)
524 {
525   if ( myOperations.contains( op ) )
526     {
527       /* abort all the operations launched after 'op' */
528       for ( QAD_Operation* cur = myOperations.last(); cur;
529             cur = myOperations.prev() )
530         {
531           if ( cur == op ) break;
532           cur->abort();
533         }
534       myOperations.remove( op );
535     }
536 }
537
538 /*!
539     Creates study frame
540 */
541 QAD_StudyFrame* QAD_Study::createStudyFrame( const QString& title, ViewType theViewType)
542 {
543   QAD_Desktop* parent = QAD_Application::getDesktop();
544 //srn: Forbid appending Interface Applicative and its children to UseCase
545   myStudy->EnableUseCaseAutoFilling(false);   
546   
547   SALOMEDS::SComponent_var father = myStudy->FindComponent("Interface Applicative");
548   SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
549   SALOMEDS::GenericAttribute_var anAttr;
550   SALOMEDS::AttributeName_var    aName;
551   SALOMEDS::AttributeComment_var aComment;
552   SALOMEDS::AttributeSelectable_var aSelAttr;
553
554 // mpv : where is "NewCommand" call?
555 //  aStudyBuilder->CommitCommand();
556
557 // mpv : is study is locked, then next code will raise exception. So, temporary unlock study
558   int aLocked = myStudy->GetProperties()->IsLocked();
559   if (aLocked) myStudy->GetProperties()->SetLocked(false);
560
561   if ( father->_is_nil() ) {
562     father = aStudyBuilder->NewComponent("Interface Applicative");
563     anAttr = aStudyBuilder->FindOrCreateAttribute(father, "AttributeName");
564     aName = SALOMEDS::AttributeName::_narrow(anAttr);
565     aName->SetValue("Interface Applicative");
566     
567     anAttr = aStudyBuilder->FindOrCreateAttribute(father, "AttributeSelectable");
568     aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
569     aSelAttr->SetSelectable(false);
570   }
571   
572   //VRV: T2.5 - add default viewer
573   if(theViewType == VIEW_TYPE_MAX) {
574     QString viewerValue = QAD_CONFIG->getSetting( "Viewer:DefaultViewer" );
575     bool ok;
576     theViewType = (ViewType)viewerValue.toInt( &ok, 10 ); 
577     if (!ok || theViewType < VIEW_OCC || theViewType >= VIEW_TYPE_MAX)
578       theViewType = VIEW_VTK;
579   }
580   //QApplication::restoreOverrideCursor();
581   QAD_StudyFrame* sf = NULL;
582   SALOMEDS::SObject_var newObj = aStudyBuilder->NewObject(father);
583   if ( theViewType == VIEW_OCC) {
584     //      MESSAGE ("Create Study Frame for OCC viewer");
585     sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
586                               title, _interp, VIEW_OCC );
587     
588     Standard_CString name = strdup(sf->title().latin1());
589     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
590     aName = SALOMEDS::AttributeName::_narrow(anAttr);
591     aName->SetValue(name);
592     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
593     aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
594     aComment->SetValue("OCC");
595     
596     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
597     aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
598     aSelAttr->SetSelectable(false);
599   } 
600   else if ( theViewType == VIEW_VTK) {
601     //      MESSAGE ("Create Study Frame for VTK viewer");
602     sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
603                               title, _interp, VIEW_VTK );
604     Standard_CString name = strdup(sf->title().latin1());
605     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
606     aName = SALOMEDS::AttributeName::_narrow(anAttr);
607     aName->SetValue(name);
608     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
609     aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
610     aComment->SetValue("VTK");
611     
612     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
613     aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
614     aSelAttr->SetSelectable(false);
615   } 
616   else if ( theViewType == VIEW_GRAPHSUPERV) { 
617     //MESSAGE ("Create Study Frame for SUPER`VISOR Graph");
618     sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
619                               title, _interp, VIEW_GRAPHSUPERV );
620     Standard_CString name = strdup(sf->title().latin1());
621     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
622     aName = SALOMEDS::AttributeName::_narrow(anAttr);
623     aName->SetValue(name);
624     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
625     aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
626     aComment->SetValue("GRAPH");
627     
628     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
629     aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
630     aSelAttr->SetSelectable(false);
631   }
632   else if ( theViewType == VIEW_PLOT2D ) {
633     sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
634                               title, _interp, VIEW_PLOT2D );
635     Standard_CString name = strdup(sf->title().latin1());
636     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
637     aName = SALOMEDS::AttributeName::_narrow(anAttr);
638     aName->SetValue(name);
639     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
640     aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
641     aComment->SetValue("PLOT2D");
642     
643     anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
644     aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
645     aSelAttr->SetSelectable(false);
646   } 
647   //VRV: T2.5 - add default viewer
648
649   sf->resize( int (0.8*parent->getMainFrame()->width()),
650               int (0.8*parent->getMainFrame()->height() ));
651   
652   sf->setEntry(newObj->GetID());
653   
654   addStudyFrame( sf );
655   
656   updateObjBrowser( true );
657   
658   parent->setSettings();
659   
660   myResult = true;
661   
662   if (aLocked) myStudy->GetProperties()->SetLocked(true);
663
664   // T2.12 - add the word "locked" to study frame captions if this study is locked
665   updateCaptions();
666
667   myStudy->EnableUseCaseAutoFilling(true);
668
669   return sf;
670 }
671
672 /*!
673    Updates study frame captions according to IsLocked study flag
674 */
675 void QAD_Study::updateCaptions()
676 {
677   QString appendix("");
678
679   if (!myStudy->_is_nil()) {
680     SALOMEDS::AttributeStudyProperties_var propAttr = myStudy->GetProperties();
681 /*    
682     if (!propAttr->_is_nil() ) {
683       if ( propAttr->IsModified() )
684         appendix += " (" + tr("PRP_STUDY_MODIFIED") + ")";
685       else
686         appendix += " (" + tr("PRP_STUDY_SAVED") + ")";
687     }  
688   
689 */
690     if (!propAttr->_is_nil() && propAttr->IsLocked()) {
691       appendix += " (" + tr("PRP_STUDY_LOCKED") + ")";
692     }
693   }
694
695   for (myStudyFrames.first(); myStudyFrames.current(); myStudyFrames.next()) {
696     myStudyFrames.current()->setCaption(myStudyFrames.current()->title() + appendix);
697   }
698   
699 }
700
701 /*!
702     Shows the active study frame.
703     Called by Desktop after 'new' and 'open' commands.
704 */
705 void QAD_Study::show()
706 {
707   for (myStudyFrames.first(); myStudyFrames.current(); myStudyFrames.next()) {
708     myStudyFrames.current()->show();
709   }
710 }
711
712 //=======================================================================//
713 //                  Study properties (CAF related)                       //
714 //=======================================================================//
715
716 /*!
717     Returns connected SALOMEDS_Study object
718 */
719 SALOMEDS::Study_var QAD_Study::getStudyDocument()
720 {
721   return myStudy;
722 }
723
724 /*!
725     Returns whether the document was saved in file
726 */
727 bool QAD_Study::isSaved() const
728 {
729   return myStudy->IsSaved();
730 }
731
732 /*!
733     Returns whether the document is modified
734 */
735 bool QAD_Study::isModified() const
736 {
737 //  return myStudy->IsModified(); // VSR:05/12/02 - USE PROPERTY : MODIFIED FLAG
738   if ( !myStudy->_is_nil() ) {
739     SALOMEDS::AttributeStudyProperties_var propAttr = myStudy->GetProperties();
740     if ( !propAttr->_is_nil() )
741       return propAttr->IsModified();
742   }
743   return false;
744 }
745
746 bool QAD_Study::undo()
747 {
748   try {
749     SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
750     SB->Undo();
751
752     /* Update Object Browser */
753     updateObjBrowser( true );
754
755     for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
756       /* Update Viewer */
757       sf->getRightFrame()->getViewFrame()->undo( myStudy, sf->entry() );
758     }
759     updateCaptions();
760
761     // mpv 07.03.2003 SAL1805: clear selection must be called after study structure changed
762     SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
763     Sel->ClearIObjects();
764   }
765   // mpv : undo command can raise exception, if study is locked
766   catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
767     QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
768                            QObject::tr("WRN_WARNING"), 
769                            QObject::tr("WRN_STUDY_LOCKED"),
770                            QObject::tr("BUT_OK"));
771     return false;
772   }
773   catch ( Standard_Failure ) {
774     return false; }
775   return true;
776 }
777
778 /*!
779     Redo last undo
780 */
781 bool QAD_Study::redo()
782 {
783   try {
784     SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
785     SB->Redo();
786
787     /* Update Object Browser */
788     updateObjBrowser( true );
789
790     /* Update Viewer */
791     for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
792       sf->getRightFrame()->getViewFrame()->redo( myStudy, sf->entry() );
793     }
794     updateCaptions();
795
796     // mpv 07.03.2003 SAL1805: clear selection must be called after study structure changed
797     SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
798     Sel->ClearIObjects();
799   }
800   // mpv : redo command can raise exception, if study is locked
801   catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
802     QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
803                            QObject::tr("WRN_WARNING"), 
804                            QObject::tr("WRN_STUDY_LOCKED"),
805                            QObject::tr("BUT_OK"));
806     return false;
807   }
808   catch ( Standard_Failure ) {
809     return false; }
810   return true;
811 }
812
813 /*!
814   Check if possible to perform 'undo' command
815 */
816 bool QAD_Study::canUndo() const
817 {
818   if ( myStudy->_is_nil() )
819     return false;
820
821   SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
822   return (SB->GetAvailableUndos() > 0 );
823 }
824
825 /*!
826     Check if possible to perform 'redo' command
827 */
828 bool QAD_Study::canRedo() const
829 {
830   if ( myStudy->_is_nil() )
831     return false;
832
833   SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
834   return (SB->GetAvailableRedos() > 0 );
835 }
836
837 /*!
838     Called when operation is started
839     Returns 'true' if started OK, 'false' otherwise.
840 */
841 bool QAD_Study::onOperationStarted( QAD_Operation* op )
842 {
843   if ( !initOperation( op ) )
844     return false;
845
846   try
847     {   /* start a new transaction */
848       SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
849       SB->NewCommand();
850     }
851   catch ( Standard_Failure )
852     {
853       /*  May be, a transaction is already open,
854           it's not a problem */
855     }
856   myOperationState = Started;
857   return true;
858 }
859
860 /*!
861     Called when operation is finished
862 */
863 void QAD_Study::onOperationFinished( QAD_Operation* op )
864 {
865   try {
866     /* transaction is completed OK */
867     SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
868     SB->CommitCommand();
869   }
870   catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
871     QApplication::restoreOverrideCursor();
872     QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
873                            QObject::tr("WRN_WARNING"), 
874                            QObject::tr("WRN_STUDY_LOCKED"),
875                            QObject::tr("BUT_OK"));
876     onOperationAborted(op);
877     updateObjBrowser( true );
878     return;
879   }
880   catch ( Standard_Failure ) {
881   }
882   myOperationState = Finished;
883   emit docOperationTerminated( true );    /* terminated successfully */
884
885   updateCaptions();
886   // mpv: any operation must call this method, otherwise study may not be saved
887   updateObjBrowser( true );
888
889   clearOperation( op );                   /* we don't need the operation anymore */
890   QAD_Application::getDesktop()->putInfo ( tr("INF_DOC_OPERATIONFINISHED") );
891 }
892
893 /*!
894     Called when operation is suspended
895 */
896 void QAD_Study::onOperationSuspended( QAD_Operation* op )
897 {
898   myOperationState = Suspended;
899 }
900
901 /*!
902     Called when operation is resumed
903 */
904 void QAD_Study::onOperationResumed( QAD_Operation* op )
905 {
906   myOperationState = Resumed;
907 }
908
909 /*!
910     Called when operation is aborted
911 */
912 void QAD_Study::onOperationAborted(QAD_Operation* op)
913 {
914   try {
915     /* abort transaction */
916     SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
917     SB->AbortCommand();
918   }
919   catch ( Standard_Failure )
920     {
921     }
922   myOperationState = Aborted;
923   emit docOperationTerminated( false );       /* aborted */
924
925   updateCaptions();
926
927   clearOperation(op);
928   QAD_Application::getDesktop()->putInfo ( tr("INF_DOC_OPERATIONABORTED") );
929 }
930
931 /*!
932     Call when the last study frame is closing
933 */
934 void QAD_Study::onLastStudyFrameClosing( QAD_StudyFrame* sf )
935 {
936   if ( myStudyFrames.count() == 1 ) {
937     emit docClosing( this );
938   } else
939     removeStudyFrame( sf );
940
941 //  QWorkspace* ws = QAD_Application::getDesktop()->getMainFrame();
942 //  if ( !ws->activeWindow() && ws->windowList().count() > 0 )
943 //    ws->activatePreviousWindow();
944 }
945
946 /*!
947     Call when created a new window3d
948 */
949 QAD_StudyFrame* QAD_Study::newWindow3d(QString name, ViewType theViewType, bool toShow)
950 {
951   if(name == "")  name = getNextStudyFrameName();
952   QAD_StudyFrame* sf = createStudyFrame( name, theViewType );
953   if ( myResult ) {
954     if (toShow) showFrame(sf);
955     //    sf->compressLeft(); /* compress LeftFrame */
956     sf->getRightFrame()->compressBottom(); /* compress BottomFrame */
957     return sf;
958   }
959   return 0;
960 }
961
962 void QAD_Study::showFrame(QAD_StudyFrame* theFrame){
963   theFrame->resize( (int)(0.64*QAD_Application::getDesktop()->getMainFrame()->width()),
964                     (int)(0.64*QAD_Application::getDesktop()->getMainFrame()->height()));
965   theFrame->show();
966
967 }
968
969
970
971 /*!
972     Call when setted a message
973 */
974 void QAD_Study::setMessage(const char* message)
975 {
976   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
977     sf->getRightFrame()->getMessage()->setMessage(message);
978   }
979 }
980
981 /*!
982     Call when updated object browser
983 */
984 void QAD_Study::updateObjBrowser( bool updateSelection )
985 {
986   QAD_Desktop* parent = QAD_Application::getDesktop();
987   SALOME_ModuleCatalog::ModuleCatalog_var Catalog = parent->getCatalogue();
988
989   QString ActiveComp = parent->getActiveComponent();
990
991   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
992     sf->getLeftFrame()->getObjectBrowser()->Update();
993   }
994
995   /* update selection */
996   if ( updateSelection && (myStudyFrames.count() > 0) ) {
997     SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
998     SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
999     for(;It.More();It.Next()) {
1000       if ( Sel->AddIObject( It.Value() ) == 0 ) {
1001         highlight( It.Value(), true, false );
1002       }
1003     }
1004   }
1005   /* update viewers */
1006   update3dViewers();
1007 }
1008
1009 /*!
1010   Updates only Use Case Browser
1011 */
1012 void QAD_Study::updateUseCaseBrowser( bool updateSelection )
1013 {
1014   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1015     sf->getLeftFrame()->getObjectBrowser()->UpdateUseCaseBrowser();
1016   }
1017   /* update selection */
1018   if ( updateSelection && (myStudyFrames.count() > 0) ) {
1019     SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
1020     SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
1021     for(;It.More();It.Next()) {
1022       if ( Sel->AddIObject( It.Value() ) == 0 ) {
1023         highlight( It.Value(), true, false );
1024       }
1025     }
1026     /* update viewers */
1027     update3dViewers();
1028   }
1029 }
1030
1031 /*!
1032   unHighlight All Interactive Objects in All Devices
1033 */
1034 void QAD_Study::unHighlightAll() 
1035 {
1036   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1037     /* Device = Viewers */
1038     sf->getRightFrame()->getViewFrame()->unHighlightAll();
1039
1040     /* Device = ObjectBrowser */
1041     sf->getLeftFrame()->getObjectBrowser()->unHighlightAll();
1042   }
1043 }
1044
1045 /*!
1046   Returns type of Interactive Object
1047 */
1048 int QAD_Study::typeIObject( const Handle(SALOME_InteractiveObject)& IObject )
1049 {
1050   bool IsStudyObject     = isInStudy( IObject );
1051   bool IsGraphicalObject = isInViewer( IObject );
1052
1053   //    MESSAGE ( "IsStudyObject : " <<  IsStudyObject )
1054   //    MESSAGE ( "IsGraphicalObject : " <<  IsGraphicalObject )
1055
1056   if ( IsStudyObject ) {
1057     if ( IsGraphicalObject )
1058       return 1; /* StudyObject and GraphicalObject */
1059     else
1060       return 2; /* only StudyObject */
1061   } else {
1062     if ( IsGraphicalObject )
1063       return 3; /* only GraphicalObject */
1064     else
1065       return 4; /* may be a component */
1066   }
1067   return 0;
1068 }
1069
1070
1071 /*!
1072   Renames the Interactive Object in All Devices
1073 */
1074 void QAD_Study::renameIObject( const Handle(SALOME_InteractiveObject)& IObject, QString newName )
1075 {
1076   if (myStudy->GetProperties()->IsLocked()) {
1077     QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
1078                            QObject::tr("WRN_WARNING"), 
1079                            QObject::tr("WRN_STUDY_LOCKED"),
1080                            QObject::tr("BUT_OK"));
1081     return;
1082   }
1083
1084   highlight( IObject, false );
1085   
1086   int nbFrames = myStudyFrames.count();
1087   for ( int i = 0; i < nbFrames; i++ ) {
1088     QAD_StudyFrame* sf = myStudyFrames.at( i );
1089     switch ( typeIObject(IObject) ) {
1090     case 1:
1091       {
1092         /* Device = Viewers */
1093         sf->getRightFrame()->getViewFrame()->rename(IObject, newName);
1094         /* Device = ObjectBrowser */
1095         sf->getLeftFrame()->getObjectBrowser()->rename(IObject, newName);
1096         break;
1097       }
1098     case 2:
1099       {
1100         /* Device = ObjectBrowser */
1101         sf->getLeftFrame()->getObjectBrowser()->rename(IObject, newName); 
1102       break;
1103       }
1104     case 3:
1105       {
1106         /* Device = Viewers */
1107         sf->getRightFrame()->getViewFrame()->rename(IObject, newName);
1108         break;
1109       }
1110     case 4:
1111       {
1112         QString ActiveComp = QAD_Application::getDesktop()->getActiveComponent();
1113         if ( !ActiveComp.isEmpty() ) {
1114           sf->getLeftFrame()->getObjectBrowser()->rename(IObject,newName);
1115         }
1116         break;
1117       }
1118     }
1119   }
1120
1121   /* SALOMEDS */
1122   SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
1123   SALOMEDS::SObject_var obj = myStudy->FindObjectID( IObject->getEntry() );
1124   if ( !obj->_is_nil() ) {
1125     SALOMEDS::GenericAttribute_var anAttr;
1126     SALOMEDS::AttributeName_var    aName;
1127     anAttr = aStudyBuilder->FindOrCreateAttribute(obj, "AttributeName");
1128     aName = SALOMEDS::AttributeName::_narrow(anAttr);
1129     aName->SetValue(strdup(newName.latin1()));
1130   }
1131
1132   // VSR 13/03/03 - rename Interactive object 
1133   IObject->setName( ( char* )newName.latin1() );
1134
1135   updateObjBrowser( true );
1136 }
1137
1138 /*!
1139   Selects the Interactive Object in All Devices
1140 */
1141 void QAD_Study::highlight( const Handle(SALOME_InteractiveObject)& IObject, bool highlight,bool immediatly ) 
1142 {
1143   //    MESSAGE ( " QAD_Study::highlight : " << highlight )
1144   int typeIO = typeIObject( IObject );
1145
1146   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1147     switch ( typeIO ) {
1148     case 1:
1149       {
1150         /* Device = Viewer */
1151         if (sf->getTypeView() >= 0 ) { /* Device = Viewers */
1152           sf->getRightFrame()->getViewFrame()->highlight(IObject, highlight, immediatly);
1153         }
1154         /* Device = ObjectBrowser */
1155         sf->getLeftFrame()->getObjectBrowser()->highlight(IObject, highlight);
1156         break;
1157       }
1158     case 2:
1159       {
1160         /* Device = ObjectBrowser */
1161         sf->getLeftFrame()->getObjectBrowser()->highlight(IObject, highlight); 
1162         break;
1163       }
1164     case 3:
1165       {
1166         /* Device = Viewer */
1167         if (sf->getTypeView() >= 0) { /* Device = Viewers */
1168           sf->getRightFrame()->getViewFrame()->highlight(IObject, highlight, immediatly);
1169         } 
1170         break;
1171       }
1172     case 4:
1173       {
1174         QString ActiveComp = QAD_Application::getDesktop()->getActiveComponent();
1175         if ( !ActiveComp.isEmpty() ) {
1176           sf->getLeftFrame()->getObjectBrowser()->highlight(IObject,highlight);
1177         }
1178         break;
1179       }
1180     }
1181   }
1182 }
1183
1184 /*!
1185   Returns TRUE if the IObject is a Study Object. Returns FALSE otherwise.
1186 */
1187 bool QAD_Study::isInStudy( const Handle(SALOME_InteractiveObject)& IObject ) 
1188 {
1189   return IObject->hasEntry();
1190 }
1191
1192 /*!
1193   Returns true if the IObject has a Graphical Object. Returns FALSE otherwise.
1194 */
1195 bool QAD_Study::isInViewer( const Handle(SALOME_InteractiveObject)& IObject ) 
1196 {
1197   bool found = false;
1198   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1199     found = sf->getRightFrame()->getViewFrame()->isInViewer(IObject);
1200     if ( found )
1201       return true;
1202   }
1203   return found;
1204 }
1205
1206 /*!
1207   Returns true if the IObject has a Graphical Object into studyframe. Returns FALSE otherwise.
1208 */
1209 bool QAD_Study::isInViewer(const char* anEntry, const char* StudyFrameEntry)
1210 {
1211   SALOMEDS::SObject_var RefSO;
1212   SALOMEDS::SObject_var SO = myStudy->FindObjectID(StudyFrameEntry);
1213   SALOMEDS::ChildIterator_var it = myStudy->NewChildIterator(SO);
1214   for (; it->More();it->Next()){
1215     SALOMEDS::SObject_var CSO= it->Value();
1216     if (CSO->ReferencedObject(RefSO))
1217       if ( strcmp( anEntry, RefSO->GetID() ) == 0 )
1218         return 1;
1219   }
1220   return 0;
1221 }
1222
1223
1224 /*!
1225     Returns title for the new studyframe window
1226 */
1227 QString QAD_Study::getNextStudyFrameName()
1228 {
1229   QString numStudyFrame;
1230   numStudyFrame.sprintf("%s%d", "#", ++myStudyFrameCount );
1231   return myTitle + numStudyFrame;   /* return unique name ( title + unique number) */
1232 }
1233
1234
1235 /*!
1236   Returns the Python interpreter that belongs to this study
1237 */
1238 QAD_PyInterp* QAD_Study::get_PyInterp(void)
1239 {
1240   return _interp;
1241 }
1242
1243 /*!
1244   Sets current selection.
1245 */
1246 void QAD_Study::Selection( QString aSelection )
1247 {
1248   if ( !SALOME_Selection::FindSelection( QString(myTitle + "_" + aSelection) ) )
1249     SALOME_Selection::CreateSelection( QString(myTitle + "_" + aSelection) );
1250
1251   SALOME_Selection* Sel = SALOME_Selection::Selection( QString(myTitle + "_" + aSelection) );
1252
1253   mySelection = aSelection;
1254 }
1255
1256 /*!
1257   Returns the name of current selection
1258 */
1259 QString QAD_Study::getSelection()
1260 {
1261   return QString (myTitle + "_" + mySelection);
1262 }
1263
1264 /*!
1265   Returns the study Id.
1266 */
1267 int QAD_Study::getStudyId()
1268 {
1269   return myStudy->StudyId();
1270 }
1271
1272 void QAD_Study::update3dViewers() 
1273 {
1274   for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1275     sf->getRightFrame()->getViewFrame()->Repaint();
1276   }
1277 }
1278
1279 /* Adds new child window */
1280 void QAD_Study::addChildWidget( QWidget* child )
1281 {
1282   if ( myChildWidgets.findRef( child ) < 0 ) {
1283     myChildWidgets.append( child );
1284     child->installEventFilter( this );
1285   }
1286 }
1287
1288 /*!
1289   Removes child window from the list ( and deletes it )
1290 */
1291 void QAD_Study::removeChildWidget( QWidget* child )
1292 {
1293   myChildWidgets.removeRef( child );
1294 }
1295
1296 /* Event filter */
1297 bool QAD_Study::eventFilter( QObject* o, QEvent* e)
1298 {
1299   int index = myChildWidgets.findRef( ( QWidget* )o );
1300   if ( index >= 0 && e->type() == QEvent::Close ) {
1301     myChildWidgets.at( index )->removeEventFilter( this );
1302     myChildWidgets.remove( ( QWidget* )o );
1303     return TRUE;
1304   }
1305   return QObject::eventFilter( o, e );
1306 }
1307