Salome HOME
Merge remote branch 'origin/V7_4_BR'
[modules/gui.git] / src / STD / STD_Application.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "STD_Application.h"
24
25 #include "STD_MDIDesktop.h"
26
27 #include <SUIT_Tools.h>
28 #include <SUIT_Study.h>
29 #include <SUIT_Desktop.h>
30 #include <SUIT_Session.h>
31 #include <SUIT_MessageBox.h>
32 #include <SUIT_ViewManager.h>
33 #include <SUIT_ResourceMgr.h>
34
35 #include <QtxDockAction.h>
36 #include <QtxMenu.h>
37 #include <QtxActionMenuMgr.h>
38 #include <QtxActionToolMgr.h>
39
40 #include <QMenu>
41 #include <QStatusBar>
42 #include <QCloseEvent>
43 #include <QFileDialog>
44 #include <QApplication>
45
46 /*!Create and return new instance of STD_Application*/
47 extern "C" STD_EXPORT SUIT_Application* createApplication()
48 {
49   return new STD_Application();
50 }
51
52 /*!Constructor.*/
53 STD_Application::STD_Application()
54 : SUIT_Application(),
55   myActiveViewMgr( 0 ),
56   myExitConfirm( true ),
57   myEditEnabled( true )
58 {
59   setDesktop( new STD_MDIDesktop() );
60 }
61
62 /*!Destructor.*/
63 STD_Application::~STD_Application()
64 {
65   clearViewManagers();
66 }
67
68 /*! \retval requirement of exit confirmation*/
69 bool STD_Application::exitConfirmation() const
70 {
71   return myExitConfirm;
72 }
73
74 /*! Set the requirement of exit confirmation*/
75 void STD_Application::setExitConfirmation( const bool on )
76 {
77   myExitConfirm = on;
78 }
79
80 /*! \retval QString "StdApplication"*/
81 QString STD_Application::applicationName() const
82 {
83   return QString( "StdApplication" );
84 }
85
86 /*!Start STD_Application*/
87 void STD_Application::start()
88 {
89   createActions();
90
91   updateDesktopTitle();
92   updateCommandsStatus();
93   setEditEnabled( myEditEnabled );
94
95   loadPreferences();
96
97   SUIT_Application::start();
98 }
99
100 /*!
101   Close the Application
102 */
103 void STD_Application::closeApplication()
104 {
105   if ( desktop() )
106     savePreferences();
107   SUIT_Study* study = activeStudy();
108
109   if ( study )
110   {
111     beforeCloseDoc( study );
112
113     study->closeDocument();
114
115     setActiveStudy( 0 );
116     delete study;
117
118     afterCloseDoc();
119   }
120
121   setDesktop( 0 );
122
123   SUIT_Application::closeApplication();
124 }
125
126 /*!Event on closing desktop*/
127 void STD_Application::onDesktopClosing( SUIT_Desktop*, QCloseEvent* e )
128 {
129   if ( SUIT_Session::session()->applications().count() < 2 )
130   {
131     onExit();
132     return;
133   }
134
135   bool closePermanently;
136   if ( !isPossibleToClose( closePermanently ) )
137   {
138     e->ignore();
139     return;
140   }
141
142   closeApplication();
143 }
144
145 /*!Create actions, menus and tools*/
146 void STD_Application::createActions()
147 {
148   SUIT_Desktop* desk = desktop();
149   SUIT_ResourceMgr* resMgr = resourceMgr();
150   if ( !desk || !resMgr )
151     return;
152
153   // Create actions
154
155   createAction( FileNewId, tr( "TOT_DESK_FILE_NEW" ),
156                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_NEW" ) ),
157                 tr( "MEN_DESK_FILE_NEW" ), tr( "PRP_DESK_FILE_NEW" ),
158                 Qt::CTRL+Qt::Key_N, desk, false, this, SLOT( onNewDoc() ) );
159
160   createAction( FileOpenId, tr( "TOT_DESK_FILE_OPEN" ),
161                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
162                 tr( "MEN_DESK_FILE_OPEN" ), tr( "PRP_DESK_FILE_OPEN" ),
163                 Qt::CTRL+Qt::Key_O, desk, false, this, SLOT( onOpenDoc() ) );
164
165   createAction( FileReopenId, tr( "TOT_DESK_FILE_REOPEN" ), QIcon(),
166                 tr( "MEN_DESK_FILE_REOPEN" ), tr( "PRP_DESK_FILE_REOPEN" ),
167                 0, desk, false, this, SLOT( onReopenDoc() ) );
168
169   createAction( FileCloseId, tr( "TOT_DESK_FILE_CLOSE" ),
170                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_CLOSE" ) ),
171                 tr( "MEN_DESK_FILE_CLOSE" ), tr( "PRP_DESK_FILE_CLOSE" ),
172                 Qt::CTRL+Qt::Key_W, desk, false, this, SLOT( onCloseDoc() ) );
173
174   createAction( FileExitId, tr( "TOT_DESK_FILE_EXIT" ), QIcon(),
175                 tr( "MEN_DESK_FILE_EXIT" ), tr( "PRP_DESK_FILE_EXIT" ),
176                 Qt::CTRL+Qt::Key_Q, desk, false, this, SLOT( onExit() ) );
177
178   createAction( FileSaveId, tr( "TOT_DESK_FILE_SAVE" ),
179                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_SAVE" ) ),
180                 tr( "MEN_DESK_FILE_SAVE" ), tr( "PRP_DESK_FILE_SAVE" ),
181                 Qt::CTRL+Qt::Key_S, desk, false, this, SLOT( onSaveDoc() ) );
182
183   createAction( FileSaveAsId, tr( "TOT_DESK_FILE_SAVEAS" ), QIcon(),
184                 tr( "MEN_DESK_FILE_SAVEAS" ), tr( "PRP_DESK_FILE_SAVEAS" ),
185                 Qt::CTRL+Qt::SHIFT+Qt::Key_S, desk, false, this, SLOT( onSaveAsDoc() ) );
186
187   createAction( EditCopyId, tr( "TOT_DESK_EDIT_COPY" ),
188                 resMgr->loadPixmap( "STD", tr( "ICON_EDIT_COPY" ) ),
189                 tr( "MEN_DESK_EDIT_COPY" ), tr( "PRP_DESK_EDIT_COPY" ),
190                 Qt::CTRL+Qt::Key_C, desk, false, this, SLOT( onCopy() ) );
191
192   createAction( EditPasteId, tr( "TOT_DESK_EDIT_PASTE" ),
193                 resMgr->loadPixmap( "STD", tr( "ICON_EDIT_PASTE" ) ),
194                 tr( "MEN_DESK_EDIT_PASTE" ), tr( "PRP_DESK_EDIT_PASTE" ),
195                 Qt::CTRL+Qt::Key_V, desk, false, this, SLOT( onPaste() ) );
196
197   QAction* a = createAction( ViewStatusBarId, tr( "TOT_DESK_VIEW_STATUSBAR" ),
198                              QIcon(), tr( "MEN_DESK_VIEW_STATUSBAR" ),
199                              tr( "PRP_DESK_VIEW_STATUSBAR" ), Qt::ALT+Qt::SHIFT+Qt::Key_S, desk, true );
200   a->setChecked( desk->statusBar()->isVisibleTo( desk ) );
201   connect( a, SIGNAL( toggled( bool ) ), this, SLOT( onViewStatusBar( bool ) ) );
202
203   createAction( NewWindowId, tr( "TOT_DESK_NEWWINDOW" ), QIcon(),
204                 tr( "MEN_DESK_NEWWINDOW" ), tr( "PRP_DESK_NEWWINDOW" ), 0, desk  );
205
206   createAction( HelpAboutId, tr( "TOT_DESK_HELP_ABOUT" ), QIcon(),
207                 tr( "MEN_DESK_HELP_ABOUT" ), tr( "PRP_DESK_HELP_ABOUT" ),
208                 Qt::ALT+Qt::SHIFT+Qt::Key_A, desk, false, this, SLOT( onHelpAbout() ) );
209
210
211   QtxDockAction* dwa = new QtxDockAction( tr( "TOT_DOCKWINDOWS" ), tr( "MEN_DESK_VIEW_DOCKWINDOWS" ), desk );
212   dwa->setDockType( QtxDockAction::DockWidget );
213   registerAction( ViewWindowsId, dwa );
214
215   QtxDockAction* tba = new QtxDockAction( tr( "TOT_TOOLBARS" ), tr( "MEN_DESK_VIEW_TOOLBARS" ), desk );
216   tba->setDockType( QtxDockAction::ToolBar );
217   registerAction( ViewToolBarsId, tba );
218
219   // Create menus
220
221   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1, MenuFileId, 0 );
222   // Let the application developers insert some menus between Edit and View
223   int editMenu = createMenu( tr( "MEN_DESK_EDIT" ), -1, MenuEditId, 5 );
224   int viewMenu = createMenu( tr( "MEN_DESK_VIEW" ), -1, MenuViewId, 10 );
225   int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, MenuHelpId, 1000 );
226
227   // Create menu items
228
229   createMenu( FileNewId,    fileMenu, 0 );
230   createMenu( FileOpenId,   fileMenu, 0 );
231   createMenu( FileReopenId, fileMenu, 0 ); 
232   createMenu( FileCloseId,  fileMenu, 5 );
233   createMenu( separator(),  fileMenu, -1, 5 );
234   createMenu( FileSaveId,   fileMenu, 5 );
235   createMenu( FileSaveAsId, fileMenu, 5 );
236   createMenu( separator(),  fileMenu, -1, 5 );
237
238   createMenu( separator(),  fileMenu );
239   createMenu( FileExitId,   fileMenu );
240
241   createMenu( EditCopyId,  editMenu );
242   createMenu( EditPasteId, editMenu );
243   createMenu( separator(), editMenu );
244
245   createMenu( ViewToolBarsId,  viewMenu, 0 );
246   createMenu( ViewWindowsId,   viewMenu, 0 );
247   createMenu( separator(),     viewMenu, -1, 10 );
248   createMenu( ViewStatusBarId, viewMenu, 10 );
249   createMenu( separator(),     viewMenu );
250
251   createMenu( HelpAboutId, helpMenu );
252   createMenu( separator(), helpMenu );
253
254   // Create tool bars
255
256   int stdTBar = createTool( tr( "INF_DESK_TOOLBAR_STANDARD" ),  // title (language-dependant)
257                             QString( "SalomeStandard" ) );      // name (language-independant)
258
259   // Create tool items
260
261   createTool( FileNewId, stdTBar );
262   createTool( FileOpenId, stdTBar );
263   createTool( FileSaveId, stdTBar );
264   createTool( FileCloseId, stdTBar );
265   createTool( separator(), stdTBar );
266   createTool( EditCopyId, stdTBar );
267   createTool( EditPasteId, stdTBar );
268 }
269
270 /*!Opens new application*/
271 void STD_Application::onNewDoc()
272 {
273   onNewDoc( QString() );
274 }
275
276 /*!Opens new application*/
277 bool STD_Application::onNewDoc( const QString& name )
278 {
279   QApplication::setOverrideCursor( Qt::WaitCursor );
280
281   bool res = true;
282   if ( !activeStudy() )
283   {
284     createEmptyStudy();
285     res = activeStudy()->createDocument( name );
286     if ( res )
287       studyCreated( activeStudy() );
288     else
289     {
290       SUIT_Study* st = activeStudy();
291       setActiveStudy( 0 );
292       delete st;
293     }
294   }
295   else
296   {
297     SUIT_Application* aApp = startApplication( 0, 0 );
298     if ( aApp->inherits( "STD_Application" ) )
299       res = ((STD_Application*)aApp)->onNewDoc( name );
300     else
301     {
302       aApp->createEmptyStudy();
303       res = aApp->activeStudy()->createDocument( name );
304     }
305     if ( !res )
306       aApp->closeApplication();
307   }
308
309   QApplication::restoreOverrideCursor();
310
311   return res;
312 }
313
314 /*!Put file name from file dialog to onOpenDoc(const QString&) function*/
315 void STD_Application::onOpenDoc()
316 {
317   // It is preferrable to use OS-specific file dialog box here !!!
318   QString aName = getFileName( true, QString(), getFileFilter(), QString(), 0 );
319   if ( aName.isNull() )
320     return;
321
322   onOpenDoc( aName );
323 }
324
325 /*! \retval true, if document was opened successful, else false.*/
326 bool STD_Application::onOpenDoc( const QString& aName )
327 {
328   QApplication::setOverrideCursor( Qt::WaitCursor );
329
330   bool res = openAction( openChoice( aName ), aName );
331   
332   QApplication::restoreOverrideCursor();
333
334   return res;
335 }
336
337 /*! Reload document from the file.*/
338 bool STD_Application::onReopenDoc()
339 {
340   bool res = false;
341
342   SUIT_Study* study = activeStudy();
343   if ( study && study->isSaved() ) {
344     // ask user for the confirmation
345     if ( SUIT_MessageBox::question( desktop(), tr( "REOPEN_STUDY" ), tr( "REOPEN_QUESTION" ),
346                                     SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No
347                                     ) == SUIT_MessageBox::No )
348       return false;
349
350     // remember study name
351     QString studyName = study->studyName();
352
353     // close study
354     beforeCloseDoc( study );
355     study->closeDocument( true );
356
357     // update views / windows / status bar / title
358     clearViewManagers();
359     setActiveStudy( 0 );
360     updateDesktopTitle();
361     updateCommandsStatus();
362
363     // delete study
364     delete study;
365     study = 0;
366     
367     // post closing actions
368     afterCloseDoc();
369
370     // reload study from the file
371     res = useFile( studyName ) && activeStudy();
372
373     // if reloading is failed, close the desktop
374     if ( !res ) {
375       setDesktop( 0 );
376       closeApplication();
377     }
378   }
379   return res;
380 }
381
382 /*!Virtual function. Not implemented here.*/
383 void STD_Application::beforeCloseDoc( SUIT_Study* )
384 {
385 }
386
387 /*!Virtual function. Not implemented here.*/
388 void STD_Application::afterCloseDoc()
389 {
390 }
391
392 /*!Close document, if it's possible.*/
393 void STD_Application::onCloseDoc( bool ask )
394 {
395   closeDoc( ask );
396 }
397
398 /*!Close document, if it's possible.*/
399 bool STD_Application::closeDoc( bool ask )
400 {
401   bool closePermanently = true;
402
403   if ( ask && !isPossibleToClose( closePermanently ) )
404     return false;
405
406   SUIT_Study* study = activeStudy();
407
408   beforeCloseDoc( study );
409
410   if ( study )
411     study->closeDocument( closePermanently );
412
413   clearViewManagers();
414
415   setActiveStudy( 0 );
416
417   int aNbStudies = 0;
418   QList<SUIT_Application*> apps = SUIT_Session::session()->applications();
419   for ( int i = 0; i < apps.count(); i++ )
420     aNbStudies += apps.at( i )->getNbStudies();
421
422   if ( aNbStudies )
423   {
424     savePreferences();
425     setDesktop( 0 );
426   }
427   else
428   {
429     updateDesktopTitle();
430     updateCommandsStatus();
431   }
432
433   // IPAL19532: deleting study should be performed after calling setDesktop(0)
434   delete study;
435
436   afterCloseDoc();
437
438   if ( !desktop() )
439     closeApplication();
440   return true;
441 }
442
443 /*!Check the application on closing.
444  * \retval true if possible, else false
445  */
446 bool STD_Application::isPossibleToClose( bool& closePermanently )
447 {
448   if ( activeStudy() )
449   {
450     activeStudy()->abortAllOperations();
451     if ( activeStudy()->isModified() )
452     {
453       QString sName = activeStudy()->studyName().trimmed();
454       return closeAction( closeChoice( sName ), closePermanently );
455     }
456   }
457   return true;
458 }
459
460 int STD_Application::closeChoice( const QString& docName )
461 {
462   int answer = SUIT_MessageBox::question( desktop(), tr( "CLOSE_STUDY" ), tr( "CLOSE_QUESTION" ).arg( docName ),
463                                           SUIT_MessageBox::Save | SUIT_MessageBox::Discard | SUIT_MessageBox::Cancel,
464                                           SUIT_MessageBox::Save );
465
466   int res = CloseCancel;
467   if ( answer == SUIT_MessageBox::Save )
468     res = CloseSave;
469   else if ( answer == SUIT_MessageBox::Discard )
470     res = CloseDiscard;
471
472   return res;
473 }
474
475 bool STD_Application::closeAction( const int choice, bool& closePermanently )
476 {
477   bool res = true;
478   switch( choice )
479   {
480   case CloseSave:
481     if ( activeStudy()->isSaved() )
482       onSaveDoc();
483     else if ( !onSaveAsDoc() )
484       res = false;
485     break;
486   case CloseDiscard:
487     break;
488   case CloseCancel:
489   default:
490     res = false;
491   }
492
493   return res;
494 }
495
496 int STD_Application::openChoice( const QString& aName )
497 {
498   SUIT_Session* aSession = SUIT_Session::session();
499
500   bool isAlreadyOpen = false;
501   QList<SUIT_Application*> aAppList = aSession->applications();
502   for ( QList<SUIT_Application*>::iterator it = aAppList.begin(); it != aAppList.end() && !isAlreadyOpen; ++it )
503     isAlreadyOpen = (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName;
504   return isAlreadyOpen ? OpenExist : OpenNew;
505 }
506
507 bool STD_Application::openAction( const int choice, const QString& aName )
508 {
509   bool res = true;
510   switch ( choice )
511   {
512   case OpenExist:
513     {
514       SUIT_Application* aApp = 0;
515       SUIT_Session* aSession = SUIT_Session::session();
516       QList<SUIT_Application*> aAppList = aSession->applications();
517       for ( QList<SUIT_Application*>::iterator it = aAppList.begin(); it != aAppList.end() && !aApp; ++it )
518       {
519         if ( (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName )
520           aApp = *it;
521       }
522       if ( aApp )
523         aApp->desktop()->activateWindow();
524       else
525         res = false;
526     }
527     break;
528   case OpenNew:
529     if ( !activeStudy() )
530       res = useFile( aName );
531     else
532     {
533       SUIT_Application* aApp = startApplication( 0, 0 );
534       if ( aApp )
535         res = aApp->useFile( aName );
536       if ( !res )
537         aApp->closeApplication();
538     }
539     break;
540   case OpenCancel:
541   default:
542     res = false;
543   }
544
545   return res;
546 }
547
548 /*!Save document if all ok, else error message.*/
549 void STD_Application::onSaveDoc()
550 {
551   if ( !activeStudy() )
552     return;
553
554   bool isOk = false;
555   if ( activeStudy()->isSaved() )
556   {
557     putInfo( tr( "INF_DOC_SAVING" ) + activeStudy()->studyName() );
558
559     QApplication::setOverrideCursor( Qt::WaitCursor );
560
561     isOk = activeStudy()->saveDocument();
562
563     QApplication::restoreOverrideCursor();
564
565     if ( !isOk )
566     {
567       putInfo( "" );
568       // displaying a message box as SUIT_Validator in case file can't be written (the most frequent case)
569       SUIT_MessageBox::critical( desktop(), tr( "ERR_ERROR" ),
570                                  tr( "INF_DOC_SAVING_FAILS" ).arg( activeStudy()->studyName() ) );
571     }
572     else
573       putInfo( tr( "INF_DOC_SAVED" ).arg( "" ) );
574   }
575
576   if ( isOk )
577     studySaved( activeStudy() );
578   else
579     onSaveAsDoc();
580 }
581
582 /*! \retval TRUE, if doument saved successful, else FALSE.*/
583 bool STD_Application::onSaveAsDoc()
584 {
585   SUIT_Study* study = activeStudy();
586   if ( !study )
587     return false;
588
589   bool isOk = false;
590   while ( !isOk )
591   {
592     QString aName = getFileName( false, study->studyName(), getFileFilter(), QString(), 0 );
593     if ( aName.isNull() )
594       return false;
595
596     QApplication::setOverrideCursor( Qt::WaitCursor );
597
598     putInfo( tr( "INF_DOC_SAVING" ) + aName );
599     isOk = study->saveDocumentAs( aName );
600
601     putInfo( isOk ? tr( "INF_DOC_SAVED" ).arg( aName ) : "" );
602
603     QApplication::restoreOverrideCursor();
604
605     if ( !isOk )
606       SUIT_MessageBox::critical( desktop(), tr( "ERROR" ), tr( "INF_DOC_SAVING_FAILS" ).arg( aName ) );
607   }
608
609   studySaved( activeStudy() );
610
611   return isOk;
612 }
613
614 /*!Closing session.*/
615 void STD_Application::onExit()
616 {
617   int aAnswer = SUIT_MessageBox::Ok;
618   if ( exitConfirmation() )
619     aAnswer = SUIT_MessageBox::question( desktop(), tr( "INF_DESK_EXIT" ), tr( "QUE_DESK_EXIT" ),
620                                          SUIT_MessageBox::Ok | SUIT_MessageBox::Cancel, SUIT_MessageBox::Cancel );
621   if ( aAnswer == SUIT_MessageBox::Ok )
622     SUIT_Session::session()->closeSession();
623 }
624
625 /*!Virtual slot. Not implemented here.*/
626 void STD_Application::onCopy()
627 {
628 }
629
630 /*!Virtual slot. Not implemented here.*/
631 void STD_Application::onPaste()
632 {
633 }
634
635 /*!Sets \a theEnable for menu manager and for tool manager.*/
636 void STD_Application::setEditEnabled( bool theEnable )
637 {
638   myEditEnabled = theEnable;
639
640   QtxActionMenuMgr* mMgr = desktop()->menuMgr();
641   QtxActionToolMgr* tMgr = desktop()->toolMgr();
642
643   for ( int i = EditCopyId; i <= EditPasteId; i++ )
644   {
645     mMgr->setShown( mMgr->actionId(action(i)), myEditEnabled );
646     tMgr->setShown( tMgr->actionId(action(i)), myEditEnabled );
647   }
648 }
649
650 /*!\retval true, if document opened successful, else false.*/
651 bool STD_Application::useFile(const QString& theFileName)
652 {
653   bool res = SUIT_Application::useFile( theFileName );
654
655   if ( res )
656     studyOpened( activeStudy() );
657
658   return res;
659 }
660
661 /*!Update desktop title.*/
662 void STD_Application::updateDesktopTitle()
663 {
664   QString aTitle = applicationName();
665   QString aVer = applicationVersion();
666   if ( !aVer.isEmpty() )
667     aTitle += QString( " " ) + aVer;
668
669   if ( activeStudy() )
670   {
671     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
672     if ( !sName.isEmpty() )
673       aTitle += QString( " - [%1]" ).arg( sName );
674   }
675
676   desktop()->setWindowTitle( aTitle );
677 }
678
679 /*!Update commands status.*/
680 void STD_Application::updateCommandsStatus()
681 {
682   SUIT_Application::updateCommandsStatus();
683
684   bool aHasStudy     = activeStudy() != 0;
685   bool aSaved        = aHasStudy && activeStudy()->isSaved();
686   bool aModified     = aHasStudy && activeStudy()->isModified();
687   bool aIsNeedToSave = aHasStudy && ( !aSaved || aModified );
688
689  if ( action( FileReopenId ) )
690     action( FileReopenId )->setEnabled( aSaved );
691  if ( action( FileSaveId ) )
692     action( FileSaveId )->setEnabled( aIsNeedToSave );
693   if ( action( FileSaveAsId ) )
694     action( FileSaveAsId )->setEnabled( aHasStudy );
695   if ( action( FileCloseId ) )
696     action( FileCloseId )->setEnabled( aHasStudy );
697   if ( action( NewWindowId ) )
698     action( NewWindowId )->setEnabled( aHasStudy );
699 }
700
701 /*!\retval SUIT_ViewManager by viewer manager type name.*/
702 SUIT_ViewManager* STD_Application::viewManager( const QString& vmType ) const
703 {
704   SUIT_ViewManager* vm = 0;
705   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end() && !vm; ++it )
706   {
707     if ( (*it)->getType() == vmType )
708       vm = *it;
709   }
710   return vm;
711 }
712
713 /*! \param vmType - input view manager type name
714  * \param lst - output list of view managers with types \a vmType.
715  */
716 void STD_Application::viewManagers( const QString& vmType, ViewManagerList& lst ) const
717 {
718   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end(); ++it )
719   {
720     if ( (*it)->getType() == vmType )
721       lst.append( *it );
722   }
723 }
724
725 /*!\param lst - output list of all view managers.*/
726 void STD_Application::viewManagers( ViewManagerList& lst ) const
727 {
728   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end(); ++it )
729     lst.append( *it );
730 }
731
732 /*!\retval ViewManagerList - const list of all view managers.*/
733 ViewManagerList STD_Application::viewManagers() const
734 {
735   ViewManagerList lst;
736   viewManagers( lst );
737   return lst;
738 }
739
740 /*!\retval SUIT_ViewManager - return pointer to active view manager.*/
741 SUIT_ViewManager* STD_Application::activeViewManager() const
742 {
743   return myActiveViewMgr;
744 }
745
746 /*!Add view manager to view managers list, if it not already there.*/
747 void STD_Application::addViewManager( SUIT_ViewManager* vm )
748 {
749   if ( !vm )
750     return;
751
752   if ( !containsViewManager( vm ) )
753   {
754     myViewMgrs.append( vm );
755     connect( vm, SIGNAL( activated( SUIT_ViewManager* ) ),
756              this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
757     vm->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
758
759     emit viewManagerAdded( vm );
760   }
761 /*
762   if ( !activeViewManager() && myViewMgrs.count() == 1 )
763     setActiveViewManager( vm );
764 */
765 }
766
767 /*!Remove view manager from view managers list.*/
768 void STD_Application::removeViewManager( SUIT_ViewManager* vm )
769 {
770   if ( !vm )
771     return;
772
773   vm->closeAllViews();
774
775   emit viewManagerRemoved( vm );
776
777   vm->disconnectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
778   disconnect( vm, SIGNAL( activated( SUIT_ViewManager* ) ),
779              this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
780   myViewMgrs.removeAll( vm );
781
782   if ( myActiveViewMgr == vm )
783     myActiveViewMgr = 0;
784 }
785
786 /*!Remove all view managers from view managers list.*/
787 void STD_Application::clearViewManagers()
788 {
789   ViewManagerList lst;
790   viewManagers( lst );
791
792   for ( QList<SUIT_ViewManager*>::iterator it = lst.begin(); it != lst.end(); ++it )
793   {
794     QPointer<SUIT_ViewManager> vm = *it;
795     removeViewManager( vm );
796     delete vm;
797   }
798 }
799
800 /*!\retval TRUE, if view manager \a vm, already in view manager list (\a myViewMgrs).*/
801 bool STD_Application::containsViewManager( SUIT_ViewManager* vm ) const
802 {
803   return myViewMgrs.contains( vm );
804 }
805
806 /*!Private slot, sets active manager to \vm, if \vm in view managers list.*/
807 void STD_Application::onViewManagerActivated( SUIT_ViewManager* vm )
808 {
809   setActiveViewManager( vm );
810 }
811
812 /*!Sets status bar show, if \on = true, else status bar hide.*/
813 void STD_Application::onViewStatusBar( bool on )
814 {
815   if ( on )
816     desktop()->statusBar()->show();
817   else
818     desktop()->statusBar()->hide();
819 }
820
821 /*!Call SUIT_MessageBox::info1(...) with about information.*/
822 void STD_Application::onHelpAbout()
823 {
824   SUIT_MessageBox::information( desktop(), tr( "About" ), tr( "ABOUT_INFO" ) );
825 }
826
827 /*!Create empty study. \n
828  * Create new view manager and adding it to view managers list.
829  */
830 void STD_Application::createEmptyStudy()
831 {
832   SUIT_Application::createEmptyStudy();
833 }
834
835 /*!Sets active manager to \vm, if \vm in view managers list.*/
836 void STD_Application::setActiveViewManager( SUIT_ViewManager* vm )
837 {
838   if ( !containsViewManager( vm ) )
839     return;
840
841   myActiveViewMgr = vm;
842   emit viewManagerActivated( vm );
843 }
844
845 /*!Public slot. */
846 void STD_Application::onConnectPopupRequest( SUIT_PopupClient* client, QContextMenuEvent* e )
847 {
848   QtxMenu* popup = new QtxMenu();
849   // fill popup by own items
850   QString title;
851   contextMenuPopup( client->popupClientType(), popup, title );
852   popup->setTitleText( title );
853
854   popup->addSeparator();
855   // add items from popup client
856   client->contextMenuPopup( popup );
857
858   SUIT_Tools::simplifySeparators( popup );
859
860   if ( !popup->actions().isEmpty() )
861     popup->exec( e->globalPos() );
862   delete popup;
863 }
864
865 /*!\retval QString - return file name from dialog.*/
866 QString STD_Application::getFileName( bool open, const QString& initial, const QString& filters,
867                                       const QString& caption, QWidget* parent )
868 {
869   if ( !parent )
870     parent = desktop();
871   if ( open )
872     return QFileDialog::getOpenFileName( parent, caption, initial, filters );
873   else
874   {
875     QString aName;
876     QString aUsedFilter;
877     QString anOldPath = initial;
878
879     bool isOk = false;
880     while ( !isOk )
881     {
882       // It is preferrable to use OS-specific file dialog box here !!!
883       aName = QFileDialog::getSaveFileName( parent, caption, anOldPath, filters, &aUsedFilter );
884
885       if ( aName.isNull() )
886         isOk = true;
887       else
888       {
889         int aEnd = aUsedFilter.lastIndexOf( ')' );
890         int aStart = aUsedFilter.lastIndexOf( '(', aEnd );
891         QString wcStr = aUsedFilter.mid( aStart + 1, aEnd - aStart - 1 );
892
893         int idx = 0;
894         QStringList extList;
895         QRegExp rx( "[\b\\*]*\\.([\\w]+)" );
896         while ( ( idx = rx.indexIn( wcStr, idx ) ) != -1 )
897         {
898           extList.append( rx.cap( 1 ) );
899           idx += rx.matchedLength();
900         }
901
902         if ( !extList.isEmpty() && !extList.contains( SUIT_Tools::extension( aName ) ) )
903           aName += QString( ".%1" ).arg( extList.first() );
904
905         if ( QFileInfo( aName ).exists() )
906         {
907           int aAnswer = SUIT_MessageBox::question( desktop(), tr( "TIT_FILE_SAVEAS" ),
908                                                    tr( "MSG_FILE_EXISTS" ).arg( aName ),
909                                                    SUIT_MessageBox::Yes | SUIT_MessageBox::No | SUIT_MessageBox::Cancel, SUIT_MessageBox::Yes );
910           if ( aAnswer == SUIT_MessageBox::Cancel )
911           {     // cancelled
912             aName = QString();
913             isOk = true;
914           }
915           else if ( aAnswer == SUIT_MessageBox::No ) // not save to this file
916             anOldPath = aName;             // not to return to the same initial dir at each "while" step
917           else                     // overwrite the existing file
918             isOk = true;
919         }
920         else
921           isOk = true;
922       }
923     }
924     return aName;
925   }
926 }
927
928 /*!\retval QString - return directory name from dialog.*/
929 QString STD_Application::getDirectory( const QString& initial, const QString& caption, QWidget* parent )
930 {
931   if ( !parent )
932     parent = desktop();
933
934   return QFileDialog::getExistingDirectory( parent, caption, initial );
935 }
936
937 /*!
938   Changes desktop
939   \param desk - new desktop
940 */
941 void STD_Application::setDesktop( SUIT_Desktop* desk )
942 {
943   SUIT_Application::setDesktop( desk );
944
945   if ( desk ) {
946     connect( desk, SIGNAL( closing( SUIT_Desktop*, QCloseEvent* ) ),
947              this, SLOT( onDesktopClosing( SUIT_Desktop*, QCloseEvent* ) ), Qt::UniqueConnection );
948   }
949 }
950
951 /*!
952   Allow to load preferences before the desktop will be shown.
953 */
954 void STD_Application::loadPreferences()
955 {
956 }
957
958 /*!
959   Allow to save preferences before the application will be closed.
960 */
961 void STD_Application::savePreferences()
962 {
963 }
964
965 /*!
966   Custom activity after study is created
967   Updates desktop and actions
968 */
969 void STD_Application::studyCreated( SUIT_Study* )
970 {
971   updateDesktopTitle();
972   updateCommandsStatus();
973 }
974
975 /*!
976   Custom activity after study is opened
977   Updates desktop and actions
978 */
979 void STD_Application::studyOpened( SUIT_Study* )
980 {
981   updateDesktopTitle();
982   updateCommandsStatus();
983 }
984
985 /*!
986   Custom activity after study is opened
987   Updates desktop and actions
988 */
989 void STD_Application::studySaved( SUIT_Study* )
990 {
991   updateDesktopTitle();
992   updateCommandsStatus();
993 }
994
995 /*!
996   Return index of the view ma
997 */
998 int STD_Application::viewManagerId( const SUIT_ViewManager* theManager) const
999 {
1000   return myViewMgrs.indexOf(const_cast<SUIT_ViewManager*>(theManager));
1001 }
1002