Salome HOME
c630ff47d099c2d85769408f497475d4af2f883a
[modules/gui.git] / src / Qtx / QtxWorkspaceAction.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/
18 //
19 // File:      QtxWorkspaceAction.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxWorkspaceAction.h"
23
24 #include <qpopupmenu.h>
25 #include <qworkspace.h>
26 #include <qwidgetlist.h>
27
28 QtxWorkspaceAction::QtxWorkspaceAction( QWorkspace* ws, QObject* parent, const char* name )
29 : QtxAction( tr( "Controls windows into workspace" ), tr( "Workspace management" ), 0, parent, name ),
30 myFlags( Standard ),
31 myWorkspace( ws )
32 {
33   myItem.insert( Cascade, new QtxAction( tr( "Arranges the windows as overlapping tiles" ),
34                                          tr( "Cascade" ), 0, this, 0, false ) );
35   myItem.insert( Tile,    new QtxAction( tr( "Arranges the windows as nonoverlapping tiles" ),
36                                          tr( "Tile" ), 0, this, 0, false ) );
37   myItem.insert( HTile,   new QtxAction( tr( "Arranges the windows as nonoverlapping horizontal tiles" ),
38                                          tr( "Tile horizontally" ), 0, this, 0, false ) );
39   myItem.insert( VTile,   new QtxAction( tr( "Arranges the windows as nonoverlapping vertical tiles" ),
40                                          tr( "Tile vertically" ), 0, this, 0, false ) );
41
42   connect( myItem[Tile], SIGNAL( activated() ), this, SLOT( tile() ) );
43   connect( myItem[Cascade], SIGNAL( activated() ), this, SLOT( cascade() ) );
44   connect( myItem[HTile], SIGNAL( activated() ), this, SLOT( tileVertical() ) );
45   connect( myItem[VTile], SIGNAL( activated() ), this, SLOT( tileHorizontal() ) );
46 }
47
48 QtxWorkspaceAction::~QtxWorkspaceAction()
49 {
50 }
51
52 QWorkspace* QtxWorkspaceAction::workspace() const
53 {
54   return myWorkspace;
55 }
56
57 int QtxWorkspaceAction::items() const
58 {
59   return myFlags;
60 }
61
62 void QtxWorkspaceAction::setItems( const int flags )
63 {
64   if ( !flags || flags == myFlags || !( flags & Operations ) )
65     return;
66
67   myFlags = flags;
68 }
69
70 bool QtxWorkspaceAction::hasItems( const int flags ) const
71 {
72   return ( myFlags & flags ) == flags;
73 }
74
75 int QtxWorkspaceAction::accel( const int id ) const
76 {
77   int a = 0;
78   if ( myItem.contains( id ) )
79     a = myItem[id]->accel();
80   return a;
81 }
82
83 QIconSet QtxWorkspaceAction::iconSet( const int id ) const
84 {
85   QIconSet ico;
86   if ( myItem.contains( id ) )
87     ico = myItem[id]->iconSet();
88   return ico;
89 }
90
91 QString QtxWorkspaceAction::menuText( const int id ) const
92 {
93   QString txt;
94   if ( myItem.contains( id ) )
95     txt = myItem[id]->menuText();
96   return txt;
97 }
98
99 QString QtxWorkspaceAction::statusTip( const int id ) const
100 {
101   QString txt;
102   if ( myItem.contains( id ) )
103     txt = myItem[id]->statusTip();
104   return txt;
105 }
106
107 void QtxWorkspaceAction::setAccel( const int id, const int a )
108 {
109   if ( myItem.contains( id ) )
110     myItem[id]->setAccel( a );
111 }
112
113 void QtxWorkspaceAction::setIconSet( const int id, const QIconSet& ico )
114 {
115   if ( myItem.contains( id ) )
116     myItem[id]->setIconSet( ico );
117 }
118
119 void QtxWorkspaceAction::setMenuText( const int id, const QString& txt )
120 {
121   if ( myItem.contains( id ) )
122     myItem[id]->setMenuText( txt );
123 }
124
125 void QtxWorkspaceAction::setStatusTip( const int id, const QString& txt )
126 {
127   if ( myItem.contains( id ) )
128     myItem[id]->setStatusTip( txt );
129 }
130
131 bool QtxWorkspaceAction::addTo( QWidget* wid )
132 {
133   return addTo( wid, -1 );
134 }
135
136 bool QtxWorkspaceAction::addTo( QWidget* wid, const int idx )
137 {
138   if ( !wid || !wid->inherits( "QPopupMenu" ) )
139     return false;
140
141   QPopupMenu* pm = (QPopupMenu*)wid;
142   checkPopup( pm );
143
144   if ( myMenu.contains( pm ) )
145     return false;
146
147   myMenu.insert( pm, QIntList() );
148   fillPopup( pm, idx );
149
150   connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
151   connect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
152
153   return true;
154 }
155
156 bool QtxWorkspaceAction::removeFrom( QWidget* wid )
157 {
158   if ( !wid || !wid->inherits( "QPopupMenu" ) )
159     return false;
160
161   QPopupMenu* pm = (QPopupMenu*)wid;
162   if ( !myMenu.contains( pm ) )
163     return false;
164
165   clearPopup( pm );
166
167   disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
168   disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
169
170   myMenu.remove( pm );
171
172   return true;
173 }
174
175 void QtxWorkspaceAction::perform( const int type )
176 {
177   switch ( type )
178   {
179   case Cascade:
180     cascade();
181     break;
182   case Tile:
183     tile();
184     break;
185   case VTile:
186     tileVertical();
187     break;
188   case HTile:
189     tileHorizontal();
190     break;
191   }
192 }
193
194 void QtxWorkspaceAction::tile()
195 {
196   QWorkspace* ws = workspace();
197   if ( !ws )
198     return;
199
200   ws->tile();
201 }
202
203 void QtxWorkspaceAction::cascade()
204 {
205   QWorkspace* ws = workspace();
206   if ( !ws )
207     return;
208
209   ws->cascade();
210
211         int w = ws->width();
212         int h = ws->height();
213
214         QWidgetList winList = ws->windowList();
215         for ( QWidgetListIt it( winList ); it.current(); ++it )
216                 it.current()->resize( int( w * 0.8 ), int( h * 0.8 ) );
217 }
218
219 void QtxWorkspaceAction::tileVertical()
220 {
221   QWorkspace* wrkSpace = workspace();
222         if ( !wrkSpace )
223                 return;
224         
225         QWidgetList winList = wrkSpace->windowList();
226         if ( winList.isEmpty() )
227     return;
228
229   int count = 0;
230         for ( QWidgetListIt itr( winList ); itr.current(); ++itr )
231     if ( !itr.current()->testWState( WState_Minimized ) )
232       count++;
233
234   if ( !count )
235     return;
236
237         int y = 0;
238
239         int heightForEach = wrkSpace->height() / count;
240         for ( QWidgetListIt it( winList ); it.current(); ++it )
241         {
242     QWidget* win = it.current();
243     if ( win->testWState( WState_Minimized ) )
244       continue;
245
246     if ( win->testWState( WState_Maximized ) )
247                 {
248                         win->hide();
249                         win->showNormal();
250     }
251     int prefH = win->minimumHeight() + win->parentWidget()->baseSize().height();
252     int actualH = QMAX( heightForEach, prefH );
253
254     win->parentWidget()->setGeometry( 0, y, wrkSpace->width(), actualH );
255     y += actualH;
256         }
257 }
258
259 void QtxWorkspaceAction::tileHorizontal()
260 {
261   QWorkspace* wrkSpace = workspace();
262         if ( !wrkSpace )
263                 return;
264
265         QWidgetList winList = wrkSpace->windowList();
266         if ( winList.isEmpty() )
267     return;
268
269   int count = 0;
270         for ( QWidgetListIt itr( winList ); itr.current(); ++itr )
271     if ( !itr.current()->testWState( WState_Minimized ) )
272       count++;
273
274   if ( !count )
275     return;
276
277         int x = 0;
278         int widthForEach = wrkSpace->width() / count;
279         for ( QWidgetListIt it( winList ); it.current(); ++it )
280         {
281     QWidget* win = it.current();
282     if ( win->testWState( WState_Minimized ) )
283       continue;
284
285     if ( win->testWState( WState_Maximized ) )
286                 {
287                         win->hide();
288                         win->showNormal();
289     }
290     int prefW = win->minimumWidth();
291     int actualW = QMAX( widthForEach, prefW );
292         
293                 win->parentWidget()->setGeometry( x, 0, actualW, wrkSpace->height() );
294     x += actualW;
295         }
296 }
297
298 void QtxWorkspaceAction::onAboutToShow()
299 {
300   const QObject* obj = sender();
301   if ( !obj || !obj->inherits( "QPopupMenu" ) )
302     return;
303
304   updatePopup( (QPopupMenu*)obj );
305 }
306
307 void QtxWorkspaceAction::onPopupDestroyed( QObject* obj )
308 {
309   myMenu.remove( (QPopupMenu*)obj );
310 }
311
312 void QtxWorkspaceAction::checkPopup( QPopupMenu* pm )
313 {
314   if ( !myMenu.contains( pm ) )
315     return;
316
317   QIntList updList;
318   for ( QIntList::const_iterator it = myMenu[pm].begin(); it != myMenu[pm].end(); ++it )
319   {
320     if ( pm->indexOf( *it ) != -1 )
321       updList.append( *it );
322   }
323
324   myMenu.remove( pm );
325
326   if ( !updList.isEmpty() )
327     myMenu.insert( pm, updList );
328   else
329   {
330     disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
331     disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
332   }
333 }
334
335 void QtxWorkspaceAction::updatePopup( QPopupMenu* pm )
336 {
337   if ( !myMenu.contains( pm ) )
338     return;
339
340   fillPopup( pm, clearPopup( pm ) );
341
342   bool count = workspace() ? workspace()->windowList().count() : 0;
343   myItem[Cascade]->setEnabled( count );
344   myItem[Tile]->setEnabled( count );
345   myItem[HTile]->setEnabled( count );
346   myItem[VTile]->setEnabled( count );
347 }
348
349 int QtxWorkspaceAction::clearPopup( QPopupMenu* pm )
350 {
351   if ( !myMenu.contains( pm ) )
352     return -1;
353
354   int idx = -1;
355   const QIntList& lst = myMenu[pm];
356   for ( QIntList::const_iterator it = lst.begin(); it != lst.end() && idx == -1; ++it )
357     idx = pm->indexOf( *it );
358
359   for ( ItemMap::ConstIterator mit = myItem.begin(); mit != myItem.end(); ++mit )
360     mit.data()->removeFrom( pm );
361
362   for ( QIntList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
363     pm->removeItem( *itr );
364
365   return idx;
366 }
367
368 void QtxWorkspaceAction::fillPopup( QPopupMenu* pm, const int idx )
369 {
370   if ( !pm )
371     return;
372
373   int index = idx < 0 ? pm->count() : QMIN( (int)pm->count(), idx );
374
375   myMenu.insert( pm, QIntList() );
376   QIntList& lst = myMenu[pm];
377
378   for ( ItemMap::ConstIterator mit = myItem.begin(); mit != myItem.end(); ++mit )
379   {
380     if ( !hasItems( mit.key() ) )
381       continue;
382
383     mit.data()->addTo( pm, index );
384     lst.append( pm->idAt( index++ ) );
385   }
386
387   QWorkspace* ws = workspace();
388   if ( !ws || !hasItems( Windows ) )
389     return;
390
391   QWidgetList wList = ws->windowList();
392   if ( wList.isEmpty() )
393     return;
394
395   lst.append( pm->insertSeparator( index++ ) );
396
397   int param = 0;
398   pm->setCheckable( true );
399   for ( QWidgetListIt it( wList ); it.current(); ++it )
400   {
401     int id = pm->insertItem( it.current()->caption(), this, SLOT( onItemActivated( int ) ), 0, -1, index++ );
402     pm->setItemParameter( id, param++ );
403     pm->setItemChecked( id, it.current() == ws->activeWindow() );
404     lst.append( id );
405   }
406 }
407
408 void QtxWorkspaceAction::onItemActivated( int idx )
409 {
410   QWorkspace* ws = workspace();
411   if ( !ws )
412     return;
413
414   QWidgetList wList = ws->windowList();
415   if ( idx < 0 || idx >= (int)wList.count() )
416     return;
417
418   wList.at( idx )->setFocus();
419 }