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