1 // File: QtxWorkstack.cxx
2 // Author: Sergey TELKOV
4 #include "QtxWorkstack.h"
13 #include <qsplitter.h>
14 #include <qpopupmenu.h>
15 #include <qobjectlist.h>
16 #include <qpushbutton.h>
17 #include <qwidgetstack.h>
18 #include <qapplication.h>
19 #include <qinputdialog.h>
22 Class: QtxWorkstack [Public]
26 QtxWorkstack::QtxWorkstack( QWidget* parent )
32 myActionsMap.insert( SplitVertical, new QAction( tr( "Split vertically" ), 0, this ) );
33 myActionsMap.insert( SplitHorizontal, new QAction( tr( "Split horizontally" ), 0, this ) );
34 myActionsMap.insert( Close, new QAction( tr( "Close" ), 0, this ) );
35 myActionsMap.insert( Rename, new QAction( tr( "Rename" ), 0, this ) );
37 connect( myActionsMap[SplitVertical], SIGNAL( activated() ), this, SLOT( splitVertical() ) );
38 connect( myActionsMap[SplitHorizontal], SIGNAL( activated() ), this, SLOT( splitHorizontal() ) );
39 connect( myActionsMap[Close], SIGNAL( activated() ), this, SLOT( onCloseWindow() ) );
40 connect( myActionsMap[Rename], SIGNAL( activated() ), this, SLOT( onRename() ) );
42 QVBoxLayout* base = new QVBoxLayout( this );
43 mySplit = new QSplitter( this );
44 mySplit->setChildrenCollapsible( false );
45 base->addWidget( mySplit );
48 QtxWorkstack::~QtxWorkstack()
52 QWidgetList QtxWorkstack::windowList() const
54 QPtrList<QtxWorkstackArea> lst;
55 areas( mySplit, lst, true );
58 for ( QPtrListIterator<QtxWorkstackArea> it( lst ); it.current(); ++it )
60 QWidgetList wids = it.current()->widgetList();
61 for ( QWidgetListIt itr( wids ); itr.current(); ++itr )
62 widList.append( itr.current() );
68 QWidgetList QtxWorkstack::splitWindowList() const
70 return myArea ? myArea->widgetList() : QWidgetList();
73 QWidget* QtxWorkstack::activeWindow() const
78 void QtxWorkstack::split( const int o )
80 QtxWorkstackArea* area = activeArea();
84 if ( area->widgetList().count() < 2 )
87 QWidget* curWid = area->activeWidget();
91 QSplitter* s = splitter( area );
92 QPtrList<QtxWorkstackArea> areaList;
95 QPtrList<QSplitter> splitList;
96 splitters( s, splitList );
99 if ( areaList.count() + splitList.count() < 2 || s->orientation() == o )
103 trg = wrapSplitter( area );
108 trg->setOrientation( (Orientation)o );
110 QtxWorkstackArea* newArea = createArea( 0 );
111 insertWidget( newArea, trg, area );
113 area->removeWidget( curWid );
114 newArea->insertWidget( curWid );
116 distributeSpace( trg );
123 * \brief Split workarea of the given widget on two parts.
124 * \param wid - widget, belonging to this workstack
125 * \param o - orientation of splitting (Qt::Horizontal or Qt::Vertical)
126 * \param type - type of splitting, see <VAR>SplitType</VAR> enumeration
128 void QtxWorkstack::Split (QWidget* wid, const Qt::Orientation o, const SplitType type)
132 // find area of the given widget
133 QtxWorkstackArea* area = NULL;
134 QPtrList<QtxWorkstackArea> allAreas;
135 areas(mySplit, allAreas, true);
137 QPtrListIterator<QtxWorkstackArea> it (allAreas);
138 for (; it.current() && !area; ++it) {
139 if (it.current()->contains(wid))
144 QWidgetList wids = area->widgetList();
145 if (wids.count() < 2)
148 QSplitter* s = splitter(area);
149 QPtrList<QtxWorkstackArea> areaList;
152 QPtrList<QSplitter> splitList;
153 splitters(s, splitList);
156 if (areaList.count() + splitList.count() < 2 || s->orientation() == o)
159 if (!trg) trg = wrapSplitter(area);
162 trg->setOrientation(o);
164 QtxWorkstackArea* newArea = createArea(0);
165 insertWidget(newArea, trg, area);
170 QWidgetListIt itr (wids);
171 for (; itr.current(); ++itr)
173 QWidget* wid_i = itr.current();
175 area->removeWidget(wid_i);
176 newArea->insertWidget(wid_i);
183 QWidgetListIt itr (wids);
184 for (; itr.current() && itr.current() != wid; ++itr) {
186 for (; itr.current(); ++itr) {
187 area->removeWidget(itr.current());
188 newArea->insertWidget(itr.current());
193 area->removeWidget(wid);
194 newArea->insertWidget(wid);
198 distributeSpace(trg);
202 * \brief Put given widget on top of its workarea
203 * \param wid - widget, belonging to this workstack
206 void QtxWorkstack::OnTop (QWidget* wid)
211 // find area of the given widget
212 QtxWorkstackArea* area = 0;
213 QPtrList<QtxWorkstackArea> allAreas;
214 areas( mySplit, allAreas, true );
215 for ( QPtrListIterator<QtxWorkstackArea> it( allAreas ); it.current() && !area; ++it )
217 if ( it.current()->contains( wid ) )
222 area->setActiveWidget( wid );
227 * \brief Move widget(s) from source workarea into target workarea
228 * or just reorder widgets inside one workarea.
229 * \param wid1 - widget from target workarea
230 * \param wid2 - widget from source workarea
231 * \param all - if this parameter is TRUE, all widgets from source workarea will
232 * be moved into the target one, else only the \a wid2 will be moved
234 * Move \a wid2 in target workarea. Put it right after \a wid1.
235 * If value of boolean argument is TRUE, all widgets from source workarea
236 * will be moved together with \a wid2, source workarea will be deleted.
237 * If \a wid1 and \a wid2 belongs to one workarea, simple reordering will take place.
239 void QtxWorkstack::Attract ( QWidget* wid1, QWidget* wid2, const bool all )
241 if ( !wid1 || !wid2 )
244 // find area of the widgets
245 QtxWorkstackArea *area1 = NULL, *area2 = NULL;
246 QPtrList<QtxWorkstackArea> allAreas;
247 areas(mySplit, allAreas, true);
248 QPtrListIterator<QtxWorkstackArea> it (allAreas);
249 for (; it.current() && !(area1 && area2); ++it) {
250 if (it.current()->contains(wid1))
251 area1 = it.current();
252 if (it.current()->contains(wid2))
253 area2 = it.current();
255 if (!area1 || !area2) return;
257 QWidget* curWid = area1->activeWidget();
260 if (area1 == area2) {
262 // Set wid1 at first position, wid2 at second
263 area1->insertWidget(wid1);
264 area1->insertWidget(wid2, 1);
266 // Set wid2 right after wid1
267 area1->removeWidget(wid2);
269 QWidgetList wids1 = area1->widgetList();
270 QWidgetListIt itr1 (wids1);
271 for (; itr1.current() && itr1.current() != wid1; ++itr1, ++wid1_ind);
272 area1->insertWidget(wid2, wid1_ind + 1);
276 QWidgetList wids1 = area1->widgetList();
277 QWidgetListIt itr1 (wids1);
278 for (; itr1.current() && itr1.current() != wid1; ++itr1, ++wid1_ind);
281 // Set wid2 right after wid1, other widgets from area2 right after wid2
282 QWidgetList wids2 = area2->widgetList();
283 QWidgetListIt itr2 (wids2);
284 for (int ind = wid1_ind + 1; itr2.current(); ++itr2, ++ind)
286 area2->removeWidget(itr2.current());
287 if (itr2.current() == wid2) {
288 area1->insertWidget(itr2.current(), wid1_ind + 1);
290 area1->insertWidget(itr2.current(), ind);
294 // Set wid2 right after wid1
295 area2->removeWidget(wid2);
296 area1->insertWidget(wid2, wid1_ind + 1);
300 area1->setActiveWidget( curWid );
303 static void setSizes (QIntList& szList, const int item_ind,
304 const int new_near, const int new_this, const int new_farr)
306 // set size to all items before an item # <item_ind>
308 QIntList::iterator its = szList.begin();
309 for (; its != szList.end() && cur_pos < item_ind; ++its, ++cur_pos) {
312 if (its == szList.end()) return;
313 // set size to item # <item_ind>
316 // set size to all items after an item # <item_ind>
317 for (; its != szList.end(); ++its) {
323 * \brief Set position of the widget relatively its splitter.
324 * \param wid - widget to set position of
325 * \param pos - position relatively splitter. Value in range [0..1].
327 * Orientation of positioning will correspond to the splitter orientation.
329 void QtxWorkstack::SetRelativePositionInSplitter( QWidget* wid, const double position )
331 if ( position < 0.0 || 1.0 < position)
337 // find area of the given widget
338 QtxWorkstackArea* area = NULL;
339 QPtrList<QtxWorkstackArea> allAreas;
340 areas(mySplit, allAreas, true);
341 for ( QPtrListIterator<QtxWorkstackArea> it( allAreas );
342 it.current() && !area;
345 if (it.current()->contains(wid))
352 QSplitter* split = splitter( area );
356 // find index of the area in its splitter
358 bool isFound = false;
359 const QObjectList* was = split->children();
360 for (QObjectListIt ito (*was); ito.current() && !isFound; ++ito, ++item_ind)
362 if (ito.current() == area)
365 if (!isFound || item_ind == 0)
368 QIntList szList = split->sizes();
369 int splitter_size = (split->orientation() == Horizontal ?
370 split->width() : split->height());
371 int nb = szList.count();
373 int new_prev = int(splitter_size * position / item_ind);
374 int new_next = int(splitter_size * (1.0 - position) / (nb - item_ind));
375 setSizes (szList, item_ind, new_prev, new_next, new_next);
376 split->setSizes(szList);
380 * \brief Set position of the widget relatively the entire workstack.
381 * \param wid - widget to set position of
382 * \param o - orientation of positioning (Qt::Horizontal or Qt::Vertical).
383 * If o = Qt::Horizontal, horizontal position of \a wid will be changed.
384 * If o = Qt::Vertical, vertical position of \a wid will be changed.
385 * \param pos - position relatively workstack. Value in range [0..1].
387 void QtxWorkstack::SetRelativePosition( QWidget* wid, const Qt::Orientation o,
388 const double position )
390 if ( position < 0.0 || 1.0 < position )
396 int splitter_size = o == Horizontal ? mySplit->width() : mySplit->height();
397 int need_pos = int( position * splitter_size );
398 int splitter_pos = 0;
400 if ( setPosition( wid, mySplit, o, need_pos, splitter_pos ) != 0 )
402 // impossible to set required position
407 * \brief Sets the action's accelerator key to accel.
408 * \param id - the key of the action in the actions map.
409 * \param accel - action's accelerator key.
411 void QtxWorkstack::setAccel( const int id, const int accel )
413 if ( !myActionsMap.contains( id ) )
416 myActionsMap[id]->setAccel( accel );
420 * \brief Returns the action's accelerator key.
421 * \param id - the key of the action in the actions map.
422 * \retval int - action's accelerator key.
424 int QtxWorkstack::accel( const int id ) const
427 if ( myActionsMap.contains( id ) )
428 res = myActionsMap[id]->accel();
432 static int positionSimple (QIntList& szList, const int nb, const int splitter_size,
433 const int item_ind, const int item_rel_pos,
434 const int need_pos, const int splitter_pos)
436 if (item_ind == 0) { // cannot move in this splitter
437 return (need_pos - splitter_pos);
442 int new_this = szList[item_ind];
445 bool isToCheck = false;
447 if (need_pos < splitter_pos) {
448 // Set size of all previous workareas to zero <--
449 if (item_ind == nb - 1) {
450 // item iz last in the splitter, it will occupy all the splitter
451 new_this = splitter_size;
453 // recompute size of next items in splitter
454 new_next = (splitter_size - new_this) / (nb - item_ind - 1);
456 delta = need_pos - splitter_pos;
458 } else if (need_pos > (splitter_pos + splitter_size)) {
459 // Set size of all next workareas to zero -->
460 // recompute size of previous items in splitter
462 new_prev = (splitter_size - new_this) / item_ind;
463 delta = need_pos - (splitter_pos + splitter_size - new_this);
465 } else { // required position lays inside this splitter
466 // Move workarea inside splitter into required position <->
467 int new_item_rel_pos = need_pos - splitter_pos;
468 new_prev = new_item_rel_pos / item_ind;
469 if (need_pos < (splitter_pos + item_rel_pos)) {
470 // Make previous workareas smaller, next - bigger
471 // No problem to keep old size of the widget
473 // Make previous workareas bigger, next - smaller
474 if (new_this > splitter_size - new_item_rel_pos) {
475 new_this = splitter_size - new_item_rel_pos;
477 // jfa to do: in this case fixed size of next widgets could prevent right resizing
480 if (item_ind == nb - 1) {
481 new_this = splitter_size - new_item_rel_pos;
483 new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
488 setSizes (szList, item_ind, new_prev, new_this, new_next);
493 * \brief Set position of given widget.
494 * \param wid - widget to be moved
495 * \param split - currently processed splitter (goes from more common
496 * to more particular splitter in recursion calls)
497 * \param o - orientation of positioning
498 * \param need_pos - required position of the given widget in pixels
499 * (from top/left side of workstack area)
500 * \param splitter_pos - position of the splitter \a split
501 * (from top/left side of workstack area)
502 * \retval int - returns difference between a required and a distinguished position.
504 * Internal method. Recursively calls itself.
505 * Is called from <VAR>SetRelativePosition</VAR> public method.
507 int QtxWorkstack::setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
508 const int need_pos, const int splitter_pos )
510 if ( !wid || !split )
511 return need_pos - splitter_pos;
513 // Find corresponding sub-splitter.
514 // Find also index of appropriate item in current splitter.
515 int cur_ind = 0, item_ind = 0;
516 bool isBottom = false, isFound = false;
517 QSplitter* sub_split = NULL;
518 const QObjectList* objs = split->children();
521 for (QObjectListIt it (*objs); it.current() && !isFound; ++it)
523 if (it.current()->inherits( "QtxWorkstackArea")) {
524 if (((QtxWorkstackArea*)it.current())->contains(wid)) {
530 } else if (it.current()->inherits("QSplitter")) {
531 QPtrList<QtxWorkstackArea> areaList;
532 areas((QSplitter*)it.current(), areaList, true);
533 for (QPtrListIterator<QtxWorkstackArea> ita (areaList);
534 ita.current() && !isFound;
537 if (ita.current()->contains(wid)) {
540 sub_split = (QSplitter*)it.current();
548 return (need_pos - splitter_pos);
550 if (split->orientation() == o) {
551 // Find coordinates of near and far sides of the appropriate item relatively current splitter
552 int splitter_size = (o == Horizontal ? split->width() : split->height());
553 QIntList szList = split->sizes();
554 int nb = szList.count();
555 int item_rel_pos = 0; // position of near side of item relatively this splitter
556 for (int i = 0; i < item_ind; i++) {
557 item_rel_pos += szList[i];
559 int item_size = szList[item_ind]; // size of item
560 int item_pos = splitter_pos + item_rel_pos;
562 // Resize splitter items to complete the conditions
564 // I. Bottom of splitters stack reached
566 int delta = positionSimple(szList, nb, splitter_size, item_ind, item_rel_pos, need_pos, splitter_pos);
567 split->setSizes(szList);
568 // Recompute delta, as some windows can reject given size
569 int new_item_rel_pos = 0;
570 QIntList szList1 = split->sizes();
571 for (int i = 0; i < item_ind; i++) {
572 new_item_rel_pos += szList1[i];
574 delta = need_pos - (splitter_pos + new_item_rel_pos);
578 // II. Bottom of splitters stack is not yet reached
580 if (item_ind == 0) { // cannot move in this splitter
581 // Process in sub-splitter
582 return setPosition(wid, sub_split, o, need_pos, splitter_pos);
586 int new_this = szList[item_ind];
589 if (need_pos < splitter_pos) {
590 // Set size of all previous workareas to zero <--
591 if (item_ind == nb - 1) {
592 new_this = splitter_size;
594 new_next = (splitter_size - new_this) / (nb - item_ind - 1);
596 setSizes (szList, item_ind, new_prev, new_this, new_next);
597 split->setSizes(szList);
598 // Recompute splitter_pos, as some windows can reject given size
599 int new_item_rel_pos = 0;
600 QIntList szList1 = split->sizes();
601 for (int i = 0; i < item_ind; i++) {
602 new_item_rel_pos += szList1[i];
604 // Process in sub-splitter
605 return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
606 } else if (need_pos > (splitter_pos + splitter_size)) {
607 // Set size of all next workareas to zero -->
608 new_prev = (splitter_size - new_this) / item_ind;
609 setSizes (szList, item_ind, new_prev, new_this, new_next);
610 split->setSizes(szList);
611 // Recompute splitter_pos, as some windows can reject given size
612 int new_item_rel_pos = 0;
613 QIntList szList1 = split->sizes();
614 for (int i = 0; i < item_ind; i++) {
615 new_item_rel_pos += szList1[i];
617 // Process in sub-splitter
618 return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
620 // Set appropriate size of all previous/next items <->
621 int new_item_rel_pos = item_rel_pos;
622 if (need_pos < item_pos || (item_pos + item_size) < need_pos) {
623 // Move item inside splitter into required position <->
624 int new_this = szList[item_ind];
626 new_item_rel_pos = need_pos - splitter_pos;
627 if ((item_pos + item_size) < need_pos) {
628 //new_item_rel_pos = need_pos - (item_pos + item_size);
629 new_item_rel_pos = item_rel_pos + (need_pos - (item_pos + item_size));
631 int new_prev = new_item_rel_pos / item_ind;
632 if (need_pos < (splitter_pos + item_rel_pos)) {
633 // Make previous workareas smaller, next - bigger
634 // No problem to keep old size of the widget
636 // Make previous workareas bigger, next - smaller
637 if (new_this > splitter_size - new_item_rel_pos) {
638 new_this = splitter_size - new_item_rel_pos;
641 if (item_ind == nb - 1) {
642 new_this = splitter_size - new_item_rel_pos;
644 new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
646 setSizes (szList, item_ind, new_prev, new_this, new_next);
647 split->setSizes(szList);
648 // Recompute new_item_rel_pos, as some windows can reject given size
649 new_item_rel_pos = 0;
650 QIntList szList1 = split->sizes();
651 for (int i = 0; i < item_ind; i++) {
652 new_item_rel_pos += szList1[i];
657 // Process in sub-splitter
658 int add_pos = setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
662 // this can be if corresponding workarea is first in sub-splitter
663 // or sub-splitter has another orientation
665 // Resize ones again to reach precize position <->
666 int need_pos_1 = splitter_pos + new_item_rel_pos + add_pos;
668 // Move workarea inside splitter into required position <->
669 int delta_1 = positionSimple(szList, nb, splitter_size, item_ind,
670 new_item_rel_pos, need_pos_1, splitter_pos);
671 split->setSizes(szList);
672 // Recompute new_item_rel_pos, as some windows can reject given size
673 new_item_rel_pos = 0;
674 QIntList szList1 = split->sizes();
675 for (int i = 0; i < item_ind; i++) {
676 new_item_rel_pos += szList1[i];
678 delta_1 = need_pos_1 - (splitter_pos + new_item_rel_pos);
683 return setPosition(wid, sub_split, o, need_pos, splitter_pos);
689 void QtxWorkstack::distributeSpace( QSplitter* split ) const
694 QIntList szList = split->sizes();
695 int size = ( split->orientation() == Horizontal ?
696 split->width() : split->height() ) / szList.count();
697 for ( QIntList::iterator it = szList.begin(); it != szList.end(); ++it )
699 split->setSizes( szList );
702 void QtxWorkstack::splitVertical()
704 split( Qt::Horizontal );
707 void QtxWorkstack::splitHorizontal()
709 split( Qt::Vertical );
712 void QtxWorkstack::renameWindow( QWidget* w )
718 QString newName = QInputDialog::getText( tr( "Rename" ), tr( "Enter new name:" ), QLineEdit::Normal,
719 w->caption(), &ok, topLevelWidget() );
721 w->setCaption( newName );
724 void QtxWorkstack::onRenameActive()
726 renameWindow( activeWindow() );
729 void QtxWorkstack::onRename()
731 renameWindow( myWorkWin );
734 QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area )
739 QSplitter* pSplit = splitter( area );
743 bool upd = pSplit->isUpdatesEnabled();
744 pSplit->setUpdatesEnabled( false );
746 QIntList szList = pSplit->sizes();
748 QSplitter* wrap = new QSplitter( 0 );
749 #if defined QT_VERSION && QT_VERSION >= 0x30200
750 wrap->setChildrenCollapsible( false );
752 insertWidget( wrap, pSplit, area );
753 area->reparent( wrap, QPoint( 0, 0 ), true );
755 pSplit->setSizes( szList );
757 pSplit->setUpdatesEnabled( upd );
762 void QtxWorkstack::insertWidget( QWidget* wid, QWidget* pWid, QWidget* after )
767 QWidgetList moveList;
768 const QObjectList* lst = pWid->children();
772 for ( QObjectListIt it( *lst ); it.current(); ++it )
774 if ( found && ( it.current()->inherits( "QSplitter" ) ||
775 it.current()->inherits( "QtxWorkstackArea" ) ) )
776 moveList.append( (QWidget*)it.current() );
777 if ( it.current() == after )
782 QMap<QWidget*, bool> map;
783 for ( QWidgetListIt it( moveList ); it.current(); ++it )
785 map.insert( it.current(), it.current()->isVisibleTo( it.current()->parentWidget() ) );
786 it.current()->reparent( 0, QPoint( 0, 0 ), false );
789 wid->reparent( pWid, QPoint( 0, 0 ), true );
791 for ( QWidgetListIt itr( moveList ); itr.current(); ++itr )
792 itr.current()->reparent( pWid, QPoint( 0, 0 ), map.contains( itr.current() ) ? map[itr.current()] : false );
796 * \brief Closes the active window.
798 void QtxWorkstack::onCloseWindow()
804 void QtxWorkstack::onDestroyed( QObject* obj )
806 QtxWorkstackArea* area = (QtxWorkstackArea*)obj;
808 if ( area == myArea )
813 QtxWorkstackArea* cur = neighbourArea( area );
818 QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
821 void QtxWorkstack::onWindowActivated( QWidget* wid )
823 const QObject* obj = sender();
824 if ( !obj->inherits( "QtxWorkstackArea" ) )
827 setActiveArea( (QtxWorkstackArea*)obj );
830 void QtxWorkstack::onDeactivated( QtxWorkstackArea* area )
832 if ( myArea != area )
835 QPtrList<QtxWorkstackArea> lst;
836 areas( mySplit, lst, true );
838 int idx = lst.find( area );
845 QtxWorkstackArea* newArea = neighbourArea( area );
846 if ( newArea && newArea->activeWidget() )
847 newArea->activeWidget()->setFocus();
849 QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
852 void QtxWorkstack::onContextMenuRequested( QWidget* w, QPoint p )
857 QWidgetList lst = activeArea()->widgetList();
863 QPopupMenu* pm = new QPopupMenu();
865 if ( lst.count() > 1 )
867 myActionsMap[SplitVertical]->addTo( pm );
868 myActionsMap[SplitHorizontal]->addTo( pm );
869 pm->insertSeparator();
874 myActionsMap[Close]->addTo( pm );
875 myActionsMap[Rename]->addTo( pm );
886 void QtxWorkstack::childEvent( QChildEvent* e )
888 if ( e->inserted() && e->child()->isWidgetType() )
890 QWidget* w = (QWidget*)e->child();
891 if ( w && w != mySplit )
893 targetArea()->insertWidget( w );
897 QWidget::childEvent( e );
900 void QtxWorkstack::customEvent( QCustomEvent* e )
905 QSplitter* QtxWorkstack::splitter( QtxWorkstackArea* area ) const
910 QSplitter* split = 0;
912 QWidget* wid = area->parentWidget();
913 if ( wid && wid->inherits( "QSplitter" ) )
914 split = (QSplitter*)wid;
919 void QtxWorkstack::splitters( QSplitter* split, QPtrList<QSplitter>& splitList, const bool rec ) const
924 const QObjectList* objs = split->children();
927 for ( QObjectListIt it( *objs ); it.current(); ++it )
930 splitters( (QSplitter*)it.current(), splitList, rec );
931 if ( it.current()->inherits( "QSplitter" ) )
932 splitList.append( (QSplitter*)it.current() );
937 void QtxWorkstack::areas( QSplitter* split, QPtrList<QtxWorkstackArea>& areaList, const bool rec ) const
942 const QObjectList* objs = split->children();
945 for ( QObjectListIt it( *objs ); it.current(); ++it )
947 if ( it.current()->inherits( "QtxWorkstackArea" ) )
948 areaList.append( (QtxWorkstackArea*)it.current() );
949 else if ( rec && it.current()->inherits( "QSplitter" ) )
950 areas( (QSplitter*)it.current(), areaList, rec );
955 QtxWorkstackArea* QtxWorkstack::activeArea() const
960 QtxWorkstackArea* QtxWorkstack::targetArea()
962 QtxWorkstackArea* area = activeArea();
964 area = currentArea();
967 QPtrList<QtxWorkstackArea> lst;
968 areas( mySplit, lst );
969 if ( !lst.isEmpty() )
974 area = createArea( mySplit );
979 QtxWorkstackArea* QtxWorkstack::currentArea() const
981 QtxWorkstackArea* area = 0;
982 QWidget* wid = focusWidget();
983 while ( wid && !area )
985 if ( wid->inherits( "QtxWorkstackArea" ) )
986 area = (QtxWorkstackArea*)wid;
987 wid = wid->parentWidget();
993 QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const
995 QtxWorkstackArea* area = new QtxWorkstackArea( parent );
997 connect( area, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
998 connect( area, SIGNAL( activated( QWidget* ) ), this, SLOT( onWindowActivated( QWidget* ) ) );
999 connect( area, SIGNAL( contextMenuRequested( QWidget*, QPoint ) ),
1000 this, SLOT( onContextMenuRequested( QWidget*, QPoint ) ) );
1001 connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) );
1006 void QtxWorkstack::setActiveArea( QtxWorkstackArea* area )
1008 QWidget* oldCur = myWin;
1010 QtxWorkstackArea* oldArea = myArea;
1014 if ( myArea != oldArea )
1017 oldArea->updateActiveState();
1019 myArea->updateActiveState();
1023 myWin = myArea->activeWidget();
1025 if ( myWin && oldCur != myWin )
1026 emit windowActivated( myWin );
1029 QtxWorkstackArea* QtxWorkstack::neighbourArea( QtxWorkstackArea* area ) const
1031 QPtrList<QtxWorkstackArea> lst;
1032 areas( mySplit, lst, true );
1033 int pos = lst.find( area );
1037 QtxWorkstackArea* na = 0;
1038 for ( int i = pos - 1; i >= 0 && !na; i-- )
1040 if ( !lst.at( i )->isEmpty() )
1044 for ( int j = pos + 1; j < (int)lst.count() && !na; j++ )
1046 if ( !lst.at( j )->isEmpty() )
1052 QtxWorkstackArea* QtxWorkstack::areaAt( const QPoint& p ) const
1054 QtxWorkstackArea* area = 0;
1055 QPtrList<QtxWorkstackArea> lst;
1056 areas( mySplit, lst, true );
1057 for ( QPtrListIterator<QtxWorkstackArea> it( lst ); it.current() && !area; ++it )
1059 QtxWorkstackArea* cur = it.current();
1060 QRect r = cur->geometry();
1061 if ( cur->parentWidget() )
1062 r = QRect( cur->parentWidget()->mapToGlobal( r.topLeft() ), r.size() );
1063 if ( r.contains( p ) )
1069 void QtxWorkstack::updateState()
1071 updateState( mySplit );
1074 void QtxWorkstack::updateState( QSplitter* split )
1076 QPtrList<QSplitter> recList;
1077 splitters( split, recList, false );
1078 for ( QPtrListIterator<QSplitter> itr( recList ); itr.current(); ++itr )
1079 updateState( itr.current() );
1081 QPtrList<QSplitter> splitList;
1082 splitters( split, splitList, false );
1084 QPtrList<QtxWorkstackArea> areaList;
1085 areas( split, areaList, false );
1088 for ( QPtrListIterator<QtxWorkstackArea> it( areaList ); it.current(); ++it )
1090 if ( it.current()->isEmpty() )
1091 it.current()->hide();
1094 it.current()->show();
1099 if ( split == mySplit )
1102 for ( QPtrListIterator<QSplitter> iter( splitList ); iter.current() && !vis; ++iter )
1103 vis = iter.current()->isVisibleTo( iter.current()->parentWidget() );
1105 if ( areaList.isEmpty() && splitList.isEmpty() )
1114 Class: QtxWorkstackArea [Internal]
1118 QtxWorkstackArea::QtxWorkstackArea( QWidget* parent )
1121 QVBoxLayout* base = new QVBoxLayout( this );
1123 QHBox* top = new QHBox( this );
1124 base->addWidget( top );
1126 myBar = new QtxWorkstackTabBar( top );
1128 QPushButton* close = new QPushButton( top );
1129 close->setPixmap( style().stylePixmap( QStyle::SP_TitleBarCloseButton ) );
1130 close->setAutoDefault( true );
1131 close->setFlat( true );
1134 top->setStretchFactor( myBar, 1 );
1136 myStack = new QWidgetStack( this );
1138 base->addWidget( myStack, 1 );
1140 connect( myClose, SIGNAL( clicked() ), this, SLOT( onClose() ) );
1141 connect( myBar, SIGNAL( selected( int ) ), this, SLOT( onSelected( int ) ) );
1142 connect( myBar, SIGNAL( dragActiveTab() ), this, SLOT( onDragActiveTab() ) );
1143 connect( myBar, SIGNAL( contextMenuRequested( QPoint ) ), this, SLOT( onContextMenuRequested( QPoint ) ) );
1147 updateActiveState();
1149 qApp->installEventFilter( this );
1152 QtxWorkstackArea::~QtxWorkstackArea()
1154 qApp->removeEventFilter( this );
1157 bool QtxWorkstackArea::isEmpty() const
1160 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it )
1161 res = it.data().vis;
1165 void QtxWorkstackArea::insertWidget( QWidget* wid, const int idx )
1170 int pos = myList.find( wid );
1171 if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) )
1174 myList.removeRef( wid );
1175 pos = idx < 0 ? myList.count() : idx;
1176 myList.insert( QMIN( pos, (int)myList.count() ), wid );
1177 if ( !myInfo.contains( wid ) )
1179 QtxWorkstackChild* child = new QtxWorkstackChild( wid, myStack );
1180 myChild.insert( wid, child );
1181 myInfo.insert( wid, WidgetInfo() );
1182 myInfo[wid].id = generateId();
1183 myInfo[wid].vis = wid->isVisibleTo( wid->parentWidget() );
1185 connect( child, SIGNAL( destroyed( QObject* ) ), this, SLOT( onChildDestroyed( QObject* ) ) );
1186 connect( wid, SIGNAL( destroyed() ), this, SLOT( onWidgetDestroyed() ) );
1187 connect( child, SIGNAL( shown( QtxWorkstackChild* ) ), this, SLOT( onChildShown( QtxWorkstackChild* ) ) );
1188 connect( child, SIGNAL( hided( QtxWorkstackChild* ) ), this, SLOT( onChildHided( QtxWorkstackChild* ) ) );
1189 connect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) );
1190 connect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) );
1195 setWidgetActive( wid );
1198 void QtxWorkstackArea::onContextMenuRequested( QPoint p )
1200 const QtxWorkstackTabBar* bar = ::qt_cast<const QtxWorkstackTabBar*>( sender() );
1205 QTab* tab = myBar->tabAt( tabAt( p ) );
1207 wid = widget( tab->identifier() );
1209 emit contextMenuRequested( wid, p );
1212 void QtxWorkstackArea::onWidgetDestroyed()
1215 removeWidget( (QWidget*)sender(), false );
1218 void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del )
1220 if ( !myList.contains( wid ) )
1223 if ( myBar->tab( widgetId( wid ) ) )
1224 myBar->removeTab( myBar->tab( widgetId( wid ) ) );
1225 myStack->removeWidget( child( wid ) );
1227 myList.remove( wid );
1228 myInfo.remove( wid );
1229 myChild.remove( wid );
1233 delete child( wid );
1234 if( myList.isEmpty() )
1243 QWidgetList QtxWorkstackArea::widgetList() const
1246 for ( QWidgetListIt it( myList ); it.current(); ++it )
1248 if ( widgetVisibility( it.current() ) )
1249 lst.append( it.current() );
1254 QWidget* QtxWorkstackArea::activeWidget() const
1256 return widget( myBar->currentTab() );
1259 void QtxWorkstackArea::setActiveWidget( QWidget* wid )
1261 myBar->setCurrentTab( widgetId( wid ) );
1264 bool QtxWorkstackArea::contains( QWidget* wid ) const
1266 return myList.contains( wid );
1269 void QtxWorkstackArea::show()
1271 QMap<QWidget*, bool> map;
1272 for ( QWidgetListIt it( myList ); it.current(); ++it )
1274 map.insert( it.current(), isBlocked( it.current() ) );
1275 setBlocked( it.current(), true );
1280 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
1281 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
1284 void QtxWorkstackArea::hide()
1286 QMap<QWidget*, bool> map;
1287 for ( QWidgetListIt it( myList ); it.current(); ++it )
1289 map.insert( it.current(), isBlocked( it.current() ) );
1290 setBlocked( it.current(), true );
1295 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
1296 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
1299 bool QtxWorkstackArea::isActive() const
1301 QtxWorkstack* ws = workstack();
1305 return ws->activeArea() == this;
1308 void QtxWorkstackArea::updateActiveState()
1310 myBar->setActive( isActive() );
1313 QtxWorkstack* QtxWorkstackArea::workstack() const
1315 QtxWorkstack* ws = 0;
1316 QWidget* wid = parentWidget();
1317 while ( wid && !ws )
1319 if ( wid->inherits( "QtxWorkstack" ) )
1320 ws = (QtxWorkstack*)wid;
1321 wid = wid->parentWidget();
1326 bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e )
1328 if ( o->isWidgetType() )
1330 QWidget* wid = (QWidget*)o;
1331 if ( e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress )
1334 while ( !ok && wid && wid != myClose )
1337 wid = wid->parentWidget();
1340 QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)( e->type() == QEvent::FocusIn ? ActivateWidget : FocusWidget ) ) );
1346 QRect QtxWorkstackArea::floatRect() const
1348 QRect r = myStack->geometry();
1349 return QRect( mapToGlobal( r.topLeft() ), mapToGlobal( r.bottomRight() ) );
1352 QRect QtxWorkstackArea::floatTab( const int idx ) const
1354 return myBar->tabRect( idx );
1357 int QtxWorkstackArea::tabAt( const QPoint& p ) const
1360 for ( int i = 0; i < myBar->count() && idx == -1; i++ )
1362 QRect r = myBar->tabRect( i );
1363 if ( r.isValid() && r.contains( p ) )
1369 void QtxWorkstackArea::customEvent( QCustomEvent* e )
1371 switch ( e->type() )
1373 case ActivateWidget:
1374 emit activated( activeWidget() );
1377 if ( activeWidget() && !activeWidget()->focusWidget() )
1378 activeWidget()->setFocus();
1381 removeWidget( (QWidget*)e->data() );
1386 void QtxWorkstackArea::focusInEvent( QFocusEvent* e )
1388 QWidget::focusInEvent( e );
1390 emit activated( activeWidget() );
1393 void QtxWorkstackArea::mousePressEvent( QMouseEvent* e )
1395 QWidget::mousePressEvent( e );
1397 emit activated( activeWidget() );
1400 void QtxWorkstackArea::onClose()
1402 QWidget* wid = activeWidget();
1407 void QtxWorkstackArea::onSelected( int id )
1411 emit activated( activeWidget() );
1414 void QtxWorkstackArea::onDragActiveTab()
1416 QtxWorkstackChild* c = child( activeWidget() );
1420 new QtxWorkstackDrag( workstack(), c );
1423 void QtxWorkstackArea::onChildDestroyed( QObject* obj )
1425 QtxWorkstackChild* child = (QtxWorkstackChild*)obj;
1426 myStack->removeWidget( child );
1429 for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it )
1431 if ( it.data() == child )
1435 myChild.remove( wid );
1437 QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)RemoveWidget, wid ) );
1440 void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c )
1442 setWidgetShown( c->widget(), true );
1445 void QtxWorkstackArea::onChildHided( QtxWorkstackChild* c )
1447 setWidgetShown( c->widget(), false );
1450 void QtxWorkstackArea::onChildActivated( QtxWorkstackChild* c )
1452 setWidgetActive( c->widget() );
1455 void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c )
1457 updateTab( c->widget() );
1460 void QtxWorkstackArea::updateCurrent()
1462 QMap<QWidget*, bool> map;
1463 for ( QWidgetListIt it( myList ); it.current(); ++it )
1465 map.insert( it.current(), isBlocked( it.current() ) );
1466 setBlocked( it.current(), true );
1469 myStack->raiseWidget( myBar->currentTab() );
1471 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
1472 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
1475 void QtxWorkstackArea::updateTab( QWidget* wid )
1477 QTab* tab = myBar->tab( widgetId( wid ) );
1484 QPixmap pix = *wid->icon();
1485 pix.convertFromImage( pix.convertToImage().smoothScale( pix.width(), 16, QImage::ScaleMin ) );
1486 icoSet = QIconSet( pix );
1489 tab->setIconSet( icoSet );
1490 tab->setText( wid->caption() );
1493 QWidget* QtxWorkstackArea::widget( const int id ) const
1496 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !wid; ++it )
1498 if ( it.data().id == id )
1504 int QtxWorkstackArea::widgetId( QWidget* wid ) const
1507 if ( myInfo.contains( wid ) )
1508 id = myInfo[wid].id;
1512 bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const
1515 if ( myInfo.contains( wid ) )
1516 res = myInfo[wid].vis;
1520 void QtxWorkstackArea::setWidgetActive( QWidget* wid )
1522 int id = widgetId( wid );
1526 myBar->setCurrentTab( id );
1529 void QtxWorkstackArea::setWidgetShown( QWidget* wid, const bool on )
1531 if ( isBlocked( wid ) || !myInfo.contains( wid ) || myInfo[wid].vis == on )
1534 myInfo[wid].vis = on;
1538 void QtxWorkstackArea::updateState()
1540 bool updBar = myBar->isUpdatesEnabled();
1541 bool updStk = myStack->isUpdatesEnabled();
1542 myBar->setUpdatesEnabled( false );
1543 myStack->setUpdatesEnabled( false );
1545 bool block = myBar->signalsBlocked();
1546 myBar->blockSignals( true );
1548 QWidget* prev = activeWidget();
1551 for ( QWidgetListIt it( myList ); it.current(); ++it )
1553 QWidget* wid = it.current();
1554 int id = widgetId( wid );
1559 bool vis = widgetVisibility( wid );
1561 if ( myBar->tab( id ) && ( !vis || myBar->indexOf( id ) != idx ) )
1562 myBar->removeTab( myBar->tab( id ) );
1564 if ( !myBar->tab( id ) && vis )
1566 QTab* tab = new QTab( wid->caption() );
1567 myBar->insertTab( tab, idx );
1568 tab->setIdentifier( id );
1573 bool block = isBlocked( wid );
1574 setBlocked( wid, true );
1576 QtxWorkstackChild* cont = child( wid );
1579 myStack->removeWidget( cont );
1580 else if ( !myStack->widget( id ) )
1581 myStack->addWidget( cont, id );
1586 setBlocked( wid, block );
1589 int curId = widgetId( prev );
1590 if ( !myBar->tab( curId ) )
1593 int pos = myList.find( prev );
1594 for ( int i = pos - 1; i >= 0 && !wid; i-- )
1596 if ( widgetVisibility( myList.at( i ) ) )
1597 wid = myList.at( i );
1600 for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ )
1602 if ( widgetVisibility( myList.at( j ) ) )
1603 wid = myList.at( j );
1607 curId = widgetId( wid );
1610 myBar->setCurrentTab( curId );
1612 myBar->blockSignals( block );
1616 myBar->setUpdatesEnabled( updBar );
1617 myStack->setUpdatesEnabled( updStk );
1623 QResizeEvent re( myBar->size(), myBar->size() );
1624 QApplication::sendEvent( myBar, &re );
1629 emit deactivated( this );
1634 if ( prev != activeWidget() )
1635 emit activated( activeWidget() );
1639 int QtxWorkstackArea::generateId() const
1643 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end(); ++it )
1644 map.insert( it.data().id, 0 );
1647 while ( map.contains( id ) )
1653 bool QtxWorkstackArea::isBlocked( QWidget* wid ) const
1655 return myBlock.contains( wid );
1658 void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on )
1661 myBlock.insert( wid, 0 );
1663 myBlock.remove( wid );
1666 QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const
1668 QtxWorkstackChild* res = 0;
1669 if ( myChild.contains( wid ) )
1675 Class: QtxWorkstackChild [Internal]
1679 QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent )
1683 myWidget->reparent( this, QPoint( 0, 0 ), myWidget->isVisibleTo( myWidget->parentWidget() ) );
1684 myWidget->installEventFilter( this );
1686 connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1689 QtxWorkstackChild::~QtxWorkstackChild()
1691 qApp->removeEventFilter( this );
1696 widget()->removeEventFilter( this );
1697 widget()->reparent( 0, QPoint( 0, 0 ), false );
1698 disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1701 QWidget* QtxWorkstackChild::widget() const
1706 bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e )
1708 if ( o->isWidgetType() )
1710 if ( e->type() == QEvent::CaptionChange || e->type() == QEvent::IconChange )
1711 emit captionChanged( this );
1713 if ( !e->spontaneous() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
1716 if ( !e->spontaneous() && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) )
1719 if ( e->type() == QEvent::FocusIn )
1720 emit activated( this );
1722 return QHBox::eventFilter( o, e );
1725 void QtxWorkstackChild::onDestroyed( QObject* obj )
1727 if ( obj != widget() )
1734 void QtxWorkstackChild::childEvent( QChildEvent* e )
1736 if ( e->type() == QEvent::ChildRemoved && e->child() == widget() )
1741 QHBox::childEvent( e );
1745 Class: QtxWorkstackTabBar [Internal]
1749 QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent )
1750 : QTabBar( parent ),
1755 QtxWorkstackTabBar::~QtxWorkstackTabBar()
1759 void QtxWorkstackTabBar::setActive( const bool on )
1761 QFont aFont = font();
1762 aFont.setUnderline( on );
1768 QRect QtxWorkstackTabBar::tabRect( const int idx ) const
1771 QTab* t = tabAt( idx );
1775 r.setLeft( QMAX( r.left(), 0 ) );
1777 int x1 = tabAt( 0 )->rect().left();
1778 int x2 = tabAt( count() - 1 )->rect().right();
1781 if ( QABS( x2 - x1 ) > width() )
1782 #if defined QT_VERSION && QT_VERSION >= 0x30300
1783 bw = 2 * style().pixelMetric( QStyle::PM_TabBarScrollButtonWidth, this );
1788 int limit = width() - bw;
1789 r.setRight( QMIN( r.right(), limit ) );
1791 r = QRect( mapToGlobal( r.topLeft() ), r.size() );
1796 void QtxWorkstackTabBar::mouseMoveEvent( QMouseEvent* e )
1798 if ( myId != -1 && !tab( myId )->rect().contains( e->pos() ) )
1801 emit dragActiveTab();
1804 QTabBar::mouseMoveEvent( e );
1807 void QtxWorkstackTabBar::mousePressEvent( QMouseEvent* e )
1809 QTabBar::mousePressEvent( e );
1811 if ( e->button() == LeftButton )
1812 myId = currentTab();
1815 void QtxWorkstackTabBar::mouseReleaseEvent( QMouseEvent* e )
1817 QTabBar::mouseReleaseEvent( e );
1821 if ( e->button() == RightButton )
1822 emit contextMenuRequested( e->globalPos() );
1825 void QtxWorkstackTabBar::contextMenuEvent( QContextMenuEvent* e )
1827 if ( e->reason() != QContextMenuEvent::Mouse )
1828 emit contextMenuRequested( e->globalPos() );
1831 void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
1833 if ( currentTab() != t->identifier() )
1835 QFont fnt = p->font();
1836 fnt.setUnderline( false );
1839 QTabBar::paintLabel( p, br, t, has_focus );
1843 Class: QtxWorkstackDrag [Internal]
1847 QtxWorkstackDrag::QtxWorkstackDrag( QtxWorkstack* ws, QtxWorkstackChild* child )
1855 qApp->installEventFilter( this );
1858 QtxWorkstackDrag::~QtxWorkstackDrag()
1860 qApp->removeEventFilter( this );
1865 bool QtxWorkstackDrag::eventFilter( QObject*, QEvent* e )
1867 switch ( e->type() )
1869 case QEvent::MouseMove:
1870 updateTarget( ((QMouseEvent*)e)->globalPos() );
1872 case QEvent::MouseButtonRelease:
1884 void QtxWorkstackDrag::updateTarget( const QPoint& p )
1887 QtxWorkstackArea* area = detectTarget( p, tab );
1888 setTarget( area, tab );
1891 QtxWorkstackArea* QtxWorkstackDrag::detectTarget( const QPoint& p, int& tab ) const
1896 QtxWorkstackArea* area = myWS->areaAt( p );
1898 tab = area->tabAt( p );
1902 void QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab )
1904 if ( !area || ( myArea == area && tab == myTab ) )
1919 void QtxWorkstackDrag::dropWidget()
1922 myArea->insertWidget( myChild->widget(), myTab );
1925 void QtxWorkstackDrag::drawRect()
1927 if ( !myPainter || !myArea )
1930 QRect r = myArea->floatRect();
1931 int m = myPainter->pen().width();
1933 r.setTop( r.top() + m + 2 );
1934 r.setLeft( r.left() + m + 2 );
1935 r.setRight( r.right() - m - 2 );
1936 r.setBottom( r.bottom() - m - 2 );
1938 myPainter->drawRect( r );
1940 QRect tr = myArea->floatTab( myTab );
1941 tr.setTop( tr.top() + m );
1942 tr.setLeft( tr.left() + m );
1943 tr.setRight( tr.right() - m );
1944 tr.setBottom( tr.bottom() - m );
1946 myPainter->drawRect( tr );
1949 void QtxWorkstackDrag::endDrawRect()
1955 void QtxWorkstackDrag::startDrawRect()
1960 int scr = QApplication::desktop()->screenNumber( (QWidget*)this );
1961 QWidget* paint_on = QApplication::desktop()->screen( scr );
1963 myPainter = new QPainter( paint_on, true );
1964 myPainter->setPen( QPen( gray, 3 ) );
1965 myPainter->setRasterOp( XorROP );