1 // File: QtxWorkstack.cxx
2 // Author: Sergey TELKOV
4 #include "QtxWorkstack.h"
11 #include <qsplitter.h>
12 #include <qpopupmenu.h>
13 #include <qobjectlist.h>
14 #include <qpushbutton.h>
15 #include <qwidgetstack.h>
16 #include <qapplication.h>
19 Class: QtxWorkstack [Public]
23 QtxWorkstack::QtxWorkstack( QWidget* parent )
28 QVBoxLayout* base = new QVBoxLayout( this );
29 mySplit = new QSplitter( this );
30 mySplit->setChildrenCollapsible( false );
31 base->addWidget( mySplit );
34 QtxWorkstack::~QtxWorkstack()
38 QWidgetList QtxWorkstack::windowList() const
40 QPtrList<QtxWorkstackArea> lst;
41 areas( mySplit, lst, true );
44 for ( QPtrListIterator<QtxWorkstackArea> it( lst ); it.current(); ++it )
46 QWidgetList wids = it.current()->widgetList();
47 for ( QWidgetListIt itr( wids ); itr.current(); ++itr )
48 widList.append( itr.current() );
54 QWidgetList QtxWorkstack::splitWindowList() const
56 return myArea ? myArea->widgetList() : QWidgetList();
59 QWidget* QtxWorkstack::activeWindow() const
64 void QtxWorkstack::split( const int o )
66 QtxWorkstackArea* area = activeArea();
70 if ( area->widgetList().count() < 2 )
73 QWidget* curWid = area->activeWidget();
77 QSplitter* s = splitter( area );
78 QPtrList<QtxWorkstackArea> areaList;
81 QPtrList<QSplitter> splitList;
82 splitters( s, splitList );
85 if ( areaList.count() + splitList.count() < 2 || s->orientation() == o )
89 trg = wrapSplitter( area );
94 trg->setOrientation( (Orientation)o );
96 QtxWorkstackArea* newArea = createArea( 0 );
97 insertWidget( newArea, trg, area );
99 area->removeWidget( curWid );
100 newArea->insertWidget( curWid );
102 distributeSpace( trg );
108 void QtxWorkstack::distributeSpace( QSplitter* split ) const
113 QIntList szList = split->sizes();
114 int size = ( split->orientation() == Horizontal ?
115 split->width() : split->height() ) / szList.count();
116 for ( QIntList::iterator it = szList.begin(); it != szList.end(); ++it )
118 split->setSizes( szList );
121 void QtxWorkstack::splitVertical()
123 split( Qt::Vertical );
126 void QtxWorkstack::splitHorizontal()
128 split( Qt::Horizontal );
131 QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area )
136 QSplitter* pSplit = splitter( area );
140 bool upd = pSplit->isUpdatesEnabled();
141 pSplit->setUpdatesEnabled( false );
143 QIntList szList = pSplit->sizes();
145 QSplitter* wrap = new QSplitter( 0 );
146 #if defined QT_VERSION && QT_VERSION >= 0x30200
147 wrap->setChildrenCollapsible( false );
149 insertWidget( wrap, pSplit, area );
150 area->reparent( wrap, QPoint( 0, 0 ), true );
152 pSplit->setSizes( szList );
154 pSplit->setUpdatesEnabled( upd );
159 void QtxWorkstack::insertWidget( QWidget* wid, QWidget* pWid, QWidget* after )
164 QWidgetList moveList;
165 const QObjectList* lst = pWid->children();
169 for ( QObjectListIt it( *lst ); it.current(); ++it )
171 if ( found && ( it.current()->inherits( "QSplitter" ) ||
172 it.current()->inherits( "QtxWorkstackArea" ) ) )
173 moveList.append( (QWidget*)it.current() );
174 if ( it.current() == after )
179 QMap<QWidget*, bool> map;
180 for ( QWidgetListIt it( moveList ); it.current(); ++it )
182 map.insert( it.current(), it.current()->isVisibleTo( it.current()->parentWidget() ) );
183 it.current()->reparent( 0, QPoint( 0, 0 ), false );
186 wid->reparent( pWid, QPoint( 0, 0 ), true );
188 for ( QWidgetListIt itr( moveList ); itr.current(); ++itr )
189 itr.current()->reparent( pWid, QPoint( 0, 0 ), map.contains( itr.current() ) ? map[itr.current()] : false );
192 void QtxWorkstack::onPopupActivated( int id )
199 case SplitHorizontal:
203 if ( activeWindow() )
204 activeWindow()->close();
209 void QtxWorkstack::onDestroyed( QObject* obj )
211 QtxWorkstackArea* area = (QtxWorkstackArea*)obj;
213 if ( area == myArea )
218 QtxWorkstackArea* cur = neighbourArea( area );
223 QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
226 void QtxWorkstack::onWindowActivated( QWidget* wid )
228 const QObject* obj = sender();
229 if ( !obj->inherits( "QtxWorkstackArea" ) )
232 setActiveArea( (QtxWorkstackArea*)obj );
235 void QtxWorkstack::onDeactivated( QtxWorkstackArea* area )
237 if ( myArea != area )
240 QPtrList<QtxWorkstackArea> lst;
241 areas( mySplit, lst, true );
243 int idx = lst.find( area );
250 QtxWorkstackArea* newArea = neighbourArea( area );
251 if ( newArea && newArea->activeWidget() )
252 newArea->activeWidget()->setFocus();
254 QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
257 void QtxWorkstack::onContextMenuRequested( QPoint p )
262 QWidgetList lst = activeArea()->widgetList();
266 QPopupMenu* pm = new QPopupMenu();
267 connect( pm, SIGNAL( activated( int ) ), this, SLOT( onPopupActivated( int ) ) );
269 if ( lst.count() > 1 )
271 pm->insertItem( tr( "Split vertically" ), SplitVertical );
272 pm->insertItem( tr( "Split horizontally" ), SplitHorizontal );
273 pm->insertSeparator();
275 pm->insertItem( tr( "Close" ), Close );
282 void QtxWorkstack::childEvent( QChildEvent* e )
284 if ( e->inserted() && e->child()->isWidgetType() )
286 QWidget* w = (QWidget*)e->child();
287 if ( w && w != mySplit )
289 targetArea()->insertWidget( w );
293 QWidget::childEvent( e );
296 void QtxWorkstack::customEvent( QCustomEvent* e )
301 QSplitter* QtxWorkstack::splitter( QtxWorkstackArea* area ) const
306 QSplitter* split = 0;
308 QWidget* wid = area->parentWidget();
309 if ( wid && wid->inherits( "QSplitter" ) )
310 split = (QSplitter*)wid;
315 void QtxWorkstack::splitters( QSplitter* split, QPtrList<QSplitter>& splitList, const bool rec ) const
320 const QObjectList* objs = split->children();
323 for ( QObjectListIt it( *objs ); it.current(); ++it )
326 splitters( (QSplitter*)it.current(), splitList, rec );
327 if ( it.current()->inherits( "QSplitter" ) )
328 splitList.append( (QSplitter*)it.current() );
333 void QtxWorkstack::areas( QSplitter* split, QPtrList<QtxWorkstackArea>& areaList, const bool rec ) const
338 const QObjectList* objs = split->children();
341 for ( QObjectListIt it( *objs ); it.current(); ++it )
343 if ( it.current()->inherits( "QtxWorkstackArea" ) )
344 areaList.append( (QtxWorkstackArea*)it.current() );
345 else if ( rec && it.current()->inherits( "QSplitter" ) )
346 areas( (QSplitter*)it.current(), areaList, rec );
351 QtxWorkstackArea* QtxWorkstack::activeArea() const
356 QtxWorkstackArea* QtxWorkstack::targetArea()
358 QtxWorkstackArea* area = activeArea();
360 area = currentArea();
363 QPtrList<QtxWorkstackArea> lst;
364 areas( mySplit, lst );
365 if ( !lst.isEmpty() )
370 area = createArea( mySplit );
375 QtxWorkstackArea* QtxWorkstack::currentArea() const
377 QtxWorkstackArea* area = 0;
378 QWidget* wid = focusWidget();
379 while ( wid && !area )
381 if ( wid->inherits( "QtxWorkstackArea" ) )
382 area = (QtxWorkstackArea*)wid;
383 wid = wid->parentWidget();
389 QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const
391 QtxWorkstackArea* area = new QtxWorkstackArea( parent );
393 connect( area, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
394 connect( area, SIGNAL( activated( QWidget* ) ), this, SLOT( onWindowActivated( QWidget* ) ) );
395 connect( area, SIGNAL( contextMenuRequested( QPoint ) ), this, SLOT( onContextMenuRequested( QPoint ) ) );
396 connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) );
401 void QtxWorkstack::setActiveArea( QtxWorkstackArea* area )
403 QWidget* oldCur = myWin;
405 QtxWorkstackArea* oldArea = myArea;
409 if ( myArea != oldArea )
412 oldArea->updateActiveState();
414 myArea->updateActiveState();
418 myWin = myArea->activeWidget();
420 if ( myWin && oldCur != myWin )
421 emit windowActivated( myWin );
424 QtxWorkstackArea* QtxWorkstack::neighbourArea( QtxWorkstackArea* area ) const
426 QPtrList<QtxWorkstackArea> lst;
427 areas( mySplit, lst, true );
428 int pos = lst.find( area );
432 QtxWorkstackArea* na = 0;
433 for ( int i = pos - 1; i >= 0 && !na; i-- )
435 if ( !lst.at( i )->isEmpty() )
439 for ( int j = pos + 1; j < (int)lst.count() && !na; j++ )
441 if ( !lst.at( j )->isEmpty() )
447 QtxWorkstackArea* QtxWorkstack::areaAt( const QPoint& p ) const
449 QtxWorkstackArea* area = 0;
450 QPtrList<QtxWorkstackArea> lst;
451 areas( mySplit, lst, true );
452 for ( QPtrListIterator<QtxWorkstackArea> it( lst ); it.current() && !area; ++it )
454 QtxWorkstackArea* cur = it.current();
455 QRect r = cur->geometry();
456 if ( cur->parentWidget() )
457 r = QRect( cur->parentWidget()->mapToGlobal( r.topLeft() ), r.size() );
458 if ( r.contains( p ) )
464 void QtxWorkstack::updateState()
466 updateState( mySplit );
469 void QtxWorkstack::updateState( QSplitter* split )
471 QPtrList<QSplitter> recList;
472 splitters( split, recList, false );
473 for ( QPtrListIterator<QSplitter> itr( recList ); itr.current(); ++itr )
474 updateState( itr.current() );
476 QPtrList<QSplitter> splitList;
477 splitters( split, splitList, false );
479 QPtrList<QtxWorkstackArea> areaList;
480 areas( split, areaList, false );
483 for ( QPtrListIterator<QtxWorkstackArea> it( areaList ); it.current(); ++it )
485 if ( it.current()->isEmpty() )
486 it.current()->hide();
489 it.current()->show();
494 if ( split == mySplit )
497 for ( QPtrListIterator<QSplitter> iter( splitList ); iter.current() && !vis; ++iter )
498 vis = iter.current()->isVisibleTo( iter.current()->parentWidget() );
500 if ( areaList.isEmpty() && splitList.isEmpty() )
509 Class: QtxWorkstackArea [Internal]
513 QtxWorkstackArea::QtxWorkstackArea( QWidget* parent )
516 QVBoxLayout* base = new QVBoxLayout( this );
518 QHBox* top = new QHBox( this );
519 base->addWidget( top );
521 myBar = new QtxWorkstackTabBar( top );
523 QPushButton* close = new QPushButton( top );
524 close->setPixmap( style().stylePixmap( QStyle::SP_TitleBarCloseButton ) );
525 close->setAutoDefault( true );
526 close->setFlat( true );
529 top->setStretchFactor( myBar, 1 );
531 myStack = new QWidgetStack( this );
533 base->addWidget( myStack, 1 );
535 connect( myClose, SIGNAL( clicked() ), this, SLOT( onClose() ) );
536 connect( myBar, SIGNAL( selected( int ) ), this, SLOT( onSelected( int ) ) );
537 connect( myBar, SIGNAL( dragActiveTab() ), this, SLOT( onDragActiveTab() ) );
538 connect( myBar, SIGNAL( contextMenuRequested( QPoint ) ), this, SIGNAL( contextMenuRequested( QPoint ) ) );
544 qApp->installEventFilter( this );
547 QtxWorkstackArea::~QtxWorkstackArea()
549 qApp->removeEventFilter( this );
552 bool QtxWorkstackArea::isEmpty() const
555 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it )
560 void QtxWorkstackArea::insertWidget( QWidget* wid, const int idx )
565 int pos = myList.find( wid );
566 if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) )
569 myList.removeRef( wid );
570 pos = idx < 0 ? myList.count() : idx;
571 myList.insert( QMIN( pos, (int)myList.count() ), wid );
572 if ( !myInfo.contains( wid ) )
574 QtxWorkstackChild* child = new QtxWorkstackChild( wid, myStack );
575 myChild.insert( wid, child );
576 myInfo.insert( wid, WidgetInfo() );
577 myInfo[wid].id = generateId();
578 myInfo[wid].vis = wid->isVisibleTo( wid->parentWidget() );
580 connect( child, SIGNAL( destroyed( QObject* ) ), this, SLOT( onChildDestroyed( QObject* ) ) );
581 connect( child, SIGNAL( shown( QtxWorkstackChild* ) ), this, SLOT( onChildShown( QtxWorkstackChild* ) ) );
582 connect( child, SIGNAL( hided( QtxWorkstackChild* ) ), this, SLOT( onChildHided( QtxWorkstackChild* ) ) );
583 connect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) );
584 connect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) );
589 setWidgetActive( wid );
592 void QtxWorkstackArea::removeWidget( QWidget* wid )
594 if ( !myList.contains( wid ) )
597 if ( myBar->tab( widgetId( wid ) ) )
598 myBar->removeTab( myBar->tab( widgetId( wid ) ) );
599 myStack->removeWidget( child( wid ) );
601 myList.remove( wid );
602 myInfo.remove( wid );
603 myChild.remove( wid );
607 if ( myList.isEmpty() )
613 QWidgetList QtxWorkstackArea::widgetList() const
616 for ( QWidgetListIt it( myList ); it.current(); ++it )
618 if ( widgetVisibility( it.current() ) )
619 lst.append( it.current() );
624 QWidget* QtxWorkstackArea::activeWidget() const
626 return widget( myBar->currentTab() );
629 void QtxWorkstackArea::setActiveWidget( QWidget* wid )
631 myBar->setCurrentTab( widgetId( wid ) );
634 bool QtxWorkstackArea::contains( QWidget* wid ) const
636 return myList.contains( wid );
639 void QtxWorkstackArea::show()
641 QMap<QWidget*, bool> map;
642 for ( QWidgetListIt it( myList ); it.current(); ++it )
644 map.insert( it.current(), isBlocked( it.current() ) );
645 setBlocked( it.current(), true );
650 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
651 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
654 void QtxWorkstackArea::hide()
656 QMap<QWidget*, bool> map;
657 for ( QWidgetListIt it( myList ); it.current(); ++it )
659 map.insert( it.current(), isBlocked( it.current() ) );
660 setBlocked( it.current(), true );
665 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
666 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
669 bool QtxWorkstackArea::isActive() const
671 QtxWorkstack* ws = workstack();
675 return ws->activeArea() == this;
678 void QtxWorkstackArea::updateActiveState()
680 myBar->setActive( isActive() );
683 QtxWorkstack* QtxWorkstackArea::workstack() const
685 QtxWorkstack* ws = 0;
686 QWidget* wid = parentWidget();
689 if ( wid->inherits( "QtxWorkstack" ) )
690 ws = (QtxWorkstack*)wid;
691 wid = wid->parentWidget();
696 bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e )
698 if ( o->isWidgetType() )
700 QWidget* wid = (QWidget*)o;
701 if ( e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress )
704 while ( !ok && wid && wid != myClose )
707 wid = wid->parentWidget();
710 QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)( e->type() == QEvent::FocusIn ? ActivateWidget : FocusWidget ) ) );
716 QRect QtxWorkstackArea::floatRect() const
718 QRect r = myStack->geometry();
719 return QRect( mapToGlobal( r.topLeft() ), mapToGlobal( r.bottomRight() ) );
722 QRect QtxWorkstackArea::floatTab( const int idx ) const
724 return myBar->tabRect( idx );
727 int QtxWorkstackArea::tabAt( const QPoint& p ) const
730 for ( int i = 0; i < myBar->count() && idx == -1; i++ )
732 QRect r = myBar->tabRect( i );
733 if ( r.isValid() && r.contains( p ) )
739 void QtxWorkstackArea::customEvent( QCustomEvent* e )
744 emit activated( activeWidget() );
747 if ( activeWidget() && !activeWidget()->focusWidget() )
748 activeWidget()->setFocus();
751 removeWidget( (QWidget*)e->data() );
756 void QtxWorkstackArea::focusInEvent( QFocusEvent* e )
758 QWidget::focusInEvent( e );
760 emit activated( activeWidget() );
763 void QtxWorkstackArea::mousePressEvent( QMouseEvent* e )
765 QWidget::mousePressEvent( e );
767 emit activated( activeWidget() );
770 void QtxWorkstackArea::onClose()
772 QWidget* wid = activeWidget();
777 void QtxWorkstackArea::onSelected( int id )
781 emit activated( activeWidget() );
784 void QtxWorkstackArea::onDragActiveTab()
786 QtxWorkstackChild* c = child( activeWidget() );
790 new QtxWorkstackDrag( workstack(), c );
793 void QtxWorkstackArea::onChildDestroyed( QObject* obj )
795 QtxWorkstackChild* child = (QtxWorkstackChild*)obj;
796 myStack->removeWidget( child );
799 for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it )
801 if ( it.data() == child )
805 myChild.remove( wid );
807 QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)RemoveWidget, wid ) );
810 void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c )
812 setWidgetShown( c->widget(), true );
815 void QtxWorkstackArea::onChildHided( QtxWorkstackChild* c )
817 setWidgetShown( c->widget(), false );
820 void QtxWorkstackArea::onChildActivated( QtxWorkstackChild* c )
822 setWidgetActive( c->widget() );
825 void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c )
827 updateTab( c->widget() );
830 void QtxWorkstackArea::updateCurrent()
832 QMap<QWidget*, bool> map;
833 for ( QWidgetListIt it( myList ); it.current(); ++it )
835 map.insert( it.current(), isBlocked( it.current() ) );
836 setBlocked( it.current(), true );
839 myStack->raiseWidget( myBar->currentTab() );
841 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
842 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
845 void QtxWorkstackArea::updateTab( QWidget* wid )
847 QTab* tab = myBar->tab( widgetId( wid ) );
853 icoSet = QIconSet( *wid->icon() );
855 tab->setIconSet( icoSet );
856 tab->setText( wid->caption() );
859 QWidget* QtxWorkstackArea::widget( const int id ) const
862 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !wid; ++it )
864 if ( it.data().id == id )
870 int QtxWorkstackArea::widgetId( QWidget* wid ) const
873 if ( myInfo.contains( wid ) )
878 bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const
881 if ( myInfo.contains( wid ) )
882 res = myInfo[wid].vis;
886 void QtxWorkstackArea::setWidgetActive( QWidget* wid )
888 int id = widgetId( wid );
892 myBar->setCurrentTab( id );
895 void QtxWorkstackArea::setWidgetShown( QWidget* wid, const bool on )
897 if ( isBlocked( wid ) || !myInfo.contains( wid ) || myInfo[wid].vis == on )
900 myInfo[wid].vis = on;
904 void QtxWorkstackArea::updateState()
906 bool updBar = myBar->isUpdatesEnabled();
907 bool updStk = myStack->isUpdatesEnabled();
908 myBar->setUpdatesEnabled( false );
909 myStack->setUpdatesEnabled( false );
911 bool block = myBar->signalsBlocked();
912 myBar->blockSignals( true );
914 QWidget* prev = activeWidget();
917 for ( QWidgetListIt it( myList ); it.current(); ++it )
919 QWidget* wid = it.current();
920 int id = widgetId( wid );
925 bool vis = widgetVisibility( wid );
927 if ( myBar->tab( id ) && ( !vis || myBar->indexOf( id ) != idx ) )
928 myBar->removeTab( myBar->tab( id ) );
930 if ( !myBar->tab( id ) && vis )
932 QTab* tab = new QTab( wid->caption() );
933 myBar->insertTab( tab, idx );
934 tab->setIdentifier( id );
939 bool block = isBlocked( wid );
940 setBlocked( wid, true );
942 QtxWorkstackChild* cont = child( wid );
945 myStack->removeWidget( cont );
946 else if ( !myStack->widget( id ) )
947 myStack->addWidget( cont, id );
952 setBlocked( wid, block );
955 int curId = widgetId( prev );
956 if ( !myBar->tab( curId ) )
959 int pos = myList.find( prev );
960 for ( int i = pos - 1; i >= 0 && !wid; i-- )
962 if ( widgetVisibility( myList.at( i ) ) )
963 wid = myList.at( i );
966 for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ )
968 if ( widgetVisibility( myList.at( j ) ) )
969 wid = myList.at( j );
973 curId = widgetId( wid );
976 myBar->setCurrentTab( curId );
978 myBar->blockSignals( block );
982 myBar->setUpdatesEnabled( updBar );
983 myStack->setUpdatesEnabled( updStk );
989 QResizeEvent re( myBar->size(), myBar->size() );
990 QApplication::sendEvent( myBar, &re );
995 emit deactivated( this );
1000 if ( prev != activeWidget() )
1001 emit activated( activeWidget() );
1005 int QtxWorkstackArea::generateId() const
1009 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end(); ++it )
1010 map.insert( it.data().id, 0 );
1013 while ( map.contains( id ) )
1019 bool QtxWorkstackArea::isBlocked( QWidget* wid ) const
1021 return myBlock.contains( wid );
1024 void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on )
1027 myBlock.insert( wid, 0 );
1029 myBlock.remove( wid );
1032 QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const
1034 QtxWorkstackChild* res = 0;
1035 if ( myChild.contains( wid ) )
1041 Class: QtxWorkstackChild [Internal]
1045 QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent )
1049 myWidget->reparent( this, QPoint( 0, 0 ), myWidget->isVisibleTo( myWidget->parentWidget() ) );
1050 myWidget->installEventFilter( this );
1052 connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1055 QtxWorkstackChild::~QtxWorkstackChild()
1057 qApp->removeEventFilter( this );
1062 widget()->removeEventFilter( this );
1063 widget()->reparent( 0, QPoint( 0, 0 ), false );
1064 disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1067 QWidget* QtxWorkstackChild::widget() const
1072 bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e )
1074 if ( o->isWidgetType() )
1076 if ( e->type() == QEvent::CaptionChange || e->type() == QEvent::IconChange )
1077 emit captionChanged( this );
1079 if ( !e->spontaneous() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
1082 if ( !e->spontaneous() && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) )
1085 if ( e->type() == QEvent::FocusIn )
1086 emit activated( this );
1088 return QHBox::eventFilter( o, e );
1091 void QtxWorkstackChild::onDestroyed( QObject* obj )
1093 if ( obj != widget() )
1100 void QtxWorkstackChild::childEvent( QChildEvent* e )
1102 if ( e->type() == QEvent::ChildRemoved && e->child() == widget() )
1107 QHBox::childEvent( e );
1111 Class: QtxWorkstackTabBar [Internal]
1115 QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent )
1116 : QTabBar( parent ),
1121 QtxWorkstackTabBar::~QtxWorkstackTabBar()
1125 void QtxWorkstackTabBar::setActive( const bool on )
1127 QFont aFont = font();
1128 aFont.setUnderline( on );
1134 QRect QtxWorkstackTabBar::tabRect( const int idx ) const
1137 QTab* t = tabAt( idx );
1141 r.setLeft( QMAX( r.left(), 0 ) );
1143 int x1 = tabAt( 0 )->rect().left();
1144 int x2 = tabAt( count() - 1 )->rect().right();
1147 if ( QABS( x2 - x1 ) > width() )
1148 #if defined QT_VERSION && QT_VERSION >= 0x30300
1149 bw = 2 * style().pixelMetric( QStyle::PM_TabBarScrollButtonWidth, this );
1154 int limit = width() - bw;
1155 r.setRight( QMIN( r.right(), limit ) );
1157 r = QRect( mapToGlobal( r.topLeft() ), r.size() );
1162 void QtxWorkstackTabBar::mouseMoveEvent( QMouseEvent* e )
1164 if ( myId != -1 && !tab( myId )->rect().contains( e->pos() ) )
1167 emit dragActiveTab();
1170 QTabBar::mouseMoveEvent( e );
1173 void QtxWorkstackTabBar::mousePressEvent( QMouseEvent* e )
1175 QTabBar::mousePressEvent( e );
1177 if ( e->button() == LeftButton )
1178 myId = currentTab();
1181 void QtxWorkstackTabBar::mouseReleaseEvent( QMouseEvent* e )
1183 QTabBar::mouseReleaseEvent( e );
1187 if ( e->button() == RightButton )
1188 emit contextMenuRequested( e->globalPos() );
1191 void QtxWorkstackTabBar::contextMenuEvent( QContextMenuEvent* e )
1193 if ( e->reason() != QContextMenuEvent::Mouse )
1194 emit contextMenuRequested( e->globalPos() );
1197 void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
1199 if ( currentTab() != t->identifier() )
1201 QFont fnt = p->font();
1202 fnt.setUnderline( false );
1205 QTabBar::paintLabel( p, br, t, has_focus );
1209 Class: QtxWorkstackDrag [Internal]
1213 QtxWorkstackDrag::QtxWorkstackDrag( QtxWorkstack* ws, QtxWorkstackChild* child )
1221 qApp->installEventFilter( this );
1224 QtxWorkstackDrag::~QtxWorkstackDrag()
1226 qApp->removeEventFilter( this );
1231 bool QtxWorkstackDrag::eventFilter( QObject*, QEvent* e )
1233 switch ( e->type() )
1235 case QEvent::MouseMove:
1236 updateTarget( ((QMouseEvent*)e)->globalPos() );
1238 case QEvent::MouseButtonRelease:
1250 void QtxWorkstackDrag::updateTarget( const QPoint& p )
1253 QtxWorkstackArea* area = detectTarget( p, tab );
1254 setTarget( area, tab );
1257 QtxWorkstackArea* QtxWorkstackDrag::detectTarget( const QPoint& p, int& tab ) const
1262 QtxWorkstackArea* area = myWS->areaAt( p );
1264 tab = area->tabAt( p );
1268 void QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab )
1270 if ( !area || ( myArea == area && tab == myTab ) )
1285 void QtxWorkstackDrag::dropWidget()
1288 myArea->insertWidget( myChild->widget(), myTab );
1291 void QtxWorkstackDrag::drawRect()
1293 if ( !myPainter || !myArea )
1296 QRect r = myArea->floatRect();
1297 int m = myPainter->pen().width();
1299 r.setTop( r.top() + m + 2 );
1300 r.setLeft( r.left() + m + 2 );
1301 r.setRight( r.right() - m - 2 );
1302 r.setBottom( r.bottom() - m - 2 );
1304 myPainter->drawRect( r );
1306 QRect tr = myArea->floatTab( myTab );
1307 tr.setTop( tr.top() + m );
1308 tr.setLeft( tr.left() + m );
1309 tr.setRight( tr.right() - m );
1310 tr.setBottom( tr.bottom() - m );
1312 myPainter->drawRect( tr );
1315 void QtxWorkstackDrag::endDrawRect()
1321 void QtxWorkstackDrag::startDrawRect()
1326 int scr = QApplication::desktop()->screenNumber( (QWidget*)this );
1327 QWidget* paint_on = QApplication::desktop()->screen( scr );
1329 myPainter = new QPainter( paint_on, true );
1330 myPainter->setPen( QPen( gray, 3 ) );
1331 myPainter->setRasterOp( XorROP );