Back to index

salome-gui  6.5.0
SalomeApp_Application.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File:      SalomeApp_Application.cxx
00024 // Created:   10/22/2004 3:23:45 PM
00025 // Author:    Sergey LITONIN
00026 
00027 #ifdef WNT
00028 // E.A. : On windows with python 2.6, there is a conflict
00029 // E.A. : between pymath.h and Standard_math.h which define
00030 // E.A. : some same symbols : acosh, asinh, ...
00031 #include <Standard_math.hxx>
00032 #include <pymath.h>
00033 #endif
00034 
00035 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
00036 #include "SalomeApp_Application.h"
00037 #include "SalomeApp_Study.h"
00038 #include "SalomeApp_DataModel.h"
00039 #include "SalomeApp_DataObject.h"
00040 #include "SalomeApp_VisualState.h"
00041 #include "SalomeApp_StudyPropertiesDlg.h"
00042 #include "SalomeApp_LoadStudiesDlg.h"
00043 #include "SalomeApp_NoteBookDlg.h"
00044 
00045 #include "SalomeApp_ExitDlg.h"
00046 
00047 #include <LightApp_Application.h>
00048 #include <LightApp_Module.h>
00049 #include <LightApp_Preferences.h>
00050 #include <LightApp_SelectionMgr.h>
00051 #include <LightApp_NameDlg.h>
00052 #include <LightApp_DataOwner.h>
00053 #include <LightApp_Displayer.h>
00054 
00055 #include <CAM_Module.h>
00056 
00057 #include <SUIT_Tools.h>
00058 #include <SUIT_Session.h>
00059 #include <SUIT_Desktop.h>
00060 #include <SUIT_DataBrowser.h>
00061 #include <SUIT_FileDlg.h>
00062 #include <SUIT_FileValidator.h>
00063 #include <SUIT_MessageBox.h>
00064 #include <SUIT_ResourceMgr.h>
00065 #include <SUIT_TreeModel.h>
00066 #include <SUIT_ViewWindow.h>
00067 #include <SUIT_ViewManager.h>
00068 #include <SUIT_ViewModel.h>
00069 
00070 #include <QtxTreeView.h>
00071 
00072 #include <SALOME_EventFilter.h>
00073 
00074 // temporary commented
00075 //#include <OB_ListItem.h>
00076 
00077 #include <PyConsole_Console.h>
00078 
00079 #include <Utils_ORB_INIT.hxx>
00080 #include <Utils_SINGLETON.hxx>
00081 #include <SALOME_LifeCycleCORBA.hxx>
00082 
00083 #include <QApplication>
00084 #include <QAction>
00085 #include <QRegExp>
00086 #include <QCheckBox>
00087 #include <QPushButton>
00088 #include <QLabel>
00089 #include <QListWidget>
00090 #include <QGridLayout>
00091 #include <QMenu>
00092 #include <QtDebug>
00093 
00094 #include <SALOMEDSClient_ClientFactory.hxx>
00095 #include <Basics_Utils.hxx>
00096 
00097 #include <SALOME_ListIO.hxx>
00098 #include <SALOME_ListIteratorOfListIO.hxx>
00099 #include <SALOME_Prs.h>
00100 
00101 
00102 #include <ToolsGUI_CatalogGeneratorDlg.h>
00103 #include <ToolsGUI_RegWidget.h>
00104 
00105 #include <vector>
00106 
00108 // temporary commented
00109 /*class SalomeApp_Updater : public OB_Updater
00110 {
00111 public:
00112   SalomeApp_Updater() : OB_Updater(){};
00113   virtual ~SalomeApp_Updater(){};
00114   virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
00115 };
00116 
00117 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
00118 {
00119   if( !theObj || !theItem )
00120     return;
00121 
00122   SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
00123   if( !SAObj )
00124     return;
00125 
00126   _PTR(SObject) SObj = SAObj->object();
00127   if( !SObj )
00128     return;
00129   _PTR( GenericAttribute ) anAttr;
00130 
00131   // Selectable
00132   if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
00133   {
00134     _PTR(AttributeSelectable) aAttrSel = anAttr;
00135     theItem->setSelectable( aAttrSel->IsSelectable() );
00136   }
00137   // Expandable
00138   if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
00139   {
00140     _PTR(AttributeExpandable) aAttrExpand = anAttr;
00141     theItem->setExpandable( aAttrExpand->IsExpandable() );
00142   }
00143   // Opened
00144   //this attribute is not supported in the version of SALOME 3.x
00145   //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
00146   //{
00147   //  _PTR(AttributeOpened) aAttrOpen = anAttr;
00148   //  theItem->setOpen( aAttrOpen->IsOpened() );
00149   //}
00150 }*/
00151 
00153 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
00154 {
00155   return new SalomeApp_Application();
00156 }
00157 
00159 SalomeApp_Application::SalomeApp_Application()
00160   : LightApp_Application()
00161 {
00162   connect( desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
00163            this,      SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
00164 
00165   setNoteBook(0);
00166 }
00167 
00171 SalomeApp_Application::~SalomeApp_Application()
00172 {
00173   // Do not destroy. It's a singleton !
00174   //SALOME_EventFilter::Destroy();
00175 }
00176 
00178 void SalomeApp_Application::start()
00179 {
00180   LightApp_Application::start();
00181 
00182   SALOME_EventFilter::Init();
00183 
00184   static bool isFirst = true;
00185   if ( isFirst ) {
00186     isFirst = false;
00187 
00188     QString hdffile;
00189     QStringList pyfiles;
00190 
00191     for (int i = 1; i < qApp->argc(); i++) {
00192       QRegExp rxs ("--study-hdf=(.+)");
00193       if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
00194         QString file = rxs.capturedTexts()[1];
00195         QFileInfo fi ( file );
00196         QString extension = fi.suffix().toLower();
00197         if ( extension == "hdf" && fi.exists() )
00198           hdffile = fi.absoluteFilePath();
00199       }
00200       else {
00201         QRegExp rxp ("--pyscript=(.+)");
00202         if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
00203           QStringList files = rxp.capturedTexts()[1].split(",",QString::SkipEmptyParts);
00204           pyfiles += files;
00205         }
00206       }
00207     }
00208 
00209     if ( !hdffile.isEmpty() )       // open hdf file given as parameter
00210       onOpenDoc( hdffile );
00211     else if ( pyfiles.count() > 0 ) // create new study
00212       onNewDoc();
00213 
00214     // import/execute python scripts
00215     if ( pyfiles.count() > 0 && activeStudy() ) {
00216       SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
00217       PyConsole_Console* pyConsole = pythonConsole();
00218       if ( appStudy && pyConsole ) {
00219         _PTR(Study) aStudy = appStudy->studyDS();
00220         if ( !aStudy->GetProperties()->IsLocked() ) {
00221           for (uint j = 0; j < pyfiles.count(); j++ ) {
00222             QFileInfo fi ( pyfiles[j] );
00223             QFileInfo fipy ( pyfiles[j] + ".py" );
00224             QString command = QString( "execfile(r\"%1\")" );
00225             if ( fi.isAbsolute() ) {
00226               if ( fi.exists() )
00227                 pyConsole->exec( command.arg( fi.absoluteFilePath() ) );
00228               else if ( fipy.exists() )
00229                 pyConsole->exec( command.arg( fipy.absoluteFilePath() ) );
00230               else
00231                 qDebug() << "Can't execute file" << pyfiles[j];
00232             }
00233             else {
00234               bool found = false;
00235               QStringList dirs;
00236               dirs << QDir::currentPath();
00237               if ( ::getenv( "PYTHONPATH" ) )
00238                 dirs += QString( ::getenv( "PYTHONPATH" ) ).split( QRegExp( "[:|;]" ) );
00239               foreach( QString dir, dirs ) {
00240                 qDebug() << "try" << QFileInfo( dir, pyfiles[j] ).absoluteFilePath();
00241                 qDebug() << "try" << QFileInfo( dir, pyfiles[j] + ".py" ).absoluteFilePath();
00242                 if ( QFileInfo( dir, pyfiles[j] ).exists() ) {
00243                   pyConsole->exec( command.arg( QFileInfo( dir, pyfiles[j] ).absoluteFilePath() ) );
00244                   found = true;
00245                   break;
00246                 }
00247                 else if ( QFileInfo( dir, pyfiles[j] + ".py" ).exists() ) {
00248                   pyConsole->exec( command.arg( QFileInfo( dir, pyfiles[j] + ".py" ).absoluteFilePath() ) );
00249                   found = true;
00250                   break;
00251                 }
00252               }
00253               if ( !found ) {
00254                 qDebug() << "Can't execute file" << pyfiles[j];
00255               }
00256             }
00257           }
00258         }
00259       }
00260     }
00261   }
00262 }
00263 
00265 void SalomeApp_Application::createActions()
00266 {
00267   LightApp_Application::createActions();
00268 
00269   SUIT_Desktop* desk = desktop();
00270 
00272   // "Save GUI State" command is moved to VISU module
00273   //  createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
00274   //            tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
00275   //            0, desk, false, this, SLOT( onSaveGUIState() ) );
00276 
00278   createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
00279                 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
00280                 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
00281 
00283   createAction(NoteBookId, tr( "TOT_DESK_FILE_NOTEBOOK" ), QIcon(),
00284                tr( "MEN_DESK_FILE_NOTEBOOK" ), tr( "PRP_DESK_FILE_NOTEBOOK" ),
00285                Qt::CTRL+Qt::Key_K, desk, false, this, SLOT(onNoteBook()));
00286 
00288   createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
00289                 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
00290                 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
00291 
00293   createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
00294                 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
00295                 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
00296 
00298   createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ),  QIcon(),
00299                 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
00300                 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
00301 
00303   createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ),  QIcon(),
00304                 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
00305                 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
00306 
00307   //SRN: BugID IPAL9021, add an action "Load"
00308   createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
00309                 resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
00310                 tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
00311                 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
00312   //SRN: BugID IPAL9021: End
00313 
00314 
00315   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
00316 
00317   // "Save GUI State" command is renamed to "Save VISU State" and
00318   // creation of menu item is moved to VISU
00319   //  createMenu( SaveGUIStateId, fileMenu, 10, -1 );
00320 
00321   createMenu( FileLoadId,   fileMenu, 0 );  //SRN: BugID IPAL9021, add a menu item "Load"
00322 
00323   createMenu( DumpStudyId, fileMenu, 10, -1 );
00324   createMenu( NoteBookId, fileMenu, 10, -1 );
00325   createMenu( separator(), fileMenu, -1, 10, -1 );
00326   createMenu( LoadScriptId, fileMenu, 10, -1 );
00327   createMenu( separator(), fileMenu, -1, 10, -1 );
00328   createMenu( PropertiesId, fileMenu, 10, -1 );
00329   createMenu( separator(), fileMenu, -1, 10, -1 );
00330 
00331   int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
00332   createMenu( CatalogGenId, toolsMenu, 10, -1 );
00333   createMenu( RegDisplayId, toolsMenu, 10, -1 );
00334   createMenu( separator(), toolsMenu, -1, 15, -1 );
00335 
00336   createExtraActions();
00337 
00338   // import Python module that manages SALOME plugins
00339   PyGILState_STATE gstate = PyGILState_Ensure();
00340   PyObject* pluginsmanager=PyImport_ImportModule((char*)"salome_pluginsmanager");
00341   PyObject* res=PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str());
00342   if(res==NULL)
00343     PyErr_Print();
00344   Py_XDECREF(res);
00345   PyGILState_Release(gstate);
00346   // end of SALOME plugins loading
00347 
00348 }
00349 
00350 
00352 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
00353 {
00354   LightApp_Application::setDesktop( desk );
00355 
00356   if ( desk ) {
00357     connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
00358              this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
00359   }
00360 }
00361 
00365 void SalomeApp_Application::onExit()
00366 {
00367   bool killServers = false;
00368   bool result = true;
00369 
00370   if ( exitConfirmation() ) {
00371     SalomeApp_ExitDlg dlg( desktop() );
00372     result = dlg.exec() == QDialog::Accepted;
00373     killServers = dlg.isServersShutdown();
00374   }
00375 
00376   if ( result )
00377     SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
00378 }
00379 
00381 void SalomeApp_Application::onLoadDoc()
00382 {
00383   QString studyName;
00384 
00385   std::vector<std::string> List = studyMgr()->GetOpenStudies();
00386 
00387   SUIT_Session* aSession = SUIT_Session::session();
00388   QList<SUIT_Application*> aAppList = aSession->applications();
00389 
00390   QStringList unloadedStudies;
00391 
00392   for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
00393      studyName = List[ind].c_str();
00394      // Add to list only unloaded studies
00395      bool isAlreadyOpen = false;
00396      QListIterator<SUIT_Application*> it( aAppList );
00397      while ( it.hasNext() && !isAlreadyOpen ) {
00398        SUIT_Application* aApp = it.next();
00399        if( !aApp || !aApp->activeStudy() )
00400          continue;
00401        if ( aApp->activeStudy()->studyName() == studyName )
00402          isAlreadyOpen = true;
00403      }
00404 
00405      if ( !isAlreadyOpen )
00406        unloadedStudies << studyName;
00407   }
00408 
00409   studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
00410   if ( studyName.isEmpty() )
00411     return;
00412 
00413 #ifndef WIN32
00414   // this code replaces marker of windows drive and path become invalid therefore
00415   // defines placed there
00416   studyName.replace( QRegExp(":"), "/" );
00417 #endif
00418 
00419   if ( onLoadDoc( studyName ) ) {
00420     updateWindows();
00421     updateViewManagers();
00422     updateObjectBrowser( true );
00423   }
00424 }
00425 
00427 void SalomeApp_Application::onNewWithScript()
00428 {
00429   QStringList filtersList;
00430   filtersList.append(tr("PYTHON_FILES_FILTER"));
00431   filtersList.append(tr("ALL_FILES_FILTER"));
00432 
00433   QString anInitialPath = "";
00434   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
00435     anInitialPath = QDir::currentPath();
00436 
00437   QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
00438 
00439   if ( !aFile.isEmpty() )
00440   {
00441     onNewDoc();
00442 
00443     QString command = QString("execfile(r\"%1\")").arg(aFile);
00444 
00445     PyConsole_Console* pyConsole = pythonConsole();
00446 
00447     if ( pyConsole )
00448       pyConsole->exec( command );
00449   }
00450 }
00451 
00452 
00454 bool SalomeApp_Application::onLoadDoc( const QString& aName )
00455 {
00456   bool res = true;
00457   if ( !activeStudy() ) {
00458     // if no study - load in current desktop
00459     res = useStudy( aName );
00460   }
00461   else {
00462     // if study exists - load in new desktop. Check: is the same file is loaded?
00463     SUIT_Session* aSession = SUIT_Session::session();
00464     QList<SUIT_Application*> aAppList = aSession->applications();
00465     bool isAlreadyOpen = false;
00466     SalomeApp_Application* aApp = 0;
00467     for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
00468           it != aAppList.end() && !isAlreadyOpen; ++it ) {
00469       aApp = dynamic_cast<SalomeApp_Application*>( *it );
00470       if ( aApp && aApp->activeStudy()->studyName() == aName )
00471         isAlreadyOpen = true;
00472     }
00473     if ( !isAlreadyOpen ) {
00474       aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
00475       if ( aApp )
00476         res = aApp->useStudy( aName );
00477     }
00478     else {
00479       aApp->desktop()->activateWindow();
00480     }
00481   }
00482 
00483   return res;
00484 }
00485 
00487 void SalomeApp_Application::onCopy()
00488 {
00489   SALOME_ListIO list;
00490   LightApp_SelectionMgr* mgr = selectionMgr();
00491   mgr->selectedObjects(list);
00492 
00493   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
00494   if(study == NULL) return;
00495 
00496   _PTR(Study) stdDS = study->studyDS();
00497   if(!stdDS) return;
00498 
00499   SALOME_ListIteratorOfListIO it( list );
00500   if(it.More())
00501     {
00502       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
00503       try {
00504         studyMgr()->Copy(so);
00505         onSelectionChanged();
00506       }
00507       catch(...) {
00508       }
00509     }
00510 }
00511 
00513 void SalomeApp_Application::onPaste()
00514 {
00515   SALOME_ListIO list;
00516   LightApp_SelectionMgr* mgr = selectionMgr();
00517   mgr->selectedObjects(list);
00518 
00519   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
00520   if(study == NULL) return;
00521 
00522   _PTR(Study) stdDS = study->studyDS();
00523   if(!stdDS) return;
00524 
00525   if ( stdDS->GetProperties()->IsLocked() ) {
00526     SUIT_MessageBox::warning( desktop(),
00527                               QObject::tr("WRN_WARNING"),
00528                               QObject::tr("WRN_STUDY_LOCKED") );
00529     return;
00530   }
00531 
00532   SALOME_ListIteratorOfListIO it( list );
00533   if(it.More())
00534     {
00535       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
00536       try {
00537         studyMgr()->Paste(so);
00538         updateObjectBrowser( true );
00539         updateActions(); //SRN: BugID IPAL9377, case 3
00540       }
00541       catch(...) {
00542       }
00543     }
00544 }
00545 
00549 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
00550 {
00551   return LightApp_Application::isPossibleToClose( closePermanently );
00552 }
00553 
00555 void SalomeApp_Application::onCloseDoc( bool ask )
00556 {
00557   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
00558 
00559   if (study != NULL) {
00560     _PTR(Study) stdDS = study->studyDS();
00561     if(stdDS && stdDS->IsStudyLocked()) {
00562       if ( SUIT_MessageBox::question( desktop(),
00563                                       QObject::tr( "WRN_WARNING" ),
00564                                       QObject::tr( "CLOSE_LOCKED_STUDY" ),
00565                                       SUIT_MessageBox::Yes | SUIT_MessageBox::No,
00566                                       SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
00567 
00568     }
00569   }
00570 
00571   if(myNoteBook && myNoteBook->isVisible())
00572     myNoteBook->hide();
00573 
00574   LightApp_Application::onCloseDoc( ask );
00575 }
00576 
00578 void SalomeApp_Application::onSelectionChanged()
00579 {
00580    SALOME_ListIO list;
00581    LightApp_SelectionMgr* mgr = selectionMgr();
00582    mgr->selectedObjects(list);
00583 
00584    bool canCopy  = false;
00585    bool canPaste = false;
00586 
00587    SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
00588    if (study != NULL) {
00589      _PTR(Study) stdDS = study->studyDS();
00590 
00591      if (stdDS) {
00592        SALOME_ListIteratorOfListIO it ( list );
00593 
00594        if (it.More() && list.Extent() == 1) {
00595          _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
00596 
00597          if ( so ) {
00598              canCopy = studyMgr()->CanCopy(so);
00599              canPaste = studyMgr()->CanPaste(so);
00600          }
00601        }
00602      }
00603    }
00604 
00605    action(EditCopyId)->setEnabled(canCopy);
00606    action(EditPasteId)->setEnabled(canPaste);
00607 }
00608 
00610 void SalomeApp_Application::onDeleteInvalidReferences()
00611 {
00612   SALOME_ListIO aList;
00613   LightApp_SelectionMgr* mgr = selectionMgr();
00614   mgr->selectedObjects( aList, QString(), false );
00615 
00616   if( aList.IsEmpty() )
00617     return;
00618 
00619   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
00620   _PTR(Study) aStudyDS = aStudy->studyDS();
00621   _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
00622   _PTR(SObject) anObj;
00623 
00624   for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
00625     if ( it.Value()->hasEntry() )
00626     {
00627       _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
00628       while( aRefObj && aRefObj->ReferencedObject( anObj ) )
00629         aRefObj = anObj;
00630 
00631       if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
00632          aStudyBuilder->RemoveReference( aSObject );
00633     }
00634   updateObjectBrowser();
00635 }
00636 
00638 void SalomeApp_Application::onOpenWith()
00639 {
00640   QApplication::setOverrideCursor( Qt::WaitCursor );
00641   SALOME_ListIO aList;
00642   LightApp_SelectionMgr* mgr = selectionMgr();
00643   mgr->selectedObjects(aList);
00644   if (aList.Extent() != 1)
00645     {
00646       QApplication::restoreOverrideCursor();
00647       return;
00648     }
00649   Handle(SALOME_InteractiveObject) aIObj = aList.First();
00650   QString aModuleName(aIObj->getComponentDataType());
00651   QString aModuleTitle = moduleTitle(aModuleName);
00652   activateModule(aModuleTitle);
00653   QApplication::restoreOverrideCursor();
00654 }
00655 
00659 SUIT_Study* SalomeApp_Application::createNewStudy()
00660 {
00661   SalomeApp_Study* aStudy = new SalomeApp_Study( this );
00662 
00663   // Set up processing of major study-related events
00664   connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
00665   connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
00666   connect( aStudy, SIGNAL( saved  ( SUIT_Study* ) ), this, SLOT( onStudySaved  ( SUIT_Study* ) ) );
00667   connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
00668 
00669   return aStudy;
00670 }
00671 
00675 void SalomeApp_Application::updateCommandsStatus()
00676 {
00677   LightApp_Application::updateCommandsStatus();
00678 
00679   // Dump study menu
00680   QAction* a = action( DumpStudyId );
00681   if ( a )
00682     a->setEnabled( activeStudy() );
00683 
00684   // Note Book
00685   a = action(NoteBookId);
00686   if( a )
00687     a->setEnabled( activeStudy() );
00688 
00689   // Load script menu
00690   a = action( LoadScriptId );
00691   if ( a )
00692     a->setEnabled( activeStudy() );
00693 
00694   // Properties menu
00695   a = action( PropertiesId );
00696   if( a )
00697     a->setEnabled( activeStudy() );
00698 
00699   // Save GUI state menu
00700   a = action( SaveGUIStateId );
00701   if( a )
00702     a->setEnabled( activeStudy() );
00703 
00704   // update state of Copy/Paste menu items
00705   onSelectionChanged();
00706 }
00707 
00713 class DumpStudyFileDlg : public SUIT_FileDlg
00714 {
00715 public:
00716   DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
00717   {
00718     QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
00719     if ( grid )
00720     {
00721       QWidget *hB = new QWidget( this );
00722       myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
00723       myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
00724       mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
00725 
00726       QHBoxLayout *layout = new QHBoxLayout;
00727       layout->addWidget(myPublishChk);
00728       layout->addWidget(myMultiFileChk);
00729       layout->addWidget(mySaveGUIChk);
00730       hB->setLayout(layout);
00731 
00732       QPushButton* pb = new QPushButton(this);
00733 
00734       int row = grid->rowCount();
00735       grid->addWidget( new QLabel("", this), row, 0 );
00736       grid->addWidget( hB, row, 1, 1, 3 );
00737       grid->addWidget( pb, row, 5 );
00738 
00739       pb->hide();
00740     }
00741   }
00742   QCheckBox* myPublishChk;
00743   QCheckBox* myMultiFileChk;
00744   QCheckBox* mySaveGUIChk;
00745 };
00746 
00747 class DumpStudyFileValidator : public SUIT_FileValidator
00748 {
00749  public:
00750   DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
00751   virtual ~DumpStudyFileValidator() {};
00752   virtual bool canSave( const QString& file, bool permissions );
00753 };
00754 
00755 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
00756 {
00757   QFileInfo fi( file );
00758   if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
00759     SUIT_MessageBox::critical( parent(),
00760                                QObject::tr("WRN_WARNING"),
00761                                QObject::tr("WRN_FILE_NAME_BAD") );
00762     return false;
00763   }
00764   return SUIT_FileValidator::canSave( file, permissions);
00765 }
00766 
00768 void SalomeApp_Application::onDumpStudy( )
00769 {
00770   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
00771   if ( !appStudy ) return;
00772   _PTR(Study) aStudy = appStudy->studyDS();
00773 
00774   QStringList aFilters;
00775   aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
00776 
00777   bool anIsPublish = true;
00778   bool anIsMultiFile = false;
00779   bool anIsSaveGUI = true;
00780 
00781   if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
00782     anIsPublish   = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
00783     anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
00784     anIsSaveGUI   = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
00785   }
00786 
00787   DumpStudyFileDlg fd( desktop() );
00788   fd.setValidator( new DumpStudyFileValidator( &fd ) );
00789   fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
00790   fd.setFilters( aFilters );
00791   fd.myPublishChk->setChecked( anIsPublish );
00792   fd.myMultiFileChk->setChecked( anIsMultiFile );
00793   fd.mySaveGUIChk->setChecked( anIsSaveGUI );
00794   if ( fd.exec() == QDialog::Accepted )
00795   {
00796     QString aFileName = fd.selectedFile();
00797 
00798     bool toPublish = fd.myPublishChk->isChecked();
00799     bool isMultiFile = fd.myMultiFileChk->isChecked();
00800     bool toSaveGUI = fd.mySaveGUIChk->isChecked();
00801 
00802     if ( !aFileName.isEmpty() ) {
00803       QFileInfo aFileInfo(aFileName);
00804       if( aFileInfo.isDir() ) // IPAL19257
00805         return;
00806       
00807       // Issue 21377 - dump study implementation moved to SalomeApp_Study class
00808       bool res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
00809 
00810       if ( !res )
00811         SUIT_MessageBox::warning( desktop(),
00812                                   QObject::tr("WRN_WARNING"),
00813                                   tr("WRN_DUMP_STUDY_FAILED") );
00814     }
00815   }
00816 }
00817 
00819 void SalomeApp_Application::onNoteBook()
00820 {
00821   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
00822   if ( appStudy ) {
00823     _PTR(Study) aStudy = appStudy->studyDS();
00824     if(!myNoteBook) {
00825       myNoteBook = new SalomeApp_NoteBookDlg(desktop(),aStudy);
00826     }
00827     else if(!myNoteBook->isVisible()){
00828       myNoteBook->Init(aStudy);
00829       myNoteBook->adjustSize();
00830       myNoteBook->move((int)(desktop()->x() + desktop()->width()/2  - myNoteBook->frameGeometry().width()/2),
00831                        (int)(desktop()->y() + desktop()->height()/2 - myNoteBook->frameGeometry().height()/2));
00832     }
00833     myNoteBook->show();
00834   }
00835 }
00836 
00838 void SalomeApp_Application::onLoadScript( )
00839 {
00840   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
00841   if ( !appStudy ) return;
00842   _PTR(Study) aStudy = appStudy->studyDS();
00843 
00844   if ( aStudy->GetProperties()->IsLocked() ) {
00845     SUIT_MessageBox::warning( desktop(),
00846                               QObject::tr("WRN_WARNING"),
00847                               QObject::tr("WRN_STUDY_LOCKED") );
00848     return;
00849   }
00850 
00851   QStringList filtersList;
00852   filtersList.append(tr("PYTHON_FILES_FILTER"));
00853   filtersList.append(tr("ALL_FILES_FILTER"));
00854 
00855   QString anInitialPath = "";
00856   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
00857     anInitialPath = QDir::currentPath();
00858 
00859   QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
00860 
00861   if ( !aFile.isEmpty() )
00862   {
00863     QString command = QString("execfile(r\"%1\")").arg(aFile);
00864 
00865     PyConsole_Console* pyConsole = pythonConsole();
00866 
00867     if ( pyConsole )
00868       pyConsole->exec( command );
00869   }
00870 }
00871 
00873 void SalomeApp_Application::onSaveGUIState()
00874 {
00875   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
00876   if ( study ) {
00877     SalomeApp_VisualState( this ).storeState();
00878     updateSavePointDataObjects( study );
00879     updateObjectBrowser();
00880   }
00881   updateActions();
00882 }
00883 
00887 QString SalomeApp_Application::getFileFilter() const
00888 {
00889   return "(*.hdf)";
00890 }
00891 
00893 QWidget* SalomeApp_Application::createWindow( const int flag )
00894 {
00895   QWidget* wid = 0;
00896   if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
00897 
00898   SUIT_ResourceMgr* resMgr = resourceMgr();
00899 
00900   if ( flag == WT_ObjectBrowser )
00901   {
00902     SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
00903     if ( ob ) {
00904       // temporary commented
00905       //ob->setUpdater( new SalomeApp_Updater() );
00906 
00907 #ifdef WITH_SALOMEDS_OBSERVER
00908       //do not activate the automatic update of Qt tree through signal/slot
00909       ob->setAutoUpdate(false);
00910       //activate update of modified objects only
00911       ob->setUpdateModified(true);
00912 #endif
00913 
00914       connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
00915 
00916       QString
00917         ValueCol = QObject::tr( "VALUE_COLUMN" ),
00918         IORCol = QObject::tr( "IOR_COLUMN" ),
00919         RefCol = QObject::tr( "REFENTRY_COLUMN" ),
00920         EntryCol = QObject::tr( "ENTRY_COLUMN" );
00921 
00922       SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
00923       treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
00924       treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
00925       treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
00926       treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
00927       treeModel->setAppropriate( EntryCol, Qtx::Toggled );
00928       treeModel->setAppropriate( ValueCol, Qtx::Toggled );
00929       treeModel->setAppropriate( IORCol, Qtx::Toggled );
00930       treeModel->setAppropriate( RefCol, Qtx::Toggled );
00931 
00932       bool autoSize      = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
00933       bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
00934       bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
00935 
00936       ob->setAutoSizeFirstColumn(autoSizeFirst);
00937       ob->setAutoSizeColumns(autoSize);
00938       ob->setResizeOnExpandItem(resizeOnExpandItem);
00939       ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
00940 
00941       // temporary commented
00942       /*
00943       for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
00944       {
00945       ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
00946       ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
00947                                                     QString().sprintf( "visibility_column_%d", i ), true ) );
00948       }
00949       */
00950 
00951       // temporary commented
00952       /*
00953         ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
00954         ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
00955         ob->resize( desktop()->width()/3, ob->height() );
00956       */
00957     }
00958   }
00959   else if ( flag == WT_PyConsole )
00960   {
00961     PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new SalomeApp_PyInterp() );
00962     pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
00963     pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
00964     pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
00965     pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
00966     wid = pyCons;
00967     //pyCons->resize( pyCons->width(), desktop()->height()/4 );
00968     pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
00969   }
00970   return wid;
00971 }
00972 
00974 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
00975 {
00976   LightApp_Application::createPreferences(pref);
00977 
00978   if ( !pref )
00979     return;
00980 
00981   int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
00982   int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
00983   int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
00984   for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
00985   {
00986     pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
00987                          LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
00988   }
00989   pref->setItemProperty( "orientation", Qt::Vertical, defCols );
00990 
00991   // adding preference to LightApp_Application handled preferences..  a bit of hacking with resources..
00992   int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
00993   int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
00994   pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
00995   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
00996   pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
00997   pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
00998   pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
00999   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
01000   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
01001 }
01002 
01004 void SalomeApp_Application::updateDesktopTitle() {
01005   QString aTitle = applicationName();
01006   QString aVer = applicationVersion();
01007   if ( !aVer.isEmpty() )
01008     aTitle += QString( " " ) + aVer;
01009 
01010   if ( activeStudy() )
01011   {
01012     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
01013     if ( !sName.isEmpty() ) {
01014       SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
01015       if ( study ) {
01016         _PTR(Study) stdDS = study->studyDS();
01017         if(stdDS) {
01018           if ( stdDS->GetProperties()->IsLocked() ) {
01019             aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
01020           } else {
01021             aTitle += QString( " - [%1]" ).arg( sName );
01022           }
01023         }
01024       }
01025     }
01026   }
01027 
01028   desktop()->setWindowTitle( aTitle );
01029 }
01030 
01031 int SalomeApp_Application::closeChoice( const QString& docName )
01032 {
01033   int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
01034                                           tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
01035                                           tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
01036 
01037   int res = CloseCancel;
01038   if ( answer == 0 )
01039     res = CloseSave;
01040   else if ( answer == 1 )
01041     res = CloseDiscard;
01042   else if ( answer == 2 )
01043     res = CloseUnload;
01044 
01045   return res;
01046 }
01047 
01048 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
01049 {
01050   bool res = true;
01051   switch( choice )
01052   {
01053   case CloseSave:
01054     if ( activeStudy()->isSaved() )
01055       onSaveDoc();
01056     else if ( !onSaveAsDoc() )
01057       res = false;
01058     break;
01059   case CloseDiscard:
01060     break;
01061   case CloseUnload:
01062     closePermanently = false;
01063     break;
01064   case CloseCancel:
01065   default:
01066     res = false;
01067   }
01068 
01069   return res;
01070 }
01071 
01072 int SalomeApp_Application::openChoice( const QString& aName )
01073 {
01074   int choice = LightApp_Application::openChoice( aName );
01075 
01076   if ( QFileInfo( aName ).exists() ) {
01077     if ( choice == OpenNew ) { // The document isn't already open.
01078       bool exist = false;
01079       std::vector<std::string> lst = studyMgr()->GetOpenStudies();
01080       for ( uint i = 0; i < lst.size() && !exist; i++ ) {
01081         if ( aName == QString( lst[i].c_str() ) )
01082           exist = true;
01083       }
01084       // The document already exists in the study manager.
01085       // Do you want to reload it?
01086       if ( exist ) {
01087         int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
01088                                                 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
01089         if ( answer == SUIT_MessageBox::Yes )
01090           choice = OpenRefresh;
01091         else
01092           choice = OpenCancel;
01093       }
01094     }
01095   } else { // file is not exist on disk
01096     SUIT_MessageBox::warning( desktop(),
01097                               QObject::tr("WRN_WARNING"),
01098                               QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
01099     return false;
01100   }
01101 
01102   return choice;
01103 }
01104 
01105 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
01106 {
01107   bool res = false;
01108   int choice = aChoice;
01109   switch ( choice )
01110   {
01111   case OpenRefresh:
01112     {
01113       _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
01114       if ( aStudy )
01115       {
01116         studyMgr()->Close( aStudy );
01117         choice = OpenNew;
01118       }
01119     }
01120   default:
01121     res = LightApp_Application::openAction( choice, aName );
01122     break;
01123   }
01124 
01125   return res;
01126 }
01127 
01143 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
01144 {
01145   QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
01146   opmap.insert( LoadStudyId,     tr( "ACTIVATE_MODULE_OP_LOAD" ) );
01147   opmap.insert( NewAndScriptId,  tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
01148   return opmap;
01149 }
01150 
01160 void SalomeApp_Application::moduleActionSelected( const int id )
01161 {
01162   switch ( id ) {
01163   case LoadStudyId:
01164     onLoadDoc();
01165     break;
01166   case NewAndScriptId:
01167     onNewWithScript();
01168     break;
01169   default:
01170     LightApp_Application::moduleActionSelected( id );
01171     break;
01172   }
01173 }
01174 
01176 CORBA::ORB_var SalomeApp_Application::orb()
01177 {
01178   ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
01179   static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
01180   return _orb;
01181 }
01182 
01184 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
01185 {
01186   static _PTR(StudyManager) _sm;
01187   if(!_sm) _sm = ClientFactory::StudyManager();
01188   return _sm.get();
01189 }
01190 
01192 SALOME_NamingService* SalomeApp_Application::namingService()
01193 {
01194   static SALOME_NamingService _ns(orb());
01195   return &_ns;
01196 }
01197 
01199 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
01200 {
01201   static SALOME_LifeCycleCORBA _lcc( namingService() );
01202   return &_lcc;
01203 }
01204 
01206 void SalomeApp_Application::onProperties()
01207 {
01208   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
01209   if( !study )
01210     return;
01211 
01212   _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
01213   SB->NewCommand();
01214 
01215   SalomeApp_StudyPropertiesDlg aDlg( desktop() );
01216   int res = aDlg.exec();
01217   if( res==QDialog::Accepted && aDlg.isChanged() )
01218     SB->CommitCommand();
01219   else
01220     SB->AbortCommand();
01221 
01222   //study->updateCaptions();
01223   updateDesktopTitle();
01224   updateActions();
01225 }
01226 
01228 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
01229 {
01230   LightApp_SelectionMgr* mgr = selectionMgr();
01231   bool cacheIsOn = mgr->isSelectionCacheEnabled();
01232   mgr->setSelectionCacheEnabled( true );
01233 
01234   LightApp_Application::contextMenuPopup( type, thePopup, title );
01235 
01236   // temporary commented
01237   /*OB_Browser* ob = objectBrowser();
01238   if ( !ob || type != ob->popupClientType() )
01239     return;*/
01240 
01241   // Get selected objects
01242   SALOME_ListIO aList;
01243   mgr->selectedObjects( aList, QString(), false );
01244 
01245   // add GUI state commands: restore, rename
01246   if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
01247        QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
01248     thePopup->addSeparator();
01249     thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
01250     thePopup->addAction( tr( "MEN_RENAME_VS" ),  objectBrowser(),
01251                          SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
01252     thePopup->addAction( tr( "MEN_DELETE_VS" ),  this, SLOT( onDeleteGUIState() ) );
01253   }
01254 
01255   // "Delete reference" item should appear only for invalid references
01256 
01257   // isInvalidRefs will be true, if at least one of selected objects is invalid reference
01258   bool isInvalidRefs = false;
01259   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
01260   _PTR(Study) aStudyDS = aStudy->studyDS();
01261   _PTR(SObject) anObj;
01262 
01263   for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
01264     if( it.Value()->hasEntry() )
01265     {
01266       _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
01267       while( aRefObj && aRefObj->ReferencedObject( anObj ) )
01268         aRefObj = anObj;
01269 
01270       if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
01271         isInvalidRefs = true;
01272     }
01273 
01274   // Add "Delete reference" item to popup
01275   if ( isInvalidRefs )
01276   {
01277     thePopup->addSeparator();
01278     thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
01279     return;
01280   }
01281 
01282   // "Activate module" item should appear only if it's necessary
01283   if ( aList.Extent() == 1 ) {
01284     aList.Clear();
01285     mgr->selectedObjects( aList );
01286 
01287     Handle(SALOME_InteractiveObject) aIObj = aList.First();
01288 
01289     // add extra popup menu (defined in XML)
01290     if ( myExtActions.size() > 0 ) {
01291       // Use only first selected object
01292       SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
01293       if ( study ) {
01294        _PTR(Study) stdDS = study->studyDS();
01295        if ( stdDS ) {
01296          _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
01297          if ( aSO ) {
01298            _PTR( GenericAttribute ) anAttr;
01299            std::string auid = "AttributeUserID";
01300            auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
01301            if ( aSO->FindAttribute( anAttr, auid ) ) {
01302              _PTR(AttributeUserID) aAttrID = anAttr;
01303              QString aId = aAttrID->Value().c_str();
01304              if ( myExtActions.contains( aId ) ) {
01305               thePopup->addAction(myExtActions[aId]);
01306              }
01307            }
01308          }
01309        }
01310       }
01311     }
01312 
01313     // check if item is a "GUI state" item (also a first level object)
01314     QString entry( aIObj->getEntry() );
01315     if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
01316       QString aModuleName( aIObj->getComponentDataType() );
01317       QString aModuleTitle = moduleTitle( aModuleName );
01318       CAM_Module* currentModule = activeModule();
01319       if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
01320        thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
01321     }
01322   }
01323 
01324   mgr->setSelectionCacheEnabled( cacheIsOn );
01325 }
01326 
01331 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
01332 {
01333   // update "non-existing" (not loaded yet) data models
01334   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
01335   if ( study )
01336   {
01337     _PTR(Study) stdDS = study->studyDS();
01338     if( stdDS )
01339     {
01340       for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
01341       {
01342         _PTR(SComponent) aComponent ( it->Value() );
01343 
01344 #ifndef WITH_SALOMEDS_OBSERVER
01345         // with GUI observers this check is not needed anymore
01346         if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
01347           continue; // skip the magic "Interface Applicative" component
01348 #endif
01349         if ( !objectBrowser() )
01350           getWindow( WT_ObjectBrowser );
01351         const bool isAutoUpdate = objectBrowser()->autoUpdate();
01352         objectBrowser()->setAutoUpdate( false );
01353         SalomeApp_DataModel::synchronize( aComponent, study );
01354         objectBrowser()->setAutoUpdate( isAutoUpdate );
01355       }
01356     }
01357   }
01358 
01359   // create data objects that correspond to GUI state save points
01360   if ( study ) updateSavePointDataObjects( study );
01361 
01362   // update existing data models (already loaded SComponents)
01363   LightApp_Application::updateObjectBrowser( updateModels );
01364 }
01365 
01367 void SalomeApp_Application::onCatalogGen()
01368 {
01369   ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
01370   aDlg.exec();
01371 }
01372 
01374 void SalomeApp_Application::onRegDisplay()
01375 {
01376   CORBA::ORB_var anOrb = orb();
01377   ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
01378   regWnd->show();
01379   regWnd->raise();
01380   regWnd->activateWindow();
01381 }
01382 
01384 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
01385 {
01386   // Issue 21379: References are supported at LightApp_DataObject level
01387   LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
01388 
01389   if( obj && obj->isReference() )
01390   {
01391     QString entry = obj->refEntry();
01392 
01393     SUIT_DataOwnerPtrList aList;
01394     aList.append( new LightApp_DataOwner( entry ) );
01395     selectionMgr()->setSelected( aList, false );
01396     
01397     SUIT_DataBrowser* ob = objectBrowser();
01398 
01399     QModelIndexList aSelectedIndexes = ob->selectedIndexes();
01400     if ( !aSelectedIndexes.isEmpty() )
01401       ob->treeView()->scrollTo( aSelectedIndexes.first() );
01402   }
01403 }
01404 
01409 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
01410 {
01411   return createViewManager(type);
01412 }
01413 
01414 
01416 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
01417 {
01418   SALOME_ListIO aList;
01419   selMgr->selectedObjects( aList );
01420   if( aList.Extent() > 0 ) {
01421     Handle(SALOME_InteractiveObject) aIObj = aList.First();
01422     QString entry( aIObj->getEntry() );
01423     QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
01424     if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
01425       return -1;
01426     bool ok; // conversion to integer is ok?
01427     int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
01428     return ok ? savePoint : -1;
01429   }
01430   return -1;
01431 }
01432 
01434 void SalomeApp_Application::onRestoreGUIState()
01435 {
01436   int savePoint = ::getSelectedSavePoint( selectionMgr() );
01437   if ( savePoint == -1 )
01438     return;
01439   SalomeApp_VisualState( this ).restoreState( savePoint );
01440 }
01441 
01443 void SalomeApp_Application::onDeleteGUIState()
01444 {
01445   int savePoint = ::getSelectedSavePoint( selectionMgr() );
01446   if ( savePoint == -1 )
01447     return;
01448   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
01449   if ( !study )
01450     return;
01451 
01452   study->removeSavePoint( savePoint );
01453   updateSavePointDataObjects( study );
01454 }
01455 
01457 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
01458 {
01459   LightApp_Application::onStudyCreated( study );
01460 
01461   connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
01462            this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
01463 
01464 
01465   objectBrowserColumnsVisibility();
01466 }
01467 
01469 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
01470 {
01471   LightApp_Application::onStudySaved( study );
01472 
01473   // temporary commented
01474   /*if ( objectBrowser() ) {
01475     updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
01476     objectBrowser()->updateTree( study->root() );
01477   }*/
01478 }
01479 
01481 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
01482 {
01483   LightApp_Application::onStudyOpened( study );
01484 
01485   connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
01486            this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
01487 
01488   objectBrowserColumnsVisibility();
01489 
01490   // temporary commented
01491   /*if ( objectBrowser() ) {
01492     updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
01493     objectBrowser()->updateTree( study->root() );
01494   }*/
01495 }
01496 
01498 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
01499 {
01500 
01501   SUIT_DataBrowser* ob = objectBrowser();
01502   LightApp_SelectionMgr* selMgr = selectionMgr();
01503 
01504   if ( !study || !ob || !selMgr ) 
01505     return;
01506 
01507   // find GUI states root object
01508   SUIT_DataObject* guiRootObj = 0;
01509   DataObjectList ch;
01510   study->root()->children( ch );
01511   DataObjectList::const_iterator it = ch.begin(), last = ch.end();
01512   for ( ; it != last ; ++it ) {
01513     if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
01514       guiRootObj = *it;
01515       break;
01516     }
01517   }
01518   std::vector<int> savePoints = study->getSavePoints();
01519   // case 1: no more save points but they existed in study's tree
01520   if ( savePoints.empty() && guiRootObj ) {
01521     //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
01522     //    : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
01523     const bool isAutoUpdate = ob->autoUpdate();
01524     selMgr->clearSelected();
01525     ob->setAutoUpdate(true);
01526     DataObjectList ch = guiRootObj->children();
01527     for( int i = 0; i < ch.size(); i++ ) 
01528       delete ch[i];
01529     delete guiRootObj;
01530     ob->setAutoUpdate(isAutoUpdate);
01531     return;
01532   }
01533   // case 2: no more save points but root does not exist either
01534   if ( savePoints.empty() && !guiRootObj )
01535     return;
01536   // case 3: save points but no root for them - create it
01537   if ( !savePoints.empty() && !guiRootObj )
01538     guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
01539   // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
01540   // to be always the last one in the tree.  Here we check - if it is not the last one - remove and
01541   // re-create it.
01542   if ( guiRootObj->nextBrother() ) {
01543     study->root()->removeChild(guiRootObj);
01544     study->root()->appendChild(guiRootObj);
01545     //study->root()->dump();
01546   }
01547 
01548   // store data objects in a map id-to-DataObject
01549   QMap<int,SalomeApp_SavePointObject*> mapDO;
01550   ch.clear();
01551   guiRootObj->children( ch );
01552   for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
01553     SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
01554     if ( dobj )
01555       mapDO[dobj->getId()] = dobj;
01556   }
01557 
01558   // iterate new save points.  if DataObject with such ID not found in map - create DataObject
01559   // if in the map - remove it from map.
01560   for ( int i = 0; i < savePoints.size(); i++ )
01561     if ( !mapDO.contains( savePoints[i] ) )
01562       new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
01563     else
01564       mapDO.remove( savePoints[i] );
01565 
01566   // delete DataObjects that are still in the map -- their IDs were not found in data model
01567   if( mapDO.size() > 0) {
01568     //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
01569     //    : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
01570     selMgr->clearSelected();
01571     const bool isAutoUpdate = ob->autoUpdate();
01572     ob->setAutoUpdate(true);
01573     for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
01574       delete it.value();
01575     ob->setAutoUpdate(isAutoUpdate);
01576   }
01577 }
01578 
01580 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
01581 {
01582   if (theObj)
01583     return true;
01584 
01585   return false;
01586 }
01587 
01592 bool SalomeApp_Application::useStudy( const QString& theName )
01593 {
01594   createEmptyStudy();
01595   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
01596   bool res = false;
01597   if (aStudy)
01598     res = aStudy->loadDocument( theName );
01599   updateDesktopTitle();
01600   updateCommandsStatus();
01601   return res;
01602 }
01603 
01605 void SalomeApp_Application::objectBrowserColumnsVisibility()
01606 {
01607   if ( objectBrowser() )
01608     for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
01609     {
01610       bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
01611       objectBrowser()->treeView()->setColumnHidden( i, !shown );
01612     }
01613 }
01614 
01616 void SalomeApp_Application::setNoteBook(SalomeApp_NoteBookDlg* theNoteBook){
01617   myNoteBook = theNoteBook;
01618 }
01619 
01621 SalomeApp_NoteBookDlg* SalomeApp_Application::getNoteBook() const
01622 {
01623   return myNoteBook;
01624 }
01625 
01643 void SalomeApp_Application::createExtraActions()
01644 {
01645   myExtActions.clear();
01646   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
01647 
01648   QStringList aModules;
01649   modules(aModules, false);
01650   foreach(QString aModile, aModules) {
01651     QString aModName = moduleName(aModile);
01652     QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
01653     if (!aSectionStr.isNull()) {
01654       QStringList aSections = aSectionStr.split(':');
01655       foreach(QString aSection, aSections) {
01656         QString aTitle = resMgr->stringValue(aSection, "title",    QString());
01657         QString aId    = resMgr->stringValue(aSection, "objectid", QString());
01658         QString aSlot  = resMgr->stringValue(aSection, "method",   QString());
01659         if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
01660           continue;
01661 
01662         QString aModuleName = resMgr->stringValue(aSection, "module", QString());
01663         if (aModuleName.isNull())
01664           aModuleName = aModName;
01665 
01666         QAction* aAction = new QAction(aTitle, this);
01667         QStringList aData;
01668         aData<<aModuleName<<aSlot;
01669         aAction->setData(aData);
01670         connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
01671         myExtActions[aId] = aAction;
01672       }
01673     }
01674   }
01675 }
01676 
01680 void SalomeApp_Application::onExtAction()
01681 {
01682   QAction* aAction = ::qobject_cast<QAction*>(sender());
01683   if (!aAction)
01684     return;
01685 
01686   QVariant aData = aAction->data();
01687   QStringList aDataList = aData.value<QStringList>();
01688   if (aDataList.size() != 2)
01689     return;
01690 
01691   LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
01692   SALOME_ListIO aListIO;
01693   aSelectionMgr->selectedObjects(aListIO);
01694   const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
01695   if (aListIO.Extent() < 1)
01696     return;
01697   if (!anIO->hasEntry())
01698     return;
01699 
01700   QString aEntry(anIO->getEntry());
01701 
01702   QApplication::setOverrideCursor( Qt::WaitCursor );
01703   QString aModuleTitle = moduleTitle(aDataList[0]);
01704   activateModule(aModuleTitle);
01705   QApplication::restoreOverrideCursor();
01706 
01707   QCoreApplication::processEvents();
01708 
01709   CAM_Module* aModule = activeModule();
01710   if (!aModule)
01711     return;
01712 
01713   if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
01714     printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
01715 }
01716 
01720 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
01721 {
01722   SUIT_DataBrowser* anOB = objectBrowser();
01723   if( !anOB )
01724     return;
01725   SUIT_DataObject* rootObj = anOB->root();
01726   if( !rootObj )
01727     return;
01728 
01729   DataObjectList listObj = rootObj->children( true );
01730 
01731   SUIT_ViewModel* vmod = 0;
01732   if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
01733     vmod = vman->getViewModel();
01734   updateVisibilityState( listObj, vmod );
01735 }
01736 
01740 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
01741                                                    SUIT_ViewModel*  theViewModel )
01742 {
01743   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
01744 
01745   if(!theViewModel)
01746     return;
01747 
01748   SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
01749 
01750   if (theList.isEmpty() || !aView || !aStudy)
01751     return;
01752 
01753   for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
01754     LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
01755 
01756     if (!obj || aStudy->isComponent(obj->entry()))
01757       continue;
01758 
01759     LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
01760     Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
01761 
01762     if(anObjModule) {
01763       LightApp_Displayer* aDisplayer = anObjModule->displayer();
01764       if(aDisplayer) {
01765         if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
01766           if(aDisplayer->IsDisplayed(obj->entry(),aView))
01767             anObjState = Qtx::ShownState;
01768           else
01769             anObjState = Qtx::HiddenState;
01770         }
01771       }
01772       aStudy->setVisibilityState( obj->entry(), anObjState );
01773     }
01774   }
01775 }
01776 
01780 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
01781 {
01782   ViewManagerList lst;
01783   viewManagers(lst);
01784   if( lst.count() == 1) { // in case if closed last view window
01785     LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
01786     if(aStudy)
01787       aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
01788   }
01789 }
01790 
01796 bool SalomeApp_Application::renameAllowed( const QString& entry) const
01797 {
01798   return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
01799 }
01800 
01807 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
01808 {
01809   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
01810 
01811   int savePoint = ::getSelectedSavePoint( selectionMgr() );
01812 
01813   if(!aStudy || savePoint == -1)
01814     return false;
01815 
01816   if ( !name.isNull() && !name.isEmpty() ) {
01817     aStudy->setNameOfSavePoint( savePoint, name );
01818     updateSavePointDataObjects( aStudy );
01819 
01820     //Mark study as modified
01821     aStudy->Modified();
01822     return true;
01823   }
01824   return false;
01825 }