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