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