1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: SalomeApp_Application.cxx
24 // Created: 10/22/2004 3:23:45 PM
25 // Author: Sergey LITONIN
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
35 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
36 #include "SalomeApp_Application.h"
37 #include "SalomeApp_Study.h"
38 #include "SalomeApp_DataModel.h"
39 #include "SalomeApp_DataObject.h"
40 #include "SalomeApp_VisualState.h"
41 #include "SalomeApp_StudyPropertiesDlg.h"
42 #include "SalomeApp_LoadStudiesDlg.h"
43 #include "SalomeApp_NoteBookDlg.h"
45 #include "SalomeApp_ExitDlg.h"
47 #include <LightApp_Application.h>
48 #include <LightApp_Module.h>
49 #include <LightApp_Preferences.h>
50 #include <LightApp_SelectionMgr.h>
51 #include <LightApp_NameDlg.h>
52 #include <LightApp_DataOwner.h>
53 #include <LightApp_Displayer.h>
55 #include <CAM_Module.h>
57 #include <SUIT_Tools.h>
58 #include <SUIT_Session.h>
59 #include <SUIT_Desktop.h>
60 #include <SUIT_DataBrowser.h>
61 #include <SUIT_FileDlg.h>
62 #include <SUIT_FileValidator.h>
63 #include <SUIT_MessageBox.h>
64 #include <SUIT_ResourceMgr.h>
65 #include <SUIT_TreeModel.h>
66 #include <SUIT_ViewWindow.h>
67 #include <SUIT_ViewManager.h>
68 #include <SUIT_ViewModel.h>
70 #include <QtxTreeView.h>
72 #include <SALOME_EventFilter.h>
74 // temporary commented
75 //#include <OB_ListItem.h>
77 #include <PyConsole_Console.h>
79 #include <Utils_ORB_INIT.hxx>
80 #include <Utils_SINGLETON.hxx>
81 #include <SALOME_LifeCycleCORBA.hxx>
83 #include <QApplication>
87 #include <QPushButton>
89 #include <QListWidget>
90 #include <QGridLayout>
94 #include <SALOMEDSClient_ClientFactory.hxx>
95 #include <Basics_Utils.hxx>
97 #include <SALOME_ListIO.hxx>
98 #include <SALOME_ListIteratorOfListIO.hxx>
99 #include <SALOME_Prs.h>
102 #include <ToolsGUI_CatalogGeneratorDlg.h>
103 #include <ToolsGUI_RegWidget.h>
107 /*!Internal class that updates object browser item properties */
108 // temporary commented
109 /*class SalomeApp_Updater : public OB_Updater
112 SalomeApp_Updater() : OB_Updater(){};
113 virtual ~SalomeApp_Updater(){};
114 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
117 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
119 if( !theObj || !theItem )
122 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
126 _PTR(SObject) SObj = SAObj->object();
129 _PTR( GenericAttribute ) anAttr;
132 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
134 _PTR(AttributeSelectable) aAttrSel = anAttr;
135 theItem->setSelectable( aAttrSel->IsSelectable() );
138 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
140 _PTR(AttributeExpandable) aAttrExpand = anAttr;
141 theItem->setExpandable( aAttrExpand->IsExpandable() );
144 //this attribute is not supported in the version of SALOME 3.x
145 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
147 // _PTR(AttributeOpened) aAttrOpen = anAttr;
148 // theItem->setOpen( aAttrOpen->IsOpened() );
152 /*!Create new instance of SalomeApp_Application.*/
153 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
155 return new SalomeApp_Application();
159 SalomeApp_Application::SalomeApp_Application()
160 : LightApp_Application()
162 connect( desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
163 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
169 *\li Destroy event filter.
171 SalomeApp_Application::~SalomeApp_Application()
173 // Do not destroy. It's a singleton !
174 //SALOME_EventFilter::Destroy();
177 /*!Start application.*/
178 void SalomeApp_Application::start()
180 LightApp_Application::start();
182 SALOME_EventFilter::Init();
184 static bool isFirst = true;
191 for (int i = 1; i < qApp->argc(); i++) {
192 QRegExp rxs ("--study-hdf=(.+)");
193 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
194 QString file = rxs.capturedTexts()[1];
195 QFileInfo fi ( file );
196 QString extension = fi.suffix().toLower();
197 if ( extension == "hdf" && fi.exists() )
198 hdffile = fi.absoluteFilePath();
201 QRegExp rxp ("--pyscript=(.+)");
202 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
203 QStringList files = rxp.capturedTexts()[1].split(",",QString::SkipEmptyParts);
209 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
210 onOpenDoc( hdffile );
211 else if ( pyfiles.count() > 0 ) // create new study
214 // import/execute python scripts
215 if ( pyfiles.count() > 0 && activeStudy() ) {
216 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
217 PyConsole_Console* pyConsole = pythonConsole();
218 if ( appStudy && pyConsole ) {
219 _PTR(Study) aStudy = appStudy->studyDS();
220 if ( !aStudy->GetProperties()->IsLocked() ) {
221 for (uint j = 0; j < pyfiles.count(); j++ ) {
222 QFileInfo fi ( pyfiles[j] );
223 QFileInfo fipy ( pyfiles[j] + ".py" );
224 QString command = QString( "execfile(r\"%1\")" );
225 if ( fi.isAbsolute() ) {
227 pyConsole->exec( command.arg( fi.absoluteFilePath() ) );
228 else if ( fipy.exists() )
229 pyConsole->exec( command.arg( fipy.absoluteFilePath() ) );
231 qDebug() << "Can't execute file" << pyfiles[j];
236 dirs << QDir::currentPath();
237 if ( ::getenv( "PYTHONPATH" ) )
238 dirs += QString( ::getenv( "PYTHONPATH" ) ).split( QRegExp( "[:|;]" ) );
239 foreach( QString dir, dirs ) {
240 qDebug() << "try" << QFileInfo( dir, pyfiles[j] ).absoluteFilePath();
241 qDebug() << "try" << QFileInfo( dir, pyfiles[j] + ".py" ).absoluteFilePath();
242 if ( QFileInfo( dir, pyfiles[j] ).exists() ) {
243 pyConsole->exec( command.arg( QFileInfo( dir, pyfiles[j] ).absoluteFilePath() ) );
247 else if ( QFileInfo( dir, pyfiles[j] + ".py" ).exists() ) {
248 pyConsole->exec( command.arg( QFileInfo( dir, pyfiles[j] + ".py" ).absoluteFilePath() ) );
254 qDebug() << "Can't execute file" << pyfiles[j];
265 void SalomeApp_Application::createActions()
267 LightApp_Application::createActions();
269 SUIT_Desktop* desk = desktop();
272 // "Save GUI State" command is moved to VISU module
273 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
274 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
275 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
278 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
279 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
280 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
283 createAction(NoteBookId, tr( "TOT_DESK_FILE_NOTEBOOK" ), QIcon(),
284 tr( "MEN_DESK_FILE_NOTEBOOK" ), tr( "PRP_DESK_FILE_NOTEBOOK" ),
285 Qt::CTRL+Qt::Key_K, desk, false, this, SLOT(onNoteBook()));
288 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
289 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
290 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
293 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
294 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
295 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
297 //! Catalog Generator
298 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
299 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
300 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
303 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
304 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
305 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
307 //SRN: BugID IPAL9021, add an action "Load"
308 createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
309 resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
310 tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
311 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
312 //SRN: BugID IPAL9021: End
315 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
317 // "Save GUI State" command is renamed to "Save VISU State" and
318 // creation of menu item is moved to VISU
319 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
321 createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load"
323 createMenu( DumpStudyId, fileMenu, 10, -1 );
324 createMenu( NoteBookId, fileMenu, 10, -1 );
325 createMenu( separator(), fileMenu, -1, 10, -1 );
326 createMenu( LoadScriptId, fileMenu, 10, -1 );
327 createMenu( separator(), fileMenu, -1, 10, -1 );
328 createMenu( PropertiesId, fileMenu, 10, -1 );
329 createMenu( separator(), fileMenu, -1, 10, -1 );
331 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
332 createMenu( CatalogGenId, toolsMenu, 10, -1 );
333 createMenu( RegDisplayId, toolsMenu, 10, -1 );
334 createMenu( separator(), toolsMenu, -1, 15, -1 );
336 createExtraActions();
338 // import Python module that manages SALOME plugins
339 PyGILState_STATE gstate = PyGILState_Ensure();
340 PyObject* pluginsmanager=PyImport_ImportModule((char*)"salome_pluginsmanager");
341 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());
345 PyGILState_Release(gstate);
346 // end of SALOME plugins loading
352 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
354 LightApp_Application::setDesktop( desk );
357 connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
358 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
363 \brief Close application.
365 void SalomeApp_Application::onExit()
367 bool killServers = false;
370 if ( exitConfirmation() ) {
371 SalomeApp_ExitDlg dlg( desktop() );
372 result = dlg.exec() == QDialog::Accepted;
373 killServers = dlg.isServersShutdown();
377 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
380 /*!SLOT. Load document.*/
381 void SalomeApp_Application::onLoadDoc()
385 std::vector<std::string> List = studyMgr()->GetOpenStudies();
387 SUIT_Session* aSession = SUIT_Session::session();
388 QList<SUIT_Application*> aAppList = aSession->applications();
390 QStringList unloadedStudies;
392 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
393 studyName = List[ind].c_str();
394 // Add to list only unloaded studies
395 bool isAlreadyOpen = false;
396 QListIterator<SUIT_Application*> it( aAppList );
397 while ( it.hasNext() && !isAlreadyOpen ) {
398 SUIT_Application* aApp = it.next();
399 if( !aApp || !aApp->activeStudy() )
401 if ( aApp->activeStudy()->studyName() == studyName )
402 isAlreadyOpen = true;
405 if ( !isAlreadyOpen )
406 unloadedStudies << studyName;
409 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
410 if ( studyName.isEmpty() )
414 // this code replaces marker of windows drive and path become invalid therefore
415 // defines placed there
416 studyName.replace( QRegExp(":"), "/" );
419 if ( onLoadDoc( studyName ) ) {
421 updateViewManagers();
422 updateObjectBrowser( true );
426 /*!SLOT. Create new study and load script*/
427 void SalomeApp_Application::onNewWithScript()
429 QStringList filtersList;
430 filtersList.append(tr("PYTHON_FILES_FILTER"));
431 filtersList.append(tr("ALL_FILES_FILTER"));
433 QString anInitialPath = "";
434 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
435 anInitialPath = QDir::currentPath();
437 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
439 if ( !aFile.isEmpty() )
443 QString command = QString("execfile(r\"%1\")").arg(aFile);
445 PyConsole_Console* pyConsole = pythonConsole();
448 pyConsole->exec( command );
453 /*!SLOT. Load document with \a aName.*/
454 bool SalomeApp_Application::onLoadDoc( const QString& aName )
457 if ( !activeStudy() ) {
458 // if no study - load in current desktop
459 res = useStudy( aName );
462 // if study exists - load in new desktop. Check: is the same file is loaded?
463 SUIT_Session* aSession = SUIT_Session::session();
464 QList<SUIT_Application*> aAppList = aSession->applications();
465 bool isAlreadyOpen = false;
466 SalomeApp_Application* aApp = 0;
467 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
468 it != aAppList.end() && !isAlreadyOpen; ++it ) {
469 aApp = dynamic_cast<SalomeApp_Application*>( *it );
470 if ( aApp && aApp->activeStudy()->studyName() == aName )
471 isAlreadyOpen = true;
473 if ( !isAlreadyOpen ) {
474 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
476 res = aApp->useStudy( aName );
479 aApp->desktop()->activateWindow();
486 /*!SLOT. Copy objects to study maneger from selection maneger..*/
487 void SalomeApp_Application::onCopy()
490 LightApp_SelectionMgr* mgr = selectionMgr();
491 mgr->selectedObjects(list);
493 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
494 if(study == NULL) return;
496 _PTR(Study) stdDS = study->studyDS();
499 SALOME_ListIteratorOfListIO it( list );
502 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
504 studyMgr()->Copy(so);
505 onSelectionChanged();
512 /*!SLOT. Paste objects to study maneger from selection manager.*/
513 void SalomeApp_Application::onPaste()
516 LightApp_SelectionMgr* mgr = selectionMgr();
517 mgr->selectedObjects(list);
519 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
520 if(study == NULL) return;
522 _PTR(Study) stdDS = study->studyDS();
525 if ( stdDS->GetProperties()->IsLocked() ) {
526 SUIT_MessageBox::warning( desktop(),
527 QObject::tr("WRN_WARNING"),
528 QObject::tr("WRN_STUDY_LOCKED") );
532 SALOME_ListIteratorOfListIO it( list );
535 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
537 studyMgr()->Paste(so);
538 updateObjectBrowser( true );
539 updateActions(); //SRN: BugID IPAL9377, case 3
546 /*!Check the application on closing.
547 * \retval true if possible, else false
549 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
551 return LightApp_Application::isPossibleToClose( closePermanently );
554 /*! Check if the study is locked */
555 void SalomeApp_Application::onCloseDoc( bool ask )
557 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
560 _PTR(Study) stdDS = study->studyDS();
561 if(stdDS && stdDS->IsStudyLocked()) {
562 if ( SUIT_MessageBox::question( desktop(),
563 QObject::tr( "WRN_WARNING" ),
564 QObject::tr( "CLOSE_LOCKED_STUDY" ),
565 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
566 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
571 if(myNoteBook && myNoteBook->isVisible())
574 LightApp_Application::onCloseDoc( ask );
577 /*!Sets enable or disable some actions on selection changed.*/
578 void SalomeApp_Application::onSelectionChanged()
581 LightApp_SelectionMgr* mgr = selectionMgr();
582 mgr->selectedObjects(list);
584 bool canCopy = false;
585 bool canPaste = false;
587 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
589 _PTR(Study) stdDS = study->studyDS();
592 SALOME_ListIteratorOfListIO it ( list );
594 if (it.More() && list.Extent() == 1) {
595 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
598 canCopy = studyMgr()->CanCopy(so);
599 canPaste = studyMgr()->CanPaste(so);
605 action(EditCopyId)->setEnabled(canCopy);
606 action(EditPasteId)->setEnabled(canPaste);
609 /*!Delete references.*/
610 void SalomeApp_Application::onDeleteInvalidReferences()
613 LightApp_SelectionMgr* mgr = selectionMgr();
614 mgr->selectedObjects( aList, QString(), false );
616 if( aList.IsEmpty() )
619 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
620 _PTR(Study) aStudyDS = aStudy->studyDS();
621 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
624 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
625 if ( it.Value()->hasEntry() )
627 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
628 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
631 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
632 aStudyBuilder->RemoveReference( aSObject );
634 updateObjectBrowser();
638 void SalomeApp_Application::onOpenWith()
640 QApplication::setOverrideCursor( Qt::WaitCursor );
642 LightApp_SelectionMgr* mgr = selectionMgr();
643 mgr->selectedObjects(aList);
644 if (aList.Extent() != 1)
646 QApplication::restoreOverrideCursor();
649 Handle(SALOME_InteractiveObject) aIObj = aList.First();
650 QString aModuleName(aIObj->getComponentDataType());
651 QString aModuleTitle = moduleTitle(aModuleName);
652 activateModule(aModuleTitle);
653 QApplication::restoreOverrideCursor();
659 SUIT_Study* SalomeApp_Application::createNewStudy()
661 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
663 // Set up processing of major study-related events
664 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
665 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
666 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
667 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
673 Enable/Disable menu items and toolbar buttons. Rebuild menu
675 void SalomeApp_Application::updateCommandsStatus()
677 LightApp_Application::updateCommandsStatus();
680 QAction* a = action( DumpStudyId );
682 a->setEnabled( activeStudy() );
685 a = action(NoteBookId);
687 a->setEnabled( activeStudy() );
690 a = action( LoadScriptId );
692 a->setEnabled( activeStudy() );
695 a = action( PropertiesId );
697 a->setEnabled( activeStudy() );
699 // Save GUI state menu
700 a = action( SaveGUIStateId );
702 a->setEnabled( activeStudy() );
704 // update state of Copy/Paste menu items
705 onSelectionChanged();
709 \class DumpStudyFileDlg
710 Private class used in Dump Study operation. Consists 2 check boxes:
711 "Publish in study" and "Save GUI parameters"
713 class DumpStudyFileDlg : public SUIT_FileDlg
716 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
718 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
721 QWidget *hB = new QWidget( this );
722 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
723 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
724 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
726 QHBoxLayout *layout = new QHBoxLayout;
727 layout->addWidget(myPublishChk);
728 layout->addWidget(myMultiFileChk);
729 layout->addWidget(mySaveGUIChk);
730 hB->setLayout(layout);
732 QPushButton* pb = new QPushButton(this);
734 int row = grid->rowCount();
735 grid->addWidget( new QLabel("", this), row, 0 );
736 grid->addWidget( hB, row, 1, 1, 3 );
737 grid->addWidget( pb, row, 5 );
742 QCheckBox* myPublishChk;
743 QCheckBox* myMultiFileChk;
744 QCheckBox* mySaveGUIChk;
747 class DumpStudyFileValidator : public SUIT_FileValidator
750 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
751 virtual ~DumpStudyFileValidator() {};
752 virtual bool canSave( const QString& file, bool permissions );
755 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
757 QFileInfo fi( file );
758 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
759 SUIT_MessageBox::critical( parent(),
760 QObject::tr("WRN_WARNING"),
761 QObject::tr("WRN_FILE_NAME_BAD") );
764 return SUIT_FileValidator::canSave( file, permissions);
767 /*!Private SLOT. On dump study.*/
768 void SalomeApp_Application::onDumpStudy( )
770 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
771 if ( !appStudy ) return;
772 _PTR(Study) aStudy = appStudy->studyDS();
774 QStringList aFilters;
775 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
777 bool anIsPublish = true;
778 bool anIsMultiFile = false;
779 bool anIsSaveGUI = true;
781 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
782 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
783 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
784 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
787 DumpStudyFileDlg fd( desktop() );
788 fd.setValidator( new DumpStudyFileValidator( &fd ) );
789 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
790 fd.setFilters( aFilters );
791 fd.myPublishChk->setChecked( anIsPublish );
792 fd.myMultiFileChk->setChecked( anIsMultiFile );
793 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
794 if ( fd.exec() == QDialog::Accepted )
796 QString aFileName = fd.selectedFile();
798 bool toPublish = fd.myPublishChk->isChecked();
799 bool isMultiFile = fd.myMultiFileChk->isChecked();
800 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
802 if ( !aFileName.isEmpty() ) {
803 QFileInfo aFileInfo(aFileName);
804 if( aFileInfo.isDir() ) // IPAL19257
807 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
808 bool res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
811 SUIT_MessageBox::warning( desktop(),
812 QObject::tr("WRN_WARNING"),
813 tr("WRN_DUMP_STUDY_FAILED") );
818 /*!Private SLOT. On NoteBook*/
819 void SalomeApp_Application::onNoteBook()
821 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
823 _PTR(Study) aStudy = appStudy->studyDS();
825 myNoteBook = new SalomeApp_NoteBookDlg(desktop(),aStudy);
827 else if(!myNoteBook->isVisible()){
828 myNoteBook->Init(aStudy);
829 myNoteBook->adjustSize();
830 myNoteBook->move((int)(desktop()->x() + desktop()->width()/2 - myNoteBook->frameGeometry().width()/2),
831 (int)(desktop()->y() + desktop()->height()/2 - myNoteBook->frameGeometry().height()/2));
837 /*!Private SLOT. On load script.*/
838 void SalomeApp_Application::onLoadScript( )
840 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
841 if ( !appStudy ) return;
842 _PTR(Study) aStudy = appStudy->studyDS();
844 if ( aStudy->GetProperties()->IsLocked() ) {
845 SUIT_MessageBox::warning( desktop(),
846 QObject::tr("WRN_WARNING"),
847 QObject::tr("WRN_STUDY_LOCKED") );
851 QStringList filtersList;
852 filtersList.append(tr("PYTHON_FILES_FILTER"));
853 filtersList.append(tr("ALL_FILES_FILTER"));
855 QString anInitialPath = "";
856 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
857 anInitialPath = QDir::currentPath();
859 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
861 if ( !aFile.isEmpty() )
863 QString command = QString("execfile(r\"%1\")").arg(aFile);
865 PyConsole_Console* pyConsole = pythonConsole();
868 pyConsole->exec( command );
872 /*!Private SLOT. On save GUI state.*/
873 void SalomeApp_Application::onSaveGUIState()
875 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
877 SalomeApp_VisualState( this ).storeState();
878 updateSavePointDataObjects( study );
879 updateObjectBrowser();
885 *\retval QString "(*.hdf)"
887 QString SalomeApp_Application::getFileFilter() const
893 QWidget* SalomeApp_Application::createWindow( const int flag )
896 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
898 SUIT_ResourceMgr* resMgr = resourceMgr();
900 if ( flag == WT_ObjectBrowser )
902 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
904 // temporary commented
905 //ob->setUpdater( new SalomeApp_Updater() );
907 #ifdef WITH_SALOMEDS_OBSERVER
908 //do not activate the automatic update of Qt tree through signal/slot
909 ob->setAutoUpdate(false);
910 //activate update of modified objects only
911 ob->setUpdateModified(true);
914 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
917 ValueCol = QObject::tr( "VALUE_COLUMN" ),
918 IORCol = QObject::tr( "IOR_COLUMN" ),
919 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
920 EntryCol = QObject::tr( "ENTRY_COLUMN" );
922 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
923 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
924 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
925 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
926 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
927 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
928 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
929 treeModel->setAppropriate( IORCol, Qtx::Toggled );
930 treeModel->setAppropriate( RefCol, Qtx::Toggled );
932 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
933 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
934 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
936 ob->setAutoSizeFirstColumn(autoSizeFirst);
937 ob->setAutoSizeColumns(autoSize);
938 ob->setResizeOnExpandItem(resizeOnExpandItem);
939 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
941 // temporary commented
943 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
945 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
946 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
947 QString().sprintf( "visibility_column_%d", i ), true ) );
951 // temporary commented
953 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
954 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
955 ob->resize( desktop()->width()/3, ob->height() );
959 else if ( flag == WT_PyConsole )
961 PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new SalomeApp_PyInterp() );
962 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
963 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
964 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
965 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
967 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
968 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
973 /*!Create preferences.*/
974 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
976 LightApp_Application::createPreferences(pref);
981 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
982 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
983 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
984 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
986 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
987 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
989 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
991 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
992 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
993 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
994 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
995 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
996 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
997 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
998 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
999 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1000 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1003 /*!Update desktop title.*/
1004 void SalomeApp_Application::updateDesktopTitle() {
1005 QString aTitle = applicationName();
1006 QString aVer = applicationVersion();
1007 if ( !aVer.isEmpty() )
1008 aTitle += QString( " " ) + aVer;
1010 if ( activeStudy() )
1012 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1013 if ( !sName.isEmpty() ) {
1014 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1016 _PTR(Study) stdDS = study->studyDS();
1018 if ( stdDS->GetProperties()->IsLocked() ) {
1019 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1021 aTitle += QString( " - [%1]" ).arg( sName );
1028 desktop()->setWindowTitle( aTitle );
1031 int SalomeApp_Application::closeChoice( const QString& docName )
1033 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1034 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1035 tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
1037 int res = CloseCancel;
1040 else if ( answer == 1 )
1042 else if ( answer == 2 )
1048 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1054 if ( activeStudy()->isSaved() )
1056 else if ( !onSaveAsDoc() )
1062 closePermanently = false;
1072 int SalomeApp_Application::openChoice( const QString& aName )
1074 int choice = LightApp_Application::openChoice( aName );
1076 if ( QFileInfo( aName ).exists() ) {
1077 if ( choice == OpenNew ) { // The document isn't already open.
1079 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1080 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1081 if ( aName == QString( lst[i].c_str() ) )
1084 // The document already exists in the study manager.
1085 // Do you want to reload it?
1087 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1088 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1089 if ( answer == SUIT_MessageBox::Yes )
1090 choice = OpenRefresh;
1092 choice = OpenCancel;
1095 } else { // file is not exist on disk
1096 SUIT_MessageBox::warning( desktop(),
1097 QObject::tr("WRN_WARNING"),
1098 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1105 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1108 int choice = aChoice;
1113 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1116 studyMgr()->Close( aStudy );
1121 res = LightApp_Application::openAction( choice, aName );
1129 \brief Get map of the operations which can be performed
1130 on the module activation.
1132 The method should return the map of the kind \c {<id>:<name>}
1133 where \c <id> is an integer identifier of the operation and
1134 \c <name> is a title for the button to be added to the
1135 dialog box. After user selects the required operation by the
1136 clicking the corresponding button in the dialog box, its identifier
1137 is passed to the moduleActionSelected() method to process
1140 \return map of the operations
1141 \sa moduleActionSelected()
1143 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1145 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1146 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1147 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1152 \brief Called when the used selectes required operation chosen
1153 from "Activate module" dialog box.
1155 Performs the required operation according to the user choice.
1157 \param id operation identifier
1158 \sa activateModuleActions()
1160 void SalomeApp_Application::moduleActionSelected( const int id )
1166 case NewAndScriptId:
1170 LightApp_Application::moduleActionSelected( id );
1175 /*!Gets CORBA::ORB_var*/
1176 CORBA::ORB_var SalomeApp_Application::orb()
1178 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1179 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1183 /*!Create and return SALOMEDS_StudyManager.*/
1184 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1186 static _PTR(StudyManager) _sm;
1187 if(!_sm) _sm = ClientFactory::StudyManager();
1191 /*!Create and return SALOME_NamingService.*/
1192 SALOME_NamingService* SalomeApp_Application::namingService()
1194 static SALOME_NamingService _ns(orb());
1198 /*!Create and return SALOME_LifeCycleCORBA.*/
1199 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1201 static SALOME_LifeCycleCORBA _lcc( namingService() );
1205 /*!Private SLOT. On preferences.*/
1206 void SalomeApp_Application::onProperties()
1208 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1212 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1215 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1216 int res = aDlg.exec();
1217 if( res==QDialog::Accepted && aDlg.isChanged() )
1218 SB->CommitCommand();
1222 //study->updateCaptions();
1223 updateDesktopTitle();
1227 /*!Insert items in popup, which necessary for current application*/
1228 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1230 LightApp_SelectionMgr* mgr = selectionMgr();
1231 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1232 mgr->setSelectionCacheEnabled( true );
1234 LightApp_Application::contextMenuPopup( type, thePopup, title );
1236 // temporary commented
1237 /*OB_Browser* ob = objectBrowser();
1238 if ( !ob || type != ob->popupClientType() )
1241 // Get selected objects
1242 SALOME_ListIO aList;
1243 mgr->selectedObjects( aList, QString(), false );
1245 // add GUI state commands: restore, rename
1246 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1247 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1248 thePopup->addSeparator();
1249 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1250 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1251 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1252 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1255 // "Delete reference" item should appear only for invalid references
1257 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1258 bool isInvalidRefs = false;
1259 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1260 _PTR(Study) aStudyDS = aStudy->studyDS();
1261 _PTR(SObject) anObj;
1263 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1264 if( it.Value()->hasEntry() )
1266 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1267 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1270 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1271 isInvalidRefs = true;
1274 // Add "Delete reference" item to popup
1275 if ( isInvalidRefs )
1277 thePopup->addSeparator();
1278 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1282 // "Activate module" item should appear only if it's necessary
1283 if ( aList.Extent() == 1 ) {
1285 mgr->selectedObjects( aList );
1287 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1289 // add extra popup menu (defined in XML)
1290 if ( myExtActions.size() > 0 ) {
1291 // Use only first selected object
1292 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1294 _PTR(Study) stdDS = study->studyDS();
1296 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1298 _PTR( GenericAttribute ) anAttr;
1299 std::string auid = "AttributeUserID";
1300 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1301 if ( aSO->FindAttribute( anAttr, auid ) ) {
1302 _PTR(AttributeUserID) aAttrID = anAttr;
1303 QString aId = aAttrID->Value().c_str();
1304 if ( myExtActions.contains( aId ) ) {
1305 thePopup->addAction(myExtActions[aId]);
1313 // check if item is a "GUI state" item (also a first level object)
1314 QString entry( aIObj->getEntry() );
1315 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1316 QString aModuleName( aIObj->getComponentDataType() );
1317 QString aModuleTitle = moduleTitle( aModuleName );
1318 CAM_Module* currentModule = activeModule();
1319 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1320 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1324 mgr->setSelectionCacheEnabled( cacheIsOn );
1327 /*!Update obect browser:
1328 1.if 'updateModels' true, update existing data models;
1329 2. update "non-existing" (not loaded yet) data models;
1330 3. update object browser if it exists */
1331 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1333 // update "non-existing" (not loaded yet) data models
1334 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1337 _PTR(Study) stdDS = study->studyDS();
1340 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1342 _PTR(SComponent) aComponent ( it->Value() );
1344 #ifndef WITH_SALOMEDS_OBSERVER
1345 // with GUI observers this check is not needed anymore
1346 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1347 continue; // skip the magic "Interface Applicative" component
1349 if ( !objectBrowser() )
1350 getWindow( WT_ObjectBrowser );
1351 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1352 objectBrowser()->setAutoUpdate( false );
1353 SalomeApp_DataModel::synchronize( aComponent, study );
1354 objectBrowser()->setAutoUpdate( isAutoUpdate );
1359 // create data objects that correspond to GUI state save points
1360 if ( study ) updateSavePointDataObjects( study );
1362 // update existing data models (already loaded SComponents)
1363 LightApp_Application::updateObjectBrowser( updateModels );
1366 /*!Display Catalog Genenerator dialog */
1367 void SalomeApp_Application::onCatalogGen()
1369 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1373 /*!Display Registry Display dialog */
1374 void SalomeApp_Application::onRegDisplay()
1376 CORBA::ORB_var anOrb = orb();
1377 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1380 regWnd->activateWindow();
1383 /*!find original object by double click on item */
1384 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1386 // Issue 21379: References are supported at LightApp_DataObject level
1387 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1389 if( obj && obj->isReference() )
1391 QString entry = obj->refEntry();
1393 SUIT_DataOwnerPtrList aList;
1394 aList.append( new LightApp_DataOwner( entry ) );
1395 selectionMgr()->setSelected( aList, false );
1397 SUIT_DataBrowser* ob = objectBrowser();
1399 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1400 if ( !aSelectedIndexes.isEmpty() )
1401 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1406 Creates new view manager
1407 \param type - type of view manager
1409 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1411 return createViewManager(type);
1415 /*!Global utility funciton, returns selected GUI Save point object's ID */
1416 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1418 SALOME_ListIO aList;
1419 selMgr->selectedObjects( aList );
1420 if( aList.Extent() > 0 ) {
1421 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1422 QString entry( aIObj->getEntry() );
1423 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1424 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1426 bool ok; // conversion to integer is ok?
1427 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1428 return ok ? savePoint : -1;
1433 /*!Called on Restore GUI State popup command*/
1434 void SalomeApp_Application::onRestoreGUIState()
1436 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1437 if ( savePoint == -1 )
1439 SalomeApp_VisualState( this ).restoreState( savePoint );
1442 /*!Called on Delete GUI State popup command*/
1443 void SalomeApp_Application::onDeleteGUIState()
1445 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1446 if ( savePoint == -1 )
1448 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1452 study->removeSavePoint( savePoint );
1453 updateSavePointDataObjects( study );
1456 /*!Called on New study operation*/
1457 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1459 LightApp_Application::onStudyCreated( study );
1461 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1462 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1465 objectBrowserColumnsVisibility();
1468 /*!Called on Save study operation*/
1469 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1471 LightApp_Application::onStudySaved( study );
1473 // temporary commented
1474 /*if ( objectBrowser() ) {
1475 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1476 objectBrowser()->updateTree( study->root() );
1480 /*!Called on Open study operation*/
1481 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1483 LightApp_Application::onStudyOpened( study );
1485 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1486 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1488 objectBrowserColumnsVisibility();
1490 // temporary commented
1491 /*if ( objectBrowser() ) {
1492 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1493 objectBrowser()->updateTree( study->root() );
1497 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1498 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1501 SUIT_DataBrowser* ob = objectBrowser();
1502 LightApp_SelectionMgr* selMgr = selectionMgr();
1504 if ( !study || !ob || !selMgr )
1507 // find GUI states root object
1508 SUIT_DataObject* guiRootObj = 0;
1510 study->root()->children( ch );
1511 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1512 for ( ; it != last ; ++it ) {
1513 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1518 std::vector<int> savePoints = study->getSavePoints();
1519 // case 1: no more save points but they existed in study's tree
1520 if ( savePoints.empty() && guiRootObj ) {
1521 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1522 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1523 const bool isAutoUpdate = ob->autoUpdate();
1524 selMgr->clearSelected();
1525 ob->setAutoUpdate(true);
1526 DataObjectList ch = guiRootObj->children();
1527 for( int i = 0; i < ch.size(); i++ )
1530 ob->setAutoUpdate(isAutoUpdate);
1533 // case 2: no more save points but root does not exist either
1534 if ( savePoints.empty() && !guiRootObj )
1536 // case 3: save points but no root for them - create it
1537 if ( !savePoints.empty() && !guiRootObj )
1538 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1539 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1540 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1542 if ( guiRootObj->nextBrother() ) {
1543 study->root()->removeChild(guiRootObj);
1544 study->root()->appendChild(guiRootObj);
1545 //study->root()->dump();
1548 // store data objects in a map id-to-DataObject
1549 QMap<int,SalomeApp_SavePointObject*> mapDO;
1551 guiRootObj->children( ch );
1552 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1553 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1555 mapDO[dobj->getId()] = dobj;
1558 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1559 // if in the map - remove it from map.
1560 for ( int i = 0; i < savePoints.size(); i++ )
1561 if ( !mapDO.contains( savePoints[i] ) )
1562 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1564 mapDO.remove( savePoints[i] );
1566 // delete DataObjects that are still in the map -- their IDs were not found in data model
1567 if( mapDO.size() > 0) {
1568 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1569 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1570 selMgr->clearSelected();
1571 const bool isAutoUpdate = ob->autoUpdate();
1572 ob->setAutoUpdate(true);
1573 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1575 ob->setAutoUpdate(isAutoUpdate);
1579 /*! Check data object */
1580 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1589 Opens other study into active Study. If Study is empty - creates it.
1590 \param theName - name of study
1592 bool SalomeApp_Application::useStudy( const QString& theName )
1595 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1598 res = aStudy->loadDocument( theName );
1599 updateDesktopTitle();
1600 updateCommandsStatus();
1604 /*! Show/hide object browser colums according to preferences */
1605 void SalomeApp_Application::objectBrowserColumnsVisibility()
1607 if ( objectBrowser() )
1608 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1610 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1611 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1615 /*! Set SalomeApp_NoteBookDlg pointer */
1616 void SalomeApp_Application::setNoteBook(SalomeApp_NoteBookDlg* theNoteBook){
1617 myNoteBook = theNoteBook;
1620 /*! Return SalomeApp_NoteBookDlg pointer */
1621 SalomeApp_NoteBookDlg* SalomeApp_Application::getNoteBook() const
1627 * Define extra actions defined in module definition XML file.
1628 * Additional popup items sections can be defined by parameter "popupitems".
1629 * Supported attributes:
1630 * title - title of menu item,
1631 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1632 * method - method which has to be called when menu item is selected
1634 * <section name="MODULENAME">
1635 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1637 * <section name="importmed">
1638 * <parameter name="title" value="My menu"/>
1639 * <parameter name="objectid" value="VISU.Result"/>
1640 * <parameter name="method" value="nameOfModuleMethod"/>
1643 void SalomeApp_Application::createExtraActions()
1645 myExtActions.clear();
1646 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1648 QStringList aModules;
1649 modules(aModules, false);
1650 foreach(QString aModile, aModules) {
1651 QString aModName = moduleName(aModile);
1652 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1653 if (!aSectionStr.isNull()) {
1654 QStringList aSections = aSectionStr.split(':');
1655 foreach(QString aSection, aSections) {
1656 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1657 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1658 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1659 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1662 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1663 if (aModuleName.isNull())
1664 aModuleName = aModName;
1666 QAction* aAction = new QAction(aTitle, this);
1668 aData<<aModuleName<<aSlot;
1669 aAction->setData(aData);
1670 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1671 myExtActions[aId] = aAction;
1678 * Called when extra action is selected
1680 void SalomeApp_Application::onExtAction()
1682 QAction* aAction = ::qobject_cast<QAction*>(sender());
1686 QVariant aData = aAction->data();
1687 QStringList aDataList = aData.value<QStringList>();
1688 if (aDataList.size() != 2)
1691 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1692 SALOME_ListIO aListIO;
1693 aSelectionMgr->selectedObjects(aListIO);
1694 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1695 if (aListIO.Extent() < 1)
1697 if (!anIO->hasEntry())
1700 QString aEntry(anIO->getEntry());
1702 QApplication::setOverrideCursor( Qt::WaitCursor );
1703 QString aModuleTitle = moduleTitle(aDataList[0]);
1704 activateModule(aModuleTitle);
1705 QApplication::restoreOverrideCursor();
1707 QCoreApplication::processEvents();
1709 CAM_Module* aModule = activeModule();
1713 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1714 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1718 * Called when window activated
1720 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
1722 SUIT_DataBrowser* anOB = objectBrowser();
1725 SUIT_DataObject* rootObj = anOB->root();
1729 DataObjectList listObj = rootObj->children( true );
1731 SUIT_ViewModel* vmod = 0;
1732 if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
1733 vmod = vman->getViewModel();
1734 updateVisibilityState( listObj, vmod );
1738 Update visibility state of given objects
1740 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
1741 SUIT_ViewModel* theViewModel )
1743 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1748 SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
1750 if (theList.isEmpty() || !aView || !aStudy)
1753 for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
1754 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
1756 if (!obj || aStudy->isComponent(obj->entry()))
1759 LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
1760 Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
1763 LightApp_Displayer* aDisplayer = anObjModule->displayer();
1765 if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
1766 if(aDisplayer->IsDisplayed(obj->entry(),aView))
1767 anObjState = Qtx::ShownState;
1769 anObjState = Qtx::HiddenState;
1772 aStudy->setVisibilityState( obj->entry(), anObjState );
1778 Called then view manager removed
1780 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
1782 ViewManagerList lst;
1784 if( lst.count() == 1) { // in case if closed last view window
1785 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1787 aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
1792 Checks that an object can be renamed.
1793 \param entry entry of the object
1794 \brief Return \c true if object can be renamed
1796 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1798 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1802 Rename object by entry.
1803 \param entry entry of the object
1804 \param name new name of the object
1805 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1807 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1809 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1811 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1813 if(!aStudy || savePoint == -1)
1816 if ( !name.isNull() && !name.isEmpty() ) {
1817 aStudy->setNameOfSavePoint( savePoint, name );
1818 updateSavePointDataObjects( aStudy );
1820 //Mark study as modified