1 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : QAD_Study.cxx
25 // Author : Nicolas REJNERI
30 \class QAD_Study QAD_Study.h
31 \brief Study for QAD-based application.
35 #include "QAD_Tools.h"
36 #include "QAD_Desktop.h"
37 #include "QAD_Study.h"
38 #include "QAD_RightFrame.h"
39 #include "QAD_LeftFrame.h"
40 #include "QAD_MessageBox.h"
41 #include "QAD_Application.h"
42 #include "QAD_ObjectBrowser.h"
43 #include "QAD_PyInterp.h"
44 #include "QAD_Config.h"
45 #include "QAD_PyInterp.h"
47 #include "utilities.h"
49 #include "SALOME_Selection.h"
50 #include "SALOME_TypeFilter.hxx"
51 #include "SALOME_InteractiveObject.hxx"
52 #include "SALOME_ListIteratorOfListIO.hxx"
54 #include <SALOMEconfig.h>
55 #include CORBA_SERVER_HEADER(SALOMEDS)
57 // OPEN CASCADE Include
58 #include <Standard_Failure.hxx>
61 #include <qapplication.h>
69 static int MYDEBUG = 1;
71 static int MYDEBUG = 0;
75 class TInitStudyThread : public QThread{
77 TInitStudyThread(const TInitStudyThread&);
80 TInitStudyThread(QAD_PyInterp*& theInterp, QMutex* theMutex):
82 myStudyLock(new ThreadLock(theMutex,"TInitStudyThread::TInitStudyThread"))
84 virtual ~TInitStudyThread() {
92 ThreadLock aPyLock = GetPyThreadLock("TInitStudyThread::aPyLock");
93 if(MYDEBUG) MESSAGE("TInitStudyThread::run()");
94 myInterp = new QAD_PyInterp();
95 myInterp->initialize();
102 QAD_PyInterp*& myInterp;
103 ThreadLock* myStudyLock;
110 QAD_Study::QAD_Study(QAD_Application* theApp,
111 SALOMEDS::Study_var theStudy,
112 const QString& thePath):
114 myOperationState(Undef),
116 myActiveStudyFrame(0),
117 myStudyFrameCount(0),
119 myTitle(QAD_Tools::getFileNameFromPath(thePath,true)),
126 myInitStudyThread(0),
127 myMutex(new QMutex())
129 myStudyFrames.setAutoDelete( true );
130 myOperations.setAutoDelete( true );
131 myChildWidgets.setAutoDelete( true );
133 /* create default selection */
134 //NRI Selection( "Salome" );
135 Selection( QAD_Application::getDesktop()->getComponentUserName( "KERNEL" ) );
137 /* create python interpreter */
138 myInitStudyThread = new TInitStudyThread(myInterp,myMutex);
139 myInitStudyThread->start();
141 /* create study frame */
142 createStudyFrame( getNextStudyFrameName() );
144 /* set default Undo/Redo limit */
145 QAD_ASSERT_DEBUG_ONLY( !myStudy->_is_nil() );
146 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
148 int aLocked = myStudy->GetProperties()->IsLocked();
149 if (aLocked) myStudy->GetProperties()->SetLocked(false);
150 SB->UndoLimit(QAD_Desktop::getUndoLevel());
151 if (aLocked) myStudy->GetProperties()->SetLocked(true);
155 void QAD_Study::Init()
163 QAD_Study::~QAD_Study ()
166 //SRN: added - clear selection in case the study will be loaded again so the title will coincide
167 SALOME_Selection::RemoveSelection( QString(myTitle + "_" + mySelection) );
170 ThreadLock aLock(myMutex,"QAD_Study::~QAD_Study()");
171 delete myInitStudyThread;
179 Returns TRUE if Study is created correctly. Returns FALSE otherwise.
181 bool QAD_Study::getResult()
187 //=======================================================================//
188 // StudyFrames management //
189 //=======================================================================//
193 void QAD_Study::addStudyFrame(QAD_StudyFrame* sf )
195 myStudyFrames.append( sf );
197 sf->getRightFrame()->getViewFrame()->setPopupServer( myApp );
198 // Provide the same common popup menu commands for both the Object Browser and 3D viewer
199 sf->getLeftFrame()->getObjectBrowser()->setPopupServer( myApp );
201 /* icon of Study Frame */
202 const QPixmap& icon = myApp->getApplicationIcon();
203 if ( !icon.isNull() )
204 sf->setIcon ( icon );
207 QAD_ASSERT ( connect( sf, SIGNAL(sfStudyFrameActivated(QAD_StudyFrame*) ),
208 SLOT(onStudyFrameActivated(QAD_StudyFrame*))) );
211 QAD_ASSERT ( connect( sf,
212 SIGNAL(sfStudyFrameClosing(QAD_StudyFrame*) ),
214 SLOT(onLastStudyFrameClosing(QAD_StudyFrame*))) );
217 myActiveStudyFrame = sf;
221 Removes studyframe from the list
223 void QAD_Study::removeStudyFrame( QAD_StudyFrame* sf )
226 if (!myStudy->IsEmpty()) {
227 SALOMEDS::SObject_var fatherSF = myStudy->FindObjectID(sf->entry());
228 if (!fatherSF->_is_nil()) {
229 SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
230 int aLocked = myStudy->GetProperties()->IsLocked();
231 if (aLocked) myStudy->GetProperties()->SetLocked(false);
232 aStudyBuilder->RemoveObject(fatherSF);
233 if (aLocked) myStudy->GetProperties()->SetLocked(true);
236 updateObjBrowser( true );
238 myStudyFrames.removeRef( sf );
243 Returns number of study frames
245 int QAD_Study::getStudyFramesCount() const
247 return myStudyFrames.count();
251 Returns study frame by its index in list
253 QAD_StudyFrame* QAD_Study::getStudyFrame( unsigned i )
255 return myStudyFrames.at(i);
259 Returns study frame by its name or null if not found
261 QAD_StudyFrame* QAD_Study::getStudyFrameByName ( const QString& name )
263 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() )
265 if ( sf->title().compare(name) == 0 ) {
273 Returns first study frame in the list
275 QAD_StudyFrame* QAD_Study::getFirstStudyFrame()
277 return myStudyFrames.first();
281 Returns last study frame in the list
283 QAD_StudyFrame* QAD_Study::getLastStudyFrame()
285 return myStudyFrames.last();
289 Returns the vector of studyframes
291 const QList<QAD_StudyFrame>& QAD_Study::getStudyFrames() const
293 return myStudyFrames;
297 Returns the active study frame
299 QAD_StudyFrame* QAD_Study::getActiveStudyFrame() const
301 return myActiveStudyFrame;
304 //=======================================================================//
305 // Study properties //
306 //=======================================================================//
308 Returns reference to supporting application
310 QAD_Application* QAD_Study::getApp() const
316 Returns the name of document ( filename without path and extension )
318 const QString& QAD_Study::getTitle() const
324 Returns the absolute file path of this document
326 const QString& QAD_Study::getPath() const
332 Changes the name of document
334 void QAD_Study::setTitle( const QString& path )
338 QString title = QAD_Tools::getFileNameFromPath( path, true );
339 QAD_ASSERT_DEBUG_ONLY ( !title.isNull() );
341 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf ; sf = myStudyFrames.next() )
343 QString oldName = sf->title();
344 int k = oldName.find( myTitle, 0, false );
345 QString restName = ( oldName.length() > myTitle.length() + k) ?
346 oldName.right(oldName.length() - (myTitle.length() + k) + 1) :
353 int l = restName.find( "#", 0, false );
354 int ll = restName.length();
355 newName = title + restName.mid( l, ll-l );
357 newName = oldName.mid(0, k);
358 newName = newName + title + restName;
360 sf->setTitle( newName );
365 Selection( QAD_Application::getDesktop()->getActiveComponent() );
369 Returns whether the document is active
371 bool QAD_Study::isActive() const
377 Returns whether the document is read only
379 bool QAD_Study::isReadOnly() const
385 Sets read-only property
387 void QAD_Study::setReadOnly(bool state)
389 myIsReadOnly = state;
392 //=======================================================================//
393 // Study operations //
394 //=======================================================================//
396 Performs specific study frame related actions when it is activated.
397 By default resumes all suspended operations.
399 void QAD_Study::onStudyFrameActivated( QAD_StudyFrame* activeStudyFrame )
401 // static int IS_FIRST_STUDY = 1;
402 // if(IS_FIRST_STUDY){ //for normally initialize "salome.py and ..."
403 // _interp->run(""); IS_FIRST_STUDY = 0;
405 // bool found = false;
406 for ( QAD_StudyFrame* studyframe = myStudyFrames.first(); studyframe; studyframe = myStudyFrames.next() ) {
407 if ( studyframe == activeStudyFrame) { /* one of my study frames */
409 // if ( !myActiveStudyFrame || myActiveStudyFrame != activeStudyFrame ) {
410 myActiveStudyFrame = activeStudyFrame;
411 //NRI if ( !myIsActive ) {
413 resumeAllOperations();
414 /* activate application */
415 myApp->onStudyActivated( this );
422 // myActiveStudyFrame = 0;
427 Performs specific study related actions when it is deactivated.
428 By default suspends all performing operations.
430 void QAD_Study::onStudyDeactivated()
432 // MESSAGE ("QAD_Study::onStudyDeactivated init. ");
434 suspendAllOperations();
435 // MESSAGE ("QAD_Study::onStudyDeactivated done. ");
439 Closes all study frames of the study and performs other specific study
440 related actions needed for proper closing of the study
442 void QAD_Study::close()
445 if ( !myStudy->_is_nil() )
446 abortAllOperations();
447 /* clear each study frame */
448 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.first() ) {
451 qApp->processEvents();
452 qApp->processEvents();
453 removeStudyFrame(sf);
456 /* delete all studyframes */
457 myStudyFrames.clear();
458 myOperations.clear();
459 myChildWidgets.clear();
461 // QWorkspace* ws = QAD_Application::getDesktop()->getMainFrame();
462 // if (/* !ws->activeWindow() && */ws->windowList().count() > 0 )
463 // ws->activateWindow(ws->windowList().last());
466 //=======================================================================//
467 // Operations management //
468 //=======================================================================//
470 Returns number of completed operations
472 int QAD_Study::getOperationsCount() const
474 return myOperations.count();
478 Returns the state of the last operation
480 OperationState QAD_Study::getOperationState() const
482 return myOperationState;
486 Returns operation by its index in list
488 QAD_Operation* QAD_Study::getOperation( unsigned i)
490 return ( myOperations.isEmpty() ? 0 : myOperations.at(i) );
494 Returns performing operation launched first
496 QAD_Operation* QAD_Study::getFirstOperation()
498 return ( myOperations.isEmpty() ? 0 : myOperations.first() );
502 Returns performing operation launched last
504 QAD_Operation* QAD_Study::getLastOperation()
506 return ( myOperations.isEmpty() ? 0 : myOperations.last() );
510 Aborts all performing operations
512 void QAD_Study::abortAllOperations()
514 for ( QAD_Operation* op = myOperations.last(); op;
515 op = myOperations.prev() )
520 Resumes all performing operations
522 void QAD_Study::resumeAllOperations()
524 for ( QAD_Operation* op = myOperations.first(); op;
525 op = myOperations.next() )
530 Suspendes all performing operations
532 void QAD_Study::suspendAllOperations()
534 // MESSAGE ( " QAD_Study::suspendAllOperations init. " )
535 for ( QAD_Operation* op = myOperations.last(); op;
536 op = myOperations.prev() )
541 Initializes the operation and checks its compatibility
542 with another operation in process if any.
543 Returns 'true' if init'ed OK, 'false' otherwise.
545 bool QAD_Study::initOperation( QAD_Operation* op )
548 { /* can't start a non-const operation */
549 if ( op->changesData() )
551 QAD_MessageBox::error1( QAD_Application::getDesktop(), tr("ERR_ERROR"),
552 tr("ERR_DOC_READONLY"), tr("BUT_OK") );
557 /* Add the new operation
559 if ( myOperations.isEmpty() )
560 myOperations.append( op );
563 /* Check compatibility of new operation with the existing operations.
564 Since each operations is checked in that way, it's enough to check
565 the last operation only */
566 if ( !getLastOperation()->compatibleWith( op ) )
568 if ( QAD_MessageBox::warn2( QAD_Application::getDesktop(), tr("WRN_WARNING"),
569 tr("QUE_ABORTCURRENTOPERATION"), tr("BUT_YES"),
570 tr("BUT_NO"), QAD_YES, QAD_NO, QAD_NO )
573 getLastOperation()->abort();
575 myOperations.append( op );
581 Called when operation was finished.
582 Removes appointed operation from the list and aborted all operations
585 void QAD_Study::clearOperation( QAD_Operation* op)
587 if ( myOperations.contains( op ) )
589 /* abort all the operations launched after 'op' */
590 for ( QAD_Operation* cur = myOperations.last(); cur;
591 cur = myOperations.prev() )
593 if ( cur == op ) break;
596 myOperations.remove( op );
603 QAD_StudyFrame* QAD_Study::createStudyFrame( const QString& title, ViewType theViewType)
605 QAD_Desktop* parent = QAD_Application::getDesktop();
606 //srn: Forbid appending Interface Applicative and its children to UseCase
607 myStudy->EnableUseCaseAutoFilling(false);
609 SALOMEDS::SComponent_var father = myStudy->FindComponent("Interface Applicative");
610 SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
611 SALOMEDS::GenericAttribute_var anAttr;
612 SALOMEDS::AttributeName_var aName;
613 SALOMEDS::AttributeComment_var aComment;
614 SALOMEDS::AttributeSelectable_var aSelAttr;
616 // mpv : where is "NewCommand" call?
617 // aStudyBuilder->CommitCommand();
619 // mpv : is study is locked, then next code will raise exception. So, temporary unlock study
620 int aLocked = myStudy->GetProperties()->IsLocked();
621 if (aLocked) myStudy->GetProperties()->SetLocked(false);
623 if ( father->_is_nil() ) {
624 father = aStudyBuilder->NewComponent("Interface Applicative");
625 anAttr = aStudyBuilder->FindOrCreateAttribute(father, "AttributeName");
626 aName = SALOMEDS::AttributeName::_narrow(anAttr);
627 aName->SetValue("Interface Applicative");
629 anAttr = aStudyBuilder->FindOrCreateAttribute(father, "AttributeSelectable");
630 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
631 aSelAttr->SetSelectable(false);
634 //VRV: T2.5 - add default viewer
635 if(theViewType == VIEW_TYPE_MAX) {
636 QString viewerValue = QAD_CONFIG->getSetting( "Viewer:DefaultViewer" );
638 theViewType = (ViewType)viewerValue.toInt( &ok, 10 );
639 if (!ok || theViewType < VIEW_OCC || theViewType >= VIEW_TYPE_MAX)
640 theViewType = VIEW_VTK;
642 //QApplication::restoreOverrideCursor();
643 QAD_StudyFrame* sf = NULL;
644 SALOMEDS::SObject_var newObj = aStudyBuilder->NewObject(father);
645 if ( theViewType == VIEW_OCC) {
646 // MESSAGE ("Create Study Frame for OCC viewer");
647 sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
651 Standard_CString name = strdup(sf->title().latin1());
652 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
653 aName = SALOMEDS::AttributeName::_narrow(anAttr);
654 aName->SetValue(name);
655 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
656 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
657 aComment->SetValue("OCC");
659 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
660 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
661 aSelAttr->SetSelectable(false);
663 else if ( theViewType == VIEW_VTK) {
664 // MESSAGE ("Create Study Frame for VTK viewer");
665 sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
668 Standard_CString name = strdup(sf->title().latin1());
669 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
670 aName = SALOMEDS::AttributeName::_narrow(anAttr);
671 aName->SetValue(name);
672 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
673 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
674 aComment->SetValue("VTK");
676 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
677 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
678 aSelAttr->SetSelectable(false);
680 else if ( theViewType == VIEW_GRAPHSUPERV) {
681 //MESSAGE ("Create Study Frame for SUPER`VISOR Graph");
682 sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
683 title, VIEW_GRAPHSUPERV,
685 Standard_CString name = strdup(sf->title().latin1());
686 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
687 aName = SALOMEDS::AttributeName::_narrow(anAttr);
688 aName->SetValue(name);
689 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
690 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
691 aComment->SetValue("GRAPH");
693 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
694 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
695 aSelAttr->SetSelectable(false);
697 else if ( theViewType == VIEW_PLOT2D ) {
698 sf = new QAD_StudyFrame ( this, parent->getMainFrame(),
701 Standard_CString name = strdup(sf->title().latin1());
702 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeName");
703 aName = SALOMEDS::AttributeName::_narrow(anAttr);
704 aName->SetValue(name);
705 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeComment");
706 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
707 aComment->SetValue("PLOT2D");
709 anAttr = aStudyBuilder->FindOrCreateAttribute(newObj, "AttributeSelectable");
710 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
711 aSelAttr->SetSelectable(false);
713 //VRV: T2.5 - add default viewer
715 sf->resize( int (0.8*parent->getMainFrame()->width()),
716 int (0.8*parent->getMainFrame()->height() ));
718 sf->setEntry(newObj->GetID());
722 updateObjBrowser( true );
724 parent->setSettings();
728 if (aLocked) myStudy->GetProperties()->SetLocked(true);
730 // T2.12 - add the word "locked" to study frame captions if this study is locked
733 myStudy->EnableUseCaseAutoFilling(true);
739 Updates study frame captions according to IsLocked study flag
741 void QAD_Study::updateCaptions()
743 QString appendix("");
745 if (!myStudy->_is_nil()) {
746 SALOMEDS::AttributeStudyProperties_var propAttr = myStudy->GetProperties();
748 if (!propAttr->_is_nil() ) {
749 if ( propAttr->IsModified() )
750 appendix += " (" + tr("PRP_STUDY_MODIFIED") + ")";
752 appendix += " (" + tr("PRP_STUDY_SAVED") + ")";
756 if (!propAttr->_is_nil() && propAttr->IsLocked()) {
757 appendix += " (" + tr("PRP_STUDY_LOCKED") + ")";
761 for (myStudyFrames.first(); myStudyFrames.current(); myStudyFrames.next()) {
762 myStudyFrames.current()->setCaption(myStudyFrames.current()->title() + appendix);
768 Shows the active study frame.
769 Called by Desktop after 'new' and 'open' commands.
771 void QAD_Study::show()
773 for (myStudyFrames.first(); myStudyFrames.current(); myStudyFrames.next()) {
774 myStudyFrames.current()->show();
778 //=======================================================================//
779 // Study properties (CAF related) //
780 //=======================================================================//
783 Returns connected SALOMEDS_Study object
785 SALOMEDS::Study_var QAD_Study::getStudyDocument()
791 Returns whether the document was saved in file
793 bool QAD_Study::isSaved() const
795 return myStudy->IsSaved();
799 Returns whether the document is modified
801 bool QAD_Study::isModified() const
803 // return myStudy->IsModified(); // VSR:05/12/02 - USE PROPERTY : MODIFIED FLAG
804 if ( !myStudy->_is_nil() ) {
805 SALOMEDS::AttributeStudyProperties_var propAttr = myStudy->GetProperties();
806 if ( !propAttr->_is_nil() )
807 return propAttr->IsModified();
812 bool QAD_Study::undo()
815 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
818 /* Update Object Browser */
819 updateObjBrowser( true );
821 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
823 sf->getRightFrame()->getViewFrame()->undo( myStudy, sf->entry() );
827 // mpv 07.03.2003 SAL1805: clear selection must be called after study structure changed
828 SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
829 Sel->ClearIObjects();
831 // mpv : undo command can raise exception, if study is locked
832 catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
833 QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
834 QObject::tr("WRN_WARNING"),
835 QObject::tr("WRN_STUDY_LOCKED"),
836 QObject::tr("BUT_OK"));
839 catch ( Standard_Failure ) {
847 bool QAD_Study::redo()
850 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
853 /* Update Object Browser */
854 updateObjBrowser( true );
857 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
858 sf->getRightFrame()->getViewFrame()->redo( myStudy, sf->entry() );
862 // mpv 07.03.2003 SAL1805: clear selection must be called after study structure changed
863 SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
864 Sel->ClearIObjects();
866 // mpv : redo command can raise exception, if study is locked
867 catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
868 QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
869 QObject::tr("WRN_WARNING"),
870 QObject::tr("WRN_STUDY_LOCKED"),
871 QObject::tr("BUT_OK"));
874 catch ( Standard_Failure ) {
880 Check if possible to perform 'undo' command
882 bool QAD_Study::canUndo() const
884 if ( myStudy->_is_nil() )
887 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
888 return (SB->GetAvailableUndos() > 0 );
892 Check if possible to perform 'redo' command
894 bool QAD_Study::canRedo() const
896 if ( myStudy->_is_nil() )
899 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
900 return (SB->GetAvailableRedos() > 0 );
904 Called when operation is started
905 Returns 'true' if started OK, 'false' otherwise.
907 bool QAD_Study::onOperationStarted( QAD_Operation* op )
909 if ( !initOperation( op ) )
913 { /* start a new transaction */
914 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
917 catch ( Standard_Failure )
919 /* May be, a transaction is already open,
920 it's not a problem */
922 myOperationState = Started;
927 Called when operation is finished
929 void QAD_Study::onOperationFinished( QAD_Operation* op )
932 /* transaction is completed OK */
933 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
936 catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
937 QApplication::restoreOverrideCursor();
938 QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
939 QObject::tr("WRN_WARNING"),
940 QObject::tr("WRN_STUDY_LOCKED"),
941 QObject::tr("BUT_OK"));
942 onOperationAborted(op);
943 updateObjBrowser( true );
946 catch ( Standard_Failure ) {
948 myOperationState = Finished;
949 emit docOperationTerminated( true ); /* terminated successfully */
952 // mpv: any operation must call this method, otherwise study may not be saved
953 updateObjBrowser( true );
955 clearOperation( op ); /* we don't need the operation anymore */
956 QAD_Application::getDesktop()->putInfo ( tr("INF_DOC_OPERATIONFINISHED") );
960 Called when operation is suspended
962 void QAD_Study::onOperationSuspended( QAD_Operation* op )
964 myOperationState = Suspended;
968 Called when operation is resumed
970 void QAD_Study::onOperationResumed( QAD_Operation* op )
972 myOperationState = Resumed;
976 Called when operation is aborted
978 void QAD_Study::onOperationAborted(QAD_Operation* op)
981 /* abort transaction */
982 SALOMEDS::StudyBuilder_var SB = myStudy->NewBuilder();
985 catch ( Standard_Failure )
988 myOperationState = Aborted;
989 emit docOperationTerminated( false ); /* aborted */
994 QAD_Application::getDesktop()->putInfo ( tr("INF_DOC_OPERATIONABORTED") );
998 Call when the last study frame is closing
1000 void QAD_Study::onLastStudyFrameClosing( QAD_StudyFrame* sf )
1002 if ( myStudyFrames.count() == 1 ) {
1003 emit docClosing( this );
1005 removeStudyFrame( sf );
1007 // QWorkspace* ws = QAD_Application::getDesktop()->getMainFrame();
1008 // if ( !ws->activeWindow() && ws->windowList().count() > 0 )
1009 // ws->activatePreviousWindow();
1013 Call when created a new window3d
1015 QAD_StudyFrame* QAD_Study::newWindow3d(QString name, ViewType theViewType, bool toShow)
1017 if(name == "") name = getNextStudyFrameName();
1018 QAD_StudyFrame* sf = createStudyFrame( name, theViewType );
1020 if (toShow) showFrame(sf);
1021 // sf->compressLeft(); /* compress LeftFrame */
1022 sf->getRightFrame()->compressBottom(); /* compress BottomFrame */
1028 void QAD_Study::showFrame(QAD_StudyFrame* theFrame){
1029 theFrame->resize( (int)(0.64*QAD_Application::getDesktop()->getMainFrame()->width()),
1030 (int)(0.64*QAD_Application::getDesktop()->getMainFrame()->height()));
1038 Call when setted a message
1040 void QAD_Study::setMessage(const char* message)
1042 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1043 sf->getRightFrame()->getMessage()->setMessage(message);
1048 Call when updated object browser
1050 void QAD_Study::updateObjBrowser( bool updateSelection )
1052 QAD_Desktop* parent = QAD_Application::getDesktop();
1053 SALOME_ModuleCatalog::ModuleCatalog_var Catalog = parent->getCatalogue();
1055 QString ActiveComp = parent->getActiveComponent();
1057 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1058 sf->getLeftFrame()->getObjectBrowser()->Update();
1061 /* update selection */
1062 if ( updateSelection && (myStudyFrames.count() > 0) ) {
1063 SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
1064 SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
1065 for(;It.More();It.Next()) {
1066 if ( Sel->AddIObject( It.Value() ) == 0 ) {
1067 highlight( It.Value(), true, false );
1071 /* update viewers */
1076 Updates only Use Case Browser
1078 void QAD_Study::updateUseCaseBrowser( bool updateSelection )
1080 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1081 sf->getLeftFrame()->getObjectBrowser()->UpdateUseCaseBrowser();
1083 /* update selection */
1084 if ( updateSelection && (myStudyFrames.count() > 0) ) {
1085 SALOME_Selection* Sel = SALOME_Selection::Selection( getSelection() );
1086 SALOME_ListIteratorOfListIO It( Sel->StoredIObjects() );
1087 for(;It.More();It.Next()) {
1088 if ( Sel->AddIObject( It.Value() ) == 0 ) {
1089 highlight( It.Value(), true, false );
1092 /* update viewers */
1098 unHighlight All Interactive Objects in All Devices
1100 void QAD_Study::unHighlightAll()
1102 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1103 /* Device = Viewers */
1104 sf->getRightFrame()->getViewFrame()->unHighlightAll();
1106 /* Device = ObjectBrowser */
1107 sf->getLeftFrame()->getObjectBrowser()->unHighlightAll();
1112 Returns type of Interactive Object
1114 int QAD_Study::typeIObject( const Handle(SALOME_InteractiveObject)& IObject )
1116 bool IsStudyObject = isInStudy( IObject );
1117 bool IsGraphicalObject = isInViewer( IObject );
1119 // MESSAGE ( "IsStudyObject : " << IsStudyObject )
1120 // MESSAGE ( "IsGraphicalObject : " << IsGraphicalObject )
1122 if ( IsStudyObject ) {
1123 if ( IsGraphicalObject )
1124 return 1; /* StudyObject and GraphicalObject */
1126 return 2; /* only StudyObject */
1128 if ( IsGraphicalObject )
1129 return 3; /* only GraphicalObject */
1131 return 4; /* may be a component */
1138 Renames the Interactive Object in All Devices
1140 void QAD_Study::renameIObject( const Handle(SALOME_InteractiveObject)& IObject, QString newName )
1142 if (myStudy->GetProperties()->IsLocked()) {
1143 QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
1144 QObject::tr("WRN_WARNING"),
1145 QObject::tr("WRN_STUDY_LOCKED"),
1146 QObject::tr("BUT_OK"));
1150 highlight( IObject, false );
1152 int nbFrames = myStudyFrames.count();
1153 for ( int i = 0; i < nbFrames; i++ ) {
1154 QAD_StudyFrame* sf = myStudyFrames.at( i );
1155 switch ( typeIObject(IObject) ) {
1158 /* Device = Viewers */
1159 sf->getRightFrame()->getViewFrame()->rename(IObject, newName);
1160 /* Device = ObjectBrowser */
1161 sf->getLeftFrame()->getObjectBrowser()->rename(IObject, newName);
1166 /* Device = ObjectBrowser */
1167 sf->getLeftFrame()->getObjectBrowser()->rename(IObject, newName);
1172 /* Device = Viewers */
1173 sf->getRightFrame()->getViewFrame()->rename(IObject, newName);
1178 QString ActiveComp = QAD_Application::getDesktop()->getActiveComponent();
1179 if ( !ActiveComp.isEmpty() ) {
1180 sf->getLeftFrame()->getObjectBrowser()->rename(IObject,newName);
1188 SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
1189 SALOMEDS::SObject_var obj = myStudy->FindObjectID( IObject->getEntry() );
1190 if ( !obj->_is_nil() ) {
1191 SALOMEDS::GenericAttribute_var anAttr;
1192 SALOMEDS::AttributeName_var aName;
1193 anAttr = aStudyBuilder->FindOrCreateAttribute(obj, "AttributeName");
1194 aName = SALOMEDS::AttributeName::_narrow(anAttr);
1195 aName->SetValue(strdup(newName.latin1()));
1198 // VSR 13/03/03 - rename Interactive object
1199 IObject->setName( ( char* )newName.latin1() );
1201 updateObjBrowser( true );
1205 Selects the Interactive Object in All Devices
1207 void QAD_Study::highlight( const Handle(SALOME_InteractiveObject)& IObject, bool highlight,bool immediatly )
1209 // MESSAGE ( " QAD_Study::highlight : " << highlight )
1210 int typeIO = typeIObject( IObject );
1212 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1216 /* Device = Viewer */
1217 if (sf->getTypeView() >= 0 ) { /* Device = Viewers */
1218 sf->getRightFrame()->getViewFrame()->highlight(IObject, highlight, immediatly);
1220 /* Device = ObjectBrowser */
1221 sf->getLeftFrame()->getObjectBrowser()->highlight(IObject, highlight);
1226 /* Device = ObjectBrowser */
1227 sf->getLeftFrame()->getObjectBrowser()->highlight(IObject, highlight);
1232 /* Device = Viewer */
1233 if (sf->getTypeView() >= 0) { /* Device = Viewers */
1234 sf->getRightFrame()->getViewFrame()->highlight(IObject, highlight, immediatly);
1240 QString ActiveComp = QAD_Application::getDesktop()->getActiveComponent();
1241 if ( !ActiveComp.isEmpty() ) {
1242 sf->getLeftFrame()->getObjectBrowser()->highlight(IObject,highlight);
1251 Returns TRUE if the IObject is a Study Object. Returns FALSE otherwise.
1253 bool QAD_Study::isInStudy( const Handle(SALOME_InteractiveObject)& IObject )
1255 return IObject->hasEntry();
1259 Returns true if the IObject has a Graphical Object. Returns FALSE otherwise.
1261 bool QAD_Study::isInViewer( const Handle(SALOME_InteractiveObject)& IObject )
1264 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1265 found = sf->getRightFrame()->getViewFrame()->isInViewer(IObject);
1273 Returns true if the IObject has a Graphical Object into studyframe. Returns FALSE otherwise.
1275 bool QAD_Study::isInViewer(const char* anEntry, const char* StudyFrameEntry)
1277 SALOMEDS::SObject_var RefSO;
1278 SALOMEDS::SObject_var SO = myStudy->FindObjectID(StudyFrameEntry);
1279 SALOMEDS::ChildIterator_var it = myStudy->NewChildIterator(SO);
1280 for (; it->More();it->Next()){
1281 SALOMEDS::SObject_var CSO= it->Value();
1282 if (CSO->ReferencedObject(RefSO))
1283 if ( strcmp( anEntry, RefSO->GetID() ) == 0 )
1291 Returns title for the new studyframe window
1293 QString QAD_Study::getNextStudyFrameName()
1295 QString numStudyFrame;
1296 numStudyFrame.sprintf("%s%d", "#", ++myStudyFrameCount );
1297 return myTitle + numStudyFrame; /* return unique name ( title + unique number) */
1302 Returns the Python interpreter that belongs to this study
1304 QAD_PyInterp* QAD_Study::get_PyInterp(void)
1310 Sets current selection.
1312 void QAD_Study::Selection( QString aSelection )
1314 if ( !SALOME_Selection::FindSelection( QString(myTitle + "_" + aSelection) ) )
1315 SALOME_Selection::CreateSelection( QString(myTitle + "_" + aSelection) );
1317 SALOME_Selection* Sel = SALOME_Selection::Selection( QString(myTitle + "_" + aSelection) );
1319 mySelection = aSelection;
1323 Returns the name of current selection
1325 QString QAD_Study::getSelection()
1327 return QString (myTitle + "_" + mySelection);
1331 Returns the study Id.
1333 int QAD_Study::getStudyId()
1335 return myStudy->StudyId();
1338 void QAD_Study::update3dViewers()
1340 for ( QAD_StudyFrame* sf = myStudyFrames.first(); sf; sf = myStudyFrames.next() ) {
1341 sf->getRightFrame()->getViewFrame()->Repaint();
1345 /* Adds new child window */
1346 void QAD_Study::addChildWidget( QWidget* child )
1348 if ( myChildWidgets.findRef( child ) < 0 ) {
1349 myChildWidgets.append( child );
1350 child->installEventFilter( this );
1355 Removes child window from the list ( and deletes it )
1357 void QAD_Study::removeChildWidget( QWidget* child )
1359 myChildWidgets.removeRef( child );
1363 bool QAD_Study::eventFilter( QObject* o, QEvent* e)
1365 int index = myChildWidgets.findRef( ( QWidget* )o );
1366 if ( index >= 0 && e->type() == QEvent::Close ) {
1367 myChildWidgets.at( index )->removeEventFilter( this );
1368 myChildWidgets.remove( ( QWidget* )o );
1371 return QObject::eventFilter( o, e );