00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "mainwindow.h"
00021 #include "dockcontainer.h"
00022
00023 #include "dockcontainer.moc"
00024
00025 #include "kdockwidget_private.h"
00026
00027 #include <qwidgetstack.h>
00028 #include <qlayout.h>
00029 #include <qtimer.h>
00030 #include <qtooltip.h>
00031 #include <kmultitabbar.h>
00032 #include <kglobalsettings.h>
00033
00034 #include <kdebug.h>
00035 #include <kiconloader.h>
00036 #include <kapplication.h>
00037 #include <kconfig.h>
00038 #include <klocale.h>
00039
00040
00041 static const char* const kmdi_not_close_xpm[]={
00042 "5 5 2 1",
00043 "# c black",
00044 ". c None",
00045 "#####",
00046 "#...#",
00047 "#...#",
00048 "#...#",
00049 "#####"};
00050
00051 namespace KMDI
00052 {
00053
00054
00055 DockContainer::DockContainer(QWidget *parent, QWidget *win, int position, int flags)
00056 : QWidget(parent),KDockContainer()
00057 {
00058 m_tabSwitching = false;
00059 m_block=false;
00060 m_inserted=-1;
00061 m_mainWin = win;
00062 oldtab=-1;
00063 mTabCnt=0;
00064 m_position = position;
00065 m_previousTab=-1;
00066 m_separatorPos = 18000;
00067 m_movingState=NotMoving;
00068 m_startEvent=0;
00069 kdDebug(760)<<"DockContainer created"<<endl;
00070
00071 QBoxLayout *l;
00072 m_vertical=!((position==KDockWidget::DockTop) || (position==KDockWidget::DockBottom));
00073
00074 if (!m_vertical)
00075 l=new QVBoxLayout(this);
00076 else
00077 l=new QHBoxLayout(this);
00078
00079 l->setAutoAdd(false);
00080
00081 m_tb=new KMultiTabBar(((position==KDockWidget::DockTop) || (position==KDockWidget::DockBottom))?
00082 KMultiTabBar::Horizontal:KMultiTabBar::Vertical,this);
00083
00084 m_tb->setStyle(KMultiTabBar::KMultiTabBarStyle(flags));
00085 m_tb->showActiveTabTexts(true);
00086
00087 m_tb->setPosition((position==KDockWidget::DockLeft)?KMultiTabBar::Left:
00088 (position==KDockWidget::DockBottom)?KMultiTabBar::Bottom:
00089 (position==KDockWidget::DockTop)?KMultiTabBar::Top:KMultiTabBar::Right);
00090
00091 m_ws=new QWidgetStack(this);
00092
00093 m_ws->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
00094
00095 if ( (position==KDockWidget::DockLeft) || (position==KDockWidget::DockTop))
00096 {
00097 l->add(m_tb);
00098 l->add(m_ws);
00099 }
00100 else
00101 {
00102 l->add(m_ws);
00103 l->add(m_tb);
00104 }
00105
00106 l->activate();
00107 m_ws->hide();
00108 m_tb->installEventFilter(this);
00109 }
00110
00111 void DockContainer::setStyle(int style) {
00112 if (m_tb) m_tb->setStyle(KMultiTabBar::KMultiTabBarStyle(style));
00113 }
00114
00115 DockContainer::~DockContainer()
00116 {
00117 QMap<KDockWidget*,int>::iterator it;
00118 while (m_map.count()) {
00119 it = m_map.begin();
00120 KDockWidget *w=it.key();
00121 if (m_overlapButtons.contains(w)) {
00122 (static_cast<KDockWidgetHeader*>(w->getHeader()->qt_cast("KDockWidgetHeader")))->removeButton(m_overlapButtons[w]);
00123 m_overlapButtons.remove(w);
00124 }
00125 m_map.remove(w);
00126 w->undock();
00127 }
00128 deactivated(this);
00129 }
00130
00131
00132 void DockContainer::init()
00133 {
00134 bool overlap = isOverlapMode();
00135 if (m_vertical)
00136 {
00137 parentDockWidget()->setForcedFixedWidth(m_tb->width());
00138 activateOverlapMode(m_tb->width());
00139 }
00140 else
00141 {
00142 parentDockWidget()->setForcedFixedHeight(m_tb->height());
00143 activateOverlapMode(m_tb->height());
00144 }
00145
00146 if (!overlap) deactivateOverlapMode();
00147
00148
00149 if ( parentDockWidget() && parentDockWidget()->parent() )
00150 {
00151 KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()->
00152 parent()->qt_cast("KDockSplitter"));
00153 if ( sp )
00154 sp->setSeparatorPosX( m_separatorPos );
00155 }
00156 }
00157
00158 KDockWidget *DockContainer::parentDockWidget()
00159 {
00160 return ((KDockWidget*)parent());
00161 }
00162
00163 void DockContainer::insertWidget (KDockWidget *dwdg, QPixmap pixmap, const QString &text, int &)
00164 {
00165 KDockWidget* w = (KDockWidget*) dwdg;
00166 int tab;
00167 bool alreadyThere=m_map.contains(w);
00168
00169 if (alreadyThere)
00170 {
00171 tab=m_map[w];
00172 if (m_ws->addWidget(w,tab)!=tab) kdDebug(760)<<"ERROR COULDN'T READD WIDGET************"<<endl;
00173 kdDebug(760)<<"READDED WIDGET***********************************"<<endl;
00174
00175
00176 }
00177 else
00178 {
00179 tab=m_ws->addWidget(w);
00180 m_map.insert(w,tab);
00181 m_revMap.insert(tab,w);
00182
00183
00184 if (((KDockWidget*)parentWidget())->mayBeShow())
00185 ((KDockWidget*)parentWidget())->dockBack();
00186
00187 if (w->getHeader()->qt_cast("KDockWidgetHeader"))
00188 {
00189 kdDebug(760)<<"*** KDockWidgetHeader has been found"<<endl;
00190
00191 KDockWidgetHeader *hdr=static_cast<KDockWidgetHeader*>(w->getHeader()->
00192 qt_cast("KDockWidgetHeader"));
00193
00194 KDockButton_Private *btn = new KDockButton_Private( hdr, "OverlapButton" );
00195
00196 QToolTip::add( btn, i18n("Switch between overlap and side by side mode", "Overlap") );
00197
00198 btn->setToggleButton( true );
00199 btn->setPixmap( const_cast< const char** >(kmdi_not_close_xpm) );
00200 hdr->addButton(btn);
00201 m_overlapButtons.insert(w,btn);
00202 btn->setOn(!isOverlapMode());
00203
00204 connect(btn,SIGNAL(clicked()),this,SLOT(changeOverlapMode()));
00205 }
00206
00207 m_tb->appendTab(pixmap.isNull()?SmallIcon("misc"):pixmap,tab,w->tabPageLabel());
00208 m_tb->tab(tab)->installEventFilter( this );
00209 kdDebug(760)<<"NAMENAMENAMENAME:===========================:"<<w->tabPageLabel()<<endl;
00210
00211
00212
00213 connect(m_tb->tab(tab),SIGNAL(clicked(int)),this,SLOT(tabClicked(int)));
00214
00215 kdDebug(760)<<"DockContainer::insertWidget()"<<endl;
00216
00217
00218
00219 mTabCnt++;
00220 m_inserted=tab;
00221 int dummy=0;
00222
00223 KDockContainer::insertWidget(w,pixmap,text,dummy);
00224 itemNames.append(w->name());
00225 tabCaptions.insert(w->name(),w->tabPageLabel());
00226 tabTooltips.insert(w->name(),w->toolTipString());
00227
00228
00229 }
00230
00231
00232 }
00233
00234
00235 bool DockContainer::eventFilter( QObject *obj, QEvent *event )
00236 {
00237 if (obj==m_tb) {
00238 if ( (event->type()==QEvent::Resize) && (m_ws->isHidden()) ) {
00239 QSize size=((QResizeEvent*)event)->size();
00240 if (m_vertical)
00241 parentDockWidget()->setForcedFixedWidth(size.width());
00242 else
00243 parentDockWidget()->setForcedFixedHeight(size.height());
00244 }
00245 }
00246 else
00247 switch ( event->type() ){
00248 case QEvent::MouseButtonPress:
00249 {
00250 KDockWidget * w=m_revMap[dynamic_cast<KMultiTabBarTab*>(obj)->id()];
00251 if (!w) {
00252 kdDebug()<<"NoWidget"<<endl;
00253 break;
00254 }
00255 if (!w->getHeader()) {
00256 kdDebug()<<"NO HEADER"<<endl;
00257 break;
00258 }
00259 KDockWidgetHeader *hdr=static_cast<KDockWidgetHeader*>(w->getHeader()->
00260 qt_cast("KDockWidgetHeader"));
00261 if (!hdr) {
00262 kdDebug()<<"Wrong header type in DockContainer::eventFilter"<<endl;
00263 break;
00264 }
00265 m_dockManager=w->dockManager();
00266 m_dragPanel=hdr->dragPanel();
00267 if (m_dragPanel) m_movingState=WaitingForMoveStart;
00268 delete m_startEvent;
00269 m_startEvent=new QMouseEvent(* ((QMouseEvent*)event));
00270 }
00271 break;
00272 case QEvent::MouseButtonRelease:
00273 if (m_movingState==Moving) {
00274 m_movingState=NotMoving;
00275 QApplication::postEvent(m_dragPanel,new QMouseEvent(* ( (QMouseEvent*)event)));
00276 delete m_startEvent;
00277 m_startEvent=0;
00278 }
00279 break;
00280 case QEvent::MouseMove:
00281 if (m_movingState==WaitingForMoveStart) {
00282 QPoint p( ((QMouseEvent*)event)->pos() - m_startEvent->pos() );
00283 if( p.manhattanLength() > KGlobalSettings::dndEventDelay()) {
00284 m_dockManager->eventFilter(m_dragPanel,m_startEvent);
00285 m_dockManager->eventFilter(m_dragPanel,event);
00286 m_movingState=Moving;
00287 }
00288 } else if (m_movingState==Moving) {
00289 m_dockManager->eventFilter(m_dragPanel,event);
00290 }
00291 break;
00292 default:
00293 break;
00294
00295 }
00296 return false;
00297
00298 }
00299
00300 void DockContainer::showWidget(KDockWidget *w) {
00301 if (!m_map.contains(w)) return;
00302
00303 kdDebug()<<"KMDI::DockContainer::<showWidget"<<endl;
00304 int id=m_map[w];
00305 m_tb->setTab(id,true);
00306 tabClicked(id);
00307
00308 }
00309
00310 void DockContainer::changeOverlapMode()
00311 {
00312 const KDockButton_Private *btn=dynamic_cast<const KDockButton_Private*>(sender());
00313
00314 kdDebug(760)<<"DockContainer::changeOverlapMode: button=="<<btn<<endl;
00315
00316 if (!btn) return;
00317
00318 if (!btn->isOn()) {
00319 kdDebug(760)<<"DockContainer::changeOverlapMode: activateOverlapMode"<<endl;
00320 if (m_vertical) {
00321 activateOverlapMode(m_tb->width());
00322 }
00323 else
00324 {
00325 activateOverlapMode(m_tb->height());
00326 }
00327 } else {
00328 kdDebug(760)<<"DockContainer::changeOverlapMode: deactivateOverlapMode"<<endl;
00329 deactivateOverlapMode();
00330 }
00331
00332 for (QMap<KDockWidget*,KDockButton_Private*>::iterator it=m_overlapButtons.begin();
00333 it!=m_overlapButtons.end();++it)
00334 it.data()->setOn(!isOverlapMode());
00335 }
00336
00337 void DockContainer::hideIfNeeded() {
00338 kdDebug(760)<<"************************* hideIfNeeded *************************"<<endl;
00339 if (!itemNames.count())
00340 ((KDockWidget*)parentWidget())->undock();
00341 }
00342
00343 void DockContainer::removeWidget(KDockWidget* dwdg)
00344 {
00345 KDockWidget* w = (KDockWidget*) dwdg;
00346 if (!m_map.contains(w)) return;
00347 int id=m_map[w];
00348 if (m_tb->isTabRaised(id)) {
00349
00350
00351 m_tb->setTab(id,false);
00352 m_tabSwitching = false;
00353 tabClicked(id);
00354 }
00355 m_tb->removeTab(id);
00356 m_ws->removeWidget(w);
00357 m_map.remove(w);
00358 m_revMap.remove(id);
00359 if (m_overlapButtons.contains(w)) {
00360 (static_cast<KDockWidgetHeader*>(w->getHeader()->qt_cast("KDockWidgetHeader")))->removeButton(m_overlapButtons[w]);
00361 m_overlapButtons.remove(w);
00362 }
00363 KDockContainer::removeWidget(w);
00364 itemNames.remove(w->name());
00365 tabCaptions.remove(w->name());
00366 tabTooltips.remove(w->name());
00367 if (!itemNames.count())
00368 ((KDockWidget*)parentWidget())->undock();
00369 }
00370
00371 void DockContainer::undockWidget(KDockWidget *dwdg)
00372 {
00373 KDockWidget* w = (KDockWidget*) dwdg;
00374
00375 if (!m_map.contains(w))
00376 return;
00377
00378 int id=m_map[w];
00379 if (m_tb->isTabRaised(id)) {
00380 kdDebug(760)<<"Wiget has been undocked, setting tab down"<<endl;
00381 m_tb->setTab(id,false);
00382 tabClicked(id);
00383 }
00384 }
00385
00386 void DockContainer::tabClicked(int t)
00387 {
00388 kdDebug(760)<<"DockContainer::tabClicked()"<<endl;
00389 bool call_makeVisible=!m_tabSwitching;
00390 m_tabSwitching=true;
00391 if ((t!=-1) && m_tb->isTabRaised(t))
00392 {
00393 if (m_ws->isHidden())
00394 {
00395 m_ws->show ();
00396 parentDockWidget()->restoreFromForcedFixedSize();
00397 }
00398 if (!m_ws->widget(t))
00399 {
00400 m_revMap[t]->manualDock(parentDockWidget(),KDockWidget::DockCenter,20);
00401 if (call_makeVisible) m_revMap[t]->makeDockVisible();
00402 m_tabSwitching=false;
00403 emit activated(this);
00404 return;
00405 }
00406 m_ws->raiseWidget(t);
00407 if (m_ws->widget(t)) {
00408 KDockWidget *tmpDw=static_cast<KDockWidget*>(m_ws->widget(t)->qt_cast("KDockWidget"));
00409 if (tmpDw) {
00410 if (tmpDw->getWidget()) tmpDw->getWidget()->setFocus();
00411 } else kdDebug(760)<<"Something really weird is going on"<<endl;
00412 } else
00413 kdDebug(760)<<"DockContainer::tabClicked(int): m_ws->widget(t)==0 "<<endl;
00414
00415 if (oldtab!=t) m_tb->setTab(oldtab,false);
00416 m_tabSwitching=true;
00417 oldtab=t;
00418 emit activated(this);
00419 }
00420 else
00421 {
00422
00423 if ( parentDockWidget() && parentDockWidget()->parent() )
00424 {
00425 KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()->
00426 parent()->qt_cast("KDockSplitter"));
00427 if ( sp )
00428 m_separatorPos = sp->separatorPos();
00429 }
00430 m_previousTab=t;
00431
00432 if (m_block) return;
00433 emit deactivated(this);
00434 m_block=true;
00435 if (m_ws->widget(t))
00436 {
00437
00438 }
00439 m_block=false;
00440 m_ws->hide ();
00441
00442
00443 kdDebug(760)<<"Fixed Width:"<<m_tb->width()<<endl;
00444 if (m_vertical)
00445 parentDockWidget()->setForcedFixedWidth(m_tb->width());
00446 else
00447 parentDockWidget()->setForcedFixedHeight(m_tb->height());
00448 }
00449 m_tabSwitching=false;
00450 }
00451
00452 void DockContainer::setToolTip (KDockWidget *, QString &s)
00453 {
00454 kdDebug(760)<<"***********************************Setting tooltip for a widget: "<<s<<endl;
00455 }
00456
00457 void DockContainer::setPixmap(KDockWidget* widget ,const QPixmap& pixmap)
00458 {
00459 int id=m_ws->id(widget);
00460 if (id==-1) return;
00461 KMultiTabBarTab *tab=m_tb->tab(id);
00462 tab->setIcon(pixmap.isNull()?SmallIcon("misc"):pixmap);
00463 }
00464
00465 void DockContainer::save(KConfig* cfg,const QString& group_or_prefix)
00466 {
00467
00468 QString grp=cfg->group();
00469 cfg->deleteGroup(group_or_prefix+QString("::%1").arg(parent()->name()));
00470 cfg->setGroup(group_or_prefix+QString("::%1").arg(parent()->name()));
00471
00472
00473 cfg->writeEntry("overlapMode",isOverlapMode());
00474
00475
00476 if ( parentDockWidget() && parentDockWidget()->parent() )
00477 {
00478 KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()->
00479 parent()->qt_cast("KDockSplitter"));
00480 if ( sp )
00481 cfg->writeEntry( "separatorPosition", m_separatorPos );
00482 }
00483
00484 QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
00485 QPtrListIterator<KMultiTabBarTab> it(*tl);
00486 QStringList::Iterator it2=itemNames.begin();
00487 int i=0;
00488 for (;it.current()!=0;++it,++it2)
00489 {
00490
00491 cfg->writeEntry(QString("widget%1").arg(i),(*it2));
00492 QString s=tabCaptions[*it2];
00493 if (!s.isEmpty()) {
00494 cfg->writeEntry(QString("widget%1-tabCaption").arg(i),s);
00495 }
00496 s=tabTooltips[*it2];
00497 if (!s.isEmpty()) {
00498 cfg->writeEntry(QString("widget%1-tabTooltip").arg(i),s);
00499 }
00500
00501 if (m_tb->isTabRaised(it.current()->id()))
00502 cfg->writeEntry(m_ws->widget(it.current()->id())->name(),true);
00503 ++i;
00504 }
00505
00506 cfg->setGroup(grp);
00507 }
00508
00509 void DockContainer::load(KConfig* cfg,const QString& group_or_prefix)
00510 {
00511 QString grp=cfg->group();
00512 cfg->setGroup(group_or_prefix+QString("::%1").arg(parent()->name()));
00513
00514 if (cfg->readBoolEntry("overlapMode"))
00515 activateOverlapMode( m_vertical?m_tb->width():m_tb->height() );
00516 else
00517 deactivateOverlapMode();
00518
00519 m_separatorPos = cfg->readNumEntry( "separatorPosition", 18000 );
00520
00521 int i=0;
00522 QString raise;
00523 while (true)
00524 {
00525 QString dwn=cfg->readEntry(QString("widget%1").arg(i));
00526 if (dwn.isEmpty()) break;
00527 kdDebug(760)<<"*************************************************************Configuring dockwidget :"<<dwn<<endl;
00528 KDockWidget *dw=((KDockWidget*)parent())->dockManager()->getDockWidgetFromName(dwn);
00529 if (dw)
00530 {
00531 QString s=cfg->readEntry(QString("widget%1-tabCaption").arg(i));
00532 if (!s.isEmpty()) {
00533 dw->setTabPageLabel(s);
00534 }
00535 s=cfg->readEntry(QString("widget%1-tabTooltip").arg(i));
00536 if (!s.isEmpty()) {
00537 dw->setToolTipString(s);
00538 }
00539 dw->manualDock((KDockWidget*)parent(),KDockWidget::DockCenter);
00540 }
00541 if (cfg->readBoolEntry(dwn,false)) raise=dwn;
00542 i++;
00543
00544 }
00545
00546 QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
00547 QPtrListIterator<KMultiTabBarTab> it1(*tl);
00548 m_ws->hide();
00549 if (m_vertical)
00550 parentDockWidget()->setForcedFixedWidth(m_tb->width());
00551 else
00552 parentDockWidget()->setForcedFixedHeight(m_tb->height());
00553 for (;it1.current()!=0;++it1)
00554 {
00555 m_tb->setTab(it1.current()->id(),false);
00556 }
00557 kapp->syncX();
00558 m_delayedRaise=-1;
00559
00560 for (QMap<KDockWidget*,KDockButton_Private*>::iterator it=m_overlapButtons.begin();
00561 it!=m_overlapButtons.end();++it)
00562 it.data()->setOn(!isOverlapMode());
00563
00564 if (!raise.isEmpty())
00565 {
00566 for (QMap<KDockWidget*,int>::iterator it=m_map.begin();it!=m_map.end();++it)
00567 {
00568 if (it.key()->name()==raise)
00569 {
00570
00571
00572
00573
00574
00575
00576
00577 m_delayedRaise=it.data();
00578 QTimer::singleShot(0,this,SLOT(delayedRaise()));
00579 kdDebug(760)<<"************** raising *******: "<<it.key()->name()<<endl;
00580 break;
00581 }
00582 }
00583
00584 }
00585 if (m_delayedRaise==-1) QTimer::singleShot(0,this,SLOT(init()));
00586 cfg->setGroup(grp);
00587
00588 }
00589
00590 void DockContainer::delayedRaise()
00591 {
00592 m_tb->setTab(m_delayedRaise,true);
00593 tabClicked(m_delayedRaise);
00594 }
00595
00596 void DockContainer::collapseOverlapped()
00597 {
00598 if (m_tabSwitching) return;
00599 if (isOverlapMode()){
00600 QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
00601 QPtrListIterator<KMultiTabBarTab> it(*tl);
00602 for(;it.current();++it) {
00603 if (it.current()->isOn()) {
00604 kdDebug(760)<<"Lowering TAB"<<endl;
00605 it.current()->setState(false);
00606 tabClicked(it.current()->id());
00607 }
00608 }
00609 }
00610 }
00611
00612 void DockContainer::toggle() {
00613 kdDebug(760)<<"DockContainer:activate"<<endl;
00614 if (m_tb->isTabRaised(oldtab)) {
00615 m_tb->setTab(oldtab,false);
00616 tabClicked(oldtab);
00617
00618
00619
00620
00621 } else {
00622 kdDebug(760)<<"DockContainer::toggle(): raising tab"<<endl;
00623 if (m_tb->tab(m_previousTab)==0) {
00624 if (m_tb->tabs()->count()==0) return;
00625 m_previousTab=m_tb->tabs()->getFirst()->id();
00626 }
00627 m_tb->setTab(m_previousTab,true);
00628 tabClicked(m_previousTab);
00629 }
00630 }
00631
00632 void DockContainer::prevToolView() {
00633 QPtrList<KMultiTabBarTab>* tabs=m_tb->tabs();
00634 int pos=tabs->findRef(m_tb->tab(oldtab));
00635 if (pos==-1) return;
00636 pos--;
00637 if (pos<0) pos=tabs->count()-1;
00638 KMultiTabBarTab *tab=tabs->at(pos);
00639 if (!tab) return;
00640 m_tb->setTab(tab->id(),true);
00641 tabClicked(tab->id());
00642 }
00643
00644 void DockContainer::nextToolView() {
00645 QPtrList<KMultiTabBarTab>* tabs=m_tb->tabs();
00646 int pos=tabs->findRef(m_tb->tab(oldtab));
00647 if (pos==-1) return;
00648 pos++;
00649 if (pos>=(int)tabs->count()) pos=0;
00650 KMultiTabBarTab *tab=tabs->at(pos);
00651 if (!tab) return;
00652 m_tb->setTab(tab->id(),true);
00653 tabClicked(tab->id());
00654 }
00655
00656 }
00657
00658