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