Salome HOME
Merge branch V7_3_1_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" ) );
257
258   // Create tool items
259
260   createTool( FileNewId, stdTBar );
261   createTool( FileOpenId, stdTBar );
262   createTool( FileSaveId, stdTBar );
263   createTool( FileCloseId, stdTBar );
264   createTool( separator(), stdTBar );
265   createTool( EditCopyId, stdTBar );
266   createTool( EditPasteId, stdTBar );
267 }
268
269 /*!Opens new application*/
270 void STD_Application::onNewDoc()
271 {
272   onNewDoc( QString() );
273 }
274
275 /*!Opens new application*/
276 bool STD_Application::onNewDoc( const QString& name )
277 {
278   QApplication::setOverrideCursor( Qt::WaitCursor );
279
280   bool res = true;
281   if ( !activeStudy() )
282   {
283     createEmptyStudy();
284     res = activeStudy()->createDocument( name );
285     if ( res )
286       studyCreated( activeStudy() );
287     else
288     {
289       SUIT_Study* st = activeStudy();
290       setActiveStudy( 0 );
291       delete st;
292     }
293   }
294   else
295   {
296     SUIT_Application* aApp = startApplication( 0, 0 );
297     if ( aApp->inherits( "STD_Application" ) )
298       res = ((STD_Application*)aApp)->onNewDoc( name );
299     else
300     {
301       aApp->createEmptyStudy();
302       res = aApp->activeStudy()->createDocument( name );
303     }
304     if ( !res )
305       aApp->closeApplication();
306   }
307
308   QApplication::restoreOverrideCursor();
309
310   return res;
311 }
312
313 /*!Put file name from file dialog to onOpenDoc(const QString&) function*/
314 void STD_Application::onOpenDoc()
315 {
316   // It is preferrable to use OS-specific file dialog box here !!!
317   QString aName = getFileName( true, QString(), getFileFilter(), QString(), 0 );
318   if ( aName.isNull() )
319     return;
320
321   onOpenDoc( aName );
322 }
323
324 /*! \retval true, if document was opened successful, else false.*/
325 bool STD_Application::onOpenDoc( const QString& aName )
326 {
327   QApplication::setOverrideCursor( Qt::WaitCursor );
328
329   bool res = openAction( openChoice( aName ), aName );
330   
331   QApplication::restoreOverrideCursor();
332
333   return res;
334 }
335
336 /*! Reload document from the file.*/
337 bool STD_Application::onReopenDoc()
338 {
339   bool res = false;
340
341   SUIT_Study* study = activeStudy();
342   if ( study && study->isSaved() ) {
343     // ask user for the confirmation
344     if ( SUIT_MessageBox::question( desktop(), tr( "REOPEN_STUDY" ), tr( "REOPEN_QUESTION" ),
345                                     SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No
346                                     ) == SUIT_MessageBox::No )
347       return false;
348
349     // remember study name
350     QString studyName = study->studyName();
351
352     // close study
353     beforeCloseDoc( study );
354     study->closeDocument( true );
355
356     // update views / windows / status bar / title
357     clearViewManagers();
358     setActiveStudy( 0 );
359     updateDesktopTitle();
360     updateCommandsStatus();
361
362     // delete study
363     delete study;
364     study = 0;
365     
366     // post closing actions
367     afterCloseDoc();
368
369     // reload study from the file
370     res = useFile( studyName ) && activeStudy();
371
372     // if reloading is failed, close the desktop
373     if ( !res ) {
374       setDesktop( 0 );
375       closeApplication();
376     }
377   }
378   return res;
379 }
380
381 /*!Virtual function. Not implemented here.*/
382 void STD_Application::beforeCloseDoc( SUIT_Study* )
383 {
384 }
385
386 /*!Virtual function. Not implemented here.*/
387 void STD_Application::afterCloseDoc()
388 {
389 }
390
391 /*!Close document, if it's possible.*/
392 void STD_Application::onCloseDoc( bool ask )
393 {
394   closeDoc( ask );
395 }
396
397 /*!Close document, if it's possible.*/
398 bool STD_Application::closeDoc( bool ask )
399 {
400   bool closePermanently = true;
401
402   if ( ask && !isPossibleToClose( closePermanently ) )
403     return false;
404
405   SUIT_Study* study = activeStudy();
406
407   beforeCloseDoc( study );
408
409   if ( study )
410     study->closeDocument( closePermanently );
411
412   clearViewManagers();
413
414   setActiveStudy( 0 );
415
416   int aNbStudies = 0;
417   QList<SUIT_Application*> apps = SUIT_Session::session()->applications();
418   for ( int i = 0; i < apps.count(); i++ )
419     aNbStudies += apps.at( i )->getNbStudies();
420
421   if ( aNbStudies )
422   {
423     savePreferences();
424     setDesktop( 0 );
425   }
426   else
427   {
428     updateDesktopTitle();
429     updateCommandsStatus();
430   }
431
432   // IPAL19532: deleting study should be performed after calling setDesktop(0)
433   delete study;
434
435   afterCloseDoc();
436
437   if ( !desktop() )
438     closeApplication();
439   return true;
440 }
441
442 /*!Check the application on closing.
443  * \retval true if possible, else false
444  */
445 bool STD_Application::isPossibleToClose( bool& closePermanently )
446 {
447   if ( activeStudy() )
448   {
449     activeStudy()->abortAllOperations();
450     if ( activeStudy()->isModified() )
451     {
452       QString sName = activeStudy()->studyName().trimmed();
453       return closeAction( closeChoice( sName ), closePermanently );
454     }
455   }
456   return true;
457 }
458
459 int STD_Application::closeChoice( const QString& docName )
460 {
461   int answer = SUIT_MessageBox::question( desktop(), tr( "CLOSE_STUDY" ), tr( "CLOSE_QUESTION" ).arg( docName ),
462                                           SUIT_MessageBox::Save | SUIT_MessageBox::Discard | SUIT_MessageBox::Cancel,
463                                           SUIT_MessageBox::Save );
464
465   int res = CloseCancel;
466   if ( answer == SUIT_MessageBox::Save )
467     res = CloseSave;
468   else if ( answer == SUIT_MessageBox::Discard )
469     res = CloseDiscard;
470
471   return res;
472 }
473
474 bool STD_Application::closeAction( const int choice, bool& closePermanently )
475 {
476   bool res = true;
477   switch( choice )
478   {
479   case CloseSave:
480     if ( activeStudy()->isSaved() )
481       onSaveDoc();
482     else if ( !onSaveAsDoc() )
483       res = false;
484     break;
485   case CloseDiscard:
486     break;
487   case CloseCancel:
488   default:
489     res = false;
490   }
491
492   return res;
493 }
494
495 int STD_Application::openChoice( const QString& aName )
496 {
497   SUIT_Session* aSession = SUIT_Session::session();
498
499   bool isAlreadyOpen = false;
500   QList<SUIT_Application*> aAppList = aSession->applications();
501   for ( QList<SUIT_Application*>::iterator it = aAppList.begin(); it != aAppList.end() && !isAlreadyOpen; ++it )
502     isAlreadyOpen = (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName;
503   return isAlreadyOpen ? OpenExist : OpenNew;
504 }
505
506 bool STD_Application::openAction( const int choice, const QString& aName )
507 {
508   bool res = true;
509   switch ( choice )
510   {
511   case OpenExist:
512     {
513       SUIT_Application* aApp = 0;
514       SUIT_Session* aSession = SUIT_Session::session();
515       QList<SUIT_Application*> aAppList = aSession->applications();
516       for ( QList<SUIT_Application*>::iterator it = aAppList.begin(); it != aAppList.end() && !aApp; ++it )
517       {
518         if ( (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName )
519           aApp = *it;
520       }
521       if ( aApp )
522         aApp->desktop()->activateWindow();
523       else
524         res = false;
525     }
526     break;
527   case OpenNew:
528     if ( !activeStudy() )
529       res = useFile( aName );
530     else
531     {
532       SUIT_Application* aApp = startApplication( 0, 0 );
533       if ( aApp )
534         res = aApp->useFile( aName );
535       if ( !res )
536         aApp->closeApplication();
537     }
538     break;
539   case OpenCancel:
540   default:
541     res = false;
542   }
543
544   return res;
545 }
546
547 /*!Save document if all ok, else error message.*/
548 void STD_Application::onSaveDoc()
549 {
550   if ( !activeStudy() )
551     return;
552
553   bool isOk = false;
554   if ( activeStudy()->isSaved() )
555   {
556     putInfo( tr( "INF_DOC_SAVING" ) + activeStudy()->studyName() );
557
558     QApplication::setOverrideCursor( Qt::WaitCursor );
559
560     isOk = activeStudy()->saveDocument();
561
562     QApplication::restoreOverrideCursor();
563
564     if ( !isOk )
565     {
566       putInfo( "" );
567       // displaying a message box as SUIT_Validator in case file can't be written (the most frequent case)
568       SUIT_MessageBox::critical( desktop(), tr( "ERR_ERROR" ),
569                                  tr( "INF_DOC_SAVING_FAILS" ).arg( activeStudy()->studyName() ) );
570     }
571     else
572       putInfo( tr( "INF_DOC_SAVED" ).arg( "" ) );
573   }
574
575   if ( isOk )
576     studySaved( activeStudy() );
577   else
578     onSaveAsDoc();
579 }
580
581 /*! \retval TRUE, if doument saved successful, else FALSE.*/
582 bool STD_Application::onSaveAsDoc()
583 {
584   SUIT_Study* study = activeStudy();
585   if ( !study )
586     return false;
587
588   bool isOk = false;
589   while ( !isOk )
590   {
591     QString aName = getFileName( false, study->studyName(), getFileFilter(), QString(), 0 );
592     if ( aName.isNull() )
593       return false;
594
595     QApplication::setOverrideCursor( Qt::WaitCursor );
596
597     putInfo( tr( "INF_DOC_SAVING" ) + aName );
598     isOk = study->saveDocumentAs( aName );
599
600     putInfo( isOk ? tr( "INF_DOC_SAVED" ).arg( aName ) : "" );
601
602     QApplication::restoreOverrideCursor();
603
604     if ( !isOk )
605       SUIT_MessageBox::critical( desktop(), tr( "ERROR" ), tr( "INF_DOC_SAVING_FAILS" ).arg( aName ) );
606   }
607
608   studySaved( activeStudy() );
609
610   return isOk;
611 }
612
613 /*!Closing session.*/
614 void STD_Application::onExit()
615 {
616   int aAnswer = SUIT_MessageBox::Ok;
617   if ( exitConfirmation() )
618     aAnswer = SUIT_MessageBox::question( desktop(), tr( "INF_DESK_EXIT" ), tr( "QUE_DESK_EXIT" ),
619                                          SUIT_MessageBox::Ok | SUIT_MessageBox::Cancel, SUIT_MessageBox::Cancel );
620   if ( aAnswer == SUIT_MessageBox::Ok )
621     SUIT_Session::session()->closeSession();
622 }
623
624 /*!Virtual slot. Not implemented here.*/
625 void STD_Application::onCopy()
626 {
627 }
628
629 /*!Virtual slot. Not implemented here.*/
630 void STD_Application::onPaste()
631 {
632 }
633
634 /*!Sets \a theEnable for menu manager and for tool manager.*/
635 void STD_Application::setEditEnabled( bool theEnable )
636 {
637   myEditEnabled = theEnable;
638
639   QtxActionMenuMgr* mMgr = desktop()->menuMgr();
640   QtxActionToolMgr* tMgr = desktop()->toolMgr();
641
642   for ( int i = EditCopyId; i <= EditPasteId; i++ )
643   {
644     mMgr->setShown( mMgr->actionId(action(i)), myEditEnabled );
645     tMgr->setShown( tMgr->actionId(action(i)), myEditEnabled );
646   }
647 }
648
649 /*!\retval true, if document opened successful, else false.*/
650 bool STD_Application::useFile(const QString& theFileName)
651 {
652   bool res = SUIT_Application::useFile( theFileName );
653
654   if ( res )
655     studyOpened( activeStudy() );
656
657   return res;
658 }
659
660 /*!Update desktop title.*/
661 void STD_Application::updateDesktopTitle()
662 {
663   QString aTitle = applicationName();
664   QString aVer = applicationVersion();
665   if ( !aVer.isEmpty() )
666     aTitle += QString( " " ) + aVer;
667
668   if ( activeStudy() )
669   {
670     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
671     if ( !sName.isEmpty() )
672       aTitle += QString( " - [%1]" ).arg( sName );
673   }
674
675   desktop()->setWindowTitle( aTitle );
676 }
677
678 /*!Update commands status.*/
679 void STD_Application::updateCommandsStatus()
680 {
681   SUIT_Application::updateCommandsStatus();
682
683   bool aHasStudy     = activeStudy() != 0;
684   bool aSaved        = aHasStudy && activeStudy()->isSaved();
685   bool aModified     = aHasStudy && activeStudy()->isModified();
686   bool aIsNeedToSave = aHasStudy && ( !aSaved || aModified );
687
688  if ( action( FileReopenId ) )
689     action( FileReopenId )->setEnabled( aSaved );
690  if ( action( FileSaveId ) )
691     action( FileSaveId )->setEnabled( aIsNeedToSave );
692   if ( action( FileSaveAsId ) )
693     action( FileSaveAsId )->setEnabled( aHasStudy );
694   if ( action( FileCloseId ) )
695     action( FileCloseId )->setEnabled( aHasStudy );
696   if ( action( NewWindowId ) )
697     action( NewWindowId )->setEnabled( aHasStudy );
698 }
699
700 /*!\retval SUIT_ViewManager by viewer manager type name.*/
701 SUIT_ViewManager* STD_Application::viewManager( const QString& vmType ) const
702 {
703   SUIT_ViewManager* vm = 0;
704   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end() && !vm; ++it )
705   {
706     if ( (*it)->getType() == vmType )
707       vm = *it;
708   }
709   return vm;
710 }
711
712 /*! \param vmType - input view manager type name
713  * \param lst - output list of view managers with types \a vmType.
714  */
715 void STD_Application::viewManagers( const QString& vmType, ViewManagerList& lst ) const
716 {
717   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end(); ++it )
718   {
719     if ( (*it)->getType() == vmType )
720       lst.append( *it );
721   }
722 }
723
724 /*!\param lst - output list of all view managers.*/
725 void STD_Application::viewManagers( ViewManagerList& lst ) const
726 {
727   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end(); ++it )
728     lst.append( *it );
729 }
730
731 /*!\retval ViewManagerList - const list of all view managers.*/
732 ViewManagerList STD_Application::viewManagers() const
733 {
734   ViewManagerList lst;
735   viewManagers( lst );
736   return lst;
737 }
738
739 /*!\retval SUIT_ViewManager - return pointer to active view manager.*/
740 SUIT_ViewManager* STD_Application::activeViewManager() const
741 {
742   return myActiveViewMgr;
743 }
744
745 /*!Add view manager to view managers list, if it not already there.*/
746 void STD_Application::addViewManager( SUIT_ViewManager* vm )
747 {
748   if ( !vm )
749     return;
750
751   if ( !containsViewManager( vm ) )
752   {
753     myViewMgrs.append( vm );
754     connect( vm, SIGNAL( activated( SUIT_ViewManager* ) ),
755              this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
756     vm->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
757
758     emit viewManagerAdded( vm );
759   }
760 /*
761   if ( !activeViewManager() && myViewMgrs.count() == 1 )
762     setActiveViewManager( vm );
763 */
764 }
765
766 /*!Remove view manager from view managers list.*/
767 void STD_Application::removeViewManager( SUIT_ViewManager* vm )
768 {
769   if ( !vm )
770     return;
771
772   vm->closeAllViews();
773
774   emit viewManagerRemoved( vm );
775
776   vm->disconnectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
777   disconnect( vm, SIGNAL( activated( SUIT_ViewManager* ) ),
778              this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
779   myViewMgrs.removeAll( vm );
780
781   if ( myActiveViewMgr == vm )
782     myActiveViewMgr = 0;
783 }
784
785 /*!Remove all view managers from view managers list.*/
786 void STD_Application::clearViewManagers()
787 {
788   ViewManagerList lst;
789   viewManagers( lst );
790
791   for ( QList<SUIT_ViewManager*>::iterator it = lst.begin(); it != lst.end(); ++it )
792   {
793     QPointer<SUIT_ViewManager> vm = *it;
794     removeViewManager( vm );
795     delete vm;
796   }
797 }
798
799 /*!\retval TRUE, if view manager \a vm, already in view manager list (\a myViewMgrs).*/
800 bool STD_Application::containsViewManager( SUIT_ViewManager* vm ) const
801 {
802   return myViewMgrs.contains( vm );
803 }
804
805 /*!Private slot, sets active manager to \vm, if \vm in view managers list.*/
806 void STD_Application::onViewManagerActivated( SUIT_ViewManager* vm )
807 {
808   setActiveViewManager( vm );
809 }
810
811 /*!Sets status bar show, if \on = true, else status bar hide.*/
812 void STD_Application::onViewStatusBar( bool on )
813 {
814   if ( on )
815     desktop()->statusBar()->show();
816   else
817     desktop()->statusBar()->hide();
818 }
819
820 /*!Call SUIT_MessageBox::info1(...) with about information.*/
821 void STD_Application::onHelpAbout()
822 {
823   SUIT_MessageBox::information( desktop(), tr( "About" ), tr( "ABOUT_INFO" ) );
824 }
825
826 /*!Create empty study. \n
827  * Create new view manager and adding it to view managers list.
828  */
829 void STD_Application::createEmptyStudy()
830 {
831   SUIT_Application::createEmptyStudy();
832 }
833
834 /*!Sets active manager to \vm, if \vm in view managers list.*/
835 void STD_Application::setActiveViewManager( SUIT_ViewManager* vm )
836 {
837   if ( !containsViewManager( vm ) )
838     return;
839
840   myActiveViewMgr = vm;
841   emit viewManagerActivated( vm );
842 }
843
844 /*!Public slot. */
845 void STD_Application::onConnectPopupRequest( SUIT_PopupClient* client, QContextMenuEvent* e )
846 {
847   QtxMenu* popup = new QtxMenu();
848   // fill popup by own items
849   QString title;
850   contextMenuPopup( client->popupClientType(), popup, title );
851   popup->setTitleText( title );
852
853   popup->addSeparator();
854   // add items from popup client
855   client->contextMenuPopup( popup );
856
857   SUIT_Tools::simplifySeparators( popup );
858
859   if ( !popup->actions().isEmpty() )
860     popup->exec( e->globalPos() );
861   delete popup;
862 }
863
864 /*!\retval QString - return file name from dialog.*/
865 QString STD_Application::getFileName( bool open, const QString& initial, const QString& filters,
866                                       const QString& caption, QWidget* parent )
867 {
868   if ( !parent )
869     parent = desktop();
870   if ( open )
871     return QFileDialog::getOpenFileName( parent, caption, initial, filters );
872   else
873   {
874     QString aName;
875     QString aUsedFilter;
876     QString anOldPath = initial;
877
878     bool isOk = false;
879     while ( !isOk )
880     {
881       // It is preferrable to use OS-specific file dialog box here !!!
882       aName = QFileDialog::getSaveFileName( parent, caption, anOldPath, filters, &aUsedFilter );
883
884       if ( aName.isNull() )
885         isOk = true;
886       else
887       {
888         int aEnd = aUsedFilter.lastIndexOf( ')' );
889         int aStart = aUsedFilter.lastIndexOf( '(', aEnd );
890         QString wcStr = aUsedFilter.mid( aStart + 1, aEnd - aStart - 1 );
891
892         int idx = 0;
893         QStringList extList;
894         QRegExp rx( "[\b\\*]*\\.([\\w]+)" );
895         while ( ( idx = rx.indexIn( wcStr, idx ) ) != -1 )
896         {
897           extList.append( rx.cap( 1 ) );
898           idx += rx.matchedLength();
899         }
900
901         if ( !extList.isEmpty() && !extList.contains( SUIT_Tools::extension( aName ) ) )
902           aName += QString( ".%1" ).arg( extList.first() );
903
904         if ( QFileInfo( aName ).exists() )
905         {
906           int aAnswer = SUIT_MessageBox::question( desktop(), tr( "TIT_FILE_SAVEAS" ),
907                                                    tr( "MSG_FILE_EXISTS" ).arg( aName ),
908                                                    SUIT_MessageBox::Yes | SUIT_MessageBox::No | SUIT_MessageBox::Cancel, SUIT_MessageBox::Yes );
909           if ( aAnswer == SUIT_MessageBox::Cancel )
910           {     // cancelled
911             aName = QString();
912             isOk = true;
913           }
914           else if ( aAnswer == SUIT_MessageBox::No ) // not save to this file
915             anOldPath = aName;             // not to return to the same initial dir at each "while" step
916           else                     // overwrite the existing file
917             isOk = true;
918         }
919         else
920           isOk = true;
921       }
922     }
923     return aName;
924   }
925 }
926
927 /*!\retval QString - return directory name from dialog.*/
928 QString STD_Application::getDirectory( const QString& initial, const QString& caption, QWidget* parent )
929 {
930   if ( !parent )
931     parent = desktop();
932
933   return QFileDialog::getExistingDirectory( parent, caption, initial );
934 }
935
936 /*!
937   Changes desktop
938   \param desk - new desktop
939 */
940 void STD_Application::setDesktop( SUIT_Desktop* desk )
941 {
942   SUIT_Application::setDesktop( desk );
943
944   if ( desk ) {
945     connect( desk, SIGNAL( closing( SUIT_Desktop*, QCloseEvent* ) ),
946              this, SLOT( onDesktopClosing( SUIT_Desktop*, QCloseEvent* ) ), Qt::UniqueConnection );
947   }
948 }
949
950 /*!
951   Allow to load preferences before the desktop will be shown.
952 */
953 void STD_Application::loadPreferences()
954 {
955 }
956
957 /*!
958   Allow to save preferences before the application will be closed.
959 */
960 void STD_Application::savePreferences()
961 {
962 }
963
964 /*!
965   Custom activity after study is created
966   Updates desktop and actions
967 */
968 void STD_Application::studyCreated( SUIT_Study* )
969 {
970   updateDesktopTitle();
971   updateCommandsStatus();
972 }
973
974 /*!
975   Custom activity after study is opened
976   Updates desktop and actions
977 */
978 void STD_Application::studyOpened( SUIT_Study* )
979 {
980   updateDesktopTitle();
981   updateCommandsStatus();
982 }
983
984 /*!
985   Custom activity after study is opened
986   Updates desktop and actions
987 */
988 void STD_Application::studySaved( SUIT_Study* )
989 {
990   updateDesktopTitle();
991   updateCommandsStatus();
992 }
993
994 /*!
995   Return index of the view ma
996 */
997 int STD_Application::viewManagerId( const SUIT_ViewManager* theManager) const
998 {
999   return myViewMgrs.indexOf(const_cast<SUIT_ViewManager*>(theManager));
1000 }
1001