Salome HOME
This commit was generated by cvs2git to create tag 'V1_4_0b1'.
[modules/kernel.git] / src / SALOMEGUI / QAD_Application.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : QAD_Application.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SALOME
27 //  $Header$
28
29 using namespace std;
30 /*!
31   \class QAD_Application QAD_Application.h
32   \brief Study manager for QAD-based application.
33 */
34
35 #include "QAD.h"
36 #include "QAD_Tools.h"
37 #include "QAD_Desktop.h"
38 #include "QAD_Application.h"
39 #include "QAD_MessageBox.h"
40 #include "QAD_Config.h"
41 #include "SALOMEGUI_AboutDlg.h"
42 #include "SALOME_Selection.h"
43
44 #include <SALOMEconfig.h>
45 #include CORBA_CLIENT_HEADER(SALOME_Exception)
46
47 // QT Includes
48 #include <qapplication.h>
49 #include <qtranslator.h>
50 #include <qpopupmenu.h>
51 #include <qstatusbar.h>
52 #include <qmenubar.h>
53 #include <qtoolbar.h>
54 #include <qdialog.h>
55 #include <qstring.h>
56 #include <qpixmap.h>
57 #include <qfile.h>
58 #include <qfileinfo.h>
59 #include <qmessagebox.h> 
60
61 // Open CASCADE Includes
62 #include <TCollection_AsciiString.hxx>
63 #include <TCollection_ExtendedString.hxx>
64 #include <Standard_Failure.hxx>
65
66 static bool checkPermission(QString fileName) {
67   if ( QFile::exists( fileName ) ) {
68     // if file exists - check it for writeability
69     if ( !QFileInfo( fileName ).isWritable() ) {
70       return false; 
71     }
72   }
73   else {
74     // if file doesn't exist - try to create it
75     QFile qf( fileName );
76     if ( !qf.open( IO_WriteOnly ) ) {
77       return false;
78     }
79     else {
80       qf.close();
81       qf.remove();
82     }
83   }
84   return true;
85 }
86
87 QAD_Desktop* QAD_Application::desktop = 0;
88
89 /*!
90     Registers a new application object and
91     adds it to the desktop [ static ]   
92 */
93 bool QAD_Application::addToDesktop( QAD_Application* app, SALOME_NamingService* name_service )
94 {
95     /* create CAF application */ 
96     if ( !app->initApp(name_service) )
97        return false;
98   
99     /* create the only desktop */
100     if ( !app->getDesktop() ) 
101     {
102         app->createDesktop(name_service); 
103         emit app->desktopCreated(); 
104     }
105
106     /* add application to the desktop */
107     desktop->addApplication( app );
108     return true;
109 }
110
111 /*! 
112     Runs the application [ static ]
113 */
114 void QAD_Application::run()
115 {
116     /* at least one application must be on desktop */
117     QAD_ASSERT_DEBUG_ONLY ( desktop );
118     desktop->showDesktop();
119 }
120
121
122 /*!
123     Returns reference to main desktop [ static ]
124 */
125 QAD_Desktop* QAD_Application::getDesktop()
126 {
127   return desktop;
128 }
129
130 /*!
131     Returns standard Palette [ static ]
132 */
133 QPalette QAD_Application::getPalette(bool alternative)
134 {
135 /*  $$$ ---> commented 20.09.2002 - application uses global palette but little changed if <alternative> is true
136     QPalette pal;
137     QColorGroup cg;
138     cg.setColor( QColorGroup::Foreground, Qt::black );
139     cg.setColor( QColorGroup::Button, QColor( 192, 192, 192) );
140     cg.setColor( QColorGroup::Light, Qt::white );
141     cg.setColor( QColorGroup::Midlight, QColor( 223, 223, 223) );
142     cg.setColor( QColorGroup::Dark, QColor( 96, 96, 96) );
143     cg.setColor( QColorGroup::Mid, QColor( 128, 128, 128) );
144     cg.setColor( QColorGroup::Text, Qt::black );
145     cg.setColor( QColorGroup::BrightText, Qt::white );
146     cg.setColor( QColorGroup::ButtonText, Qt::black );
147     cg.setColor( QColorGroup::Base, QColor( 255,255,220 )  ); 
148     cg.setColor( QColorGroup::Background, QColor( 192, 192, 192) );
149     cg.setColor( QColorGroup::Shadow, Qt::black );
150     cg.setColor( QColorGroup::Highlight, QColor( 0, 0, 128) );
151     cg.setColor( QColorGroup::HighlightedText, Qt::white );
152     pal.setActive( cg );
153     cg.setColor( QColorGroup::Foreground, Qt::black );
154     cg.setColor( QColorGroup::Button, QColor( 192, 192, 192) );
155     cg.setColor( QColorGroup::Light, Qt::white );
156     cg.setColor( QColorGroup::Midlight, QColor( 220, 220, 220) );
157     cg.setColor( QColorGroup::Dark, QColor( 96, 96, 96) );
158     cg.setColor( QColorGroup::Mid, QColor( 128, 128, 128) );
159     cg.setColor( QColorGroup::Text, Qt::black );
160     cg.setColor( QColorGroup::BrightText, Qt::white );
161     cg.setColor( QColorGroup::ButtonText, Qt::black );
162     cg.setColor( QColorGroup::Base, QColor( 255,255,220 ) );
163     cg.setColor( QColorGroup::Background, QColor( 192, 192, 192) );
164     cg.setColor( QColorGroup::Shadow, Qt::black );
165     cg.setColor( QColorGroup::Highlight, QColor( 0, 0, 128) );
166     cg.setColor( QColorGroup::HighlightedText, Qt::white );
167     pal.setInactive( cg );
168     cg.setColor( QColorGroup::Foreground, QColor( 128, 128, 128) );
169     cg.setColor( QColorGroup::Button, QColor( 192, 192, 192) );
170     cg.setColor( QColorGroup::Light, Qt::white );
171     cg.setColor( QColorGroup::Midlight, QColor( 220, 220, 220) );
172     cg.setColor( QColorGroup::Dark, QColor( 96, 96, 96) );
173     cg.setColor( QColorGroup::Mid, QColor( 128, 128, 128) );
174     cg.setColor( QColorGroup::Text, Qt::black );
175     cg.setColor( QColorGroup::BrightText, Qt::white );
176     cg.setColor( QColorGroup::ButtonText, QColor( 128, 128, 128) );
177     cg.setColor( QColorGroup::Base, QColor( 255,255,220 ) );
178     cg.setColor( QColorGroup::Background, QColor( 192, 192, 192) );
179     cg.setColor( QColorGroup::Shadow, Qt::black );
180     cg.setColor( QColorGroup::Highlight, QColor( 0, 0, 128) );
181     cg.setColor( QColorGroup::HighlightedText, Qt::white );
182     pal.setDisabled( cg );
183  $$$ <--------------------------------------------------------------------- */
184   QPalette pal = QApplication::palette();
185   // $$$ --> this prevents qt bug - bag child window's icon drawing (not transparent)
186   // when it is maximized
187   pal.setColor(QPalette::Active,   QColorGroup::Background, pal.active().button());
188   pal.setColor(QPalette::Inactive, QColorGroup::Background, pal.inactive().button());
189   pal.setColor(QPalette::Disabled, QColorGroup::Background, pal.disabled().button());
190   // $$$ <---
191   if (alternative) {
192     // alternative palette is used for Object Browser, PyEditor, Message and Help windows
193     QColorGroup cg = pal.active();
194     cg.setColor( QColorGroup::Highlight, QColor( 0, 0, 128) );
195     cg.setColor( QColorGroup::HighlightedText, Qt::white );
196     cg.setColor( QColorGroup::Base, QColor( 255,255,220 )  ); 
197     cg.setColor( QColorGroup::Text, Qt::black );
198     pal.setActive  ( cg );
199     cg = pal.inactive();
200     cg.setColor( QColorGroup::Highlight, QColor( 0, 0, 128) );
201     cg.setColor( QColorGroup::HighlightedText, Qt::white );
202     cg.setColor( QColorGroup::Base, QColor( 255,255,220 )  ); 
203     cg.setColor( QColorGroup::Text, Qt::black );
204     pal.setInactive( cg );
205     cg = pal.disabled();
206     cg.setColor( QColorGroup::Highlight, QColor( 0, 0, 128) );
207     cg.setColor( QColorGroup::HighlightedText, Qt::white );
208     cg.setColor( QColorGroup::Base, QColor( 255,255,220 )  ); 
209     cg.setColor( QColorGroup::Text, Qt::black );
210     pal.setDisabled( cg );
211   }
212   return pal; 
213 }
214
215 /*!
216     Constructor
217 */
218 QAD_Application::QAD_Application( const QString& format, const QString& description, 
219                                   const QString& extension ) :
220 myActiveStudy( 0 ),
221 myStudyFormat( format ),
222 myStudyExtension( extension ),
223 myStudyDescription( description )
224 {        
225   /* actions are stored in vectors only */
226   
227   /* studies are managed by me */
228   myStudies.setAutoDelete( true );   
229   
230   /* load resources for all QAD */
231   QAD_ResourceMgr* resMgr = QAD_Desktop::getResourceManager();
232   if ( !resMgr ) resMgr = QAD_Desktop::createResourceManager();
233   QString message;
234   resMgr->loadResources( "QAD", message );    
235   resMgr->loadResources( "CLIENT", message );    
236   
237   /* set default icon */
238   myIcon = resMgr->loadPixmap( "CLIENT", tr("ICON_APP_DEFAULTICON") );
239   myName = tr("APP_DEFAULTTITLE");        
240   
241   /*  We need to know that desktop is created in order
242       to have some additional internal initialization */
243   QAD_ASSERT( connect( this, SIGNAL(desktopCreated()), this, 
244                        SLOT(onDesktopCreated()) ));
245 }   
246
247 /*!
248     Destructor
249 */
250 QAD_Application::~QAD_Application ()
251 {
252   myEditActions.clear();
253   myViewActions.clear();
254   myHelpActions.clear();        
255   QMap<int, QToolBar*>::Iterator it;
256   for ( it = myToolBars.begin(); it != myToolBars.end(); it++ ) {
257     delete it.data();
258   }
259   myToolBars.clear();
260 }
261
262 /*!
263     Creates the main desktop( called once )
264 */
265 bool QAD_Application::createDesktop( SALOME_NamingService* name_service )
266 {    
267     QAD_ASSERT_DEBUG_ONLY( !desktop );
268     desktop = new QAD_Desktop ( name_service ); 
269     return ( desktop != NULL );
270 }
271
272 /*!
273     Creates the actions provided by this application 
274     ( internal )
275 */
276 void QAD_Application::createActions()
277 {
278   /*  Basic application provides only Undo/Redo 
279       functionalities which is disabled by default.
280       All others must be added by subclasses. 
281   */  
282   QAD_ResourceMgr* rmgr = QAD_Desktop::getResourceManager();
283   // Undo
284   if ( !myEditActions.at( EditUndoId ) )
285     {        
286       QActionP* editUndo = new QActionP( tr("TOT_APP_EDIT_UNDO"), 
287                                         rmgr->loadPixmap( "QAD",
288                                                           tr("ICON_APP_EDIT_UNDO") ), 
289                                         tr("MEN_APP_EDIT_UNDO"),
290                                         CTRL+Key_Z, desktop );
291       editUndo->setStatusTip ( tr("PRP_APP_EDIT_UNDO") );
292       QAD_ASSERT ( connect( editUndo, SIGNAL( activated() ), this, SLOT( onUndo() )));
293       myEditActions.insert( EditUndoId, editUndo );        
294     }
295   // Redo
296   if ( !myEditActions.at( EditRedoId ) )
297     {               
298       QActionP* editRedo = new QActionP ( tr("TOT_APP_EDIT_REDO"), 
299                                         rmgr->loadPixmap( "QAD",  tr("ICON_APP_EDIT_REDO") ), 
300                                         tr("MEN_APP_EDIT_REDO"), CTRL+Key_Y, desktop );
301       editRedo->setStatusTip ( tr("PRP_APP_EDIT_REDO") );
302       QAD_ASSERT ( connect( editRedo, SIGNAL( activated() ), this, SLOT( onRedo() )));
303       myEditActions.insert( EditRedoId, editRedo );        
304     }
305   // Copy
306   if ( !myEditActions.at( EditCopyId ) )
307     {        
308       QActionP* editCopy = new QActionP ( tr("TOT_APP_EDIT_COPY"), 
309                                         rmgr->loadPixmap( "QAD",
310                                                           tr("ICON_APP_EDIT_COPY") ), 
311                                         tr("MEN_APP_EDIT_COPY"),
312                                         CTRL+Key_C, desktop );
313       editCopy->setStatusTip ( tr("PRP_APP_EDIT_COPY") );
314       QAD_ASSERT ( connect( editCopy, SIGNAL( activated() ), this, SLOT( onCopy() )));
315       myEditActions.insert( EditCopyId, editCopy );        
316     }
317   // Paste
318   if ( !myEditActions.at( EditPasteId ) )
319     {        
320       QActionP* editPaste = new QActionP ( tr("TOT_APP_EDIT_PASTE"), 
321                                         rmgr->loadPixmap( "QAD",
322                                                           tr("ICON_APP_EDIT_PASTE") ), 
323                                         tr("MEN_APP_EDIT_PASTE"),
324                                         CTRL+Key_V, desktop );
325       editPaste->setStatusTip ( tr("PRP_APP_EDIT_PASTE") );
326       QAD_ASSERT ( connect( editPaste, SIGNAL( activated() ), this, SLOT( onPaste() )));
327       myEditActions.insert( EditPasteId, editPaste );        
328     }
329   // Update action state
330   updateActions();
331 }
332
333 /*!
334     Enables/disables the actions according to the
335     application state
336 */
337 void QAD_Application::updateActions()
338 {  
339   QAD_ASSERT_DEBUG_ONLY( !myEditActions.isEmpty() );        
340   if ( myActiveStudy ) {        
341     myEditActions.at( EditUndoId )->setEnabled( myActiveStudy->canUndo() );
342     myEditActions.at( EditRedoId )->setEnabled( myActiveStudy->canRedo() );
343     myEditActions.at( EditCopyId )->setEnabled( canCopy() );
344     myEditActions.at( EditPasteId )->setEnabled( canPaste() );
345   }    
346   else {
347     myEditActions.at( EditUndoId )->setEnabled( false );
348     myEditActions.at( EditRedoId )->setEnabled( false );
349     myEditActions.at( EditCopyId )->setEnabled( false );
350     myEditActions.at( EditPasteId )->setEnabled( false );
351   }
352 }
353
354 /*!
355     Returns the aplication name
356 */
357 const QString& QAD_Application::getApplicationName() const
358 {
359   return myName;
360 }
361
362 /*! 
363     Returns the application icon   
364 */
365 const QPixmap& QAD_Application::getApplicationIcon() const
366 {
367   return myIcon;
368 }
369
370 /*!
371     Returns the study description
372 */
373 const QString&  QAD_Application::getStudyDescription() const
374 {
375   return myStudyDescription;
376 }
377
378 /*!
379     Returns the CAF study format
380 */
381 const QString& QAD_Application::getStudyFormat() const
382 {
383   return myStudyFormat;
384 }
385
386 /*!
387     Returns the extension of supported type of files
388 */
389 const QString& QAD_Application::getStudyExtension() const
390 {
391   return myStudyExtension;
392 }
393
394 /*! 
395     Returns 'true' if study is opened
396 */
397 bool QAD_Application::isStudyOpened( const QString& studyName )
398 {
399   QString Name = QAD_Tools::getFileNameFromPath( studyName, true );
400   return (( getStudyByName( studyName ) != NULL ) || (getStudyByName( Name ) != NULL )); 
401 }
402
403 /*! 
404     Returns the study object by its name
405 */
406 QAD_Study* QAD_Application::getStudyByName( const QString& studyname )
407 {
408   for ( QAD_Study* study = myStudies.first(); study; study = myStudies.next() )
409     {
410       if ( (studyname.compare( study->getPath() ) == 0 ) ||  
411            (studyname.compare( study->getTitle() ) == 0 ))
412         return study;
413     }
414   return NULL;
415 }
416
417 /*!
418     Returns vector of all opened studies
419 */
420 QList<QAD_Study>& QAD_Application::getStudies() 
421 {
422   return myStudies;
423 }
424
425 /*!
426     Adds the study to the list of opened studies
427     and set listeners for the study signals.    
428 */
429 void QAD_Application::addStudy( QAD_Study* study )
430 {
431   if ( !study ) return;
432   
433   QAD_ASSERT( connect(study,SIGNAL(docClosing(QAD_Study*)),desktop,
434                       SLOT(onCloseStudy(QAD_Study*))) );    
435   myStudies.append( study );
436 }
437
438 /*!
439     Removes the study from the list of opened studies
440 */
441 void QAD_Application::removeStudy( QAD_Study* study )
442 {
443   if ( study ) 
444     {
445       /* close and destroy */        
446       if ( study == myActiveStudy )
447         myActiveStudy = 0; 
448       myStudies.removeRef( study );
449     }
450 }
451
452 /*!
453     Activates 'About' dialog
454 */
455 void QAD_Application::helpAbout()
456 {
457   /* just calls QAD_Desktop::helpAbout() but can have own implementation */
458   getDesktop()->helpAbout();
459 }
460
461 /*!
462     Activates search in help 
463 */
464 void QAD_Application::helpSearch()
465 {
466   /* just calls QAD_Desktop::helpSearch() but can have own implementation */
467 //  getDesktop()->helpSearch();
468 }
469
470 /*!
471     Activates help contents
472 */
473 void QAD_Application::helpContents()
474 {
475   /* just calls QAD_Desktop::helpContents() but can have own implementation */
476 //  getDesktop()->helpContents();
477 }
478
479 /*!
480     Customizes menu "File" for the active application
481 */
482 void QAD_Application::updateFilePopup( QPopupMenu* menu, bool add, int index )
483 {    
484   if ( !menu ) return;
485   
486 #ifdef DEBUG
487   /*  ensure that 'add' command is followed by 'remove' */        
488   static bool isAdded = false;            
489   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );     
490   isAdded = add;
491 #endif
492   onUpdateFileActions( menu, add, index );
493 }
494
495 /*!
496     Customizes menu "Edit" for the active application
497 */
498 void QAD_Application::updateEditPopup( QPopupMenu* menu, bool add, int index  )
499 {
500   if ( !menu ) return;
501   
502 #ifdef DEBUG
503   /*  ensure that 'add' command is followed by 'remove' */        
504   static bool isAdded = false;            
505   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );     
506   isAdded = add;
507 #endif
508   onUpdateEditActions( menu, add, index );
509 }
510
511 /*!
512     Customizes menu "View" for the active application
513 */
514 void QAD_Application::updateViewPopup( QPopupMenu* menu, bool add, int index  )
515 {
516   if ( !menu ) return;
517   
518 #ifdef DEBUG
519   /*  ensure that 'add' command is followed by 'remove' */        
520   static bool isAdded = false;            
521   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );     
522   isAdded = add;
523 #endif
524   onUpdateViewActions( menu, add, index ); 
525 }
526
527 /*!
528     Customizes menu "Help" for the active application
529 */
530 void QAD_Application::updateHelpPopup( QPopupMenu* menu, bool add, int index )
531 {
532   if ( !menu ) return;
533 #ifdef DEBUG
534   /*  ensure that 'add' command is followed by 'remove' */        
535   static bool isAdded = false;            
536   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );         
537   isAdded = add;
538 #endif
539   onUpdateHelpActions ( menu, add, index ); 
540 }
541
542 /*!
543   Customizes the main menu bar to add some new popup, 
544   'Options' or 'Tools' for example.
545 */
546 void QAD_Application::updateMainMenu( QMenuBar* menubar, bool add, int index )
547 {
548   if ( !menubar ) return;
549 #ifdef DEBUG
550   /*  ensure that 'add' command is followed by 'remove' */        
551   static bool isAdded = false;            
552   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );         
553   isAdded = add;
554 #endif
555   onUpdateMainMenuItems ( menubar, add, index ); 
556 }
557
558 /*!
559     Adds specific application buttons for standard toolbar
560 */
561 void QAD_Application::updateToolBars( bool add )
562 {    
563 #ifdef DEBUG
564   /*  ensure that 'add' command is followed by 'remove' */        
565   static bool isAdded = false;            
566   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );         
567   isAdded = add;
568 #endif
569   onUpdateToolBars ( add ); 
570 }
571
572 /*!
573     Customizes the status bar
574 */
575 void QAD_Application::updateStatusBar( QStatusBar* statusBar, bool add ) 
576 {
577 #ifdef DEBUG
578   /*  ensure that 'add' command is followed by 'remove' */        
579   static bool isAdded = false;            
580   QAD_ASSERT_DEBUG_ONLY ( (add && !isAdded) || (!add && isAdded) );         
581   isAdded = add;
582 #endif
583   onUpdateStatusBar( statusBar, add );
584 }
585
586 /*!
587   Creates toolbar to be managed by QAD_Application
588 */
589 QToolBar* QAD_Application::createToolBar( int   id,
590                                           const QString& label, Dock dock, 
591                                           bool  dockTop,        bool dockBottom, 
592                                           bool  dockLeft,       bool dockRight, 
593                                           bool  dockMinimized,  bool dockTornOff )
594 {
595   QToolBar* tb = 0;
596   if ( getDesktop() ) {
597     tb = new QToolBar( label, getDesktop(), 0 );
598     tb->setCloseMode( QDockWindow::Undocked );
599     getDesktop()->setDockEnabled( tb, DockTop,       dockTop );
600     getDesktop()->setDockEnabled( tb, DockBottom,    dockBottom );
601     getDesktop()->setDockEnabled( tb, DockLeft,      dockLeft );
602     getDesktop()->setDockEnabled( tb, DockRight,     dockRight );
603     getDesktop()->setDockEnabled( tb, DockMinimized, dockMinimized );
604     getDesktop()->setDockEnabled( tb, DockTornOff,   dockTornOff );
605     getDesktop()->addDockWindow( tb, label, dock );
606     getDesktop()->setAppropriate( tb, false );
607     tb->hide();
608     removeToolBar( id );
609     myToolBars.insert( id, tb);
610   }
611   return tb;
612 }
613
614 /*!
615   Removes toolbar
616 */
617 void QAD_Application::removeToolBar( int id )
618 {
619   QToolBar* tb = myToolBars[ id ];
620   if ( tb ) {
621     myToolBars.remove( id );
622     getDesktop()->removeDockWindow( tb );
623     delete tb;
624   }
625 }
626
627 /*!
628   Gets toolbar by id
629 */
630 QToolBar* QAD_Application::getToolBar( int id )
631 {
632   return myToolBars[ id ];
633 }
634
635 /*!
636   Gets all toolbars managed by QAD_Applica
637 */
638 QList<QToolBar> QAD_Application::getToolBars()
639 {
640   QList<QToolBar> toolbars;
641   QMap<int, QToolBar*>::Iterator it;
642   for ( it = myToolBars.begin(); it != myToolBars.end(); it++ )
643     toolbars.append( it.data() );
644   return toolbars;
645 }
646
647 /*!
648     Called by 'updateMainMenu' when application is activated/deactivated.
649     Redefine to insert/remove the actions provided by the application
650     to the main menu at 'index'.
651     Returns the number of added/removed items.
652 */
653 int QAD_Application::onUpdateMainMenuItems ( QMenuBar* mb, bool add, int index )
654 {
655     return 0;
656 }
657
658 /*!
659     Called by 'updateFilePopup' when application is activated/deactivated.
660     Redefine to insert/remove the actions provided by the application to
661     'File' menu of the desktop at 'index'.
662     Returns the number of added/removed items.
663 */
664 int QAD_Application::onUpdateFileActions ( QPopupMenu* popup, bool add, int index )
665 {
666     return 0;
667 }
668
669 /*!
670     Called by 'updateEditPopup' when application is activated/deactivated.
671     Redefine to insert/remove the actions provided by the application to
672     'Edit' menu of the desktop at 'index'.
673     Returns the number of added/removed items.
674 */
675 int QAD_Application::onUpdateEditActions ( QPopupMenu* popup, bool add, int index )
676 {
677     QAD_ASSERT_DEBUG_ONLY( !myEditActions.isEmpty() );
678     QToolBar* tb = getDesktop()->getStdToolBar();
679     QActionP* undo  = myEditActions.at( EditUndoId );
680     QActionP* redo  = myEditActions.at( EditRedoId );
681     QActionP* copy  = myEditActions.at( EditCopyId );
682     QActionP* paste = myEditActions.at( EditPasteId );
683     if ( add ) 
684     {         
685       undo->addTo( popup );     
686       index++;
687       redo->addTo( popup );        
688       index++;
689       copy->addTo( popup );        
690       index++;
691       paste->addTo( popup );        
692       index++;
693       undo->addTo( tb );
694       redo->addTo( tb );
695       copy->addTo( tb );
696       paste->addTo( tb );
697     }
698     else
699     {
700       popup->removeItemAt(index);
701       popup->removeItemAt(index);
702       popup->removeItemAt(index);
703       popup->removeItemAt(index);
704
705       undo->removeFrom( tb );
706       redo->removeFrom( tb );
707       copy->removeFrom( tb );
708       paste->removeFrom( tb );
709     }
710     return index;
711 }
712
713 /*!
714     Called by 'updateViewPopup' when application is activated/deactivated.
715     Redefine to insert/remove the actions provided by the application to the
716     'View' menu of the desktop at 'index'.
717     Returns the number of added/removed items.
718 */
719 int QAD_Application::onUpdateViewActions ( QPopupMenu* popup, bool add, int index )
720 {
721     return 0;
722 }
723
724 /*!
725     Called by 'updateHelpPopup' when application is activated/deactivated.
726     Redefine to insert/remove the actions provided by the application
727     to 'Help' menu of the desktop at 'index'.
728     Returns the number of added/removed items.
729 */
730 int QAD_Application::onUpdateHelpActions ( QPopupMenu* popup, bool add, int index )
731 {
732     return 0;
733 }
734
735 /*!
736     Called by 'updateStatusBar' when application is activated/deactivated.
737     Redefine to customize status bar.
738 */
739 void QAD_Application::onUpdateStatusBar( QStatusBar* sb, bool activate )
740 {
741 }
742
743 /*!
744     Called by 'updateToolBars' when application is activated/deactivated.
745     Redefine to show your specific toolbars on the desktop.
746 */
747 void QAD_Application::onUpdateToolBars( bool activate )
748 {
749   QMap<int, QToolBar*>::Iterator it;
750   for ( it = myToolBars.begin(); it != myToolBars.end(); it++ ) {
751     activate ? it.data()->show() : it.data()->hide();
752     getDesktop()->setAppropriate( it.data(), activate );
753   }
754 }
755
756 //=======================================================================//
757 //                          Study management                             //
758 //=======================================================================//
759 /*!
760     Returns the active study
761 */
762 QAD_Study* QAD_Application::getActiveStudy() const
763 {
764     return myActiveStudy;
765 }
766
767 //=======================================================================//
768 //                          Operation management                         //
769 //=======================================================================//
770 /*!
771     Runs a new operation of class appointed
772 */
773 void QAD_Application::startOperation( QAD_Operation* op )
774 {
775     if ( op ) op->start();
776 }
777
778
779 //=======================================================================//
780 //                          Study management                             //
781 //=======================================================================//
782 /*!
783     Creates new study
784 */
785 QAD_Study* QAD_Application::newStudy()
786 {       
787   QAD_Study* newStudy = 0;
788   QAD_ASSERT_DEBUG_ONLY( !myStudyMgr->_is_nil() );
789   QApplication::setOverrideCursor( Qt::waitCursor );
790   try {
791     /* create QAD study*/
792     QString StudyName = getDesktop()->getNewStudyName();
793
794     CORBA::Object_var obj = getDesktop()->getNameService()->Resolve("/myStudyManager");
795     SALOMEDS::StudyManager_var myStudyMgr = SALOMEDS::StudyManager::_narrow(obj);
796     ASSERT(! CORBA::is_nil(myStudyMgr));
797     SALOMEDS::ListOfOpenStudies_var List = myStudyMgr->GetOpenStudies();
798     
799     bool exist = true;
800     
801     while ( exist ) {
802       exist = false;
803       for (unsigned int ind = 0; ind < List->length();ind++) {
804         QString NameS = QAD_Tools::getFileNameFromPath( QString( List[ind] ), true );
805         if ( NameS.compare( StudyName ) == 0 ) {
806           StudyName = getDesktop()->getNewStudyName();
807           exist = true;
808           break;
809         }
810       }
811     }
812     
813     if (getStudyByName ( StudyName ) != NULL )
814       {
815         /* create StudyDS */
816         SALOMEDS::Study_var aStudy = myStudyMgr->NewStudy(getDesktop()->getNewStudyName());
817         newStudy = new QAD_Study( this, aStudy, getDesktop()->getNewStudyName());
818       }
819     else 
820       {
821         /* create StudyDS */
822         SALOMEDS::Study_var aStudy = myStudyMgr->NewStudy(StudyName);
823         newStudy = new QAD_Study( this, aStudy, StudyName);
824       }
825
826     if ( newStudy->getResult() ) {
827       addStudy( newStudy );
828       
829       /* activate */
830       onStudyActivated( newStudy );
831       
832       /* customization on create ( called only once )*/
833       onStudyCreated( newStudy );        
834       
835       /* show */
836       newStudy->show();
837       
838       /* customization on show ( called only once ) */
839       onStudyShown( newStudy );        
840     }
841   }
842   catch( Standard_Failure ) {     
843   }    
844   qApp->processEvents();  /* update desktop*/
845   QApplication::restoreOverrideCursor();
846   return newStudy;
847 }
848
849 /*!
850     Loads the existed study in StudyManager
851 */
852 QAD_Study* QAD_Application::loadStudy( const QString& fileName )
853 {
854   /* connect CAF document to CAF application */
855   QAD_ASSERT_DEBUG_ONLY( !myStudyMgr->_is_nil() );
856     
857   SALOMEDS::Study_var aStudy = myStudyMgr->GetStudyByName( fileName );
858
859  //   SALOMEDS::ListOfOpenStudies_var List = myStudyMgr->GetOpenStudies();
860 //    for (unsigned int ind = 0; ind < List->length();ind++) {
861 //      MESSAGE ( " Study index : " << List[ind] )
862 //      aStudy = myStudyMgr->GetStudyByName(List[ind]);
863 //    }
864  
865   QAD_Study* loadStudy = 0;
866   QApplication::setOverrideCursor( Qt::waitCursor );
867   try {        
868     /* create QAD study */  
869     loadStudy = new QAD_Study( this, aStudy, aStudy->Name() );
870     
871     if ( loadStudy->getResult() ) {
872       addStudy( loadStudy );
873       
874      /* activate */
875       onStudyActivated( loadStudy );
876       
877       /* customisation on load ( called only once ) */
878       onStudyOpened( loadStudy );       
879       
880      /* show */
881       loadStudy->show();
882       
883      /* customization on show ( called only once ) */
884       onStudyShown( loadStudy );        
885     }
886
887   }
888   catch( Standard_Failure ) {    
889   }
890   qApp->processEvents();  /* update desktop*/
891   QApplication::restoreOverrideCursor();
892   return loadStudy;
893 }
894
895 /*!
896     Opens the existed study
897 */
898 QAD_Study* QAD_Application::openStudy( const QString& fileName )
899 {
900 #ifdef WNT
901     /*  Qt uses UNIX-like slashes even on WIN platform */        
902     QString name = QAD_Tools::unix2win( fileName );
903 #else
904     QString name = fileName;
905 #endif    
906     SALOMEDS::Study_var aStudy;
907     
908     /* connect CAF document to CAF application */
909     QAD_ASSERT_DEBUG_ONLY( !myStudyMgr->_is_nil() );
910  
911     QAD_Study* openStudy = 0;
912     QApplication::setOverrideCursor( Qt::waitCursor );
913     try {        
914       /* open StudyDS */
915       SALOMEDS::Study_var aStudy = myStudyMgr->Open((char*) name.latin1());
916
917       //MPV: name of the study is set in the study manager now
918       //NRI DEBUG : 11/02/2002
919       //aStudy->Name( QAD_Tools::getFileNameFromPath(name,true) );
920
921       /* create QAD study */            
922       openStudy = new QAD_Study( this, aStudy, fileName );
923       
924       if ( openStudy->getResult() ) {
925         addStudy( openStudy );
926         
927         /* activate */
928         onStudyActivated( openStudy );
929         
930         /* customisation on open ( called only once ) */
931         onStudyOpened( openStudy );       
932         
933         /* show */
934         openStudy->show();
935         
936         /* customization on show ( called only once ) */
937         onStudyShown( openStudy );        
938       }
939
940     }
941     // Handle SALOME::SALOME_Exception raised by SALOMEDS::StudyMgr
942     // Ensure that null study is returned in case of errors
943     catch(SALOME::SALOME_Exception&) {
944       if (openStudy) {
945         delete openStudy;
946         openStudy = 0;
947       }
948     }
949     catch( Standard_Failure ) {    
950     }
951     qApp->processEvents();  /* update desktop*/
952     QApplication::restoreOverrideCursor();
953     return openStudy;
954 }
955
956 /*!
957     Saves the study
958 */
959 bool QAD_Application::saveStudy( QAD_Study* study )
960 {
961     bool MultiSave = QAD_CONFIG->getSetting("Desktop:MultiFileSave") == "true";
962     bool ASCIISave = QAD_CONFIG->getSetting("Desktop:ASCIISave") == "true";
963     bool success = true;
964     QApplication::setOverrideCursor( Qt::waitCursor );
965     try {
966       /* save StudyDS */
967       if (ASCIISave) myStudyMgr->SaveASCII(study->getStudyDocument(), MultiSave);
968       else myStudyMgr->Save(study->getStudyDocument(), MultiSave);
969       study->updateCaptions();
970     } 
971     catch ( Standard_Failure ) {        
972         success = false;
973     }
974     qApp->processEvents();  /* update desktop*/
975     QApplication::restoreOverrideCursor();
976     return success;
977 }
978
979 /*!
980     Saves the study in a new file
981 */
982 bool QAD_Application::saveAsStudy( QAD_Study* study, const QString& fileName )
983 {   
984     bool MultiSave = QAD_CONFIG->getSetting("Desktop:MultiFileSave") == "true";
985     bool ASCIISave = QAD_CONFIG->getSetting("Desktop:ASCIISave") == "true";
986     bool success = false;
987 #ifdef WNT
988     /*  Qt uses UNIX-like slashes even on WIN platform */        
989     QString name = QAD_Tools::unix2win( fileName );
990 #else
991     QString name = fileName;
992 #endif    
993     if ( !name.isNull() )
994     {
995        /* check permission */
996         if (!checkPermission(name))
997           return false;
998         QApplication::setOverrideCursor( Qt::waitCursor );
999         TCollection_ExtendedString fileNameExt ( (char*) name.latin1() );
1000         try {
1001           /* save as StudyDS */
1002           if (ASCIISave) myStudyMgr->SaveAsASCII(name.latin1(), study->getStudyDocument(), MultiSave);
1003           else myStudyMgr->SaveAs(name.latin1(), study->getStudyDocument(), MultiSave);
1004
1005           study->setTitle( fileName );
1006           study->updateCaptions();
1007           success = true;
1008         }
1009         catch (Standard_Failure) {            
1010         }
1011         qApp->processEvents();  /* update desktop*/
1012         QApplication::restoreOverrideCursor(); 
1013     }
1014     return success;    
1015 }
1016
1017 /*!
1018     Closes the study
1019 */
1020 bool QAD_Application::closeStudy( QAD_Study* study, bool permanently /*=false*/ )
1021 {
1022   bool success = true;
1023   /* close CAF document */
1024   QApplication::setOverrideCursor( Qt::waitCursor );
1025   try
1026     {
1027       SALOMEDS::Study_var aStudyDocument = study->getStudyDocument();
1028       
1029       /* customization */
1030       onStudyClosed( study );
1031       
1032       /* remove */
1033       removeStudy( study );
1034       
1035       /* activate */
1036       myActiveStudy = myStudies.last();
1037       
1038       /* close application when the last study is closed */
1039       if ( myStudies.isEmpty() )
1040         emit appDeactivated ( this );
1041
1042       if ( permanently )
1043         {
1044           /* close StudyDS */
1045           myStudyMgr->Close( aStudyDocument );
1046         }
1047     } 
1048   catch ( Standard_Failure )
1049     {
1050       success = false;
1051     }
1052   qApp->processEvents();  /* update desktop*/
1053   QApplication::restoreOverrideCursor(); 
1054   return success;
1055 }
1056
1057 /*!
1058     Undo operation on the active study. 
1059     Calls undo( activeStudy ).
1060 */
1061 bool QAD_Application::onUndo()
1062 {
1063     bool ok = undo( myActiveStudy );
1064     updateActions();     /* enable/disable undo/redo */
1065     return ok;
1066 }
1067
1068 /*!
1069     Undo operation on the given study
1070 */
1071 bool QAD_Application::undo(QAD_Study* study)
1072 {
1073   bool status = false;
1074   if ( study ) 
1075     {
1076       status = study->undo();
1077     }
1078   return status;
1079 }
1080
1081 /*!
1082     Redo operation on the active study.
1083     Calls redo( myActiveStudy ). 
1084 */
1085 bool QAD_Application::onRedo()
1086 {
1087   bool ok = redo( myActiveStudy );
1088   updateActions();   /* enable/disable undo/redo */
1089   return ok;
1090 }
1091
1092 /*!
1093     Redo operation on the given study.
1094 */
1095 bool QAD_Application::redo(QAD_Study* study)
1096 {
1097   bool status = false;
1098   if ( study )
1099     {
1100       status = study->redo();
1101     }
1102   return status;
1103 }
1104
1105 /*!
1106     Copies object to the pseudo-clipboard
1107 */
1108 bool QAD_Application::onCopy()
1109 {
1110   bool status = false;
1111   if ( myActiveStudy) {
1112     SALOME_Selection* Sel = SALOME_Selection::Selection( myActiveStudy->getSelection() );
1113     if ( Sel && Sel->IObjectCount() == 1 ) {
1114       SALOMEDS::SObject_var    SO = myActiveStudy->getStudyDocument()->FindObjectID( Sel->firstIObject()->getEntry() );
1115       if ( !SO->_is_nil() ) {
1116         SALOMEDS::SComponent_var SComp = SALOMEDS::SComponent::_narrow( SO );
1117         if ( SComp->_is_nil() ) { // disable 'copy' operations for components 
1118           status = myStudyMgr->Copy( SO );
1119           updateActions();     
1120         }
1121       }
1122     }
1123   } 
1124   return status;
1125 }
1126
1127 /*!
1128     Pastes object from the pseudo-clipboard
1129 */
1130 bool QAD_Application::onPaste()
1131 {
1132   SALOMEDS::SObject_var aResult;
1133   if ( myActiveStudy) {
1134     SALOME_Selection* Sel = SALOME_Selection::Selection( myActiveStudy->getSelection() );
1135     if ( Sel && Sel->IObjectCount() == 1 ) {
1136       SALOMEDS::SObject_var    SO = myActiveStudy->getStudyDocument()->FindObjectID( Sel->firstIObject()->getEntry() );
1137       if ( !SO->_is_nil() ) {
1138         try {
1139           aResult = myStudyMgr->Paste( SO );
1140         }
1141         catch ( SALOMEDS::StudyBuilder::LockProtection& ) {
1142           myActiveStudy->updateObjBrowser( true );
1143           updateActions();
1144           QAD_MessageBox::warn1 ((QWidget*)QAD_Application::getDesktop(),
1145                                  QObject::tr("WRN_WARNING"), 
1146                                  QObject::tr("WRN_STUDY_LOCKED"),
1147                                  QObject::tr("BUT_OK"));
1148           return false;
1149         }
1150         myActiveStudy->updateObjBrowser( true );
1151         updateActions();
1152       }
1153     }
1154   } 
1155   return aResult->_is_nil();
1156 }
1157
1158 /*!
1159     Checks if it is possible to make 'copy' operation
1160 */
1161 bool QAD_Application::canCopy() 
1162 {
1163   bool status = false;
1164   if ( myActiveStudy) {
1165     SALOME_Selection* Sel = SALOME_Selection::Selection( myActiveStudy->getSelection() );
1166     if ( Sel && Sel->IObjectCount() == 1 ) {
1167       SALOMEDS::SObject_var    SO = myActiveStudy->getStudyDocument()->FindObjectID( Sel->firstIObject()->getEntry() );
1168       if ( !SO->_is_nil() ) {
1169         SALOMEDS::SComponent_var SComp = SALOMEDS::SComponent::_narrow( SO );
1170         if ( SComp->_is_nil() ) // disable copy for components
1171           status = myStudyMgr->CanCopy( SO );
1172       }
1173     }
1174   } 
1175   return status;
1176 }
1177
1178 /*!
1179     Checks if it is possible to make 'paste' operation
1180 */
1181 bool QAD_Application::canPaste() 
1182 {
1183   bool status = false;
1184   if ( myActiveStudy) {
1185     SALOME_Selection* Sel = SALOME_Selection::Selection( myActiveStudy->getSelection() );
1186     if ( Sel && Sel->IObjectCount() == 1 ) {
1187       SALOMEDS::SObject_var    SO = myActiveStudy->getStudyDocument()->FindObjectID( Sel->firstIObject()->getEntry() );
1188       if ( !SO->_is_nil() ) {
1189         status = myStudyMgr->CanPaste( SO );
1190       }
1191     }
1192   } 
1193   return status;
1194 }
1195
1196 /*!
1197     Called when the main desktop is created ( internal )
1198 */
1199 void QAD_Application::onDesktopCreated()
1200 {
1201   createActions();
1202 }
1203
1204 /*!
1205     Called after creating the given study
1206 */
1207 void QAD_Application::onStudyCreated(QAD_Study* study)
1208 {
1209 }
1210
1211 /*!
1212     Called after opening the given study
1213 */
1214 void QAD_Application::onStudyOpened(QAD_Study* study)
1215 {
1216 }
1217
1218 /*!
1219     Called after the first showing of the given study
1220 */
1221 void QAD_Application::onStudyShown( QAD_Study* study )
1222 {
1223 }
1224
1225 /*!
1226     Called when the given study is activated
1227 */
1228 void QAD_Application::onStudyActivated(QAD_Study* study)
1229 {
1230   //  MESSAGE ("QAD_Application::onStudyActivated init. "); 
1231
1232   /* deactivate old study, activate new study*/
1233
1234   /* NRI : init DEBUG IAP_001 */
1235   QAD_Study* oldActiveStudy = 0;
1236   if ( myActiveStudy != NULL )
1237     oldActiveStudy = myActiveStudy;
1238   /* NRI : end DEBUG IAP_001 */
1239   
1240
1241   if ( myActiveStudy )    
1242     onStudyDeactivated( myActiveStudy );        
1243   
1244   myActiveStudy = study;
1245
1246   /* notification */
1247   onActiveStudyChanged( oldActiveStudy, myActiveStudy );
1248   
1249   /* application activated */
1250   emit appActivated( this );
1251 }
1252
1253 /*!
1254     Called when the given study is deactivated
1255 */
1256 void QAD_Application::onStudyDeactivated(QAD_Study* study)
1257 {
1258   //  MESSAGE ("QAD_Application::onStudyDeactivated init. "); 
1259   QAD_ASSERT_DEBUG_ONLY ( myActiveStudy == study );
1260   myActiveStudy->onStudyDeactivated();
1261   myActiveStudy = 0;
1262   //  MESSAGE ("QAD_Application::onStudyDeactivated done. "); 
1263 }
1264
1265 /*!
1266     Called before closing the given study
1267 */
1268 void QAD_Application::onStudyClosed(QAD_Study* study)
1269 {
1270 }
1271
1272 /*!
1273     Called when the active study changed
1274 */
1275 void QAD_Application::onActiveStudyChanged( QAD_Study* oldActiveStudy, 
1276                                             QAD_Study* newActiveStudy )
1277 {
1278   getDesktop()->onActiveStudyChanged();
1279
1280   if ( oldActiveStudy )
1281     QAD_ASSERT( disconnect( oldActiveStudy, SIGNAL(docOperationTerminated( bool )),
1282                             this, SLOT( onOperationTerminated( bool ) ) ));
1283   if ( newActiveStudy )
1284     QAD_ASSERT( connect( newActiveStudy, SIGNAL(docOperationTerminated( bool )),
1285                          this, SLOT( onOperationTerminated( bool ) ) ));
1286   updateActions();
1287 }
1288
1289 /*!
1290     Called when the operation 'op' terminated [ protected slot ]
1291 */
1292 void QAD_Application::onOperationTerminated( bool successfully )
1293 {
1294   if ( successfully )     
1295     updateActions();        /* enable/disable undo/redo */        
1296 }
1297
1298 /*!
1299     Adds the specific items to context popup menu activated usually by MB3.
1300     Redefine to fill with desired items.
1301 */
1302 void QAD_Application::onCreatePopup ()
1303 {
1304 }
1305