Salome HOME
b9e850cdf61d6c8a9d1ba6a0b7343b6f5d383d61
[modules/gui.git] / src / SUIT / SUIT_ViewManager.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "SUIT_ViewManager.h"
24
25 #include "SUIT_Desktop.h"
26 #include "SUIT_ViewModel.h"
27 #include "SUIT_ViewWindow.h"
28 #include "SUIT_Study.h"
29 #include "SUIT_Session.h"
30
31 #include <QMap>
32 #include <QRegExp>
33 #include <QIcon>
34
35 #ifdef WIN32
36 #include <windows.h>
37 #endif
38
39 QMap<QString, int> SUIT_ViewManager::_ViewMgrId;
40
41 /*!\class SUIT_ViewManager.
42  * Class provide manipulation with view windows.
43  */
44
45 /*!Constructor.*/
46 SUIT_ViewManager::SUIT_ViewManager( SUIT_Study* theStudy,
47                                     SUIT_Desktop* theDesktop,
48                                     SUIT_ViewModel* theViewModel )
49 : QObject( 0 ),
50   myDesktop( theDesktop ),
51   myTitle( "Default: %M - viewer %V" ),
52   myStudy( NULL ),
53   myIsDetached( false )
54 {
55   myViewModel = 0;
56   myActiveView = 0;
57   setViewModel( theViewModel );
58
59   myId = useNewId( getType() );
60
61   connect( theDesktop, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
62            this,       SLOT( onWindowActivated( SUIT_ViewWindow* ) ) );
63
64   myStudy = theStudy;
65   if ( myStudy )
66     connect( myStudy, SIGNAL( destroyed() ), this, SLOT( onDeleteStudy() ) );
67 }
68
69 /*!Destructor.*/
70 SUIT_ViewManager::~SUIT_ViewManager()
71 {
72   if ( myViewModel )
73   {
74     myViewModel->setViewManager( 0 );
75     delete myViewModel;
76   }
77 }
78
79 int SUIT_ViewManager::useNewId( const QString& type )
80 {
81   if ( !_ViewMgrId.contains( type ) )
82     _ViewMgrId.insert( type, 0 );
83
84   int id = _ViewMgrId[type];
85   _ViewMgrId[type]++;
86   return id;
87 }
88
89
90 int SUIT_ViewManager::getGlobalId() const {
91   int id = -1;
92   SUIT_Application* app = SUIT_Session::session()->activeApplication();
93   if(app) {
94     id = app->viewManagerId(this);
95   }
96   return id;
97 }
98
99 void SUIT_ViewManager::setTitle( const QString& theTitle )
100 {
101   if ( myTitle == theTitle )
102     return;
103
104   myTitle = theTitle;
105   for ( int i = 0; i < myViews.count(); i++ )
106     setViewName( myViews[i] );
107 }
108
109 void SUIT_ViewManager::setIcon( const QPixmap& theIcon )
110 {
111   myIcon = theIcon;
112   for ( int i = 0; i < myViews.count(); i++ )
113     myViews[i]->setWindowIcon( QIcon( myIcon ) );
114 }
115
116 /*!Sets view model \a theViewModel to view manager.*/
117 void SUIT_ViewManager::setViewModel(SUIT_ViewModel* theViewModel)
118 {
119   if (myViewModel && myViewModel != theViewModel) {
120     myViewModel->setViewManager(0);
121     delete myViewModel;
122   }
123   myViewModel = theViewModel;
124   if (myViewModel)
125     myViewModel->setViewManager(this);
126 }
127
128 /*!Sets view name for view window \a theView.*/
129 void SUIT_ViewManager::setViewName( SUIT_ViewWindow* theView )
130 {
131   QString title = prepareTitle( getTitle(), myId + 1, myViews.indexOf( theView ) + 1 );
132   theView->setWindowTitle( title );
133 }
134
135 QString SUIT_ViewManager::prepareTitle( const QString& title, const int mId, const int vId )
136 {
137   QString res = title;
138   QRegExp re( "%[%MV]" );
139   int i = 0;
140   while ( ( i = re.indexIn( res, i ) ) != -1 )
141   {
142     QString rplc;
143     QString str = res.mid( i, re.matchedLength() );
144     if ( str == QString( "%%" ) )
145       rplc = QString( "%" );
146     else if ( str == QString( "%M" ) )
147       rplc = QString::number( mId );
148     else if ( str == QString( "%V" ) )
149       rplc = QString::number( vId );
150     res.replace( i, re.matchedLength(), rplc );
151     i += rplc.length();
152   }
153   return res;
154 }
155
156 /*! Creates View, adds it into list of views and returns just created view window*/
157 SUIT_ViewWindow* SUIT_ViewManager::createViewWindow()
158 {
159   SUIT_ViewWindow* aView = myViewModel->createView(myDesktop);
160
161   if ( !insertView( aView ) ){
162     delete aView;
163     return 0;
164   }
165
166   setViewName( aView );
167   aView->setWindowIcon( QIcon( myIcon ) );
168
169   //myDesktop->addViewWindow( aView );
170   //it is done automatically during creation of view
171
172   aView->setViewManager( this );
173   emit viewCreated( aView );
174
175   // Special treatment for the case when <aView> is the first one in this view manager
176   // -> call onWindowActivated() directly, because somebody may always want
177   // to use getActiveView()
178   if ( !myActiveView )
179     onWindowActivated( aView );
180
181   return aView;
182 }
183
184 /*! Get identifier */
185 int SUIT_ViewManager::getId() const
186 {
187   return myId;
188 }
189
190 /*!Create view window.*/
191 void SUIT_ViewManager::createView()
192 {
193   createViewWindow();
194 }
195
196 QVector<SUIT_ViewWindow*> SUIT_ViewManager::getViews() const
197 {
198   QVector<SUIT_ViewWindow*> res;
199   for ( int i = 0; i < myViews.count(); i++ )
200   {
201     if ( myViews[i] )
202       res.append( myViews[i] );
203   }
204
205   return res;
206 }
207
208 /*!Insert view window to view manager.
209  *\retval false - if something wrong, else true.
210  */
211 bool SUIT_ViewManager::insertView(SUIT_ViewWindow* theView)
212 {
213   unsigned int aSize = myViews.size();
214   unsigned int aNbItems = myViews.count() + 1;
215   if ( aNbItems > aSize )
216   {
217     myViews.resize( aNbItems );
218     aSize = myViews.size();
219   }
220
221   connect(theView, SIGNAL(closing(SUIT_ViewWindow*)),
222           this,    SLOT(onClosingView(SUIT_ViewWindow*)));
223
224   connect(theView, SIGNAL(tryClosing(SUIT_ViewWindow*)),
225           this,    SIGNAL(tryCloseView(SUIT_ViewWindow*)));
226
227   connect(theView, SIGNAL(mousePressed(SUIT_ViewWindow*, QMouseEvent*)),
228           this,    SLOT(onMousePressed(SUIT_ViewWindow*, QMouseEvent*)));
229
230   connect(theView, SIGNAL(mouseReleased(SUIT_ViewWindow*, QMouseEvent*)),
231           this,    SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)));
232
233   connect(theView, SIGNAL(mouseDoubleClicked(SUIT_ViewWindow*, QMouseEvent*)),
234           this,    SIGNAL(mouseDoubleClick(SUIT_ViewWindow*, QMouseEvent*)));
235
236   connect(theView, SIGNAL(mouseMoving(SUIT_ViewWindow*, QMouseEvent*)),
237           this,    SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)));
238
239   connect(theView, SIGNAL(wheeling(SUIT_ViewWindow*, QWheelEvent*)),
240           this,    SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)));
241
242   connect(theView, SIGNAL(keyPressed(SUIT_ViewWindow*, QKeyEvent*)),
243           this,    SIGNAL(keyPress(SUIT_ViewWindow*, QKeyEvent*)));
244
245   connect(theView, SIGNAL(keyReleased(SUIT_ViewWindow*, QKeyEvent*)),
246           this,    SIGNAL(keyRelease(SUIT_ViewWindow*, QKeyEvent*)));
247
248   connect(theView, SIGNAL(contextMenuRequested( QContextMenuEvent * )),
249           this,    SLOT  (onContextMenuRequested( QContextMenuEvent * )));
250
251   for ( uint i = 0; i < aSize; i++ )
252   {
253     if ( myViews[i] == 0 )
254     {
255       myViews[i] = theView;
256       return true;
257     }
258   }
259   return false;
260 }
261
262 /*!Emit delete view. Remove view window \a theView from view manager.
263 */
264 void SUIT_ViewManager::onClosingView( SUIT_ViewWindow* theView )
265 {
266   closeView( theView );
267 }
268
269 /*!
270   Remove the view window \a theView from view manager and destroy it.
271 */
272 void SUIT_ViewManager::closeView( SUIT_ViewWindow* theView )
273 {
274   if ( !theView )
275     return;
276
277   QPointer<SUIT_ViewWindow> view( theView );
278
279   view->setClosable( false );
280   view->hide();
281
282   if ( !view->testAttribute( Qt::WA_DeleteOnClose ) )
283     return;
284
285   emit deleteView( view );
286   removeView( view );
287
288   if ( view )
289     delete view;
290 }
291
292 /*!Remove view window \a theView from view manager.
293  *And close the last view, if it has \a theView.
294 */
295 void SUIT_ViewManager::removeView( SUIT_ViewWindow* theView )
296 {
297   theView->disconnect( this );
298   myViews.remove( myViews.indexOf( theView ) );
299   if ( myActiveView == theView )
300     myActiveView = 0;
301   if ( !myViews.count() )
302     emit lastViewClosed( this );
303 }
304
305 /*!
306   Set or clear flag Qt::WDestructiveClose for all views
307 */
308 void SUIT_ViewManager::setDestructiveClose( const bool on )
309 {
310   for ( int i = 0; i < myViews.count(); i++ )
311     myViews[i]->setDestructiveClose( on );
312 }
313
314 /*!
315   Returns 'true' if any of views (view windows) is visible.
316 */
317 bool SUIT_ViewManager::isVisible() const
318 {
319   bool res = false;
320   for ( int i = 0; i < myViews.count() && !res; i++ )
321     res = myViews[i]->isVisibleTo( myViews[i]->parentWidget() );
322   return res;
323 }
324
325 /*!
326   Show or hide all views (view windows)
327 */
328 void SUIT_ViewManager::setShown( const bool on )
329 {
330   for ( int i = 0; i < myViews.count(); i++ )
331     myViews.at( i )->setVisible( on );
332 }
333
334 /*!Emit on \a theEvent mouse pressed in \a theView.*/
335 void SUIT_ViewManager::onMousePressed(SUIT_ViewWindow* theView, QMouseEvent* theEvent)
336 {
337   emit mousePress(theView, theEvent);
338 }
339
340 /*!Emit activated for view \a view.
341 */
342 void SUIT_ViewManager::onWindowActivated(SUIT_ViewWindow* view)
343 {
344   if (view) {
345     unsigned int aSize = myViews.size();
346     for (uint i = 0; i < aSize; i++) {
347       if (myViews[i] && myViews[i] == view) {
348         myActiveView = view;
349         emit activated( this );
350         return;
351       }
352     }
353   }
354 }
355
356 /*!Close all views.
357 */
358 void SUIT_ViewManager::closeAllViews()
359 {
360   for ( int i = 0; i < myViews.size(); i++ )
361     delete myViews[i];
362   myViews.clear();
363 }
364
365 /*!
366  *\retval QString - type of view model.
367  */
368 QString SUIT_ViewManager::getType() const
369 {
370   return (!myViewModel)? "": myViewModel->getType();
371 }
372
373 /*!
374  *\retval SUIT_Study* - current study.
375  */
376 SUIT_Study* SUIT_ViewManager::study() const
377 {
378     return myStudy;
379 }
380
381 /*!
382  * Sets stydy to NULL.
383  */
384 void SUIT_ViewManager::onDeleteStudy()
385 {
386     myStudy = NULL;
387 }
388
389 /*! invoke method of SUIT_PopupClient, which notifies about popup*/
390 void SUIT_ViewManager::onContextMenuRequested( QContextMenuEvent* e )
391 {
392   contextMenuRequest( e );
393 }
394
395 /*!Context menu popup for \a popup.*/
396 void SUIT_ViewManager::contextMenuPopup( QMenu* popup )
397 {
398   SUIT_ViewModel* vm = getViewModel();
399   if ( vm )
400     vm->contextMenuPopup( popup );
401 }
402
403 /*! option detached (false by default) to set before the viewWindow is added to Desktop TabBar */
404 void SUIT_ViewManager::setDetached(bool detached)
405 {
406   myIsDetached = detached;
407 }
408
409 /*! get option detached (false by default) to decide if the viewWindow is to be added to Desktop TabBar */
410 bool SUIT_ViewManager::getDetached() const
411 {
412   return myIsDetached;
413 }