Salome HOME
Improvement(Add keyboard shortcuts to make ?Split vertical / Split horizontal / Close...
[modules/gui.git] / src / Qtx / QtxWorkstack.h
1 // File:      QtxWorkstack.h
2 // Author:    Sergey TELKOV
3
4 #ifndef QTXWORKSTACK_H
5 #define QTXWORKSTACK_H
6
7 #include "Qtx.h"
8
9 #include <qhbox.h>
10 #include <qwidget.h>
11 #include <qtabbar.h>
12 #include <qwidgetlist.h>
13
14 class QAction;
15 class QTabBar;
16 class QPainter;
17 class QSplitter;
18 class QPushButton;
19 class QWidgetStack;
20
21 class QtxWorkstackArea;
22 class QtxWorkstackDrag;
23 class QtxWorkstackChild;
24 class QtxWorkstackTabBar;
25
26 class QTX_EXPORT QtxWorkstack : public QWidget
27 {
28   Q_OBJECT
29  
30 public:
31
32   QtxWorkstack( QWidget* = 0 );
33   virtual ~QtxWorkstack();
34
35   QWidgetList         windowList() const;
36   QWidgetList         splitWindowList() const;
37
38   QWidget*            activeWindow() const;
39
40   void                split( const int );
41
42   enum { SplitVertical, SplitHorizontal, Close };
43
44   // begin: jfa 06.07.2005
45   enum SplitType {
46     SPLIT_STAY, //!< given widget stays in its workarea, others are moved into a new one
47     SPLIT_AT,   //!< widgets before a given widget stays in they workarea, others are moved into a new one
48     SPLIT_MOVE  //!< given widget is moved into a new workarea, others stay in an old one
49   };
50
51   /*!
52    * \brief Split workarea of the given widget on two parts.
53    * \param wid  - widget, belonging to this workstack
54    * \param o    - orientation of splitting (Qt::Horizontal or Qt::Vertical)
55    * \param type - type of splitting, see <VAR>SplitType</VAR> enumeration
56    */
57   void Split( QWidget* wid, const Qt::Orientation o, const SplitType type);
58
59   /*!
60    * \brief Put given widget on top of its workarea
61    * \param wid - widget, belonging to this workstack
62    */
63   void OnTop( QWidget* wid);
64
65   /*!
66    * \brief Move widget(s) from source workarea into target workarea
67    *        or just reorder widgets inside one workarea.
68    * \param wid1 - widget from target workarea
69    * \param wid2 - widget from source workarea
70    * \param all  - if this parameter is TRUE, all widgets from source workarea will
71    *               be moved into the target one, else only the \a wid2 will be moved
72    *
73    * Move \a wid2 in target workarea. Put it right after \a wid1.
74    * If value of boolean argument is TRUE, all widgets from source workarea
75    * will be moved together with \a wid2, source workarea will be deleted.
76    * If \a wid1 and \a wid2 belongs to one workarea, simple reordering will take place.
77    */
78   void Attract( QWidget* wid1, QWidget* wid2, const bool all );
79
80   /*!
81    * \brief Set position of the widget relatively its splitter.
82    * \param wid - widget to set position of
83    * \param pos - position relatively splitter. Value in range [0..1].
84    *
85    * Orientation of positioning will correspond to the splitter orientation.
86    */
87   void SetRelativePositionInSplitter( QWidget* wid, const double pos );
88
89   /*!
90    * \brief Set position of the widget relatively the entire workstack.
91    * \param wid - widget to set position of
92    * \param o   - orientation of positioning (Qt::Horizontal or Qt::Vertical).
93    *              If o = Qt::Horizontal, horizontal position of \a wid will be changed.
94    *              If o = Qt::Vertical, vertical position of \a wid will be changed.
95    * \param pos - position relatively workstack. Value in range [0..1].
96    */
97   void SetRelativePosition( QWidget* wid, const Qt::Orientation o, const double pos );
98   // end: jfa 06.07.2005
99
100   /*!
101    * \brief Sets the action's accelerator key to accel. 
102    * \param id - the key of the action in the actions map.
103    * \param accel - action's accelerator key.
104    */
105   void setAccel( const int id, const int accel );
106
107   /*!
108    * \brief Returns the action's accelerator key.
109    * \param id - the key of the action in the actions map.
110    * \retval int  - action's accelerator key.
111    */
112   int accel (const int id) const;
113
114 signals:
115   void                windowActivated( QWidget* );
116
117 public slots:
118   void                splitVertical();
119   void                splitHorizontal();
120   
121 private slots:
122   void                onDestroyed( QObject* );
123   void                onWindowActivated( QWidget* );
124   void                onContextMenuRequested( QPoint );
125   void                onDeactivated( QtxWorkstackArea* );
126   /*!
127    * \brief Closes the active window.
128    */
129   void                onCloseWindow();
130
131 protected:
132   virtual void        childEvent( QChildEvent* );
133   virtual void        customEvent( QCustomEvent* );
134
135 private:
136   QSplitter*          splitter( QtxWorkstackArea* ) const;
137   void                splitters( QSplitter*, QPtrList<QSplitter>&, const bool = false ) const;
138   void                areas( QSplitter*, QPtrList<QtxWorkstackArea>&, const bool = false ) const;
139
140   QSplitter*          wrapSplitter( QtxWorkstackArea* );
141   void                insertWidget( QWidget*, QWidget*, QWidget* );
142
143   QtxWorkstackArea*   areaAt( const QPoint& ) const;
144
145   QtxWorkstackArea*   targetArea();
146   QtxWorkstackArea*   activeArea() const;
147   QtxWorkstackArea*   currentArea() const;
148
149   void                setActiveArea( QtxWorkstackArea* );
150   QtxWorkstackArea*   neighbourArea( QtxWorkstackArea* ) const;
151
152   QtxWorkstackArea*   createArea( QWidget* ) const;
153
154   void                updateState();
155   void                updateState( QSplitter* );
156
157   void                distributeSpace( QSplitter* ) const;
158
159   // begin: jfa 06.07.2005
160   /*!
161    * \brief Set position of given widget.
162    * \param wid          - widget to be moved
163    * \param split        - currently processed splitter (goes from more common
164    *                       to more particular splitter in recursion calls)
165    * \param o            - orientation of positioning
166    * \param need_pos     - required position of the given widget in pixels
167    *                       (from top/left side of workstack area)
168    * \param splitter_pos - position of the splitter \a split
169    *                       (from top/left side of workstack area)
170    * \retval int - returns difference between a required and a distinguished position.
171    * 
172    * Internal method. Recursively calls itself.
173    * Is called from <VAR>SetRelativePosition</VAR> public method.
174    */
175   int                 setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
176                                    const int need_pos, const int splitter_pos);
177   // end: jfa 06.07.2005
178
179 private:
180   QWidget*            myWin;
181   QtxWorkstackArea*   myArea;
182   QSplitter*          mySplit;
183
184   QMap<int, QAction*> myActionsMap; //!< The map of the actions. Allows to get the QAction object by the key.
185
186   friend class QtxWorkstackArea;
187   friend class QtxWorkstackDrag;
188 };
189
190 class QtxWorkstackArea : public QWidget
191 {
192   Q_OBJECT
193
194 public:
195   QtxWorkstackArea( QWidget* );
196   virtual ~QtxWorkstackArea();
197
198   bool                isEmpty() const;
199
200   void                insertWidget( QWidget*, const int = -1 );
201   void                removeWidget( QWidget* );
202
203   QWidget*            activeWidget() const;
204   void                setActiveWidget( QWidget* );
205
206   bool                contains( QWidget* ) const;
207
208   QWidgetList         widgetList() const;
209
210   bool                isActive() const;
211   void                updateActiveState();
212
213   QtxWorkstack*       workstack() const;
214
215   virtual bool        eventFilter( QObject*, QEvent* );
216
217   QRect               floatRect() const;
218   QRect               floatTab( const int ) const;
219
220   int                 tabAt( const QPoint& ) const;
221
222 signals:
223   void                activated( QWidget* );
224   void                contextMenuRequested( QPoint );
225   void                deactivated( QtxWorkstackArea* );
226
227 public slots:
228   virtual void        show();
229   virtual void        hide();
230
231 private slots:
232   void                onClose();
233   void                onSelected( int );
234
235   void                onDragActiveTab();
236   void                onChildDestroyed( QObject* );
237   void                onChildShown( QtxWorkstackChild* );
238   void                onChildHided( QtxWorkstackChild* );
239   void                onChildActivated( QtxWorkstackChild* );
240   void                onChildCaptionChanged( QtxWorkstackChild* );
241
242 protected:
243   virtual void        customEvent( QCustomEvent* );
244   virtual void        focusInEvent( QFocusEvent* );
245   virtual void        mousePressEvent( QMouseEvent* );
246
247 private:
248   enum { ActivateWidget = QEvent::User, FocusWidget, RemoveWidget };
249
250 private:
251   void                updateState();
252   void                updateCurrent();
253   void                updateTab( QWidget* );
254
255   QWidget*            widget( const int ) const;
256   int                 widgetId( QWidget* ) const;
257   bool                widgetVisibility( QWidget* ) const;
258
259   void                setWidgetActive( QWidget* );
260   void                setWidgetShown( QWidget*, const bool );
261
262   int                 generateId() const;
263
264   bool                isBlocked( QWidget* ) const;
265   void                setBlocked( QWidget*, const bool );
266
267   QtxWorkstackChild*  child( QWidget* ) const;
268
269 private:
270   typedef QMap<QWidget*, bool>               BlockMap;
271   typedef QMap<QWidget*, QtxWorkstackChild*> ChildMap;
272   typedef struct { int id; bool vis; }       WidgetInfo;
273   typedef QMap<QWidget*, WidgetInfo>         WidgetInfoMap;
274
275 private:
276   QtxWorkstackTabBar* myBar;
277   QPushButton*        myClose;
278   QWidgetStack*       myStack;
279
280   QWidgetList         myList;
281   WidgetInfoMap       myInfo;
282   ChildMap            myChild;
283   BlockMap            myBlock;
284 };
285
286 class QtxWorkstackChild : public QHBox
287 {
288   Q_OBJECT
289
290 public:
291   QtxWorkstackChild( QWidget*, QWidget* = 0 );
292   virtual ~QtxWorkstackChild();
293
294   QWidget*            widget() const;
295
296   virtual bool        eventFilter( QObject*, QEvent* );
297
298 signals:
299   void                shown( QtxWorkstackChild* );
300   void                hided( QtxWorkstackChild* );
301   void                activated( QtxWorkstackChild* );
302   void                captionChanged( QtxWorkstackChild* );
303
304 private slots:
305   void                onDestroyed( QObject* );
306
307 protected:
308   virtual void        childEvent( QChildEvent* );
309
310 private:
311   QWidget*            myWidget;
312 };
313
314 class QtxWorkstackTabBar : public QTabBar
315 {
316   Q_OBJECT
317
318 public:
319   QtxWorkstackTabBar( QWidget* = 0 );
320   virtual ~QtxWorkstackTabBar();
321
322   QRect               tabRect( const int ) const;
323
324   void                setActive( const bool );
325
326 signals:
327   void                dragActiveTab();
328   void                contextMenuRequested( QPoint );
329
330 protected:
331   virtual void        mouseMoveEvent( QMouseEvent* );
332   virtual void        mousePressEvent( QMouseEvent* );
333   virtual void        mouseReleaseEvent( QMouseEvent* );
334   virtual void        contextMenuEvent( QContextMenuEvent* );
335
336   virtual void        paintLabel( QPainter*, const QRect&, QTab*, bool ) const;
337
338 private:
339   int                 myId;
340 };
341
342 class QtxWorkstackDrag : public QObject
343 {
344   Q_OBJECT
345
346 public:
347   QtxWorkstackDrag( QtxWorkstack*, QtxWorkstackChild* );
348   virtual ~QtxWorkstackDrag();
349
350   virtual bool        eventFilter( QObject*, QEvent* );
351
352 private:
353   void                dropWidget();
354
355   void                updateTarget( const QPoint& );
356   QtxWorkstackArea*   detectTarget( const QPoint&, int& ) const;
357   void                setTarget( QtxWorkstackArea*, const int );
358
359   void                drawRect();
360   void                endDrawRect();
361   void                startDrawRect();
362
363 private:
364   QtxWorkstack*       myWS;
365   QtxWorkstackChild*  myChild;
366
367   int                 myTab;
368   QtxWorkstackArea*   myArea;
369   QPainter*           myPainter;
370   
371 };
372
373 #endif