Fix crash because of empty memory dump.
[kdbg.git] / DockWidget / dockmanager.cpp
blob013ccb9c1e0071724caf745cb3ea31058b16aefc
1 /***************************************************************************
2 DockWidget part of KDEStudio
3 -------------------
4 copyright : (C) 1999 by Judin Max
5 email : novaprint@mtu-net.ru
6 ***************************************************************************/
8 #define DOCK_CONFIG_VERSION "0.0.4"
10 #include <kconfig.h>
11 #include <qpopupmenu.h>
12 #include <qapplication.h>
13 #include <kapp.h>
15 #include <qobjcoll.h>
16 #include <qframe.h>
17 #include <qpainter.h>
18 #include <qcursor.h>
20 #include "dockmainwindow.h"
21 #include "dockmanager.h"
22 #include "docksplitter.h"
23 #include "dockmovemanager.h"
25 #include "close.xpm"
26 #include "notclose.xpm"
28 // remove Xlib's defines
29 #ifdef KeyPress
30 #undef KeyPress
31 #endif
33 SDockButton::SDockButton( QWidget *parent, const char * name )
34 :QPushButton( parent, name )
36 moveMouse = false;
39 SDockButton::~SDockButton()
43 void SDockButton::drawButton( QPainter* p )
45 QBrush bgBrush = colorGroup().brush(QColorGroup::Background);
46 p->fillRect( 0,0, width(), height(), bgBrush );
47 p->drawPixmap( (width() - pixmap()->width()) / 2, (height() - pixmap()->height()) / 2, *pixmap() );
48 if ( moveMouse && !isDown() ){
49 p->setPen( white );
50 p->moveTo( 0, height() - 1 );
51 p->lineTo( 0, 0 );
52 p->lineTo( width() - 1, 0 );
54 p->setPen( colorGroup().dark() );
55 p->lineTo( width() - 1, height() - 1 );
56 p->lineTo( 0, height() - 1 );
58 if ( isOn() || isDown() ){
59 p->setPen( colorGroup().dark() );
60 p->moveTo( 0, height() - 1 );
61 p->lineTo( 0, 0 );
62 p->lineTo( width() - 1, 0 );
64 p->setPen( white );
65 p->lineTo( width() - 1, height() - 1 );
66 p->lineTo( 0, height() - 1 );
70 void SDockButton::enterEvent( QEvent * )
72 moveMouse = true;
73 repaint();
76 void SDockButton::leaveEvent( QEvent * )
78 moveMouse = false;
79 repaint();
82 /*************************************************************************/
84 DockWidget::DockWidget( DockManager* dockManager, const char* name, const QPixmap &pixmap, QWidget* parent )
85 : QWidget( parent, name )
87 setCaption( name );
89 eDocking = DockTop|DockLeft|DockRight|DockBottom|DockCenter|DockDesktop;
90 sDocking = DockTop|DockLeft|DockRight|DockBottom|DockCenter;
92 isGroup = false;
93 isTabGroup = false;
95 manager = dockManager;
96 installEventFilter( manager );
97 manager->childDock->append( this );
99 closeButton = new SDockButton( this, "DockWidgetCloseButton");
100 closeButton->setFocusPolicy( NoFocus );
101 closeButton->setPixmap(close_xpm);
102 connect( closeButton, SIGNAL(clicked()), SLOT(slotCloseButtonClick()));
104 stayButton = new SDockButton( this, "DockWidgetStayButton");
105 stayButton->setFocusPolicy( NoFocus );
106 stayButton->setToggleButton( true );
107 stayButton->setPixmap(not_close_xpm);
109 closeButton->resize( 9, 9 );
110 closeButton->hide();
112 stayButton->resize( 9, 9 );
113 stayButton->hide();
115 QPoint p = QPoint(0,0);
116 widget = 0L;
117 dockCaptionHeight = 10;
119 drawBuffer = 0L;
120 pix = new QPixmap(pixmap);
122 applyToWidget( parent, p );
125 DockWidget::~DockWidget()
127 if ( !manager->undockProcess ){
128 unDock();
130 delete pix;
131 delete drawBuffer;
132 manager->childDock->remove( this );
135 void DockWidget::setEnableDocking( int pos )
137 eDocking = pos;
138 updateCaptionButton();
141 void DockWidget::updateCaptionButton()
143 if ( parent() ){
144 if ( (parent() == manager->main) || isGroup || (eDocking == DockNone) ){
145 dockCaptionHeight = 0;
146 closeButton->hide();
147 stayButton->hide();
148 } else {
149 dockCaptionHeight = 10;
150 closeButton->show();
151 stayButton->show();
153 } else {
154 dockCaptionHeight = 10;
155 closeButton->hide();
156 stayButton->hide();
158 repaint(false);
161 void DockWidget::applyToWidget( QWidget* s, const QPoint& p )
163 if ( parent() != s ){
164 hide();
165 reparent(s, 0, QPoint(0,0), false);
166 QApplication::syncX();
169 setMouseTracking( true );
171 if ( s && s->inherits("DockMainWindow") ){
172 ((DockMainWindow*)s)->setDockView( this );
175 if ( s == manager->main )
176 setGeometry( QRect(QPoint(0,0), manager->main->geometry().size()) );
178 if ( !s ){
179 XSetTransientForHint( qt_xdisplay(), winId(), manager->main->topLevelWidget()->winId());
180 move(p);
181 } else {
182 if ( !s->inherits("DockSplitter") && !s->inherits("DockTabCtl") )
183 eDocking = DockNone;
186 updateCaptionButton();
189 void DockWidget::show()
191 if ( parent() || manager->main->isVisible() )
192 if ( !parent() ){
193 emit manager->setDockDefaultPos( this );
194 emit setDockDefaultPos();
195 if ( parent() ){
196 makeDockVisible();
197 } else {
198 stayButton->setOn( false );
199 QWidget::show();
201 } else {
202 QWidget::show();
206 bool DockWidget::event( QEvent *event )
208 switch ( event->type() )
210 case QEvent::ChildInserted:
211 if ( ((QChildEvent*)event)->child()->inherits("SDockButton") ) break;
212 widget = (QWidget*)((QChildEvent*)event)->child();
213 widget->setGeometry( crect() );
214 break;
215 case QEvent::ChildRemoved:
216 if ( widget == ((QChildEvent*)event)->child() ) widget = 0L;
217 break;
218 case QEvent::Resize:
219 closeButton->move( width() - closeButton->width() - 1, 0 );
220 stayButton->move( closeButton->x() - stayButton->width() - 1, 0 );
221 if ( widget ){
222 widget->setGeometry( crect() );
224 if ( drawBuffer ) delete drawBuffer;
225 drawBuffer = new QPixmap( width(), height() );
226 break;
227 case QEvent::Paint:
228 paintCaption();
229 break;
230 case QEvent::Show:
231 if ( widget ) widget->show();
232 break;
233 case QEvent::Hide:
234 if ( widget ) widget->hide();
235 break;
236 default:
237 break;
239 return QWidget::event( event );
242 QRect DockWidget::crect()
244 return QRect(0, dockCaptionHeight, width(), height()-dockCaptionHeight);
247 void DockWidget::paintCaption()
249 if ( dockCaptionHeight == 0 ) return;
251 QPainter paint;
252 int delta = ( parent() ) ? 24:0;
254 QBrush bgBrush = colorGroup().brush(QColorGroup::Background);
256 paint.begin( drawBuffer );
257 paint.fillRect( drawBuffer->rect(), bgBrush );
259 paint.setPen( white );
260 paint.drawLine( 1, 3, 1, 2 );
261 paint.drawLine( 1, 2, width()-delta, 2 );
263 paint.setPen( colorGroup().mid() );
264 paint.drawLine( 1, 4, width()-delta, 4 );
265 paint.drawLine( width()-delta, 4, width()-delta, 3 );
267 paint.setPen( white );
268 paint.drawLine( 1, 6, 1, 5 );
269 paint.drawLine( 1, 5, width()-delta, 5 );
271 paint.setPen( colorGroup().mid() );
272 paint.drawLine( 1, 7, width()-delta, 7 );
273 paint.drawLine( width()-delta, 7, width()-delta, 6 );
275 bitBlt( this,0,0,drawBuffer,0,0,width(),dockCaptionHeight );
276 paint.end();
279 DockWidget* DockWidget::manualDock( DockWidget* target, DockPosition dockPos, int spliPos, QPoint pos, bool check )
281 bool succes = true; // tested flag
283 // check allowed this dock submit this operations
284 if ( !(eDocking & (int)dockPos) ){
285 succes = false;
288 // check allowed target submit this operations
289 if ( target && !(target->sDocking & (int)dockPos) ){
290 succes = false;
293 if ( !succes ){
294 // try to make another manualDock
295 DockWidget* dock_result = 0L;
296 if ( target && !check ){
297 int another_spliPos = 100 - spliPos;
298 DockPosition another__dockPos = DockNone;
299 switch ( dockPos ){
300 case DockLeft : another__dockPos = DockRight ; break;
301 case DockRight : another__dockPos = DockLeft ; break;
302 case DockTop : another__dockPos = DockBottom; break;
303 case DockBottom: another__dockPos = DockTop ; break;
304 default: break;
306 dock_result = target->manualDock( this, another__dockPos, another_spliPos, pos, true );
308 return dock_result;
310 // end check block
312 unDock();
314 if ( !target ){
315 move( pos );
316 show();
317 emit manager->change();
318 return this;
321 QWidget* parentDock = target->parentWidget();
323 if ( parentDock && parentDock->inherits("DockTabCtl") ){
324 // add to existing TabGroup
325 applyToWidget( parentDock );
326 ((DockTabCtl*)parentDock)->insertPage( this, caption() );
327 ((DockTabCtl*)parentDock)->setPixmap( this, *pix );
328 setDockTabName( (DockTabCtl*)parentDock );
330 emit manager->change();
331 return (DockWidget*)parentDock->parent();
334 DockWidget* newDock = new DockWidget( manager, "tempName", QPixmap(""), parentDock );
336 if ( dockPos == DockCenter ){
337 newDock->isTabGroup = true;
338 } else {
339 newDock->isGroup = true;
341 newDock->eDocking = (target->eDocking & eDocking) & (~(int)DockCenter);
343 newDock->applyToWidget( parentDock );
345 if ( !parentDock ){
346 newDock->move( target->frameGeometry().topLeft() );
347 newDock->resize( target->geometry().size() );
348 if ( target->isVisibleToTLW() ) newDock->show();
352 if ( dockPos == DockCenter )
354 DockTabCtl* tab = manager->createTabCtrl( newDock, "_dock_tab");
355 newDock->widget = tab;
356 #ifdef DOCK_ORIGINAL
357 connect( tab, SIGNAL(tabShowPopup(int,QPoint)), manager, SLOT(slotTabShowPopup(int,QPoint)));
358 #endif
359 target->applyToWidget( tab );
360 applyToWidget( tab );
362 tab->insertPage( target, target->caption() );
363 tab->setPixmap( target, *(target->pix) );
365 tab->insertPage( this, caption() );
366 tab->setPixmap( this, *pix );
368 setDockTabName( tab );
369 tab->show();
370 } else {
371 DockSplitter* panner = 0L;
372 if ( dockPos == DockTop || dockPos == DockBottom ) panner = manager->createDockSplitter( newDock, "DockPaner", DockSplitter::Horizontal, KNewPanner::Percent, spliPos );
373 if ( dockPos == DockLeft || dockPos == DockRight ) panner = manager->createDockSplitter( newDock, "DockPaner", DockSplitter::Vertical , KNewPanner::Percent, spliPos );
374 newDock->widget = panner;
375 panner->setFocusPolicy( NoFocus );
376 target->applyToWidget( panner );
377 applyToWidget( panner );
378 if ( dockPos == DockRight || dockPos == DockBottom ) panner->activate( target, this );
379 if ( dockPos == DockTop || dockPos == DockLeft ) panner->activate( this, target );
380 target->show();
381 show();
382 panner->show();
385 if ( parentDock ){
386 if ( parentDock->inherits("DockSplitter") ){
387 DockSplitter* sp = (DockSplitter*)parentDock;
388 sp->deactivate();
389 if ( sp->getFirst() == target )
390 sp->activate( newDock, 0L );
391 else
392 sp->activate( 0L, newDock );
396 newDock->show();
397 emit target->docking( this, dockPos );
398 emit manager->replaceDock( target, newDock );
399 emit manager->change();
401 return newDock;
404 void DockWidget::unDock()
406 QWidget* parentW = parentWidget();
408 if ( !parentW || parentW == manager->main || eDocking == DockNone )
409 return;
411 manager->blockSignals(true);
412 manager->undockProcess = true;
414 bool isV = parentW->isVisibleToTLW();
415 if ( parentW->inherits("DockTabCtl") ){
416 ((DockTabCtl*)parentW)->removePage( this );
417 applyToWidget( 0L );
418 if ( ((DockTabCtl*)parentW)->pageCount() == 1 ){
420 /* last subdock widget in the tab control*/
421 DockWidget* lastTab = (DockWidget*)((DockTabCtl*)parentW)->getFirstPage();
422 ((DockTabCtl*)parentW)->removePage( lastTab );
423 lastTab->applyToWidget( 0L );
424 lastTab->move( parentW->mapToGlobal(parentW->frameGeometry().topLeft()) );
426 /* DockTabCtl always have a parent is DockWidget*/
427 DockWidget* parentOfTab = (DockWidget*)parentW->parent();
428 delete parentW; // DockTabCtl
430 QWidget* parentOfDockWidget = parentOfTab->parentWidget();
431 if ( parentOfDockWidget == 0L ){
432 if ( isV ) lastTab->show();
433 } else {
434 if ( parentOfDockWidget->inherits("DockSplitter") ){
435 DockSplitter* split = (DockSplitter*)parentOfDockWidget;
436 lastTab->applyToWidget( split );
437 split->deactivate();
438 if ( split->getFirst() == parentOfTab ){
439 split->activate( lastTab );
440 if ( ((DockWidget*)split->parent())->splitterOrientation == (int)KNewPanner::Vertical )
441 emit ((DockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, DockLeft );
442 else
443 emit ((DockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, DockTop );
444 } else {
445 split->activate( 0L, lastTab );
446 if ( ((DockWidget*)split->parent())->splitterOrientation == (int)KNewPanner::Vertical )
447 emit ((DockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, DockRight );
448 else
449 emit ((DockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, DockBottom );
451 split->show();
452 } else {
453 lastTab->applyToWidget( parentOfDockWidget );
455 lastTab->show();
457 manager->blockSignals(false);
458 emit manager->replaceDock( parentOfTab, lastTab );
459 manager->blockSignals(true);
460 delete parentOfTab;
462 } else {
463 setDockTabName( (DockTabCtl*)parentW );
465 } else {
466 /*********************************************************************************************/
467 if ( parentW->inherits("DockSplitter") ){
468 DockSplitter* parentSplitterOfDockWidget = (DockSplitter*)parentW;
470 applyToWidget( 0L );
471 DockWidget* secondWidget = (DockWidget*)parentSplitterOfDockWidget->getAnother( this );
472 DockWidget* group = (DockWidget*)parentSplitterOfDockWidget->parentWidget();
473 group->hide();
475 if ( !group->parentWidget() ){
476 secondWidget->applyToWidget( 0L, group->frameGeometry().topLeft() );
477 secondWidget->resize( group->width(), group->height() );
478 } else {
479 QWidget* obj = group->parentWidget();
480 secondWidget->applyToWidget( obj );
481 if ( obj->inherits("DockSplitter") ){
482 DockSplitter* parentOfGroup = (DockSplitter*)obj;
483 parentOfGroup->deactivate();
485 if ( parentOfGroup->getFirst() == group )
486 parentOfGroup->activate( secondWidget );
487 else
488 parentOfGroup->activate( 0L, secondWidget );
491 delete parentSplitterOfDockWidget;
492 manager->blockSignals(false);
493 emit manager->replaceDock( group, secondWidget );
494 manager->blockSignals(true);
495 delete group;
497 if ( isV ) secondWidget->show();
499 /*********************************************************************************************/
501 manager->blockSignals(false);
502 emit manager->change();
503 manager->undockProcess = false;
506 void DockWidget::setWidget( QWidget* mw )
508 mw->recreate(this, 0, QPoint(0,0), false);
509 QApplication::syncX();
512 void DockWidget::slotCloseButtonClick()
514 if ( stayButton->isOn() ) return;
515 if ( parent() ) unDock(); else hide();
516 emit manager->change();
519 void DockWidget::setDockTabName( DockTabCtl* tab )
521 QString listOfName;
522 QString listOfCaption;
523 for ( QWidget* w = tab->getFirstPage(); w; w = tab->getNextPage( w ) ){
524 listOfCaption.append( w->caption() ).append(",");
526 listOfCaption.remove( listOfCaption.length()-1, 1 );
528 for ( QWidget* w = tab->getFirstPage(); w; w = tab->getNextPage( w ) ){
529 listOfName.append( w->name() ).append(",");
531 listOfName.remove( listOfName.length()-1, 1 );
533 tab->parentWidget()->setName( listOfName );
534 tab->parentWidget()->setCaption( listOfCaption );
536 tab->parentWidget()->repaint( false ); // DockWidget->repaint
537 if ( tab->parentWidget()->parent() )
538 if ( tab->parentWidget()->parent()->inherits("DockSplitter") )
539 ((DockSplitter*)(tab->parentWidget()->parent()))->updateName();
541 /**************************************************************************************/
543 DockManager::DockManager( QWidget* mainWindow , const char* name )
544 :QObject( 0, name )
546 main = mainWindow;
547 main->installEventFilter( this );
549 undockProcess = false;
551 #ifdef DOCK_ORIGINAL
552 menuData = new QList<menuDockData>;
553 menuData->setAutoDelete( true );
554 menuData->setAutoDelete( true );
556 menu = new QPopupMenu();
558 connect( menu, SIGNAL(aboutToShow()), SLOT(slotMenuPopup()) );
559 connect( menu, SIGNAL(activated(int)), SLOT(slotMenuActivated(int)) );
560 #endif
562 childDock = new QList<DockWidget>();
563 childDock->setAutoDelete( false );
564 mg = 0L;
565 draging = false;
566 dropCancel = false;
569 DockManager::~DockManager()
571 #ifdef DOCK_ORIGINAL
572 delete menuData;
573 delete menu;
574 #endif
576 QListIterator<DockWidget> it( *childDock );
577 DockWidget * obj;
579 while ( (obj=it.current()) ) {
580 delete obj;
582 delete childDock;
585 void DockManager::activate()
587 QListIterator<DockWidget> it( *childDock );
588 DockWidget * obj;
590 while ( (obj=it.current()) ) {
591 ++it;
592 if ( obj->widget ) obj->widget->show();
593 if ( obj->parent() && !obj->parent()->inherits("DockTabCtl") ){
594 obj->show();
596 if ( !obj->parent() ){
597 obj->show();
600 if ( !main->inherits("QDialog") ) main->show();
603 bool DockManager::eventFilter( QObject *obj, QEvent *event )
605 if ( obj == main && event->type() == QEvent::Resize && main->children() ){
606 QWidget* fc = (QWidget*)main->children()->getFirst();
607 if ( fc )
608 fc->setGeometry( QRect(QPoint(0,0), main->geometry().size()) );
611 if ( obj->inherits("DockWidget") ){
612 DockWidget* ww;
613 DockWidget* curdw = (DockWidget*)obj;
614 switch ( event->type() )
616 case QEvent::CaptionChange:
617 curdw->repaint( false );
618 if ( curdw->parentWidget() ){
619 if ( curdw->parentWidget()->inherits("DockSplitter") ){
620 ((DockSplitter*)(curdw->parentWidget()))->updateName();
622 if ( curdw->parentWidget()->inherits("DockTabCtl") ){
623 curdw->setDockTabName( ((DockTabCtl*)(curdw->parentWidget())) );
624 ((DockTabCtl*)(curdw->parentWidget()))->setPageCaption( curdw, curdw->caption() );
627 break;
628 case QEvent::MouseButtonRelease:
629 if ( draging && !dropCancel ){
630 draging = false;
631 drop();
633 dropCancel = false;
634 break;
635 case QEvent::MouseMove:
636 if ( draging ) {
637 ww = findDockWidgetAt( QCursor::pos() );
638 DockWidget* oldMoveWidget = currentMoveWidget;
639 if ( currentMoveWidget && ww == currentMoveWidget ) { //move
640 dragMove( currentMoveWidget, currentMoveWidget->mapFromGlobal( QCursor::pos() ) );
641 break;
644 if ( !ww && (curdw->eDocking & DockWidget::DockDesktop) == 0 ){
645 currentMoveWidget = ww;
646 curPos = DockWidget::DockDesktop;
647 mg->movePause();
648 } else {
649 if ( oldMoveWidget && ww != currentMoveWidget ) { //leave
650 currentMoveWidget = ww;
651 curPos = DockWidget::DockDesktop;
652 mg->resize( storeW, storeH );
653 mg->moveContinue();
657 if ( oldMoveWidget != ww && ww ) { //enter ww
658 currentMoveWidget = ww;
659 curPos = DockWidget::DockDesktop;
660 storeW = mg->width();
661 storeH = mg->height();
662 mg->movePause();
664 } else {
665 if ( (((QMouseEvent*)event)->state() == LeftButton) && !dropCancel ){
666 if ( curdw->eDocking != DockWidget::DockNone ){
667 dropCancel = false;
668 curdw->setFocus();
669 qApp->processOneEvent();
670 startDrag( curdw );
674 break;
675 case QEvent::KeyPress:
676 if ( ((QKeyEvent*)event)->key() == Qt::Key_Escape ){
677 if ( draging ){
678 dropCancel = true;
679 draging = false;
680 drop();
683 break;
684 case QEvent::Hide:
685 case QEvent::Show:
686 emit change();
687 break;
688 default:
689 break;
692 return false;
695 DockWidget* DockManager::findDockWidgetAt( const QPoint& pos )
697 if (currentDragWidget->eDocking == DockWidget::DockNone ) return 0L;
699 QWidget* p = QApplication::widgetAt( pos );
700 if ( !p ) return 0L;
701 QWidget* w = 0L;
702 findChildDockWidget( w, p, p->mapFromParent(pos) );
703 if ( !w ){
704 if ( !p->inherits("DockWidget") ) return 0L;
705 w = p;
707 if ( qt_find_obj_child( w, "DockSplitter", "DockPaner" ) ) return 0L;
708 if ( qt_find_obj_child( w, "DockTabCtl", "_dock_tab" ) ) return 0L;
709 if ( childDockWidgetList->find(w) != -1 ) return 0L;
710 if ( w->parent() && currentDragWidget->isGroup && w->parent()->inherits("DockTabCtl") ) return 0L;
712 DockWidget* www = (DockWidget*)w;
713 if ( www->sDocking == DockWidget::DockNone ) return 0L;
715 DockWidget::DockPosition curPos = DockWidget::DockDesktop;
716 QPoint cpos = www->mapFromGlobal( pos );
717 QRect r = www->crect();
719 int ww = r.width() / 3;
720 int hh = r.height() / 3;
722 if ( cpos.y() <= hh ){
723 curPos = DockWidget::DockTop;
724 } else
725 if ( cpos.y() >= 2*hh ){
726 curPos = DockWidget::DockBottom;
727 } else
728 if ( cpos.x() <= ww ){
729 curPos = DockWidget::DockLeft;
730 } else
731 if ( cpos.x() >= 2*ww ){
732 curPos = DockWidget::DockRight;
733 } else
734 curPos = DockWidget::DockCenter;
736 if ( !(www->sDocking & (int)curPos) ) return 0L;
737 if ( !(currentDragWidget->eDocking & (int)curPos) ) return 0L;
739 return www;
742 void DockManager::findChildDockWidget( QWidget*& ww, const QWidget* p, const QPoint& pos )
744 if ( p->children() ) {
745 QWidget *w;
746 QObjectListIt it( *p->children() );
747 it.toLast();
748 while ( it.current() ) {
749 if ( it.current()->isWidgetType() ) {
750 w = (QWidget*)it.current();
751 if ( w->isVisible() && w->geometry().contains(pos) ) {
752 if ( w->inherits("DockWidget") ) ww = w;
753 findChildDockWidget( ww, w, w->mapFromParent(pos) );
754 return;
757 --it;
760 return;
763 void DockManager::findChildDockWidget( const QWidget* p, WidgetList*& list )
765 if ( p->children() ) {
766 QWidget *w;
767 QObjectListIt it( *p->children() );
768 it.toLast();
769 while ( it.current() ) {
770 if ( it.current()->isWidgetType() ) {
771 w = (QWidget*)it.current();
772 if ( w->isVisible() ) {
773 if ( w->inherits("DockWidget") ) list->append( w );
774 findChildDockWidget( w, list );
777 --it;
780 return;
783 void DockManager::startDrag( DockWidget* w )
785 if ( w->stayButton->isOn() ) return;
786 currentMoveWidget = 0L;
787 currentDragWidget = w;
788 childDockWidgetList = new WidgetList();
789 childDockWidgetList->append( w );
790 findChildDockWidget( w, childDockWidgetList );
792 if ( mg ) delete mg;
793 mg = new DockMoveManager( w );
794 curPos = DockWidget::DockDesktop;
795 draging = true;
796 mg->doMove( true, true, false);
799 void DockManager::dragMove( DockWidget* dw, QPoint pos )
801 QRect r = dw->crect();
802 QPoint p = dw->mapToGlobal( r.topLeft() );
803 DockWidget::DockPosition oldPos = curPos;
805 if ( dw->parent() )
806 if ( dw->parent()->inherits("DockTabCtl") ){
807 curPos = DockWidget::DockCenter;
808 if ( oldPos != curPos ) mg->setGeometry( p.x()+2, p.y()+2, r.width()-4, r.height()-4 );
809 return;
812 int w = r.width() / 3;
813 int h = r.height() / 3;
815 if ( pos.y() <= h ){
816 curPos = DockWidget::DockTop;
817 w = r.width();
818 } else
819 if ( pos.y() >= 2*h ){
820 curPos = DockWidget::DockBottom;
821 p.setY( p.y() + 2*h );
822 w = r.width();
823 } else
824 if ( pos.x() <= w ){
825 curPos = DockWidget::DockLeft;
826 h = r.height();
827 } else
828 if ( pos.x() >= 2*w ){
829 curPos = DockWidget::DockRight;
830 p.setX( p.x() + 2*w );
831 h = r.height();
832 } else
834 curPos = DockWidget::DockCenter;
835 p.setX( p.x() + w );
836 p.setY( p.y() + h );
839 if ( oldPos != curPos ) mg->setGeometry( p.x(), p.y(), w, h );
842 void DockManager::drop()
844 mg->stop();
845 delete childDockWidgetList;
846 if ( dropCancel ) return;
847 if ( !currentMoveWidget && ((currentDragWidget->eDocking & DockWidget::DockDesktop) == 0) ) return;
849 if ( !currentMoveWidget && !currentDragWidget->parent() )
850 currentDragWidget->move( mg->x(), mg->y() );
851 else
852 currentDragWidget->manualDock( currentMoveWidget, curPos , 50, QPoint(mg->x(), mg->y()) );
855 void DockManager::writeConfig( KConfig* c, QString group )
857 //debug("BEGIN Write Config");
858 if ( !c ) c = kapp->config();
859 if ( group.isEmpty() ) group = "dock_setting_default";
861 c->setGroup( group );
862 c->writeEntry( "Version", DOCK_CONFIG_VERSION );
864 QStrList nameList;
865 QStrList findList;
866 QListIterator<DockWidget> it( *childDock );
867 DockWidget * obj;
869 // collect DockWidget's name
870 QStrList nList;
871 while ( (obj=it.current()) ) {
872 ++it;
873 // debug(" +Add subdock %s", obj->name());
874 nList.append( obj->name() );
877 nList.first();
878 while ( nList.current() ){
879 // debug(" -Try to save %s", nList.current());
880 obj = getDockWidgetFromName( nList.current() );
881 QString cname = obj->name();
882 c->writeEntry( cname+":stayButton", obj->stayButton->isOn() );
883 /*************************************************************************************************/
884 if ( obj->isGroup ){
885 if ( findList.find( obj->firstName ) != -1 && findList.find( obj->lastName ) != -1 ){
887 c->writeEntry( cname+":type", "GROUP");
888 if ( !obj->parent() ){
889 c->writeEntry( cname+":parent", "___null___");
890 c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
891 c->writeEntry( cname+":visible", obj->isVisible());
892 } else {
893 c->writeEntry( cname+":parent", "yes");
895 c->writeEntry( cname+":first_name", obj->firstName );
896 c->writeEntry( cname+":last_name", obj->lastName );
897 c->writeEntry( cname+":orientation", obj->splitterOrientation );
898 c->writeEntry( cname+":sepPos", ((DockSplitter*)obj->widget)->separatorPos() );
900 nameList.append( obj->name() );
901 findList.append( obj->name() );
902 // debug(" Save %s", nList.current());
903 nList.remove();
904 nList.first();
905 } else {
906 /*************************************************************************************************/
907 // debug(" Skip %s", nList.current());
908 // if ( findList.find( obj->firstName ) == -1 )
909 // debug(" ? Not found %s", obj->firstName);
910 // if ( findList.find( obj->lastName ) == -1 )
911 // debug(" ? Not found %s", obj->lastName);
912 nList.next();
913 if ( !nList.current() ) nList.first();
915 } else {
916 /*************************************************************************************************/
917 if ( obj->isTabGroup){
918 c->writeEntry( cname+":type", "TAB_GROUP");
919 if ( !obj->parent() ){
920 c->writeEntry( cname+":parent", "___null___");
921 c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
922 c->writeEntry( cname+":visible", obj->isVisible());
923 } else {
924 c->writeEntry( cname+":parent", "yes");
926 QStrList list;
927 for ( QWidget* w = ((DockTabCtl*)obj->widget)->getFirstPage(); w; w = ((DockTabCtl*)obj->widget)->getNextPage( w ) ){
928 list.append( w->name() );
930 c->writeEntry( cname+":tabNames", list );
931 c->writeEntry( cname+":curTab", ((DockTabCtl*)obj->widget)->visiblePageId() );
933 nameList.append( obj->name() );
934 findList.append( obj->name() ); // not realy need !!!
935 // debug(" Save %s", nList.current());
936 nList.remove();
937 nList.first();
938 } else {
939 /*************************************************************************************************/
940 if ( !obj->parent() ){
941 c->writeEntry( cname+":type", "NULL_DOCK");
942 c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
943 c->writeEntry( cname+":visible", obj->isVisible());
944 } else {
945 c->writeEntry( cname+":type", "DOCK");
947 nameList.append( cname );
948 // debug(" Save %s", nList.current());
949 findList.append( obj->name() );
950 nList.remove();
951 nList.first();
955 c->writeEntry( "NameList", nameList );
957 c->writeEntry( "Main:Geometry", QRect(main->frameGeometry().topLeft(), main->size()) );
958 c->writeEntry( "Main:visible", main->isVisible()); // curently nou use
960 if ( main->inherits("DockMainWindow") ){
961 DockMainWindow* dmain = (DockMainWindow*)main;
962 // for DockMainWindow->setDockView() in reafConfig()
963 c->writeEntry( "Main:view", dmain->getMainViewDockWidget() ? dmain->getMainViewDockWidget()->name():"" );
964 #ifdef DOCK_ORIGINAL
965 c->writeEntry( "Main:dock", dmain->getMainDockWidget() ? dmain->getMainDockWidget()->name() :"" );
966 #endif
969 c->sync();
970 // debug("END Write Config");
973 void DockManager::readConfig( KConfig* c, QString group )
975 if ( !c ) c = kapp->config();
976 if ( group.isEmpty() ) group = "dock_setting_default";
978 c->setGroup( group );
979 QStrList nameList;
980 c->readListEntry( "NameList", nameList );
981 QString ver = c->readEntry( "Version", "0.0.1" );
982 nameList.first();
983 if ( !nameList.current() || ver != DOCK_CONFIG_VERSION ){
984 activate();
985 return;
988 autoCreateDock = new QObjectList();
989 autoCreateDock->setAutoDelete( true );
991 main->hide();
993 QListIterator<DockWidget> it( *childDock );
994 DockWidget * obj;
996 while ( (obj=it.current()) ) {
997 ++it;
998 if ( !obj->isGroup && !obj->isTabGroup )
1000 if ( obj->parent() ) obj->unDock(); else obj->hide();
1004 nameList.first();
1005 while ( nameList.current() ){
1006 QString oname = nameList.current();
1007 QString type = c->readEntry( oname + ":type" );
1008 obj = 0L;
1010 if ( type == "GROUP" ){
1011 DockWidget* first = getDockWidgetFromName( c->readEntry( oname + ":first_name" ) );
1012 DockWidget* last = getDockWidgetFromName( c->readEntry( oname + ":last_name" ) );
1014 int p = c->readNumEntry( oname + ":orientation" );
1015 if ( first && last ){
1016 obj = first->manualDock( last, ( p == 0 ) ? DockWidget::DockLeft : DockWidget::DockTop );
1017 if (obj){
1018 obj->setName( oname );
1019 ((DockSplitter*)obj->widget)->setSeparatorPos( c->readNumEntry( oname + ":sepPos" ) );
1024 if ( type == "TAB_GROUP" ){
1025 QStrList list;
1026 DockWidget* tabDockGroup = 0L;
1027 c->readListEntry( oname+":tabNames", list );
1028 DockWidget* d1 = getDockWidgetFromName( list.first() );
1029 list.next();
1030 DockWidget* d2 = getDockWidgetFromName( list.current() );
1031 tabDockGroup = d2->manualDock( d1, DockWidget::DockCenter );
1032 if ( tabDockGroup ){
1033 DockTabCtl* tab = (DockTabCtl*)tabDockGroup->widget;
1034 list.next();
1035 while ( list.current() && tabDockGroup ){
1036 DockWidget* tabDock = getDockWidgetFromName( list.current() );
1037 tabDockGroup = tabDock->manualDock( d1, DockWidget::DockCenter );
1038 list.next();
1040 if ( tabDockGroup ){
1041 tabDockGroup->setName( oname );
1042 tab->setVisiblePage( c->readNumEntry( oname+":curTab" ) );
1047 if ( type == "NULL_DOCK" || c->readEntry( oname + ":parent") == "___null___" ){
1048 QRect r = c->readRectEntry( oname + ":geometry" );
1049 obj = getDockWidgetFromName( oname );
1050 obj->setGeometry(r);
1052 if ( c->readBoolEntry( oname + ":visible" ) ){
1053 obj->QWidget::show();
1057 if ( type == "DOCK" ){
1058 obj = getDockWidgetFromName( oname );
1061 if ( obj ) obj->stayButton->setOn( c->readBoolEntry( oname+":stayButton", false ) );
1063 nameList.next();
1066 // delete all autocreate dock
1067 delete autoCreateDock;
1068 autoCreateDock = 0L;
1070 if ( main->inherits("DockMainWindow") ){
1071 DockMainWindow* dmain = (DockMainWindow*)main;
1073 QString mv = c->readEntry( "Main:view" );
1074 if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){
1075 DockWidget* mvd = getDockWidgetFromName( mv );
1076 mvd->applyToWidget( dmain );
1077 mvd->show();
1078 dmain->setDockView( mvd );
1080 #ifdef DOCK_ORIGINAL
1081 QString md = c->readEntry( "Main:dock" );
1082 if ( !md.isEmpty() && getDockWidgetFromName( md ) ){
1083 DockWidget* mvd = getDockWidgetFromName( md );
1084 dmain->setMainDockWidget( mvd );
1086 #endif
1089 QRect mr = c->readRectEntry("Main:Geometry");
1090 main->setGeometry(mr);
1091 if ( !main->inherits("QDialog") ) main->show();
1094 DockWidget* DockManager::getDockWidgetFromName( const char* dockName )
1096 QListIterator<DockWidget> it( *childDock );
1097 DockWidget * obj;
1098 while ( (obj=it.current()) ) {
1099 ++it;
1100 if ( QString(obj->name()) == QString(dockName) ) return obj;
1103 DockWidget* autoCreate = 0L;
1104 if ( autoCreateDock ){
1105 autoCreate = new DockWidget( this, dockName, QPixmap("") );
1106 autoCreateDock->append( autoCreate );
1108 return autoCreate;
1111 #ifdef DOCK_ORIGINAL
1112 void DockManager::slotTabShowPopup( int id, QPoint pos )
1114 curTabDockWidget = (DockWidget*)((DockTabCtl*)sender())->page(id);
1115 QPopupMenu menu;
1116 menu.insertItem( "Undock", this, SLOT(slotUndockTab()) );
1117 menu.insertItem( "Hide", this, SLOT(slotHideTab()) );
1118 menu.exec( pos );
1121 void DockManager::slotUndockTab()
1123 curTabDockWidget->manualDock( 0L, DockDesktop, 50, curTabDockWidget->mapToGlobal(curTabDockWidget->frameGeometry().topLeft()));
1124 curTabDockWidget->show();
1127 void DockManager::slotHideTab()
1129 curTabDockWidget->unDock();
1132 void DockManager::slotMenuPopup()
1134 menu->clear();
1135 menuData->clear();
1137 if ( main->isVisible() ){
1138 menu->insertItem( "Hide toplevel window", 0 );
1139 menuData->append( new menuDockData( main, true ) );
1140 } else {
1141 menu->insertItem( "Show toplevel window", 0 );
1142 menuData->append( new menuDockData( main, false ) );
1144 menu->insertSeparator();
1146 QListIterator<DockWidget> it( *childDock );
1147 DockWidget * obj;
1148 int numerator = 1;
1149 while ( (obj=it.current()) ) {
1150 ++it;
1151 if ( obj->mayBeHide() )
1153 menu->insertItem( *obj->pix, QString("Hide ") + obj->caption(), numerator++ );
1154 menuData->append( new menuDockData( obj, true ) );
1157 if ( obj->mayBeShow() )
1159 menu->insertItem( *obj->pix, QString("Show ") + obj->caption(), numerator++ );
1160 menuData->append( new menuDockData( obj, false ) );
1164 #endif // DOCK_ORIGINAL
1166 bool DockWidget::mayBeHide()
1168 bool f = (parent() != manager->main);
1169 return ( !isGroup && !isTabGroup && f && isVisible() && ( eDocking != (int)DockNone ) );
1172 bool DockWidget::mayBeShow()
1174 bool f = (parent() != manager->main);
1175 return ( !isGroup && !isTabGroup && f && !isVisible() );
1178 #ifdef DOCK_ORIGINAL
1179 void DockManager::slotMenuActivated( int id )
1181 menuDockData* data = menuData->at( id );
1183 QWidget * obj = data->dock;
1184 if ( obj->inherits("DockWidget") ){
1185 ((DockWidget*)(data->dock))->changeHideShowState();
1186 } else {
1187 if ( data->hide ){
1188 obj->hide();
1189 } else {
1190 obj->show();
1194 #endif // DOCK_ORIGINAL
1196 void DockWidget::changeHideShowState()
1198 if ( mayBeHide() ){
1199 slotCloseButtonClick();
1200 return;
1203 if ( mayBeShow() ){
1204 if ( manager->main->inherits("DockMainWindow") ){
1205 ((DockMainWindow*)manager->main)->makeDockVisible(this);
1206 } else {
1207 makeDockVisible();
1212 void DockWidget::makeDockVisible()
1214 if ( isVisible() ) return;
1216 if ( parent() && parent()->inherits("DockTabCtl") ){
1217 ((DockTabCtl*)parent())->setVisiblePage( this );
1219 QWidget* p = parentWidget();
1220 while ( p ){
1221 if ( !p->isVisible() ) p->show();
1222 p = p->parentWidget();
1224 show();
1227 DockWidget* DockManager::findWidgetParentDock( QWidget* w )
1229 QListIterator<DockWidget> it( *childDock );
1230 DockWidget * dock;
1231 DockWidget * found = 0L;
1233 while ( (dock=it.current()) ) {
1234 ++it;
1235 if ( dock->widget == w ){ found = dock; break; }
1237 return found;
1240 DockTabCtl* DockManager::createTabCtrl( QWidget *parent, const char *name )
1242 return new DockTabCtl( parent, name );
1245 DockSplitter* DockManager::createDockSplitter(QWidget *parent, const char *name,
1246 KNewPanner::Orientation orient,
1247 KNewPanner::Units units, int pos)
1249 return new DockSplitter(parent, name, orient, units, pos);