Salome HOME
Merge branch 'hydro/imps_2015' of https://git.salome-platform.org/gitpub/modules...
[modules/gui.git] / src / SUIT / SUIT_Application.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "SUIT_Application.h"
24
25 #include "SUIT_Study.h"
26 #include "SUIT_Session.h"
27 #include "SUIT_Desktop.h"
28 #include "SUIT_ResourceMgr.h"
29 #include "SUIT_ShortcutMgr.h"
30
31 #include <QTimer>
32 #include <QLabel>
33 #include <QStatusBar>
34 #include <QApplication>
35 #include <QSize>
36
37 #include <QtxAction.h>
38 #include <QtxActionMenuMgr.h>
39 #include <QtxActionToolMgr.h>
40
41
42 /*!
43   \class StatusLabel
44   \brief Status bar customization label. Used to workaroubd desktop resizing bug.
45   \internal
46 */
47 class StatusLabel : public QLabel
48 {
49 public:
50   StatusLabel( QWidget* parent ) : QLabel( parent ) {}
51   QSize minimumSizeHint () const { return QSize( 0, QLabel::minimumSizeHint().height() ); }
52 };
53
54 /*!
55   Default constructor
56 */
57 SUIT_Application::SUIT_Application()
58 : QObject( 0 ),
59   myStudy( 0 ),
60   myDesktop( 0 ),
61   myStatusLabel( 0 )
62 {
63   if ( SUIT_Session::session() )
64     SUIT_Session::session()->insertApplication( this );
65 }
66
67 /*!
68   Destructor
69 */
70 SUIT_Application::~SUIT_Application()
71 {
72   SUIT_Study* s = myStudy;
73   setActiveStudy( 0 );
74   delete s;
75
76   setDesktop( 0 );
77 }
78
79 /*!
80   \return main window of application (desktop)
81 */
82 SUIT_Desktop* SUIT_Application::desktop()
83 {
84   return myDesktop;
85 }
86
87 /*!
88    \return FALSE if application can not be closed (because of non saved data for example).
89    This method called by SUIT_Session whin closing of application was requested.
90 */
91 bool SUIT_Application::isPossibleToClose( bool& )
92 {
93   return true;
94 }
95
96 /*!
97   Performs some finalization of life cycle of this application.
98   For instance, the application can force its documents(s) to close.
99 */
100 void SUIT_Application::closeApplication()
101 {
102   emit applicationClosed( this );
103 }
104
105 /*!
106   \return active Study. If Application supports wirking with several studies this method should be redefined
107 */
108 SUIT_Study* SUIT_Application::activeStudy() const
109 {
110   return myStudy;
111 }
112
113 /*!
114   \return version of application
115 */
116 QString SUIT_Application::applicationVersion() const
117 {
118   return QString();
119 }
120
121 /*!
122   Shows the application's main widget. For non GUI application must be redefined.
123 */
124 void SUIT_Application::start()
125 {
126   if ( desktop() )
127     desktop()->show();
128
129   // Initialize shortcut manager
130   SUIT_ShortcutMgr::Init();
131 }
132
133 /*!
134   Opens document into active Study. If Study is empty - creates it.
135   \param theFileName - name of document file
136 */
137 bool SUIT_Application::useFile( const QString& theFileName )
138 {
139   createEmptyStudy();
140   SUIT_Study* study = activeStudy();
141
142   bool status = study ? study->openDocument( theFileName ) : false;
143
144   if ( !status )
145   {
146     setActiveStudy( 0 );
147     delete study;
148   }
149
150   return status;
151 }
152
153 /*!
154   Creates new empty Study if active Study = 0
155 */
156 void SUIT_Application::createEmptyStudy()
157 {
158   if ( !activeStudy() )
159     setActiveStudy( createNewStudy() );
160 }
161
162 /*!
163   \return number of Studies.
164   Must be redefined in Applications which support several studies for one Application instance.
165 */
166 int SUIT_Application::getNbStudies() const
167 {
168   return activeStudy() ? 1 : 0;
169 }
170
171 /*!
172   \return global resource manager
173 */
174 SUIT_ResourceMgr* SUIT_Application::resourceMgr() const
175 {
176   if ( !SUIT_Session::session() )
177     return 0;
178
179   return SUIT_Session::session()->resourceMgr();
180 }
181
182 /*!
183   \brief Get access to shortcut manager.
184   \return global shortcut manager
185 */
186 SUIT_ShortcutMgr* SUIT_Application::shortcutMgr() const
187 {
188   return SUIT_ShortcutMgr::getShortcutMgr();
189 }
190
191 #define DEFAULT_MESSAGE_DELAY 3000
192
193 /*!
194   Puts the message to the status bar
195   \param msg - text of message
196   \param msec - time in milliseconds, after that the status label will be cleared
197 */
198 void SUIT_Application::putInfo( const QString& msg, const int msec )
199 {
200   if ( !desktop() )
201     return;
202
203   if ( !myStatusLabel )
204   {
205     myStatusLabel = new StatusLabel( desktop()->statusBar() );
206     desktop()->statusBar()->addWidget( myStatusLabel, 1 );
207     myStatusLabel->show();
208   }
209
210   QString prev = myStatusLabel->text();
211
212   myStatusLabel->setText( msg );
213   if ( msec != -1 )
214     QTimer::singleShot( msec <= 0 ? DEFAULT_MESSAGE_DELAY : msec, this, SLOT( onInfoClear() ) );
215
216   if ( prev != msg )
217     emit infoChanged( msg );
218 }
219
220 /*!
221   Clear the information label in status bar after delay.
222 */
223 void SUIT_Application::onInfoClear()
224 {
225   if ( !myStatusLabel )
226     return;
227
228   bool changed = !myStatusLabel->text().isEmpty();
229   myStatusLabel->clear();
230   if ( changed )
231     emit infoChanged( QString() );
232 }
233
234 /*!
235   Update status of the registerd actions
236 */
237 void SUIT_Application::updateCommandsStatus()
238 {
239 }
240
241 /*!
242   Initialize with application arguments
243   \param argc - number of application arguments
244   \param argv - array of application arguments
245 */
246 SUIT_Application* SUIT_Application::startApplication( int argc, char** argv ) const
247 {
248   return startApplication( objectName(), argc, argv );
249 }
250
251 /*!
252   Initialize with application name and arguments
253   \param name - name of application
254   \param argc - number of application arguments
255   \param argv - array of application arguments
256 */
257 SUIT_Application* SUIT_Application::startApplication( const QString& name, int argc, char** argv ) const
258 {
259   SUIT_Session* session = SUIT_Session::session();
260   if ( !session )
261     return 0;
262
263   return session->startApplication( name, argc, argv );
264 }
265
266 /*!
267   Sets the main window of application
268   \param desk - new main window (desktop)
269 */
270 void SUIT_Application::setDesktop( SUIT_Desktop* desk )
271 {
272   if ( myDesktop == desk )
273     return;
274
275   // >> VSR 09/06/2009: workaround about the Qt 4.5.0 bug: SIGSEGV on desktop delete
276   myDesktop->deleteLater(); // delete myDesktop;
277   // << VSR 09/06/2009
278   myDesktop = desk;
279   if ( myDesktop ) {
280     connect( myDesktop, SIGNAL( activated() ), this, SLOT( onDesktopActivated() ) );
281 //    connect( myDesktop, SIGNAL( moved() ), this, SLOT( onDesktopMoved() ) );
282     // Force desktop activation (NPAL16628)
283     QApplication::postEvent(myDesktop, new QEvent(QEvent::WindowActivate));
284   }
285 }
286
287 /*!
288   Creates new instance of study.
289   By default, it is called from createEmptyStudy()
290   \sa createEmptyStudy()
291 */
292 SUIT_Study* SUIT_Application::createNewStudy()
293 {
294   return new SUIT_Study( this );
295 }
296
297 /*!
298   Sets study as active
299   \param study - instance of study to be set as active
300 */
301 void SUIT_Application::setActiveStudy( SUIT_Study* study )
302 {
303   if ( myStudy == study )
304     return;
305
306   if ( myStudy )
307     disconnect( myStudy, SIGNAL( studyModified( SUIT_Study* ) ),
308                 this, SLOT( updateCommandsStatus() ) );
309   if ( study )
310     connect( study, SIGNAL( studyModified( SUIT_Study* ) ),
311              this, SLOT( updateCommandsStatus() ) );
312
313   myStudy = study;
314 }
315
316 /*!
317   Creates new toolbar
318   \return identificator of new toolbar in tool manager
319   \param title - title of new toolbar
320   \param name - name (identifier) of new toolbar
321 */
322 int SUIT_Application::createTool( const QString& title, const QString& name )
323 {
324   if ( !desktop() || !desktop()->toolMgr() )
325     return -1;
326
327   return desktop()->toolMgr()->createToolBar( title, name );
328 }
329
330 /*!
331   Creates new toolbutton
332   \return SUIT identificator of new action
333   \param a - action
334   \param tBar - identificator of toolbar
335   \param id - proposed SUIT identificator of action (if it is -1, then must be use any free)
336   \param idx - index in toolbar
337 */
338 int SUIT_Application::createTool( QAction* a, const int tBar, const int id, const int idx )
339 {
340   if ( !desktop() || !desktop()->toolMgr() )
341     return -1;
342
343   int regId = registerAction( id, a );
344   int intId = desktop()->toolMgr()->insert( a, tBar, idx );
345   return intId != -1 ? regId : -1;
346 }
347
348 /*!
349   Creates new toolbutton
350   \return SUIT identificator of new action
351   \param a - action
352   \param tBar - name of toolbar
353   \param id - proposed SUIT identificator of action (if it is -1, then must be use any free)
354   \param idx - index in toolbar
355 */
356 int SUIT_Application::createTool( QAction* a, const QString& tBar, const int id, const int idx )
357 {
358   if ( !desktop() || !desktop()->toolMgr() )
359     return -1;
360
361   int regId = registerAction( id, a );
362   int intId = desktop()->toolMgr()->insert( a, tBar, idx );
363   return intId != -1 ? regId : -1;
364 }
365
366 /*!
367   Creates new toolbutton
368   \return "id" if all right or -1 otherwise
369   \param id - SUIT identificator of action
370   \param tBar - identificator of toolbar
371   \param idx - index in toolbar
372 */
373 int SUIT_Application::createTool( const int id, const int tBar, const int idx )
374 {
375   if ( !desktop() || !desktop()->toolMgr() )
376     return -1;
377
378   int intId = desktop()->toolMgr()->insert( action( id ), tBar, idx );
379   return intId != -1 ? id : -1;
380 }
381
382 /*!
383   Creates new toolbutton
384   \return "id" if all right or -1 otherwise
385   \param id - SUIT identificator of action
386   \param tBar - name of toolbar
387   \param idx - index in toolbar
388 */
389 int SUIT_Application::createTool( const int id, const QString& tBar, const int idx )
390 {
391   if ( !desktop() || !desktop()->toolMgr() )
392     return -1;
393
394   int intId = desktop()->toolMgr()->insert( action( id ), tBar, idx );
395   return intId != -1 ? id : -1;
396 }
397
398 /*!
399   Creates new menu item
400   \return identificator of new action in menu manager
401   \param subMenu - menu text of new item
402   \param menu - identificator of parent menu item
403   \param id - proposed identificator of action
404   \param group - group in menu manager
405   \param index - index in menu
406 */
407 int SUIT_Application::createMenu( const QString& subMenu, const int menu,
408                                   const int id, const int group, const int index )
409 {
410   if ( !desktop() || !desktop()->menuMgr() )
411     return -1;
412
413   return desktop()->menuMgr()->insert( subMenu, menu, group, id, index );
414 }
415
416 /*!
417   Creates new menu item
418   \return identificator of new action in menu manager
419   \param subMenu - menu text of new item
420   \param menu - menu text of parent menu item
421   \param id - proposed identificator of action
422   \param group - group in menu manager
423   \param index - index in menu
424 */
425 int SUIT_Application::createMenu( const QString& subMenu, const QString& menu,
426                                   const int id, const int group, const int index )
427 {
428   if ( !desktop() || !desktop()->menuMgr() )
429     return -1;
430
431   return desktop()->menuMgr()->insert( subMenu, menu, group, id, index );
432 }
433
434 /*!
435   Creates new menu item
436   \return SUIT identificator of new action
437   \param a - action
438   \param menu - identificator of parent menu item
439   \param id - proposed SUIT identificator of action
440   \param group - group in menu manager
441   \param index - index in menu
442 */
443 int SUIT_Application::createMenu( QAction* a, const int menu, const int id, const int group, const int index )
444 {
445   if ( !a || !desktop() || !desktop()->menuMgr() )
446     return -1;
447
448   int regId = registerAction( id, a );
449   int intId = desktop()->menuMgr()->insert( a, menu, group, index );
450   return intId != -1 ? regId : -1;
451 }
452
453 /*!
454   Creates new menu item
455   \return SUIT identificator of new action
456   \param a - action
457   \param menu - menu text of parent menu item
458   \param id - proposed SUIT identificator of action
459   \param group - group in menu manager
460   \param index - index in menu
461 */
462 int SUIT_Application::createMenu( QAction* a, const QString& menu, const int id, const int group, const int index )
463 {
464   if ( !a || !desktop() || !desktop()->menuMgr() )
465     return -1;
466
467   int regId = registerAction( id, a );
468   int intId = desktop()->menuMgr()->insert( a, menu, group, index );
469   return intId != -1 ? regId : -1;
470 }
471
472 /*!
473   Creates new menu item
474   \return identificator of new action in menu manager
475   \param id - SUIT identificator of action
476   \param menu - menu text of parent menu item
477   \param group - group in menu manager
478   \param index - index in menu
479 */
480 int SUIT_Application::createMenu( const int id, const int menu, const int group, const int index )
481 {
482   if ( !desktop() || !desktop()->menuMgr() )
483     return -1;
484
485   int intId = desktop()->menuMgr()->insert( action( id ), menu, group, index );
486   return intId != -1 ? id : -1;
487 }
488
489 /*!
490   Creates new menu item
491   \return identificator of new action in menu manager
492   \param id - SUIT identificator of action
493   \param menu - menu text of parent menu item
494   \param group - group in menu manager
495   \param index - index in menu
496 */
497 int SUIT_Application::createMenu( const int id, const QString& menu, const int group, const int index )
498 {
499   if ( !desktop() || !desktop()->menuMgr() )
500     return -1;
501
502   int intId = desktop()->menuMgr()->insert( action( id ), menu, group, index );
503   return intId != -1 ? id : -1;
504 }
505
506 /*!
507   Show/hide menu item corresponding to action
508   \param a - action
509   \param on - if it is true, the item will be shown, otherwise it will be hidden
510 */
511 void SUIT_Application::setMenuShown( QAction* a, const bool on )
512 {
513   if ( !a || !desktop() )
514     return;
515
516   QtxActionMenuMgr* mMgr = desktop()->menuMgr();
517   if ( mMgr )
518     mMgr->setShown( mMgr->actionId( a ), on );
519 }
520
521 /*!
522   Show/hide menu item corresponding to action
523   \param id - identificator of action in menu manager
524   \param on - if it is true, the item will be shown, otherwise it will be hidden
525 */
526 void SUIT_Application::setMenuShown( const int id, const bool on )
527 {
528   setMenuShown( action( id ), on );
529 }
530
531 /*!
532   Show/hide tool button corresponding to action
533   \param a - action
534   \param on - if it is true, the button will be shown, otherwise it will be hidden
535 */
536 void SUIT_Application::setToolShown( QAction* a, const bool on )
537 {
538   if ( !a || !desktop() )
539     return;
540
541   QtxActionToolMgr* tMgr = desktop()->toolMgr();
542   if ( tMgr )
543     tMgr->setShown( tMgr->actionId( a ), on );
544 }
545
546 /*!
547   Show/hide menu item corresponding to action
548   \param id - identificator of action in tool manager
549   \param on - if it is true, the button will be shown, otherwise it will be hidden
550 */
551 void SUIT_Application::setToolShown( const int id, const bool on )
552 {
553   setToolShown( action( id ), on );
554 }
555
556 /*!
557   Show/hide both menu item and tool button corresponding to action
558   \param a - action
559   \param on - if it is true, the item will be shown, otherwise it will be hidden
560 */
561 void SUIT_Application::setActionShown( QAction* a, const bool on )
562 {
563   setMenuShown( a, on );
564   setToolShown( a, on );
565 }
566
567 /*!
568   Show/hide both menu item and tool button corresponding to action
569   \param id - identificator in both menu manager and tool manager
570   \param on - if it is true, the item will be shown, otherwise it will be hidden
571 */
572 void SUIT_Application::setActionShown( const int id, const bool on )
573 {
574   setMenuShown( id, on );
575   setToolShown( id, on );
576 }
577
578 /*!
579   \return action by it's SUIT identificator
580   \param id - SUIT identificator
581 */
582 QAction* SUIT_Application::action( const int id ) const
583 {
584   QAction* a = 0;
585   if ( myActionMap.contains( id ) )
586     a = myActionMap[id];
587   return a;
588 }
589
590 /*!
591   \return SUIT identificator of action
592   \param a - action
593 */
594 int SUIT_Application::actionId( const QAction* a ) const
595 {
596   int id = -1;
597   for ( QMap<int, QAction*>::ConstIterator it = myActionMap.begin(); it != myActionMap.end() && id == -1; ++it )
598   {
599     if ( it.value() == a )
600       id = it.key();
601   }
602   return id;
603 }
604
605 QList<QAction*> SUIT_Application::actions() const
606 {
607   return myActionMap.values();
608 }
609
610 QList<int> SUIT_Application::actionIds() const
611 {
612   return myActionMap.keys();
613 }
614
615 /*!
616   Creates action and registers it both in menu manager and tool manager
617   \return new instance of action
618   \param id - proposed SUIT identificator
619   \param text - description
620   \param icon - icon for toolbar
621   \param menu - menu text
622   \param tip - tool tip
623   \param key - shortcut
624   \param parent - parent object
625   \param toggle - if it is TRUE the action will be a toggle action, otherwise it will be a command action
626   \param reciever - object that contains slot
627   \param member - slot to be called when action is activated
628 */
629 QAction* SUIT_Application::createAction( const int id, const QString& text, const QIcon& icon,
630                                          const QString& menu, const QString& tip, const int key,
631                                          QObject* parent, const bool toggle, QObject* reciever, 
632                                          const char* member, const QString& shortcutAction )
633 {
634   QtxAction* a = new QtxAction( text, icon, menu, key, parent, toggle, shortcutAction );
635   a->setStatusTip( tip );
636
637   if ( reciever && member )
638     connect( a, SIGNAL( triggered( bool ) ), reciever, member );
639
640   registerAction( id, a );
641
642   return a;
643 }
644
645 /*!
646   Registers action both in menu manager and tool manager
647   \param id - proposed SUIT identificator (if it is -1, auto generated one is used)
648   \param a - action
649 */
650 int SUIT_Application::registerAction( const int id, QAction* a )
651 {
652   int ident = actionId( a );
653   if ( ident != -1 )
654     return ident;
655
656   static int generatedId = -1;
657   ident = id == -1 ? --generatedId : id;
658
659   if ( action( ident ) )
660     qWarning( "Action registration id is already in use: %d", ident );
661
662   myActionMap.insert( ident, a );
663
664   if ( desktop() && desktop()->menuMgr() )
665     desktop()->menuMgr()->registerAction( a );
666
667   if ( desktop() && desktop()->toolMgr() )
668     desktop()->toolMgr()->registerAction( a );
669
670   if ( desktop() )
671     desktop()->addAction( a );
672
673   return ident;
674 }
675
676 /*!
677   \return global action used as separator
678 */
679 QAction* SUIT_Application::separator()
680 {
681   return QtxActionMgr::separator();
682 }
683
684 /*!
685   SLOT: it is called when desktop is activated
686 */
687
688 void SUIT_Application::onDesktopActivated()
689 {
690   emit activated( this );
691 }
692
693 /*!
694   SLOT: it is called when desktop is moved
695 */
696 /*void SUIT_Application::onDesktopMoved()
697 {
698   emit moving();
699 }*/
700 /*!
701   SLOT: is used for Help browsing
702 */
703 void SUIT_Application::onHelpContextModule( const QString& /*theComponentName*/,
704                                             const QString& /*theFileName*/,
705                                             const QString& /*theContext*/ )
706 {
707 }