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