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