]> SALOME platform Git repositories - modules/gui.git/blob - src/STD/STD_Application.cxx
Salome HOME
0023564: [EDF] AsterStudy: introduce a feature to show popup notifications
[modules/gui.git] / src / STD / STD_Application.cxx
1 // Copyright (C) 2007-2016  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   myNotify( 0 ),
57   myExitConfirm( true ),
58   myEditEnabled( true )
59 {
60   setDesktop( new STD_MDIDesktop() );
61 }
62
63 /*!Destructor.*/
64 STD_Application::~STD_Application()
65 {
66   clearViewManagers();
67 }
68
69 /*! \retval requirement of exit confirmation*/
70 bool STD_Application::exitConfirmation() const
71 {
72   return myExitConfirm;
73 }
74
75 /*! Set the requirement of exit confirmation*/
76 void STD_Application::setExitConfirmation( const bool on )
77 {
78   myExitConfirm = on;
79 }
80
81 /*! \retval QString "StdApplication"*/
82 QString STD_Application::applicationName() const
83 {
84   return QString( "StdApplication" );
85 }
86
87 /*!Start STD_Application*/
88 void STD_Application::start()
89 {
90   createActions();
91
92   updateDesktopTitle();
93   updateCommandsStatus();
94   setEditEnabled( myEditEnabled );
95
96   loadPreferences();
97
98   SUIT_Application::start();
99 }
100
101 /*!
102   Close the Application
103 */
104 void STD_Application::closeApplication()
105 {
106   if ( desktop() )
107     savePreferences();
108   SUIT_Study* study = activeStudy();
109
110   if ( study )
111   {
112     beforeCloseDoc( study );
113
114     study->closeDocument();
115     emit appClosed();
116     setActiveStudy( 0 );
117     delete study;
118
119     afterCloseDoc();
120   }
121
122   setDesktop( 0 );
123
124   SUIT_Application::closeApplication();
125 }
126
127 /*!Event on closing desktop*/
128 void STD_Application::onDesktopClosing( SUIT_Desktop*, QCloseEvent* e )
129 {
130   if ( SUIT_Session::session()->applications().count() < 2 )
131   {
132     onExit();
133     return;
134   }
135
136   bool closePermanently;
137   if ( !isPossibleToClose( closePermanently ) )
138   {
139     e->ignore();
140     return;
141   }
142
143   closeApplication();
144 }
145
146 /*!Create actions, menus and tools*/
147 void STD_Application::createActions()
148 {
149   SUIT_Desktop* desk = desktop();
150   SUIT_ResourceMgr* resMgr = resourceMgr();
151   if ( !desk || !resMgr )
152     return;
153
154   // Create actions
155
156   createAction( FileNewId, tr( "TOT_DESK_FILE_NEW" ),
157                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_NEW" ) ),
158                 tr( "MEN_DESK_FILE_NEW" ), tr( "PRP_DESK_FILE_NEW" ),
159                 Qt::CTRL+Qt::Key_N, desk, false, this, SLOT( onNewDoc() ) );
160
161   createAction( FileOpenId, tr( "TOT_DESK_FILE_OPEN" ),
162                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
163                 tr( "MEN_DESK_FILE_OPEN" ), tr( "PRP_DESK_FILE_OPEN" ),
164                 Qt::CTRL+Qt::Key_O, desk, false, this, SLOT( onOpenDoc() ) );
165
166   createAction( FileReopenId, tr( "TOT_DESK_FILE_REOPEN" ), QIcon(),
167                 tr( "MEN_DESK_FILE_REOPEN" ), tr( "PRP_DESK_FILE_REOPEN" ),
168                 0, desk, false, this, SLOT( onReopenDoc() ) );
169
170   createAction( FileCloseId, tr( "TOT_DESK_FILE_CLOSE" ),
171                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_CLOSE" ) ),
172                 tr( "MEN_DESK_FILE_CLOSE" ), tr( "PRP_DESK_FILE_CLOSE" ),
173                 Qt::CTRL+Qt::Key_W, desk, false, this, SLOT( onCloseDoc() ) );
174
175   createAction( FileExitId, tr( "TOT_DESK_FILE_EXIT" ), QIcon(),
176                 tr( "MEN_DESK_FILE_EXIT" ), tr( "PRP_DESK_FILE_EXIT" ),
177                 Qt::CTRL+Qt::Key_Q, desk, false, this, SLOT( onExit() ) );
178
179   createAction( FileSaveId, tr( "TOT_DESK_FILE_SAVE" ),
180                 resMgr->loadPixmap( "STD", tr( "ICON_FILE_SAVE" ) ),
181                 tr( "MEN_DESK_FILE_SAVE" ), tr( "PRP_DESK_FILE_SAVE" ),
182                 Qt::CTRL+Qt::Key_S, desk, false, this, SLOT( onSaveDoc() ) );
183
184   createAction( FileSaveAsId, tr( "TOT_DESK_FILE_SAVEAS" ), QIcon(),
185                 tr( "MEN_DESK_FILE_SAVEAS" ), tr( "PRP_DESK_FILE_SAVEAS" ),
186                 Qt::CTRL+Qt::SHIFT+Qt::Key_S, desk, false, this, SLOT( onSaveAsDoc() ) );
187
188   createAction( EditCopyId, tr( "TOT_DESK_EDIT_COPY" ),
189                 resMgr->loadPixmap( "STD", tr( "ICON_EDIT_COPY" ) ),
190                 tr( "MEN_DESK_EDIT_COPY" ), tr( "PRP_DESK_EDIT_COPY" ),
191                 Qt::CTRL+Qt::Key_C, desk, false, this, SLOT( onCopy() ) );
192
193   createAction( EditPasteId, tr( "TOT_DESK_EDIT_PASTE" ),
194                 resMgr->loadPixmap( "STD", tr( "ICON_EDIT_PASTE" ) ),
195                 tr( "MEN_DESK_EDIT_PASTE" ), tr( "PRP_DESK_EDIT_PASTE" ),
196                 Qt::CTRL+Qt::Key_V, desk, false, this, SLOT( onPaste() ) );
197
198   QAction* a = createAction( ViewStatusBarId, tr( "TOT_DESK_VIEW_STATUSBAR" ),
199                              QIcon(), tr( "MEN_DESK_VIEW_STATUSBAR" ),
200                              tr( "PRP_DESK_VIEW_STATUSBAR" ), Qt::ALT+Qt::SHIFT+Qt::Key_S, desk, true );
201   a->setChecked( desk->statusBar()->isVisibleTo( desk ) );
202   connect( a, SIGNAL( toggled( bool ) ), this, SLOT( onViewStatusBar( bool ) ) );
203
204   createAction( NewWindowId, tr( "TOT_DESK_NEWWINDOW" ), QIcon(),
205                 tr( "MEN_DESK_NEWWINDOW" ), tr( "PRP_DESK_NEWWINDOW" ), 0, desk  );
206
207   createAction( HelpAboutId, tr( "TOT_DESK_HELP_ABOUT" ),
208                 resMgr->loadPixmap( "STD", tr( "ICON_DESK_ABOUT" ) ),
209                 tr( "MEN_DESK_HELP_ABOUT" ), tr( "PRP_DESK_HELP_ABOUT" ),
210                 Qt::ALT+Qt::SHIFT+Qt::Key_A, desk, false, this, SLOT( onHelpAbout() ) );
211
212
213   QtxDockAction* dwa = new QtxDockAction( tr( "TOT_DOCKWINDOWS" ), tr( "MEN_DESK_VIEW_DOCKWINDOWS" ), desk );
214   dwa->setDockType( QtxDockAction::DockWidget );
215   registerAction( ViewWindowsId, dwa );
216
217   QtxDockAction* tba = new QtxDockAction( tr( "TOT_TOOLBARS" ), tr( "MEN_DESK_VIEW_TOOLBARS" ), desk );
218   tba->setDockType( QtxDockAction::ToolBar );
219   registerAction( ViewToolBarsId, tba );
220
221   // Create menus
222
223   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1, MenuFileId, 0 );
224   // Let the application developers insert some menus between Edit and View
225   int editMenu = createMenu( tr( "MEN_DESK_EDIT" ), -1, MenuEditId, 5 );
226   int viewMenu = createMenu( tr( "MEN_DESK_VIEW" ), -1, MenuViewId, 10 );
227   int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, MenuHelpId, 1000 );
228
229   // Create menu items
230
231   createMenu( FileNewId,    fileMenu, 0 );
232   createMenu( FileOpenId,   fileMenu, 0 );
233   createMenu( FileReopenId, fileMenu, 0 ); 
234   createMenu( FileSaveId,   fileMenu, 5 );
235   createMenu( FileSaveAsId, fileMenu, 5 );
236   createMenu( FileCloseId,  fileMenu, 5 );
237   createMenu( separator(),  fileMenu, -1, 5 );
238
239   createMenu( separator(),  fileMenu );
240   createMenu( FileExitId,   fileMenu );
241
242   createMenu( EditCopyId,  editMenu );
243   createMenu( EditPasteId, editMenu );
244   createMenu( separator(), editMenu );
245
246   createMenu( ViewToolBarsId,  viewMenu, 0 );
247   createMenu( ViewWindowsId,   viewMenu, 0 );
248   createMenu( separator(),     viewMenu, -1, 10 );
249   createMenu( ViewStatusBarId, viewMenu, 10 );
250   createMenu( separator(),     viewMenu );
251
252   createMenu( HelpAboutId, helpMenu );
253   createMenu( separator(), helpMenu );
254
255   // Create tool bars
256
257   int stdTBar = createTool( tr( "INF_DESK_TOOLBAR_STANDARD" ),  // title (language-dependant)
258                             QString( "SalomeStandard" ) );      // name (language-independant)
259
260   // Create tool items
261
262   createTool( FileNewId, stdTBar );
263   createTool( FileOpenId, stdTBar );
264   createTool( FileSaveId, stdTBar );
265   createTool( FileCloseId, stdTBar );
266   createTool( separator(), stdTBar );
267   createTool( EditCopyId, stdTBar );
268   createTool( EditPasteId, stdTBar );
269 }
270
271 /*!Opens new application*/
272 void STD_Application::onNewDoc()
273 {
274   onNewDoc( QString() );
275 }
276
277 /*!Opens new application*/
278 bool STD_Application::onNewDoc( const QString& name )
279 {
280   QApplication::setOverrideCursor( Qt::WaitCursor );
281
282   bool res = true;
283   if ( !activeStudy() )
284   {
285     createEmptyStudy();
286     res = activeStudy()->createDocument( name );
287     if ( res )
288       studyCreated( activeStudy() );
289     else
290     {
291       SUIT_Study* st = activeStudy();
292       setActiveStudy( 0 );
293       delete st;
294     }
295   }
296   else
297   {
298     SUIT_Application* aApp = startApplication( 0, 0 );
299     if ( aApp->inherits( "STD_Application" ) )
300       res = ((STD_Application*)aApp)->onNewDoc( name );
301     else
302     {
303       aApp->createEmptyStudy();
304       res = aApp->activeStudy()->createDocument( name );
305     }
306     if ( !res )
307       aApp->closeApplication();
308   }
309
310   QApplication::restoreOverrideCursor();
311
312   return res;
313 }
314
315 /*!Put file name from file dialog to onOpenDoc(const QString&) function*/
316 void STD_Application::onOpenDoc()
317 {
318   // It is preferrable to use OS-specific file dialog box here !!!
319   QString aName = getFileName( true, QString(), getFileFilter( true ), QString(), 0 );
320   if ( aName.isNull() )
321     return;
322
323   onOpenDoc( aName );
324 }
325
326 /*! \retval \c true, if document was opened successful, else \c false.*/
327 bool STD_Application::onOpenDoc( const QString& aName )
328 {
329   if ( !abortAllOperations() )
330     return false;
331
332   QApplication::setOverrideCursor( Qt::WaitCursor );
333
334   bool res = openAction( openChoice( aName ), aName );
335   
336   QApplication::restoreOverrideCursor();
337
338   return res;
339 }
340
341 /*! Reload document from the file.*/
342 bool STD_Application::onReopenDoc()
343 {
344   bool res = false;
345
346   SUIT_Study* study = activeStudy();
347   if ( study && study->isSaved() ) {
348     // ask user for the confirmation
349     if ( SUIT_MessageBox::question( desktop(), tr( "REOPEN_STUDY" ), tr( "REOPEN_QUESTION" ),
350                                     SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No
351                                     ) == SUIT_MessageBox::No )
352       return false;
353
354     // remember study name
355     QString studyName = study->studyName();
356
357     // close study
358     beforeCloseDoc( study );
359     study->closeDocument( true );
360
361     // update views / windows / status bar / title
362     clearViewManagers();
363     setActiveStudy( 0 );
364
365     // delete study
366     delete study;
367     study = 0;
368     
369     // post closing actions
370     afterCloseDoc();
371
372     int aNbStudies = 0;
373     QList<SUIT_Application*> apps = SUIT_Session::session()->applications();
374     for ( int i = 0; i < apps.count(); i++ )
375       aNbStudies += apps.at( i )->getNbStudies();
376
377     // reload study from the file
378     res = useFile( studyName ) && activeStudy();
379
380     // if reloading is failed, close the desktop
381     if ( aNbStudies && !res )
382       closeApplication();
383     else
384     {
385       updateDesktopTitle();
386       updateCommandsStatus();
387     }
388   }
389   return res;
390 }
391
392 /*!Virtual function. Not implemented here.*/
393 void STD_Application::beforeCloseDoc( SUIT_Study* )
394 {
395 }
396
397 /*!Virtual function. Not implemented here.*/
398 void STD_Application::afterCloseDoc()
399 {
400 }
401
402 /*!Close document, if it's possible.*/
403 void STD_Application::onCloseDoc( bool ask )
404 {
405   closeDoc( ask );
406 }
407
408 /*!Close document, if it's possible.*/
409 bool STD_Application::closeDoc( bool ask )
410 {
411   bool closePermanently = true;
412
413   if ( ask && !isPossibleToClose( closePermanently ) )
414     return false;
415
416   return closeActiveDoc( closePermanently );
417 }
418
419 /*!Close document.*/
420 bool STD_Application::closeActiveDoc( bool permanently )
421 {
422   SUIT_Study* study = activeStudy();
423   if ( !study ) // no active study
424     return true;
425
426   beforeCloseDoc( study );
427
428   if ( study )
429     study->closeDocument( permanently );
430
431   clearViewManagers();
432
433   setActiveStudy( 0 );
434
435   int aNbStudies = 0;
436   QList<SUIT_Application*> apps = SUIT_Session::session()->applications();
437   for ( int i = 0; i < apps.count(); i++ )
438     aNbStudies += apps.at( i )->getNbStudies();
439
440   if ( aNbStudies )
441   {
442     savePreferences();
443     setDesktop( 0 );
444   }
445   else
446   {
447     updateDesktopTitle();
448     updateCommandsStatus();
449   }
450
451   // IPAL19532: deleting study should be performed after calling setDesktop(0)
452   delete study;
453
454   afterCloseDoc();
455
456   if ( !desktop() )
457     closeApplication();
458   return true;
459 }
460
461 /*!Check the application on closing.
462  * \retval \c true if possible, else \c false
463  */
464 bool STD_Application::isPossibleToClose( bool& closePermanently )
465 {
466   if ( activeStudy() )
467   {
468     activeStudy()->abortAllOperations();
469     if ( activeStudy()->isModified() )
470     {
471       QString sName = activeStudy()->studyName().trimmed();
472       return closeAction( closeChoice( sName ), closePermanently );
473     }
474   }
475   return true;
476 }
477
478 int STD_Application::closeChoice( const QString& docName )
479 {
480   int answer = SUIT_MessageBox::question( desktop(), tr( "CLOSE_STUDY" ), tr( "CLOSE_QUESTION" ),
481                                           SUIT_MessageBox::Save | SUIT_MessageBox::Discard | SUIT_MessageBox::Cancel,
482                                           SUIT_MessageBox::Save );
483
484   int res = CloseCancel;
485   if ( answer == SUIT_MessageBox::Save )
486     res = CloseSave;
487   else if ( answer == SUIT_MessageBox::Discard )
488     res = CloseDiscard;
489
490   return res;
491 }
492
493 bool STD_Application::closeAction( const int choice, bool& closePermanently )
494 {
495   bool res = true;
496   switch( choice )
497   {
498   case CloseSave:
499     if ( activeStudy()->isSaved() )
500       onSaveDoc();
501     else if ( !onSaveAsDoc() )
502       res = false;
503     break;
504   case CloseDiscard:
505     break;
506   case CloseCancel:
507   default:
508     res = false;
509   }
510
511   return res;
512 }
513
514 int STD_Application::openChoice( const QString& aName )
515 {
516   SUIT_Session* aSession = SUIT_Session::session();
517
518   bool isAlreadyOpen = false;
519   QList<SUIT_Application*> aAppList = aSession->applications();
520   for ( QList<SUIT_Application*>::iterator it = aAppList.begin(); it != aAppList.end() && !isAlreadyOpen; ++it )
521     isAlreadyOpen = (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName;
522   return isAlreadyOpen ? OpenExist : OpenNew;
523 }
524
525 bool STD_Application::openAction( const int choice, const QString& aName )
526 {
527   bool res = true;
528   switch ( choice )
529   {
530   case OpenExist:
531     {
532       SUIT_Application* aApp = 0;
533       SUIT_Session* aSession = SUIT_Session::session();
534       QList<SUIT_Application*> aAppList = aSession->applications();
535       for ( QList<SUIT_Application*>::iterator it = aAppList.begin(); it != aAppList.end() && !aApp; ++it )
536       {
537         if ( (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName )
538           aApp = *it;
539       }
540       if ( aApp )
541         aApp->desktop()->activateWindow();
542       else
543         res = false;
544     }
545     break;
546   case OpenNew:
547     if ( !activeStudy() )
548       res = useFile( aName );
549     else
550     {
551       SUIT_Application* aApp = startApplication( 0, 0 );
552       if ( aApp )
553         res = aApp->useFile( aName );
554       if ( !res )
555         aApp->closeApplication();
556     }
557     break;
558   case OpenCancel:
559   default:
560     res = false;
561   }
562
563   return res;
564 }
565
566 /*!Save document if all ok, else error message.*/
567 void STD_Application::onSaveDoc()
568 {
569   if ( !activeStudy() )
570     return;
571
572   if ( !abortAllOperations() )
573     return;
574
575   bool isOk = false;
576   if ( activeStudy()->isSaved() )
577   {
578     putInfo( tr( "INF_DOC_SAVING" ) + activeStudy()->studyName() );
579
580     QApplication::setOverrideCursor( Qt::WaitCursor );
581
582     isOk = activeStudy()->saveDocument();
583
584     QApplication::restoreOverrideCursor();
585
586     if ( !isOk )
587     {
588       putInfo( "" );
589       // displaying a message box as SUIT_Validator in case file can't be written (the most frequent case)
590       SUIT_MessageBox::critical( desktop(), tr( "ERR_ERROR" ),
591                                  tr( "INF_DOC_SAVING_FAILS" ).arg( activeStudy()->studyName() ) );
592     }
593     else
594       putInfo( tr( "INF_DOC_SAVED" ).arg( "" ) );
595   }
596
597   if ( isOk )
598     studySaved( activeStudy() );
599   else
600     onSaveAsDoc();
601 }
602
603 /*! \retval \c true, if document saved successfully, else \c false.*/
604 bool STD_Application::onSaveAsDoc()
605 {
606   SUIT_Study* study = activeStudy();
607   if ( !study )
608     return false;
609
610   if ( !abortAllOperations() )
611     return false;
612
613   bool isOk = false;
614   while ( !isOk )
615   {
616     QString aName = getFileName( false, study->studyName(), getFileFilter( false ), QString(), 0 );
617     if ( aName.isNull() )
618       return false;
619
620     QApplication::setOverrideCursor( Qt::WaitCursor );
621
622     putInfo( tr( "INF_DOC_SAVING" ) + aName );
623     isOk = study->saveDocumentAs( aName );
624
625     putInfo( isOk ? tr( "INF_DOC_SAVED" ).arg( aName ) : "" );
626
627     QApplication::restoreOverrideCursor();
628
629     if ( !isOk )
630       SUIT_MessageBox::critical( desktop(), tr( "ERROR" ), tr( "INF_DOC_SAVING_FAILS" ).arg( aName ) );
631   }
632
633   studySaved( activeStudy() );
634
635   return isOk;
636 }
637
638 /*!Closing session.*/
639 void STD_Application::onExit()
640 {
641   int aAnswer = SUIT_MessageBox::Ok;
642   if ( exitConfirmation() )
643     aAnswer = SUIT_MessageBox::question( desktop(), tr( "INF_DESK_EXIT" ), tr( "QUE_DESK_EXIT" ),
644                                          SUIT_MessageBox::Ok | SUIT_MessageBox::Cancel, SUIT_MessageBox::Cancel );
645   if ( aAnswer == SUIT_MessageBox::Ok )
646     SUIT_Session::session()->closeSession();
647 }
648
649 /*!Virtual slot. Not implemented here.*/
650 void STD_Application::onCopy()
651 {
652 }
653
654 /*!Virtual slot. Not implemented here.*/
655 void STD_Application::onPaste()
656 {
657 }
658
659 /*!Sets \a theEnable for menu manager and for tool manager.*/
660 void STD_Application::setEditEnabled( bool theEnable )
661 {
662   myEditEnabled = theEnable;
663
664   QtxActionMenuMgr* mMgr = desktop()->menuMgr();
665   QtxActionToolMgr* tMgr = desktop()->toolMgr();
666
667   for ( int i = EditCopyId; i <= EditPasteId; i++ )
668   {
669     mMgr->setShown( mMgr->actionId(action(i)), myEditEnabled );
670     tMgr->setShown( tMgr->actionId(action(i)), myEditEnabled );
671   }
672 }
673
674 /*!\retval \c true, if document opened successfully, else \c false.*/
675 bool STD_Application::useFile(const QString& theFileName)
676 {
677   bool res = SUIT_Application::useFile( theFileName );
678
679   if ( res )
680     studyOpened( activeStudy() );
681
682   return res;
683 }
684
685 /*!Update desktop title.*/
686 void STD_Application::updateDesktopTitle()
687 {
688   QString aTitle = applicationName();
689   QString aVer = applicationVersion();
690   if ( !aVer.isEmpty() )
691     aTitle += QString( " " ) + aVer;
692
693   if ( activeStudy() )
694   {
695     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
696     if ( !sName.isEmpty() )
697       aTitle += QString( " - [%1]" ).arg( sName );
698   }
699
700   desktop()->setWindowTitle( aTitle );
701 }
702
703 /*!Update commands status.*/
704 void STD_Application::updateCommandsStatus()
705 {
706   SUIT_Application::updateCommandsStatus();
707
708   bool aHasStudy     = activeStudy() != 0;
709   bool aSaved        = aHasStudy && activeStudy()->isSaved();
710   bool aModified     = aHasStudy && activeStudy()->isModified();
711   bool aIsNeedToSave = aHasStudy && ( !aSaved || aModified );
712
713  if ( action( FileReopenId ) )
714     action( FileReopenId )->setEnabled( aSaved );
715  if ( action( FileSaveId ) )
716     action( FileSaveId )->setEnabled( aIsNeedToSave );
717   if ( action( FileSaveAsId ) )
718     action( FileSaveAsId )->setEnabled( aHasStudy );
719   if ( action( FileCloseId ) )
720     action( FileCloseId )->setEnabled( aHasStudy );
721   if ( action( NewWindowId ) )
722     action( NewWindowId )->setEnabled( aHasStudy );
723 }
724
725 /*!
726   \brief Show notification with specified text and title.
727   
728   Notification will be automatically hidden after specified \a timeout
729   (given in milliseconds). If \a timeout is zero, the notification
730   is not automatically hidden; it can be only closed by the user manually.
731   
732   \param text - Notification text
733   \param title - Notification title
734   \param timeout - Timeout in milliseconds
735   \return Notification's unique identifier
736 */
737 int STD_Application::showNotification(const QString& message, const QString& title, int timeout)
738 {
739   QtxNotify* ntfMgr = notifyMgr();
740   if (ntfMgr)
741   {
742     int delay = timeout;
743     if (delay < 0)
744     {
745       SUIT_ResourceMgr* aResMgr = resourceMgr();
746       if (aResMgr)
747         delay = aResMgr->integerValue("notification", "timeout", 0) * 1000;
748     }
749     ntfMgr->showNotification(message, title, qMax(delay, 0));
750   }
751 }
752
753 /*!
754   \brief Close notifications with specified text.
755   \param text - Notification text
756 */
757 void STD_Application::hideNotification(const QString& message)
758 {
759   QtxNotify* ntfMgr = notifyMgr();
760   if (ntfMgr)
761     ntfMgr->hideNotification(message);
762 }
763
764 /*!
765   \brief Closes the notifications with specified identifier.
766   \param id - Notification identifier
767 */
768 void STD_Application::hideNotification(int id)
769 {
770   QtxNotify* ntfMgr = notifyMgr();
771   if (ntfMgr)
772     ntfMgr->hideNotification(id);
773 }
774
775 /*!\retval SUIT_ViewManager by viewer manager type name.*/
776 SUIT_ViewManager* STD_Application::viewManager( const QString& vmType ) const
777 {
778   SUIT_ViewManager* vm = 0;
779   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end() && !vm; ++it )
780   {
781     if ( (*it)->getType() == vmType && !(*it)->getDetached())
782       vm = *it;
783   }
784   return vm;
785 }
786
787 /*! \param vmType - input view manager type name
788  * \param lst - output list of view managers with types \a vmType.
789  */
790 void STD_Application::viewManagers( const QString& vmType, ViewManagerList& lst ) const
791 {
792   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end(); ++it )
793   {
794     if ( (*it)->getType() == vmType )
795       lst.append( *it );
796   }
797 }
798
799 /*!\param lst - output list of all view managers.*/
800 void STD_Application::viewManagers( ViewManagerList& lst ) const
801 {
802   for ( QList<SUIT_ViewManager*>::const_iterator it = myViewMgrs.begin(); it != myViewMgrs.end(); ++it )
803     lst.append( *it );
804 }
805
806 /*!\retval ViewManagerList - const list of all view managers.*/
807 ViewManagerList STD_Application::viewManagers() const
808 {
809   ViewManagerList lst;
810   viewManagers( lst );
811   return lst;
812 }
813
814 /*!\retval SUIT_ViewManager - return pointer to active view manager.*/
815 SUIT_ViewManager* STD_Application::activeViewManager() const
816 {
817   return myActiveViewMgr;
818 }
819
820 /*!Add view manager to view managers list, if it not already there.*/
821 void STD_Application::addViewManager( SUIT_ViewManager* vm )
822 {
823   if ( !vm )
824     return;
825
826   if ( !containsViewManager( vm ) )
827   {
828     myViewMgrs.append( vm );
829     connect( vm, SIGNAL( activated( SUIT_ViewManager* ) ),
830              this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
831     vm->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
832
833     emit viewManagerAdded( vm );
834   }
835 /*
836   if ( !activeViewManager() && myViewMgrs.count() == 1 )
837     setActiveViewManager( vm );
838 */
839 }
840
841 /*!Remove view manager from view managers list.*/
842 void STD_Application::removeViewManager( SUIT_ViewManager* vm )
843 {
844   if ( !vm )
845     return;
846
847   vm->closeAllViews();
848
849   emit viewManagerRemoved( vm );
850
851   vm->disconnectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
852   disconnect( vm, SIGNAL( activated( SUIT_ViewManager* ) ),
853              this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
854   myViewMgrs.removeAll( vm );
855
856   if ( myActiveViewMgr == vm )
857     myActiveViewMgr = 0;
858 }
859
860 /*!Remove all view managers from view managers list.*/
861 void STD_Application::clearViewManagers()
862 {
863   ViewManagerList lst;
864   viewManagers( lst );
865
866   for ( QList<SUIT_ViewManager*>::iterator it = lst.begin(); it != lst.end(); ++it )
867   {
868     QPointer<SUIT_ViewManager> vm = *it;
869     removeViewManager( vm );
870     delete vm;
871   }
872 }
873
874 /*!\retval \c true, if view manager \a vm, already in view manager list (\a myViewMgrs).*/
875 bool STD_Application::containsViewManager( SUIT_ViewManager* vm ) const
876 {
877   return myViewMgrs.contains( vm );
878 }
879
880 /*!Private slot, sets active manager to \vm, if \vm in view managers list.*/
881 void STD_Application::onViewManagerActivated( SUIT_ViewManager* vm )
882 {
883   setActiveViewManager( vm );
884 }
885
886 /*!Shows status bar, if on is \c true, else hides status bar.*/
887 void STD_Application::onViewStatusBar( bool on )
888 {
889   if ( on )
890     desktop()->statusBar()->show();
891   else
892     desktop()->statusBar()->hide();
893 }
894
895 /*!Call SUIT_MessageBox::info1(...) with about information.*/
896 void STD_Application::onHelpAbout()
897 {
898   SUIT_MessageBox::information( desktop(), tr( "About" ), tr( "ABOUT_INFO" ) );
899 }
900
901 /*!Create empty study. \n
902  * Create new view manager and adding it to view managers list.
903  */
904 void STD_Application::createEmptyStudy()
905 {
906   SUIT_Application::createEmptyStudy();
907 }
908
909 /*!Sets active manager to \vm, if \vm in view managers list.*/
910 void STD_Application::setActiveViewManager( SUIT_ViewManager* vm )
911 {
912   if ( !containsViewManager( vm ) )
913     return;
914
915   myActiveViewMgr = vm;
916   emit viewManagerActivated( vm );
917 }
918
919 /*!Public slot. */
920 void STD_Application::onConnectPopupRequest( SUIT_PopupClient* client, QContextMenuEvent* e )
921 {
922   QtxMenu* popup = new QtxMenu();
923   // fill popup by own items
924   QString title;
925   contextMenuPopup( client->popupClientType(), popup, title );
926   popup->setTitleText( title );
927
928   popup->addSeparator();
929   // add items from popup client
930   client->contextMenuPopup( popup );
931
932   SUIT_Tools::simplifySeparators( popup );
933
934   if ( !popup->actions().isEmpty() )
935     popup->exec( e->globalPos() );
936   delete popup;
937 }
938
939 /*!\retval QString - return file extension(s).*/
940 QString STD_Application::getFileFilter( bool /*open*/ ) const
941 {
942   return QString();
943 }
944
945 /*!\retval QString - return file name from dialog.*/
946 QString STD_Application::getFileName( bool open, const QString& initial, const QString& filters,
947                                       const QString& caption, QWidget* parent )
948 {
949   if ( !parent )
950     parent = desktop();
951   if ( open )
952     return QFileDialog::getOpenFileName( parent, caption, initial, filters );
953   else
954   {
955     QString aName;
956     QString aUsedFilter;
957     QString anOldPath = initial;
958
959     bool isOk = false;
960     while ( !isOk )
961     {
962       // It is preferrable to use OS-specific file dialog box here !!!
963       aName = QFileDialog::getSaveFileName( parent, caption, anOldPath, filters, &aUsedFilter );
964
965       if ( aName.isNull() )
966         isOk = true;
967       else
968       {
969         int aEnd = aUsedFilter.lastIndexOf( ')' );
970         int aStart = aUsedFilter.lastIndexOf( '(', aEnd );
971         QString wcStr = aUsedFilter.mid( aStart + 1, aEnd - aStart - 1 );
972
973         int idx = 0;
974         QStringList extList;
975         QRegExp rx( "[\b\\*]*\\.([\\w]+)" );
976         while ( ( idx = rx.indexIn( wcStr, idx ) ) != -1 )
977         {
978           extList.append( rx.cap( 1 ) );
979           idx += rx.matchedLength();
980         }
981
982         if ( !extList.isEmpty() && !extList.contains( SUIT_Tools::extension( aName ) ) )
983           aName += QString( ".%1" ).arg( extList.first() );
984
985         if ( QFileInfo( aName ).exists() )
986         {
987           int aAnswer = SUIT_MessageBox::question( desktop(), tr( "TIT_FILE_SAVEAS" ),
988                                                    tr( "MSG_FILE_EXISTS" ).arg( aName ),
989                                                    SUIT_MessageBox::Yes | SUIT_MessageBox::No | SUIT_MessageBox::Cancel, SUIT_MessageBox::Yes );
990           if ( aAnswer == SUIT_MessageBox::Cancel )
991           {     // cancelled
992             aName = QString();
993             isOk = true;
994           }
995           else if ( aAnswer == SUIT_MessageBox::No ) // not save to this file
996             anOldPath = aName;             // not to return to the same initial dir at each "while" step
997           else                     // overwrite the existing file
998             isOk = true;
999         }
1000         else
1001           isOk = true;
1002       }
1003     }
1004     return aName;
1005   }
1006 }
1007
1008 /*!\retval QString - return directory name from dialog.*/
1009 QString STD_Application::getDirectory( const QString& initial, const QString& caption, QWidget* parent )
1010 {
1011   if ( !parent )
1012     parent = desktop();
1013
1014   return QFileDialog::getExistingDirectory( parent, caption, initial );
1015 }
1016
1017 /*!
1018   Changes desktop
1019   \param desk - new desktop
1020 */
1021 void STD_Application::setDesktop( SUIT_Desktop* desk )
1022 {
1023   SUIT_Application::setDesktop( desk );
1024
1025   if ( desk ) {
1026     connect( desk, SIGNAL( closing( SUIT_Desktop*, QCloseEvent* ) ),
1027              this, SLOT( onDesktopClosing( SUIT_Desktop*, QCloseEvent* ) ), Qt::UniqueConnection );
1028   }
1029 }
1030
1031 /*!
1032   Allow to load preferences before the desktop will be shown.
1033 */
1034 void STD_Application::loadPreferences()
1035 {
1036 }
1037
1038 /*!
1039   Allow to save preferences before the application will be closed.
1040 */
1041 void STD_Application::savePreferences()
1042 {
1043 }
1044
1045 /*!
1046   Custom activity after study is created
1047   Updates desktop and actions
1048 */
1049 void STD_Application::studyCreated( SUIT_Study* )
1050 {
1051   updateDesktopTitle();
1052   updateCommandsStatus();
1053 }
1054
1055 /*!
1056   Custom activity after study is opened
1057   Updates desktop and actions
1058 */
1059 void STD_Application::studyOpened( SUIT_Study* )
1060 {
1061   updateDesktopTitle();
1062   updateCommandsStatus();
1063 }
1064
1065 /*!
1066   Custom activity after study is opened
1067   Updates desktop and actions
1068 */
1069 void STD_Application::studySaved( SUIT_Study* )
1070 {
1071   updateDesktopTitle();
1072   updateCommandsStatus();
1073 }
1074
1075 /*!
1076   Return index of the view ma
1077 */
1078 int STD_Application::viewManagerId( const SUIT_ViewManager* theManager) const
1079 {
1080   return myViewMgrs.indexOf(const_cast<SUIT_ViewManager*>(theManager));
1081 }
1082
1083 /*!
1084   \brief Abort active operations if there are any
1085   \return \c false if some operation cannot be aborted
1086 */
1087 bool STD_Application::abortAllOperations()
1088 {
1089   return true;
1090 }
1091
1092 /*!
1093   \brief Gets the notification manager. Creates it if not exists.
1094   \return \c notification manager instance
1095 */
1096 QtxNotify* STD_Application::notifyMgr()
1097 {
1098   if ( !myNotify )
1099   {
1100     myNotify = new QtxNotify(desktop());
1101     myNotify->setWindow(desktop());
1102
1103     SUIT_ResourceMgr* aResMgr = resourceMgr();
1104     if (aResMgr)
1105     {
1106       int anim = aResMgr->integerValue("notification", "animation", 0);
1107       myNotify->setAnimationTime(anim);
1108
1109       double size = aResMgr->integerValue("notification", "size", 250);
1110       myNotify->setNotificationSize(size);
1111     }
1112   }
1113   return myNotify;
1114 }