Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/gui.git] / src / Qtx / QtxWorkstack.h
1 // Copyright (C) 2007-2012  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.
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 // File:      QtxWorkstack.h
24 // Author:    Sergey TELKOV
25 //
26 #ifndef QTXWORKSTACK_H
27 #define QTXWORKSTACK_H
28
29 #include "Qtx.h"
30
31 #include <QMap>
32 #include <QFrame>
33 #include <QEvent>
34 #include <QWidget>
35 #include <QTabBar>
36 #include <QPointer>
37 #include <QSplitter>
38 #include <QByteArray>
39
40 class QAction;
41 class QDataStream;
42 class QRubberBand;
43 class QStackedWidget;
44 class QAbstractButton;
45
46 class QtxWorkstackArea;
47 class QtxWorkstackDrag;
48 class QtxWorkstackChild;
49 class QtxWorkstackTabBar;
50 class QtxWorkstackSplitter;
51
52 #ifdef WIN32
53 #pragma warning( disable:4251 )
54 #endif
55
56 class QTX_EXPORT QtxWorkstack : public QWidget
57 {
58   Q_OBJECT
59
60 public:
61   //! Workstack actions (context menu items)
62   enum { SplitVertical    = 0x01,  //!< "Split vertically" menu item
63          SplitHorizontal  = 0x02,  //!< "Split horizontally" menu item
64          Close            = 0x04,  //!< "Close" menu item
65          Rename           = 0x08,  //!< "Rename" menu item
66          All = SplitVertical | SplitHorizontal |
67                Close | Rename      //!< all menu items
68   };
69
70   enum { VersionMarker = 0x01,
71                SplitMarker   = 0x02,
72                AreaMarker    = 0x04,
73                WidgetMarker  = 0x08
74   };
75
76   enum { Horizontal = 0x01,
77                Visible    = 0x02
78   };
79
80   //! Workstack splitting type
81   enum SplitType
82   {
83     SplitStay,  //!< selected widget stays in current workarea, others widgets are moved into a new workarea
84     SplitAt,    //!< all widgets before selected widget stay in current workarea, other widgess are moved into a new workarea
85     SplitMove   //!< selected widget is moved into a new workarea, all other widgets stay in an old workarea
86   };
87
88 public:
89   QtxWorkstack( QWidget* = 0 );
90   virtual ~QtxWorkstack();
91
92   QWidgetList         windowList( QWidget* = 0 ) const;
93   QWidgetList         splitWindowList() const;
94
95   QWidget*            activeWindow() const;
96
97   int                 accel( const int ) const;
98   void                setAccel( const int, const int );
99
100   QIcon               icon( const int ) const;
101   void                setIcon( const int, const QIcon& );
102
103   void                setMenuActions( const int );
104   int                 menuActions() const;
105
106   void                stack();
107   void                split( const int );
108   bool                move( QWidget* wid, QWidget* wid_to, const bool before );
109
110   QWidget*            addWindow( QWidget*, Qt::WindowFlags = 0 );
111
112   QByteArray          saveState( int ) const;
113   bool                restoreState( const QByteArray&, int );
114   
115   void                setOpaqueResize( bool = true );
116   bool                opaqueResize() const;
117
118   void Split( QWidget* wid, const Qt::Orientation o, const SplitType type );
119   void Attract( QWidget* wid1, QWidget* wid2, const bool all );
120   void SetRelativePosition( QWidget* wid, const Qt::Orientation o, const double pos );
121   void SetRelativePositionInSplitter( QWidget* wid, const double pos );
122
123 signals:
124   void                windowActivated( QWidget* );
125
126 public slots:
127   void                splitVertical();
128   void                splitHorizontal();
129
130 private slots:
131   void                onRename();
132   void                onCloseWindow();
133   void                onDestroyed( QObject* );
134   void                onWindowActivated( QWidget* );
135   void                onContextMenuRequested( QWidget*, QPoint );
136   void                onDeactivated( QtxWorkstackArea* );
137
138 protected:
139   virtual void        customEvent( QEvent* );
140
141   QAction*            action( const int ) const;
142
143   void                saveState( QDataStream& ) const;
144   bool                restoreState( QDataStream& );
145
146 private:
147   QSplitter*          splitter( QtxWorkstackArea* ) const;
148   void                splitters( QSplitter*, QList<QSplitter*>&, const bool = false ) const;
149   void                areas( QSplitter*, QList<QtxWorkstackArea*>&, const bool = false ) const;
150
151   QSplitter*          wrapSplitter( QtxWorkstackArea* );
152   void                insertWidget( QWidget*, QWidget*, QWidget* );
153
154   QtxWorkstackArea*   areaAt( const QPoint& ) const;
155   QtxWorkstackArea*   wgArea( QWidget* ) const;
156
157   QtxWorkstackArea*   targetArea();
158   QtxWorkstackArea*   activeArea() const;
159   QtxWorkstackArea*   currentArea() const;
160
161   void                setActiveArea( QtxWorkstackArea* );
162   QtxWorkstackArea*   neighbourArea( QtxWorkstackArea* ) const;
163
164   QtxWorkstackArea*   createArea( QWidget* ) const;
165
166   void                updateState();
167   void                updateState( QSplitter* );
168
169   void                distributeSpace( QSplitter* ) const;
170
171   int                 setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
172                                                            const int need_pos, const int splitter_pos );
173
174 private:
175   QPointer<QWidget>          myWin;        //!< active widget
176   QPointer<QtxWorkstackArea> myArea;       //!< active workarea
177   QtxWorkstackSplitter*      mySplit;      //!< tol-level splitter
178   QPointer<QWidget>          myWorkWin;    //!< widget where popup menu is invoked (used internally)
179   QPointer<QtxWorkstackArea> myWorkArea;   //!< workarea where popup menu is invoked (used internally)
180
181   QMap<int, QAction*> myActionsMap; //!< actions map
182
183   friend class QtxWorkstackArea;
184   friend class QtxWorkstackDrag;
185   friend class QtxWorkstackAction;
186   friend class QtxWorkstackSplitter;
187 };
188
189 class QtxWorkstackSplitter : public QSplitter
190 {
191   Q_OBJECT
192
193 public:
194   QtxWorkstackSplitter( QWidget* = 0 );
195   virtual ~QtxWorkstackSplitter();
196
197   QtxWorkstack*       workstack() const;
198
199   void                saveState( QDataStream& ) const;
200   bool                restoreState( QDataStream&, QMap<QString, QtxWorkstackChild*>& );
201 };
202
203 class QtxWorkstackArea : public QFrame
204 {
205   Q_OBJECT
206
207   class WidgetEvent;
208   class RestoreEvent;
209
210 public:
211   QtxWorkstackArea( QWidget* );
212   virtual ~QtxWorkstackArea();
213
214   bool                isNull() const;
215   bool                isEmpty() const;
216
217   QtxWorkstackChild*  insertWidget( QWidget*, const int = -1, Qt::WindowFlags = 0 );
218   void                removeWidget( QWidget*, const bool = true );
219
220   void                insertChild( QtxWorkstackChild*, const int = -1 );
221   void                removeChild( QtxWorkstackChild*, const bool = true );
222
223   QWidget*            activeWidget() const;
224   void                setActiveWidget( QWidget* );
225
226   bool                contains( QWidget* ) const;
227
228   QWidgetList         widgetList() const;
229   QList<QtxWorkstackChild*> childList() const;
230
231   bool                isActive() const;
232   void                updateActiveState();
233
234   QtxWorkstack*       workstack() const;
235
236   virtual bool        eventFilter( QObject*, QEvent* );
237
238   QRect               floatRect() const;
239   QRect               floatTab( const int ) const;
240
241   int                 tabAt( const QPoint& ) const;
242
243   void                saveState( QDataStream& ) const;
244   bool                restoreState( QDataStream&, QMap<QString, QtxWorkstackChild*>& );
245
246 signals:
247   void                activated( QWidget* );
248   void                contextMenuRequested( QWidget*, QPoint );
249   void                deactivated( QtxWorkstackArea* );
250
251 private slots:
252   void                onClose();
253   void                onCurrentChanged( int );
254
255   void                onChildDestroyed( QObject* );
256   void                onChildShown( QtxWorkstackChild* );
257   void                onChildHidden( QtxWorkstackChild* );
258   void                onChildActivated( QtxWorkstackChild* );
259   void                onChildCaptionChanged( QtxWorkstackChild* );
260
261   void                onDragActiveTab();
262   void                onContextMenuRequested( QPoint );
263
264 protected:
265   virtual void        customEvent( QEvent* );
266   virtual void        focusInEvent( QFocusEvent* );
267   virtual void        mousePressEvent( QMouseEvent* );
268
269 private:
270   //! Custom events
271   enum { ActivateWidget = QEvent::User,   //!< activate widget event
272                FocusWidget,                     //!< focus receiving widget event
273          MakeCurrent,
274          RestoreWidget
275   };
276
277 private:
278   void                updateState();
279   void                updateCurrent();
280   void                updateTab( QWidget* );
281
282   QWidget*            widget( const int ) const;
283   int                 widgetId( QWidget* ) const;
284
285   QtxWorkstackChild*  child( QWidget* ) const;
286   QtxWorkstackChild*  child( const int ) const;
287
288   void                setWidgetActive( QWidget* );
289
290   int                 generateId() const;
291
292 private:
293   typedef QList<QtxWorkstackChild*> ChildList;
294
295 private:
296   QtxWorkstackTabBar* myBar;     //!< workarea tab bar header
297   ChildList           myList;    //!< child widgets list
298   QAbstractButton*    myClose;   //!< close button
299   QStackedWidget*     myStack;   //!< widget stack
300 };
301
302 class QtxWorkstackChild : public QWidget
303 {
304   Q_OBJECT
305
306 public:
307   QtxWorkstackChild( QWidget*, QWidget* = 0, Qt::WindowFlags = 0 );
308   virtual ~QtxWorkstackChild();
309
310   QWidget*            widget() const
311 ;
312
313   int                 id() const;
314   void                setId( const int );
315
316   bool                visibility();
317
318   QtxWorkstackArea*   area() const;
319
320   virtual bool        eventFilter( QObject*, QEvent* );
321
322 signals:
323   void                shown( QtxWorkstackChild* );
324   void                hidden( QtxWorkstackChild* );
325   void                activated( QtxWorkstackChild* );
326   void                captionChanged( QtxWorkstackChild* );
327
328 private slots:
329   void                onDestroyed( QObject* );
330
331 protected:
332   virtual void        childEvent( QChildEvent* );
333
334 private:
335   int                 myId;       //!< id
336   QPointer<QWidget>   myWidget;   //!< child widget
337 };
338
339 class QtxWorkstackTabBar : public QTabBar
340 {
341   Q_OBJECT
342
343 public:
344   QtxWorkstackTabBar( QWidget* = 0 );
345   virtual ~QtxWorkstackTabBar();
346
347   bool                isActive() const;
348   void                setActive( const bool );
349
350   int                 tabId( const int ) const;
351   int                 indexOf( const int ) const;
352   void                setTabId( const int, const int );
353
354   void                updateActiveState();
355
356 signals:
357   void                dragActiveTab();
358   void                contextMenuRequested( QPoint );
359
360 private slots:
361   void                onCurrentChanged( int );
362
363 protected:
364   virtual void        changeEvent( QEvent* );
365   virtual void        mouseMoveEvent( QMouseEvent* );
366   virtual void        mousePressEvent( QMouseEvent* );
367   virtual void        mouseReleaseEvent( QMouseEvent* );
368   virtual void        contextMenuEvent( QContextMenuEvent* );
369
370 private:
371   int                 myId;         //!< current tab page index
372   bool                myActive;     //!< "active" status
373 };
374
375 class QtxWorkstackDrag : public QObject
376 {
377   Q_OBJECT
378
379 public:
380   QtxWorkstackDrag( QtxWorkstack*, QtxWorkstackChild* );
381   virtual ~QtxWorkstackDrag();
382
383   virtual bool        eventFilter( QObject*, QEvent* );
384
385 private:
386   void                dropWidget();
387
388   void                updateTarget( const QPoint& );
389   QtxWorkstackArea*   detectTarget( const QPoint&, int& ) const;
390   void                setTarget( QtxWorkstackArea*, const int );
391
392   void                drawRect();
393   void                endDrawRect();
394   void                startDrawRect();
395
396 private:
397   QtxWorkstack*       myWS;          //!< parent workstack
398   QtxWorkstackChild*  myChild;       //!< workstack child widget container
399
400   int                 myTab;         //!< workarea tab page index
401   QtxWorkstackArea*   myArea;        //!< workarea
402   QRubberBand*        myTabRect;     //!< tab bar rubber band
403   QRubberBand*        myAreaRect;    //!< workarea rubber band
404 };
405
406 #ifdef WIN32
407 #pragma warning( default:4251 )
408 #endif
409
410 #endif   // QTXWORKSTACK_H