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