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