Salome HOME
Merge relevant changes from V8_0_0_BR branch
[modules/gui.git] / src / SUIT / SUIT_ViewManager.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_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 {
54   myViewModel = 0;
55   myActiveView = 0;
56   setViewModel( theViewModel );
57
58   myId = useNewId( getType() );
59
60   connect( theDesktop, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
61            this,       SLOT( onWindowActivated( SUIT_ViewWindow* ) ) );
62
63   myStudy = theStudy;
64   if ( myStudy )
65     connect( myStudy, SIGNAL( destroyed() ), this, SLOT( onDeleteStudy() ) );
66 }
67
68 /*!Destructor.*/
69 SUIT_ViewManager::~SUIT_ViewManager()
70 {
71   if ( myViewModel )
72   {
73     myViewModel->setViewManager( 0 );
74     delete myViewModel;
75   }
76 }
77
78 int SUIT_ViewManager::useNewId( const QString& type )
79 {
80   if ( !_ViewMgrId.contains( type ) )
81     _ViewMgrId.insert( type, 0 );
82
83   int id = _ViewMgrId[type];
84   _ViewMgrId[type]++;
85   return id;
86 }
87
88
89 int SUIT_ViewManager::getGlobalId() const {
90   int id = -1;
91   SUIT_Application* app = SUIT_Session::session()->activeApplication();
92   if(app) {
93     id = app->viewManagerId(this);
94   }
95   return id;
96 }
97
98 void SUIT_ViewManager::setTitle( const QString& theTitle )
99 {
100   if ( myTitle == theTitle )
101     return;
102
103   myTitle = theTitle;
104   for ( int i = 0; i < myViews.count(); i++ )
105     setViewName( myViews[i] );
106 }
107
108 void SUIT_ViewManager::setIcon( const QPixmap& theIcon )
109 {
110   myIcon = theIcon;
111   for ( int i = 0; i < myViews.count(); i++ )
112     myViews[i]->setWindowIcon( QIcon( myIcon ) );
113 }
114
115 /*!Sets view model \a theViewModel to view manager.*/
116 void SUIT_ViewManager::setViewModel(SUIT_ViewModel* theViewModel)
117 {
118   if (myViewModel && myViewModel != theViewModel) {
119     myViewModel->setViewManager(0);
120     delete myViewModel;
121   }
122   myViewModel = theViewModel;
123   if (myViewModel)
124     myViewModel->setViewManager(this);
125 }
126
127 /*!Sets view name for view window \a theView.*/
128 void SUIT_ViewManager::setViewName( SUIT_ViewWindow* theView )
129 {
130   QString title = prepareTitle( getTitle(), myId + 1, myViews.indexOf( theView ) + 1 );
131   theView->setWindowTitle( title );
132 }
133
134 QString SUIT_ViewManager::prepareTitle( const QString& title, const int mId, const int vId )
135 {
136   QString res = title;
137   QRegExp re( "%[%MV]" );
138   int i = 0;
139   while ( ( i = re.indexIn( res, i ) ) != -1 )
140   {
141     QString rplc;
142     QString str = res.mid( i, re.matchedLength() );
143     if ( str == QString( "%%" ) )
144       rplc = QString( "%" );
145     else if ( str == QString( "%M" ) )
146       rplc = QString::number( mId );
147     else if ( str == QString( "%V" ) )
148       rplc = QString::number( vId );
149     res.replace( i, re.matchedLength(), rplc );
150     i += rplc.length();
151   }
152   return res;
153 }
154
155 /*! Creates View, adds it into list of views and returns just created view window*/
156 SUIT_ViewWindow* SUIT_ViewManager::createViewWindow()
157 {
158   SUIT_ViewWindow* aView = myViewModel->createView(myDesktop);
159
160   if ( !insertView( aView ) ){
161     delete aView;
162     return 0;
163   }
164
165   setViewName( aView );
166   aView->setWindowIcon( QIcon( myIcon ) );
167
168   //myDesktop->addViewWindow( aView );
169   //it is done automatically during creation of view
170
171   aView->setViewManager( this );
172   emit viewCreated( aView );
173
174   // Special treatment for the case when <aView> is the first one in this view manager
175   // -> call onWindowActivated() directly, because somebody may always want
176   // to use getActiveView()
177   if ( !myActiveView )
178     onWindowActivated( aView );
179
180   return aView;
181 }
182
183 /*! Get identifier */
184 int SUIT_ViewManager::getId() const
185 {
186   return myId;
187 }
188
189 /*!Create view window.*/
190 void SUIT_ViewManager::createView()
191 {
192   createViewWindow();
193 }
194
195 QVector<SUIT_ViewWindow*> SUIT_ViewManager::getViews() const
196 {
197   QVector<SUIT_ViewWindow*> res;
198   for ( int i = 0; i < myViews.count(); i++ )
199   {
200     if ( myViews[i] )
201       res.append( myViews[i] );
202   }
203
204   return res;
205 }
206
207 /*!Insert view window to view manager.
208  *\retval false - if something wrong, else true.
209  */
210 bool SUIT_ViewManager::insertView(SUIT_ViewWindow* theView)
211 {
212   unsigned int aSize = myViews.size();
213   unsigned int aNbItems = myViews.count() + 1;
214   if ( aNbItems > aSize )
215   {
216     myViews.resize( aNbItems );
217     aSize = myViews.size();
218   }
219
220   connect(theView, SIGNAL(closing(SUIT_ViewWindow*)),
221           this,    SLOT(onClosingView(SUIT_ViewWindow*)));
222
223   connect(theView, SIGNAL(tryClosing(SUIT_ViewWindow*)),
224           this,    SIGNAL(tryCloseView(SUIT_ViewWindow*)));
225
226   connect(theView, SIGNAL(mousePressed(SUIT_ViewWindow*, QMouseEvent*)),
227           this,    SLOT(onMousePressed(SUIT_ViewWindow*, QMouseEvent*)));
228
229   connect(theView, SIGNAL(mouseReleased(SUIT_ViewWindow*, QMouseEvent*)),
230           this,    SIGNAL(mouseRelease(SUIT_ViewWindow*, QMouseEvent*)));
231
232   connect(theView, SIGNAL(mouseDoubleClicked(SUIT_ViewWindow*, QMouseEvent*)),
233           this,    SIGNAL(mouseDoubleClick(SUIT_ViewWindow*, QMouseEvent*)));
234
235   connect(theView, SIGNAL(mouseMoving(SUIT_ViewWindow*, QMouseEvent*)),
236           this,    SIGNAL(mouseMove(SUIT_ViewWindow*, QMouseEvent*)));
237
238   connect(theView, SIGNAL(wheeling(SUIT_ViewWindow*, QWheelEvent*)),
239           this,    SIGNAL(wheel(SUIT_ViewWindow*, QWheelEvent*)));
240
241   connect(theView, SIGNAL(keyPressed(SUIT_ViewWindow*, QKeyEvent*)),
242           this,    SIGNAL(keyPress(SUIT_ViewWindow*, QKeyEvent*)));
243
244   connect(theView, SIGNAL(keyReleased(SUIT_ViewWindow*, QKeyEvent*)),
245           this,    SIGNAL(keyRelease(SUIT_ViewWindow*, QKeyEvent*)));
246
247   connect(theView, SIGNAL(contextMenuRequested( QContextMenuEvent * )),
248           this,    SLOT  (onContextMenuRequested( QContextMenuEvent * )));
249
250   for ( uint i = 0; i < aSize; i++ )
251   {
252     if ( myViews[i] == 0 )
253     {
254       myViews[i] = theView;
255       return true;
256     }
257   }
258   return false;
259 }
260
261 /*!Emit delete view. Remove view window \a theView from view manager.
262 */
263 void SUIT_ViewManager::onClosingView( SUIT_ViewWindow* theView )
264 {
265   closeView( theView );
266 }
267
268 /*!
269   Remove the view window \a theView from view manager and destroy it.
270 */
271 void SUIT_ViewManager::closeView( SUIT_ViewWindow* theView )
272 {
273   if ( !theView )
274     return;
275
276   QPointer<SUIT_ViewWindow> view( theView );
277
278   view->setClosable( false );
279   view->hide();
280
281   if ( !view->testAttribute( Qt::WA_DeleteOnClose ) )
282     return;
283
284   emit deleteView( view );
285   removeView( view );
286
287   if ( view )
288     delete view;
289 }
290
291 /*!Remove view window \a theView from view manager.
292  *And close the last view, if it has \a theView.
293 */
294 void SUIT_ViewManager::removeView( SUIT_ViewWindow* theView )
295 {
296   theView->disconnect( this );
297   myViews.remove( myViews.indexOf( theView ) );
298   if ( myActiveView == theView )
299     myActiveView = 0;
300   if ( !myViews.count() )
301     emit lastViewClosed( this );
302 }
303
304 /*!
305   Set or clear flag Qt::WDestructiveClose for all views
306 */
307 void SUIT_ViewManager::setDestructiveClose( const bool on )
308 {
309   for ( int i = 0; i < myViews.count(); i++ )
310     myViews[i]->setDestructiveClose( on );
311 }
312
313 /*!
314   Returns 'true' if any of views (view windows) is visible.
315 */
316 bool SUIT_ViewManager::isVisible() const
317 {
318   bool res = false;
319   for ( int i = 0; i < myViews.count() && !res; i++ )
320     res = myViews[i]->isVisibleTo( myViews[i]->parentWidget() );
321   return res;
322 }
323
324 /*!
325   Show or hide all views (view windows)
326 */
327 void SUIT_ViewManager::setShown( const bool on )
328 {
329   for ( int i = 0; i < myViews.count(); i++ )
330     myViews.at( i )->setVisible( on );
331 }
332
333 /*!Emit on \a theEvent mouse pressed in \a theView.*/
334 void SUIT_ViewManager::onMousePressed(SUIT_ViewWindow* theView, QMouseEvent* theEvent)
335 {
336   emit mousePress(theView, theEvent);
337 }
338
339 /*!Emit activated for view \a view.
340 */
341 void SUIT_ViewManager::onWindowActivated(SUIT_ViewWindow* view)
342 {
343   if (view) {
344     unsigned int aSize = myViews.size();
345     for (uint i = 0; i < aSize; i++) {
346       if (myViews[i] && myViews[i] == view) {
347         myActiveView = view;
348         emit activated( this );
349         return;
350       }
351     }
352   }
353 }
354
355 /*!Close all views.
356 */
357 void SUIT_ViewManager::closeAllViews()
358 {
359   for ( int i = 0; i < myViews.size(); i++ )
360     delete myViews[i];
361   myViews.clear();
362 }
363
364 /*!
365  *\retval QString - type of view model.
366  */
367 QString SUIT_ViewManager::getType() const
368 {
369   return (!myViewModel)? "": myViewModel->getType();
370 }
371
372 /*!
373  *\retval SUIT_Study* - current study.
374  */
375 SUIT_Study* SUIT_ViewManager::study() const
376 {
377     return myStudy;
378 }
379
380 /*!
381  * Sets stydy to NULL.
382  */
383 void SUIT_ViewManager::onDeleteStudy()
384 {
385     myStudy = NULL;
386 }
387
388 /*! invoke method of SUIT_PopupClient, which notifies about popup*/
389 void SUIT_ViewManager::onContextMenuRequested( QContextMenuEvent* e )
390 {
391   contextMenuRequest( e );
392 }
393
394 /*!Context menu popup for \a popup.*/
395 void SUIT_ViewManager::contextMenuPopup( QMenu* popup )
396 {
397   SUIT_ViewModel* vm = getViewModel();
398   if ( vm )
399     vm->contextMenuPopup( popup );
400 }