1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/
19 // File: QtxWorkstack.cxx
20 // Author: Sergey TELKOV
22 #include "QtxWorkstack.h"
31 #include <qsplitter.h>
32 #include <qpopupmenu.h>
33 #include <qobjectlist.h>
34 #include <qpushbutton.h>
35 #include <qwidgetstack.h>
36 #include <qapplication.h>
37 #include <qinputdialog.h>
40 Class: QtxWorkstack [Public]
44 QtxWorkstack::QtxWorkstack( QWidget* parent )
50 myActionsMap.insert( SplitVertical, new QAction( tr( "Split vertically" ), 0, this ) );
51 myActionsMap.insert( SplitHorizontal, new QAction( tr( "Split horizontally" ), 0, this ) );
52 myActionsMap.insert( Close, new QAction( tr( "Close" ), 0, this ) );
53 myActionsMap.insert( Rename, new QAction( tr( "Rename" ), 0, this ) );
55 connect( myActionsMap[SplitVertical], SIGNAL( activated() ), this, SLOT( splitVertical() ) );
56 connect( myActionsMap[SplitHorizontal], SIGNAL( activated() ), this, SLOT( splitHorizontal() ) );
57 connect( myActionsMap[Close], SIGNAL( activated() ), this, SLOT( onCloseWindow() ) );
58 connect( myActionsMap[Rename], SIGNAL( activated() ), this, SLOT( onRename() ) );
60 QVBoxLayout* base = new QVBoxLayout( this );
61 mySplit = new QSplitter( this );
62 mySplit->setChildrenCollapsible( false );
63 base->addWidget( mySplit );
66 QtxWorkstack::~QtxWorkstack()
70 QWidgetList QtxWorkstack::windowList() const
72 QPtrList<QtxWorkstackArea> lst;
73 areas( mySplit, lst, true );
76 for ( QPtrListIterator<QtxWorkstackArea> it( lst ); it.current(); ++it )
78 QWidgetList wids = it.current()->widgetList();
79 for ( QWidgetListIt itr( wids ); itr.current(); ++itr )
80 widList.append( itr.current() );
86 QWidgetList QtxWorkstack::splitWindowList() const
88 return myArea ? myArea->widgetList() : QWidgetList();
91 QWidget* QtxWorkstack::activeWindow() const
96 void QtxWorkstack::split( const int o )
98 QtxWorkstackArea* area = activeArea();
102 if ( area->widgetList().count() < 2 )
105 QWidget* curWid = area->activeWidget();
109 QSplitter* s = splitter( area );
110 QPtrList<QtxWorkstackArea> areaList;
111 areas( s, areaList );
113 QPtrList<QSplitter> splitList;
114 splitters( s, splitList );
117 if ( areaList.count() + splitList.count() < 2 || s->orientation() == o )
121 trg = wrapSplitter( area );
126 trg->setOrientation( (Orientation)o );
128 QtxWorkstackArea* newArea = createArea( 0 );
129 insertWidget( newArea, trg, area );
131 area->removeWidget( curWid );
132 newArea->insertWidget( curWid );
134 distributeSpace( trg );
141 * \brief Split workarea of the given widget on two parts.
142 * \param wid - widget, belonging to this workstack
143 * \param o - orientation of splitting (Qt::Horizontal or Qt::Vertical)
144 * \param type - type of splitting, see <VAR>SplitType</VAR> enumeration
146 void QtxWorkstack::Split (QWidget* wid, const Qt::Orientation o, const SplitType type)
150 // find area of the given widget
151 QtxWorkstackArea* area = NULL;
152 QPtrList<QtxWorkstackArea> allAreas;
153 areas(mySplit, allAreas, true);
155 QPtrListIterator<QtxWorkstackArea> it (allAreas);
156 for (; it.current() && !area; ++it) {
157 if (it.current()->contains(wid))
162 QWidgetList wids = area->widgetList();
163 if (wids.count() < 2)
166 QSplitter* s = splitter(area);
167 QPtrList<QtxWorkstackArea> areaList;
170 QPtrList<QSplitter> splitList;
171 splitters(s, splitList);
174 if (areaList.count() + splitList.count() < 2 || s->orientation() == o)
177 if (!trg) trg = wrapSplitter(area);
180 trg->setOrientation(o);
182 QtxWorkstackArea* newArea = createArea(0);
183 insertWidget(newArea, trg, area);
188 QWidgetListIt itr (wids);
189 for (; itr.current(); ++itr)
191 QWidget* wid_i = itr.current();
193 area->removeWidget(wid_i);
194 newArea->insertWidget(wid_i);
201 QWidgetListIt itr (wids);
202 for (; itr.current() && itr.current() != wid; ++itr) {
204 for (; itr.current(); ++itr) {
205 area->removeWidget(itr.current());
206 newArea->insertWidget(itr.current());
211 area->removeWidget(wid);
212 newArea->insertWidget(wid);
216 distributeSpace(trg);
220 * \brief Put given widget on top of its workarea
221 * \param wid - widget, belonging to this workstack
224 void QtxWorkstack::OnTop (QWidget* wid)
229 // find area of the given widget
230 QtxWorkstackArea* area = 0;
231 QPtrList<QtxWorkstackArea> allAreas;
232 areas( mySplit, allAreas, true );
233 for ( QPtrListIterator<QtxWorkstackArea> it( allAreas ); it.current() && !area; ++it )
235 if ( it.current()->contains( wid ) )
240 area->setActiveWidget( wid );
245 * \brief Move widget(s) from source workarea into target workarea
246 * or just reorder widgets inside one workarea.
247 * \param wid1 - widget from target workarea
248 * \param wid2 - widget from source workarea
249 * \param all - if this parameter is TRUE, all widgets from source workarea will
250 * be moved into the target one, else only the \a wid2 will be moved
252 * Move \a wid2 in target workarea. Put it right after \a wid1.
253 * If value of boolean argument is TRUE, all widgets from source workarea
254 * will be moved together with \a wid2, source workarea will be deleted.
255 * If \a wid1 and \a wid2 belongs to one workarea, simple reordering will take place.
257 void QtxWorkstack::Attract ( QWidget* wid1, QWidget* wid2, const bool all )
259 if ( !wid1 || !wid2 )
262 // find area of the widgets
263 QtxWorkstackArea *area1 = NULL, *area2 = NULL;
264 QPtrList<QtxWorkstackArea> allAreas;
265 areas(mySplit, allAreas, true);
266 QPtrListIterator<QtxWorkstackArea> it (allAreas);
267 for (; it.current() && !(area1 && area2); ++it) {
268 if (it.current()->contains(wid1))
269 area1 = it.current();
270 if (it.current()->contains(wid2))
271 area2 = it.current();
273 if (!area1 || !area2) return;
275 QWidget* curWid = area1->activeWidget();
278 if (area1 == area2) {
280 // Set wid1 at first position, wid2 at second
281 area1->insertWidget(wid1);
282 area1->insertWidget(wid2, 1);
284 // Set wid2 right after wid1
285 area1->removeWidget(wid2);
287 QWidgetList wids1 = area1->widgetList();
288 QWidgetListIt itr1 (wids1);
289 for (; itr1.current() && itr1.current() != wid1; ++itr1, ++wid1_ind);
290 area1->insertWidget(wid2, wid1_ind + 1);
294 QWidgetList wids1 = area1->widgetList();
295 QWidgetListIt itr1 (wids1);
296 for (; itr1.current() && itr1.current() != wid1; ++itr1, ++wid1_ind);
299 // Set wid2 right after wid1, other widgets from area2 right after wid2
300 QWidgetList wids2 = area2->widgetList();
301 QWidgetListIt itr2 (wids2);
302 for (int ind = wid1_ind + 1; itr2.current(); ++itr2, ++ind)
304 area2->removeWidget(itr2.current());
305 if (itr2.current() == wid2) {
306 area1->insertWidget(itr2.current(), wid1_ind + 1);
308 area1->insertWidget(itr2.current(), ind);
312 // Set wid2 right after wid1
313 area2->removeWidget(wid2);
314 area1->insertWidget(wid2, wid1_ind + 1);
318 area1->setActiveWidget( curWid );
321 static void setSizes (QIntList& szList, const int item_ind,
322 const int new_near, const int new_this, const int new_farr)
324 // set size to all items before an item # <item_ind>
326 QIntList::iterator its = szList.begin();
327 for (; its != szList.end() && cur_pos < item_ind; ++its, ++cur_pos) {
330 if (its == szList.end()) return;
331 // set size to item # <item_ind>
334 // set size to all items after an item # <item_ind>
335 for (; its != szList.end(); ++its) {
341 * \brief Set position of the widget relatively its splitter.
342 * \param wid - widget to set position of
343 * \param pos - position relatively splitter. Value in range [0..1].
345 * Orientation of positioning will correspond to the splitter orientation.
347 void QtxWorkstack::SetRelativePositionInSplitter( QWidget* wid, const double position )
349 if ( position < 0.0 || 1.0 < position)
355 // find area of the given widget
356 QtxWorkstackArea* area = NULL;
357 QPtrList<QtxWorkstackArea> allAreas;
358 areas(mySplit, allAreas, true);
359 for ( QPtrListIterator<QtxWorkstackArea> it( allAreas );
360 it.current() && !area;
363 if (it.current()->contains(wid))
370 QSplitter* split = splitter( area );
374 // find index of the area in its splitter
376 bool isFound = false;
377 const QObjectList* was = split->children();
378 for (QObjectListIt ito (*was); ito.current() && !isFound; ++ito, ++item_ind)
380 if (ito.current() == area)
383 if (!isFound || item_ind == 0)
386 QIntList szList = split->sizes();
387 int splitter_size = (split->orientation() == Horizontal ?
388 split->width() : split->height());
389 int nb = szList.count();
391 int new_prev = int(splitter_size * position / item_ind);
392 int new_next = int(splitter_size * (1.0 - position) / (nb - item_ind));
393 setSizes (szList, item_ind, new_prev, new_next, new_next);
394 split->setSizes(szList);
398 * \brief Set position of the widget relatively the entire workstack.
399 * \param wid - widget to set position of
400 * \param o - orientation of positioning (Qt::Horizontal or Qt::Vertical).
401 * If o = Qt::Horizontal, horizontal position of \a wid will be changed.
402 * If o = Qt::Vertical, vertical position of \a wid will be changed.
403 * \param pos - position relatively workstack. Value in range [0..1].
405 void QtxWorkstack::SetRelativePosition( QWidget* wid, const Qt::Orientation o,
406 const double position )
408 if ( position < 0.0 || 1.0 < position )
414 int splitter_size = o == Horizontal ? mySplit->width() : mySplit->height();
415 int need_pos = int( position * splitter_size );
416 int splitter_pos = 0;
418 if ( setPosition( wid, mySplit, o, need_pos, splitter_pos ) != 0 )
420 // impossible to set required position
425 * \brief Sets the action's accelerator key to accel.
426 * \param id - the key of the action in the actions map.
427 * \param accel - action's accelerator key.
429 void QtxWorkstack::setAccel( const int id, const int accel )
431 if ( !myActionsMap.contains( id ) )
434 myActionsMap[id]->setAccel( accel );
438 * \brief Returns the action's accelerator key.
439 * \param id - the key of the action in the actions map.
440 * \retval int - action's accelerator key.
442 int QtxWorkstack::accel( const int id ) const
445 if ( myActionsMap.contains( id ) )
446 res = myActionsMap[id]->accel();
450 static int positionSimple (QIntList& szList, const int nb, const int splitter_size,
451 const int item_ind, const int item_rel_pos,
452 const int need_pos, const int splitter_pos)
454 if (item_ind == 0) { // cannot move in this splitter
455 return (need_pos - splitter_pos);
460 int new_this = szList[item_ind];
463 bool isToCheck = false;
465 if (need_pos < splitter_pos) {
466 // Set size of all previous workareas to zero <--
467 if (item_ind == nb - 1) {
468 // item iz last in the splitter, it will occupy all the splitter
469 new_this = splitter_size;
471 // recompute size of next items in splitter
472 new_next = (splitter_size - new_this) / (nb - item_ind - 1);
474 delta = need_pos - splitter_pos;
476 } else if (need_pos > (splitter_pos + splitter_size)) {
477 // Set size of all next workareas to zero -->
478 // recompute size of previous items in splitter
480 new_prev = (splitter_size - new_this) / item_ind;
481 delta = need_pos - (splitter_pos + splitter_size - new_this);
483 } else { // required position lays inside this splitter
484 // Move workarea inside splitter into required position <->
485 int new_item_rel_pos = need_pos - splitter_pos;
486 new_prev = new_item_rel_pos / item_ind;
487 if (need_pos < (splitter_pos + item_rel_pos)) {
488 // Make previous workareas smaller, next - bigger
489 // No problem to keep old size of the widget
491 // Make previous workareas bigger, next - smaller
492 if (new_this > splitter_size - new_item_rel_pos) {
493 new_this = splitter_size - new_item_rel_pos;
495 // jfa to do: in this case fixed size of next widgets could prevent right resizing
498 if (item_ind == nb - 1) {
499 new_this = splitter_size - new_item_rel_pos;
501 new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
506 setSizes (szList, item_ind, new_prev, new_this, new_next);
511 * \brief Set position of given widget.
512 * \param wid - widget to be moved
513 * \param split - currently processed splitter (goes from more common
514 * to more particular splitter in recursion calls)
515 * \param o - orientation of positioning
516 * \param need_pos - required position of the given widget in pixels
517 * (from top/left side of workstack area)
518 * \param splitter_pos - position of the splitter \a split
519 * (from top/left side of workstack area)
520 * \retval int - returns difference between a required and a distinguished position.
522 * Internal method. Recursively calls itself.
523 * Is called from <VAR>SetRelativePosition</VAR> public method.
525 int QtxWorkstack::setPosition( QWidget* wid, QSplitter* split, const Qt::Orientation o,
526 const int need_pos, const int splitter_pos )
528 if ( !wid || !split )
529 return need_pos - splitter_pos;
531 // Find corresponding sub-splitter.
532 // Find also index of appropriate item in current splitter.
533 int cur_ind = 0, item_ind = 0;
534 bool isBottom = false, isFound = false;
535 QSplitter* sub_split = NULL;
536 const QObjectList* objs = split->children();
539 for (QObjectListIt it (*objs); it.current() && !isFound; ++it)
541 if (it.current()->inherits( "QtxWorkstackArea")) {
542 if (((QtxWorkstackArea*)it.current())->contains(wid)) {
548 } else if (it.current()->inherits("QSplitter")) {
549 QPtrList<QtxWorkstackArea> areaList;
550 areas((QSplitter*)it.current(), areaList, true);
551 for (QPtrListIterator<QtxWorkstackArea> ita (areaList);
552 ita.current() && !isFound;
555 if (ita.current()->contains(wid)) {
558 sub_split = (QSplitter*)it.current();
566 return (need_pos - splitter_pos);
568 if (split->orientation() == o) {
569 // Find coordinates of near and far sides of the appropriate item relatively current splitter
570 int splitter_size = (o == Horizontal ? split->width() : split->height());
571 QIntList szList = split->sizes();
572 int nb = szList.count();
573 int item_rel_pos = 0; // position of near side of item relatively this splitter
574 for (int i = 0; i < item_ind; i++) {
575 item_rel_pos += szList[i];
577 int item_size = szList[item_ind]; // size of item
578 int item_pos = splitter_pos + item_rel_pos;
580 // Resize splitter items to complete the conditions
582 // I. Bottom of splitters stack reached
584 int delta = positionSimple(szList, nb, splitter_size, item_ind, item_rel_pos, need_pos, splitter_pos);
585 split->setSizes(szList);
586 // Recompute delta, as some windows can reject given size
587 int new_item_rel_pos = 0;
588 QIntList szList1 = split->sizes();
589 for (int i = 0; i < item_ind; i++) {
590 new_item_rel_pos += szList1[i];
592 delta = need_pos - (splitter_pos + new_item_rel_pos);
596 // II. Bottom of splitters stack is not yet reached
598 if (item_ind == 0) { // cannot move in this splitter
599 // Process in sub-splitter
600 return setPosition(wid, sub_split, o, need_pos, splitter_pos);
604 int new_this = szList[item_ind];
607 if (need_pos < splitter_pos) {
608 // Set size of all previous workareas to zero <--
609 if (item_ind == nb - 1) {
610 new_this = splitter_size;
612 new_next = (splitter_size - new_this) / (nb - item_ind - 1);
614 setSizes (szList, item_ind, new_prev, new_this, new_next);
615 split->setSizes(szList);
616 // Recompute splitter_pos, as some windows can reject given size
617 int new_item_rel_pos = 0;
618 QIntList szList1 = split->sizes();
619 for (int i = 0; i < item_ind; i++) {
620 new_item_rel_pos += szList1[i];
622 // Process in sub-splitter
623 return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
624 } else if (need_pos > (splitter_pos + splitter_size)) {
625 // Set size of all next workareas to zero -->
626 new_prev = (splitter_size - new_this) / item_ind;
627 setSizes (szList, item_ind, new_prev, new_this, new_next);
628 split->setSizes(szList);
629 // Recompute splitter_pos, as some windows can reject given size
630 int new_item_rel_pos = 0;
631 QIntList szList1 = split->sizes();
632 for (int i = 0; i < item_ind; i++) {
633 new_item_rel_pos += szList1[i];
635 // Process in sub-splitter
636 return setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
638 // Set appropriate size of all previous/next items <->
639 int new_item_rel_pos = item_rel_pos;
640 if (need_pos < item_pos || (item_pos + item_size) < need_pos) {
641 // Move item inside splitter into required position <->
642 int new_this = szList[item_ind];
644 new_item_rel_pos = need_pos - splitter_pos;
645 if ((item_pos + item_size) < need_pos) {
646 //new_item_rel_pos = need_pos - (item_pos + item_size);
647 new_item_rel_pos = item_rel_pos + (need_pos - (item_pos + item_size));
649 int new_prev = new_item_rel_pos / item_ind;
650 if (need_pos < (splitter_pos + item_rel_pos)) {
651 // Make previous workareas smaller, next - bigger
652 // No problem to keep old size of the widget
654 // Make previous workareas bigger, next - smaller
655 if (new_this > splitter_size - new_item_rel_pos) {
656 new_this = splitter_size - new_item_rel_pos;
659 if (item_ind == nb - 1) {
660 new_this = splitter_size - new_item_rel_pos;
662 new_next = (splitter_size - new_item_rel_pos - new_this) / (nb - item_ind - 1);
664 setSizes (szList, item_ind, new_prev, new_this, new_next);
665 split->setSizes(szList);
666 // Recompute new_item_rel_pos, as some windows can reject given size
667 new_item_rel_pos = 0;
668 QIntList szList1 = split->sizes();
669 for (int i = 0; i < item_ind; i++) {
670 new_item_rel_pos += szList1[i];
675 // Process in sub-splitter
676 int add_pos = setPosition(wid, sub_split, o, need_pos, splitter_pos + new_item_rel_pos);
680 // this can be if corresponding workarea is first in sub-splitter
681 // or sub-splitter has another orientation
683 // Resize ones again to reach precize position <->
684 int need_pos_1 = splitter_pos + new_item_rel_pos + add_pos;
686 // Move workarea inside splitter into required position <->
687 int delta_1 = positionSimple(szList, nb, splitter_size, item_ind,
688 new_item_rel_pos, need_pos_1, splitter_pos);
689 split->setSizes(szList);
690 // Recompute new_item_rel_pos, as some windows can reject given size
691 new_item_rel_pos = 0;
692 QIntList szList1 = split->sizes();
693 for (int i = 0; i < item_ind; i++) {
694 new_item_rel_pos += szList1[i];
696 delta_1 = need_pos_1 - (splitter_pos + new_item_rel_pos);
701 return setPosition(wid, sub_split, o, need_pos, splitter_pos);
707 void QtxWorkstack::distributeSpace( QSplitter* split ) const
712 QIntList szList = split->sizes();
713 int size = ( split->orientation() == Horizontal ?
714 split->width() : split->height() ) / szList.count();
715 for ( QIntList::iterator it = szList.begin(); it != szList.end(); ++it )
717 split->setSizes( szList );
720 void QtxWorkstack::splitVertical()
722 split( Qt::Horizontal );
725 void QtxWorkstack::splitHorizontal()
727 split( Qt::Vertical );
730 void QtxWorkstack::onRename()
736 QString newName = QInputDialog::getText( tr( "Rename" ), tr( "Enter new name:" ), QLineEdit::Normal,
737 myWorkWin->caption(), &ok, topLevelWidget() );
738 if ( ok && !newName.isEmpty() )
739 myWorkWin->setCaption( newName );
742 QSplitter* QtxWorkstack::wrapSplitter( QtxWorkstackArea* area )
747 QSplitter* pSplit = splitter( area );
751 bool upd = pSplit->isUpdatesEnabled();
752 pSplit->setUpdatesEnabled( false );
754 QIntList szList = pSplit->sizes();
756 QSplitter* wrap = new QSplitter( 0 );
757 #if defined QT_VERSION && QT_VERSION >= 0x30200
758 wrap->setChildrenCollapsible( false );
760 insertWidget( wrap, pSplit, area );
761 area->reparent( wrap, QPoint( 0, 0 ), true );
763 pSplit->setSizes( szList );
765 pSplit->setUpdatesEnabled( upd );
770 void QtxWorkstack::insertWidget( QWidget* wid, QWidget* pWid, QWidget* after )
775 QWidgetList moveList;
776 const QObjectList* lst = pWid->children();
780 for ( QObjectListIt it( *lst ); it.current(); ++it )
782 if ( found && ( it.current()->inherits( "QSplitter" ) ||
783 it.current()->inherits( "QtxWorkstackArea" ) ) )
784 moveList.append( (QWidget*)it.current() );
785 if ( it.current() == after )
790 QMap<QWidget*, bool> map;
791 for ( QWidgetListIt it( moveList ); it.current(); ++it )
793 map.insert( it.current(), it.current()->isVisibleTo( it.current()->parentWidget() ) );
794 it.current()->reparent( 0, QPoint( 0, 0 ), false );
797 wid->reparent( pWid, QPoint( 0, 0 ), true );
799 for ( QWidgetListIt itr( moveList ); itr.current(); ++itr )
800 itr.current()->reparent( pWid, QPoint( 0, 0 ), map.contains( itr.current() ) ? map[itr.current()] : false );
804 * \brief Closes the active window.
806 void QtxWorkstack::onCloseWindow()
810 else if( activeWindow() )
811 activeWindow()->close();
814 void QtxWorkstack::onDestroyed( QObject* obj )
816 QtxWorkstackArea* area = (QtxWorkstackArea*)obj;
818 if ( area == myArea )
823 QtxWorkstackArea* cur = neighbourArea( area );
828 QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
831 void QtxWorkstack::onWindowActivated( QWidget* wid )
833 const QObject* obj = sender();
834 if ( !obj->inherits( "QtxWorkstackArea" ) )
837 setActiveArea( (QtxWorkstackArea*)obj );
840 void QtxWorkstack::onDeactivated( QtxWorkstackArea* area )
842 if ( myArea != area )
845 QPtrList<QtxWorkstackArea> lst;
846 areas( mySplit, lst, true );
848 int idx = lst.find( area );
855 QtxWorkstackArea* newArea = neighbourArea( area );
856 if ( newArea && newArea->activeWidget() )
857 newArea->activeWidget()->setFocus();
859 QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
862 void QtxWorkstack::onContextMenuRequested( QWidget* w, QPoint p )
867 QWidgetList lst = activeArea()->widgetList();
873 QPopupMenu* pm = new QPopupMenu();
875 if ( lst.count() > 1 )
877 myActionsMap[SplitVertical]->addTo( pm );
878 myActionsMap[SplitHorizontal]->addTo( pm );
879 pm->insertSeparator();
884 myActionsMap[Close]->addTo( pm );
885 myActionsMap[Rename]->addTo( pm );
896 void QtxWorkstack::childEvent( QChildEvent* e )
898 if ( e->inserted() && e->child()->isWidgetType() )
900 QWidget* w = (QWidget*)e->child();
901 if ( w && w != mySplit )
903 targetArea()->insertWidget( w );
907 QWidget::childEvent( e );
910 void QtxWorkstack::customEvent( QCustomEvent* e )
915 QSplitter* QtxWorkstack::splitter( QtxWorkstackArea* area ) const
920 QSplitter* split = 0;
922 QWidget* wid = area->parentWidget();
923 if ( wid && wid->inherits( "QSplitter" ) )
924 split = (QSplitter*)wid;
929 void QtxWorkstack::splitters( QSplitter* split, QPtrList<QSplitter>& splitList, const bool rec ) const
934 const QObjectList* objs = split->children();
937 for ( QObjectListIt it( *objs ); it.current(); ++it )
940 splitters( (QSplitter*)it.current(), splitList, rec );
941 if ( it.current()->inherits( "QSplitter" ) )
942 splitList.append( (QSplitter*)it.current() );
947 void QtxWorkstack::areas( QSplitter* split, QPtrList<QtxWorkstackArea>& areaList, const bool rec ) const
952 const QObjectList* objs = split->children();
955 for ( QObjectListIt it( *objs ); it.current(); ++it )
957 if ( it.current()->inherits( "QtxWorkstackArea" ) )
958 areaList.append( (QtxWorkstackArea*)it.current() );
959 else if ( rec && it.current()->inherits( "QSplitter" ) )
960 areas( (QSplitter*)it.current(), areaList, rec );
965 QtxWorkstackArea* QtxWorkstack::activeArea() const
970 QtxWorkstackArea* QtxWorkstack::targetArea()
972 QtxWorkstackArea* area = activeArea();
974 area = currentArea();
977 QPtrList<QtxWorkstackArea> lst;
978 areas( mySplit, lst );
979 if ( !lst.isEmpty() )
984 area = createArea( mySplit );
989 QtxWorkstackArea* QtxWorkstack::currentArea() const
991 QtxWorkstackArea* area = 0;
992 QWidget* wid = focusWidget();
993 while ( wid && !area )
995 if ( wid->inherits( "QtxWorkstackArea" ) )
996 area = (QtxWorkstackArea*)wid;
997 wid = wid->parentWidget();
1003 QtxWorkstackArea* QtxWorkstack::createArea( QWidget* parent ) const
1005 QtxWorkstackArea* area = new QtxWorkstackArea( parent );
1007 connect( area, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1008 connect( area, SIGNAL( activated( QWidget* ) ), this, SLOT( onWindowActivated( QWidget* ) ) );
1009 connect( area, SIGNAL( contextMenuRequested( QWidget*, QPoint ) ),
1010 this, SLOT( onContextMenuRequested( QWidget*, QPoint ) ) );
1011 connect( area, SIGNAL( deactivated( QtxWorkstackArea* ) ), this, SLOT( onDeactivated( QtxWorkstackArea* ) ) );
1016 void QtxWorkstack::setActiveArea( QtxWorkstackArea* area )
1018 QWidget* oldCur = myWin;
1020 QtxWorkstackArea* oldArea = myArea;
1024 if ( myArea != oldArea )
1027 oldArea->updateActiveState();
1029 myArea->updateActiveState();
1033 myWin = myArea->activeWidget();
1035 if ( myWin && oldCur != myWin )
1036 emit windowActivated( myWin );
1039 QtxWorkstackArea* QtxWorkstack::neighbourArea( QtxWorkstackArea* area ) const
1041 QPtrList<QtxWorkstackArea> lst;
1042 areas( mySplit, lst, true );
1043 int pos = lst.find( area );
1047 QtxWorkstackArea* na = 0;
1048 for ( int i = pos - 1; i >= 0 && !na; i-- )
1050 if ( !lst.at( i )->isEmpty() )
1054 for ( int j = pos + 1; j < (int)lst.count() && !na; j++ )
1056 if ( !lst.at( j )->isEmpty() )
1062 QtxWorkstackArea* QtxWorkstack::areaAt( const QPoint& p ) const
1064 QtxWorkstackArea* area = 0;
1065 QPtrList<QtxWorkstackArea> lst;
1066 areas( mySplit, lst, true );
1067 for ( QPtrListIterator<QtxWorkstackArea> it( lst ); it.current() && !area; ++it )
1069 QtxWorkstackArea* cur = it.current();
1070 QRect r = cur->geometry();
1071 if ( cur->parentWidget() )
1072 r = QRect( cur->parentWidget()->mapToGlobal( r.topLeft() ), r.size() );
1073 if ( r.contains( p ) )
1079 void QtxWorkstack::updateState()
1081 updateState( mySplit );
1084 void QtxWorkstack::updateState( QSplitter* split )
1086 QPtrList<QSplitter> recList;
1087 splitters( split, recList, false );
1088 for ( QPtrListIterator<QSplitter> itr( recList ); itr.current(); ++itr )
1089 updateState( itr.current() );
1091 QPtrList<QSplitter> splitList;
1092 splitters( split, splitList, false );
1094 QPtrList<QtxWorkstackArea> areaList;
1095 areas( split, areaList, false );
1098 for ( QPtrListIterator<QtxWorkstackArea> it( areaList ); it.current(); ++it )
1100 if ( it.current()->isEmpty() )
1101 it.current()->hide();
1104 it.current()->show();
1109 if ( split == mySplit )
1112 for ( QPtrListIterator<QSplitter> iter( splitList ); iter.current() && !vis; ++iter )
1113 vis = iter.current()->isVisibleTo( iter.current()->parentWidget() );
1115 if ( areaList.isEmpty() && splitList.isEmpty() )
1124 Class: QtxWorkstackArea [Internal]
1128 QtxWorkstackArea::QtxWorkstackArea( QWidget* parent )
1131 QVBoxLayout* base = new QVBoxLayout( this );
1133 QHBox* top = new QHBox( this );
1134 base->addWidget( top );
1136 myBar = new QtxWorkstackTabBar( top );
1138 QPushButton* close = new QPushButton( top );
1139 close->setPixmap( style().stylePixmap( QStyle::SP_TitleBarCloseButton ) );
1140 close->setAutoDefault( true );
1141 close->setFlat( true );
1144 top->setStretchFactor( myBar, 1 );
1146 myStack = new QWidgetStack( this );
1148 base->addWidget( myStack, 1 );
1150 connect( myClose, SIGNAL( clicked() ), this, SLOT( onClose() ) );
1151 connect( myBar, SIGNAL( selected( int ) ), this, SLOT( onSelected( int ) ) );
1152 connect( myBar, SIGNAL( dragActiveTab() ), this, SLOT( onDragActiveTab() ) );
1153 connect( myBar, SIGNAL( contextMenuRequested( QPoint ) ), this, SLOT( onContextMenuRequested( QPoint ) ) );
1157 updateActiveState();
1159 qApp->installEventFilter( this );
1162 QtxWorkstackArea::~QtxWorkstackArea()
1164 qApp->removeEventFilter( this );
1167 bool QtxWorkstackArea::isEmpty() const
1170 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !res; ++it )
1171 res = it.data().vis;
1175 void QtxWorkstackArea::insertWidget( QWidget* wid, const int idx )
1180 int pos = myList.find( wid );
1181 if ( pos != -1 && ( pos == idx || ( idx < 0 && pos == (int)myList.count() - 1 ) ) )
1184 myList.removeRef( wid );
1185 pos = idx < 0 ? myList.count() : idx;
1186 myList.insert( QMIN( pos, (int)myList.count() ), wid );
1187 if ( !myInfo.contains( wid ) )
1189 QtxWorkstackChild* child = new QtxWorkstackChild( wid, myStack );
1190 myChild.insert( wid, child );
1191 myInfo.insert( wid, WidgetInfo() );
1192 myInfo[wid].id = generateId();
1193 myInfo[wid].vis = wid->isVisibleTo( wid->parentWidget() );
1195 connect( child, SIGNAL( destroyed( QObject* ) ), this, SLOT( onChildDestroyed( QObject* ) ) );
1196 connect( wid, SIGNAL( destroyed() ), this, SLOT( onWidgetDestroyed() ) );
1197 connect( child, SIGNAL( shown( QtxWorkstackChild* ) ), this, SLOT( onChildShown( QtxWorkstackChild* ) ) );
1198 connect( child, SIGNAL( hided( QtxWorkstackChild* ) ), this, SLOT( onChildHided( QtxWorkstackChild* ) ) );
1199 connect( child, SIGNAL( activated( QtxWorkstackChild* ) ), this, SLOT( onChildActivated( QtxWorkstackChild* ) ) );
1200 connect( child, SIGNAL( captionChanged( QtxWorkstackChild* ) ), this, SLOT( onChildCaptionChanged( QtxWorkstackChild* ) ) );
1205 setWidgetActive( wid );
1208 void QtxWorkstackArea::onContextMenuRequested( QPoint p )
1210 const QtxWorkstackTabBar* bar = ::qt_cast<const QtxWorkstackTabBar*>( sender() );
1215 QTab* tab = myBar->tabAt( tabAt( p ) );
1217 wid = widget( tab->identifier() );
1219 emit contextMenuRequested( wid, p );
1222 void QtxWorkstackArea::onWidgetDestroyed()
1225 removeWidget( (QWidget*)sender(), false );
1228 void QtxWorkstackArea::removeWidget( QWidget* wid, const bool del )
1230 if ( !myList.contains( wid ) )
1233 if ( myBar->tab( widgetId( wid ) ) )
1234 myBar->removeTab( myBar->tab( widgetId( wid ) ) );
1235 myStack->removeWidget( child( wid ) );
1237 myList.remove( wid );
1238 myInfo.remove( wid );
1239 myChild.remove( wid );
1243 delete child( wid );
1244 if( myList.isEmpty() )
1253 QWidgetList QtxWorkstackArea::widgetList() const
1256 for ( QWidgetListIt it( myList ); it.current(); ++it )
1258 if ( widgetVisibility( it.current() ) )
1259 lst.append( it.current() );
1264 QWidget* QtxWorkstackArea::activeWidget() const
1266 return widget( myBar->currentTab() );
1269 void QtxWorkstackArea::setActiveWidget( QWidget* wid )
1271 myBar->setCurrentTab( widgetId( wid ) );
1274 bool QtxWorkstackArea::contains( QWidget* wid ) const
1276 return myList.contains( wid );
1279 void QtxWorkstackArea::show()
1281 QMap<QWidget*, bool> map;
1282 for ( QWidgetListIt it( myList ); it.current(); ++it )
1284 map.insert( it.current(), isBlocked( it.current() ) );
1285 setBlocked( it.current(), true );
1290 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
1291 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
1294 void QtxWorkstackArea::hide()
1296 QMap<QWidget*, bool> map;
1297 for ( QWidgetListIt it( myList ); it.current(); ++it )
1299 map.insert( it.current(), isBlocked( it.current() ) );
1300 setBlocked( it.current(), true );
1305 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
1306 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
1309 bool QtxWorkstackArea::isActive() const
1311 QtxWorkstack* ws = workstack();
1315 return ws->activeArea() == this;
1318 void QtxWorkstackArea::updateActiveState()
1320 myBar->setActive( isActive() );
1323 QtxWorkstack* QtxWorkstackArea::workstack() const
1325 QtxWorkstack* ws = 0;
1326 QWidget* wid = parentWidget();
1327 while ( wid && !ws )
1329 if ( wid->inherits( "QtxWorkstack" ) )
1330 ws = (QtxWorkstack*)wid;
1331 wid = wid->parentWidget();
1336 bool QtxWorkstackArea::eventFilter( QObject* o, QEvent* e )
1338 if ( o->isWidgetType() )
1340 QWidget* wid = (QWidget*)o;
1341 if ( e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress )
1344 while ( !ok && wid && wid != myClose )
1347 wid = wid->parentWidget();
1350 QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)( e->type() == QEvent::FocusIn ? ActivateWidget : FocusWidget ) ) );
1356 QRect QtxWorkstackArea::floatRect() const
1358 QRect r = myStack->geometry();
1359 return QRect( mapToGlobal( r.topLeft() ), mapToGlobal( r.bottomRight() ) );
1362 QRect QtxWorkstackArea::floatTab( const int idx ) const
1364 return myBar->tabRect( idx );
1367 int QtxWorkstackArea::tabAt( const QPoint& p ) const
1370 for ( int i = 0; i < myBar->count() && idx == -1; i++ )
1372 QRect r = myBar->tabRect( i );
1373 if ( r.isValid() && r.contains( p ) )
1379 void QtxWorkstackArea::customEvent( QCustomEvent* e )
1381 switch ( e->type() )
1383 case ActivateWidget:
1384 emit activated( activeWidget() );
1387 if ( activeWidget() && !activeWidget()->focusWidget() )
1388 activeWidget()->setFocus();
1391 removeWidget( (QWidget*)e->data() );
1396 void QtxWorkstackArea::focusInEvent( QFocusEvent* e )
1398 QWidget::focusInEvent( e );
1400 emit activated( activeWidget() );
1403 void QtxWorkstackArea::mousePressEvent( QMouseEvent* e )
1405 QWidget::mousePressEvent( e );
1407 emit activated( activeWidget() );
1410 void QtxWorkstackArea::onClose()
1412 QWidget* wid = activeWidget();
1417 void QtxWorkstackArea::onSelected( int id )
1421 emit activated( activeWidget() );
1424 void QtxWorkstackArea::onDragActiveTab()
1426 QtxWorkstackChild* c = child( activeWidget() );
1430 new QtxWorkstackDrag( workstack(), c );
1433 void QtxWorkstackArea::onChildDestroyed( QObject* obj )
1435 QtxWorkstackChild* child = (QtxWorkstackChild*)obj;
1436 myStack->removeWidget( child );
1439 for ( ChildMap::ConstIterator it = myChild.begin(); it != myChild.end() && !wid; ++it )
1441 if ( it.data() == child )
1445 myChild.remove( wid );
1447 QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)RemoveWidget, wid ) );
1450 void QtxWorkstackArea::onChildShown( QtxWorkstackChild* c )
1452 setWidgetShown( c->widget(), true );
1455 void QtxWorkstackArea::onChildHided( QtxWorkstackChild* c )
1457 setWidgetShown( c->widget(), false );
1460 void QtxWorkstackArea::onChildActivated( QtxWorkstackChild* c )
1462 setWidgetActive( c->widget() );
1465 void QtxWorkstackArea::onChildCaptionChanged( QtxWorkstackChild* c )
1467 updateTab( c->widget() );
1470 void QtxWorkstackArea::updateCurrent()
1472 QMap<QWidget*, bool> map;
1473 for ( QWidgetListIt it( myList ); it.current(); ++it )
1475 map.insert( it.current(), isBlocked( it.current() ) );
1476 setBlocked( it.current(), true );
1479 myStack->raiseWidget( myBar->currentTab() );
1481 for ( QWidgetListIt itr( myList ); itr.current(); ++itr )
1482 setBlocked( itr.current(), map.contains( itr.current() ) ? map[itr.current()] : false );
1485 void QtxWorkstackArea::updateTab( QWidget* wid )
1487 QTab* tab = myBar->tab( widgetId( wid ) );
1494 QPixmap pix = *wid->icon();
1495 pix.convertFromImage( pix.convertToImage().smoothScale( pix.width(), 16, QImage::ScaleMin ) );
1496 icoSet = QIconSet( pix );
1499 tab->setIconSet( icoSet );
1500 tab->setText( wid->caption() );
1503 QWidget* QtxWorkstackArea::widget( const int id ) const
1506 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !wid; ++it )
1508 if ( it.data().id == id )
1514 int QtxWorkstackArea::widgetId( QWidget* wid ) const
1517 if ( myInfo.contains( wid ) )
1518 id = myInfo[wid].id;
1522 bool QtxWorkstackArea::widgetVisibility( QWidget* wid ) const
1525 if ( myInfo.contains( wid ) )
1526 res = myInfo[wid].vis;
1530 void QtxWorkstackArea::setWidgetActive( QWidget* wid )
1532 int id = widgetId( wid );
1536 myBar->setCurrentTab( id );
1539 void QtxWorkstackArea::setWidgetShown( QWidget* wid, const bool on )
1541 if ( isBlocked( wid ) || !myInfo.contains( wid ) || myInfo[wid].vis == on )
1544 myInfo[wid].vis = on;
1548 void QtxWorkstackArea::updateState()
1550 bool updBar = myBar->isUpdatesEnabled();
1551 bool updStk = myStack->isUpdatesEnabled();
1552 myBar->setUpdatesEnabled( false );
1553 myStack->setUpdatesEnabled( false );
1555 bool block = myBar->signalsBlocked();
1556 myBar->blockSignals( true );
1558 QWidget* prev = activeWidget();
1561 for ( QWidgetListIt it( myList ); it.current(); ++it )
1563 QWidget* wid = it.current();
1564 int id = widgetId( wid );
1569 bool vis = widgetVisibility( wid );
1571 if ( myBar->tab( id ) && ( !vis || myBar->indexOf( id ) != idx ) )
1572 myBar->removeTab( myBar->tab( id ) );
1574 if ( !myBar->tab( id ) && vis )
1576 QTab* tab = new QTab( wid->caption() );
1577 myBar->insertTab( tab, idx );
1578 tab->setIdentifier( id );
1583 bool block = isBlocked( wid );
1584 setBlocked( wid, true );
1586 QtxWorkstackChild* cont = child( wid );
1589 myStack->removeWidget( cont );
1590 else if ( !myStack->widget( id ) )
1591 myStack->addWidget( cont, id );
1596 setBlocked( wid, block );
1599 int curId = widgetId( prev );
1600 if ( !myBar->tab( curId ) )
1603 int pos = myList.find( prev );
1604 for ( int i = pos - 1; i >= 0 && !wid; i-- )
1606 if ( widgetVisibility( myList.at( i ) ) )
1607 wid = myList.at( i );
1610 for ( int j = pos + 1; j < (int)myList.count() && !wid; j++ )
1612 if ( widgetVisibility( myList.at( j ) ) )
1613 wid = myList.at( j );
1617 curId = widgetId( wid );
1620 myBar->setCurrentTab( curId );
1622 myBar->blockSignals( block );
1626 myBar->setUpdatesEnabled( updBar );
1627 myStack->setUpdatesEnabled( updStk );
1633 QResizeEvent re( myBar->size(), myBar->size() );
1634 QApplication::sendEvent( myBar, &re );
1639 emit deactivated( this );
1644 if ( prev != activeWidget() )
1645 emit activated( activeWidget() );
1649 int QtxWorkstackArea::generateId() const
1653 for ( WidgetInfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end(); ++it )
1654 map.insert( it.data().id, 0 );
1657 while ( map.contains( id ) )
1663 bool QtxWorkstackArea::isBlocked( QWidget* wid ) const
1665 return myBlock.contains( wid );
1668 void QtxWorkstackArea::setBlocked( QWidget* wid, const bool on )
1671 myBlock.insert( wid, 0 );
1673 myBlock.remove( wid );
1676 QtxWorkstackChild* QtxWorkstackArea::child( QWidget* wid ) const
1678 QtxWorkstackChild* res = 0;
1679 if ( myChild.contains( wid ) )
1685 Class: QtxWorkstackChild [Internal]
1689 QtxWorkstackChild::QtxWorkstackChild( QWidget* wid, QWidget* parent )
1693 myWidget->reparent( this, QPoint( 0, 0 ), myWidget->isVisibleTo( myWidget->parentWidget() ) );
1694 myWidget->installEventFilter( this );
1696 connect( myWidget, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1699 QtxWorkstackChild::~QtxWorkstackChild()
1701 qApp->removeEventFilter( this );
1706 widget()->removeEventFilter( this );
1707 widget()->reparent( 0, QPoint( 0, 0 ), false );
1708 disconnect( widget(), SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
1711 QWidget* QtxWorkstackChild::widget() const
1716 bool QtxWorkstackChild::eventFilter( QObject* o, QEvent* e )
1718 if ( o->isWidgetType() )
1720 if ( e->type() == QEvent::CaptionChange || e->type() == QEvent::IconChange )
1721 emit captionChanged( this );
1723 if ( !e->spontaneous() && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
1726 if ( !e->spontaneous() && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) )
1729 if ( e->type() == QEvent::FocusIn )
1730 emit activated( this );
1732 return QHBox::eventFilter( o, e );
1735 void QtxWorkstackChild::onDestroyed( QObject* obj )
1737 if ( obj != widget() )
1744 void QtxWorkstackChild::childEvent( QChildEvent* e )
1746 if ( e->type() == QEvent::ChildRemoved && e->child() == widget() )
1751 QHBox::childEvent( e );
1755 Class: QtxWorkstackTabBar [Internal]
1759 QtxWorkstackTabBar::QtxWorkstackTabBar( QWidget* parent )
1760 : QTabBar( parent ),
1765 QtxWorkstackTabBar::~QtxWorkstackTabBar()
1769 void QtxWorkstackTabBar::setActive( const bool on )
1771 QFont aFont = font();
1772 aFont.setUnderline( on );
1778 QRect QtxWorkstackTabBar::tabRect( const int idx ) const
1781 QTab* t = tabAt( idx );
1785 r.setLeft( QMAX( r.left(), 0 ) );
1787 int x1 = tabAt( 0 )->rect().left();
1788 int x2 = tabAt( count() - 1 )->rect().right();
1791 if ( QABS( x2 - x1 ) > width() )
1792 #if defined QT_VERSION && QT_VERSION >= 0x30300
1793 bw = 2 * style().pixelMetric( QStyle::PM_TabBarScrollButtonWidth, this );
1798 int limit = width() - bw;
1799 r.setRight( QMIN( r.right(), limit ) );
1801 r = QRect( mapToGlobal( r.topLeft() ), r.size() );
1806 void QtxWorkstackTabBar::mouseMoveEvent( QMouseEvent* e )
1808 if ( myId != -1 && !tab( myId )->rect().contains( e->pos() ) )
1811 emit dragActiveTab();
1814 QTabBar::mouseMoveEvent( e );
1817 void QtxWorkstackTabBar::mousePressEvent( QMouseEvent* e )
1819 QTabBar::mousePressEvent( e );
1821 if ( e->button() == LeftButton )
1822 myId = currentTab();
1825 void QtxWorkstackTabBar::mouseReleaseEvent( QMouseEvent* e )
1827 QTabBar::mouseReleaseEvent( e );
1831 if ( e->button() == RightButton )
1832 emit contextMenuRequested( e->globalPos() );
1835 void QtxWorkstackTabBar::contextMenuEvent( QContextMenuEvent* e )
1837 if ( e->reason() != QContextMenuEvent::Mouse )
1838 emit contextMenuRequested( e->globalPos() );
1841 void QtxWorkstackTabBar::paintLabel( QPainter* p, const QRect& br, QTab* t, bool has_focus ) const
1843 if ( currentTab() != t->identifier() )
1845 QFont fnt = p->font();
1846 fnt.setUnderline( false );
1849 QTabBar::paintLabel( p, br, t, has_focus );
1853 Class: QtxWorkstackDrag [Internal]
1857 QtxWorkstackDrag::QtxWorkstackDrag( QtxWorkstack* ws, QtxWorkstackChild* child )
1865 qApp->installEventFilter( this );
1868 QtxWorkstackDrag::~QtxWorkstackDrag()
1870 qApp->removeEventFilter( this );
1875 bool QtxWorkstackDrag::eventFilter( QObject*, QEvent* e )
1877 switch ( e->type() )
1879 case QEvent::MouseMove:
1880 updateTarget( ((QMouseEvent*)e)->globalPos() );
1882 case QEvent::MouseButtonRelease:
1894 void QtxWorkstackDrag::updateTarget( const QPoint& p )
1897 QtxWorkstackArea* area = detectTarget( p, tab );
1898 setTarget( area, tab );
1901 QtxWorkstackArea* QtxWorkstackDrag::detectTarget( const QPoint& p, int& tab ) const
1906 QtxWorkstackArea* area = myWS->areaAt( p );
1908 tab = area->tabAt( p );
1912 void QtxWorkstackDrag::setTarget( QtxWorkstackArea* area, const int tab )
1914 if ( !area || ( myArea == area && tab == myTab ) )
1929 void QtxWorkstackDrag::dropWidget()
1932 myArea->insertWidget( myChild->widget(), myTab );
1935 void QtxWorkstackDrag::drawRect()
1937 if ( !myPainter || !myArea )
1940 QRect r = myArea->floatRect();
1941 int m = myPainter->pen().width();
1943 r.setTop( r.top() + m + 2 );
1944 r.setLeft( r.left() + m + 2 );
1945 r.setRight( r.right() - m - 2 );
1946 r.setBottom( r.bottom() - m - 2 );
1948 myPainter->drawRect( r );
1950 QRect tr = myArea->floatTab( myTab );
1951 tr.setTop( tr.top() + m );
1952 tr.setLeft( tr.left() + m );
1953 tr.setRight( tr.right() - m );
1954 tr.setBottom( tr.bottom() - m );
1956 myPainter->drawRect( tr );
1959 void QtxWorkstackDrag::endDrawRect()
1965 void QtxWorkstackDrag::startDrawRect()
1970 int scr = QApplication::desktop()->screenNumber( (QWidget*)this );
1971 QWidget* paint_on = QApplication::desktop()->screen( scr );
1973 myPainter = new QPainter( paint_on, true );
1974 myPainter->setPen( QPen( gray, 3 ) );
1975 myPainter->setRasterOp( XorROP );