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