diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch) | |
tree | 5ac38a06f3dde268dc7927dc155896926aaf7012 /kmdi | |
download | tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kmdi')
71 files changed, 15486 insertions, 0 deletions
diff --git a/kmdi/Makefile.am b/kmdi/Makefile.am new file mode 100644 index 000000000..9eb6d8e71 --- /dev/null +++ b/kmdi/Makefile.am @@ -0,0 +1,20 @@ +SUBDIRS = kmdi . test + +INCLUDES = -I$(top_srcdir)/kmdi/res -I$(top_srcdir)/kutils -I$(top_srcdir) -I$(top_srcdir)/kmdi $(all_includes) + +lib_LTLIBRARIES = libkmdi.la +libkmdi_la_LDFLAGS = $(all_libraries) -version-info 1:0 +libkmdi_la_LIBADD = $(LIB_KPARTS) $(top_builddir)/kutils/libkutils.la + +libkmdi_la_SOURCES = kmdichildarea.cpp kmdichildfrm.cpp kmdichildfrmcaption.cpp \ + kmdichildview.cpp kmdimainfrm.cpp kmditaskbar.cpp kmdidockcontainer.cpp \ + kmditoolviewaccessor.cpp kmdiguiclient.cpp kmdidocumentviewtabwidget.cpp \ + kmdifocuslist.cpp + +include_HEADERS = kmdichildarea.h kmdichildfrm.h kmdichildfrmcaption.h kmdidefines.h \ + kmdiiterator.h kmdilistiterator.h kmdimainfrm.h kmdinulliterator.h \ + kmditaskbar.h kmdichildview.h kmditoolviewaccessor.h + +METASOURCES = AUTO + +include ../admin/Doxyfile.am diff --git a/kmdi/TODO b/kmdi/TODO new file mode 100644 index 000000000..b04df59db --- /dev/null +++ b/kmdi/TODO @@ -0,0 +1,4 @@ +- fix .xpm file stuff to be more KDE-conform +- if QDockWindow becomes more protected and virtual than private, change from base class KDockWidget to QDockWindow +- add splitter mode for Kate-like MDI appearance +- fix KDE style guide (allow MDI where it is sensefull) diff --git a/kmdi/kmdi/Makefile.am b/kmdi/kmdi/Makefile.am new file mode 100644 index 000000000..494d5866a --- /dev/null +++ b/kmdi/kmdi/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = -I$(top_srcdir)/kutils -I$(top_srcdir) -I$(top_srcdir)/kmdi $(all_includes) + +lib_LTLIBRARIES = libkmdi2.la +libkmdi2_la_LDFLAGS = $(all_libraries) -version-info 1:0 +libkmdi2_la_LIBADD = $(LIB_KPARTS) $(top_builddir)/kutils/libkutils.la + +libkmdi2_la_SOURCES = mainwindow.cpp dockcontainer.cpp toolviewaccessor.cpp guiclient.cpp tabwidget.cpp + +kmdiincludedir = $(includedir)/kmdi +kmdiinclude_HEADERS = global.h mainwindow.h toolviewaccessor.h tabwidget.h + +METASOURCES = AUTO + +include ../../admin/Doxyfile.am diff --git a/kmdi/kmdi/dockcontainer.cpp b/kmdi/kmdi/dockcontainer.cpp new file mode 100644 index 000000000..f1012d3dd --- /dev/null +++ b/kmdi/kmdi/dockcontainer.cpp @@ -0,0 +1,658 @@ +/* This file is part of the KDE project + Copyright (C) 2002, 2003 Joseph Wenninger <jowenn@kde.org> + Copyright (C) 2002, 2004 Christoph Cullmann <cullmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "mainwindow.h" +#include "dockcontainer.h" + +#include "dockcontainer.moc" + +#include "kdockwidget_private.h" + +#include <qwidgetstack.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <kmultitabbar.h> +#include <kglobalsettings.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <kapplication.h> +#include <kconfig.h> +#include <klocale.h> + +//TODO: Well, this is already defined in kdeui/kdockwidget.cpp +static const char* const kmdi_not_close_xpm[]={ +"5 5 2 1", +"# c black", +". c None", +"#####", +"#...#", +"#...#", +"#...#", +"#####"}; + +namespace KMDI +{ + + +DockContainer::DockContainer(QWidget *parent, QWidget *win, int position, int flags) +: QWidget(parent),KDockContainer() +{ + m_tabSwitching = false; + m_block=false; + m_inserted=-1; + m_mainWin = win; + oldtab=-1; + mTabCnt=0; + m_position = position; + m_previousTab=-1; + m_separatorPos = 18000; + m_movingState=NotMoving; + m_startEvent=0; + kdDebug(760)<<"DockContainer created"<<endl; + + QBoxLayout *l; + m_vertical=!((position==KDockWidget::DockTop) || (position==KDockWidget::DockBottom)); + + if (!m_vertical) + l=new QVBoxLayout(this); + else + l=new QHBoxLayout(this); + + l->setAutoAdd(false); + + m_tb=new KMultiTabBar(((position==KDockWidget::DockTop) || (position==KDockWidget::DockBottom))? + KMultiTabBar::Horizontal:KMultiTabBar::Vertical,this); + + m_tb->setStyle(KMultiTabBar::KMultiTabBarStyle(flags)); + m_tb->showActiveTabTexts(true); + + m_tb->setPosition((position==KDockWidget::DockLeft)?KMultiTabBar::Left: + (position==KDockWidget::DockBottom)?KMultiTabBar::Bottom: + (position==KDockWidget::DockTop)?KMultiTabBar::Top:KMultiTabBar::Right); + + m_ws=new QWidgetStack(this); + + m_ws->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding)); + + if ( (position==KDockWidget::DockLeft) || (position==KDockWidget::DockTop)) + { + l->add(m_tb); + l->add(m_ws); + } + else + { + l->add(m_ws); + l->add(m_tb); + } + + l->activate(); + m_ws->hide(); + m_tb->installEventFilter(this); +} + +void DockContainer::setStyle(int style) { + if (m_tb) m_tb->setStyle(KMultiTabBar::KMultiTabBarStyle(style)); +} + +DockContainer::~DockContainer() +{ + QMap<KDockWidget*,int>::iterator it; + while (m_map.count()) { + it = m_map.begin(); + KDockWidget *w=it.key(); + if (m_overlapButtons.contains(w)) { + (static_cast<KDockWidgetHeader*>(w->getHeader()->qt_cast("KDockWidgetHeader")))->removeButton(m_overlapButtons[w]); + m_overlapButtons.remove(w); + } + m_map.remove(w); + w->undock(); + } + deactivated(this); +} + + +void DockContainer::init() +{ + bool overlap = isOverlapMode(); + if (m_vertical) + { + parentDockWidget()->setForcedFixedWidth(m_tb->width()); + activateOverlapMode(m_tb->width()); + } + else + { + parentDockWidget()->setForcedFixedHeight(m_tb->height()); + activateOverlapMode(m_tb->height()); + } + + if (!overlap) deactivateOverlapMode(); + + // try to restore splitter size + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()-> + parent()->qt_cast("KDockSplitter")); + if ( sp ) + sp->setSeparatorPosX( m_separatorPos ); + } +} + +KDockWidget *DockContainer::parentDockWidget() +{ + return ((KDockWidget*)parent()); +} + +void DockContainer::insertWidget (KDockWidget *dwdg, QPixmap pixmap, const QString &text, int &) +{ + KDockWidget* w = (KDockWidget*) dwdg; + int tab; + bool alreadyThere=m_map.contains(w); + + if (alreadyThere) + { + tab=m_map[w]; + if (m_ws->addWidget(w,tab)!=tab) kdDebug(760)<<"ERROR COULDN'T READD WIDGET************"<<endl; + kdDebug(760)<<"READDED WIDGET***********************************"<<endl; +/*JOWENN m_tb->setTab(tab,true); + tabClicked(tab);*/ + } + else + { + tab=m_ws->addWidget(w); + m_map.insert(w,tab); + m_revMap.insert(tab,w); + + + if (((KDockWidget*)parentWidget())->mayBeShow()) + ((KDockWidget*)parentWidget())->dockBack(); + + if (w->getHeader()->qt_cast("KDockWidgetHeader")) + { + kdDebug(760)<<"*** KDockWidgetHeader has been found"<<endl; + + KDockWidgetHeader *hdr=static_cast<KDockWidgetHeader*>(w->getHeader()-> + qt_cast("KDockWidgetHeader")); + + KDockButton_Private *btn = new KDockButton_Private( hdr, "OverlapButton" ); + + QToolTip::add( btn, i18n("Switch between overlap and side by side mode", "Overlap") ); + + btn->setToggleButton( true ); + btn->setPixmap( const_cast< const char** >(kmdi_not_close_xpm) ); + hdr->addButton(btn); + m_overlapButtons.insert(w,btn); + btn->setOn(!isOverlapMode()); + + connect(btn,SIGNAL(clicked()),this,SLOT(changeOverlapMode())); + } + + m_tb->appendTab(pixmap.isNull()?SmallIcon("misc"):pixmap,tab,w->tabPageLabel()); + m_tb->tab(tab)->installEventFilter( this ); + kdDebug(760)<<"NAMENAMENAMENAME:===========================:"<<w->tabPageLabel()<<endl; + +//FB m_tb->setTab(tab,true); + + connect(m_tb->tab(tab),SIGNAL(clicked(int)),this,SLOT(tabClicked(int))); + + kdDebug(760)<<"DockContainer::insertWidget()"<<endl; + +//FB m_tb->setTab(oldtab,false); + + mTabCnt++; + m_inserted=tab; + int dummy=0; +//FB tabClicked(tab); + KDockContainer::insertWidget(w,pixmap,text,dummy); + itemNames.append(w->name()); + tabCaptions.insert(w->name(),w->tabPageLabel()); + tabTooltips.insert(w->name(),w->toolTipString()); + + + } + +//FB m_ws->raiseWidget(tab); +} + + +bool DockContainer::eventFilter( QObject *obj, QEvent *event ) +{ + if (obj==m_tb) { + if ( (event->type()==QEvent::Resize) && (m_ws->isHidden()) ) { + QSize size=((QResizeEvent*)event)->size(); + if (m_vertical) + parentDockWidget()->setForcedFixedWidth(size.width()); + else + parentDockWidget()->setForcedFixedHeight(size.height()); + } + } + else + switch ( event->type() ){ + case QEvent::MouseButtonPress: + { + KDockWidget * w=m_revMap[dynamic_cast<KMultiTabBarTab*>(obj)->id()]; + if (!w) { + kdDebug()<<"NoWidget"<<endl; + break; + } + if (!w->getHeader()) { + kdDebug()<<"NO HEADER"<<endl; + break; + } + KDockWidgetHeader *hdr=static_cast<KDockWidgetHeader*>(w->getHeader()-> + qt_cast("KDockWidgetHeader")); + if (!hdr) { + kdDebug()<<"Wrong header type in DockContainer::eventFilter"<<endl; + break; + } + m_dockManager=w->dockManager(); + m_dragPanel=hdr->dragPanel(); + if (m_dragPanel) m_movingState=WaitingForMoveStart; + delete m_startEvent; + m_startEvent=new QMouseEvent(* ((QMouseEvent*)event)); + } + break; + case QEvent::MouseButtonRelease: + if (m_movingState==Moving) { + m_movingState=NotMoving; + QApplication::postEvent(m_dragPanel,new QMouseEvent(* ( (QMouseEvent*)event))); + delete m_startEvent; + m_startEvent=0; + } + break; + case QEvent::MouseMove: + if (m_movingState==WaitingForMoveStart) { + QPoint p( ((QMouseEvent*)event)->pos() - m_startEvent->pos() ); + if( p.manhattanLength() > KGlobalSettings::dndEventDelay()) { + m_dockManager->eventFilter(m_dragPanel,m_startEvent); + m_dockManager->eventFilter(m_dragPanel,event); + m_movingState=Moving; + } + } else if (m_movingState==Moving) { + m_dockManager->eventFilter(m_dragPanel,event); + } + break; + default: + break; + + } + return false; + +} + +void DockContainer::showWidget(KDockWidget *w) { + if (!m_map.contains(w)) return; + + kdDebug()<<"KMDI::DockContainer::<showWidget"<<endl; + int id=m_map[w]; + m_tb->setTab(id,true); + tabClicked(id); + +} + +void DockContainer::changeOverlapMode() +{ + const KDockButton_Private *btn=dynamic_cast<const KDockButton_Private*>(sender()); + + kdDebug(760)<<"DockContainer::changeOverlapMode: button=="<<btn<<endl; + + if (!btn) return; + + if (!btn->isOn()) { + kdDebug(760)<<"DockContainer::changeOverlapMode: activateOverlapMode"<<endl; + if (m_vertical) { + activateOverlapMode(m_tb->width()); + } + else + { + activateOverlapMode(m_tb->height()); + } + } else { + kdDebug(760)<<"DockContainer::changeOverlapMode: deactivateOverlapMode"<<endl; + deactivateOverlapMode(); + } + + for (QMap<KDockWidget*,KDockButton_Private*>::iterator it=m_overlapButtons.begin(); + it!=m_overlapButtons.end();++it) + it.data()->setOn(!isOverlapMode()); +} + +void DockContainer::hideIfNeeded() { + kdDebug(760)<<"************************* hideIfNeeded *************************"<<endl; + if (!itemNames.count()) + ((KDockWidget*)parentWidget())->undock(); +} + +void DockContainer::removeWidget(KDockWidget* dwdg) +{ + KDockWidget* w = (KDockWidget*) dwdg; + if (!m_map.contains(w)) return; + int id=m_map[w]; + if (m_tb->isTabRaised(id)) { + //why do we hide the tab if we're just going + //to remove it? - mattr 2004-10-26 + m_tb->setTab(id,false); + m_tabSwitching = false; + tabClicked(id); + } + m_tb->removeTab(id); + m_ws->removeWidget(w); + m_map.remove(w); + m_revMap.remove(id); + if (m_overlapButtons.contains(w)) { + (static_cast<KDockWidgetHeader*>(w->getHeader()->qt_cast("KDockWidgetHeader")))->removeButton(m_overlapButtons[w]); + m_overlapButtons.remove(w); + } + KDockContainer::removeWidget(w); + itemNames.remove(w->name()); + tabCaptions.remove(w->name()); + tabTooltips.remove(w->name()); + if (!itemNames.count()) + ((KDockWidget*)parentWidget())->undock(); +} + +void DockContainer::undockWidget(KDockWidget *dwdg) +{ + KDockWidget* w = (KDockWidget*) dwdg; + + if (!m_map.contains(w)) + return; + + int id=m_map[w]; + if (m_tb->isTabRaised(id)) { + kdDebug(760)<<"Wiget has been undocked, setting tab down"<<endl; + m_tb->setTab(id,false); + tabClicked(id); + } +} + +void DockContainer::tabClicked(int t) +{ + kdDebug(760)<<"DockContainer::tabClicked()"<<endl; + bool call_makeVisible=!m_tabSwitching; + m_tabSwitching=true; + if ((t!=-1) && m_tb->isTabRaised(t)) + { + if (m_ws->isHidden()) + { + m_ws->show (); + parentDockWidget()->restoreFromForcedFixedSize(); + } + if (!m_ws->widget(t)) + { + m_revMap[t]->manualDock(parentDockWidget(),KDockWidget::DockCenter,20); + if (call_makeVisible) m_revMap[t]->makeDockVisible();//manualDock(parentDockWidget(),KDockWidget::DockCenter,20); + m_tabSwitching=false; + emit activated(this); + return; + } + m_ws->raiseWidget(t); + if (m_ws->widget(t)) { + KDockWidget *tmpDw=static_cast<KDockWidget*>(m_ws->widget(t)->qt_cast("KDockWidget")); + if (tmpDw) { + if (tmpDw->getWidget()) tmpDw->getWidget()->setFocus(); + } else kdDebug(760)<<"Something really weird is going on"<<endl; + } else + kdDebug(760)<<"DockContainer::tabClicked(int): m_ws->widget(t)==0 "<<endl; + + if (oldtab!=t) m_tb->setTab(oldtab,false); + m_tabSwitching=true; + oldtab=t; + emit activated(this); + } + else + { + // try save splitter position + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()-> + parent()->qt_cast("KDockSplitter")); + if ( sp ) + m_separatorPos = sp->separatorPos(); + } + m_previousTab=t; +// oldtab=-1; + if (m_block) return; + emit deactivated(this); + m_block=true; + if (m_ws->widget(t)) + { +// ((KDockWidget*)m_ws->widget(t))->undock(); + } + m_block=false; + m_ws->hide (); + + + kdDebug(760)<<"Fixed Width:"<<m_tb->width()<<endl; + if (m_vertical) + parentDockWidget()->setForcedFixedWidth(m_tb->width()); // strange why it worked before at all + else + parentDockWidget()->setForcedFixedHeight(m_tb->height()); // strange why it worked before at all + } + m_tabSwitching=false; +} + +void DockContainer::setToolTip (KDockWidget *, QString &s) +{ + kdDebug(760)<<"***********************************Setting tooltip for a widget: "<<s<<endl; +} + +void DockContainer::setPixmap(KDockWidget* widget ,const QPixmap& pixmap) +{ + int id=m_ws->id(widget); + if (id==-1) return; + KMultiTabBarTab *tab=m_tb->tab(id); + tab->setIcon(pixmap.isNull()?SmallIcon("misc"):pixmap); +} + +void DockContainer::save(KConfig* cfg,const QString& group_or_prefix) +{ + // group name + QString grp=cfg->group(); + cfg->deleteGroup(group_or_prefix+QString("::%1").arg(parent()->name())); + cfg->setGroup(group_or_prefix+QString("::%1").arg(parent()->name())); + + // save overlap mode + cfg->writeEntry("overlapMode",isOverlapMode()); + + // try to save the splitter position + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()-> + parent()->qt_cast("KDockSplitter")); + if ( sp ) + cfg->writeEntry( "separatorPosition", m_separatorPos ); + } + + QPtrList<KMultiTabBarTab>* tl=m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it(*tl); + QStringList::Iterator it2=itemNames.begin(); + int i=0; + for (;it.current()!=0;++it,++it2) + { +// cfg->writeEntry(QString("widget%1").arg(i),m_ws->widget(it.current()->id())->name()); + cfg->writeEntry(QString("widget%1").arg(i),(*it2)); + QString s=tabCaptions[*it2]; + if (!s.isEmpty()) { + cfg->writeEntry(QString("widget%1-tabCaption").arg(i),s); + } + s=tabTooltips[*it2]; + if (!s.isEmpty()) { + cfg->writeEntry(QString("widget%1-tabTooltip").arg(i),s); + } +// kdDebug(760)<<"****************************************Saving: "<<m_ws->widget(it.current()->id())->name()<<endl; + if (m_tb->isTabRaised(it.current()->id())) + cfg->writeEntry(m_ws->widget(it.current()->id())->name(),true); + ++i; + } + + cfg->setGroup(grp); +} + +void DockContainer::load(KConfig* cfg,const QString& group_or_prefix) +{ + QString grp=cfg->group(); + cfg->setGroup(group_or_prefix+QString("::%1").arg(parent()->name())); + + if (cfg->readBoolEntry("overlapMode")) + activateOverlapMode( m_vertical?m_tb->width():m_tb->height() ); + else + deactivateOverlapMode(); + + m_separatorPos = cfg->readNumEntry( "separatorPosition", 18000 ); // = 18% + + int i=0; + QString raise; + while (true) + { + QString dwn=cfg->readEntry(QString("widget%1").arg(i)); + if (dwn.isEmpty()) break; + kdDebug(760)<<"*************************************************************Configuring dockwidget :"<<dwn<<endl; + KDockWidget *dw=((KDockWidget*)parent())->dockManager()->getDockWidgetFromName(dwn); + if (dw) + { + QString s=cfg->readEntry(QString("widget%1-tabCaption").arg(i)); + if (!s.isEmpty()) { + dw->setTabPageLabel(s); + } + s=cfg->readEntry(QString("widget%1-tabTooltip").arg(i)); + if (!s.isEmpty()) { + dw->setToolTipString(s); + } + dw->manualDock((KDockWidget*)parent(),KDockWidget::DockCenter); + } + if (cfg->readBoolEntry(dwn,false)) raise=dwn; + i++; + + } + + QPtrList<KMultiTabBarTab>* tl=m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it1(*tl); + m_ws->hide(); + if (m_vertical) + parentDockWidget()->setForcedFixedWidth(m_tb->width()); + else + parentDockWidget()->setForcedFixedHeight(m_tb->height()); + for (;it1.current()!=0;++it1) + { + m_tb->setTab(it1.current()->id(),false); + } + kapp->syncX(); + m_delayedRaise=-1; + + for (QMap<KDockWidget*,KDockButton_Private*>::iterator it=m_overlapButtons.begin(); + it!=m_overlapButtons.end();++it) + it.data()->setOn(!isOverlapMode()); + + if (!raise.isEmpty()) + { + for (QMap<KDockWidget*,int>::iterator it=m_map.begin();it!=m_map.end();++it) + { + if (it.key()->name()==raise) + { +/* tabClicked(it.data()); + m_tb->setTab(it.data(),true); + tabClicked(it.data()); + m_ws->raiseWidget(it.key()); + kapp->sendPostedEvents(); + kapp->syncX();*/ + + m_delayedRaise=it.data(); + QTimer::singleShot(0,this,SLOT(delayedRaise())); + kdDebug(760)<<"************** raising *******: "<<it.key()->name()<<endl; + break; + } + } + + } + if (m_delayedRaise==-1) QTimer::singleShot(0,this,SLOT(init())); + cfg->setGroup(grp); + +} + +void DockContainer::delayedRaise() +{ + m_tb->setTab(m_delayedRaise,true); + tabClicked(m_delayedRaise); +} + +void DockContainer::collapseOverlapped() +{ + if (m_tabSwitching) return; + if (isOverlapMode()){ + QPtrList<KMultiTabBarTab>* tl=m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it(*tl); + for(;it.current();++it) { + if (it.current()->isOn()) { + kdDebug(760)<<"Lowering TAB"<<endl; + it.current()->setState(false); + tabClicked(it.current()->id()); + } + } + } +} + +void DockContainer::toggle() { + kdDebug(760)<<"DockContainer:activate"<<endl; + if (m_tb->isTabRaised(oldtab)) { + m_tb->setTab(oldtab,false); + tabClicked(oldtab); + // KMDI::MainWindow *mainFrm = dynamic_cast<KMDI::MainWindow*>(m_mainWin); + // if (mainFrm && mainFrm->activeWindow() ) // TODO + // mainFrm->activeWindow()->setFocus(); + + } else { + kdDebug(760)<<"DockContainer::toggle(): raising tab"<<endl; + if (m_tb->tab(m_previousTab)==0) { + if (m_tb->tabs()->count()==0) return; + m_previousTab=m_tb->tabs()->getFirst()->id(); + } + m_tb->setTab(m_previousTab,true); + tabClicked(m_previousTab); + } +} + +void DockContainer::prevToolView() { + QPtrList<KMultiTabBarTab>* tabs=m_tb->tabs(); + int pos=tabs->findRef(m_tb->tab(oldtab)); + if (pos==-1) return; + pos--; + if (pos<0) pos=tabs->count()-1; + KMultiTabBarTab *tab=tabs->at(pos); + if (!tab) return; //can never happen here, but who knows + m_tb->setTab(tab->id(),true); + tabClicked(tab->id()); +} + +void DockContainer::nextToolView() { + QPtrList<KMultiTabBarTab>* tabs=m_tb->tabs(); + int pos=tabs->findRef(m_tb->tab(oldtab)); + if (pos==-1) return; + pos++; + if (pos>=(int)tabs->count()) pos=0; + KMultiTabBarTab *tab=tabs->at(pos); + if (!tab) return; //can never happen here, but who knows + m_tb->setTab(tab->id(),true); + tabClicked(tab->id()); +} + +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/dockcontainer.h b/kmdi/kmdi/dockcontainer.h new file mode 100644 index 000000000..d301d3c53 --- /dev/null +++ b/kmdi/kmdi/dockcontainer.h @@ -0,0 +1,144 @@ +/* This file is part of the KDE project + Copyright (C) 2002, 2003 Joseph Wenninger <jowenn@kde.org> + Copyright (C) 2002, 2004 Christoph Cullmann <cullmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _KMDI_DOCK_CONTAINER_ +#define _KMDI_DOCK_CONTAINER_ + +#include <qwidget.h> +#include <qstringlist.h> +#include <kdockwidget.h> +#include <qmap.h> + +# include <kdockwidget_p.h> + +#include <qpushbutton.h> + +class QWidgetStack; +class KMultiTabBar; +class KDockButton_Private; + +namespace KMDI +{ + +class DockContainer: public QWidget, public KDockContainer +{ + Q_OBJECT + + public: + DockContainer(QWidget *parent, QWidget *win, int position, int flags); + virtual ~DockContainer(); + + /** Get the KDockWidget that is our parent */ + KDockWidget *parentDockWidget(); + + /** + * Add a widget to this container. + * \param w the KDockWidget object to add + * \todo Remove the extra parameters that we don't use? + */ + virtual void insertWidget (KDockWidget *w, QPixmap, const QString &, int &); + + /** + * Show a KDockWidget in our DockContainer + * \param w the KDockWidget to show + */ + virtual void showWidget (KDockWidget *w); + + /** + * Set a tooltip for a widget + * + * \todo Actually implement it? Right now, it looks just it + * does exactly nothing + */ + virtual void setToolTip (KDockWidget *, QString &); + + /** + * Set a pixmap for one of our dock widgets + * \param widget the KDockWidget to set the pixmap for + * \param pixmap the pixmap you want to give the widget + */ + virtual void setPixmap(KDockWidget* widget, const QPixmap& pixmap); + + /** + * Undock a widget from the container. This function is called + * when you've dragged a tab off the dock it's attached to. + * \param dwdg the KDockWidget to undock + */ + virtual void undockWidget(KDockWidget* dwdg); + + /** + * Remove a widget from the container. The caller + * of this function is responsible for deleting the widget after calling + * this function. + */ + virtual void removeWidget(KDockWidget*); + + void hideIfNeeded(); + + virtual void save(KConfig *,const QString& group_or_prefix); + virtual void load(KConfig *,const QString& group_or_prefix); + + void setStyle(int); + protected: + bool eventFilter(QObject*,QEvent*); + + public slots: + void init(); + void collapseOverlapped(); + void toggle(); + void nextToolView(); + void prevToolView(); + protected slots: + void tabClicked(int); + void delayedRaise(); + void changeOverlapMode(); + private: + QWidget *m_mainWin; + QWidgetStack *m_ws; + KMultiTabBar *m_tb; + int mTabCnt; + int oldtab; + int m_previousTab; + int m_position; + int m_separatorPos; + QMap<KDockWidget*,int> m_map; + QMap<int,KDockWidget*> m_revMap; + QMap<KDockWidget*,KDockButton_Private*> m_overlapButtons; + QStringList itemNames; + QMap<QString,QString> tabCaptions; + QMap<QString,QString> tabTooltips; + int m_inserted; + int m_delayedRaise; + bool m_vertical; + bool m_block; + bool m_tabSwitching; + QObject *m_dragPanel; + KDockManager *m_dockManager; + QMouseEvent *m_startEvent; + enum MovingState {NotMoving=0,WaitingForMoveStart,MovingInternal,Moving} m_movingState; + signals: + void activated(DockContainer*); + void deactivated(DockContainer*); +}; + +} + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/global.h b/kmdi/kmdi/global.h new file mode 100644 index 000000000..bf66ea74c --- /dev/null +++ b/kmdi/kmdi/global.h @@ -0,0 +1,69 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Based on: + + //---------------------------------------------------------------------------- + // Project : KDE MDI extension + // + // begin : 07/1999 by Szymon Stefanek as part of kvirc + // (an IRC application) + // changes : 09/1999 by Falk Brettschneider to create an + // - 06/2000 stand-alone Qt extension set of + // classes and a Qt-based library + // : 02/2000 by Massimo Morin (mmorin@schedsys.com) + // 2000-2003 maintained by the KDevelop project + // patches : -/2000 by Lars Beikirch (Lars.Beikirch@gmx.net) + // : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) + // + // copyright : (C) 1999-2003 by Falk Brettschneider + // and + // Szymon Stefanek (stefanek@tin.it) + // email : falkbr@kdevelop.org (Falk Brettschneider) + //---------------------------------------------------------------------------- +*/ + +#ifndef _KMDI_GLOBAL_H_ +#define _KMDI_GLOBAL_H_ + +/** + * @short A namespace for the KMDI library + */ +namespace KMDI +{ + enum TabWidgetVisibility { + AlwaysShowTabs = 0, + ShowWhenMoreThanOneTab = 1, + NeverShowTabs = 2 + }; + + /** + * The style of the toolview tabs + */ + enum ToolviewStyle { + /** Show only icons on the toolview tabs. The visible toolviews contain both the icon and text. */ + IconOnly = 0, + /** Show only the text description on the toolview tabs. */ + TextOnly = 1, + /** Show both the icon and description on the toolview tabs. */ + TextAndIcon = 3 + }; +} + +#endif diff --git a/kmdi/kmdi/guiclient.cpp b/kmdi/kmdi/guiclient.cpp new file mode 100644 index 000000000..7e146b836 --- /dev/null +++ b/kmdi/kmdi/guiclient.cpp @@ -0,0 +1,230 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + based on ktoolbarhandler.cpp: Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "guiclient.h" +#include "guiclient.moc" + +#include <qpopupmenu.h> +#include <kapplication.h> +#include <kconfig.h> +#include <ktoolbar.h> +#include <klocale.h> +#include <kaction.h> +#include <qstring.h> +#include <kdebug.h> +#include <kdockwidget.h> + +#include "mainwindow.h" +#include "toolviewaccessor.h" +#include "toolviewaccessor_p.h" + +static const char *actionListName = "show_kmdi_document_tool_view_actions"; + +static const char *guiDescription = "" + "<!DOCTYPE kpartgui><kpartgui name=\"KMDIViewActions\">" + "<MenuBar>" + " <Menu name=\"window\">" + " <ActionList name=\"%1\" />" + " </Menu>" + "</MenuBar>" + "</kpartgui>"; + +static const char *resourceFileName = "kmdiviewactions.rc"; + +namespace KMDIPrivate +{ + +GUIClient::GUIClient (KMDI::MainWindow* mdiMainFrm,const char* name) + : QObject ( mdiMainFrm,name ) + , KXMLGUIClient ( mdiMainFrm ) +{ + m_mdiMainFrm=mdiMainFrm; + + connect( mdiMainFrm->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ), + this, SLOT( clientAdded( KXMLGUIClient * ) ) ); + + /* re-use an existing resource file if it exists. can happen if the user launches the + * toolbar editor */ + /* + setXMLFile( resourceFileName ); + */ + + if ( domDocument().documentElement().isNull() ) + { + QString completeDescription = QString::fromLatin1( guiDescription ).arg( actionListName ); + + setXML( completeDescription, false /*merge*/ ); + } + + if (actionCollection()->kaccel()==0) + actionCollection()->setWidget(mdiMainFrm); + + m_toolMenu=new KActionMenu(i18n("Tool &Views"),actionCollection(),"kmdi_toolview_menu"); + + m_gotoToolDockMenu=new KActionMenu(i18n("Tool &Docks"),actionCollection(),"kmdi_tooldock_menu"); + m_gotoToolDockMenu->insert(new KAction(i18n("Switch Top Dock"),ALT+CTRL+SHIFT+Key_T,this,SIGNAL(toggleTop()), + actionCollection(),"kmdi_activate_top")); + m_gotoToolDockMenu->insert(new KAction(i18n("Switch Left Dock"),ALT+CTRL+SHIFT+Key_L,this,SIGNAL(toggleLeft()), + actionCollection(),"kmdi_activate_left")); + m_gotoToolDockMenu->insert(new KAction(i18n("Switch Right Dock"),ALT+CTRL+SHIFT+Key_R,this,SIGNAL(toggleRight()), + actionCollection(),"kmdi_activate_right")); + m_gotoToolDockMenu->insert(new KAction(i18n("Switch Bottom Dock"),ALT+CTRL+SHIFT+Key_B,this,SIGNAL(toggleBottom()), + actionCollection(),"kmdi_activate_bottom")); + m_gotoToolDockMenu->insert(new KActionSeparator(actionCollection(),"kmdi_goto_menu_separator")); + m_gotoToolDockMenu->insert(new KAction(i18n("Previous Tool View"),ALT+CTRL+Key_Left,m_mdiMainFrm,SLOT(prevToolViewInDock()), + actionCollection(),"kmdi_prev_toolview")); + m_gotoToolDockMenu->insert(new KAction(i18n("Next Tool View"),ALT+CTRL+Key_Right,m_mdiMainFrm,SLOT(nextToolViewInDock()), + actionCollection(),"kmdi_next_toolview")); + + actionCollection()->readShortcutSettings( "Shortcuts", kapp->config() ); +} + +GUIClient::~GUIClient() +{ +// actionCollection()->writeShortcutSettings( "KMDI Shortcuts", kapp->config() ); + for (uint i=0;i<m_toolViewActions.count();i++) + disconnect(m_toolViewActions.at(i),0,this,0); + + m_toolViewActions.setAutoDelete( false ); + m_toolViewActions.clear(); + m_documentViewActions.setAutoDelete( false ); + m_documentViewActions.clear(); +} + +void GUIClient::setupActions() +{ + if ( !factory() || !m_mdiMainFrm ) + return; + + unplugActionList( actionListName ); + + QPtrList<KAction> addList; + if (m_toolViewActions.count()<3) + { + for (uint i=0;i<m_toolViewActions.count();i++) + addList.append(m_toolViewActions.at(i)); + } + else + addList.append(m_toolMenu); + + addList.append(m_gotoToolDockMenu); + + kdDebug(760)<<"GUIClient::setupActions: plugActionList"<<endl; + + plugActionList( actionListName, addList ); +} + +void GUIClient::addToolView(KMDI::ToolViewAccessor* mtva) +{ + kdDebug(760)<<"*****void GUIClient::addToolView(KMDI::ToolViewAccessor* mtva)*****"<<endl; + + QString aname = QString("kmdi_toolview_") + mtva->wrappedWidget()->name(); + + // try to read the action shortcut + KShortcut sc; + KConfig *cfg = kapp->config(); + QString _grp = cfg->group(); + cfg->setGroup("Shortcuts"); + sc = KShortcut( cfg->readEntry( aname, "" ) ); + cfg->setGroup( _grp ); + + KAction *a=new ToggleToolViewAction(i18n("Show %1").arg(mtva->wrappedWidget()->caption()), + /*QString::null*/sc,dynamic_cast<KDockWidget*>(mtva->wrapperWidget()), + m_mdiMainFrm,actionCollection(), aname.latin1() ); + + ((ToggleToolViewAction*)a)->setCheckedState(i18n("Hide %1").arg(mtva->wrappedWidget()->caption())); + + connect(a,SIGNAL(destroyed(QObject*)),this,SLOT(actionDeleted(QObject*))); + + m_toolViewActions.append(a); + m_toolMenu->insert(a); + mtva->d->action=a; + + setupActions(); +} + +void GUIClient::actionDeleted(QObject* a) +{ + m_toolViewActions.remove(static_cast<KAction*>(a)); + setupActions(); +} + + +void GUIClient::clientAdded( KXMLGUIClient *client ) +{ + if ( client == this ) + setupActions(); +} + +ToggleToolViewAction::ToggleToolViewAction ( const QString& text, const KShortcut& cut,KDockWidget *dw, KMDI::MainWindow *mdiMainFrm, + QObject* parent, const char* name ) + : KToggleAction(text,cut,parent,name) + , m_dw(dw) + , m_mdiMainFrm(mdiMainFrm) +{ + if (m_dw) + { + connect(this,SIGNAL(toggled(bool)),this,SLOT(slotToggled(bool))); + connect(m_dw->dockManager(),SIGNAL(change()),this,SLOT(anDWChanged())); + connect(m_dw,SIGNAL(destroyed()),this,SLOT(slotWidgetDestroyed())); + + setChecked(m_dw->mayBeHide()); + } +} + +ToggleToolViewAction::~ToggleToolViewAction() +{ + unplugAll(); +} + +void ToggleToolViewAction::anDWChanged() +{ + if (isChecked() && m_dw->mayBeShow()) + setChecked(false); + else if ((!isChecked()) && m_dw->mayBeHide()) + setChecked(true); + else if (isChecked() && (m_dw->parentDockTabGroup() && + ((static_cast<KDockWidget*>(m_dw->parentDockTabGroup()-> + parent()->qt_cast("KDockWidget")))->mayBeShow()))) + setChecked(false); +} + + +void ToggleToolViewAction::slotToggled(bool t) +{ + if ((!t) && m_dw->mayBeHide() ) + m_dw->undock(); + else + if ( t && m_dw->mayBeShow() ) + m_mdiMainFrm->makeDockVisible(m_dw); +} + +void ToggleToolViewAction::slotWidgetDestroyed() +{ + disconnect(m_dw->dockManager(),SIGNAL(change()),this,SLOT(anDWChanged())); + disconnect(this,SIGNAL(toggled(bool)),0,0); + + unplugAll(); + deleteLater(); +} + +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/guiclient.h b/kmdi/kmdi/guiclient.h new file mode 100644 index 000000000..04dd2fbd2 --- /dev/null +++ b/kmdi/kmdi/guiclient.h @@ -0,0 +1,103 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + based on ktoolbarhandler.cpp: Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _KMDI_GUICLIENT_H_ +#define _KMDI_GUICLIENT_H_ + +#include <qobject.h> +#include <qguardedptr.h> +#include <kxmlguiclient.h> +#include <kaction.h> + +#include <kmdi/global.h> + +class KMainWindow; +class KToolBar; + +namespace KMDI { + class MainWindow; + class ToolViewAccessor; +} + +class KDockWidget; + +namespace KMDIPrivate { + +class GUIClientPrivate; + +class GUIClient : public QObject, public KXMLGUIClient +{ + Q_OBJECT + + public: + GUIClient( KMDI::MainWindow *mdiMainFrm, const char *name = 0 ); + virtual ~GUIClient(); + + void addToolView(KMDI::ToolViewAccessor*); + + private slots: + void clientAdded( KXMLGUIClient *client ); + void setupActions(); + void actionDeleted(QObject*); + + signals: + void toggleTop(); + void toggleLeft(); + void toggleRight(); + void toggleBottom(); + + private: + GUIClientPrivate *d; + + QGuardedPtr<KMDI::MainWindow> m_mdiMainFrm; + QPtrList<KAction> m_toolViewActions; + QPtrList<KAction> m_documentViewActions; + + KActionMenu *m_docMenu; + KActionMenu *m_toolMenu; + + KActionMenu *m_gotoToolDockMenu; +}; + +class ToggleToolViewAction:public KToggleAction +{ + Q_OBJECT + + public: + ToggleToolViewAction ( const QString& text, const KShortcut& cut = KShortcut(), + KDockWidget *dw=0,KMDI::MainWindow *mdiMainFrm=0, QObject* parent = 0, const char* name = 0 ); + + virtual ~ToggleToolViewAction(); + + protected slots: + void slotToggled(bool); + void anDWChanged(); + void slotWidgetDestroyed(); + + private: + KDockWidget *m_dw; + KMDI::MainWindow *m_mdiMainFrm; +}; + +} + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/mainwindow.cpp b/kmdi/kmdi/mainwindow.cpp new file mode 100644 index 000000000..048086178 --- /dev/null +++ b/kmdi/kmdi/mainwindow.cpp @@ -0,0 +1,451 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Based on: + + //---------------------------------------------------------------------------- + // Project : KDE MDI extension + // + // begin : 07/1999 by Szymon Stefanek as part of kvirc + // (an IRC application) + // changes : 09/1999 by Falk Brettschneider to create an + // - 06/2000 stand-alone Qt extension set of + // classes and a Qt-based library + // : 02/2000 by Massimo Morin (mmorin@schedsys.com) + // 2000-2003 maintained by the KDevelop project + // patches : -/2000 by Lars Beikirch (Lars.Beikirch@gmx.net) + // : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) + // + // copyright : (C) 1999-2003 by Falk Brettschneider + // and + // Szymon Stefanek (stefanek@tin.it) + // email : falkbr@kdevelop.org (Falk Brettschneider) + //---------------------------------------------------------------------------- +*/ + +#include "config.h" + +#include "tabwidget.h" + +#include <assert.h> + +#include <qcursor.h> +#include <qclipboard.h> +#include <qobjectlist.h> +#include <qpopupmenu.h> +#include <qmenubar.h> + +#include <kmenubar.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <qtabwidget.h> +#include <klocale.h> + +#include <kiconloader.h> +#include "dockcontainer.h" +#include "mainwindow.moc" + + +#include <qtoolbutton.h> +#include <qlayout.h> +#include <qstring.h> +#include <qmap.h> +#include <qvaluelist.h> + +#include "mainwindow.h" +#include "dockcontainer.h" +#include "toolviewaccessor_p.h" + +#include "guiclient.h" + +namespace KMDIPrivate +{ + class MainWindowPrivate { + public: + MainWindowPrivate() { + for (int i=0;i<4;i++) { + activeDockPriority[i]=0; + m_styleIDEAlMode = 0; + m_toolviewStyle = 0; + } + } + ~MainWindowPrivate() {} + KMDI::DockContainer* activeDockPriority[4]; + int m_styleIDEAlMode; + int m_toolviewStyle; + }; +} + +namespace KMDI +{ + +//============ constructor ============// +MainWindow::MainWindow(QWidget* parentWidget, const char* name) + : KParts::DockMainWindow( parentWidget, name) + , m_toolViews (new QMap<QWidget*,KMDI::ToolViewAccessor*>) + , d(new KMDIPrivate::MainWindowPrivate()) +{ + // setup main dock stuff + setupMainDock (); + + // setup the sidebar framework + setupToolViews (); + + // setup all menu entries + setupGUIClient (); +} + +//============ ~MainWindow ============// +MainWindow::~MainWindow() +{ + delete m_toolViews; + m_toolViews=0; + + delete d; + d=0; +} + +void MainWindow::setupMainDock () +{ + // cover KMdi's childarea by a dockwidget + KDockWidget *dw = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover"); + dw->setDockWindowTransient(this,true); + dw->setEnableDocking(KDockWidget::DockNone); + dw->setDockSite(KDockWidget::DockCorner); + + // setup tab widget + m_tabWidget = new KMDI::TabWidget (dw); + dw->setWidget(m_tabWidget); + + // set this dock to main view + setView(dw); + setMainDockWidget(dw); + + // connect signals to collapse sidebars + connect(m_tabWidget,SIGNAL(focusInEvent()),this,SIGNAL(collapseOverlapContainers())); +} + +void MainWindow::setupToolViews () +{ + m_leftContainer = createDockWidget("KMdiDock::leftDock",SmallIcon("misc"),0L,"Left Dock"); + m_rightContainer = createDockWidget("KMdiDock::rightDock",SmallIcon("misc"),0L,"Right Dock"); + m_topContainer = createDockWidget("KMdiDock::topDock",SmallIcon("misc"),0L,"Top Dock"); + m_bottomContainer = createDockWidget("KMdiDock::bottomDock",SmallIcon("misc"),0L,"Bottom Dock"); + + KDockWidget *mainDock=getMainDockWidget(); + KDockWidget *w=mainDock; + + if (mainDock->parentDockTabGroup()) { + w=static_cast<KDockWidget*>(mainDock->parentDockTabGroup()->parent()); + } + + QPtrList<KDockWidget> leftReparentWidgets; + QPtrList<KDockWidget> rightReparentWidgets; + QPtrList<KDockWidget> bottomReparentWidgets; + QPtrList<KDockWidget> topReparentWidgets; + + if (mainDock->parentDockTabGroup()) { + mainDock=static_cast<KDockWidget*>(mainDock->parentDockTabGroup()->parent()); + } + + findToolViewsDockedToMain(&leftReparentWidgets,KDockWidget::DockLeft); + findToolViewsDockedToMain(&rightReparentWidgets,KDockWidget::DockRight); + findToolViewsDockedToMain(&bottomReparentWidgets,KDockWidget::DockBottom); + findToolViewsDockedToMain(&topReparentWidgets,KDockWidget::DockTop); + + mainDock->setEnableDocking(KDockWidget::DockNone); //::DockCorner); + mainDock->setDockSite(KDockWidget::DockCorner); + + + DockContainer *tmpDC; + m_leftContainer->setWidget(tmpDC=new DockContainer(m_leftContainer, this, KDockWidget::DockLeft, d->m_styleIDEAlMode)); + m_leftContainer->setEnableDocking(KDockWidget::DockLeft); + m_leftContainer->manualDock(mainDock, KDockWidget::DockLeft,20); + tmpDC->init(); + + connect (this,SIGNAL(toggleLeft()),tmpDC,SLOT(toggle())); + connect(this,SIGNAL(collapseOverlapContainers()),tmpDC,SLOT(collapseOverlapped())); + connect(tmpDC,SIGNAL(activated(DockContainer*)),this,SLOT(setActiveToolDock(DockContainer*))); + connect(tmpDC,SIGNAL(deactivated(DockContainer*)),this,SLOT(removeFromActiveDockList(DockContainer*))); + + m_rightContainer->setWidget(tmpDC=new DockContainer(m_rightContainer, this, KDockWidget::DockRight, d->m_styleIDEAlMode)); + m_rightContainer->setEnableDocking(KDockWidget::DockRight); + m_rightContainer->manualDock(mainDock, KDockWidget::DockRight,80); + tmpDC->init(); + + connect (this,SIGNAL(toggleRight()),tmpDC,SLOT(toggle())); + connect(this,SIGNAL(collapseOverlapContainers()),tmpDC,SLOT(collapseOverlapped())); + connect(tmpDC,SIGNAL(activated(DockContainer*)),this,SLOT(setActiveToolDock(DockContainer*))); + connect(tmpDC,SIGNAL(deactivated(DockContainer*)),this,SLOT(removeFromActiveDockList(DockContainer*))); + + m_topContainer->setWidget(tmpDC=new DockContainer(m_topContainer, this, KDockWidget::DockTop, d->m_styleIDEAlMode)); + m_topContainer->setEnableDocking(KDockWidget::DockTop); + m_topContainer->manualDock(mainDock, KDockWidget::DockTop,20); + tmpDC->init(); + + connect (this,SIGNAL(toggleTop()),tmpDC,SLOT(toggle())); + connect(this,SIGNAL(collapseOverlapContainers()),tmpDC,SLOT(collapseOverlapped())); + connect(tmpDC,SIGNAL(activated(DockContainer*)),this,SLOT(setActiveToolDock(DockContainer*))); + connect(tmpDC,SIGNAL(deactivated(DockContainer*)),this,SLOT(removeFromActiveDockList(DockContainer*))); + + m_bottomContainer->setWidget(tmpDC=new DockContainer(m_bottomContainer, this, KDockWidget::DockBottom, d->m_styleIDEAlMode)); + m_bottomContainer->setEnableDocking(KDockWidget::DockBottom); + m_bottomContainer->manualDock(mainDock, KDockWidget::DockBottom,80); + tmpDC->init(); + + connect (this,SIGNAL(toggleBottom()),tmpDC,SLOT(toggle())); + connect(this,SIGNAL(collapseOverlapContainers()),tmpDC,SLOT(collapseOverlapped())); + connect(tmpDC,SIGNAL(activated(DockContainer*)),this,SLOT(setActiveToolDock(DockContainer*))); + connect(tmpDC,SIGNAL(deactivated(DockContainer*)),this,SLOT(removeFromActiveDockList(DockContainer*))); + + m_leftContainer->setDockSite( KDockWidget::DockCenter ); + m_rightContainer->setDockSite( KDockWidget::DockCenter ); + m_topContainer->setDockSite( KDockWidget::DockCenter ); + m_bottomContainer->setDockSite( KDockWidget::DockCenter ); + + dockToolViewsIntoContainers(leftReparentWidgets,m_leftContainer); + dockToolViewsIntoContainers(rightReparentWidgets,m_rightContainer); + dockToolViewsIntoContainers(bottomReparentWidgets,m_bottomContainer); + dockToolViewsIntoContainers(topReparentWidgets,m_topContainer); + + dockManager->setSpecialLeftDockContainer(m_leftContainer); + dockManager->setSpecialRightDockContainer(m_rightContainer); + dockManager->setSpecialTopDockContainer(m_topContainer); + dockManager->setSpecialBottomDockContainer(m_bottomContainer); + + ((DockContainer*) (m_leftContainer->getWidget()))->hideIfNeeded(); + ((DockContainer*) (m_rightContainer->getWidget()))->hideIfNeeded(); + ((DockContainer*) (m_topContainer->getWidget()))->hideIfNeeded(); + ((DockContainer*) (m_bottomContainer->getWidget()))->hideIfNeeded(); +} + +void MainWindow::setupGUIClient () +{ + m_guiClient = new KMDIPrivate::GUIClient (this); + + connect(m_guiClient,SIGNAL(toggleTop()),this,SIGNAL(toggleTop())); + connect(m_guiClient,SIGNAL(toggleLeft()),this,SIGNAL(toggleLeft())); + connect(m_guiClient,SIGNAL(toggleRight()),this,SIGNAL(toggleRight())); + connect(m_guiClient,SIGNAL(toggleBottom()),this,SIGNAL(toggleBottom())); +} + +TabWidget *MainWindow::tabWidget () +{ + return m_tabWidget; +} + +ToolViewAccessor *MainWindow::createToolWindow() +{ + return new KMDI::ToolViewAccessor(this); +} + +KMDI::ToolViewAccessor *MainWindow::addToolWindow( QWidget* pWnd, KDockWidget::DockPosition pos, QWidget* pTargetWnd, int percent, const QString& tabToolTip, const QString& tabCaption) +{ + QWidget *tvta=pWnd; + KDockWidget* pDW = dockManager->getDockWidgetFromName(pWnd->name()); + if (pDW) { + // probably readDockConfig already created the widgetContainer, use that + pDW->setWidget(pWnd); + + if (pWnd->icon()) { + pDW->setPixmap(*pWnd->icon()); + } + pDW->setTabPageLabel((tabCaption==0)?pWnd->caption():tabCaption); + pDW->setToolTipString(tabToolTip); + dockManager->removeFromAutoCreateList(pDW); + pWnd=pDW; + } + + QRect r=pWnd->geometry(); + + KMDI::ToolViewAccessor *mtva=new KMDI::ToolViewAccessor(this,pWnd,tabToolTip,(tabCaption==0)?pWnd->caption():tabCaption); + m_toolViews->insert(tvta,mtva); + + if (pos == KDockWidget::DockNone) { + mtva->d->widgetContainer->setEnableDocking(KDockWidget::DockNone); + mtva->d->widgetContainer->reparent(this, Qt::WType_TopLevel | Qt::WType_Dialog, r.topLeft(), isVisible()); + } else { // add (and dock) the toolview as DockWidget view + //const QPixmap& wndIcon = pWnd->icon() ? *(pWnd->icon()) : QPixmap(); + + //KDockWidget *pCover=mtva->d->widgetContainer; + + mtva->place(pos, pTargetWnd,percent); + } + + return mtva; +} + +void MainWindow::deleteToolWindow( KMDI::ToolViewAccessor *accessor) +{ + delete accessor; +} + +void MainWindow::deleteToolWindow( QWidget* pWnd) +{ + if (!pWnd) + return; + + if (m_toolViews->contains(pWnd)) { + deleteToolWindow((*m_toolViews)[pWnd]); + } +} + +void MainWindow::setToolViewStyle(int flag) +{ + d->m_styleIDEAlMode = flag; // see KMultiTabBar for the first 3 bits + + DockContainer *tmpL=(DockContainer*) (m_leftContainer->getWidget()->qt_cast("KMDI::DockContainer")); + if (tmpL) tmpL->setStyle(flag); + + DockContainer *tmpR=(DockContainer*) (m_rightContainer->getWidget()->qt_cast("KMDI::DockContainer")); + if (tmpR) tmpR->setStyle(flag); + + DockContainer *tmpT=(DockContainer*) (m_topContainer->getWidget()->qt_cast("KMDI::DockContainer")); + if (tmpT) tmpT->setStyle(flag); + + DockContainer *tmpB=(DockContainer*) (m_bottomContainer->getWidget()->qt_cast("KMDI::DockContainer")); + if (tmpB) tmpB->setStyle(flag); + + d->m_toolviewStyle = flag; + bool toolviewExists = false; + QMap<QWidget*,KMDI::ToolViewAccessor*>::Iterator it; + for (it = m_toolViews->begin(); it != m_toolViews->end(); ++it) { + KDockWidget *dockWidget = dynamic_cast<KDockWidget*>(it.data()->wrapperWidget()); + if (dockWidget) { + if (flag == KMDI::IconOnly) + { + dockWidget->setTabPageLabel(" "); + dockWidget->setPixmap(*(it.data()->wrappedWidget()->icon())); + } else + if (flag == KMDI::TextOnly) + { + dockWidget->setPixmap(); //FIXME: Does not hide the icon in the IDEAl mode. + dockWidget->setTabPageLabel(it.data()->wrappedWidget()->caption()); + } else + if (flag == KMDI::TextAndIcon) + { + dockWidget->setPixmap(*(it.data()->wrappedWidget()->icon())); + dockWidget->setTabPageLabel(it.data()->wrappedWidget()->caption()); + } + toolviewExists = true; + } + } + if (toolviewExists) + { + //workaround for the above FIXME to make switching to TextOnly mode work in IDEAl as well. Be sure that this version of switch* is called. + if (flag == KMDI::TextOnly) + { + /* MainWindow::switchToTabPageMode(); + MainWindow::switchToIDEAlMode();*/ //TODO + } else + { + writeDockConfig(); + readDockConfig(); + } + } +} + +void MainWindow::dockToolViewsIntoContainers(QPtrList<KDockWidget>& widgetsToReparent,KDockWidget *container) { + for ( KDockWidget *dw = widgetsToReparent.first(); dw; + dw=widgetsToReparent.next()){ + dw->manualDock(container,KDockWidget::DockCenter,20); + dw->loseFormerBrotherDockWidget(); + } +} + +void MainWindow::findToolViewsDockedToMain(QPtrList<KDockWidget>* list,KDockWidget::DockPosition dprtmw) { + KDockWidget *mainDock=getMainDockWidget(); + if (mainDock->parentDockTabGroup()) { + mainDock=dynamic_cast<KDockWidget*>(mainDock->parentDockTabGroup()->parent()); + // FIXME: will likely crash below due to unchecked cast + } + + KDockWidget* widget=mainDock->findNearestDockWidget(dprtmw); + if (widget) { + if (widget->parentDockTabGroup()) { + widget=static_cast<KDockWidget*>(widget->parentDockTabGroup()->parent()); + } + + if (widget) { + KDockTabGroup *tg=dynamic_cast<KDockTabGroup*>(widget-> + getWidget()); + if (tg) { + kdDebug(760)<<"KDockTabGroup found"<<endl; + for (int i=0;i<tg->count();i++) + list->append((KDockWidget*)static_cast<KDockWidget*>( + tg->page(i))); + } else + list->append((KDockWidget*)widget); + } else + kdDebug(760)<<"setupToolViewsForIDEALMode: no widget found"<<endl; + } else + kdDebug(760)<<"No main dock widget found"<<endl; +} + +void MainWindow::setActiveToolDock(DockContainer* td) { + if (td==d->activeDockPriority[0]) return; + if (d->activeDockPriority[0]==0) { + d->activeDockPriority[0]=td; + // d->focusList=new KMdiFocusList(this); + // if (m_pMdi) d->focusList->addWidgetTree(m_pMdi); + // if (m_documentTabWidget) d->focusList->addWidgetTree(m_documentTabWidget); + return; + } + for (int dst=3,src=2;src>=0;dst--,src--) { + if (d->activeDockPriority[src]==td) src--; + if (src<0) break; + d->activeDockPriority[dst]=d->activeDockPriority[src]; + } + d->activeDockPriority[0]=td; +} + +void MainWindow::removeFromActiveDockList(DockContainer* td) { + for (int i=0;i<4;i++) { + if (d->activeDockPriority[i]==td) { + for (;i<3;i++) + d->activeDockPriority[i]=d->activeDockPriority[i+1]; + d->activeDockPriority[3]=0; + break; + } + } + /* + if (d->activeDockPriority[0]==0) { + if (d->focusList) d->focusList->restore(); + delete d->focusList; + d->focusList=0; + } + */ +} + +void MainWindow::prevToolViewInDock() { + DockContainer* td=d->activeDockPriority[0]; + if (!td) return; + td->prevToolView(); +} + +void MainWindow::nextToolViewInDock() { + DockContainer* td=d->activeDockPriority[0]; + if (!td) return; + td->nextToolView(); +} + +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/mainwindow.h b/kmdi/kmdi/mainwindow.h new file mode 100644 index 000000000..391ce8df9 --- /dev/null +++ b/kmdi/kmdi/mainwindow.h @@ -0,0 +1,199 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Based on: + + //---------------------------------------------------------------------------- + // Project : KDE MDI extension + // + // begin : 07/1999 by Szymon Stefanek as part of kvirc + // (an IRC application) + // changes : 09/1999 by Falk Brettschneider to create an + // - 06/2000 stand-alone Qt extension set of + // classes and a Qt-based library + // : 02/2000 by Massimo Morin (mmorin@schedsys.com) + // 2000-2003 maintained by the KDevelop project + // patches : -/2000 by Lars Beikirch (Lars.Beikirch@gmx.net) + // : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) + // + // copyright : (C) 1999-2003 by Falk Brettschneider + // and + // Szymon Stefanek (stefanek@tin.it) + // email : falkbr@kdevelop.org (Falk Brettschneider) + //---------------------------------------------------------------------------- +*/ + +#ifndef _KMDI_MAINWINDOW_H_ +#define _KMDI_MAINWINDOW_H_ + +#include <kparts/dockmainwindow.h> +#include <kmenubar.h> +#include <kpopupmenu.h> + +#include <qptrlist.h> +#include <qrect.h> +#include <qapplication.h> +#include <qguardedptr.h> + +#include <kmdi/global.h> + +class QPopupMenu; +class QMenuBar; + +#include <kmdi/toolviewaccessor.h> + +namespace KMDIPrivate { + class MainWindowPrivate; + class GUIClient; +} + +namespace KMDI +{ + +class DockContainer; +class TabWidget; + +class KMDI_EXPORT MainWindow : public KParts::DockMainWindow +{ + Q_OBJECT + + friend class KMDI::ToolViewAccessor; + + public: + /** + * Constructor. + */ + MainWindow ( QWidget* parentWidget, const char* name = ""); + + /** + * Destructor. + */ + virtual ~MainWindow (); + + public: + /** + * get the central tabwidget + * add all your content as child to this widget + * or as multiple tabs + * @return tabwidget in central of window + */ + TabWidget *tabWidget (); + + /** + * Using this method you have to use the setWidget method of the access object, and it is very recommendet, that you use + * the widgetContainer() method for the parent of your newly created widget + * @return created toolview + */ + KMDI::ToolViewAccessor *createToolWindow(); + + /** + * Usually called from addWindow() when adding a tool view window. It reparents the given widget + * as toplevel and stay-on-top on the application's main widget. + * @param pWnd widget for the toolview + * @param pos docking position + * @param pTargetWnd + * @param percent + * @param tabToolTip + * @param tabCaption + * @return created toolview + */ + KMDI::ToolViewAccessor *addToolWindow( QWidget* pWnd, KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L, int percent = 50, const QString& tabToolTip = 0, const QString& tabCaption = 0); + + /** + * delete the toolview belonging to the given accessor + * @param accessor toolview to delete + */ + void deleteToolWindow( KMDI::ToolViewAccessor *accessor); + + /** + * delete the toolview belonging to the given pWnd + * @param pWnd toolview to be deleted + */ + void deleteToolWindow( QWidget* pWnd); + + /** + * Sets the appearance of the toolview tabs. + * @param flags See KMDI::ToolviewStyle. + */ + void setToolViewStyle(int flags); + + public slots: + void prevToolViewInDock(); + void nextToolViewInDock(); + + signals: + void collapseOverlapContainers(); + + protected: + void findToolViewsDockedToMain(QPtrList<KDockWidget>* list,KDockWidget::DockPosition dprtmw); + void dockToolViewsIntoContainers(QPtrList<KDockWidget>& widgetsToReparent,KDockWidget *container); + + private: + /** + * setup main dock + tab widget + */ + void setupMainDock (); + + /** + * setup the sidebars for the toolviews + * and other internals to get them working + */ + void setupToolViews (); + + /** + * setup the menuentries + * must be done AFTER setupToolViews () + */ + void setupGUIClient (); + + private slots: + void setActiveToolDock(DockContainer*); + void removeFromActiveDockList(DockContainer*); + + #define protected public + signals: + #undef protected + void toggleTop(); + void toggleLeft(); + void toggleRight(); + void toggleBottom(); + + protected: + KMDIPrivate::GUIClient *m_guiClient; + QMap <QWidget*, KMDI::ToolViewAccessor*> *m_toolViews; + + KDockWidget *m_leftContainer; + KDockWidget *m_rightContainer; + KDockWidget *m_topContainer; + KDockWidget *m_bottomContainer; + + KMDI::TabWidget *m_tabWidget; + + private: + /** + * private d-pointer for BC + */ + KMDIPrivate::MainWindowPrivate *d; +}; + +} + +#endif //_MainWindow_H_ + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/tabwidget.cpp b/kmdi/kmdi/tabwidget.cpp new file mode 100644 index 000000000..5d18e3769 --- /dev/null +++ b/kmdi/kmdi/tabwidget.cpp @@ -0,0 +1,284 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Based on: + + //---------------------------------------------------------------------------- + // Project : KDE MDI extension + // + // begin : 07/1999 by Szymon Stefanek as part of kvirc + // (an IRC application) + // changes : 09/1999 by Falk Brettschneider to create an + // - 06/2000 stand-alone Qt extension set of + // classes and a Qt-based library + // : 02/2000 by Massimo Morin (mmorin@schedsys.com) + // 2000-2003 maintained by the KDevelop project + // patches : -/2000 by Lars Beikirch (Lars.Beikirch@gmx.net) + // : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) + // + // copyright : (C) 1999-2003 by Falk Brettschneider + // and + // Szymon Stefanek (stefanek@tin.it) + // email : falkbr@kdevelop.org (Falk Brettschneider) + //---------------------------------------------------------------------------- +*/ + +#include <ktabbar.h> +#include <kpopupmenu.h> +#include <kdebug.h> + +#include <qobjectlist.h> + +#include "tabwidget.h" +#include "tabwidget.moc" + +namespace KMDIPrivate +{ + class TabWidgetPrivate + { + + }; +} + +namespace KMDI +{ + +TabWidget::TabWidget(QWidget* parent, const char* name) + : KTabWidget(parent,name) + , m_visibility (KMDI::ShowWhenMoreThanOneTab) + , d (new KMDIPrivate::TabWidgetPrivate()) +{ + installEventFilter (this); + + tabBar()->hide(); + + setHoverCloseButton(true); + + connect(this, SIGNAL(closeRequest(QWidget*)), this, SLOT(closeTab(QWidget*))); +} + +TabWidget::~TabWidget() +{ + delete d; + d = 0; +} + +bool TabWidget::eventFilter(QObject *obj, QEvent *e ) +{ + if(e->type() == QEvent::FocusIn) + { + emit focusInEvent (); + } + else if (e->type() == QEvent::ChildRemoved) + { + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + QObject* pLostChild = ((QChildEvent*)e)->child(); + if ((pLostChild != 0L) && (pLostChild->isWidgetType())) { + QObjectList *list = pLostChild->queryList( "QWidget" ); + list->insert(0, pLostChild); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject * o; + while ( (o=it.current()) != 0 ) { // for each found object... + QWidget* widg = (QWidget*)o; + ++it; + widg->removeEventFilter(this); + } + delete list; // delete the list, not the objects + } + } + else if (e->type() == QEvent::ChildInserted) + { + // if we got a new child and we are attached to the MDI system we + // install ourself as event filter for the new child and its children + // (as we did when we were added to the MDI system). + QObject* pNewChild = ((QChildEvent*)e)->child(); + if ((pNewChild != 0L) && (pNewChild->isWidgetType())) + { + QWidget* pNewWidget = (QWidget*)pNewChild; + if (pNewWidget->testWFlags(Qt::WType_Dialog | Qt::WShowModal)) + return false; + QObjectList *list = pNewWidget->queryList( "QWidget" ); + list->insert(0, pNewChild); // add the new child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all new child widgets + QObject * o; + while ( (o=it.current()) != 0 ) { // for each found object... + QWidget* widg = (QWidget*)o; + ++it; + widg->installEventFilter(this); + connect(widg, SIGNAL(destroyed()), this, SLOT(childDestroyed())); + } + delete list; // delete the list, not the objects + } + } + + return KTabWidget::eventFilter (obj, e); +} + +void TabWidget::childDestroyed() +{ + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + const QObject* pLostChild = QObject::sender(); + if ((pLostChild != 0L) && (pLostChild->isWidgetType())) + { + QObjectList *list = ((QObject*)(pLostChild))->queryList("QWidget"); + list->insert(0, pLostChild); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject * obj; + while ( (obj=it.current()) != 0 ) { // for each found object... + QWidget* widg = (QWidget*)obj; + ++it; + widg->removeEventFilter(this); + } + delete list; // delete the list, not the objects + } +} + +void TabWidget::closeTab(QWidget* w) +{ + w->close(); +} + +void TabWidget::addTab ( QWidget * child, const QString & label ) +{ + KTabWidget::addTab(child,label); + showPage(child); + maybeShow(); +} + +void TabWidget::addTab ( QWidget * child, const QIconSet & iconset, const QString & label ) +{ + KTabWidget::addTab(child,iconset,label); + showPage(child); + maybeShow(); +} + +void TabWidget::addTab ( QWidget * child, QTab * tab ) +{ + KTabWidget::addTab(child,tab); + showPage(child); + maybeShow(); +} + +void TabWidget::insertTab ( QWidget * child, const QString & label, int index) +{ + KTabWidget::insertTab(child,label,index); + showPage(child); + maybeShow(); + tabBar()->repaint(); +} + +void TabWidget::insertTab ( QWidget * child, const QIconSet & iconset, const QString & label, int index ) +{ + KTabWidget::insertTab(child,iconset,label,index); + showPage(child); + maybeShow(); + tabBar()->repaint(); +} + +void TabWidget::insertTab ( QWidget * child, QTab * tab, int index) +{ + KTabWidget::insertTab(child,tab,index); + showPage(child); + maybeShow(); + tabBar()->repaint(); +} + +void TabWidget::removePage ( QWidget * w ) +{ + KTabWidget::removePage(w); + maybeShow(); +} + +void TabWidget::updateIconInView( QWidget *w, QPixmap icon ) +{ + changeTab(w,icon,tabLabel(w)); +} + +void TabWidget::updateCaptionInView( QWidget *w, const QString &caption ) +{ + changeTab(w, caption); +} + +void TabWidget::maybeShow() +{ + switch (m_visibility) + { + case KMDI::AlwaysShowTabs: + tabBar()->show(); + + // show/hide corner widgets + if (count() == 0) + setCornerWidgetVisibility(false); + else + setCornerWidgetVisibility(true); + + break; + + case KMDI::ShowWhenMoreThanOneTab: + if (count()<2) tabBar()->hide(); + else tabBar()->show(); + + // show/hide corner widgets + if (count() < 2) + setCornerWidgetVisibility(false); + else + setCornerWidgetVisibility(true); + + break; + + case KMDI::NeverShowTabs: + tabBar()->hide(); + break; + } +} + +void TabWidget::setCornerWidgetVisibility(bool visible) { + // there are two corner widgets: on TopLeft and on TopTight! + + if (cornerWidget(Qt::TopLeft) ) { + if (visible) + cornerWidget(Qt::TopLeft)->show(); + else + cornerWidget(Qt::TopLeft)->hide(); + } + + if (cornerWidget(Qt::TopRight) ) { + if (visible) + cornerWidget(Qt::TopRight)->show(); + else + cornerWidget(Qt::TopRight)->hide(); + } +} + +void TabWidget::setTabWidgetVisibility( KMDI::TabWidgetVisibility visibility ) +{ + m_visibility = visibility; + maybeShow(); +} + +KMDI::TabWidgetVisibility TabWidget::tabWidgetVisibility( ) const +{ + return m_visibility; +} + +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/tabwidget.h b/kmdi/kmdi/tabwidget.h new file mode 100644 index 000000000..9aa67d2aa --- /dev/null +++ b/kmdi/kmdi/tabwidget.h @@ -0,0 +1,115 @@ +/* This file is part of the KDE libraries + Copyright (C) 2004 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + Based on: + + //---------------------------------------------------------------------------- + // Project : KDE MDI extension + // + // begin : 07/1999 by Szymon Stefanek as part of kvirc + // (an IRC application) + // changes : 09/1999 by Falk Brettschneider to create an + // - 06/2000 stand-alone Qt extension set of + // classes and a Qt-based library + // : 02/2000 by Massimo Morin (mmorin@schedsys.com) + // 2000-2003 maintained by the KDevelop project + // patches : -/2000 by Lars Beikirch (Lars.Beikirch@gmx.net) + // : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) + // + // copyright : (C) 1999-2003 by Falk Brettschneider + // and + // Szymon Stefanek (stefanek@tin.it) + // email : falkbr@kdevelop.org (Falk Brettschneider) + //---------------------------------------------------------------------------- +*/ + +#ifndef _KMDI_TABWIDGET_H_ +#define _KMDI_TABWIDGET_H_ + +#include <ktabwidget.h> +#include <kmdi/global.h> + +namespace KMDIPrivate +{ + class TabWidgetPrivate; +} + +namespace KMDI +{ + +class KMDI_EXPORT TabWidget : public KTabWidget +{ + Q_OBJECT + + public: + TabWidget(QWidget* parent, const char* name=0); + virtual ~TabWidget(); + + virtual void addTab ( QWidget * child, const QString & label ); + + virtual void addTab ( QWidget * child, const QIconSet & iconset, const QString & label ); + + virtual void addTab ( QWidget * child, QTab * tab ); + + virtual void insertTab ( QWidget * child, const QString & label, int index = -1 ); + + virtual void insertTab ( QWidget * child, const QIconSet & iconset, const QString & label, int index = -1 ); + + virtual void insertTab ( QWidget * child, QTab * tab, int index = -1 ); + + virtual void removePage ( QWidget * w ); + + KMDI::TabWidgetVisibility tabWidgetVisibility() const; + + void setTabWidgetVisibility( KMDI::TabWidgetVisibility ); + + bool eventFilter(QObject *obj, QEvent *e ); + + private slots: + void closeTab(QWidget* w); + + public slots: + void updateIconInView(QWidget*,QPixmap); + void updateCaptionInView(QWidget*,const QString&); + + signals: + void focusInEvent (); + + protected slots: + void childDestroyed (); + + private: + void maybeShow(); + void setCornerWidgetVisibility(bool visible); + + private: + KMDI::TabWidgetVisibility m_visibility; + + private: + /** + * private d-pointer for BC + */ + KMDIPrivate::TabWidgetPrivate *d; +}; + +} + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/toolviewaccessor.cpp b/kmdi/kmdi/toolviewaccessor.cpp new file mode 100644 index 000000000..11e1ce4f3 --- /dev/null +++ b/kmdi/kmdi/toolviewaccessor.cpp @@ -0,0 +1,223 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> + +#include "toolviewaccessor_p.h" +#include "guiclient.h" +#include "mainwindow.h" + +#include "toolviewaccessor.h" +#include "toolviewaccessor.moc" + +#include "toolviewaccessor_p.h" + +namespace KMDI +{ + +ToolViewAccessor::ToolViewAccessor( KMDI::MainWindow *parent, QWidget *widgetToWrap, const QString& tabToolTip, const QString& tabCaption) +: QObject(parent) +{ + mdiMainFrm=parent; + d=new KMDIPrivate::ToolViewAccessorPrivate(); + if (widgetToWrap->inherits("KDockWidget")) { + d->widgetContainer=dynamic_cast<KDockWidget*>(widgetToWrap); + d->widget=d->widgetContainer->getWidget(); + } else { + d->widget=widgetToWrap; + QString finalTabCaption; + if (tabCaption == 0) { + finalTabCaption = widgetToWrap->caption(); + if (finalTabCaption.isEmpty() && !widgetToWrap->icon()) { + finalTabCaption = widgetToWrap->name(); + } + } + else { + finalTabCaption = tabCaption; + } + d->widgetContainer= parent->createDockWidget( widgetToWrap->name(), + (widgetToWrap->icon()?(*(widgetToWrap->icon())):QPixmap()), + 0L, // parent + widgetToWrap->caption(), + finalTabCaption); + d->widgetContainer->setWidget(widgetToWrap); + if (tabToolTip!=0) { + d->widgetContainer->setToolTipString(tabToolTip); + } + } + + //mdiMainFrm->m_toolViews.insert(d->widget,this); + mdiMainFrm->m_guiClient->addToolView(this); + d->widget->installEventFilter(this); +} + +ToolViewAccessor::ToolViewAccessor( KMDI::MainWindow *parent) : QObject(parent) { + mdiMainFrm=parent; + d=new KMDIPrivate::ToolViewAccessorPrivate(); +} + +ToolViewAccessor::~ToolViewAccessor() { + if (mdiMainFrm->m_toolViews) + mdiMainFrm->m_toolViews->remove(d->widget); + delete d; + +} + +QWidget *ToolViewAccessor::wrapperWidget() { + if (!d->widgetContainer) { + d->widgetContainer=mdiMainFrm->createDockWidget( "ToolViewAccessor::null",QPixmap()); + connect(d->widgetContainer,SIGNAL(widgetSet(QWidget*)),this,SLOT(setWidgetToWrap(QWidget*))); + } + return d->widgetContainer; +} + +QWidget *ToolViewAccessor::wrappedWidget() { + return d->widget; +} + + +void ToolViewAccessor::setWidgetToWrap(QWidget *widgetToWrap, const QString& tabToolTip, const QString& tabCaption) +{ + Q_ASSERT(!(d->widget)); + Q_ASSERT(!widgetToWrap->inherits("KDockWidget")); + disconnect(d->widgetContainer,SIGNAL(widgetSet(QWidget*)),this,SLOT(setWidgetToWrap(QWidget*))); + delete d->widget; + d->widget=widgetToWrap; + KDockWidget *tmp=d->widgetContainer; + + QString finalTabCaption; + if (tabCaption == 0) { + finalTabCaption = widgetToWrap->caption(); + if (finalTabCaption.isEmpty() && !widgetToWrap->icon()) { + finalTabCaption = widgetToWrap->name(); + } + } + else { + finalTabCaption = tabCaption; + } + + if (!tmp) { + tmp = mdiMainFrm->createDockWidget( widgetToWrap->name(), + widgetToWrap->icon()?(*(widgetToWrap->icon())):QPixmap(), + 0L, // parent + widgetToWrap->caption(), + finalTabCaption ); + d->widgetContainer= tmp; + if (tabToolTip!=0) { + d->widgetContainer->setToolTipString(tabToolTip); + } + } + else { + tmp->setCaption(widgetToWrap->caption()); + tmp->setTabPageLabel(finalTabCaption); + tmp->setPixmap(widgetToWrap->icon()?(*(widgetToWrap->icon())):QPixmap()); + tmp->setName(widgetToWrap->name()); + if (tabToolTip!=0) { + d->widgetContainer->setToolTipString(tabToolTip); + } + } + tmp->setWidget(widgetToWrap); + mdiMainFrm->m_toolViews->insert(widgetToWrap,this); + mdiMainFrm->m_guiClient->addToolView(this); + + d->widget->installEventFilter(this); +} + + +bool ToolViewAccessor::eventFilter(QObject *o, QEvent *e) { + if (e->type()==QEvent::IconChange) { + d->widgetContainer->setPixmap(d->widget->icon()?(*d->widget->icon()):QPixmap()); + } + return false; +} + +void ToolViewAccessor::placeAndShow(KDockWidget::DockPosition pos, QWidget* pTargetWnd ,int percent) +{ + place(pos,pTargetWnd,percent); + show(); +} +void ToolViewAccessor::place(KDockWidget::DockPosition pos, QWidget* pTargetWnd ,int percent) +{ + Q_ASSERT(d->widgetContainer); + if (!d->widgetContainer) return; + if (pos == KDockWidget::DockNone) { + d->widgetContainer->setEnableDocking(KDockWidget::DockNone); + d->widgetContainer->reparent(mdiMainFrm, Qt::WType_TopLevel | Qt::WType_Dialog, QPoint(0,0), mdiMainFrm->isVisible()); + } + else { // add (and dock) the toolview as DockWidget view + + KDockWidget* pCover = d->widgetContainer; + + KDockWidget* pTargetDock = 0L; + if (pTargetWnd->inherits("KDockWidget") || pTargetWnd->inherits("KDockWidget_Compat::KDockWidget")) { + pTargetDock = (KDockWidget*) pTargetWnd; + } + + // Should we dock to ourself? + bool DockToOurself = false; + if (mdiMainFrm->getMainDockWidget()) { + if (pTargetWnd == mdiMainFrm->getMainDockWidget()->getWidget()) { + DockToOurself = true; + pTargetDock = mdiMainFrm->getMainDockWidget(); + } + else if (pTargetWnd == mdiMainFrm->getMainDockWidget()) { + DockToOurself = true; + pTargetDock = mdiMainFrm->getMainDockWidget(); + } + } + // this is not inheriting QWidget*, its plain impossible that this condition is true + //if (pTargetWnd == this) DockToOurself = true; + if (!DockToOurself) if(pTargetWnd != 0L) { + pTargetDock = mdiMainFrm->dockManager->findWidgetParentDock( pTargetWnd); + if (!pTargetDock) { + if (pTargetWnd->parentWidget()) { + pTargetDock = mdiMainFrm->dockManager->findWidgetParentDock( pTargetWnd->parentWidget()); + } + } + } + /* if (!pTargetDock || pTargetWnd == mdiMainFrm->getMainDockWidget()) { + if (mdiMainFrm->m_managedDockPositionMode && (mdiMainFrm->m_pMdi || mdiMainFrm->m_documentTabWidget)) { + KDockWidget *dw1=pTargetDock->findNearestDockWidget(pos); + if (dw1) + pCover->manualDock(dw1,KDockWidget::DockCenter,percent); + else + pCover->manualDock ( pTargetDock, pos, 20 ); + return; + } + }*/ //TODO + pCover->manualDock( pTargetDock, pos, percent); +//check pCover->show(); + } +} + +void ToolViewAccessor::hide() { + Q_ASSERT(d->widgetContainer); + if (!d->widgetContainer) return; + d->widgetContainer->undock(); +} + +void ToolViewAccessor::show() { + Q_ASSERT(d->widgetContainer); + if (!d->widgetContainer) return; + d->widgetContainer->makeDockVisible(); +} + +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/toolviewaccessor.h b/kmdi/kmdi/toolviewaccessor.h new file mode 100644 index 000000000..2a1bd4de2 --- /dev/null +++ b/kmdi/kmdi/toolviewaccessor.h @@ -0,0 +1,88 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _KMDI_TOOLVIEWACCESSOR_H_ +#define _KMDI_TOOLVIEWACCESSOR_H_ + +#include <qwidget.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdatetime.h> + +#include <kdockwidget.h> + +namespace KMDIPrivate { + class GUIClient; + class ToolViewAccessorPrivate; +} + +namespace KMDI { + +class MainWindow; + +class ToolViewAccessor : public QObject +{ + Q_OBJECT + + friend class KMDI::MainWindow; + friend class KMDIPrivate::GUIClient; + +private: + /** + * Internally used by KMDI::MainWindow to store a temporary information that the method + * activate() is unnecessary and that it can by escaped. + * This saves from unnecessary calls when activate is called directly. + */ + bool m_bInterruptActivation; + /** + * Internally used to prevent cycles between KMDI::MainWindow::activateView() and KMdiChildView::activate(). + */ + bool m_bMainframesActivateViewIsPending; + /** + * + */ + bool m_bFocusInEventIsPending; + +private: + ToolViewAccessor( KMDI::MainWindow *parent , QWidget *widgetToWrap, const QString& tabToolTip = 0, const QString& tabCaption = 0); + ToolViewAccessor( KMDI::MainWindow *parent); +public: + ~ToolViewAccessor(); + QWidget *wrapperWidget(); + QWidget *wrappedWidget(); + void place(KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L,int percent = 50); + void placeAndShow(KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L,int percent = 50); + void show(); +public slots: + void setWidgetToWrap(QWidget* widgetToWrap, const QString& tabToolTip = 0, const QString& tabCaption = 0); + void hide(); +private: + KMDIPrivate::ToolViewAccessorPrivate *d; + KMDI::MainWindow *mdiMainFrm; + +protected: + bool eventFilter(QObject *o, QEvent *e); +}; + +} + +#endif //_KMDITOOLVIEWACCESSOR_H_ + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/kmdi/kmdi/toolviewaccessor_p.h b/kmdi/kmdi/toolviewaccessor_p.h new file mode 100644 index 000000000..3d7b6161a --- /dev/null +++ b/kmdi/kmdi/toolviewaccessor_p.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KMDI_TOOLVIEW_ACCESSOR_PRIVATE_H_ +#define KMDI_TOOLVIEW_ACCESSOR_PRIVATE_H_ + +#include <kdockwidget.h> +#include <qguardedptr.h> +#include <kaction.h> + +namespace KMDIPrivate +{ + +class ToolViewAccessorPrivate +{ + public: + ToolViewAccessorPrivate() + : widgetContainer (0) + , widget (0) + { + } + + ~ToolViewAccessorPrivate() + { + delete action; + + if (!widgetContainer.isNull()) + widgetContainer->undock(); + + delete (KDockWidget*)widgetContainer; + } + + QGuardedPtr<KDockWidget> widgetContainer; + QWidget *widget; + QGuardedPtr<KAction> action; +}; + +} + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; + + diff --git a/kmdi/kmdichildarea.cpp b/kmdi/kmdichildarea.cpp new file mode 100644 index 000000000..8074dac41 --- /dev/null +++ b/kmdi/kmdichildarea.cpp @@ -0,0 +1,789 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildarea.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#include "kmdichildarea.h" +#include "kmdichildarea.moc" + +#include "kmdidefines.h" + +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> + +#include <math.h> +#include <qpopupmenu.h> + + +/////////////////////////////////////////////////////////////////////////////// +// KMdiChildArea +/////////////////////////////////////////////////////////////////////////////// + +//============ KMdiChildArea ============// + +KMdiChildArea::KMdiChildArea( QWidget *parent ) + : QFrame( parent, "kmdi_childarea" ) +{ + setFrameStyle( QFrame::Panel | QFrame::Sunken ); + m_captionFont = QFont(); + QFontMetrics fm( m_captionFont ); + m_captionFontLineSpacing = fm.lineSpacing(); + m_captionActiveBackColor = KGlobalSettings::activeTitleColor(); + m_captionActiveForeColor = KGlobalSettings::activeTextColor(); + m_captionInactiveBackColor = KGlobalSettings::inactiveTitleColor(); + m_captionInactiveForeColor = KGlobalSettings::inactiveTextColor(); + m_pZ = new QPtrList<KMdiChildFrm>; + m_pZ->setAutoDelete( true ); + setFocusPolicy( ClickFocus ); + m_defaultChildFrmSize = QSize( 400, 300 ); +} + + +KMdiChildArea::~KMdiChildArea() +{ + delete m_pZ; //This will destroy all the widgets inside. +} + + +void KMdiChildArea::manageChild( KMdiChildFrm* child, bool show, bool cascade ) +{ + kdDebug( 760 ) << k_funcinfo << "Adding child " << child << " to be managed" << endl; + KMdiChildFrm* top = topChild(); + + //remove old references. There can be more than one so we remove them all + if ( m_pZ->findRef( child ) != -1 ) + { + //QPtrList::find* moves current() to the found item + m_pZ->take(); + while ( m_pZ->findNextRef( child ) != -1 ) + m_pZ->take(); + } + + if ( show ) + m_pZ->append( child ); //visible -> first in the Z order + else + m_pZ->insert( 0, child ); //hidden -> last in the Z order + + if ( cascade ) + child->move( getCascadePoint( m_pZ->count() - 1 ) ); + + if ( show ) + { + if ( top && top->state() == KMdiChildFrm::Maximized ) + { + kdDebug( 760 ) << k_funcinfo << "Maximizing the new child" << endl; + emit sysButtonConnectionsMustChange( top, child ); + top->setState( KMdiChildFrm::Normal, false /*animate*/ ); + child->setState( KMdiChildFrm::Maximized, false /*animate*/ ); + } + child->show(); + focusTopChild(); + } +} + + +void KMdiChildArea::destroyChild( KMdiChildFrm *child, bool focusTop ) +{ + kdDebug( 760 ) << k_funcinfo << "Removing child " << child->caption() << endl; + bool wasMaximized = ( child->state() == KMdiChildFrm::Maximized ); + + // destroy the old one + QObject::disconnect( child ); + child->blockSignals( true ); + m_pZ->setAutoDelete( false ); + m_pZ->removeRef( child ); + + // focus the next new childframe + KMdiChildFrm* newTopChild = topChild(); + if ( wasMaximized ) + { + if ( newTopChild ) + { + newTopChild->setState( KMdiChildFrm::Maximized, false ); + emit sysButtonConnectionsMustChange( child, newTopChild ); + } + else + emit noMaximizedChildFrmLeft( child ); // last childframe removed + } + + delete child; + m_pZ->setAutoDelete( true ); + + if ( focusTop ) + focusTopChild(); +} + + +void KMdiChildArea::destroyChildButNotItsView( KMdiChildFrm* child, bool focusTop ) +{ + kdDebug( 760 ) << k_funcinfo << "Removing child " << child->caption() << endl; + bool wasMaximized = ( child->state() == KMdiChildFrm::Maximized ); + + // destroy the old one + QObject::disconnect( child ); + child->unsetClient(); + m_pZ->setAutoDelete( false ); + m_pZ->removeRef( child ); + + // focus the next new childframe + KMdiChildFrm* newTopChild = topChild(); + if ( wasMaximized ) + { + if ( newTopChild ) + { + newTopChild->setState( KMdiChildFrm::Maximized, false ); + emit sysButtonConnectionsMustChange( child, newTopChild ); + } + else + emit noMaximizedChildFrmLeft( child ); // last childframe removed + } + delete child; + m_pZ->setAutoDelete( true ); + + if ( focusTop ) + focusTopChild(); +} + +void KMdiChildArea::setTopChild( KMdiChildFrm* child, bool /* bSetFocus */ ) +{ + if ( !child ) + return; + + if ( topChild() != child ) + { + kdDebug( 760 ) << k_funcinfo << "Setting " << child->caption() << " as the new top child" << endl; + m_pZ->setAutoDelete( false ); + if ( child ) + m_pZ->removeRef( child ); + m_pZ->setAutoDelete( true ); + + //disable the labels of all the other children + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + ( *it )->m_pCaption->setActive( false ); + + KMdiChildFrm* maximizedChild = topChild(); + bool topChildMaximized = false; + if ( maximizedChild && maximizedChild->state() == KMdiChildFrm::Maximized ) + topChildMaximized = true; + + m_pZ->append( child ); + + int nChildAreaMinW = 0, nChildAreaMinH = 0; + int nChildAreaMaxW = QWIDGETSIZE_MAX, nChildAreaMaxH = QWIDGETSIZE_MAX; + if ( topChildMaximized && child->m_pClient ) + { + //the former top child is maximized, so maximize the new one + nChildAreaMinW = child->m_pClient->minimumWidth(); + nChildAreaMinH = child->m_pClient->minimumHeight(); + /// @todo: setting the maximum size doesn't work properly - fix this later + // nChildAreaMaxW = child->m_pClient->maximumWidth(); + // nChildAreaMaxH = child->m_pClient->maximumHeight(); + } + + //set the min and max sizes of this child area to the new top child + setMinimumSize( nChildAreaMinW, nChildAreaMinH ); + setMaximumSize( nChildAreaMaxW, nChildAreaMaxH ); + + if ( topChildMaximized ) + { //maximize the new view and restore the old + child->setState( KMdiChildFrm::Maximized, false /*animate*/); + maximizedChild->setState( KMdiChildFrm::Normal, false /*animate*/ ); + emit sysButtonConnectionsMustChange( maximizedChild, child ); + } + else + child->raise(); + + QFocusEvent::setReason( QFocusEvent::Other ); + child->m_pClient->setFocus(); + } +} + + +void KMdiChildArea::resizeEvent( QResizeEvent* e ) +{ + //If we have a maximized children at the top , adjust its size + KMdiChildFrm* child = topChild(); + if ( child && child->state() == KMdiChildFrm::Maximized ) + { + int clientw = 0, clienth = 0; + if ( child->m_pClient != 0L ) + { + clientw = child->m_pClient->width(); + clienth = child->m_pClient->height(); + } + child->resize( width() + KMDI_CHILDFRM_DOUBLE_BORDER, + height() + child->m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER ); + + } + layoutMinimizedChildren(); + QWidget::resizeEvent( e ); +} + +//=============== mousePressEvent =============// + +void KMdiChildArea::mousePressEvent( QMouseEvent *e ) +{ + //Popup the window menu + if ( e->button() & RightButton ) + emit popupWindowMenu( mapToGlobal( e->pos() ) ); +} + +//=============== getCascadePoint ============// + +QPoint KMdiChildArea::getCascadePoint( int indexOfWindow ) +{ + if ( indexOfWindow < 0 ) + { + indexOfWindow = m_pZ->count(); //use the window count + kdDebug( 760 ) << k_funcinfo << "indexOfWindow was less than zero, using " + << indexOfWindow << " as new index" << endl; + } + + QPoint pnt( 0, 0 ); + if ( indexOfWindow == 0 ) + { + kdDebug( 760 ) << k_funcinfo << "No windows. Returning QPoint( 0, 0 ) as the cascade point" << endl; + return pnt; + } + + bool topLevelMode = false; + if ( height() == 1 ) // hacky?! + topLevelMode = true; + + kdDebug( 760 ) << k_funcinfo << "Getting the cascade point for window index " << indexOfWindow << endl; + kdDebug( 760 ) << k_funcinfo << "Do we think we're in top level mode? " << topLevelMode << endl; + + KMdiChildFrm* child = m_pZ->first(); + + //default values + int step = 20; + int h = ( topLevelMode ? QApplication::desktop()->height() : height() ); + int w = ( topLevelMode ? QApplication::desktop()->width() : width() ); + + int availableHeight = h - m_defaultChildFrmSize.height(); + int availableWidth = w - m_defaultChildFrmSize.width(); + int ax = 0; + int ay = 0; + + if ( child ) + { + kdDebug( 760 ) << k_funcinfo << "child frame exists. resetting height and width values" << endl; + step = child->m_pCaption->heightHint() + KMDI_CHILDFRM_BORDER; + availableHeight = h - child->minimumHeight(); + availableWidth = w - child->minimumWidth(); + } + + for ( int i = 0; i < indexOfWindow; i++ ) + { + ax += step; + ay += step; + + //do some bounds checking, because to not do it would be bad. + if ( ax > availableWidth ) + ax = 0; + + if ( ay > availableHeight ) + ay = 0; + } + pnt.setX( ax ); + pnt.setY( ay ); + return pnt; +} + + +void KMdiChildArea::childMinimized( KMdiChildFrm *minimizedChild, bool wasMaximized ) +{ + //can't find the child in our list, so we don't care. + if ( m_pZ->findRef( minimizedChild ) == -1 ) + { + kdDebug( 760 ) << k_funcinfo << "child was minimized but wasn't in our list!" << endl; + return; + } + + kdDebug( 760 ) << k_funcinfo << endl; + if ( m_pZ->count() > 1 ) + { + //move the minimized child to the bottom + m_pZ->setAutoDelete( false ); + m_pZ->removeRef( minimizedChild ); + m_pZ->setAutoDelete( true ); + m_pZ->insert( 0, minimizedChild ); + + if ( wasMaximized ) + { // Need to maximize the new top child + kdDebug( 760 ) << k_funcinfo << "child just minimized from maximized state. maximize new top child" << endl; + minimizedChild = topChild(); + if ( !minimizedChild ) + return; //?? + + if ( minimizedChild->state() == KMdiChildFrm::Maximized ) + return; //it's already maximized + + minimizedChild->setState( KMdiChildFrm::Maximized, false ); //do not animate the change + } + focusTopChild(); + } + else + setFocus(); //Remove focus from the child. We only have one window +} + +void KMdiChildArea::focusTopChild() +{ + KMdiChildFrm* lastChild = topChild(); + if ( !lastChild ) + { + kdDebug( 760 ) << k_funcinfo << "No more child windows left" << endl; + emit lastChildFrmClosed(); + return; + } + + if ( !lastChild->m_pClient->hasFocus() ) + { + //disable the labels of all the other children + QPtrListIterator<KMdiChildFrm> it ( *m_pZ ); + for ( ; ( *it ); ++it ) + { + if ( ( *it ) != lastChild ) + ( *it )->m_pCaption->setActive( false ); + } + + kdDebug( 760 ) << k_funcinfo << "Giving focus to " << lastChild->caption() << endl; + lastChild->raise(); + lastChild->m_pClient->activate(); + } + +} + +void KMdiChildArea::cascadeWindows() +{ + kdDebug( 760 ) << k_funcinfo << "cascading windows but not changing their size" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if ( childFrm->state() != KMdiChildFrm::Minimized ) + { + if ( childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + childFrm->move( getCascadePoint( idx ) ); + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +void KMdiChildArea::cascadeMaximized() +{ + kdDebug( 760 ) << k_funcinfo << "cascading windows. will make sure they are minimum sized" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if (childFrm->state() != KMdiChildFrm::Minimized ) + { + if (childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + QPoint pnt( getCascadePoint( idx ) ); + childFrm->move( pnt ); + QSize curSize( width() - pnt.x(), height() - pnt.y() ); + + if ( ( childFrm->minimumSize().width() > curSize.width() ) || + ( childFrm->minimumSize().height() > curSize.height() ) ) + { + childFrm->resize( childFrm->minimumSize() ); + } + else + childFrm->resize( curSize ); + + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +void KMdiChildArea::expandVertical() +{ + kdDebug( 760 ) << k_funcinfo << "expanding all child frames vertically" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if ( childFrm->state() != KMdiChildFrm::Minimized ) + { + if ( childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + childFrm->setGeometry( childFrm->x(), 0, childFrm->width(), height() ); + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +void KMdiChildArea::expandHorizontal() +{ + kdDebug( 760 ) << k_funcinfo << "expanding all child frames horizontally" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if ( childFrm->state() != KMdiChildFrm::Minimized ) + { + if ( childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + childFrm->setGeometry( 0, childFrm->y(), width(), childFrm->height() ); + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +int KMdiChildArea::getVisibleChildCount() const +{ + int visibleChildCount = 0; + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + if ( ( *it )->state() != KMdiChildFrm::Minimized && ( *it )->isVisible() ) + visibleChildCount++; + } + return visibleChildCount; +} + +void KMdiChildArea::tilePragma() +{ + kdDebug( 760 ) << k_funcinfo << endl; + tileAllInternal( 9 ); +} + +void KMdiChildArea::tileAllInternal( int maxWnds ) +{ + kdDebug( 760 ) << k_funcinfo << endl; + //NUM WINDOWS = 1,2,3,4,5,6,7,8,9 + static int colstable[ 9 ] = { 1, 1, 1, 2, 2, 2, 3, 3, 3 }; //num columns + static int rowstable[ 9 ] = { 1, 2, 3, 2, 3, 3, 3, 3, 3 }; //num rows + static int lastwindw[ 9 ] = { 1, 1, 1, 1, 2, 1, 3, 2, 1 }; //last window multiplier + static int colrecall[ 9 ] = { 0, 0, 0, 3, 3, 3, 6, 6, 6 }; //adjust self + static int rowrecall[ 9 ] = { 0, 0, 0, 0, 4, 4, 4, 4, 4 }; //adjust self + + int numVisible = getVisibleChildCount(); + if ( numVisible < 1 ) + { + kdDebug( 760 ) << k_funcinfo << "No visible child windows to tile" << endl; + return; + } + + KMdiChildFrm *tcw = topChild(); + int numToHandle = ( ( numVisible > maxWnds ) ? maxWnds : numVisible ); + + int xQuantum = width() / colstable[ numToHandle - 1 ]; + int widthToCompare; + + if ( tcw->minimumWidth() > m_defaultChildFrmSize.width() ) + widthToCompare = tcw->minimumWidth(); + else + widthToCompare = m_defaultChildFrmSize.width(); + + if ( xQuantum < widthToCompare ) + { + if ( colrecall[ numToHandle - 1 ] != 0 ) + { + tileAllInternal( colrecall[ numToHandle - 1 ] ); + return ; + } + } + + int yQuantum = height() / rowstable[ numToHandle - 1 ]; + int heightToCompare; + if ( tcw->minimumHeight() > m_defaultChildFrmSize.height() ) + heightToCompare = tcw->minimumHeight(); + else + heightToCompare = m_defaultChildFrmSize.height(); + + if ( yQuantum < heightToCompare ) + { + if ( rowrecall[ numToHandle - 1 ] != 0 ) + { + tileAllInternal( rowrecall[ numToHandle - 1 ] ); + return ; + } + } + int curX = 0; + int curY = 0; + int curRow = 1; + int curCol = 1; + int curWin = 1; + + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = ( *it ); + if ( child->state() != KMdiChildFrm::Minimized ) + { + //restore the window + if ( child->state() == KMdiChildFrm::Maximized ) + child->restorePressed(); + + if ( ( curWin % numToHandle ) == 0 ) + child->setGeometry( curX, curY, xQuantum * lastwindw[ numToHandle - 1 ], yQuantum ); + else + child->setGeometry( curX, curY, xQuantum, yQuantum ); + + //example : 12 windows : 3 cols 3 rows + if ( curCol < colstable[ numToHandle - 1 ] ) + { //curCol<3 + curX += xQuantum; //add a column in the same row + curCol++; //increase current column + } + else + { + curX = 0; //new row + curCol = 1; //column 1 + if ( curRow < rowstable[ numToHandle - 1 ] ) + { //curRow<3 + curY += yQuantum; //add a row + curRow++; //increase current row + } + else + { + curY = 0; //restart from beginning + curRow = 1; //reset current row + } + } + curWin++; + } + } + + if ( tcw ) + tcw->m_pClient->activate(); +} + +void KMdiChildArea::tileAnodine() +{ + KMdiChildFrm * topChildWindow = topChild(); + int numVisible = getVisibleChildCount(); // count visible windows + if ( numVisible < 1 ) + return ; + + int numCols = int( sqrt( ( double ) numVisible ) ); // set columns to square root of visible count + // create an array to form grid layout + int *numRows = new int[ numCols ]; + int numCurCol = 0; + + while ( numCurCol < numCols ) + { + numRows[numCurCol] = numCols; // create primary grid values + numCurCol++; + } + + int numDiff = numVisible - ( numCols * numCols ); // count extra rows + int numCurDiffCol = numCols; // set column limiting for grid updates + + while ( numDiff > 0 ) + { + numCurDiffCol--; + numRows[numCurDiffCol]++; // add extra rows to column grid + + if ( numCurDiffCol < 1 ) + numCurDiffCol = numCols; // rotate through the grid + + numDiff--; + } + + numCurCol = 0; + int numCurRow = 0; + int curX = 0; + int curY = 0; + + // the following code will size everything based on my grid above + // there is no limit to the number of windows it will handle + // it's great when a kick-ass theory works!!! // Pragma :) + int xQuantum = width() / numCols; + int yQuantum = height() / numRows[numCurCol]; + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = ( *it ); + if ( child->state() != KMdiChildFrm::Minimized ) + { + if ( child->state() == KMdiChildFrm::Maximized ) + child->restorePressed(); + + child->setGeometry( curX, curY, xQuantum, yQuantum ); + numCurRow++; + curY += yQuantum; + + if ( numCurRow == numRows[numCurCol] ) + { + numCurRow = 0; + numCurCol++; + curY = 0; + curX += xQuantum; + if ( numCurCol != numCols ) + yQuantum = height() / numRows[ numCurCol ]; + } + } + } + + delete[] numRows; + + if ( topChildWindow ) + topChildWindow->m_pClient->activate(); +} + + +void KMdiChildArea::tileVertically() +{ + KMdiChildFrm * topChildWindow = topChild(); + int numVisible = getVisibleChildCount(); // count visible windows + if ( numVisible < 1 ) + return ; + + int w = width() / numVisible; + int lastWidth = 0; + + if ( numVisible > 1 ) + lastWidth = width() - ( w * ( numVisible - 1 ) ); + else + lastWidth = w; + + int h = height(); + int posX = 0; + int countVisible = 0; + + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = ( *it ); + if ( child->state() != KMdiChildFrm::Minimized ) + { + if ( child->state() == KMdiChildFrm::Maximized ) + child->restorePressed(); + + countVisible++; + + if ( countVisible < numVisible ) + { + child->setGeometry( posX, 0, w, h ); + posX += w; + } + else + { // last visible childframe + child->setGeometry( posX, 0, lastWidth, h ); + } + } + } + + if ( topChildWindow ) + topChildWindow->m_pClient->activate(); +} + + +void KMdiChildArea::layoutMinimizedChildren() +{ + int posX = 0; + int posY = height(); + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = *( it ); + if ( child->state() == KMdiChildFrm::Minimized ) + { + + if ( ( posX > 0 ) && ( posX + child->width() > width() ) ) + { + posX = 0; + posY -= child->height(); + } + + child->move( posX, posY - child->height() ); + posX = child->geometry().right(); + } + } +} + + +void KMdiChildArea::setMdiCaptionFont( const QFont& fnt ) +{ + m_captionFont = fnt; + QFontMetrics fm( m_captionFont ); + m_captionFontLineSpacing = fm.lineSpacing(); + + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + ( *it )->doResize(); + +} + +void KMdiChildArea::setMdiCaptionActiveForeColor( const QColor& clr ) +{ + m_captionActiveForeColor = clr; +} + +void KMdiChildArea::setMdiCaptionActiveBackColor( const QColor& clr ) +{ + m_captionActiveBackColor = clr; +} + +void KMdiChildArea::setMdiCaptionInactiveForeColor( const QColor& clr ) +{ + m_captionInactiveForeColor = clr; +} + +void KMdiChildArea::setMdiCaptionInactiveBackColor( const QColor& clr ) +{ + m_captionInactiveBackColor = clr; +} + +//KDE4: remove +void KMdiChildArea::getCaptionColors( const QPalette& /*pal*/, QColor& activeBG, + QColor& activeFG, QColor& inactiveBG, QColor& inactiveFG ) +{ + activeBG = KGlobalSettings::activeTitleColor(); + activeFG = KGlobalSettings::activeTextColor(); + inactiveBG = KGlobalSettings::inactiveTitleColor(); + inactiveFG = KGlobalSettings::inactiveTextColor(); +} + +// kate: space-indent off; replace-tabs off; tab-width 4; indent-mode csands; diff --git a/kmdi/kmdichildarea.h b/kmdi/kmdichildarea.h new file mode 100644 index 000000000..7bbe07fff --- /dev/null +++ b/kmdi/kmdichildarea.h @@ -0,0 +1,304 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildarea.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDI_CHILD_AREA_H_ +#define _KMDI_CHILD_AREA_H_ + +#include <qframe.h> +#include <qptrlist.h> + +#include "kmdichildfrm.h" +#include "kmdichildview.h" + +class KMdiChildAreaPrivate; + +/** + * @short Internal class. + * + * The main frame widget KMdiMainFrm consists of 2 child widgets. One is this class. + * It's the widget where the child frames (emulated toplevel MDI views) live in. + * This class is the manager for the child frame widgets because it controls the + * Z-order widget stack of KMdiChildFrm's. + * It provides all placing and positioning algorithms for docked (attached) MDI views. + * + * KMdiChildArea doesn't know anything about the actual MDI views. It only knows + * and manages the frame widgets of attached MDI views. + * All actions and stuff concerning only to childframes are handled here. + */ +class KMDI_EXPORT KMdiChildArea : public QFrame +{ + friend class KMdiChildFrmCaption; + friend class KMdiChildFrm; + +Q_OBJECT + + // attributes +public: + /** + * Z Order stack of KMdiChildFrm childframe windows (top=last) + */ + QPtrList<KMdiChildFrm> *m_pZ; //Auto delete enabled + + /** + * the default size of an newly created childframe + */ + QSize m_defaultChildFrmSize; +protected: + /** + * The MDI childframe window caption font + */ + QFont m_captionFont; + + /** + * The foreground color of the active MDI childframe window caption + */ + QColor m_captionActiveBackColor; + + /** + * The background color of the active MDI childframe window captions + */ + QColor m_captionActiveForeColor; + + /** + * The foreground color of inactive MDI childframe window captions + */ + QColor m_captionInactiveBackColor; + + /** + * The background color of inactive MDI childframe window captions + */ + QColor m_captionInactiveForeColor; + + int m_captionFontLineSpacing; + + // methods +public: + + /** + * Consruction. Note: This class needn't to know about KMdiMainFrm . + */ + KMdiChildArea( QWidget *parent ); + + /** + * Destructor : THERE should be no child windows anymore... + * Howewer it simply deletes all the child widgets :) + */ + ~KMdiChildArea(); + + /** + * Appends a new KMdiChildFrm to this manager. + * The child is shown,raised and gets focus if this window has it. + */ + void manageChild( KMdiChildFrm *lpC, bool bShow = true, bool bCascade = true ); + + /** + * Destroys a managed KMdiChildFrm + * Also deletes the client attached to this child. + */ + void destroyChild( KMdiChildFrm* child, bool focusTopChild = true ); + + /** + * Destroys a managed KMdiChildFrm + * Clients attached to the KMdiChildFrm are not deleted. + */ + void destroyChildButNotItsView( KMdiChildFrm *lpC, bool bFocusTopChild = true ); + + /** + * Brings the child to the top of the stack + * The child is focused if setFocus is true. If setFocus is false, the + * child is just raised. + */ + void setTopChild( KMdiChildFrm* child, bool setFocus = false ); + + /** + * Returns the topmost child (the active one) or 0 if there are no children. + * Note that the topmost child may be also hidded , if ALL the windows are minimized. + */ + inline KMdiChildFrm * topChild() const { return m_pZ->last(); } + + /** + * Returns the number of visible children + */ + int getVisibleChildCount() const; + + /** + * Calculates the cascade point for the given index. If index is -1 + * the cascade point is calculated for the window following the last window + * @param indexOfWindow the index of the window in relation the z-ordered window list + */ + QPoint getCascadePoint( int indexOfWindow = -1 ); + + /** + * Sets the MDI childframe window caption font + * A relayout does not occur when using this function + */ + void setMdiCaptionFont( const QFont &fnt ); + + /** + * Sets the foreground color of the active MDI childframe window caption + * A relayout does not occur when using this function + */ + void setMdiCaptionActiveForeColor( const QColor &clr ); + + /** + * Sets the background color of the active MDI childframe window captions + * A relayout does not occur when using this function + */ + void setMdiCaptionActiveBackColor( const QColor &clr ); + + /** + * Sets the foreground color of inactive MDI childframe window captions + * A relayout does not occur when using this function + */ + void setMdiCaptionInactiveForeColor( const QColor &clr ); + + /** + * Sets the background color of inactive MDI childframe window captions + * A relayout does not occur when using this function + */ + void setMdiCaptionInactiveBackColor( const QColor &clr ); + + /** + * Gets all caption colors, consistent with current WM settings + * (or other Desktop settings e.g. system settings for win32) + * This method is useful not only for KMDI child windows. + * Colors are returned via activeBG, activeFG, inactiveBG, inactiveFG references. + * + * @deprecated Use KGlobalSettings::activeTitleColor(), KGlobalSettings::activeTextColor(), + * KGlobalSettings::inactiveTitleColor() and KGlobalSettings::inactiveTextColor() instead. + */ + static void getCaptionColors( const QPalette &pal, QColor &activeBG, QColor &activeFG, + QColor &inactiveBG, QColor &inactiveFG ) KDE_DEPRECATED; + +public slots: + /** + * Cascades all windows resizing them to the minimum size. + */ + void cascadeWindows(); + + /** + * Cascades all windows resizing them to the maximum available size. + */ + void cascadeMaximized(); + + /** + * Maximize all windows but only in vertical direction + */ + void expandVertical(); + + /** + * Maximize all windows but only in horizontal direction + */ + void expandHorizontal(); + + /** + * Gives focus to the topmost child if it doesn't get focus + * automatically or you want to wait to give it focus + */ + void focusTopChild(); + + /** + * Tile Pragma + */ + void tilePragma(); + + /** + * Tile Anodine + */ + void tileAnodine(); + + /** + * Tile all the windows in the child area vertically + */ + void tileVertically(); + + /** + * Position and layout the minimized child frames + */ + void layoutMinimizedChildren(); + +protected: + + /** + * Internally used for the tile algorithm + */ + void tileAllInternal( int maxWnds ); + + /** + * Automatically resizes a maximized MDI view and layouts the positions of minimized MDI views. + */ + virtual void resizeEvent( QResizeEvent * ); + + /** + * Shows the 'Window' popup menu on right mouse button click + */ + void mousePressEvent( QMouseEvent *e ); + + /** + * Internally used. Actions that are necessary when an MDI view gets minimized + */ + void childMinimized( KMdiChildFrm *lpC, bool bWasMaximized ); + +signals: + /** + * Signals that there aren't maximized child frames any more + */ + void noMaximizedChildFrmLeft( KMdiChildFrm* ); + + /** + * Signals that the child frames are maximized now + */ + void nowMaximized( bool ); + + /** + * Signals a KMdiMainFrm that the signal/slot connections of the system buttons in the + * menubar (only in Maximize mode) must be updated to another MDI view because the focused + * MDI view has changed + * @internal + */ + void sysButtonConnectionsMustChange( KMdiChildFrm*, KMdiChildFrm* ); + + /** + * Signals a KMdiMainFrm that the 'Window' popup menu must be shown + * @internal + */ + void popupWindowMenu( QPoint ); + + /** + * Signals that the last attached (docked) MDI view has been closed. + * Note: Detached MDI views can remain. + */ + void lastChildFrmClosed(); + +private: + + KMdiChildAreaPrivate *d; +}; + +#endif // _KMDICHILDAREA_H_ + +// kate: indent-mode csands; tab-width 4; auto-insert-doxygen on; diff --git a/kmdi/kmdichildfrm.cpp b/kmdi/kmdichildfrm.cpp new file mode 100644 index 000000000..da5470410 --- /dev/null +++ b/kmdi/kmdichildfrm.cpp @@ -0,0 +1,1409 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrm.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// : 01/2003 by Jens Zurheide to allow switching +// between views based on timestamps +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#include "kmdichildfrm.h" +#include "kmdichildfrm.moc" + +#include "kmdidefines.h" +#include "kmdichildfrmcaption.h" +#include "kmdichildarea.h" +#include "kmdimainfrm.h" + +#include <qpainter.h> +#include <qapplication.h> +#include <qcursor.h> +#include <qobjectlist.h> +#include <qframe.h> +#include <qpopupmenu.h> +#include <qtoolbutton.h> +#include <qnamespace.h> +#include <qimage.h> + +#include <klocale.h> +#include <kiconloader.h> + +////////////////////////////////////////////////////////////////////////////// +// KMdiChildFrm +////////////////////////////////////////////////////////////////////////////// + +#define KMDI_NORESIZE 0 +#define KMDI_RESIZE_TOP 1 +#define KMDI_RESIZE_LEFT 2 +#define KMDI_RESIZE_RIGHT 4 +#define KMDI_RESIZE_BOTTOM 8 +#define KMDI_RESIZE_TOPLEFT (1|2) +#define KMDI_RESIZE_TOPRIGHT (1|4) +#define KMDI_RESIZE_BOTTOMLEFT (8|2) +#define KMDI_RESIZE_BOTTOMRIGHT (8|4) + +#include "filenew.xpm" +#include "win_closebutton.xpm" +#include "win_minbutton.xpm" +#include "win_maxbutton.xpm" +#include "win_restorebutton.xpm" +#include "win_undockbutton.xpm" +#include "kde_closebutton.xpm" +#include "kde_minbutton.xpm" +#include "kde_maxbutton.xpm" +#include "kde_restorebutton.xpm" +#include "kde_undockbutton.xpm" +#include "kde2_closebutton.xpm" +#include "kde2_minbutton.xpm" +#include "kde2_maxbutton.xpm" +#include "kde2_restorebutton.xpm" +#include "kde2_undockbutton.xpm" +#include "kde2laptop_closebutton.xpm" +#include "kde2laptop_minbutton.xpm" +#include "kde2laptop_maxbutton.xpm" +#include "kde2laptop_restorebutton.xpm" +#include "kde2laptop_undockbutton.xpm" + + +KMdiWin32IconButton::KMdiWin32IconButton( QWidget* parent, const char* name ) + : QLabel( parent, name ) +{} + +//============ mousePressEvent ============// + +void KMdiWin32IconButton::mousePressEvent( QMouseEvent* ) +{ + //emit pressed(); +} + +//============ KMdiChildFrm ============// + +KMdiChildFrm::KMdiChildFrm( KMdiChildArea *parent ) + : QFrame( parent, "kmdi_childfrm" ) + , m_pClient( 0L ) + , m_pManager( 0L ) + , m_pCaption( 0L ) + , m_pWinIcon( 0L ) + , m_pUnixIcon( 0L ) + , m_pMinimize( 0L ) + , m_pMaximize( 0L ) + , m_pClose( 0L ) + , m_pUndock( 0L ) + , m_state( Normal ) + , m_restoredRect() + , m_iResizeCorner( KMDI_NORESIZE ) + , m_iLastCursorCorner( KMDI_NORESIZE ) + , m_bResizing( false ) + , m_bDragging( false ) + , m_pIconButtonPixmap( 0L ) + , m_pMinButtonPixmap( 0L ) + , m_pMaxButtonPixmap( 0L ) + , m_pRestoreButtonPixmap( 0L ) + , m_pCloseButtonPixmap( 0L ) + , m_pUndockButtonPixmap( 0L ) + , m_windowMenuID( 0 ) + , m_pSystemMenu( 0L ) + , m_oldClientMinSize() + , m_oldClientMaxSize() + , m_oldLayoutResizeMode( QLayout::Minimum ) +{ + m_pCaption = new KMdiChildFrmCaption( this ); + + m_pManager = parent; + + m_pWinIcon = new KMdiWin32IconButton( m_pCaption, "kmdi_iconbutton_icon" ); + m_pUnixIcon = new QToolButton( m_pCaption, "kmdi_toolbutton_icon" ); + m_pMinimize = new QToolButton( m_pCaption, "kmdi_toolbutton_min" ); + m_pMaximize = new QToolButton( m_pCaption, "kmdi_toolbutton_max" ); + m_pClose = new QToolButton( m_pCaption, "kmdi_toolbutton_close" ); + m_pUndock = new QToolButton( m_pCaption, "kmdi_toolbutton_undock" ); + + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + QObject::connect( m_pMaximize, SIGNAL( clicked() ), this, SLOT( maximizePressed() ) ); + QObject::connect( m_pClose, SIGNAL( clicked() ), this, SLOT( closePressed() ) ); + QObject::connect( m_pUndock, SIGNAL( clicked() ), this, SLOT( undockPressed() ) ); + + m_pIconButtonPixmap = new QPixmap( SmallIcon( "filenew" ) ); + if ( m_pIconButtonPixmap->isNull() ) + * m_pIconButtonPixmap = QPixmap( filenew ); + + redecorateButtons(); + + m_pWinIcon->setFocusPolicy( NoFocus ); + m_pUnixIcon->setFocusPolicy( NoFocus ); + m_pClose->setFocusPolicy( NoFocus ); + m_pMinimize->setFocusPolicy( NoFocus ); + m_pMaximize->setFocusPolicy( NoFocus ); + m_pUndock->setFocusPolicy( NoFocus ); + + setFrameStyle( QFrame::WinPanel | QFrame::Raised ); + setFocusPolicy( NoFocus ); + + setMouseTracking( true ); + + setMinimumSize( KMDI_CHILDFRM_MIN_WIDTH, m_pCaption->heightHint() ); + + m_pSystemMenu = new QPopupMenu(); +} + +//============ ~KMdiChildFrm ============// + +KMdiChildFrm::~KMdiChildFrm() +{ + delete m_pMinButtonPixmap; + delete m_pMaxButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + delete m_pUndockButtonPixmap; + delete m_pSystemMenu; + delete m_pIconButtonPixmap; +} + +//============ mousePressEvent =============// +void KMdiChildFrm::mousePressEvent( QMouseEvent *e ) +{ + if ( m_bResizing ) + { + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + + m_bResizing = false; + releaseMouse(); + } + + m_pCaption->setActive( true ); + m_pManager->setTopChild( this, false ); + + m_iResizeCorner = getResizeCorner( e->pos().x(), e->pos().y() ); + if ( m_iResizeCorner != KMDI_NORESIZE ) + { + m_bResizing = true; + //notify child view + KMdiChildFrmResizeBeginEvent ue( e ); + if ( m_pClient != 0L ) + QApplication::sendEvent( m_pClient, &ue ); + } +} + +//============ mouseReleaseEvent ==============// + +void KMdiChildFrm::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( m_bResizing ) + { + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + + m_bResizing = false; + //notify child view + KMdiChildFrmResizeEndEvent ue( e ); + if ( m_pClient != 0L ) + QApplication::sendEvent( m_pClient, &ue ); + } +} + +//============= setResizeCursor ===============// + +void KMdiChildFrm::setResizeCursor( int resizeCorner ) +{ + if ( resizeCorner == m_iLastCursorCorner ) + return ; //Don't do it twice + + m_iLastCursorCorner = resizeCorner; + switch ( resizeCorner ) + { + case KMDI_NORESIZE: + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + break; + case KMDI_RESIZE_LEFT: + case KMDI_RESIZE_RIGHT: + QApplication::setOverrideCursor( Qt::sizeHorCursor, true ); + break; + case KMDI_RESIZE_TOP: + case KMDI_RESIZE_BOTTOM: + QApplication::setOverrideCursor( Qt::sizeVerCursor, true ); + break; + case KMDI_RESIZE_TOPLEFT: + case KMDI_RESIZE_BOTTOMRIGHT: + QApplication::setOverrideCursor( Qt::sizeFDiagCursor, true ); + break; + case KMDI_RESIZE_BOTTOMLEFT: + case KMDI_RESIZE_TOPRIGHT: + QApplication::setOverrideCursor( Qt::sizeBDiagCursor, true ); + break; + } +} + +//============= unsetResizeCursor ===============// + +void KMdiChildFrm::unsetResizeCursor() +{ + if ( !m_bResizing && m_iResizeCorner != KMDI_NORESIZE ) + { + m_iResizeCorner = KMDI_NORESIZE; + m_iLastCursorCorner = KMDI_NORESIZE; + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + } +} + +//============= mouseMoveEvent ===============// + +void KMdiChildFrm::mouseMoveEvent( QMouseEvent *e ) +{ + if ( m_state != Normal ) + return; + + if ( !m_pClient ) + return; + + if ( m_pClient->minimumSize() == m_pClient->maximumSize() ) + return; + + if ( m_bResizing ) + { + if ( !( e->state() & RightButton ) && !( e->state() & MidButton ) ) + { + // same as: if no button or left button pressed + QPoint p = parentWidget()->mapFromGlobal( e->globalPos() ); + resizeWindow( m_iResizeCorner, p.x(), p.y() ); + } + else + m_bResizing = false; + } + else + { + m_iResizeCorner = getResizeCorner( e->pos().x(), e->pos().y() ); + setResizeCursor( m_iResizeCorner ); + } +} + +//============= moveEvent ===============// + +void KMdiChildFrm::moveEvent( QMoveEvent* me ) +{ + // give its child view the chance to notify a childframe move + KMdiChildFrmMoveEvent cfme( me ); + if ( m_pClient != 0L ) + QApplication::sendEvent( m_pClient, &cfme ); +} + +//=============== leaveEvent ===============// + +void KMdiChildFrm::leaveEvent( QEvent * ) +{ + unsetResizeCursor(); +} + +void KMdiChildFrm::resizeWindow( int resizeCorner, int xPos, int yPos ) +{ + QRect resizeRect( x(), y(), width(), height() ); + + // Calculate the minimum width & height + int minWidth = 0; + int minHeight = 0; + int maxWidth = QWIDGETSIZE_MAX; + int maxHeight = QWIDGETSIZE_MAX; + + // it could be the client forces the childframe to enlarge its minimum size + if ( m_pClient ) + { + minWidth = m_pClient->minimumSize().width() + KMDI_CHILDFRM_DOUBLE_BORDER; + minHeight = m_pClient->minimumSize().height() + KMDI_CHILDFRM_DOUBLE_BORDER + + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR; + maxWidth = m_pClient->maximumSize().width() + KMDI_CHILDFRM_DOUBLE_BORDER; + maxHeight = m_pClient->maximumSize().height() + KMDI_CHILDFRM_DOUBLE_BORDER + + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR; + } + + if ( minWidth < minimumWidth() ) + minWidth = minimumWidth(); + + if ( minHeight < minimumHeight() ) + minHeight = minimumHeight(); + + if ( maxWidth > maximumWidth() ) + maxWidth = maximumWidth(); + + if ( maxHeight > maximumHeight() ) + maxHeight = maximumHeight(); + + QPoint mousePos( xPos, yPos ); + + // manipulate width + switch ( resizeCorner ) + { + //left sides + case KMDI_RESIZE_TOPLEFT: + case KMDI_RESIZE_LEFT: + case KMDI_RESIZE_BOTTOMLEFT: + resizeRect.setLeft( mousePos.x() ); + if ( resizeRect.width() < minWidth ) + resizeRect.setLeft( resizeRect.right() - minWidth + 1 ); + if ( resizeRect.width() > maxWidth ) + resizeRect.setLeft( resizeRect.right() - maxWidth + 1 ); + break; + //right sides + case KMDI_RESIZE_TOPRIGHT: + case KMDI_RESIZE_RIGHT: + case KMDI_RESIZE_BOTTOMRIGHT: + resizeRect.setRight( mousePos.x() ); + if ( resizeRect.width() < minWidth ) + resizeRect.setRight( resizeRect.left() + minWidth - 1 ); + if ( resizeRect.width() > maxWidth ) + resizeRect.setRight( resizeRect.left() + maxWidth - 1 ); + break; + default: + break; + } + + // manipulate height + switch ( resizeCorner ) + { + case KMDI_RESIZE_TOPLEFT: + case KMDI_RESIZE_TOP: + case KMDI_RESIZE_TOPRIGHT: + resizeRect.setTop( mousePos.y() ); + if ( resizeRect.height() < minHeight ) + resizeRect.setTop( resizeRect.bottom() - minHeight + 1 ); + if ( resizeRect.height() > maxHeight ) + resizeRect.setTop( resizeRect.bottom() - maxHeight + 1 ); + break; + case KMDI_RESIZE_BOTTOMLEFT: + case KMDI_RESIZE_BOTTOM: + case KMDI_RESIZE_BOTTOMRIGHT: + resizeRect.setBottom( mousePos.y() ); + if ( resizeRect.height() < minHeight ) + resizeRect.setBottom( resizeRect.top() + minHeight - 1 ); + if ( resizeRect.height() > maxHeight ) + resizeRect.setBottom( resizeRect.top() + maxHeight - 1 ); + break; + default: + // nothing to do + break; + } + // actually resize + setGeometry( resizeRect ); + + if ( m_state == Maximized ) + { + m_state = Normal; + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + } +} + +//================= getResizeCorner =============// + +int KMdiChildFrm::getResizeCorner( int ax, int ay ) +{ + int ret = KMDI_NORESIZE; + if ( m_pClient->minimumWidth() != m_pClient->maximumWidth() ) + { + if ( ( ax > 0 ) && ( ax < ( KMDI_CHILDFRM_BORDER + 2 ) ) ) + ret |= KMDI_RESIZE_LEFT; + + if ( ( ax < width() ) && ( ax > ( width() - ( KMDI_CHILDFRM_BORDER + 2 ) ) ) ) + ret |= KMDI_RESIZE_RIGHT; + } + if ( m_pClient->minimumHeight() != m_pClient->maximumHeight() ) + { + if ( ( ay > 0 ) && ( ay < ( KMDI_CHILDFRM_BORDER + 2 ) ) ) + ret |= KMDI_RESIZE_TOP; + + if ( ( ay < ( height() ) ) && ( ay > ( height() - ( KMDI_CHILDFRM_BORDER + 2 ) ) ) ) + ret |= KMDI_RESIZE_BOTTOM; + } + return ret; +} + +//============= maximizePressed ============// + +void KMdiChildFrm::maximizePressed() +{ + switch ( m_state ) + { + case Maximized: + emit m_pManager->nowMaximized( false ); + setState( Normal ); + break; + case Normal: + case Minimized: + setState( Maximized ); + emit m_pManager->nowMaximized( true ); + break; + } +} + +void KMdiChildFrm::restorePressed() +{ + if ( m_state == Normal ) + return ; + + if ( m_state == Maximized ) + emit m_pManager->nowMaximized( false ); + + setState( Normal ); +} + +//============= minimizePressed ============// + +void KMdiChildFrm::minimizePressed() +{ + switch ( m_state ) + { + case Minimized: + setState( Normal ); + break; + case Normal: + setState( Minimized ); + break; + case Maximized: + emit m_pManager->nowMaximized( false ); + setState( Normal ); + setState( Minimized ); + break; + } +} + +//============= closePressed ============// + +void KMdiChildFrm::closePressed() +{ + if ( m_pClient ) + m_pClient->close(); +} + +//============= undockPressed ============// + +void KMdiChildFrm::undockPressed() +{ + if ( m_pClient ) + { + if ( m_state == Minimized ) + setState( Normal ); + m_pClient->detach(); + } +} + +//============ setState =================// + +void KMdiChildFrm::setState( MdiWindowState state, bool /*bAnimate*/ ) +{ + if ( m_state == Normal ) //save the current rect + m_restoredRect = QRect( x(), y(), width(), height() ); + + switch ( state ) + { + case Normal: + switch ( m_state ) + { + case Maximized: + m_pClient->m_stateChanged = true; + m_state = state; + // client min / max size / layout behavior don't change + // set frame max size indirectly by setting the clients max size to + // it's current value (calls setMaxSize() of frame) + m_pClient->setMaximumSize( m_pClient->maximumSize().width(), m_pClient->maximumSize().height() ); + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + setGeometry( m_restoredRect ); + break; + case Minimized: + m_pClient->m_stateChanged = true; + m_state = state; + // restore client min / max size / layout behavior + m_pClient->setMinimumSize( m_oldClientMinSize.width(), m_oldClientMinSize.height() ); + m_pClient->setMaximumSize( m_oldClientMaxSize.width(), m_oldClientMaxSize.height() ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( m_oldLayoutResizeMode ); + } + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( restorePressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + setGeometry( m_restoredRect ); + break; + case Normal: + break; + } + break; + case Maximized: + switch ( m_state ) + { + case Minimized: + { + m_pClient->m_stateChanged = true; + m_state = state; + // restore client min / max size / layout behavior + m_pClient->setMinimumSize( m_oldClientMinSize.width(), m_oldClientMinSize.height() ); + m_pClient->setMaximumSize( m_oldClientMaxSize.width(), m_oldClientMaxSize.height() ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( m_oldLayoutResizeMode ); + } + setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + // reset to maximize-captionbar + m_pMaximize->setPixmap( *m_pRestoreButtonPixmap ); + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( restorePressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + int nFrameWidth = KMDI_CHILDFRM_DOUBLE_BORDER; + int nFrameHeight = KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + + m_pCaption->heightHint(); + setGeometry( -m_pClient->x(), -m_pClient->y(), + m_pManager->width() + nFrameWidth, + m_pManager->height() + nFrameHeight ); + raise(); + } + break; + case Normal: + { + m_pClient->m_stateChanged = true; + m_state = state; + // client min / max size / layout behavior don't change + setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + m_pMaximize->setPixmap( *m_pRestoreButtonPixmap ); + int nFrameWidth = KMDI_CHILDFRM_DOUBLE_BORDER; + int nFrameHeight = KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + + m_pCaption->heightHint(); + QRect maximizedFrmRect( -m_pClient->x(), -m_pClient->y(), + m_pManager->width() + nFrameWidth, + m_pManager->height() + nFrameHeight ); + if ( geometry() != maximizedFrmRect ) + { + setGeometry( maximizedFrmRect ); + } + raise(); + } + break; + case Maximized: + break; + } + break; + case Minimized: + switch ( m_state ) + { + case Maximized: + m_pClient->m_stateChanged = true; + m_state = state; + // save client min / max size / layout behavior + m_oldClientMinSize = m_pClient->minimumSize(); + m_oldClientMaxSize = m_pClient->maximumSize(); + if ( m_pClient->layout() != 0L ) + { + m_oldLayoutResizeMode = m_pClient->layout() ->resizeMode(); + } + m_pClient->setMinimumSize( 0, 0 ); + m_pClient->setMaximumSize( 0, 0 ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( QLayout::FreeResize ); + } + switchToMinimizeLayout(); + m_pManager->childMinimized( this, true ); + break; + case Normal: + m_pClient->m_stateChanged = true; + m_state = state; + // save client min / max size / layout behavior + m_oldClientMinSize = m_pClient->minimumSize(); + m_oldClientMaxSize = m_pClient->maximumSize(); + if ( m_pClient->layout() != 0L ) + { + m_oldLayoutResizeMode = m_pClient->layout() ->resizeMode(); + } + m_restoredRect = geometry(); + m_pClient->setMinimumSize( 0, 0 ); + m_pClient->setMaximumSize( 0, 0 ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( QLayout::FreeResize ); + } + switchToMinimizeLayout(); + m_pManager->childMinimized( this, false ); + break; + case Minimized: + break; + } + break; + } + + KMdiChildFrm* pTopFrame = m_pManager->topChild(); + KMdiChildView* pTopChild = 0L; + if ( pTopFrame != 0L ) + { + pTopChild = pTopFrame->m_pClient; + } + if ( ( pTopChild != 0L ) && pTopChild->isMaximized() ) + { + m_pManager->setMinimumSize( pTopChild->minimumWidth(), pTopChild->minimumHeight() ); + /// @todo: setting the maximum size doesn't work properly - fix this later + /// m_pManager->setMaximumSize(pTopChild->maximumWidth(), pTopChild->maximumHeight()); + } + else + { + m_pManager->setMinimumSize( 0, 0 ); + m_pManager->setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + } +} + +//============== restoreGeometry ================// + +QRect KMdiChildFrm::restoreGeometry() const +{ + return m_restoredRect; +} + +//============== setRestoreGeometry ================// + +void KMdiChildFrm::setRestoreGeometry( const QRect& newRestGeo ) +{ + m_restoredRect = newRestGeo; +} + +//============ setCaption ===============// + +void KMdiChildFrm::setCaption( const QString& text ) +{ + m_pCaption->setCaption( text ); +} + +//============ enableClose ==============// + +void KMdiChildFrm::enableClose( bool bEnable ) +{ + m_pClose->setEnabled( bEnable ); + m_pClose->repaint( false ); +} + +//============ setIcon ==================// + +void KMdiChildFrm::setIcon( const QPixmap& pxm ) +{ + QPixmap p = pxm; + if ( p.width() != 18 || p.height() != 18 ) + { + QImage img = p.convertToImage(); + p = img.smoothScale( 18, 18, QImage::ScaleMin ); + } + const bool do_resize = m_pIconButtonPixmap->size() != p.size(); + *m_pIconButtonPixmap = p; + m_pWinIcon->setPixmap( p ); + m_pUnixIcon->setPixmap( p ); + if ( do_resize ) + doResize( true ); +} + +//============ icon =================// + +QPixmap* KMdiChildFrm::icon() const +{ + return m_pIconButtonPixmap; +} + +//============ setClient ============// +void KMdiChildFrm::setClient( KMdiChildView *w, bool bAutomaticResize ) +{ + m_pClient = w; + + if ( w->icon() ) + setIcon( *( w->icon() ) ); + + //resize to match the client + int clientYPos = m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_BORDER; + if ( bAutomaticResize || w->size().isEmpty() || ( w->size() == QSize( 1, 1 ) ) ) + { + if ( m_pManager->topChild() ) + { + resize( m_pManager->topChild() ->size() ); + } + else + { + resize( m_pManager->m_defaultChildFrmSize.width() + KMDI_CHILDFRM_DOUBLE_BORDER, + m_pManager->m_defaultChildFrmSize.height() + KMDI_CHILDFRM_BORDER + clientYPos ); + } + } + else + { + resize( w->width() + KMDI_CHILDFRM_DOUBLE_BORDER, w->height() + KMDI_CHILDFRM_BORDER + clientYPos ); + } + + // memorize the focuses in a dictionary because they will get lost during reparenting + QDict<FocusPolicy>* pFocPolDict = new QDict<FocusPolicy>; + pFocPolDict->setAutoDelete( true ); + QObjectList *list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over the buttons + QObject * obj; + int i = 1; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + ++it; + QWidget* widg = ( QWidget* ) obj; + if ( widg->name( 0 ) == 0 ) + { + QString tmpStr; + tmpStr.setNum( i ); + tmpStr = "unnamed" + tmpStr; + widg->setName( tmpStr.latin1() ); + i++; + } + FocusPolicy* pFocPol = new FocusPolicy; + *pFocPol = widg->focusPolicy(); + pFocPolDict->insert( widg->name(), pFocPol ); + } + delete list; // delete the list, not the objects + + //Reparent if needed + if ( w->parent() != this ) + { + //reparent to this widget , no flags , point , show it + QPoint pnt2( KMDI_CHILDFRM_BORDER, clientYPos ); + QSize mincs = w->minimumSize(); + QSize maxcs = w->maximumSize(); + w->setMinimumSize( 0, 0 ); + w->setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + + // min/max sizes, flags, DND get lost. :-( + w->reparent( this, 0, pnt2, w->isVisible() ); + + w->setMinimumSize( mincs.width(), mincs.height() ); + w->setMaximumSize( maxcs.width(), maxcs.height() ); + } + else + w->move( KMDI_CHILDFRM_BORDER, clientYPos ); + + linkChildren( pFocPolDict ); + + QObject::connect( m_pClient, SIGNAL( mdiParentNowMaximized( bool ) ), m_pManager, SIGNAL( nowMaximized( bool ) ) ); + + if ( m_pClient->minimumWidth() > m_pManager->m_defaultChildFrmSize.width() ) + setMinimumWidth( m_pClient->minimumSize().width() + KMDI_CHILDFRM_DOUBLE_BORDER ); + + if ( m_pClient->minimumHeight() > m_pManager->m_defaultChildFrmSize.height() ) + { + setMinimumHeight( m_pClient->minimumSize().height() + KMDI_CHILDFRM_DOUBLE_BORDER + + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR ); + } +} + +//============ unsetClient ============// + +void KMdiChildFrm::unsetClient( QPoint positionOffset ) +{ + if ( !m_pClient ) + return ; + + QObject::disconnect( m_pClient, SIGNAL( mdiParentNowMaximized( bool ) ), m_pManager, SIGNAL( nowMaximized( bool ) ) ); + + //reparent to desktop widget , no flags , point , show it + QDict<FocusPolicy>* pFocPolDict; + pFocPolDict = unlinkChildren(); + + // get name of focused child widget + QWidget* focusedChildWidget = m_pClient->focusedChildWidget(); + const char* nameOfFocusedWidget = ""; + if ( focusedChildWidget != 0 ) + nameOfFocusedWidget = focusedChildWidget->name(); + + QSize mins = m_pClient->minimumSize(); + QSize maxs = m_pClient->maximumSize(); + m_pClient->reparent( 0, 0, mapToGlobal( pos() ) - pos() + positionOffset, isVisible() ); + m_pClient->setMinimumSize( mins.width(), mins.height() ); + m_pClient->setMaximumSize( maxs.width(), maxs.height() ); + + // remember the focus policies using the dictionary and reset them + QObjectList *list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets of child frame + QObject * obj; + QWidget* firstFocusableChildWidget = 0; + QWidget* lastFocusableChildWidget = 0; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) obj; + ++it; + FocusPolicy* pFocPol = pFocPolDict->find( widg->name() ); // remember the focus policy from before the reparent + if ( pFocPol ) + widg->setFocusPolicy( *pFocPol ); + + // reset focus to old position (doesn't work :-( for its own unexplicable reasons) + if ( widg->name() == nameOfFocusedWidget ) + widg->setFocus(); + + // get first and last focusable widget + if ( ( widg->focusPolicy() == QWidget::StrongFocus ) || ( widg->focusPolicy() == QWidget::TabFocus ) ) + { + if ( firstFocusableChildWidget == 0 ) + firstFocusableChildWidget = widg; // first widget + lastFocusableChildWidget = widg; // last widget + + } + else + { + if ( widg->focusPolicy() == QWidget::WheelFocus ) + { + if ( firstFocusableChildWidget == 0 ) + firstFocusableChildWidget = widg; // first widget + lastFocusableChildWidget = widg; // last widget + //qDebug("*** %s (%s)",widg->name(),widg->className()); + } + } + } + delete list; // delete the list, not the objects + delete pFocPolDict; + + // reset first and last focusable widget + m_pClient->setFirstFocusableChildWidget( firstFocusableChildWidget ); + m_pClient->setLastFocusableChildWidget( lastFocusableChildWidget ); + + // reset the focus policy of the view + m_pClient->setFocusPolicy( QWidget::ClickFocus ); + + // lose information about the view (because it's undocked now) + m_pClient = 0; +} + +//============== linkChildren =============// +void KMdiChildFrm::linkChildren( QDict<FocusPolicy>* pFocPolDict ) +{ + // reset the focus policies for all widgets in the view (take them from the dictionary) + QObjectList* list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets of child frame + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget* widg = ( QWidget* ) obj; + ++it; + FocusPolicy* pFocPol = pFocPolDict->find( widg->name() ); // remember the focus policy from before the reparent + + if ( pFocPol != 0 ) + widg->setFocusPolicy( *pFocPol ); + + if ( !( widg->inherits( "QPopupMenu" ) ) ) + widg->installEventFilter( this ); + + } + delete list; // delete the list, not the objects + delete pFocPolDict; + + // reset the focus policies for the rest + m_pWinIcon->setFocusPolicy( QWidget::NoFocus ); + m_pUnixIcon->setFocusPolicy( QWidget::NoFocus ); + m_pClient->setFocusPolicy( QWidget::ClickFocus ); + m_pCaption->setFocusPolicy( QWidget::NoFocus ); + m_pUndock->setFocusPolicy( QWidget::NoFocus ); + m_pMinimize->setFocusPolicy( QWidget::NoFocus ); + m_pMaximize->setFocusPolicy( QWidget::NoFocus ); + m_pClose->setFocusPolicy( QWidget::NoFocus ); + + // install the event filter (catch mouse clicks) for the rest + m_pWinIcon->installEventFilter( this ); + m_pUnixIcon->installEventFilter( this ); + m_pCaption->installEventFilter( this ); + m_pUndock->installEventFilter( this ); + m_pMinimize->installEventFilter( this ); + m_pMaximize->installEventFilter( this ); + m_pClose->installEventFilter( this ); + m_pClient->installEventFilter( this ); + // m_pClient->installEventFilterForAllChildren(); +} + +//============== unlinkChildren =============// + +QDict<QWidget::FocusPolicy>* KMdiChildFrm::unlinkChildren() +{ + // memorize the focuses in a dictionary because they will get lost during reparenting + QDict<FocusPolicy>* pFocPolDict = new QDict<FocusPolicy>; + pFocPolDict->setAutoDelete( true ); + + QObjectList *list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets of child frame + QObject * obj; + int i = 1; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + ++it; + QWidget* w = ( QWidget* ) obj; + // get current widget object name + if ( w->name( 0 ) == 0 ) + { + QString tmpStr; + tmpStr.setNum( i ); + tmpStr = "unnamed" + tmpStr; + w->setName( tmpStr.latin1() ); + i++; + } + FocusPolicy* pFocPol = new FocusPolicy; + *pFocPol = w->focusPolicy(); + // memorize focus policy + pFocPolDict->insert( w->name(), pFocPol ); + // remove event filter + ( ( QWidget* ) obj ) ->removeEventFilter( this ); + } + delete list; // delete the list, not the objects + + // remove the event filter (catch mouse clicks) for the rest + m_pWinIcon->removeEventFilter( this ); + m_pUnixIcon->removeEventFilter( this ); + m_pCaption->removeEventFilter( this ); + m_pUndock->removeEventFilter( this ); + m_pMinimize->removeEventFilter( this ); + m_pMaximize->removeEventFilter( this ); + m_pClose->removeEventFilter( this ); + m_pClient->removeEventFilter( this ); + + //SCHEDULED_FOR_REMOVE m_pClient->removeEventFilterForAllChildren(); + + return pFocPolDict; +} + +//============== resizeEvent ===============// + +void KMdiChildFrm::resizeEvent( QResizeEvent * ) +{ + doResize(); // an extra method because it can also called directly +} + +void KMdiChildFrm::doResize() +{ + doResize( false ); +} + +void KMdiChildFrm::doResize( bool captionOnly ) +{ + //Resize the caption + int captionHeight = m_pCaption->heightHint(); + int captionWidth = width() - KMDI_CHILDFRM_DOUBLE_BORDER; + int buttonHeight = m_pClose->pixmap() ->height(); + int buttonWidth = m_pClose->pixmap() ->width(); + int heightOffset = captionHeight / 2 - buttonHeight / 2; + int rightOffset1 = 1; + int rightOffset2 = 1; + int frmIconHeight = m_pWinIcon->pixmap() ->height(); + int frmIconWidth = m_pWinIcon->pixmap() ->width(); + int frmIconOffset = 1; + QWidget* pIconWidget = m_pWinIcon; + m_pCaption->setGeometry( KMDI_CHILDFRM_BORDER, KMDI_CHILDFRM_BORDER, captionWidth, captionHeight ); + + //The buttons are caption children + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + rightOffset2 += 2; + m_pUnixIcon->hide(); + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + buttonWidth += 4; + buttonHeight += 4; + heightOffset -= 2; + rightOffset1 = 0; + rightOffset2 = 0; + m_pWinIcon->hide(); + frmIconHeight = buttonHeight; + frmIconWidth = buttonWidth; + frmIconOffset = 0; + pIconWidget = m_pUnixIcon; + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + { + buttonWidth += 3; + buttonHeight += 3; + heightOffset -= 1; + m_pUnixIcon->hide(); + } + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::KDELaptopLook ) + { + pIconWidget->setGeometry( frmIconOffset, captionHeight / 2 - frmIconHeight / 2, frmIconWidth, frmIconHeight ); + m_pClose->setGeometry( ( captionWidth - buttonWidth ) - rightOffset1, heightOffset, buttonWidth, buttonHeight ); + m_pMaximize->setGeometry( ( captionWidth - ( buttonWidth * 2 ) ) - rightOffset2, heightOffset, buttonWidth, buttonHeight ); + m_pMinimize->setGeometry( ( captionWidth - ( buttonWidth * 3 ) ) - rightOffset2, heightOffset, buttonWidth, buttonHeight ); + m_pUndock->setGeometry( ( captionWidth - ( buttonWidth * 4 ) ) - rightOffset2, heightOffset, buttonWidth, buttonHeight ); + } + else + { // KDELaptopLook + m_pWinIcon->hide(); + m_pUnixIcon->hide(); + buttonHeight += 5; + heightOffset -= 2; + m_pClose->setGeometry ( 0, heightOffset, 27, buttonHeight ); + m_pMaximize->setGeometry( captionWidth - 27, heightOffset, 27, buttonHeight ); + m_pMinimize->setGeometry( captionWidth - 27 * 2, heightOffset, 27, buttonHeight ); + m_pUndock->setGeometry ( captionWidth - 27 * 3, heightOffset, 27, buttonHeight ); + } + + //Resize the client + if ( !captionOnly && m_pClient ) + { + QSize newClientSize( captionWidth, + height() - ( KMDI_CHILDFRM_DOUBLE_BORDER + captionHeight + KMDI_CHILDFRM_SEPARATOR ) ); + if ( newClientSize != m_pClient->size() ) + { + m_pClient->setGeometry( KMDI_CHILDFRM_BORDER, + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_BORDER, + newClientSize.width(), newClientSize.height() ); + } + } +} + +static bool hasParent( QObject* par, QObject* o ) +{ + while ( o && o != par ) + o = o->parent(); + return o == par; +} + +//============= eventFilter ===============// + +bool KMdiChildFrm::eventFilter( QObject *obj, QEvent *e ) +{ + switch ( e->type() ) + { + case QEvent::Enter: + { + // check if the receiver is really a child of this frame + bool bIsChild = false; + QObject* pObj = obj; + while ( ( pObj != 0L ) && !bIsChild ) + { + bIsChild = ( pObj == this ); + pObj = pObj->parent(); + } + // unset the resize cursor if the cursor moved from the frame into a inner widget + if ( bIsChild ) + unsetResizeCursor(); + } + break; + case QEvent::MouseButtonPress: + { + if ( !hasParent( m_pClient, obj ) ) + { + bool bIsSecondClick = false; + if ( m_timeMeasure.elapsed() <= QApplication::doubleClickInterval() ) + bIsSecondClick = true; // of a possible double click + + if ( !( ( ( obj == m_pWinIcon ) || ( obj == m_pUnixIcon ) ) && bIsSecondClick ) ) + { + // in case we didn't click on the icon button + QFocusEvent focusEvent( QFocusEvent::FocusIn ); + QApplication::sendEvent( qApp->mainWidget(), &focusEvent ); + if ( m_pClient ) + { + m_pClient->updateTimeStamp(); + m_pClient->activate(); + } + + if ( ( obj->parent() != m_pCaption ) && ( obj != m_pCaption ) ) + { + QWidget* w = ( QWidget* ) obj; + if ( ( w->focusPolicy() == QWidget::ClickFocus ) || ( w->focusPolicy() == QWidget::StrongFocus ) ) + { + w->setFocus(); + } + } + } + if ( ( obj == m_pWinIcon ) || ( obj == m_pUnixIcon ) ) + { + // in case we clicked on the icon button + if ( m_timeMeasure.elapsed() > QApplication::doubleClickInterval() ) + { + showSystemMenu(); + m_timeMeasure.start(); + } + else + closePressed(); // double click on icon button closes the view + + return true; + } + } + } + break; + case QEvent::Resize: + { + if ( ( ( QWidget* ) obj == m_pClient ) && ( m_state == Normal ) ) + { + QResizeEvent* re = ( QResizeEvent* ) e; + int captionHeight = m_pCaption->heightHint(); + QSize newChildFrmSize( re->size().width() + KMDI_CHILDFRM_DOUBLE_BORDER, + re->size().height() + captionHeight + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER ); + if ( newChildFrmSize != size() ) + resize( newChildFrmSize ); + } + } + break; + case QEvent::ChildRemoved: + { + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + QObject* pLostChild = ( ( QChildEvent* ) e )->child(); + if ( ( pLostChild != 0L ) /*&& (pLostChild->inherits("QWidget"))*/ ) + { + QObjectList* list = pLostChild->queryList(); + list->insert( 0, pLostChild ); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget* widg = ( QWidget* ) obj; + ++it; + widg->removeEventFilter( this ); + } + delete list; // delete the list, not the objects + } + } + break; + case QEvent::ChildInserted: + { + // if we got a new child we install ourself as event filter for the new + // child and its children (as we did when we got our client). + // XXX see linkChildren() and focus policy stuff + QObject* pNewChild = ( ( QChildEvent* ) e ) ->child(); + if ( ( pNewChild != 0L ) && ::qt_cast<QWidget*>( pNewChild ) ) + { + QWidget * pNewWidget = static_cast<QWidget*>( pNewChild ); + QObjectList *list = pNewWidget->queryList( "QWidget" ); + list->insert( 0, pNewChild ); // add the new child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all new child widgets + QObject * obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) obj; + ++it; + if ( !::qt_cast<QPopupMenu*>( widg ) ) + { + widg->installEventFilter( this ); + } + } + delete list; // delete the list, not the objects + } + } + break; + default: + break; + } + + return false; // standard event processing (see Qt documentation) +} + +//============= raiseAndActivate ===============// + +void KMdiChildFrm::raiseAndActivate() +{ + m_pCaption->setActive( true ); + m_pManager->setTopChild( this, false ); //Do not focus by now... +} + +//============= setMinimumSize ===============// + +void KMdiChildFrm::setMinimumSize ( int minw, int minh ) +{ + QWidget::setMinimumSize( minw, minh ); + if ( m_state == Maximized ) + { + m_pManager->setMinimumSize( minw, minh ); + } +} + +//============= systemMenu ===============// + +QPopupMenu* KMdiChildFrm::systemMenu() const +{ + if ( m_pSystemMenu == 0 ) + return 0; + + m_pSystemMenu->clear(); + + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + { + m_pSystemMenu->insertItem( i18n( "&Restore" ), this, SLOT( restorePressed() ) ); + m_pSystemMenu->insertItem( i18n( "&Move" ), m_pCaption, SLOT( slot_moveViaSystemMenu() ) ); + m_pSystemMenu->insertItem( i18n( "R&esize" ), this, SLOT( slot_resizeViaSystemMenu() ) ); + m_pSystemMenu->insertItem( i18n( "M&inimize" ), this, SLOT( minimizePressed() ) ); + m_pSystemMenu->insertItem( i18n( "M&aximize" ), this, SLOT( maximizePressed() ) ); + if ( state() == Normal ) + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 0 ), false ); + else if ( state() == Maximized ) + { + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 1 ), false ); + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 2 ), false ); + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 4 ), false ); + } + else if ( state() == Minimized ) + { + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 2 ), false ); + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 3 ), false ); + } + } + else + { + if ( state() != Normal ) + m_pSystemMenu->insertItem( i18n( "&Restore" ), this, SLOT( restorePressed() ) ); + if ( state() != Maximized ) + m_pSystemMenu->insertItem( i18n( "&Maximize" ), this, SLOT( maximizePressed() ) ); + if ( state() != Minimized ) + m_pSystemMenu->insertItem( i18n( "&Minimize" ), this, SLOT( minimizePressed() ) ); + if ( state() != Maximized ) + m_pSystemMenu->insertItem( i18n( "M&ove" ), m_pCaption, SLOT( slot_moveViaSystemMenu() ) ); + if ( state() == Normal ) + m_pSystemMenu->insertItem( i18n( "&Resize" ), this, SLOT( slot_resizeViaSystemMenu() ) ); + } + + m_pSystemMenu->insertItem( i18n( "&Undock" ), this, SLOT( undockPressed() ) ); + m_pSystemMenu->insertSeparator(); + m_pSystemMenu->insertItem( i18n( "&Close" ), this, SLOT( closePressed() ) ); + + return m_pSystemMenu; +} + +/** Shows a system menu for child frame windows. */ +void KMdiChildFrm::showSystemMenu() +{ + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + m_pUnixIcon->setDown( false ); + + QPoint popupmenuPosition; + + QRect iconGeom; + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + iconGeom = m_pWinIcon->geometry(); + else + iconGeom = m_pUnixIcon->geometry(); + + popupmenuPosition = QPoint( iconGeom.x(), iconGeom.y() + captionHeight() + KMDI_CHILDFRM_BORDER ); + systemMenu() ->popup( mapToGlobal( popupmenuPosition ) ); +} + +void KMdiChildFrm::switchToMinimizeLayout() +{ + setMinimumWidth( KMDI_CHILDFRM_MIN_WIDTH ); + setFixedHeight( m_pCaption->height() + KMDI_CHILDFRM_DOUBLE_BORDER ); + + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + + // temporary use of minimize button for restore function + m_pMinimize->setPixmap( *m_pRestoreButtonPixmap ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( restorePressed() ) ); + + // resizing + resize( 300, minimumHeight() ); + + // positioning + m_pManager->layoutMinimizedChildren(); +} + +void KMdiChildFrm::slot_resizeViaSystemMenu() +{ + grabMouse(); + m_bResizing = true; + m_iResizeCorner = KMDI_RESIZE_BOTTOMLEFT; + setResizeCursor( m_iResizeCorner ); +} + +void KMdiChildFrm::redecorateButtons() +{ + delete m_pMinButtonPixmap; + delete m_pMaxButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + delete m_pUndockButtonPixmap; + + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + m_pMinButtonPixmap = new QPixmap( win_minbutton ); + m_pMaxButtonPixmap = new QPixmap( win_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( win_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( win_closebutton ); + m_pUndockButtonPixmap = new QPixmap( win_undockbutton ); + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + m_pMinButtonPixmap = new QPixmap( kde_minbutton ); + m_pMaxButtonPixmap = new QPixmap( kde_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde_closebutton ); + m_pUndockButtonPixmap = new QPixmap( kde_undockbutton ); + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + { + m_pMinButtonPixmap = new QPixmap( kde2_minbutton ); + m_pMaxButtonPixmap = new QPixmap( kde2_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2_closebutton ); + m_pUndockButtonPixmap = new QPixmap( kde2_undockbutton ); + } + else + { // kde2laptop look + m_pMinButtonPixmap = new QPixmap( kde2laptop_minbutton ); + m_pMaxButtonPixmap = new QPixmap( kde2laptop_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2laptop_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2laptop_closebutton ); + m_pUndockButtonPixmap = new QPixmap( kde2laptop_undockbutton ); + } + + m_pUnixIcon->setAutoRaise( true ); + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + m_pMinimize->setAutoRaise( true ); + m_pMaximize->setAutoRaise( true ); + m_pClose->setAutoRaise( true ); + m_pUndock->setAutoRaise( true ); + } + else + { + m_pMinimize->setAutoRaise( false ); + m_pMaximize->setAutoRaise( false ); + m_pClose->setAutoRaise( false ); + m_pUndock->setAutoRaise( false ); + } + + if ( m_pClient && m_pClient->icon() ) + { + m_pWinIcon->setPixmap( *( m_pClient )->icon() ); + m_pUnixIcon->setPixmap( *( m_pClient )->icon() ); + } + else + { + m_pWinIcon->setPixmap( *m_pIconButtonPixmap ); + m_pUnixIcon->setPixmap( *m_pIconButtonPixmap ); + } + m_pClose->setPixmap( *m_pCloseButtonPixmap ); + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + m_pUndock->setPixmap( *m_pUndockButtonPixmap ); +} + +QRect KMdiChildFrm::mdiAreaContentsRect() const +{ + QFrame * p = ( QFrame* ) parentWidget(); + if ( p ) + { + return p->contentsRect(); + } + else + { + QRect empty; + return empty; + } +} + +// kate: indent-mode csands; tab-width 4; space-indent off; replace-tabs off; diff --git a/kmdi/kmdichildfrm.h b/kmdi/kmdichildfrm.h new file mode 100644 index 000000000..58959a42a --- /dev/null +++ b/kmdi/kmdichildfrm.h @@ -0,0 +1,446 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrm.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : */2000 Lars Beikirch (Lars.Beikirch@gmx.net) +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//------------------------------------------------------------------------------ +#ifndef _KMDI_CHILD_FRM_H_ +#define _KMDI_CHILD_FRM_H_ + +#include <qptrlist.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qdatetime.h> +#include <qlayout.h> + +#include <qdict.h> + +#include "kmdichildfrmcaption.h" + +class KMdiChildArea; +class KMdiChildView; +class QPopupMenu; +class QToolButton; + +//============================================================================== +/** + * @short Internal class, only used on Win32. + * This class provides a label widget that can process mouse click events. + */ +class KMDI_EXPORT KMdiWin32IconButton : public QLabel +{ + Q_OBJECT +public: + KMdiWin32IconButton( QWidget* parent, const char* name = 0 ); + virtual void mousePressEvent( QMouseEvent* ); + +signals: + void pressed(); +}; + +//============================================================================== +/* some special events, see kmdidefines.h +*/ +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for move + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmMoveEvent : public QCustomEvent +{ +public: + KMdiChildFrmMoveEvent( QMoveEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_Move ) ), e ) {} + +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for begin of dragging + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmDragBeginEvent : public QCustomEvent +{ +public: + KMdiChildFrmDragBeginEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_DragBegin ) ), e ) {} +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for end of dragging + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmDragEndEvent : public QCustomEvent +{ +public: + KMdiChildFrmDragEndEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_DragEnd ) ), e ) {} +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for begin of resizing + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmResizeBeginEvent : public QCustomEvent +{ +public: + KMdiChildFrmResizeBeginEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_ResizeBegin ) ), e ) {} +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for end of resizing + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmResizeEndEvent : public QCustomEvent +{ +public: + KMdiChildFrmResizeEndEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_ResizeEnd ) ), e ) {} +}; + + +class KMdiChildFrmPrivate; +//============================================================================== +/** + * @short Internal class. + * It's an MDI child frame widget. It contains a view widget and a frame caption. Usually you derive from its view. + */ +//------------------------------------------------------------------------------ +class KMDI_EXPORT KMdiChildFrm : public QFrame +{ + friend class KMdiChildArea; + friend class KMdiChildFrmCaption; + + Q_OBJECT + + // attributes +public: + enum MdiWindowState { Normal, Maximized, Minimized }; + //positions same in h and cpp for fast order check + KMdiChildView* m_pClient; + +protected: + KMdiChildArea* m_pManager; + KMdiChildFrmCaption* m_pCaption; + KMdiWin32IconButton* m_pWinIcon; + QToolButton* m_pUnixIcon; + QToolButton* m_pMinimize; + QToolButton* m_pMaximize; + QToolButton* m_pClose; + QToolButton* m_pUndock; + MdiWindowState m_state; + QRect m_restoredRect; + int m_iResizeCorner; + int m_iLastCursorCorner; + bool m_bResizing; + bool m_bDragging; + QPixmap* m_pIconButtonPixmap; + QPixmap* m_pMinButtonPixmap; + QPixmap* m_pMaxButtonPixmap; + QPixmap* m_pRestoreButtonPixmap; + QPixmap* m_pCloseButtonPixmap; + QPixmap* m_pUndockButtonPixmap; + + /** + * Every child frame window has an temporary ID in the Window menu of the child area. + */ + int m_windowMenuID; + + /** + * Imitates a system menu for child frame windows + */ + QPopupMenu* m_pSystemMenu; + + QSize m_oldClientMinSize; + QSize m_oldClientMaxSize; + QLayout::ResizeMode m_oldLayoutResizeMode; + QTime m_timeMeasure; + + // methods +public: + + /** + * Creates a new KMdiChildFrm class. + */ + KMdiChildFrm( KMdiChildArea *parent ); + + /** + * Destroys this KMdiChildFrm + * If a child is still here managed (no recreation was made) it is destroyed too. + */ + ~KMdiChildFrm(); + + /** + * Reparents the widget w to this KMdiChildFrm (if this is not already done) + * Installs an event filter to catch focus events. + * Resizes this mdi child in a way that the child fits perfectly in. + */ + void setClient( KMdiChildView *w, bool bAutomaticResize = false ); + + /** + * Reparents the client widget to 0 (desktop), moves with an offset from the original position + * Removes the event filter. + */ + void unsetClient( QPoint positionOffset = QPoint( 0, 0 ) ); + + /** + * Sets the window icon pointer. + */ + void setIcon( const QPixmap &pxm ); + + /** + * Returns the child frame icon. + */ + QPixmap* icon() const; + + /** + * Enables or disables the close button + */ + void enableClose( bool bEnable ); + + /** + * Sets the caption of this window + */ + void setCaption( const QString& text ); + + /** + * Gets the caption of this mdi child. + */ + const QString& caption() { return m_pCaption->m_szCaption; } + + /** + * Minimizes, Maximizes, or restores the window. + */ + void setState( MdiWindowState state, bool bAnimate = true ); + + /** + * Returns the current state of the window + */ + inline MdiWindowState state() const { return m_state; } + + /** + * Returns the inner client area of the parent of this (which is KMdiChildArea). + */ + QRect mdiAreaContentsRect() const; + + /** + * Returns the geometry that will be restored by calling restore(). + */ + QRect restoreGeometry() const; + + /** + * Sets the geometry that will be restored by calling restore(). + */ + void setRestoreGeometry( const QRect& newRestGeo ); + + /** + * Forces updating the rects of the caption and so... + * It may be useful when setting the mdiCaptionFont of the MdiManager + */ + void updateRects() { resizeEvent( 0 ); } + + /** + * Returns the system menu. + */ + QPopupMenu* systemMenu() const; + + /** + * Returns the caption bar height + */ + inline int captionHeight() const { return m_pCaption->height(); } + + /** + * sets new raise behavior and pixmaps of the buttons depending on the current decoration style + */ + void redecorateButtons(); + + /** + * returns the mouse state "In Drag" + */ + bool isInDrag() const { return m_bDragging; } + + /** + * returns the mouse state "In Resize" + */ + bool isInResize() const { return m_bResizing; } + + /** + * Internally called from the signal focusInEventOccurs. + * It raises the MDI childframe to the top of all other MDI child frames and sets the focus on it. + */ + void raiseAndActivate(); + + /** + * Sets the minimum size of the widget to w by h pixels. + * It extends it's base clase method in a way that the minimum size of + * the child area will be set additionally if the view is maximized. + */ + virtual void setMinimumSize ( int minw, int minh ); + +public slots: + + void slot_resizeViaSystemMenu(); + +protected: + + /** + * Reimplemented from the base class. + * Resizes the captionbar, relayouts the position of the system buttons, + * and calls resize for its embedded KMdiChildView with the proper size + */ + virtual void resizeEvent( QResizeEvent * ); + + /** + * Reimplemented from the base class. + * Detects if the mouse is on the edge of window and what resize cursor must be set. + * Calls KMdiChildFrm::resizeWindow if it is in m_bResizing. + */ + virtual void mouseMoveEvent( QMouseEvent *e ); + + /** + * Reimplemented from the base class. + * Colours the caption, raises the childfrm widget and + * turns to resize mode if it is on the edge (resize-sensitive area) + */ + virtual void mousePressEvent( QMouseEvent *e ); + + /** + * Reimplemented from the base class. + * Sets a normal cursor and leaves the resize mode. + */ + virtual void mouseReleaseEvent( QMouseEvent * ); + + /** + * Reimplemented from the base class. + * give its child view the chance to notify a childframe move... that's why it sends + * a KMdiChildMovedEvent to the embedded KMdiChildView . + */ + virtual void moveEvent( QMoveEvent* me ); + + /** + * Reimplemented from the base class. If not in resize mode, it sets the mouse cursor to normal appearance. + */ + virtual void leaveEvent( QEvent * ); + + /** + * Reimplemented from the base class. + * In addition, the following are caught + * -the client's mousebutton press events which raises and activates the childframe + * -the client's resize event which resizes this widget as well + */ + virtual bool eventFilter( QObject*, QEvent* ); + + /** + * Calculates the new geometry from the new mouse position given as parameters + * and calls KMdiChildFrm::setGeometry + */ + void resizeWindow( int resizeCorner, int x, int y ); + + /** + * Override the cursor appearance depending on the widget corner given as parameter + */ + void setResizeCursor( int resizeCorner ); + + /** + * Changes from the resize cursor to the normal (previous) cursor + */ + void unsetResizeCursor(); + + /** + * That means to show a mini window showing the childframe's caption bar, only. + * It cannot be resized. + */ + virtual void switchToMinimizeLayout(); + + /** + * Does the actual resize. Called from various places but from resizeEvent in general. + */ + void doResize(); + + /** + * Does the actual resize, like doResize() but skips resize of the client if \a captionOnly is true. + * @todo: merge with doResize() + */ + void doResize( bool captionOnly ); + +protected slots: + + /** + * Handles a click on the Maximize button + */ + void maximizePressed(); + + /** + * Handles a click on the Restore (Normalize) button + */ + void restorePressed(); + + /** + * Handles a click on the Minimize button. + */ + void minimizePressed(); + + /** + * Handles a click on the Close button. + */ + void closePressed(); + + /** + * Handles a click on the Undock (Detach) button + */ + void undockPressed(); + + /** + * Shows a system menu for child frame windows. + */ + void showSystemMenu(); + +protected: + + /** + * Restore the focus policies for _all_ widgets in the view using the list given as parameter. + * Install the event filter for all direct child widgets of this. (See KMdiChildFrm::eventFilter) + */ + void linkChildren( QDict<FocusPolicy>* pFocPolDict ); + + /** + * Backups all focus policies of _all_ child widgets in the MDI childview since they get lost during a reparent. + * Remove all event filters for all direct child widgets of this. (See KMdiChildFrm::eventFilter) + */ + QDict<QWidget::FocusPolicy>* unlinkChildren(); + + /** + * Calculates the corner id for the resize cursor. The return value can be tested for: + * KMDI_RESIZE_LEFT, KMDI_RESIZE_RIGHT, KMDI_RESIZE_TOP, KMDI_RESIZE_BOTTOM + * or an OR'd variant of them for the corners. + */ + int getResizeCorner( int ax, int ay ); + +private: + KMdiChildFrmPrivate *d; +}; + +#endif //_KMDICHILDFRM_H_ + +// kate: space-indent off; replace-tabs off; tab-width 4; indent-mode csands; diff --git a/kmdi/kmdichildfrmcaption.cpp b/kmdi/kmdichildfrmcaption.cpp new file mode 100644 index 000000000..815d07d44 --- /dev/null +++ b/kmdi/kmdichildfrmcaption.cpp @@ -0,0 +1,322 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrmcaption.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#include "kmdichildfrmcaption.h" +#include "kmdichildfrmcaption.moc" + +#include <qpainter.h> +#include <qapplication.h> +#include <qcursor.h> +#include <qtoolbutton.h> +#include <qpopupmenu.h> + +#include "kmdidefines.h" +#include "kmdichildfrm.h" +#include "kmdichildarea.h" +#include "kmdimainfrm.h" +#include <klocale.h> +#include <iostream> + +#ifdef Q_WS_WIN +//TODO: one day gradient can be added for win98/winnt5+ +// ask system properties on windows +#ifndef SPI_GETGRADIENTCAPTIONS +# define SPI_GETGRADIENTCAPTIONS 0x1008 +#endif +#ifndef COLOR_GRADIENTACTIVECAPTION +# define COLOR_GRADIENTACTIVECAPTION 27 +#endif +#ifndef COLOR_GRADIENTINACTIVECAPTION +# define COLOR_GRADIENTINACTIVECAPTION 28 +#endif +#endif +//#endif + +////////////////////////////////////////////////////////////////////////////// +// Class : KMdiChildFrmCaption +// Purpose : An MDI label that draws the title +// +// +////////////////////////////////////////////////////////////////////////////// + +//============== KMdiChildFrmCaption =============// + +KMdiChildFrmCaption::KMdiChildFrmCaption( KMdiChildFrm *parent ) + : QWidget( parent, "kmdi_childfrmcaption" ) +{ + m_szCaption = i18n( "Unnamed" ); + m_bActive = false; + m_pParent = parent; + setBackgroundMode( NoBackground ); + setFocusPolicy( NoFocus ); + m_bChildInDrag = false; +} + +//============== ~KMdiChildFrmCaption =============// + +KMdiChildFrmCaption::~KMdiChildFrmCaption() +{} + +//============= mousePressEvent ==============// + +void KMdiChildFrmCaption::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + { + setMouseTracking( false ); + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + { + QApplication::setOverrideCursor( Qt::sizeAllCursor, true ); + } + m_pParent->m_bDragging = true; + m_offset = mapToParent( e->pos() ); + } + else if ( e->button() == RightButton ) + { + m_pParent->systemMenu()->popup( mapToGlobal( e->pos() ) ); + } +} + +//============= mouseReleaseEvent ============// + +void KMdiChildFrmCaption::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + { + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + QApplication::restoreOverrideCursor(); + + releaseMouse(); + if ( m_pParent->m_bDragging ) + { + m_pParent->m_bDragging = false; + if ( m_bChildInDrag ) + { + //notify child view + KMdiChildFrmDragEndEvent ue( e ); + if ( m_pParent->m_pClient != 0L ) + QApplication::sendEvent( m_pParent->m_pClient, &ue ); + + m_bChildInDrag = false; + } + } + } +} + +//============== mouseMoveEvent =============// +void KMdiChildFrmCaption::mouseMoveEvent( QMouseEvent *e ) +{ + if ( !m_pParent->m_bDragging ) + return ; + + if ( !m_bChildInDrag ) + { + //notify child view + KMdiChildFrmDragBeginEvent ue( e ); + if ( m_pParent->m_pClient != 0L ) + QApplication::sendEvent( m_pParent->m_pClient, &ue ); + + m_bChildInDrag = true; + } + + QPoint relMousePosInChildArea = m_pParent->m_pManager->mapFromGlobal( e->globalPos() ); + + // mouse out of child area? stop child frame dragging + if ( !m_pParent->m_pManager->rect().contains( relMousePosInChildArea ) ) + { + if ( relMousePosInChildArea.x() < 0 ) + relMousePosInChildArea.rx() = 0; + + if ( relMousePosInChildArea.y() < 0 ) + relMousePosInChildArea.ry() = 0; + + if ( relMousePosInChildArea.x() > m_pParent->m_pManager->width() ) + relMousePosInChildArea.rx() = m_pParent->m_pManager->width(); + + if ( relMousePosInChildArea.y() > m_pParent->m_pManager->height() ) + relMousePosInChildArea.ry() = m_pParent->m_pManager->height(); + } + QPoint mousePosInChildArea = relMousePosInChildArea - m_offset; + + // set new child frame position + parentWidget() ->move( mousePosInChildArea ); +} + +//=============== setActive ===============// + +void KMdiChildFrmCaption::setActive( bool bActive ) +{ + if ( m_bActive == bActive ) + return ; + + // Ensure the icon's pixmap has the correct bg color + m_pParent->m_pWinIcon->setBackgroundColor( bActive ? + m_pParent->m_pManager->m_captionActiveBackColor : + m_pParent->m_pManager->m_captionInactiveBackColor ); + m_pParent->m_pUnixIcon->setBackgroundColor( bActive ? + m_pParent->m_pManager->m_captionActiveBackColor : + m_pParent->m_pManager->m_captionInactiveBackColor ); + + m_bActive = bActive; + repaint( false ); +} + +//=============== setCaption ===============// + +void KMdiChildFrmCaption::setCaption( const QString& text ) +{ + m_szCaption = text; + repaint( false ); +} + +//============== heightHint ===============// + +int KMdiChildFrmCaption::heightHint() +{ + int hint = m_pParent->m_pManager->m_captionFontLineSpacing + 3; + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + if ( hint < 18 ) + hint = 18; + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + if ( hint < 20 ) + hint = 20; + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + { + if ( hint < 16 ) + hint = 16; + } + else + { // kde2laptop look + hint -= 4; + if ( hint < 14 ) + hint = 14; + } + return hint; +} + +//=============== paintEvent ==============// + +void KMdiChildFrmCaption::paintEvent( QPaintEvent * ) +{ + QPainter p( this ); + QRect r = rect(); + p.setFont( m_pParent->m_pManager->m_captionFont ); + + if ( m_bActive ) + { + p.fillRect( r, m_pParent->m_pManager->m_captionActiveBackColor ); + p.setPen( m_pParent->m_pManager->m_captionActiveForeColor ); + } + else + { + p.fillRect( r, m_pParent->m_pManager->m_captionInactiveBackColor ); + p.setPen( m_pParent->m_pManager->m_captionInactiveForeColor ); + } + + //Shift the text after the icon + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + r.setLeft( r.left() + m_pParent->icon() ->width() + 3 ); + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + r.setLeft( r.left() + 22 ); + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + r.setLeft( r.left() + m_pParent->icon() ->width() + 3 ); + else // kde2laptop look + r.setLeft( r.left() + 30 ); + + int captionWidthForText = width() - 4 * m_pParent->m_pClose->width() - m_pParent->icon() ->width() - 5; + QString text = abbreviateText( m_szCaption, captionWidthForText ); + p.drawText( r, AlignVCenter | AlignLeft | SingleLine, text ); + +} + + +QString KMdiChildFrmCaption::abbreviateText( QString origStr, int maxWidth ) +{ + QFontMetrics fm = fontMetrics(); + int actualWidth = fm.width( origStr ); + + int realLetterCount = origStr.length(); + int newLetterCount; + + if ( actualWidth != 0 ) + newLetterCount = ( maxWidth * realLetterCount ) / actualWidth; + else + newLetterCount = realLetterCount; // should be 0 anyway + + int w = maxWidth + 1; + QString s = origStr; + + if ( newLetterCount <= 0 ) + s = ""; + + while ( ( w > maxWidth ) && ( newLetterCount >= 1 ) ) + { + if ( newLetterCount < realLetterCount ) + { + if ( newLetterCount > 3 ) + s = origStr.left( newLetterCount / 2 ) + "..." + origStr.right( newLetterCount / 2 ); + else + { + if ( newLetterCount > 1 ) + s = origStr.left( newLetterCount ) + ".."; + else + s = origStr.left( 1 ); + } + } + QFontMetrics fm = fontMetrics(); + w = fm.width( s ); + newLetterCount--; + } + return s; +} + +//============= mouseDoubleClickEvent ===========// + +void KMdiChildFrmCaption::mouseDoubleClickEvent( QMouseEvent * ) +{ + m_pParent->maximizePressed(); +} + +//============= slot_moveViaSystemMenu ===========// + +void KMdiChildFrmCaption::slot_moveViaSystemMenu() +{ + setMouseTracking( true ); + grabMouse(); + + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + QApplication::setOverrideCursor( Qt::sizeAllCursor, true ); + + m_pParent->m_bDragging = true; + m_offset = mapFromGlobal( QCursor::pos() ); +} + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/kmdi/kmdichildfrmcaption.h b/kmdi/kmdichildfrmcaption.h new file mode 100644 index 000000000..6100acc02 --- /dev/null +++ b/kmdi/kmdichildfrmcaption.h @@ -0,0 +1,145 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrmcaption.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- +#ifndef _KMDI_CHILD_FRM_CAPTION_H_ +#define _KMDI_CHILD_FRM_CAPTION_H_ + +#include <qwidget.h> + +#include "kmdidefines.h" + +class KMdiChildFrm; + + +class KMdiChildFrmCaptionPrivate; + +/** +* @short Internal class. +* +* It's the caption bar of a child frame widget. +*/ +class KMDI_EXPORT KMdiChildFrmCaption : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + KMdiChildFrmCaption( KMdiChildFrm *parent ); + + /** + * Destructor + */ + ~KMdiChildFrmCaption(); + + /** + * Repaint the caption bar in active background colors + */ + void setActive( bool bActive ); + + /** + * Repaint with a new caption bar title + */ + void setCaption( const QString& text ); + + /** + * Returns the caption bar height depending on the used font + */ + int heightHint(); + +public slots: + /** + * Grabs the mouse, a move cursor, sets a move indicator variable to true and keeps the global mouse position in mind + */ + void slot_moveViaSystemMenu(); + +protected: + /** + * Draws the caption bar and its title using the settings + */ + virtual void paintEvent( QPaintEvent *e ); + + /** + * The same as KMdiChildFrmCaption::slot_moveViaSystemMenu + */ + virtual void mousePressEvent( QMouseEvent * ); + + /** + * Calls maximizePressed of the parent widget ( KMdiChildFrm ) + */ + virtual void mouseDoubleClickEvent( QMouseEvent * ); + + /** + * Restore the normal mouse cursor, set the state variable back to 'not moving' + */ + virtual void mouseReleaseEvent( QMouseEvent * ); + + /** + * Checks if out of move range of the KMdiChildArea and calls KMdiChildFrm::move + */ + virtual void mouseMoveEvent( QMouseEvent *e ); + + /** + * Computes a new abbreviated string from a given string depending on a given maximum width + * @todo Replace with a call to a KStringHandler function instead of rolling our own + */ + QString abbreviateText( QString origStr, int maxWidth ); + + // attributes +public: + /** + * the title string shown in the caption bar + */ + QString m_szCaption; + +protected: // Protected attributes + /** + * parent widget + */ + KMdiChildFrm *m_pParent; + + /** + * state variable indicating whether activated or not activated + */ + bool m_bActive; + + /** + * the position offset related to its parent widget (internally used for translating mouse move positions + */ + QPoint m_offset; + + /** + * True if the child knows that it is currently being dragged. + */ + bool m_bChildInDrag; + +private: + KMdiChildFrmCaptionPrivate *d; +}; + +#endif //_KMDICAPTION_H_ + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/kmdi/kmdichildview.cpp b/kmdi/kmdichildview.cpp new file mode 100644 index 000000000..ffe30b652 --- /dev/null +++ b/kmdi/kmdichildview.cpp @@ -0,0 +1,774 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildview.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create a +// -06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// 02/2001 by Eva Brucherseifer (eva@rt.e-technik.tu-darmstadt.de) +// 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#include "kmdichildview.h" +#include "kmdichildview.moc" + +#include <qdatetime.h> +#include <qobjectlist.h> + +#include "kmdimainfrm.h" +#include "kmdichildfrm.h" +#include "kmdidefines.h" +#include <kdebug.h> +#include <klocale.h> +#include <qiconset.h> + +//============ KMdiChildView ============// + +KMdiChildView::KMdiChildView( const QString& caption, QWidget* parentWidget, const char* name, WFlags f ) + : QWidget( parentWidget, name, f ) + , m_focusedChildWidget( 0L ) + , m_firstFocusableChildWidget( 0L ) + , m_lastFocusableChildWidget( 0L ) + , m_stateChanged( true ) + , m_bToolView( false ) + , m_bInterruptActivation( false ) + , m_bMainframesActivateViewIsPending( false ) + , m_bFocusInEventIsPending( false ) + , m_trackChanges( 0 ) +{ + setGeometry( 0, 0, 0, 0 ); // reset + if ( caption != 0L ) + m_szCaption = caption; + else + m_szCaption = i18n( "Unnamed" ); + + m_sTabCaption = m_szCaption; + setFocusPolicy( ClickFocus ); + installEventFilter( this ); + + // store the current time + updateTimeStamp(); +} + + +//============ KMdiChildView ============// + +KMdiChildView::KMdiChildView( QWidget* parentWidget, const char* name, WFlags f ) + : QWidget( parentWidget, name, f ) + , m_focusedChildWidget( 0L ) + , m_firstFocusableChildWidget( 0L ) + , m_lastFocusableChildWidget( 0L ) + , m_stateChanged( true ) + , m_bToolView( false ) + , m_bInterruptActivation( false ) + , m_bMainframesActivateViewIsPending( false ) + , m_bFocusInEventIsPending( false ) + , m_trackChanges( 0 ) +{ + setGeometry( 0, 0, 0, 0 ); // reset + m_szCaption = i18n( "Unnamed" ); + m_sTabCaption = m_szCaption; + setFocusPolicy( ClickFocus ); + installEventFilter( this ); + + // store the current time + updateTimeStamp(); +} + +//============ ~KMdiChildView ============// + +KMdiChildView::~KMdiChildView() +{ + kdDebug( 760 ) << k_funcinfo << endl; +} + +void KMdiChildView::trackIconAndCaptionChanges( QWidget *view ) +{ + m_trackChanges = view; +} + + +//============== internal geometry ==============// + +QRect KMdiChildView::internalGeometry() const +{ + if ( mdiParent() ) + { // is attached + // get the client area coordinates inside the MDI child frame + QRect posInFrame = geometry(); + // map these values to the parent of the MDI child frame + // (this usually is the MDI child area) and return + QPoint ptTopLeft = mdiParent() ->mapToParent( posInFrame.topLeft() ); + QSize sz = size(); + return QRect( ptTopLeft, sz ); + } + else + { + QRect geo = geometry(); + QRect frameGeo = externalGeometry(); + return QRect( frameGeo.x(), frameGeo.y(), geo.width(), geo.height() ); + // return geometry(); + } +} + +//============== set internal geometry ==============// + +void KMdiChildView::setInternalGeometry( const QRect& newGeometry ) +{ + if ( mdiParent() ) + { // is attached + // retrieve the frame size + QRect geo = internalGeometry(); + QRect frameGeo = externalGeometry(); + int nFrameSizeTop = geo.y() - frameGeo.y(); + int nFrameSizeLeft = geo.x() - frameGeo.x(); + + // create the new geometry that is accepted by the QWidget::setGeometry() method + QRect newGeoQt; + newGeoQt.setX( newGeometry.x() - nFrameSizeLeft ); + newGeoQt.setY( newGeometry.y() - nFrameSizeTop ); + + newGeoQt.setWidth( newGeometry.width() + nFrameSizeLeft + KMDI_CHILDFRM_DOUBLE_BORDER / 2 ); + newGeoQt.setHeight( newGeometry.height() + nFrameSizeTop + KMDI_CHILDFRM_DOUBLE_BORDER / 2 ); + // newGeoQt.setWidth(newGeometry.width()+KMDI_MDI_CHILDFRM_DOUBLE_BORDER); + // newGeoQt.setHeight(newGeometry.height()+mdiParent()->captionHeight()+KMDI_MDI_CHILDFRM_DOUBLE_BORDER); + + // set the geometry + mdiParent()->setGeometry( newGeoQt ); + } + else + { + // retrieve the frame size + QRect geo = internalGeometry(); + QRect frameGeo = externalGeometry(); + int nFrameSizeTop = geo.y() - frameGeo.y(); + int nFrameSizeLeft = geo.x() - frameGeo.x(); + + // create the new geometry that is accepted by the QWidget::setGeometry() method + QRect newGeoQt; + + newGeoQt.setX( newGeometry.x() - nFrameSizeLeft ); + newGeoQt.setY( newGeometry.y() - nFrameSizeTop ); + + newGeoQt.setWidth( newGeometry.width() ); + newGeoQt.setHeight( newGeometry.height() ); + + // set the geometry + setGeometry( newGeoQt ); + } +} + +//============== external geometry ==============// + +QRect KMdiChildView::externalGeometry() const +{ + return mdiParent() ? mdiParent()->frameGeometry() : frameGeometry(); +} + +//============== set external geometry ==============// + +void KMdiChildView::setExternalGeometry( const QRect& newGeometry ) +{ + if ( mdiParent() ) + { // is attached + mdiParent() ->setGeometry( newGeometry ); + } + else + { + // retrieve the frame size + QRect geo = internalGeometry(); + QRect frameGeo = externalGeometry(); + int nTotalFrameWidth = frameGeo.width() - geo.width(); + int nTotalFrameHeight = frameGeo.height() - geo.height(); + int nFrameSizeTop = geo.y() - frameGeo.y(); + int nFrameSizeLeft = geo.x() - frameGeo.x(); + + // create the new geometry that is accepted by the QWidget::setGeometry() method + // not attached => the window system makes the frame + QRect newGeoQt; + newGeoQt.setX( newGeometry.x() + nFrameSizeLeft ); + newGeoQt.setY( newGeometry.y() + nFrameSizeTop ); + newGeoQt.setWidth( newGeometry.width() - nTotalFrameWidth ); + newGeoQt.setHeight( newGeometry.height() - nTotalFrameHeight ); + + // set the geometry + setGeometry( newGeoQt ); + } +} + +//============== minimize ==============// + +void KMdiChildView::minimize( bool bAnimate ) +{ + if ( mdiParent() ) + { + if ( !isMinimized() ) + { + mdiParent() ->setState( KMdiChildFrm::Minimized, bAnimate ); + } + } + else + showMinimized(); +} + +void KMdiChildView::showMinimized() +{ + emit isMinimizedNow(); + QWidget::showMinimized(); +} + +//slot: +void KMdiChildView::minimize() +{ + minimize( true ); +} + +//============= maximize ==============// + +void KMdiChildView::maximize( bool bAnimate ) +{ + if ( mdiParent() ) + { + if ( !isMaximized() ) + { + mdiParent() ->setState( KMdiChildFrm::Maximized, bAnimate ); + emit mdiParentNowMaximized( true ); + } + } + else + showMaximized(); +} + +void KMdiChildView::showMaximized() +{ + emit isMaximizedNow(); + QWidget::showMaximized(); +} + +//slot: +void KMdiChildView::maximize() +{ + maximize( true ); +} + +//============== restoreGeometry ================// + +QRect KMdiChildView::restoreGeometry() +{ + if ( mdiParent() ) + return mdiParent() ->restoreGeometry(); + else //FIXME not really supported, may be we must use Windows or X11 funtions + return geometry(); +} + +//============== setRestoreGeometry ================// + +void KMdiChildView::setRestoreGeometry( const QRect& newRestGeo ) +{ + if ( mdiParent() ) + mdiParent()->setRestoreGeometry( newRestGeo ); +} + +//============== attach ================// + +void KMdiChildView::attach() +{ + emit attachWindow( this, true ); +} + +//============== detach =================// + +void KMdiChildView::detach() +{ + emit detachWindow( this, true ); +} + +//=============== isMinimized ? =================// + +bool KMdiChildView::isMinimized() const +{ + if ( mdiParent() ) + return ( mdiParent()->state() == KMdiChildFrm::Minimized ); + else + return QWidget::isMinimized(); +} + +//============== isMaximized ? ==================// + +bool KMdiChildView::isMaximized() const +{ + if ( mdiParent() ) + return ( mdiParent()->state() == KMdiChildFrm::Maximized ); + else + return QWidget::isMaximized(); +} + +//============== restore ================// + +void KMdiChildView::restore() +{ + if ( mdiParent() ) + { + if ( isMaximized() ) + emit mdiParentNowMaximized( false ); + + if ( isMinimized() || isMaximized() ) + mdiParent()->setState( KMdiChildFrm::Normal ); + } + else + showNormal(); +} + +void KMdiChildView::showNormal() +{ + emit isRestoredNow(); + QWidget::showNormal(); +} + +//=============== youAreAttached ============// + +void KMdiChildView::youAreAttached( KMdiChildFrm *lpC ) +{ + lpC->setCaption( m_szCaption ); + emit isAttachedNow(); +} + +//================ youAreDetached =============// + +void KMdiChildView::youAreDetached() +{ + setCaption( m_szCaption ); + + setTabCaption( m_sTabCaption ); + if ( myIconPtr() ) + setIcon( *( myIconPtr() ) ); + + setFocusPolicy( QWidget::StrongFocus ); + + emit isDetachedNow(); +} + +//================ setCaption ================// +// this set the caption of only the window +void KMdiChildView::setCaption( const QString& szCaption ) +{ + // this will work only for window + m_szCaption = szCaption; + if ( mdiParent() ) + mdiParent() ->setCaption( m_szCaption ); + else //have to call the parent one + QWidget::setCaption( m_szCaption ); + + emit windowCaptionChanged( m_szCaption ); +} + +//============== closeEvent ================// + +void KMdiChildView::closeEvent( QCloseEvent *e ) +{ + e->ignore(); //we ignore the event , and then close later if needed. + emit childWindowCloseRequest( this ); +} + +//================ myIconPtr =================// + +QPixmap* KMdiChildView::myIconPtr() +{ + return 0; +} + +//============= focusInEvent ===============// + +void KMdiChildView::focusInEvent( QFocusEvent *e ) +{ + QWidget::focusInEvent( e ); + + // every widget get a focusInEvent when a popup menu is opened!?! -> maybe bug of QT + if ( e && ( ( e->reason() ) == QFocusEvent::Popup ) ) + return ; + + + m_bFocusInEventIsPending = true; + activate(); + m_bFocusInEventIsPending = false; + + emit gotFocus( this ); +} + +//============= activate ===============// + +void KMdiChildView::activate() +{ + // avoid circularity + static bool s_bActivateIsPending = false; + if ( s_bActivateIsPending ) + return ; + + s_bActivateIsPending = true; + + // raise the view and push the taskbar button + if ( !m_bMainframesActivateViewIsPending ) + emit focusInEventOccurs( this ); + + // if this method was called directly, check if the mainframe wants that we interrupt + if ( m_bInterruptActivation ) + m_bInterruptActivation = false; + else + { + if ( !m_bFocusInEventIsPending ) + setFocus(); + + kdDebug( 760 ) << k_funcinfo << endl; + emit activated( this ); + } + + if ( m_focusedChildWidget != 0L ) + m_focusedChildWidget->setFocus(); + else + { + if ( m_firstFocusableChildWidget != 0L ) + { + m_firstFocusableChildWidget->setFocus(); + m_focusedChildWidget = m_firstFocusableChildWidget; + } + } + s_bActivateIsPending = false; +} + +//============= focusOutEvent ===============// + +void KMdiChildView::focusOutEvent( QFocusEvent* e ) +{ + QWidget::focusOutEvent( e ); + emit lostFocus( this ); +} + +//============= resizeEvent ===============// + +void KMdiChildView::resizeEvent( QResizeEvent* e ) +{ + QWidget::resizeEvent( e ); + + if ( m_stateChanged ) + { + m_stateChanged = false; + if ( isMaximized() ) + { //maximized + emit isMaximizedNow(); + } + else if ( isMinimized() ) + { //minimized + emit isMinimizedNow(); + } + else + { //is restored + emit isRestoredNow(); + } + } +} + +void KMdiChildView::slot_childDestroyed() +{ + // do what we do if a child is removed + + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + const QObject * pLostChild = QObject::sender(); + if ( pLostChild && ( pLostChild->isWidgetType() ) ) + { + QObjectList* list = ( ( QObject* ) ( pLostChild ) ) ->queryList( "QWidget" ); + list->insert( 0, pLostChild ); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) obj; + ++it; + widg->removeEventFilter( this ); + if ( m_firstFocusableChildWidget == widg ) + m_firstFocusableChildWidget = 0L; // reset first widget + + if ( m_lastFocusableChildWidget == widg ) + m_lastFocusableChildWidget = 0L; // reset last widget + + if ( m_focusedChildWidget == widg ) + m_focusedChildWidget = 0L; // reset focused widget + } + delete list; // delete the list, not the objects + } +} + +//============= eventFilter ===============// +bool KMdiChildView::eventFilter( QObject *obj, QEvent *e ) +{ + if ( e->type() == QEvent::KeyPress && isAttached() ) + { + QKeyEvent* ke = ( QKeyEvent* ) e; + if ( ke->key() == Qt::Key_Tab ) + { + QWidget* w = ( QWidget* ) obj; + FocusPolicy wfp = w->focusPolicy(); + if ( wfp == QWidget::StrongFocus || wfp == QWidget::TabFocus || w->focusPolicy() == QWidget::WheelFocus ) + { + if ( m_lastFocusableChildWidget != 0 ) + { + if ( w == m_lastFocusableChildWidget ) + { + if ( w != m_firstFocusableChildWidget ) + m_firstFocusableChildWidget->setFocus(); + } + } + } + } + } + else if ( e->type() == QEvent::FocusIn ) + { + if ( obj->isWidgetType() ) + { + QObjectList * list = queryList( "QWidget" ); + if ( list->find( obj ) != -1 ) + m_focusedChildWidget = ( QWidget* ) obj; + + delete list; // delete the list, not the objects + } + if ( !isAttached() ) + { // is toplevel, for attached views activation is done by main frame event filter + static bool m_bActivationIsPending = false; + if ( !m_bActivationIsPending ) + { + m_bActivationIsPending = true; + activate(); // sets the focus + m_bActivationIsPending = false; + } + } + } + else if ( e->type() == QEvent::ChildRemoved ) + { + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + QObject * pLostChild = ( ( QChildEvent* ) e ) ->child(); + if ( ( pLostChild != 0L ) && ( pLostChild->isWidgetType() ) ) + { + QObjectList * list = pLostChild->queryList( "QWidget" ); + list->insert( 0, pLostChild ); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject * o; + while ( ( o = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) o; + ++it; + widg->removeEventFilter( this ); + FocusPolicy wfp = widg->focusPolicy(); + if ( wfp == QWidget::StrongFocus || wfp == QWidget::TabFocus || widg->focusPolicy() == QWidget::WheelFocus ) + { + if ( m_firstFocusableChildWidget == widg ) + m_firstFocusableChildWidget = 0L; // reset first widget + + if ( m_lastFocusableChildWidget == widg ) + m_lastFocusableChildWidget = 0L; // reset last widget + } + } + delete list; // delete the list, not the objects + } + } + else if ( e->type() == QEvent::ChildInserted ) + { + // if we got a new child and we are attached to the MDI system we + // install ourself as event filter for the new child and its children + // (as we did when we were added to the MDI system). + QObject * pNewChild = ( ( QChildEvent* ) e ) ->child(); + if ( ( pNewChild != 0L ) && ( pNewChild->isWidgetType() ) ) + { + QWidget * pNewWidget = ( QWidget* ) pNewChild; + if ( pNewWidget->testWFlags( Qt::WType_Dialog | Qt::WShowModal ) ) + return false; + QObjectList *list = pNewWidget->queryList( "QWidget" ); + list->insert( 0, pNewChild ); // add the new child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all new child widgets + QObject * o; + while ( ( o = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) o; + ++it; + widg->installEventFilter( this ); + connect( widg, SIGNAL( destroyed() ), this, SLOT( slot_childDestroyed() ) ); + FocusPolicy wfp = widg->focusPolicy(); + if ( wfp == QWidget::StrongFocus || wfp == QWidget::TabFocus || widg->focusPolicy() == QWidget::WheelFocus ) + { + if ( m_firstFocusableChildWidget == 0 ) + m_firstFocusableChildWidget = widg; // first widge + + m_lastFocusableChildWidget = widg; // last widget + } + } + delete list; // delete the list, not the objects + } + } + else + { + if ( e->type() == QEvent::IconChange ) + { + // qDebug("KMDiChildView:: QEvent:IconChange intercepted\n"); + if ( obj == this ) + iconUpdated( this, icon() ? ( *icon() ) : QPixmap() ); + else if ( obj == m_trackChanges ) + setIcon( m_trackChanges->icon() ? ( *( m_trackChanges->icon() ) ) : QPixmap() ); + } + if ( e->type() == QEvent::CaptionChange ) + { + if ( obj == this ) + captionUpdated( this, caption() ); + } + } + + return false; // standard event processing +} + +/** Switches interposing in event loop of all current child widgets off. */ +void KMdiChildView::removeEventFilterForAllChildren() +{ + QObjectList* list = queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget* widg = ( QWidget* ) obj; + ++it; + widg->removeEventFilter( this ); + } + delete list; // delete the list, not the objects +} + +QWidget* KMdiChildView::focusedChildWidget() +{ + return m_focusedChildWidget; +} + +void KMdiChildView::setFirstFocusableChildWidget( QWidget* firstFocusableChildWidget ) +{ + m_firstFocusableChildWidget = firstFocusableChildWidget; +} + +void KMdiChildView::setLastFocusableChildWidget( QWidget* lastFocusableChildWidget ) +{ + m_lastFocusableChildWidget = lastFocusableChildWidget; +} + +/** Set a new value of the task bar button caption */ +void KMdiChildView::setTabCaption ( const QString& stbCaption ) +{ + m_sTabCaption = stbCaption; + emit tabCaptionChanged( m_sTabCaption ); +} + +void KMdiChildView::setMDICaption ( const QString& caption ) +{ + setCaption( caption ); + setTabCaption( caption ); +} + +/** sets an ID */ +void KMdiChildView::setWindowMenuID( int id ) +{ + m_windowMenuID = id; +} + +//============= slot_clickedInWindowMenu ===============// + +/** called if someone click on the "Window" menu item for this child frame window */ +void KMdiChildView::slot_clickedInWindowMenu() +{ + updateTimeStamp(); + emit clickedInWindowMenu( m_windowMenuID ); +} + +//============= slot_clickedInDockMenu ===============// + +/** called if someone click on the "Dock/Undock..." menu item for this child frame window */ +void KMdiChildView::slot_clickedInDockMenu() +{ + emit clickedInDockMenu( m_windowMenuID ); +} + +//============= setMinimumSize ===============// + +void KMdiChildView::setMinimumSize( int minw, int minh ) +{ + QWidget::setMinimumSize( minw, minh ); + if ( mdiParent() && mdiParent()->state() != KMdiChildFrm::Minimized ) + { + mdiParent() ->setMinimumSize( minw + KMDI_CHILDFRM_DOUBLE_BORDER, + minh + KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + mdiParent() ->captionHeight() ); + } +} + +//============= setMaximumSize ===============// + +void KMdiChildView::setMaximumSize( int maxw, int maxh ) +{ + if ( mdiParent() && mdiParent()->state() == KMdiChildFrm::Normal ) + { + int w = maxw + KMDI_CHILDFRM_DOUBLE_BORDER; + if ( w > QWIDGETSIZE_MAX ) + w = QWIDGETSIZE_MAX; + + int h = maxh + KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + mdiParent() ->captionHeight(); + if ( h > QWIDGETSIZE_MAX ) + h = QWIDGETSIZE_MAX; + + mdiParent()->setMaximumSize( w, h ); + } + QWidget::setMaximumSize( maxw, maxh ); +} + +//============= show ===============// + +void KMdiChildView::show() +{ + if ( mdiParent() ) + mdiParent()->show(); + + QWidget::show(); +} + +//============= hide ===============// + +void KMdiChildView::hide() +{ + if ( mdiParent() ) + mdiParent()->hide(); + + QWidget::hide(); +} + +//============= raise ===============// + +void KMdiChildView::raise() +{ + if ( mdiParent() ) //TODO Check Z-order + mdiParent()->raise(); + + QWidget::raise(); +} + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/kmdi/kmdichildview.h b/kmdi/kmdichildview.h new file mode 100644 index 000000000..fda0b95bc --- /dev/null +++ b/kmdi/kmdichildview.h @@ -0,0 +1,615 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildview.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// 02/2001 by Eva Brucherseifer (eva@rt.e-technik.tu-darmstadt.de) +// 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- +#ifndef _KMDI_CHILD_VIEW_H_ +#define _KMDI_CHILD_VIEW_H_ + +#include <qwidget.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdatetime.h> + +#include "kmdichildfrm.h" + +class KMdiChildViewPrivate; + +/** + * @short Base class for all your special view windows. + * + * Base class for all MDI view widgets. KMdi stores additional information in this class + * to handle the attach/detach mechanism and such things. + * + * All such windows 'lives' attached to a KMdiChildFrm widget + * managed by KMdiChildArea, or detached (managed by the window manager.) + * So remember that the KMdiChildView::parent pointer may change, and may be 0L, too. + * + * There are 2 possibilities for you to put your widgets under MDI control: + * + * Either you inherit all the views from KMdiChildView: + * \code + * class MyMdiWidget : public KMdiChildView + * { .... }; + * ... + * MyMdiWidget w; + * mainframe->addWindow(w, flags); + * \endcode + * + * or you wrap them by a KMdiChildView somehow like this: + * + * \code + * void DocViewMan::addKMdiFrame(QWidget* pNewView, bool bShow, const QPixmap& icon) + * { + * // cover it by a KMdi childview and add that MDI system + * KMdiChildView* pMDICover = new KMdiChildView( pNewView->caption()); + * pMDICover->setIcon(icon); + * m_MDICoverList.append( pMDICover); + * QBoxLayout* pLayout = new QHBoxLayout( pMDICover, 0, -1, "layout"); + * pNewView->reparent( pMDICover, QPoint(0,0)); + * pLayout->addWidget( pNewView); + * pMDICover->setName( pNewView->name()); + * // captions + * QString shortName = pNewView->caption(); + * int length = shortName.length(); + * shortName = shortName.right(length - (shortName.findRev('/') +1)); + * pMDICover->setTabCaption( shortName); + * pMDICover->setCaption(pNewView->caption()); + * + * // fake a viewActivated to update the currentEditView/currentBrowserView pointers _before_ adding to MDI control + * slot_viewActivated( pMDICover); + * + * // take it under MDI mainframe control (note: this triggers also a setFocus()) + * int flags; + * if (bShow) { + * flags = KMdi::StandardAdd; + * } + * else { + * flags = KMdi::Hide; + * } + * // set the accelerators for Toplevel MDI mode (each toplevel window needs its own accels + * connect( m_pParent, SIGNAL(childViewIsDetachedNow(QWidget*)), this, SLOT(initKeyAccel(QWidget*)) ); + * + * m_pParent->addWindow( pMDICover, flags); + * // correct the default settings of KMdi ('cause we haven't a tab order for subwidget focuses) + * pMDICover->setFirstFocusableChildWidget(0L); + * pMDICover->setLastFocusableChildWidget(0L); + * } + * \endcode + * + */ + +class KMDI_EXPORT KMdiChildView : public QWidget +{ + friend class KMdiMainFrm; + friend class KMdiChildFrm; + Q_OBJECT + + // attributes +protected: + /** + * See KMdiChildView::caption + */ + QString m_szCaption; + + /** + * See KMdiChildView::tabCaption + */ + QString m_sTabCaption; + + /** + * See KMdiChildView::focusedChildWidget + */ + QWidget* m_focusedChildWidget; + + /** + * See KMdiChildView::setFirstFocusableChildWidget + */ + QWidget* m_firstFocusableChildWidget; + + /** + * See KMdiChildView::setLastFocusableChildWidget + */ + QWidget* m_lastFocusableChildWidget; + + /** + * Every child view window has an temporary ID in the Window menu of the main frame. + */ + int m_windowMenuID; + + /** + * Holds a temporary information about if the MDI view state has changed but is not processed yet (pending state). + * For example it could be that a 'maximize' is pending, if this variable is true. + */ + bool m_stateChanged; + + /** + * Holds the time when this view was activated (not only displayed) for the last time. + */ + QDateTime m_time; + +private: + /** + * Internally used as indicator whether this KMdiChildView is treated as document view or as tool view. + */ + bool m_bToolView; + + /** + * Internally used by KMdiMainFrm to store a temporary information that the method + * activate() is unnecessary and that it can by escaped. + * This saves from unnecessary calls when activate is called directly. + */ + bool m_bInterruptActivation; + + /** + * Internally used to prevent cycles between KMdiMainFrm::activateView() and KMdiChildView::activate(). + */ + bool m_bMainframesActivateViewIsPending; + + /** + * Internally used to check if there is a focus in event pending + */ + bool m_bFocusInEventIsPending; + + // methods +public: + /** + * Constructor + */ + KMdiChildView( const QString& caption, QWidget* parentWidget = 0L, const char* name = 0L, WFlags f = 0 ); + + /** + * Constructor + * sets "Unnamed" as default caption + */ + KMdiChildView( QWidget* parentWidget = 0L, const char* name = 0L, WFlags f = 0 ); + + /** + * Destructor + */ + ~KMdiChildView(); + + /** + * This method does the same as focusInEvent(). That's why it is a replacement for the setFocus() call. It makes + * sense if you for instance want to focus (I mean raise and activate) this view although the real focus is + * in another toplevel widget. focusInEvent() will never get called in that case and your setFocus() call for this + * widget would fail without any effect. + * Use this method with caution, it always raises the view and pushes the taskbar button. Also when the focus is + * still on another MDI view in the same toplevel window where this is located! + */ + void activate(); + + /** + * Memorizes the first focusable child widget of this widget + */ + void setFirstFocusableChildWidget( QWidget* ); + + /** + * Memorizes the last focusable child widget of this widget + */ + void setLastFocusableChildWidget( QWidget* ); + + /** + * Returns the current focused child widget of this widget + */ + QWidget* focusedChildWidget(); + + /** + * Returns true if the MDI view is a child window within the MDI mainframe widget + * or false if the MDI view is in toplevel mode + */ + bool isAttached() const { return ( mdiParent() != 0L ); } + + /** + * Returns the caption of the child window (different from the caption on the button in the taskbar) + */ + const QString& caption() const { return m_szCaption; } + + /** + * Returns the caption of the button on the taskbar + */ + const QString& tabCaption() const { return m_sTabCaption; } + + /** + * Sets the window caption string... + * Calls updateButton on the taskbar button if it has been set. + */ + virtual void setCaption( const QString& szCaption ); + + /** + * Sets the caption of the button referring to this window + */ + virtual void setTabCaption( const QString& caption ); + + /** + * Sets the caption of both the window and the button on the taskbar + */ + virtual void setMDICaption( const QString &caption ); + + /** + * Returns the KMdiChildFrm parent widget (or 0 if the window is not attached) + */ + KMdiChildFrm *mdiParent() const; + + /** + * Tells if the window is minimized when attached to the Mdi manager, + * or if it is VISIBLE when 'floating'. + */ + bool isMinimized() const; + + /** + * Tells if the window is minimized when attached to the Mdi manager, + * otherwise returns false. + */ + bool isMaximized() const; + + /** + * Returns the geometry of this MDI child window as QWidget::geometry() does. + */ + QRect internalGeometry() const; + + /** + * Sets the geometry of the client area of this MDI child window. The + * top left position of the argument is the position of the top left point + * of the client area in its parent coordinates and the arguments width + * and height is the width and height of the client area. Please note: This + * differs from the behavior of QWidget::setGeometry()! + */ + void setInternalGeometry( const QRect& newGeomety ); + + /** + * Returns the frame geometry of this window or of the parent if there is any... + */ + QRect externalGeometry() const; + + /** + * Sets the geometry of the frame of this MDI child window. The top left + * position of the argument is the position of the top left point of the + * frame in its parent coordinates and the arguments width and height is + * the width and height of the widget frame. Please note: This differs + * from the behavior of QWidget::setGeometry()! + */ + void setExternalGeometry( const QRect& newGeomety ); + + /** + * You should override this function in the derived class. + */ + virtual QPixmap* myIconPtr(); + + /** + * Minimizes this window when it is attached to the Mdi manager. + * Otherwise has no effect + */ + virtual void minimize( bool bAnimate ); + + /** + * Maximizes this window when it is attached to the Mdi manager. + * Otherwise has no effect + */ + virtual void maximize( bool bAnimate ); + + /** + * Returns the geometry that will be restored by calling restore(). + */ + QRect restoreGeometry(); + + /** + * Sets the geometry that will be restored by calling restore(). + */ + void setRestoreGeometry( const QRect& newRestGeo ); + + /** + * Switches interposing in event loop of all current child widgets off. + */ + void removeEventFilterForAllChildren(); + + /** + * Internally used for setting an ID for the 'Window' menu entry + */ + void setWindowMenuID( int id ); + + /** + * Sets the minimum size of the widget to w by h pixels. + * It extends it base clase method in a way that the minimum size of + * its childframe (if there is one) will be set, additionally. + */ + virtual void setMinimumSize ( int minw, int minh ); + + /** + * Sets the maximum size of the widget to w by h pixels. + * It extends it base clase method in a way that the maximum size of + * its childframe (if there is one) will be set, additionally. + */ + virtual void setMaximumSize ( int maxw, int maxh ); + + /** + * Returns if this is added as MDI tool-view + */ + inline bool isToolView() const { return m_bToolView; } + + /** + * Remember the current time + */ + inline void updateTimeStamp() + { + m_time.setDate( QDate::currentDate() ); + m_time.setTime( QTime::currentTime() ); + } + + /** + * Recall a previously remembered time, i.e. the value of m_time + */ + inline const QDateTime& getTimeStamp() const { return m_time; } + +public slots: + /** + * Attaches this window to the Mdi manager. + * It calls the KMdiMainFrm attachWindow function , so if you have a pointer + * to this KMdiMainFrm you'll be faster calling that function. + */ + virtual void attach(); + + /** + * Detaches this window from the Mdi manager. + * It calls the KMdiMainFrm detachWindow function , so if you have a pointer + * to this KMdiMainFrm you'll be faster calling that function. + */ + virtual void detach(); + + /** + * Mimimizes the MDI view. If attached, the covering childframe widget is minimized (only a mini widget + * showing the caption bar and the system buttons will remain visible). If detached, it will use the + * minimize of the underlying system ( QWidget::showMinimized ). + */ + virtual void minimize(); + + /** + * Maximizes the MDI view. If attached, this widget will fill the whole MDI view area widget. The system buttons + * move to the main menubar (if set by KMdiMainFrm::setMenuForSDIModeSysButtons ). + * If detached, it will use the minimize of the underlying system ( QWidget::showMaximized ). + */ + virtual void maximize(); + + /** + * Restores this window to its normal size. Also known as 'normalize'. + */ + virtual void restore(); + + /** + * Internally called, if KMdiMainFrm::attach is called. + * Actually, only the caption of the covering childframe is set. + */ + virtual void youAreAttached( KMdiChildFrm *lpC ); + + /** + * Internally called, if KMdiMainFrm::detach is called. + * Some things for going toplevel will be done here. + */ + virtual void youAreDetached(); + + /** + * Called if someone click on the "Window" menu item for this child frame window + */ + virtual void slot_clickedInWindowMenu(); + + /** + * Called if someone click on the "Dock/Undock..." menu item for this child frame window + */ + virtual void slot_clickedInDockMenu(); + + /** + * Calls QWidget::show but also for it's parent widget if attached + */ + virtual void show(); + + /** + * Calls QWidget::hide() or it's parent widget hide() if attached + */ + virtual void hide(); + + /** + * Calls QWidget::raise() or it's parent widget raise() if attached + */ + virtual void raise(); + + /** + * Overridden from its base class method. Emits a signal KMdiChildView::isMinimizedNow , additionally. + * Note that this method is not used by an external windows manager call on system minimizing. + */ + virtual void showMinimized(); + + /** + * Overridden from its base class method. Emits a signal KMdiChildView::isMaximizedNow , additionally. + * Note that this method is not used by an external windows manager call on system maximizing. + */ + virtual void showMaximized(); + + /** + * Overridden from its base class method. Emits a signal KMdiChildView::isRestoredNow , additionally. + * Note that this method is not used by an external windows manager call on system normalizing. + */ + virtual void showNormal(); + + +protected: + /** + * Ignores the event and calls KMdiMainFrm::childWindowCloseRequest instead. This is because the + * mainframe has control over the views. Therefore the MDI view has to request the mainframe for a close. + */ + virtual void closeEvent( QCloseEvent *e ); + + /** + * It only catches QEvent::KeyPress events there. If a Qt::Key_Tab is pressed, the internal MDI focus + * handling is called. That means if the last focusable child widget of this is called, it will jump to the + * first focusable child widget of this. + * See KMdiChildView::setFirstFocusableChildWidget and KMdiChildView::lastFirstFocusableChildWidget + */ + virtual bool eventFilter( QObject *obj, QEvent *e ); + + /** + * If attached, the childframe will be activated and the MDI taskbar button will be pressed. Additionally, the + * memorized old focused child widget of this is focused again. + * Sends the focusInEventOccurs signal before changing the focus and the + * gotFocus signal after changing the focus. + */ + virtual void focusInEvent( QFocusEvent *e ); + + /** + * Send the lostFocus signal + */ + virtual void focusOutEvent( QFocusEvent *e ); + + /** + * Internally used for the minimize/maximize/restore mechanism when in attach mode. + */ + virtual void resizeEvent( QResizeEvent *e ); + + void trackIconAndCaptionChanges( QWidget *view ); + +protected slots: + void slot_childDestroyed(); + +signals: + /** + * Internally used by KMdiChildView::attach to send it as command to the mainframe. + */ + void attachWindow( KMdiChildView*, bool ); + + /** + * Internally used by KMdiChildView::detach to send it as command to the mainframe. + */ + void detachWindow( KMdiChildView*, bool ); + + /** + * Is sent when this MDI child view is going to receive focus (before actually changing the focus). + * Internally used to send information to the mainframe that this MDI child view is focused. + * See KMdiChildView::focusInEvent + */ + void focusInEventOccurs( KMdiChildView* ); + + /** + * Is sent when this MDI child has received the focus (after actually changing the focus). + * See KMdiChildView::focusInEvent + */ + void gotFocus( KMdiChildView* ); + + /** + * Is sent when this MDI child was set to the activate view of all MDI views (after actually changing the focus). + * See KMdiChildView::activate + */ + void activated( KMdiChildView* ); + + /** Is sent when this MDI child view has lost the focus (after actually changing the focus). + * See KMdiChildView::focusOutEvent + */ + void lostFocus( KMdiChildView* ); + + /** Is sent when this MDI child view was deactivated (after actually changing the focus). + * See KMdiChildView::focusOutEvent + */ + void deactivated( KMdiChildView* ); + + /** + * Internally used to send information to the mainframe that this MDI child view wants to be closed. + * See KMdiChildView::closeEvent and KMdiMainFrm::closeWindow + */ + void childWindowCloseRequest( KMdiChildView* ); + + /** + * Emitted when the window caption is changed via KMdiChildView::setCaption or KMdiChildView::setMDICaption + */ + void windowCaptionChanged( const QString& ); + + /** + * Emitted when the window caption is changed via KMdiChildView::setTabCaption or KMdiChildView::setMDICaption + */ + void tabCaptionChanged( const QString& ); + + /** + * Internally used to send information to the mainframe that this MDI view is maximized now. + * Usually, the mainframe switches system buttons. + */ + void mdiParentNowMaximized( bool ); + + /** + * Is automatically emitted when slot_clickedInWindowMenu is called + */ + void clickedInWindowMenu( int ); + + /** + * Is automatically emitted when slot_clickedInDockMenu is called + */ + void clickedInDockMenu( int ); + + /** + * Signals this has been maximized + */ + void isMaximizedNow(); + + /** + * Signals this has been minimized + */ + void isMinimizedNow(); + + /** + * Signals this has been restored (normalized) + */ + void isRestoredNow(); + + /** + * Signals this has been attached + */ + void isAttachedNow(); + + /** + * Signals this has been detached + */ + void isDetachedNow(); + + void iconUpdated( QWidget*, QPixmap ); + void captionUpdated( QWidget*, const QString& ); + + +private: + KMdiChildViewPrivate *d; + QWidget *m_trackChanges; +}; + +inline KMdiChildFrm *KMdiChildView::mdiParent() const +{ + QWidget * pw = parentWidget(); + if ( pw != 0L ) + if ( pw->inherits( "KMdiChildFrm" ) ) + return ( KMdiChildFrm * ) pw; + return 0L; +} + +#endif //_KMDICHILDVIEW_H_ + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/kmdi/kmdidefines.h b/kmdi/kmdidefines.h new file mode 100644 index 000000000..503432352 --- /dev/null +++ b/kmdi/kmdidefines.h @@ -0,0 +1,117 @@ +//---------------------------------------------------------------------------- +// filename : kmdidefines.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- +#ifndef _KMDI_DEFINES_H_ +#define _KMDI_DEFINES_H_ + +#include <kdelibs_export.h> + +#define KMDI_CHILDFRM_SEPARATOR 2 +#define KMDI_CHILDFRM_BORDER 4 +#define KMDI_CHILDFRM_DOUBLE_BORDER 8 +#define KMDI_CHILDFRM_MIN_WIDTH 130 + +//---------------------------------------------------------------------------- +/** +* @short A namespace for the KMDI library +*/ +namespace KMdi +{ + /** extent Qt events + @see QCustomEvent, QEvent::User + \code + bool B_MyWidget::event( QEvent* e) { + if( e->type() == QEvent::Type(QEvent::User + int(KMdi::EV_Move))) { + ... + } + ... + } + \endcode + */ + enum EventType { + EV_Move=1, + EV_DragBegin, + EV_DragEnd, + EV_ResizeBegin, + EV_ResizeEnd + }; + + /** + * During KMdiMainFrm::addWindow the enum AddWindowFlags is used to determine how the view is initialy being added to the MDI system + */ + enum AddWindowFlags { + /** + * standard is: show normal, attached, visible, document view (not toolview). Maximize, Minimize, Hide adds + * appropriately. Detach adds a view that appears toplevel, ToolWindow adds the view as tool view. + * That means it is stay-on-top and toplevel. UseKMdiSizeHint should use the restore geometry of the + * latest current top childframe but is not supported yet. + */ + StandardAdd = 0, + Maximize = 1, + Minimize = 2, + Hide = 4, + Detach = 8, + ToolWindow = 16, + UseKMdiSizeHint = 32, + AddWindowFlags = 0xff + }; + + enum FrameDecor { + Win95Look = 0, + KDE1Look = 1, + KDELook = 2, + KDELaptopLook = 3 + }; + + enum MdiMode { + UndefinedMode = 0, + ToplevelMode = 1, + ChildframeMode = 2, + TabPageMode = 3, + IDEAlMode = 4 + }; + + enum TabWidgetVisibility { + AlwaysShowTabs = 0, + ShowWhenMoreThanOneTab = 1, + NeverShowTabs = 2 + }; + + /** + * The style of the toolview tabs + * \since 3.3 + */ + enum ToolviewStyle { + /** Show only icons on the toolview tabs. The visible toolviews contain both the icon and text. */ + IconOnly = 0, + /** Show only the text description on the toolview tabs. */ + TextOnly = 1, + /** Show both the icon and description on the toolview tabs. */ + TextAndIcon = 3 + }; +} //namespace + +#endif //_KMDIDEFINES_H_ diff --git a/kmdi/kmdidockcontainer.cpp b/kmdi/kmdidockcontainer.cpp new file mode 100644 index 000000000..dd9c32b4d --- /dev/null +++ b/kmdi/kmdidockcontainer.cpp @@ -0,0 +1,859 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kmdimainfrm.h" +#include "kmdidockcontainer.h" +#include "kmdidockcontainer.moc" + +#include "kdockwidget_private.h" + +#include <qwidgetstack.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <kmultitabbar.h> +#include <kglobalsettings.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <kapplication.h> +#include <kconfig.h> +#include <klocale.h> + +//TODO: Well, this is already defined in kdeui/kdockwidget.cpp +static const char* const kmdi_not_close_xpm[] = + { + "5 5 2 1", + "# c black", + ". c None", + "#####", + "#...#", + "#...#", + "#...#", + "#####" + }; + +KMdiDockContainer::KMdiDockContainer( QWidget *parent, QWidget *win, int position, int flags ) + : QWidget( parent ), KDockContainer() +{ + m_tabSwitching = false; + m_block = false; + m_inserted = -1; + m_mainWin = win; + oldtab = -1; + mTabCnt = 0; + m_position = position; + m_previousTab = -1; + m_separatorPos = 18000; + m_movingState = NotMoving; + m_startEvent = 0; + kdDebug( 760 ) << k_funcinfo << endl; + + QBoxLayout *l; + m_horizontal = ( ( position == KDockWidget::DockTop ) || ( position == KDockWidget::DockBottom ) ); + + + if ( m_horizontal ) + l = new QVBoxLayout( this ); //vertical layout for top and bottom docks + else + l = new QHBoxLayout( this ); //horizontal layout for left and right docks + + l->setAutoAdd( false ); + + m_tb = new KMultiTabBar( m_horizontal ? KMultiTabBar::Horizontal : KMultiTabBar::Vertical, this ); + + m_tb->setStyle( KMultiTabBar::KMultiTabBarStyle( flags ) ); + m_tb->showActiveTabTexts( true ); + + KMultiTabBar::KMultiTabBarPosition kmtbPos; + switch( position ) + { + case KDockWidget::DockLeft: + kmtbPos = KMultiTabBar::Left; + break; + case KDockWidget::DockRight: + kmtbPos = KMultiTabBar::Right; + break; + case KDockWidget::DockTop: + kmtbPos = KMultiTabBar::Top; + break; + case KDockWidget::DockBottom: + kmtbPos = KMultiTabBar::Bottom; + break; + default: + kmtbPos = KMultiTabBar::Right; + break; + } + m_tb->setPosition( kmtbPos ); + + m_ws = new QWidgetStack( this ); + + m_ws->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + //layout the tabbar + if ( position == KDockWidget::DockLeft || position == KDockWidget::DockTop ) + { + //add the tabbar then the widget stack + l->add( m_tb ); + l->add( m_ws ); + } + else + { + //add the widget stack then the tabbar + l->add( m_ws ); + l->add( m_tb ); + } + + l->activate(); + m_ws->hide(); + +} + +void KMdiDockContainer::setStyle( int style ) +{ + if ( m_tb ) + m_tb->setStyle( KMultiTabBar::KMultiTabBarStyle( style ) ); +} + +KMdiDockContainer::~KMdiDockContainer() +{ + QMap<KDockWidget*, int>::iterator it; + while ( m_map.count() ) + { + it = m_map.begin(); + KDockWidget *w = it.key(); + if ( m_overlapButtons.contains( w ) ) + { + ( static_cast<KDockWidgetHeader*>( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ) )->removeButton( m_overlapButtons[w] ); + m_overlapButtons.remove( w ); + } + m_map.remove( w ); + w->undock(); + } + deactivated( this ); +} + + +void KMdiDockContainer::init() +{ + bool overlap = isOverlapMode(); + kdDebug( 760 ) << k_funcinfo << endl; + if ( !m_horizontal ) + { + kdDebug( 760 ) << k_funcinfo << "Horizontal tabbar. Setting forced fixed width." << endl; + parentDockWidget()->setForcedFixedWidth( m_tb->width() ); + activateOverlapMode( m_tb->width() ); + } + else + { + kdDebug( 760 ) << k_funcinfo << "Vertical tabbar. Setting forced fixed height." << endl; + parentDockWidget()->setForcedFixedHeight( m_tb->height() ); + activateOverlapMode( m_tb->height() ); + } + + if (!overlap) deactivateOverlapMode(); + + // try to restore splitter size + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter * sp = static_cast<KDockSplitter*>( parentDockWidget()->parent()->qt_cast( "KDockSplitter" ) ); + if ( sp ) + sp->setSeparatorPosX( m_separatorPos ); + } +} + +KDockWidget* KMdiDockContainer::parentDockWidget() +{ + return ( ( KDockWidget* ) parent() ); +} + +void KMdiDockContainer::insertWidget ( KDockWidget *dwdg, QPixmap pixmap, const QString &text, int & ) +{ + kdDebug( 760 ) << k_funcinfo << "Adding a dockwidget to the dock container" << endl; + KDockWidget* w = dwdg; + int tab; + bool alreadyThere = m_map.contains( w ); + + if ( alreadyThere ) + { + tab = m_map[ w ]; + if ( m_ws->addWidget( w, tab ) != tab ) + kdDebug( 760 ) << "ERROR COULDN'T READD WIDGET" << endl; + + kdDebug( 760 ) << k_funcinfo << "Readded widget " << dwdg << endl; + } + else + { + tab = m_ws->addWidget( w ); + m_map.insert( w, tab ); + m_revMap.insert( tab, w ); + + if ( ( ( KDockWidget* ) parentWidget() ) ->mayBeShow() ) + ( ( KDockWidget* ) parentWidget() ) ->dockBack(); + + if ( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ) + { + kdDebug( 760 ) << k_funcinfo << "The dockwidget we're adding has a header" << endl; + kdDebug( 760 ) << k_funcinfo << "Adding our overlap mode button to it" << endl; + + KDockWidgetHeader *hdr = static_cast<KDockWidgetHeader*>( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ); + KDockButton_Private *btn = new KDockButton_Private( hdr, "OverlapButton" ); + + QToolTip::add( btn, i18n( "Switch between overlap and side by side mode", "Overlap" ) ); + + btn->setToggleButton( true ); + btn->setPixmap( const_cast< const char** >( kmdi_not_close_xpm ) ); + hdr->addButton( btn ); + m_overlapButtons.insert( w, btn ); + btn->setOn( !isOverlapMode() ); + + connect( btn, SIGNAL( clicked() ), this, SLOT( changeOverlapMode() ) ); + } + + m_tb->appendTab( pixmap.isNull() ? SmallIcon( "misc" ) : pixmap, tab, w->tabPageLabel() ); + m_tb->tab( tab )->installEventFilter( this ); + kdDebug( 760 ) << k_funcinfo << "Added tab with label " << w->tabPageLabel() << + " to the tabbar" << endl; + + connect( m_tb->tab( tab ), SIGNAL( clicked( int ) ), this, SLOT( tabClicked( int ) ) ); + + mTabCnt++; + m_inserted = tab; + int dummy = 0; + KDockContainer::insertWidget( w, pixmap, text, dummy ); + itemNames.append( w->name() ); + tabCaptions.insert( w->name(), w->tabPageLabel() ); + tabTooltips.insert( w->name(), w->toolTipString() ); + } + + //FB m_ws->raiseWidget(tab); +} + + +bool KMdiDockContainer::eventFilter( QObject *obj, QEvent *event ) +{ + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + KMultiTabBarTab* kmtbTab = dynamic_cast<KMultiTabBarTab*>( obj ); + if ( !kmtbTab ) + { + kdDebug(760) << k_funcinfo << "Got a mouse button press but we have no tab" << endl; + break; + } + + KDockWidget* w = m_revMap[ kmtbTab->id() ]; + if ( !w ) + { + kdDebug(760) << k_funcinfo << "Got a mouse button press but we have no widget" << endl; + break; + } + + if ( !w->getHeader() ) + { + kdDebug(760) << k_funcinfo << "Got a mouse button press but we have no header" << endl; + break; + } + + KDockWidgetHeader *hdr = static_cast<KDockWidgetHeader*>( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ); + if ( !hdr ) + { + kdDebug(760) << "Wrong header type in KMdiDockContainer::eventFilter" << endl; + break; + } + + m_dockManager = w->dockManager(); + m_dragPanel = hdr->dragPanel(); + + if ( m_dragPanel ) + m_movingState = WaitingForMoveStart; + + delete m_startEvent; + m_startEvent = new QMouseEvent( * ( ( QMouseEvent* ) event ) ); + } + break; + case QEvent::MouseButtonRelease: + if ( m_movingState == Moving ) + { + m_movingState = NotMoving; + QApplication::postEvent( m_dragPanel, new QMouseEvent( * ( ( QMouseEvent* ) event ) ) ); + delete m_startEvent; + m_startEvent = 0; + } + case QEvent::MouseMove: + if ( m_movingState == WaitingForMoveStart ) + { + QPoint p( ( ( QMouseEvent* ) event )->pos() - m_startEvent->pos() ); + if ( p.manhattanLength() > KGlobalSettings::dndEventDelay() ) + { + m_dockManager->eventFilter( m_dragPanel, m_startEvent ); + m_dockManager->eventFilter( m_dragPanel, event ); + m_movingState = Moving; + } + } + else if ( m_movingState == Moving ) + m_dockManager->eventFilter( m_dragPanel, event ); + + break; + default: + break; + + } + return false; + +} + +void KMdiDockContainer::showWidget( KDockWidget *w ) +{ + if ( !m_map.contains( w ) ) + return ; + + int id = m_map[ w ]; + m_tb->setTab( id, true ); + tabClicked( id ); +} + +void KMdiDockContainer::changeOverlapMode() +{ + const KDockButton_Private * btn = dynamic_cast<const KDockButton_Private*>( sender() ); + + if ( !btn ) + return ; + + if ( !btn->isOn() ) + { + kdDebug( 760 ) << k_funcinfo << "Activating overlap mode" << endl; + if ( !m_horizontal ) + activateOverlapMode( m_tb->width() ); + else + activateOverlapMode( m_tb->height() ); + + } + else + { + kdDebug( 760 ) << k_funcinfo << "Deactivating overlap mode" << endl; + deactivateOverlapMode(); + } + + QMap<KDockWidget*, KDockButton_Private*>::iterator it; + for ( it = m_overlapButtons.begin(); it != m_overlapButtons.end(); ++it ) + it.data()->setOn( !isOverlapMode() ); +} + +void KMdiDockContainer::hideIfNeeded() +{ + if ( itemNames.count() == 0 ) + { + kdDebug( 760 ) << k_funcinfo << "Hiding the dock container" << endl; + ( ( KDockWidget* ) parentWidget() )->undock(); + } +} + +void KMdiDockContainer::removeWidget( KDockWidget* dwdg ) +{ + KDockWidget * w = dwdg; + if ( !m_map.contains( w ) ) + return; //we don't have this widget in our container + + kdDebug( 760 ) << k_funcinfo << endl; + //lower the tab. ( TODO: needed? ) + int id = m_map[ w ]; + if ( m_tb->isTabRaised( id ) ) + { + m_tb->setTab( id, false ); + tabClicked( id ); + } + + m_tb->removeTab( id ); + m_ws->removeWidget( w ); + m_map.remove( w ); + m_revMap.remove( id ); + if ( m_overlapButtons.contains( w ) ) + { + ( static_cast<KDockWidgetHeader*>( w->getHeader() ->qt_cast( "KDockWidgetHeader" ) ) )->removeButton( m_overlapButtons[ w ] ); + m_overlapButtons.remove( w ); + } + KDockContainer::removeWidget( w ); + itemNames.remove( w->name() ); + tabCaptions.remove( w->name() ); + tabTooltips.remove( w->name() ); + hideIfNeeded(); +} + +void KMdiDockContainer::undockWidget( KDockWidget *dwdg ) +{ + KDockWidget * w = dwdg; + + if ( !m_map.contains( w ) ) + return ; + + int id = m_map[ w ]; + if ( m_tb->isTabRaised( id ) ) + { + kdDebug( 760 ) << k_funcinfo << "Widget has been undocked, setting tab down" << endl; + m_tb->setTab( id, false ); + tabClicked( id ); + } +} + +void KMdiDockContainer::tabClicked( int t ) +{ + bool call_makeVisible = !m_tabSwitching; + m_tabSwitching = true; + if ( m_tb->isTabRaised( t ) ) + { + kdDebug( 760 ) << k_funcinfo << "Tab " << t << " was just activated" << endl; + if ( m_ws->isHidden() ) + { + kdDebug( 760 ) << k_funcinfo << "Showing widgetstack for tab just clicked" << endl; + m_ws->show(); + parentDockWidget()->restoreFromForcedFixedSize(); + } + + if ( !m_ws->widget( t ) ) + { + kdDebug( 760 ) << k_funcinfo << "Widget tab was clicked for is not in our stack" << endl; + kdDebug( 760 ) << k_funcinfo << "Docking it back in" << endl; + m_revMap[t]->manualDock( parentDockWidget(), KDockWidget::DockCenter, 20 ); + if ( call_makeVisible ) + m_revMap[t]->makeDockVisible(); + m_tabSwitching = false; + emit activated( this ); + return ; + } + + if ( m_ws->widget( t ) ) + { + m_ws->raiseWidget( t ); + KDockWidget * tmpDw = static_cast<KDockWidget*>( m_ws->widget( t )->qt_cast( "KDockWidget" ) ); + if ( tmpDw ) + { + if ( tmpDw->getWidget() ) + tmpDw->getWidget()->setFocus(); + } + else + kdDebug( 760 ) << k_funcinfo << "Something really weird is going on" << endl; + } + else + kdDebug( 760 ) << k_funcinfo << "We have no widget to handle in our stack." << endl; + + if ( oldtab != t ) + m_tb->setTab( oldtab, false ); + + m_tabSwitching = true; + oldtab = t; + emit activated( this ); + } + else + { + kdDebug( 760 ) << k_funcinfo << "Tab " << t << " was just deactiviated" << endl; + // try save splitter position + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter * sp = static_cast<KDockSplitter*>( parentDockWidget()->parent()->qt_cast( "KDockSplitter" ) ); + if ( sp ) + m_separatorPos = sp->separatorPos(); + } + m_previousTab = t; + // oldtab=-1; + if ( m_block ) + return ; + emit deactivated( this ); + m_block = true; + if ( m_ws->widget( t ) ) + { + // ((KDockWidget*)m_ws->widget(t))->undock(); + } + m_block = false; + m_ws->hide (); + + + kdDebug( 760 ) << k_funcinfo << "Fixed Width:" << m_tb->width() << endl; + if ( !m_horizontal ) + parentDockWidget()->setForcedFixedWidth( m_tb->width() ); // strange why it worked before at all + else + parentDockWidget()->setForcedFixedHeight( m_tb->height() ); // strange why it worked before at all + } + m_tabSwitching = false; +} + +void KMdiDockContainer::setToolTip ( KDockWidget* w, QString &s ) +{ + kdDebug( 760 ) << k_funcinfo << "Setting tooltip '" << s << "' for widget " << w << endl; + int tabId = m_map[w]; + KMultiTabBarTab *mbTab = m_tb->tab( tabId ); + QToolTip::remove( mbTab ); + QToolTip::add( mbTab, s ); +} + +void KMdiDockContainer::setPixmap( KDockWidget* widget , const QPixmap& pixmap ) +{ + int id = m_ws->id( widget ); + if ( id == -1 ) + return ; + KMultiTabBarTab *tab = m_tb->tab( id ); + tab->setIcon( pixmap.isNull() ? SmallIcon( "misc" ) : pixmap ); +} + +void KMdiDockContainer::save( QDomElement& dockEl ) +{ + QDomDocument doc = dockEl.ownerDocument(); + QDomElement el; + el = doc.createElement( "name" ); + el.appendChild( doc.createTextNode( QString( "%1" ).arg( parent() ->name() ) ) ); + dockEl.appendChild( el ); + el = doc.createElement( "overlapMode" ); + el.appendChild( doc.createTextNode( isOverlapMode() ? "true" : "false" ) ); + dockEl.appendChild( el ); + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it( *tl ); + QStringList::Iterator it2 = itemNames.begin(); + int i = 0; + for ( ;it.current() != 0;++it, ++it2 ) + { + el = doc.createElement( "child" ); + el.setAttribute( "pos", QString( "%1" ).arg( i ) ); + QString s = tabCaptions[ *it2 ]; + if ( !s.isEmpty() ) + { + el.setAttribute( "tabCaption", s ); + } + s = tabTooltips[ *it2 ]; + if ( !s.isEmpty() ) + { + el.setAttribute( "tabTooltip", s ); + } + el.appendChild( doc.createTextNode( *it2 ) ); + dockEl.appendChild( el ); + if ( m_tb->isTabRaised( it.current() ->id() ) ) + { + QDomElement el2 = doc.createElement( "raised" ); + el2.appendChild( doc.createTextNode( m_ws->widget( it.current() ->id() ) ->name() ) ); + el.appendChild( el2 ); + } + ++i; + } + + +} + +void KMdiDockContainer::load( QDomElement& dockEl ) +{ + QString raise; + + for ( QDomNode n = dockEl.firstChild();!n.isNull();n = n.nextSibling() ) + { + QDomElement el = n.toElement(); + if ( el.isNull() ) + continue; + if ( el.tagName() == "overlapMode" ) + { + if ( el.attribute( "overlapMode" ) != "false" ) + activateOverlapMode( m_horizontal?m_tb->height():m_tb->width() ); + else + deactivateOverlapMode(); + } + else if ( el.tagName() == "child" ) + { + KDockWidget * dw = ( ( KDockWidget* ) parent() ) ->dockManager() ->getDockWidgetFromName( el.text() ); + if ( dw ) + { + if ( el.hasAttribute( "tabCaption" ) ) + { + dw->setTabPageLabel( el.attribute( "tabCaption" ) ); + } + if ( el.hasAttribute( "tabTooltip" ) ) + { + dw->setToolTipString( el.attribute( "tabTooltip" ) ); + } + dw->manualDock( ( KDockWidget* ) parent(), KDockWidget::DockCenter ); + } + } + } + + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it1( *tl ); + m_ws->hide(); + if ( !m_horizontal ) + parentDockWidget()->setForcedFixedWidth( m_tb->width() ); + else + parentDockWidget()->setForcedFixedHeight( m_tb->height() ); + + for ( ;it1.current() != 0;++it1 ) + m_tb->setTab( it1.current() ->id(), false ); + + kapp->syncX(); + m_delayedRaise = -1; + + for ( QMap<KDockWidget*, KDockButton_Private*>::iterator it = m_overlapButtons.begin(); + it != m_overlapButtons.end();++it ) + it.data() ->setOn( !isOverlapMode() ); + + if ( !raise.isEmpty() ) + { + for ( QMap<KDockWidget*, int>::iterator it = m_map.begin();it != m_map.end();++it ) + { + if ( it.key() ->name() == raise ) + { + m_delayedRaise = it.data(); + QTimer::singleShot( 0, this, SLOT( delayedRaise() ) ); + kdDebug( 760 ) << k_funcinfo << "raising " << it.key()->name() << endl; + break; + } + } + + } + if ( m_delayedRaise == -1 ) + QTimer::singleShot( 0, this, SLOT( init() ) ); +} + +void KMdiDockContainer::save( KConfig* cfg, const QString& group_or_prefix ) +{ + QString grp = cfg->group(); + cfg->deleteGroup( group_or_prefix + QString( "::%1" ).arg( parent() ->name() ) ); + cfg->setGroup( group_or_prefix + QString( "::%1" ).arg( parent() ->name() ) ); + + if ( isOverlapMode() ) + cfg->writeEntry( "overlapMode", "true" ); + else + cfg->writeEntry( "overlapMode", "false" ); + + // try to save the splitter position + if ( parentDockWidget() && parentDockWidget() ->parent() ) + { + KDockSplitter * sp = static_cast<KDockSplitter*>( parentDockWidget() -> + parent() ->qt_cast( "KDockSplitter" ) ); + if ( sp ) + cfg->writeEntry( "separatorPosition", m_separatorPos ); + } + + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it( *tl ); + QStringList::Iterator it2 = itemNames.begin(); + int i = 0; + for ( ;it.current() != 0;++it, ++it2 ) + { + // cfg->writeEntry(QString("widget%1").arg(i),m_ws->widget(it.current()->id())->name()); + cfg->writeEntry( QString( "widget%1" ).arg( i ), ( *it2 ) ); + QString s = tabCaptions[ *it2 ]; + if ( !s.isEmpty() ) + { + cfg->writeEntry( QString( "widget%1-tabCaption" ).arg( i ), s ); + } + s = tabTooltips[ *it2 ]; + if ( !s.isEmpty() ) + { + cfg->writeEntry( QString( "widget%1-tabTooltip" ).arg( i ), s ); + } + // kdDebug(760)<<"****************************************Saving: "<<m_ws->widget(it.current()->id())->name()<<endl; + if ( m_tb->isTabRaised( it.current() ->id() ) ) + cfg->writeEntry( m_ws->widget( it.current() ->id() ) ->name(), true ); + ++i; + } + cfg->sync(); + cfg->setGroup( grp ); + +} + +void KMdiDockContainer::load( KConfig* cfg, const QString& group_or_prefix ) +{ + QString grp = cfg->group(); + cfg->setGroup( group_or_prefix + QString( "::%1" ).arg( parent() ->name() ) ); + + if ( cfg->readEntry( "overlapMode" ) != "false" ) + activateOverlapMode( m_horizontal?m_tb->height():m_tb->width() ); + else + deactivateOverlapMode(); + + m_separatorPos = cfg->readNumEntry( "separatorPosition", 18000 ); + + int i = 0; + QString raise; + while ( true ) + { + QString dwn = cfg->readEntry( QString( "widget%1" ).arg( i ) ); + if ( dwn.isEmpty() ) + break; + kdDebug( 760 ) << k_funcinfo << "configuring dockwidget :" << dwn << endl; + KDockWidget *dw = ( ( KDockWidget* ) parent() ) ->dockManager() ->getDockWidgetFromName( dwn ); + if ( dw ) + { + QString s = cfg->readEntry( QString( "widget%1-tabCaption" ).arg( i ) ); + if ( !s.isEmpty() ) + { + dw->setTabPageLabel( s ); + } + s = cfg->readEntry( QString( "widget%1-tabTooltip" ).arg( i ) ); + if ( !s.isEmpty() ) + { + dw->setToolTipString( s ); + } + dw->manualDock( ( KDockWidget* ) parent(), KDockWidget::DockCenter ); + } + if ( cfg->readBoolEntry( dwn, false ) ) + raise = dwn; + i++; + + } + + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it1( *tl ); + m_ws->hide(); + if ( !m_horizontal ) + parentDockWidget() ->setForcedFixedWidth( m_tb->width() ); + else + parentDockWidget() ->setForcedFixedHeight( m_tb->height() ); + for ( ;it1.current() != 0;++it1 ) + { + m_tb->setTab( it1.current() ->id(), false ); + } + kapp->syncX(); + m_delayedRaise = -1; + + for ( QMap<KDockWidget*, KDockButton_Private*>::iterator it = m_overlapButtons.begin(); + it != m_overlapButtons.end();++it ) + it.data() ->setOn( !isOverlapMode() ); + + if ( !raise.isEmpty() ) + { + for ( QMap<KDockWidget*, int>::iterator it = m_map.begin();it != m_map.end();++it ) + { + if ( it.key() ->name() == raise ) + { + /* tabClicked(it.data()); + m_tb->setTab(it.data(),true); + tabClicked(it.data()); + m_ws->raiseWidget(it.key()); + kapp->sendPostedEvents(); + kapp->syncX();*/ + + m_delayedRaise = it.data(); + QTimer::singleShot( 0, this, SLOT( delayedRaise() ) ); + kdDebug( 760 ) << k_funcinfo << "raising" << it.key() ->name() << endl; + break; + } + } + + } + if ( m_delayedRaise == -1 ) + QTimer::singleShot( 0, this, SLOT( init() ) ); + cfg->setGroup( grp ); + +} + +void KMdiDockContainer::delayedRaise() +{ + m_tb->setTab( m_delayedRaise, true ); + tabClicked( m_delayedRaise ); +} + +void KMdiDockContainer::collapseOverlapped() +{ + //don't collapse if we're switching tabs + if ( m_tabSwitching ) + return; + + if ( isOverlapMode() ) + { + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it( *tl ); + for ( ;it.current();++it ) + { + if ( it.current()->isOn() ) + { + kdDebug( 760 ) << k_funcinfo << "lowering tab with id " << ( *it )->id() << endl; + it.current()->setState( false ); + tabClicked( ( *it )->id() ); + } + } + } +} + +void KMdiDockContainer::toggle() +{ + kdDebug( 760 ) << k_funcinfo << endl; + + if ( m_tb->isTabRaised( oldtab ) ) + { + kdDebug( 760 ) << k_funcinfo << "lowering tab" << endl; + m_tb->setTab( oldtab, false ); + tabClicked( oldtab ); + KMdiMainFrm *mainFrm = dynamic_cast<KMdiMainFrm*>( m_mainWin ); + if ( mainFrm && mainFrm->activeWindow() ) + mainFrm->activeWindow()->setFocus(); + } + else + { + kdDebug( 760 ) << k_funcinfo << "raising tab" << endl; + if ( m_tb->tab( m_previousTab ) == 0 ) + { + if ( m_tb->tabs() ->count() == 0 ) + return ; + + m_previousTab = m_tb->tabs() ->getFirst() ->id(); + } + m_tb->setTab( m_previousTab, true ); + tabClicked( m_previousTab ); + } +} + +void KMdiDockContainer::prevToolView() +{ + kdDebug( 760 ) << k_funcinfo << endl; + QPtrList<KMultiTabBarTab>* tabs = m_tb->tabs(); + int pos = tabs->findRef( m_tb->tab( oldtab ) ); + + if ( pos == -1 ) + return ; + + pos--; + if ( pos < 0 ) + pos = tabs->count() - 1; + + KMultiTabBarTab *tab = tabs->at( pos ); + if ( !tab ) + return ; //can never happen here, but who knows + + m_tb->setTab( tab->id(), true ); + tabClicked( tab->id() ); +} + +void KMdiDockContainer::nextToolView() +{ + kdDebug( 760 ) << k_funcinfo << endl; + QPtrList<KMultiTabBarTab>* tabs = m_tb->tabs(); + int pos = tabs->findRef( m_tb->tab( oldtab ) ); + + if ( pos == -1 ) + return ; + + pos++; + if ( pos >= ( int ) tabs->count() ) + pos = 0; + + KMultiTabBarTab *tab = tabs->at( pos ); + if ( !tab ) + return ; //can never happen here, but who knows + + m_tb->setTab( tab->id(), true ); + tabClicked( tab->id() ); +} + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdidockcontainer.h b/kmdi/kmdidockcontainer.h new file mode 100644 index 000000000..917dac4d0 --- /dev/null +++ b/kmdi/kmdidockcontainer.h @@ -0,0 +1,167 @@ + /* This file is part of the KDE project + Copyright (C) 2002 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _KMDI_DOCK_CONTAINER_ +#define _KMDI_DOCK_CONTAINER_ + +#include <qwidget.h> +#include <qstringlist.h> +#include <kdockwidget.h> +#include <qmap.h> +#include <qdom.h> + +# include <kdockwidget_p.h> + +#include <qpushbutton.h> + +class QWidgetStack; +class KMultiTabBar; +class KDockButton_Private; + +class KMDI_EXPORT KMdiDockContainer: public QWidget, public KDockContainer +{ + Q_OBJECT + +public: + KMdiDockContainer( QWidget *parent, QWidget *win, int position, int flags ); + virtual ~KMdiDockContainer(); + + /** Get the KDockWidget that is our parent */ + KDockWidget *parentDockWidget(); + + /** + * Add a widget to this container + * \param w the KDockWidget we are adding + */ + virtual void insertWidget ( KDockWidget *w, QPixmap, const QString &, int & ); + + /** + * Show a widget. + * + * The widget has to belong to this container otherwise + * it will not be shown + * \param w the KDockWidget to show + */ + virtual void showWidget ( KDockWidget *w ); + + /** + * Set the tooltip for the widget. + * Currently, this method does nothing + */ + virtual void setToolTip ( KDockWidget *, QString & ); + + /** + * Set the pixmap for the widget. + */ + virtual void setPixmap( KDockWidget* widget, const QPixmap& pixmap ); + + /** + * Undock the widget from the container. + */ + virtual void undockWidget( KDockWidget* dwdg ); + + /** + * Remove a widget from the container. The caller of this function + * is responsible for deleting the widget + */ + virtual void removeWidget( KDockWidget* ); + + /** + * Hide the the dock container if the number of items is 0 + */ + void hideIfNeeded(); + + /** + * Save the config using a KConfig object + * + * The combination of the group_or_prefix variable and the parent + * dockwidget's name will be the group the configuration is saved in + * \param group_or_prefix the prefix to append to the parent dockwidget's name + */ + virtual void save( KConfig *, const QString& group_or_prefix ); + + /** + * Load the config using a KConfig object + * + * The combination of the group_or_prefix variable and the parent + * dockwidget's name will be the group the configuration is loaded from + * \param group_or_prefix the prefix to append to the parent dockwidget's name + */ + virtual void load( KConfig *, const QString& group_or_prefix ); + + /** + * Save the config to a QDomElement + */ + virtual void save( QDomElement& ); + + /** + * Load the config from a QDomElement + */ + virtual void load( QDomElement& ); + + /** + * Set the style for the tabbar + */ + void setStyle( int ); + +protected: + bool eventFilter( QObject*, QEvent* ); + +public slots: + void init(); + void collapseOverlapped(); + void toggle(); + void nextToolView(); + void prevToolView(); +protected slots: + void tabClicked( int ); + void delayedRaise(); + void changeOverlapMode(); +private: + QWidget *m_mainWin; + QWidgetStack *m_ws; + KMultiTabBar *m_tb; + int mTabCnt; + int oldtab; + int m_previousTab; + int m_position; + int m_separatorPos; + QMap<KDockWidget*, int> m_map; + QMap<int, KDockWidget*> m_revMap; + QMap<KDockWidget*, KDockButton_Private*> m_overlapButtons; + QStringList itemNames; + QMap<QString, QString> tabCaptions; + QMap<QString, QString> tabTooltips; + int m_inserted; + int m_delayedRaise; + bool m_horizontal; + bool m_block; + bool m_tabSwitching; + QObject *m_dragPanel; + KDockManager *m_dockManager; + QMouseEvent *m_startEvent; + enum MovingState {NotMoving = 0, WaitingForMoveStart, Moving} m_movingState; +signals: + void activated( KMdiDockContainer* ); + void deactivated( KMdiDockContainer* ); +}; + +#endif + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdidocumentviewtabwidget.cpp b/kmdi/kmdidocumentviewtabwidget.cpp new file mode 100644 index 000000000..2e2e9b87e --- /dev/null +++ b/kmdi/kmdidocumentviewtabwidget.cpp @@ -0,0 +1,148 @@ +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#include <qtimer.h> + +#include <ktabbar.h> +#include <kpopupmenu.h> +#include "kmdidocumentviewtabwidget.h" + +KMdiDocumentViewTabWidget::KMdiDocumentViewTabWidget( QWidget* parent, const char* name ) : KTabWidget( parent, name ) +{ + m_visibility = KMdi::ShowWhenMoreThanOneTab; + tabBar() ->hide(); + setHoverCloseButton( true ); + connect( this, SIGNAL( closeRequest( QWidget* ) ), this, SLOT( closeTab( QWidget* ) ) ); +} + +KMdiDocumentViewTabWidget::~KMdiDocumentViewTabWidget() +{} + +void KMdiDocumentViewTabWidget::closeTab( QWidget* w ) +{ + w->close(); +} +void KMdiDocumentViewTabWidget::addTab ( QWidget * child, const QString & label ) +{ + KTabWidget::addTab( child, label ); + showPage( child ); + QTimer::singleShot(0, this, SLOT(maybeShow())); +} + +void KMdiDocumentViewTabWidget::addTab ( QWidget * child, const QIconSet & iconset, const QString & label ) +{ + KTabWidget::addTab( child, iconset, label ); + showPage( child ); + QTimer::singleShot(0, this, SLOT(maybeShow())); +} + +void KMdiDocumentViewTabWidget::addTab ( QWidget * child, QTab * tab ) +{ + KTabWidget::addTab( child, tab ); + showPage( child ); + QTimer::singleShot(0, this, SLOT(maybeShow())); +} + +void KMdiDocumentViewTabWidget::insertTab ( QWidget * child, const QString & label, int index ) +{ + KTabWidget::insertTab( child, label, index ); + showPage( child ); + QTimer::singleShot(0, this, SLOT(maybeShow())); + tabBar() ->repaint(); +} + +void KMdiDocumentViewTabWidget::insertTab ( QWidget * child, const QIconSet & iconset, const QString & label, int index ) +{ + KTabWidget::insertTab( child, iconset, label, index ); + showPage( child ); + QTimer::singleShot(0, this, SLOT(maybeShow())); + tabBar() ->repaint(); +} + +void KMdiDocumentViewTabWidget::insertTab ( QWidget * child, QTab * tab, int index ) +{ + KTabWidget::insertTab( child, tab, index ); + showPage( child ); + QTimer::singleShot(0, this, SLOT(maybeShow())); + tabBar() ->repaint(); +} + +void KMdiDocumentViewTabWidget::removePage ( QWidget * w ) +{ + KTabWidget::removePage( w ); + QTimer::singleShot(0, this, SLOT(maybeShow())); +} + +void KMdiDocumentViewTabWidget::updateIconInView( QWidget *w, QPixmap icon ) +{ + changeTab( w, icon, tabLabel( w ) ); +} + +void KMdiDocumentViewTabWidget::updateCaptionInView( QWidget *w, const QString &caption ) +{ + changeTab( w, caption ); +} + +void KMdiDocumentViewTabWidget::maybeShow() +{ + switch (m_visibility) + { + case KMdi::AlwaysShowTabs: + tabBar() ->show(); + if ( cornerWidget() ) + { + if ( count() == 0 ) + cornerWidget() ->hide(); + else + cornerWidget() ->show(); + } + break; + + case KMdi::ShowWhenMoreThanOneTab: + if ( count() < 2 ) + tabBar() ->hide(); + else tabBar() ->show(); + if ( cornerWidget() ) + { + if ( count() < 2 ) + cornerWidget() ->hide(); + else + cornerWidget() ->show(); + } + break; + case KMdi::NeverShowTabs: + tabBar() ->hide(); + break; + } +} + +void KMdiDocumentViewTabWidget::setTabWidgetVisibility( KMdi::TabWidgetVisibility visibility ) +{ + m_visibility = visibility; + maybeShow(); +} + +void KMdiDocumentViewTabWidget::moveTab( int from, int to ) +{ + emit initiateTabMove( from, to ); + KTabWidget::moveTab( from, to ); +} + +KMdi::TabWidgetVisibility KMdiDocumentViewTabWidget::tabWidgetVisibility( ) +{ + return m_visibility; +} + + +#ifndef NO_INCLUDE_MOCFILES +#include "kmdidocumentviewtabwidget.moc" +#endif + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmdidocumentviewtabwidget.h b/kmdi/kmdidocumentviewtabwidget.h new file mode 100644 index 000000000..ce7ea5e88 --- /dev/null +++ b/kmdi/kmdidocumentviewtabwidget.h @@ -0,0 +1,125 @@ +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDI_DOCUMENT_VIEW_TAB_WIDGET_H_ +#define _KMDI_DOCUMENT_VIEW_TAB_WIDGET_H_ + +#include <ktabwidget.h> +#include <kmdidefines.h> + +class KPopupMenu; + +//KDE4: Add a d pointer +/** + * A reimplementation of KTabWidget for KMDI + */ +class KMDI_EXPORT KMdiDocumentViewTabWidget: + public KTabWidget +{ + Q_OBJECT +public: + KMdiDocumentViewTabWidget( QWidget* parent, const char* name = 0 ); + ~KMdiDocumentViewTabWidget(); + + /** + * Add a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void addTab ( QWidget * child, const QString & label ); + + /** + * Add a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void addTab ( QWidget * child, const QIconSet & iconset, const QString & label ); + + /** + * Add a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void addTab ( QWidget * child, QTab * tab ); + + /** + * Insert a tab into the tabwidget with a label + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void insertTab ( QWidget * child, const QString & label, int index = -1 ); + + /** + * Inserts a tab into the tabwidget with an icon and label + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void insertTab ( QWidget * child, const QIconSet & iconset, const QString & label, int index = -1 ); + + /** + * Inserts a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void insertTab ( QWidget * child, QTab * tab, int index = -1 ); + + /** + * Removes the tab from the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void removePage ( QWidget * w ); + + /** + * Set the tab widget's visibility and then make the change + * to match the new setting + */ + KMdi::TabWidgetVisibility tabWidgetVisibility(); + + /** Get the tab widget's visibility */ + void setTabWidgetVisibility( KMdi::TabWidgetVisibility ); + +private slots: + + /** Close the tab specified by w */ + void closeTab( QWidget* w ); + + /** Moves a tab. Reimplemented for internal reasons. */ + void moveTab( int from, int to ); + +public slots: + + /** Change the icon for the tab */ + void updateIconInView( QWidget*, QPixmap ); + + /** Change the caption for the tab */ + void updateCaptionInView( QWidget*, const QString& ); + +private slots: + + /** + * Determine whether or not we should show the tab bar + * The tab bar is hidden if it's determined that it should be hidden + * and shown if it's determined that it should be shown + */ + void maybeShow(); + +private: + + KMdi::TabWidgetVisibility m_visibility; + +signals: + void initiateTabMove(int, int); +}; + + + +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmdifocuslist.cpp b/kmdi/kmdifocuslist.cpp new file mode 100644 index 000000000..0f055358a --- /dev/null +++ b/kmdi/kmdifocuslist.cpp @@ -0,0 +1,70 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kmdifocuslist.h" +#include "kmdifocuslist.moc" +#include <qobjectlist.h> +#include <kdebug.h> + +KMdiFocusList::KMdiFocusList( QObject *parent ) : QObject( parent ) +{} + +KMdiFocusList::~KMdiFocusList() +{} + +void KMdiFocusList::addWidgetTree( QWidget* w ) +{ + //this method should never be called twice on the same hierarchy + m_list.insert( w, w->focusPolicy() ); + w->setFocusPolicy( QWidget::ClickFocus ); + kdDebug( 760 ) << "KMdiFocusList::addWidgetTree: adding toplevel" << endl; + connect( w, SIGNAL( destroyed( QObject * ) ), this, SLOT( objectHasBeenDestroyed( QObject* ) ) ); + QObjectList *l = w->queryList( "QWidget" ); + QObjectListIt it( *l ); + QObject *obj; + while ( ( obj = it.current() ) != 0 ) + { + QWidget * wid = ( QWidget* ) obj; + m_list.insert( wid, wid->focusPolicy() ); + wid->setFocusPolicy( QWidget::ClickFocus ); + kdDebug( 760 ) << "KMdiFocusList::addWidgetTree: adding widget" << endl; + connect( wid, SIGNAL( destroyed( QObject * ) ), this, SLOT( objectHasBeenDestroyed( QObject* ) ) ); + ++it; + } + delete l; +} + +void KMdiFocusList::restore() +{ + for ( QMap<QWidget*, QWidget::FocusPolicy>::const_iterator it = m_list.constBegin();it != m_list.constEnd();++it ) + { + it.key() ->setFocusPolicy( it.data() ); + } + m_list.clear(); +} + + +void KMdiFocusList::objectHasBeenDestroyed( QObject * o ) +{ + if ( !o || !o->isWidgetType() ) + return ; + QWidget *w = ( QWidget* ) o; + m_list.remove( w ); +} + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdifocuslist.h b/kmdi/kmdifocuslist.h new file mode 100644 index 000000000..fbc178d1d --- /dev/null +++ b/kmdi/kmdifocuslist.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KMDI_FOCUS_LIST +#define KMDI_FOCUS_LIST + +#include <qobject.h> +#include <qmap.h> +#include <qwidget.h> +#include <kdelibs_export.h> + +class KMDI_EXPORT KMdiFocusList: public QObject +{ + Q_OBJECT +public: + KMdiFocusList( QObject *parent ); + ~KMdiFocusList(); + void addWidgetTree( QWidget* ); + void restore(); +protected slots: + void objectHasBeenDestroyed( QObject* ); +private: + QMap<QWidget*, QWidget::FocusPolicy> m_list; + +}; + +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdiguiclient.cpp b/kmdi/kmdiguiclient.cpp new file mode 100644 index 000000000..ec00ec784 --- /dev/null +++ b/kmdi/kmdiguiclient.cpp @@ -0,0 +1,320 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + based on ktoolbarhandler.cpp: Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kmdiguiclient.h" +#include "kmdiguiclient.moc" + +#include <qpopupmenu.h> +#include <kapplication.h> +#include <kconfig.h> +#include <ktoolbar.h> +#include <kmainwindow.h> +#include <klocale.h> +#include <kaction.h> +#include <qstring.h> +#include <assert.h> +#include <kdebug.h> +#include <kdockwidget.h> +#include <kdeversion.h> +#include "kmdimainfrm.h" +#include "kmditoolviewaccessor.h" +#include "kmditoolviewaccessor_p.h" +namespace +{ +const char *actionListName = "show_kmdi_document_tool_view_actions"; + +const char *guiDescription = "" + "<!DOCTYPE kpartgui><kpartgui name=\"KMDIViewActions\">" + "<MenuBar>" + " <Menu name=\"view\">" + " <ActionList name=\"%1\" />" + " </Menu>" + "</MenuBar>" + "</kpartgui>"; + +const char *resourceFileName = "kmdiviewactions.rc"; + +} + + +using namespace KMDIPrivate; + + + +ToggleToolViewAction::ToggleToolViewAction( const QString& text, const KShortcut& cut, KDockWidget *dw, KMdiMainFrm *mdiMainFrm, + QObject* parent, const char* name ) + : KToggleAction( text, cut, parent, name ), m_dw( dw ), m_mdiMainFrm( mdiMainFrm ) +{ + if ( m_dw ) + { + connect( this, SIGNAL( toggled( bool ) ), this, SLOT( slotToggled( bool ) ) ); + connect( m_dw->dockManager(), SIGNAL( change() ), this, SLOT( anDWChanged() ) ); + connect( m_dw, SIGNAL( destroyed() ), this, SLOT( slotWidgetDestroyed() ) ); + setChecked( m_dw->mayBeHide() ); + } +} + + +ToggleToolViewAction::~ToggleToolViewAction() +{ + unplugAll(); +} + +void ToggleToolViewAction::anDWChanged() +{ + if ( isChecked() && m_dw->mayBeShow() ) + setChecked( false ); + else if ( ( !isChecked() ) && m_dw->mayBeHide() ) + setChecked( true ); + else if ( isChecked() && ( m_dw->parentDockTabGroup() && + ( ( static_cast<KDockWidget*>( m_dw->parentDockTabGroup() -> + parent() ->qt_cast( "KDockWidget" ) ) ) ->mayBeShow() ) ) ) + setChecked( false ); +} + + +void ToggleToolViewAction::slotToggled( bool t ) +{ + // m_mw->mainDock->setDockSite( KDockWidget::DockCorner ); + + if ( ( !t ) && m_dw->mayBeHide() ) + m_dw->undock(); + else + if ( t && m_dw->mayBeShow() ) + m_mdiMainFrm->makeDockVisible( m_dw ); + + // m_mw->mainDock->setDockSite( KDockWidget::DockNone ); +} + +void ToggleToolViewAction::slotWidgetDestroyed() +{ + disconnect( m_dw->dockManager(), SIGNAL( change() ), this, SLOT( anDWChanged() ) ); + disconnect( this, SIGNAL( toggled( bool ) ), 0, 0 ); + unplugAll(); + deleteLater(); +} + + +KMDIGUIClient::KMDIGUIClient( KMdiMainFrm* mdiMainFrm, bool showMDIModeAction, const char* name ) : QObject( mdiMainFrm, name ), + KXMLGUIClient( mdiMainFrm ) +{ + m_mdiMode = KMdi::ChildframeMode; + m_mdiMainFrm = mdiMainFrm; + connect( mdiMainFrm->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ), + this, SLOT( clientAdded( KXMLGUIClient * ) ) ); + + /* re-use an existing resource file if it exists. can happen if the user launches the + * toolbar editor */ + /* + setXMLFile( resourceFileName ); + */ + + if ( domDocument().documentElement().isNull() ) + { + + QString completeDescription = QString::fromLatin1( guiDescription ) + .arg( actionListName ); + + setXML( completeDescription, false /*merge*/ ); + } + + if ( actionCollection() ->kaccel() == 0 ) + actionCollection() ->setWidget( mdiMainFrm ); + m_toolMenu = new KActionMenu( i18n( "Tool &Views" ), actionCollection(), "kmdi_toolview_menu" ); + if ( showMDIModeAction ) + { + m_mdiModeAction = new KSelectAction( i18n( "MDI Mode" ), 0, actionCollection() ); + QStringList modes; + modes << i18n( "&Toplevel Mode" ) << i18n( "C&hildframe Mode" ) << i18n( "Ta&b Page Mode" ) << i18n( "I&DEAl Mode" ); + m_mdiModeAction->setItems( modes ); + connect( m_mdiModeAction, SIGNAL( activated( int ) ), this, SLOT( changeViewMode( int ) ) ); + } + else + m_mdiModeAction = 0; + + connect( m_mdiMainFrm, SIGNAL( mdiModeHasBeenChangedTo( KMdi::MdiMode ) ), + this, SLOT( mdiModeHasBeenChangedTo( KMdi::MdiMode ) ) ); + + m_gotoToolDockMenu = new KActionMenu( i18n( "Tool &Docks" ), actionCollection(), "kmdi_tooldock_menu" ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Top Dock" ), ALT + CTRL + SHIFT + Key_T, this, SIGNAL( toggleTop() ), + actionCollection(), "kmdi_activate_top" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Left Dock" ), ALT + CTRL + SHIFT + Key_L, this, SIGNAL( toggleLeft() ), + actionCollection(), "kmdi_activate_left" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Right Dock" ), ALT + CTRL + SHIFT + Key_R, this, SIGNAL( toggleRight() ), + actionCollection(), "kmdi_activate_right" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Bottom Dock" ), ALT + CTRL + SHIFT + Key_B, this, SIGNAL( toggleBottom() ), + actionCollection(), "kmdi_activate_bottom" ) ); + m_gotoToolDockMenu->insert( new KActionSeparator( actionCollection(), "kmdi_goto_menu_separator" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Previous Tool View" ), ALT + CTRL + Key_Left, m_mdiMainFrm, SLOT( prevToolViewInDock() ), + actionCollection(), "kmdi_prev_toolview" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Next Tool View" ), ALT + CTRL + Key_Right, m_mdiMainFrm, SLOT( nextToolViewInDock() ), + actionCollection(), "kmdi_next_toolview" ) ); + + actionCollection() ->readShortcutSettings( "Shortcuts", kapp->config() ); +} + +KMDIGUIClient::~KMDIGUIClient() +{ + + // actionCollection()->writeShortcutSettings( "KMDI Shortcuts", kapp->config() ); + for ( uint i = 0;i < m_toolViewActions.count();i++ ) + disconnect( m_toolViewActions.at( i ), 0, this, 0 ); + + m_toolViewActions.setAutoDelete( false ); + m_toolViewActions.clear(); + m_documentViewActions.setAutoDelete( false ); + m_documentViewActions.clear(); +} + +void KMDIGUIClient::changeViewMode( int id ) +{ + switch ( id ) + { + case 0: + m_mdiMainFrm->switchToToplevelMode(); + break; + case 1: + m_mdiMainFrm->switchToChildframeMode(); + break; + case 2: + m_mdiMainFrm->switchToTabPageMode(); + break; + case 3: + m_mdiMainFrm->switchToIDEAlMode(); + break; + default: + Q_ASSERT( 0 ); + } +} + +void KMDIGUIClient::setupActions() +{ + if ( !factory() || !m_mdiMainFrm ) + return ; + + // BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars ); + + // if ( !builder.needsRebuild() ) + // return; + + + unplugActionList( actionListName ); + + // m_actions.setAutoDelete( true ); + // m_actions.clear(); + // m_actions.setAutoDelete( false ); + + // m_actions = builder.create(); + + // m_toolBars = builder.toolBars(); + + // m_toolViewActions.append(new KAction( "TESTKMDIGUICLIENT", QString::null, 0, + // this, SLOT(blah()),actionCollection(),"nothing")); + + QPtrList<KAction> addList; + if ( m_toolViewActions.count() < 3 ) + for ( uint i = 0;i < m_toolViewActions.count();i++ ) + addList.append( m_toolViewActions.at( i ) ); + else + addList.append( m_toolMenu ); + if ( m_mdiMode == KMdi::IDEAlMode ) + addList.append( m_gotoToolDockMenu ); + if ( m_mdiModeAction ) + addList.append( m_mdiModeAction ); + kdDebug( 760 ) << "KMDIGUIClient::setupActions: plugActionList" << endl; + plugActionList( actionListName, addList ); + + // connectToActionContainers(); +} + +void KMDIGUIClient::addToolView( KMdiToolViewAccessor* mtva ) +{ + kdDebug( 760 ) << "*****void KMDIGUIClient::addToolView(KMdiToolViewAccessor* mtva)*****" << endl; + // kdDebug()<<"name: "<<mtva->wrappedWidget()->name()<<endl; + QString aname = QString( "kmdi_toolview_" ) + mtva->wrappedWidget() ->name(); + + // try to read the action shortcut + KShortcut sc; + KConfig *cfg = kapp->config(); + QString _grp = cfg->group(); + cfg->setGroup( "Shortcuts" ); + // if ( cfg->hasKey( aname ) ) + sc = KShortcut( cfg->readEntry( aname, "" ) ); + cfg->setGroup( _grp ); + KAction *a = new ToggleToolViewAction( i18n( "Show %1" ).arg( mtva->wrappedWidget() ->caption() ), + /*QString::null*/sc, dynamic_cast<KDockWidget*>( mtva->wrapperWidget() ), + m_mdiMainFrm, actionCollection(), aname.latin1() ); +#if KDE_IS_VERSION(3,2,90) + + ( ( ToggleToolViewAction* ) a ) ->setCheckedState( i18n( "Hide %1" ).arg( mtva->wrappedWidget() ->caption() ) ); +#endif + + connect( a, SIGNAL( destroyed( QObject* ) ), this, SLOT( actionDeleted( QObject* ) ) ); + m_toolViewActions.append( a ); + m_toolMenu->insert( a ); + mtva->d->action = a; + + setupActions(); +} + +void KMDIGUIClient::actionDeleted( QObject* a ) +{ + m_toolViewActions.remove( static_cast<KAction*>( a ) ); + /* if (!m_toolMenu.isNull()) m_toolMenu->remove(static_cast<KAction*>(a));*/ + setupActions(); +} + + +void KMDIGUIClient::clientAdded( KXMLGUIClient *client ) +{ + if ( client == this ) + setupActions(); +} + + +void KMDIGUIClient::mdiModeHasBeenChangedTo( KMdi::MdiMode mode ) +{ + kdDebug( 760 ) << "KMDIGUIClient::mdiModeHasBennChangeTo" << endl; + m_mdiMode = mode; + if ( m_mdiModeAction ) + { + switch ( mode ) + { + case KMdi::ToplevelMode: + m_mdiModeAction->setCurrentItem( 0 ); + break; + case KMdi::ChildframeMode: + m_mdiModeAction->setCurrentItem( 1 ); + break; + case KMdi::TabPageMode: + m_mdiModeAction->setCurrentItem( 2 ); + break; + case KMdi::IDEAlMode: + m_mdiModeAction->setCurrentItem( 3 ); + break; + default: + Q_ASSERT( 0 ); + } + } + setupActions(); + +} + + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdiguiclient.h b/kmdi/kmdiguiclient.h new file mode 100644 index 000000000..a52db681c --- /dev/null +++ b/kmdi/kmdiguiclient.h @@ -0,0 +1,146 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KMDIGUICLIENT_H +#define KMDIGUICLIENT_H + +#include <qobject.h> +#include <qguardedptr.h> +#include <kxmlguiclient.h> +#include <kaction.h> +#include "kmdidefines.h" + +class KMainWindow; +class KToolBar; +class KMdiToolViewAccessor; +class KMdiMainFrm; +class KDockWidget; + +namespace KMDIPrivate +{ + +/** + * A class derived from KXMLGUIClient that handles the various + * KMDI modes + */ +class KMDI_EXPORT KMDIGUIClient : public QObject, + public KXMLGUIClient +{ + Q_OBJECT +public: + + KMDIGUIClient( KMdiMainFrm *mdiMainFrm, bool showMDIModeAction, const char *name = 0 ); + virtual ~KMDIGUIClient(); + + /** + * Add a new tool view to this KMDIGUIClient. Reads the shortcut + * for the tool view from the KMDI application's config file and also + * adds a ToggleToolViewAction so that the visibility of the toolviews + * can be turned on and off + */ + void addToolView( KMdiToolViewAccessor* ); + +private slots: + + /** + * The XMLGUIClient factory has added an XMLGUI client. Plug our actions + * in if we're the client that's been added. + */ + void clientAdded( KXMLGUIClient *client ); + /** + * Plug in the various toggle actions we have into the tool views menu + */ + void setupActions(); + + /** + * Change the view mode. This will automatically change the view mode + * of the KMdiMainFrm associated with this KMDIGUIClient + */ + void changeViewMode( int id ); + + /** + * One of our tool view toggle actions has been deleted. Redo the + * tool views menu + */ + void actionDeleted( QObject* ); + + /** + * Updates the action that lets the user change the MDI mode to the + * correct value based on the current mode + */ + void mdiModeHasBeenChangedTo( KMdi::MdiMode ); + +signals: + /** Toggle the top tool dock */ + void toggleTop(); + + /** Toggle the left tool dock */ + void toggleLeft(); + + /** Toggle the right tool dock */ + void toggleRight(); + + /** Toggle the bottom tool dock */ + void toggleBottom(); + +private: + class KMDIGUIClientPrivate; + KMDIGUIClientPrivate *d; + KMdi::MdiMode m_mdiMode; + + QGuardedPtr<KMdiMainFrm> m_mdiMainFrm; + QPtrList<KAction> m_toolViewActions; + QPtrList<KAction> m_documentViewActions; + + KActionMenu *m_docMenu; + KActionMenu *m_toolMenu; + KSelectAction *m_mdiModeAction; + + KActionMenu *m_gotoToolDockMenu; +}; + +/** + * A KToggleAction specifically for toggling the showing + * or the hiding of a KMDI tool view + */ +class KMDI_EXPORT ToggleToolViewAction: public KToggleAction +{ + Q_OBJECT +public: + + ToggleToolViewAction( const QString& text, const KShortcut& cut = KShortcut(), KDockWidget *dw = 0, KMdiMainFrm *mdiMainFrm = 0, + QObject* parent = 0, const char* name = 0 ); + + virtual ~ToggleToolViewAction(); + +private: + + KDockWidget *m_dw; + KMdiMainFrm *m_mdiMainFrm; +protected slots: + + void slotToggled( bool ); + void anDWChanged(); + void slotWidgetDestroyed(); +}; + + +} + +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdiiterator.h b/kmdi/kmdiiterator.h new file mode 100644 index 000000000..6bb6f7eac --- /dev/null +++ b/kmdi/kmdiiterator.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// filename : kmdiiterator.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 02/2000 by Massimo Morin +// changes : 02/2000 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Massimo Morin (mmorin@schedsys.com) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDIITERATOR_H_ +#define _KMDIITERATOR_H_ + + +template <class Item> +class KMdiIterator +{ +public: + virtual ~KMdiIterator() {} + + virtual void first() = 0; + virtual void last() = 0; + virtual void next() = 0; + virtual void prev() = 0; + virtual bool isDone() const = 0; + virtual Item currentItem() const = 0; + +protected: + KMdiIterator() {} +} +; + +#endif // _KMDIITERATOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmdilistiterator.h b/kmdi/kmdilistiterator.h new file mode 100644 index 000000000..fe92bfcc2 --- /dev/null +++ b/kmdi/kmdilistiterator.h @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------------- +// filename : kmdilistiterator.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 02/2000 by Massimo Morin +// changes : 02/2000 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Massimo Morin (mmorin@schedsys.com) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDILISTITERATOR_H_ +#define _KMDILISTITERATOR_H_ + +#include <kmdiiterator.h> + +template <class I> +class QPtrList; +template <class I> +class QPtrListIterator; + +template <class Item> +class KMdiListIterator : public KMdiIterator<Item*> +{ +public: + KMdiListIterator( QPtrList<Item>& list ) + { + m_iterator = new QPtrListIterator<Item>( list ); + } + + virtual void first() { m_iterator->toFirst(); } + virtual void last() { m_iterator->toLast(); } + virtual void next() { ++( *m_iterator ); } + virtual void prev() { --( *m_iterator ); } + virtual bool isDone() const { return m_iterator->current() == 0; } + virtual Item* currentItem() const { return m_iterator->current(); } + + virtual ~KMdiListIterator() { delete m_iterator; } + +private: + QPtrListIterator<Item> *m_iterator; +}; + +#endif // _KMDILISTITERATOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmdimainfrm.cpp b/kmdi/kmdimainfrm.cpp new file mode 100644 index 000000000..e4afce397 --- /dev/null +++ b/kmdi/kmdimainfrm.cpp @@ -0,0 +1,2937 @@ +//---------------------------------------------------------------------------- +// filename : kmdimainfrm.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + + +/* + * ATTENTION: please do you part to try to make this file legible. It's + * extremely hard to read already. Especially follow the indenting rules. + */ +#include "config.h" + +#include <assert.h> + +#include <qcursor.h> +#include <qclipboard.h> +#include <qobjectlist.h> +#include <qpopupmenu.h> +#include <qmenubar.h> + +#include <kmenubar.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <qtabwidget.h> +#include <klocale.h> +#include <kstdaccel.h> + +#include <kiconloader.h> +#include <kmdidockcontainer.h> + + +#include <qtoolbutton.h> +#include <qdockarea.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qtextstream.h> +#include <qstring.h> +#include <qmap.h> +#include <qvaluelist.h> + +#include "kmdimainfrm.h" +#include "kmditaskbar.h" +#include "kmdichildfrm.h" +#include "kmdichildarea.h" +#include "kmdichildview.h" +#include "kmdidockcontainer.h" +#include "kmditoolviewaccessor_p.h" +#include "kmdifocuslist.h" +#include "kmdidocumentviewtabwidget.h" +#include "kmdiguiclient.h" + +#include "win_undockbutton.xpm" +#include "win_minbutton.xpm" +#include "win_restorebutton.xpm" +#include "win_closebutton.xpm" +#include "kde_undockbutton.xpm" +#include "kde_minbutton.xpm" +#include "kde_restorebutton.xpm" +#include "kde_closebutton.xpm" +#include "kde2_undockbutton.xpm" +#include "kde2_minbutton.xpm" +#include "kde2_restorebutton.xpm" +#include "kde2_closebutton.xpm" +#include "kde2laptop_undockbutton.xpm" +#include "kde2laptop_minbutton.xpm" +#include "kde2laptop_restorebutton.xpm" +#include "kde2laptop_closebutton.xpm" +#include "kde2laptop_closebutton_menu.xpm" + +#ifdef Q_WS_X11 +#ifndef NO_KDE +#include <X11/X.h> // schroder +#include <X11/Xlib.h> // schroder +#endif + +#ifdef KeyRelease +/* I hate the defines in the X11 header files. Get rid of one of them */ +#undef KeyRelease +#endif + +#ifdef KeyPress +/* I hate the defines in the X11 header files. Get rid of one of them */ +#undef KeyPress +#endif +#endif // Q_WS_X11 && ! K_WS_QTONLY + +using namespace KParts; + +KMdi::FrameDecor KMdiMainFrm::m_frameDecoration = KMdi::KDELook; + +class KMdiMainFrmPrivate +{ +public: + KMdiMainFrmPrivate() : focusList( 0 ) + { + for ( int i = 0;i < 4;i++ ) + { + activeDockPriority[ i ] = 0; + m_styleIDEAlMode = 0; + m_toolviewStyle = 0; + } + } + ~KMdiMainFrmPrivate() + {} + KMdiDockContainer* activeDockPriority[ 4 ]; + KMdiFocusList *focusList; + int m_styleIDEAlMode; + int m_toolviewStyle; + KAction *closeWindowAction; +}; + +//============ constructor ============// +KMdiMainFrm::KMdiMainFrm( QWidget* parentWidget, const char* name, KMdi::MdiMode mdiMode, WFlags flags ) + : KParts::DockMainWindow( parentWidget, name, flags ) + , m_mdiMode( KMdi::UndefinedMode ) + , m_pMdi( 0L ) + , m_pTaskBar( 0L ) + , m_pDocumentViews( 0L ) + , m_pCurrentWindow( 0L ) + , m_pWindowPopup( 0L ) + , m_pTaskBarPopup( 0L ) + , m_pWindowMenu( 0L ) + , m_pDockMenu( 0L ) + , m_pMdiModeMenu( 0L ) + , m_pPlacingMenu( 0L ) + , m_pMainMenuBar( 0L ) + , m_pUndockButtonPixmap( 0L ) + , m_pMinButtonPixmap( 0L ) + , m_pRestoreButtonPixmap( 0L ) + , m_pCloseButtonPixmap( 0L ) + , m_pUndock( 0L ) + , m_pMinimize( 0L ) + , m_pRestore( 0L ) + , m_pClose( 0L ) + , m_bMaximizedChildFrmMode( false ) + , m_oldMainFrmHeight( 0 ) + , m_oldMainFrmMinHeight( 0 ) + , m_oldMainFrmMaxHeight( 0 ) + , m_bSDIApplication( false ) + , m_pDockbaseAreaOfDocumentViews( 0L ) + , m_pTempDockSession( 0L ) + , m_bClearingOfWindowMenuBlocked( false ) + , m_pDragEndTimer( 0L ) + , m_bSwitching( false ) + , m_leftContainer( 0 ) + , m_rightContainer( 0 ) + , m_topContainer( 0 ) + , m_bottomContainer( 0 ) + , d( new KMdiMainFrmPrivate() ) + , m_mdiGUIClient( 0 ) + , m_managedDockPositionMode( false ) + , m_documentTabWidget( 0 ) +{ + kdDebug(760) << k_funcinfo << endl; + // Create the local lists of windows + m_pDocumentViews = new QPtrList<KMdiChildView>; + m_pDocumentViews->setAutoDelete( false ); + m_pToolViews = new QMap<QWidget*, KMdiToolViewAccessor*>; + + // This seems to be needed (re-check it after Qt2.0 comed out) + setFocusPolicy( ClickFocus ); + + // create the central widget + createMdiManager(); + + // cover KMdi's childarea by a dockwidget + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + // set this dock to main view + setView( m_pDockbaseAreaOfDocumentViews ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + + // Apply options for the MDI manager + applyOptions(); + + m_pTaskBarPopup = new QPopupMenu( this, "taskbar_popup_menu" ); + m_pWindowPopup = new QPopupMenu( this, "window_popup_menu" ); + + m_pWindowMenu = new QPopupMenu( this, "window_menu" ); + m_pWindowMenu->setCheckable( true ); + QObject::connect( m_pWindowMenu, SIGNAL( aboutToShow() ), this, SLOT( fillWindowMenu() ) ); + + m_pDockMenu = new QPopupMenu( this, "dock_menu" ); + m_pDockMenu->setCheckable( true ); + + m_pMdiModeMenu = new QPopupMenu( this, "mdimode_menu" ); + m_pMdiModeMenu->setCheckable( true ); + + m_pPlacingMenu = new QPopupMenu( this, "placing_menu" ); + + d->closeWindowAction = new KAction(i18n("&Close"), KStdAccel::close(), + this, SLOT(closeActiveView()), actionCollection(), "window_close"); + + // the MDI view taskbar + createTaskBar(); + + // this is only a hack, but prevents us from crash because the buttons are otherwise + // not created before we switch the modes where we need them !!! + setMenuForSDIModeSysButtons( menuBar() ); + + switch ( mdiMode ) + { + case KMdi::IDEAlMode: + kdDebug(760) << k_funcinfo << "Switching to IDEAl mode" << endl; + switchToIDEAlMode(); + break; + case KMdi::TabPageMode: + kdDebug(760) << k_funcinfo << "Switching to tab page mode" << endl; + switchToTabPageMode(); + break; + case KMdi::ToplevelMode: + kdDebug(760) << k_funcinfo << "Switching to top level mode" << endl; + switchToToplevelMode(); + break; + default: + m_mdiMode = KMdi::ChildframeMode; + kdDebug(760) << k_funcinfo << "Switching to child frame mode" << endl; + break; + } + + // drag end timer + m_pDragEndTimer = new QTimer(); + connect( m_pDragEndTimer, SIGNAL( timeout() ), this, SLOT( dragEndTimeOut() ) ); + connect( guiFactory(), SIGNAL( clientAdded( KXMLGUIClient* ) ), + this, SLOT( verifyToplevelHeight() ) ); + connect( guiFactory(), SIGNAL( clientRemoved( KXMLGUIClient* ) ), + this, SLOT( verifyToplevelHeight() ) ); +} + +void KMdiMainFrm::verifyToplevelHeight() +{ + if ( m_mdiMode != KMdi::ToplevelMode ) + return; + + //kdDebug(760) << k_funcinfo << endl; + int topDockHeight = topDock() ? topDock()->height() : 0; + int menuBarHeight = hasMenuBar() ? menuBar()->height() : 0; + setFixedHeight( topDockHeight + menuBarHeight ); + resize( width(), height() ); +} + +void KMdiMainFrm::setStandardMDIMenuEnabled( bool showModeMenu ) +{ + m_mdiGUIClient = new KMDIPrivate::KMDIGUIClient( this, showModeMenu ); + connect( m_mdiGUIClient, SIGNAL( toggleTop() ), this, SIGNAL( toggleTop() ) ); + connect( m_mdiGUIClient, SIGNAL( toggleLeft() ), this, SIGNAL( toggleLeft() ) ); + connect( m_mdiGUIClient, SIGNAL( toggleRight() ), this, SIGNAL( toggleRight() ) ); + connect( m_mdiGUIClient, SIGNAL( toggleBottom() ), this, SIGNAL( toggleBottom() ) ); + + if ( m_mdiMode == KMdi::IDEAlMode ) + { + if ( m_topContainer ) + connect( this, SIGNAL( toggleTop() ), m_topContainer->getWidget(), SLOT( toggle() ) ); + if ( m_leftContainer ) + connect( this, SIGNAL( toggleLeft() ), m_leftContainer->getWidget(), SLOT( toggle() ) ); + if ( m_rightContainer ) + connect( this, SIGNAL( toggleRight() ), m_rightContainer->getWidget(), SLOT( toggle() ) ); + if ( m_bottomContainer ) + connect( this, SIGNAL( toggleBottom() ), m_bottomContainer->getWidget(), SLOT( toggle() ) ); + } + + emit mdiModeHasBeenChangedTo( m_mdiMode ); +} + +//============ ~KMdiMainFrm ============// +KMdiMainFrm::~KMdiMainFrm() +{ + //save the children first to a list, as removing invalidates our iterator + QValueList<KMdiChildView*> children; + for ( KMdiChildView * w = m_pDocumentViews->first();w;w = m_pDocumentViews->next() ) + children.append( w ); + + // safely close the windows so properties are saved... + QValueListIterator<KMdiChildView*> childIt; + for ( childIt = children.begin(); childIt != children.end(); ++childIt ) + { + closeWindow( *childIt, false ); // without re-layout taskbar! + } + + emit lastChildViewClosed(); + delete m_pDocumentViews; + delete m_pToolViews; + m_pToolViews = 0; + delete m_pDragEndTimer; + + delete m_pUndockButtonPixmap; + delete m_pMinButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + + //deletes added for Release-Version-Pop-Up-WinMenu-And-Go-Out-Problem + delete m_pDockMenu; + delete m_pMdiModeMenu; + delete m_pPlacingMenu; + delete m_pTaskBarPopup; + delete m_pWindowPopup; + delete m_pWindowMenu; + delete m_mdiGUIClient; + delete m_pTempDockSession; + m_mdiGUIClient = 0; + delete d; + d = 0; +} + +//============ applyOptions ============// +//FIXME something wrong with this function. dunno what though +void KMdiMainFrm::applyOptions() +{ + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + QWidget* childFrame = 0L; + if ( ( *it )->mdiParent() ) + { + kdDebug(760) << k_funcinfo << "using child view's mdi parent for resize hack" << endl; + childFrame = ( *it )->mdiParent(); + } + else + { + kdDebug(760) << k_funcinfo << "using child view for resize hack" << endl; + childFrame = ( *it ); + } + + int w = childFrame->width(); + int h = childFrame->height(); + childFrame->resize( w + 1, h + 1 ); + childFrame->resize( w - 1, h - 1 ); + } +} + +//============ createMdiManager ============// +void KMdiMainFrm::createMdiManager() +{ + kdDebug(760) << k_funcinfo << "creating MDI manager" << endl; + m_pMdi = new KMdiChildArea( this ); + setCentralWidget( m_pMdi ); + QObject::connect( m_pMdi, SIGNAL( nowMaximized( bool ) ), + this, SLOT( setEnableMaximizedChildFrmMode( bool ) ) ); + QObject::connect( m_pMdi, SIGNAL( noMaximizedChildFrmLeft( KMdiChildFrm* ) ), + this, SLOT( switchOffMaximizeModeForMenu( KMdiChildFrm* ) ) ); + QObject::connect( m_pMdi, SIGNAL( sysButtonConnectionsMustChange( KMdiChildFrm*, KMdiChildFrm* ) ), + this, SLOT( updateSysButtonConnections( KMdiChildFrm*, KMdiChildFrm* ) ) ); + QObject::connect( m_pMdi, SIGNAL( popupWindowMenu( QPoint ) ), + this, SLOT( popupWindowMenu( QPoint ) ) ); + QObject::connect( m_pMdi, SIGNAL( lastChildFrmClosed() ), + this, SIGNAL( lastChildFrmClosed() ) ); +} + +//============ createTaskBar ==============// +void KMdiMainFrm::createTaskBar() +{ + m_pTaskBar = new KMdiTaskBar( this, QMainWindow::DockBottom ); + m_pTaskBar->installEventFilter( this ); +} + +void KMdiMainFrm::slot_toggleTaskBar() +{ + if ( !m_pTaskBar ) + return; + m_pTaskBar->switchOn( !m_pTaskBar->isSwitchedOn() ); +} + +void KMdiMainFrm::resizeEvent( QResizeEvent *e ) +{ + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + if ( e->oldSize().height() != e->size().height() ) + return ; + } + KParts::DockMainWindow::resizeEvent( e ); + if ( !m_mdiGUIClient ) + return ; + setSysButtonsAtMenuPosition(); +} + +//================ setMinimumSize ===============// + +void KMdiMainFrm::setMinimumSize( int minw, int minh ) +{ + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + return ; + DockMainWindow::setMinimumSize( minw, minh ); +} + +//================ wrapper ===============// + +KMdiChildView* KMdiMainFrm::createWrapper( QWidget *view, const QString& name, const QString& shortName ) +{ + Q_ASSERT( view ); // if this assert fails, then some part didn't return a widget. Fix the part ;) + + KMdiChildView* pMDICover = new KMdiChildView( name /*caption*/, 0L /*parent*/, + name.latin1() ); + QBoxLayout* pLayout = new QHBoxLayout( pMDICover, 0, -1, "layout" ); + view->reparent( pMDICover, QPoint( 0, 0 ) ); + pLayout->addWidget( view ); + // pMDICover->setName(name); + pMDICover->setTabCaption( shortName ); + pMDICover->setCaption( name ); + + const QPixmap* wndIcon = view->icon(); + if ( wndIcon ) + pMDICover->setIcon( *wndIcon ); + + pMDICover->trackIconAndCaptionChanges( view ); + return pMDICover; +} + +//================ addWindow ===============// + +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, int flags ) +{ + addWindow( pWnd, flags, -1 ); +} + +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, int flags, int index ) +{ + if ( windowExists( pWnd, AnyView ) ) //already added + return; + + if ( flags & KMdi::ToolWindow ) + { + addToolWindow( pWnd ); + // some kind of cascading + pWnd->move( m_pMdi->mapToGlobal( m_pMdi->getCascadePoint() ) ); + + return ; + } + + d->closeWindowAction->setEnabled(true); + + // common connections used when under MDI control + QObject::connect( pWnd, SIGNAL( clickedInWindowMenu( int ) ), this, SLOT( windowMenuItemActivated( int ) ) ); + QObject::connect( pWnd, SIGNAL( focusInEventOccurs( KMdiChildView* ) ), this, SLOT( activateView( KMdiChildView* ) ) ); + QObject::connect( pWnd, SIGNAL( childWindowCloseRequest( KMdiChildView* ) ), this, SLOT( childWindowCloseRequest( KMdiChildView* ) ) ); + QObject::connect( pWnd, SIGNAL( attachWindow( KMdiChildView*, bool ) ), this, SLOT( attachWindow( KMdiChildView*, bool ) ) ); + QObject::connect( pWnd, SIGNAL( detachWindow( KMdiChildView*, bool ) ), this, SLOT( detachWindow( KMdiChildView*, bool ) ) ); + QObject::connect( pWnd, SIGNAL( clickedInDockMenu( int ) ), this, SLOT( dockMenuItemActivated( int ) ) ); + QObject::connect( pWnd, SIGNAL( activated( KMdiChildView* ) ), this, SIGNAL( viewActivated( KMdiChildView* ) ) ); + QObject::connect( pWnd, SIGNAL( deactivated( KMdiChildView* ) ), this, SIGNAL( viewDeactivated( KMdiChildView* ) ) ); + + if ( index == -1 ) + m_pDocumentViews->append( pWnd ); + else + m_pDocumentViews->insert( index, pWnd ); + + if ( m_pTaskBar ) + { + KMdiTaskBarButton* but = m_pTaskBar->addWinButton( pWnd ); + QObject::connect( pWnd, SIGNAL( tabCaptionChanged( const QString& ) ), but, SLOT( setNewText( const QString& ) ) ); + } + + // embed the view depending on the current MDI mode + if ( m_mdiMode == KMdi::TabPageMode || m_mdiMode == KMdi::IDEAlMode ) + { + QPixmap pixmap; + if ( pWnd->icon() ) + pixmap = *( pWnd->icon() ); + + m_documentTabWidget->insertTab( pWnd, pixmap, pWnd->tabCaption(), index ); + + connect( pWnd, SIGNAL( iconUpdated( QWidget*, QPixmap ) ), m_documentTabWidget, SLOT( updateIconInView( QWidget*, QPixmap ) ) ); + connect( pWnd, SIGNAL( captionUpdated( QWidget*, const QString& ) ), m_documentTabWidget, SLOT( updateCaptionInView( QWidget*, const QString& ) ) ); + } + else + { + if ( ( flags & KMdi::Detach ) || ( m_mdiMode == KMdi::ToplevelMode ) ) + { + detachWindow( pWnd, !( flags & KMdi::Hide ) ); + emit childViewIsDetachedNow( pWnd ); // fake it because detach won't call it in this case of addWindow-to-MDI + } + else + attachWindow( pWnd, !( flags & KMdi::Hide ), flags & KMdi::UseKMdiSizeHint ); + + if ( ( m_bMaximizedChildFrmMode && ( !m_bSDIApplication && ( flags & KMdi::Detach ) ) + && m_mdiMode != KMdi::ToplevelMode ) || ( flags & KMdi::Maximize ) ) + { + if ( !pWnd->isMaximized() ) + pWnd->maximize(); + } + + if ( !m_bSDIApplication || ( flags & KMdi::Detach ) ) + { + if ( flags & KMdi::Minimize ) + pWnd->minimize(); + + if ( !( flags & KMdi::Hide ) ) + { + if ( pWnd->isAttached() ) + pWnd->mdiParent()->show(); + else + pWnd->show(); + } + } + } +} + +//============ addWindow ============// +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, QRect rectNormal, int flags ) +{ + addWindow( pWnd, flags ); + if ( m_bMaximizedChildFrmMode && pWnd->isAttached() ) + pWnd->setRestoreGeometry( rectNormal ); + else + pWnd->setGeometry( rectNormal ); +} + +//============ addWindow ============// +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, QPoint pos, int flags ) +{ + addWindow( pWnd, flags ); + if ( m_bMaximizedChildFrmMode && pWnd->isAttached() ) + pWnd->setRestoreGeometry( QRect( pos, pWnd->restoreGeometry().size() ) ); + else + pWnd->move( pos ); +} + + + +KMdiToolViewAccessor *KMdiMainFrm::createToolWindow() +{ + return new KMdiToolViewAccessor( this ); +} + + +void KMdiMainFrm::deleteToolWindow( QWidget* pWnd ) +{ + if ( m_pToolViews->contains( pWnd ) ) + deleteToolWindow( ( *m_pToolViews ) [ pWnd ] ); +} + +void KMdiMainFrm::deleteToolWindow( KMdiToolViewAccessor *accessor ) +{ + delete accessor; +} + +//============ addWindow ============// +KMdiToolViewAccessor *KMdiMainFrm::addToolWindow( QWidget* pWnd, KDockWidget::DockPosition pos, QWidget* pTargetWnd, + int percent, const QString& tabToolTip, const QString& tabCaption ) +{ + QWidget* tvta = pWnd; + KDockWidget* pDW = dockManager->getDockWidgetFromName( pWnd->name() ); + if ( pDW ) + { + // probably readDockConfig already created the widgetContainer, use that + pDW->setWidget( pWnd ); + + if ( pWnd->icon() ) + pDW->setPixmap( *pWnd->icon() ); + + pDW->setTabPageLabel( ( tabCaption == 0 ) ? pWnd->caption() : tabCaption ); + pDW->setToolTipString( tabToolTip ); + dockManager->removeFromAutoCreateList( pDW ); + pWnd = pDW; + } + + QRect r = pWnd->geometry(); + + KMdiToolViewAccessor *mtva = new KMdiToolViewAccessor( this, pWnd, tabToolTip, ( tabCaption == 0 ) ? pWnd->caption() : tabCaption ); + m_pToolViews->insert( tvta, mtva ); + + if ( pos == KDockWidget::DockNone ) + { + mtva->d->widgetContainer->setEnableDocking( KDockWidget::DockNone ); + mtva->d->widgetContainer->reparent( this, Qt::WType_TopLevel | Qt::WType_Dialog, r.topLeft(), true ); //pToolView->isVisible()); + } + else //add and dock the toolview as a dockwidget view + mtva->place( pos, pTargetWnd, percent ); + + + return mtva; +} + +//============ attachWindow ============// +void KMdiMainFrm::attachWindow( KMdiChildView *pWnd, bool bShow, bool bAutomaticResize ) +{ + pWnd->installEventFilter( this ); + + // decide whether window shall be cascaded + bool bCascade = false; + QApplication::sendPostedEvents(); + QRect frameGeo = pWnd->frameGeometry(); + QPoint topLeftScreen = pWnd->mapToGlobal( QPoint( 0, 0 ) ); + QPoint topLeftMdiChildArea = m_pMdi->mapFromGlobal( topLeftScreen ); + QRect childAreaGeo = m_pMdi->geometry(); + if ( topLeftMdiChildArea.x() < 0 || topLeftMdiChildArea.y() < 0 || + ( topLeftMdiChildArea.x() + frameGeo.width() > childAreaGeo.width() ) || + ( topLeftMdiChildArea.y() + frameGeo.height() > childAreaGeo.height() ) ) + { + bCascade = true; + } + + // create frame and insert child view + KMdiChildFrm *lpC = new KMdiChildFrm( m_pMdi ); + pWnd->hide(); + if ( !bCascade ) + lpC->move( topLeftMdiChildArea ); + + lpC->setClient( pWnd, bAutomaticResize ); + lpC->setFocus(); + pWnd->youAreAttached( lpC ); + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + setMinimumHeight( m_oldMainFrmMinHeight ); + setMaximumHeight( m_oldMainFrmMaxHeight ); + resize( width(), m_oldMainFrmHeight ); + m_oldMainFrmHeight = 0; + switchToChildframeMode(); + } + + m_pMdi->manageChild( lpC, false, bCascade ); + if ( m_pMdi->topChild() && m_pMdi->topChild() ->isMaximized() ) + { + QRect r = lpC->geometry(); + lpC->setGeometry( -lpC->m_pClient->x(), -lpC->m_pClient->y(), + m_pMdi->width() + KMDI_CHILDFRM_DOUBLE_BORDER, + m_pMdi->height() + lpC->captionHeight() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER ); + lpC->setRestoreGeometry( r ); + } + + if ( bShow ) + { + lpC->show(); + } + +#undef FocusIn + QFocusEvent fe( QEvent::FocusIn ); + QApplication::sendEvent( pWnd, &fe ); + + m_pCurrentWindow = pWnd; // required for checking the active item +} + +//============= detachWindow ==============// +void KMdiMainFrm::detachWindow( KMdiChildView *pWnd, bool bShow ) +{ + if ( pWnd->isAttached() ) + { + pWnd->removeEventFilter( this ); + pWnd->youAreDetached(); + // this is only if it was attached and you want to detach it + if ( pWnd->parent() ) + { + KMdiChildFrm * lpC = pWnd->mdiParent(); + if ( lpC ) + { + if ( lpC->icon() ) + { + QPixmap pixm( *( lpC->icon() ) ); + pWnd->setIcon( pixm ); + } + QString capt( lpC->caption() ); + if ( !bShow ) + lpC->hide(); + lpC->unsetClient( m_undockPositioningOffset ); + m_pMdi->destroyChildButNotItsView( lpC, false ); //Do not focus the new top child , we loose focus... + pWnd->setCaption( capt ); + } + } + } + else + { + if ( pWnd->size().isEmpty() || ( pWnd->size() == QSize( 1, 1 ) ) ) + { + if ( m_pCurrentWindow ) + { + pWnd->setGeometry( QRect( m_pMdi->getCascadePoint( m_pDocumentViews->count() - 1 ), m_pCurrentWindow->size() ) ); + } + else + { + pWnd->setGeometry( QRect( m_pMdi->getCascadePoint( m_pDocumentViews->count() - 1 ), defaultChildFrmSize() ) ); + } + } +#ifdef Q_WS_X11 + if ( mdiMode() == KMdi::ToplevelMode ) + { + XSetTransientForHint( qt_xdisplay(), pWnd->winId(), topLevelWidget() ->winId() ); + } +#endif + + return ; + } + +#ifdef Q_WS_X11 + if ( mdiMode() == KMdi::ToplevelMode ) + { + XSetTransientForHint( qt_xdisplay(), pWnd->winId(), topLevelWidget() ->winId() ); + } +#endif + + // this will show it... + if ( bShow ) + { + activateView( pWnd ); + } + + emit childViewIsDetachedNow( pWnd ); +} + +//============== removeWindowFromMdi ==============// +void KMdiMainFrm::removeWindowFromMdi( KMdiChildView *pWnd ) +{ + Q_UNUSED( pWnd ); + //Closes a child window. sends no close event : simply deletes it + //FIXME something wrong with this, but nobody knows whatcart +#if 0 + if ( !( m_pWinList->removeRef( pWnd ) ) ) + return ; + if ( m_pWinList->count() == 0 ) + m_pCurrentWindow = 0L; + + QObject::disconnect( pWnd, SIGNAL( attachWindow( KMdiChildView*, bool ) ), this, SLOT( attachWindow( KMdiChildView*, bool ) ) ); + QObject::disconnect( pWnd, SIGNAL( detachWindow( KMdiChildView*, bool ) ), this, SLOT( detachWindow( KMdiChildView*, bool ) ) ); + QObject::disconnect( pWnd, SIGNAL( focusInEventOccurs( KMdiChildView* ) ), this, SLOT( activateView( KMdiChildView* ) ) ); + QObject::disconnect( pWnd, SIGNAL( childWindowCloseRequest( KMdiChildView* ) ), this, SLOT( childWindowCloseRequest( KMdiChildView* ) ) ); + QObject::disconnect( pWnd, SIGNAL( clickedInWindowMenu( int ) ), this, SLOT( windowMenuItemActivated( int ) ) ); + QObject::disconnect( pWnd, SIGNAL( clickedInDockMenu( int ) ), this, SLOT( dockMenuItemActivated( int ) ) ); + + if ( m_pTaskBar ) + { + KMdiTaskBarButton * but = m_pTaskBar->getButton( pWnd ); + if ( but != 0L ) + { + QObject::disconnect( pWnd, SIGNAL( tabCaptionChanged( const QString& ) ), but, SLOT( setNewText( const QString& ) ) ); + } + m_pTaskBar->removeWinButton( pWnd ); + } + + if ( m_mdiMode == KMdi::TabPageMode ) + { + if ( m_pWinList->count() == 0 ) + { + if ( !m_pDockbaseAreaOfDocumentViews ) + { + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + } + m_pDockbaseOfTabPage->setDockSite( KDockWidget::DockFullSite ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->manualDock( m_pDockbaseOfTabPage, KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseOfTabPage = m_pDockbaseAreaOfDocumentViews; + m_pClose->hide(); + } + KDockWidget* pDockW = ( KDockWidget* ) pWnd->parentWidget(); + pWnd->reparent( 0L, QPoint( 0, 0 ) ); + pDockW->setWidget( 0L ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + QTabWidget * pTab = ( QTabWidget* ) pDockW->parentWidget() ->parentWidget(); + int cnt = pTab->count(); + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 2 ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 1 ); // different to the one deleted next + } + } + delete pDockW; + if ( m_pWinList->count() == 1 ) + { + m_pWinList->last() ->activate(); // all other views are activated by tab switch + } + } + else if ( pWnd->isAttached() ) + { + pWnd->mdiParent() ->hide(); + m_pMdi->destroyChildButNotItsView( pWnd->mdiParent() ); + } + else + { + // is not attached + if ( m_pMdi->getVisibleChildCount() > 0 ) + { + setActiveWindow(); + m_pCurrentWindow = 0L; + KMdiChildView* pView = m_pMdi->topChild() ->m_pClient; + if ( pView ) + { + pView->activate(); + } + } + else if ( m_pWinList->count() > 0 ) + { + //crash? m_pWinList->last()->activate(); + //crash? m_pWinList->last()->setFocus(); + } + } + + if ( pWnd->isToolView() ) + pWnd->m_bToolView = false; + + if ( !m_pCurrentWindow ) + emit lastChildViewClosed(); +#endif +} + +//============== closeWindow ==============// +void KMdiMainFrm::closeWindow( KMdiChildView *pWnd, bool layoutTaskBar ) +{ + if ( !pWnd ) + return ; + //Closes a child window. sends no close event : simply deletes it + m_pDocumentViews->removeRef( pWnd ); + if ( m_pDocumentViews->count() == 0 ) + m_pCurrentWindow = 0L; + + if ( m_pTaskBar ) + { + m_pTaskBar->removeWinButton( pWnd, layoutTaskBar ); + } + + if ( ( m_mdiMode == KMdi::TabPageMode ) || ( m_mdiMode == KMdi::IDEAlMode ) ) + { + if ( !m_documentTabWidget ) + return ; //oops + if ( m_pDocumentViews->count() == 0 ) + m_pClose->hide(); + pWnd->reparent( 0L, QPoint( 0, 0 ) ); + kdDebug(760) << "-------- 1" << endl; + if ( m_pDocumentViews->count() == 1 ) + { + m_pDocumentViews->last() ->activate(); // all other views are activated by tab switch + } + } + if ( ( m_mdiMode == KMdi::TabPageMode ) || ( m_mdiMode == KMdi::IDEAlMode ) ) + { + if ( m_pDocumentViews->count() == 0 ) + { + if ( !m_pDockbaseAreaOfDocumentViews ) + { + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + } +#if 0 + m_pDockbaseOfTabPage->setDockSite( KDockWidget::DockFullSite ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->manualDock( m_pDockbaseOfTabPage, KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseOfTabPage = m_pDockbaseAreaOfDocumentViews; +#endif + + m_pClose->hide(); + } +#if 0 + KDockWidget* pDockW = ( KDockWidget* ) pWnd->parentWidget(); + pWnd->reparent( 0L, QPoint( 0, 0 ) ); + pDockW->setWidget( 0L ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + QTabWidget * pTab = ( QTabWidget* ) pDockW->parentWidget() ->parentWidget(); + int cnt = pTab->count(); + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 2 ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 1 ); // different to the one deleted next + } + } + delete pDockW; +#endif + + delete pWnd; + if ( m_pDocumentViews->count() == 1 ) + { + m_pDocumentViews->last() ->activate(); // all other views are activated by tab switch + } + } + else if ( pWnd->isAttached() ) + { + m_pMdi->destroyChild( pWnd->mdiParent() ); + } + else + { + delete pWnd; + // is not attached + if ( m_pMdi->getVisibleChildCount() > 0 ) + { + setActiveWindow(); + m_pCurrentWindow = 0L; + KMdiChildView* pView = m_pMdi->topChild() ->m_pClient; + if ( pView ) + { + pView->activate(); + } + } + else if ( m_pDocumentViews->count() > 0 ) + { + if ( m_pDocumentViews->current() ) + { + m_pDocumentViews->current() ->activate(); + m_pDocumentViews->current() ->setFocus(); + } + else + { + m_pDocumentViews->last() ->activate(); + m_pDocumentViews->last() ->setFocus(); + } + } + } + + if ( !m_pCurrentWindow ) + { + d->closeWindowAction->setEnabled(false); + emit lastChildViewClosed(); + } +} + +//================== findWindow =================// +KMdiChildView* KMdiMainFrm::findWindow( const QString& caption ) +{ + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + if ( ( *it )->caption() == caption ) + return ( *it ); + } + return 0L; +} + +//================== activeWindow ===================// +KMdiChildView* KMdiMainFrm::activeWindow() +{ + return m_pCurrentWindow; +} + +//================== windowExists ? =================// +bool KMdiMainFrm::windowExists( KMdiChildView *pWnd, ExistsAs as ) +{ + if ( ( as == ToolView ) || ( as == AnyView ) ) + { + if ( m_pToolViews->contains( pWnd ) ) + return true; + if ( as == ToolView ) + return false; + } + + if ( m_pDocumentViews->findRef( pWnd ) != -1 ) + return true; + + return false; +} + +QPopupMenu * KMdiMainFrm::windowPopup( KMdiChildView * pWnd, bool bIncludeTaskbarPopup ) +{ + m_pWindowPopup->clear(); + if ( bIncludeTaskbarPopup ) + { + m_pWindowPopup->insertItem( i18n( "Window" ), taskBarPopup( pWnd, false ) ); + m_pWindowPopup->insertSeparator(); + } + return m_pWindowPopup; +} + +//================ taskBarPopup =================// +QPopupMenu* KMdiMainFrm::taskBarPopup( KMdiChildView *pWnd, bool /*bIncludeWindowPopup*/ ) +{ + //returns the g_pTaskBarPopup filled according to the KMdiChildView state + m_pTaskBarPopup->clear(); + if ( pWnd->isAttached() ) + { + m_pTaskBarPopup->insertItem( i18n( "Undock" ), pWnd, SLOT( detach() ) ); + m_pTaskBarPopup->insertSeparator(); + if ( pWnd->isMinimized() || pWnd->isMaximized() ) + m_pTaskBarPopup->insertItem( i18n( "Restore" ), pWnd, SLOT( restore() ) ); + if ( !pWnd->isMaximized() ) + m_pTaskBarPopup->insertItem( i18n( "Maximize" ), pWnd, SLOT( maximize() ) ); + if ( !pWnd->isMinimized() ) + m_pTaskBarPopup->insertItem( i18n( "Minimize" ), pWnd, SLOT( minimize() ) ); + } + else + m_pTaskBarPopup->insertItem( i18n( "Dock" ), pWnd, SLOT( attach() ) ); + m_pTaskBarPopup->insertSeparator(); + m_pTaskBarPopup->insertItem( i18n( "Close" ), pWnd, SLOT( close() ) ); + // the window has a view...get the window popup + m_pTaskBarPopup->insertSeparator(); + m_pTaskBarPopup->insertItem( i18n( "Operations" ), windowPopup( pWnd, false ) ); //alvoid recursion + return m_pTaskBarPopup; +} + +void KMdiMainFrm::slotDocCurrentChanged( QWidget* pWidget ) +{ + KMdiChildView * pWnd = static_cast<KMdiChildView*>( pWidget ); + pWnd->m_bMainframesActivateViewIsPending = true; + + bool bActivateNecessary = true; + if ( m_pCurrentWindow != pWnd ) + m_pCurrentWindow = pWnd; + + if ( m_pTaskBar ) + m_pTaskBar->setActiveButton( pWnd ); + + if ( m_documentTabWidget && ( m_mdiMode == KMdi::TabPageMode || m_mdiMode == KMdi::IDEAlMode ) ) + { + m_documentTabWidget->showPage( pWnd ); + pWnd->activate(); + } + else + { + if ( pWnd->isAttached() ) + { + if ( bActivateNecessary && ( m_pMdi->topChild() == pWnd->mdiParent() ) ) + pWnd->activate(); + + pWnd->mdiParent()->raiseAndActivate(); + } + if ( !pWnd->isAttached() ) + { + if ( bActivateNecessary ) + pWnd->activate(); + + m_pMdi->setTopChild( 0L ); // lose focus in the mainframe window + if ( !pWnd->isActiveWindow() ) + pWnd->setActiveWindow(); + + pWnd->raise(); + } + } + if ( !switching() ) + activeWindow()->updateTimeStamp(); + emit collapseOverlapContainers(); + pWnd->m_bMainframesActivateViewIsPending = false; +} + + +void KMdiMainFrm::activateView( KMdiChildView* pWnd ) +{ + pWnd->m_bMainframesActivateViewIsPending = true; + + bool bActivateNecessary = true; + if ( m_pCurrentWindow != pWnd ) + m_pCurrentWindow = pWnd; + else + { + bActivateNecessary = false; + // if this method is called as answer to view->activate(), + // interrupt it because it's not necessary + pWnd->m_bInterruptActivation = true; + } + + if ( m_pTaskBar ) + m_pTaskBar->setActiveButton( pWnd ); + + if ( m_documentTabWidget && m_mdiMode == KMdi::TabPageMode || m_mdiMode == KMdi::IDEAlMode ) + { + m_documentTabWidget->showPage( pWnd ); + pWnd->activate(); + } + else + { + if ( pWnd->isAttached() ) + { + if ( bActivateNecessary && ( m_pMdi->topChild() == pWnd->mdiParent() ) ) + pWnd->activate(); + + pWnd->mdiParent() ->raiseAndActivate(); + } + if ( !pWnd->isAttached() ) + { + if ( bActivateNecessary ) + pWnd->activate(); + + m_pMdi->setTopChild( 0L ); // lose focus in the mainframe window + if ( !pWnd->isActiveWindow() ) + pWnd->setActiveWindow(); + + pWnd->raise(); + } + } + + emit collapseOverlapContainers(); + + pWnd->m_bMainframesActivateViewIsPending = false; +} + +void KMdiMainFrm::taskbarButtonRightClicked( KMdiChildView *pWnd ) +{ + activateView( pWnd ); // set focus + //QApplication::sendPostedEvents(); + taskBarPopup( pWnd, true ) ->popup( QCursor::pos() ); +} + +void KMdiMainFrm::childWindowCloseRequest( KMdiChildView *pWnd ) +{ + KMdiViewCloseEvent * ce = new KMdiViewCloseEvent( pWnd ); + QApplication::postEvent( this, ce ); +} + +bool KMdiMainFrm::event( QEvent* e ) +{ + if ( e->type() == QEvent::User ) + { + KMdiChildView * pWnd = ( KMdiChildView* ) ( ( KMdiViewCloseEvent* ) e )->data(); + if ( pWnd != 0L ) + closeWindow( pWnd ); + return true; + // A little hack: If MDI child views are moved implicietly by moving + // the main widget they should know this too. Unfortunately there seems to + // be no way to catch the move start / move stop situations for the main + // widget in a clean way. (There is no MouseButtonPress/Release or + // something like that.) Therefore we do the following: When we get the + // "first" move event we start a timer and interprete it as "drag begin". + // If we get the next move event and the timer is running we restart the + // timer and don't do anything else. If the timer elapses (this meens we + // haven't had any move event for a while) we interprete this as "drag + // end". If the moving didn't stop actually, we will later get another + // "drag begin", so we get a drag end too much, but this would be the same + // as if the user would stop moving for a little while. + // Actually we seem to be lucky that the timer does not elapse while we + // are moving -> so we have no obsolete drag end / begin + } + else if ( isVisible() && e->type() == QEvent::Move ) + { + if ( m_pDragEndTimer->isActive() ) + { + // this is not the first move -> stop old timer + m_pDragEndTimer->stop(); + } + else + { + // this is the first move -> send the drag begin to all concerned views + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrmDragBeginEvent dragBeginEvent( 0L ); + QApplication::sendEvent( ( *it ), &dragBeginEvent ); + } + } + m_pDragEndTimer->start( 200, true ); // single shot after 200 ms + } + + return DockMainWindow::event( e ); +} + +bool KMdiMainFrm::eventFilter( QObject * /*obj*/, QEvent *e ) +{ + if ( e->type() == QEvent::Resize && m_mdiMode == KMdi::ToplevelMode ) + { + verifyToplevelHeight(); + return false; //let the rest of the resize magic do its work + } + + if ( e->type() == QEvent::FocusIn ) + { + QFocusEvent * pFE = ( QFocusEvent* ) e; + if ( pFE->reason() == QFocusEvent::ActiveWindow ) + { + if ( m_pCurrentWindow && !m_pCurrentWindow->isHidden() && + !m_pCurrentWindow->isAttached() && m_pMdi->topChild() ) + { + return true; // eat the event + } + } + if ( m_pMdi ) + { + static bool focusTCIsPending = false; + if ( !focusTCIsPending && m_mdiMode == KMdi::ChildframeMode ) + { + focusTCIsPending = true; + m_pMdi->focusTopChild(); + focusTCIsPending = false; + } + } + } + else if ( e->type() == QEvent::KeyRelease ) + { + if ( switching() ) + { + KAction * a = actionCollection() ->action( "view_last_window" ) ; + if ( a ) + { + const KShortcut cut( a->shortcut() ); + const KKeySequence& seq = cut.seq( 0 ); + const KKey& key = seq.key( 0 ); + int modFlags = key.modFlags(); + int state = ( ( QKeyEvent * ) e ) ->state(); + KKey key2( ( QKeyEvent * ) e ); + + /** these are quite some assumptions: + * The key combination uses exactly one modifier key + * The WIN button in KDE is the meta button in Qt + **/ + if ( state != ( ( QKeyEvent * ) e ) ->stateAfter() && + ( ( modFlags & KKey::CTRL ) > 0 ) == ( ( state & Qt::ControlButton ) > 0 ) && + ( ( modFlags & KKey::ALT ) > 0 ) == ( ( state & Qt::AltButton ) > 0 ) && + ( ( modFlags & KKey::WIN ) > 0 ) == ( ( state & Qt::MetaButton ) > 0 ) ) + { + activeWindow() ->updateTimeStamp(); + setSwitching( false ); + } + return true; + } + else + { + kdDebug(760) << "KAction( \"view_last_window\") not found." << endl; + } + } + } + return false; // standard event processing +} + +/** + * close all views + */ +void KMdiMainFrm::closeAllViews() +{ + //save the children first to a list, as removing invalidates our iterator + QValueList<KMdiChildView*> children; + for ( KMdiChildView * w = m_pDocumentViews->first();w;w = m_pDocumentViews->next() ) + { + children.append( w ); + } + QValueListIterator<KMdiChildView *> childIt; + for ( childIt = children.begin(); childIt != children.end(); ++childIt ) + { + ( *childIt )->close(); + } +} + + +/** + * iconify all views + */ +void KMdiMainFrm::iconifyAllViews() +{ + kdDebug(760) << k_funcinfo << "minimizing all the views" << endl; + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + ( *it )->minimize(); +} + +/** + * closes the view of the active (topchild) window + */ +void KMdiMainFrm::closeActiveView() +{ + kdDebug(760) << k_funcinfo << "closing the active view" << endl; + if ( m_pCurrentWindow ) + m_pCurrentWindow->close(); +} + +/** find the root dockwidgets and store their geometry */ +void KMdiMainFrm::findRootDockWidgets( QPtrList<KDockWidget>* rootDockWidgetList, QValueList<QRect>* positionList ) +{ + //nothing is valid + if ( !rootDockWidgetList && !positionList ) + return ; + + // since we set some windows to toplevel, we must consider the window manager's window frame + const int frameBorderWidth = 7; // @todo: Can we / do we need to ask the window manager? + const int windowTitleHeight = 10; // @todo: -"- + + QObjectList* pObjList = queryList( "KDockWidget" ); + if ( pObjList->isEmpty() ) + pObjList = queryList( "KDockWidget_Compat::KDockWidget" ); + + QObjectListIt it( *pObjList ); + // for all dockwidgets (which are children of this mainwindow) + while ( ( *it ) ) + { + KDockWidget* dockWindow = 0L; /* pDockW */ + KDockWidget* rootDockWindow = 0L; /* pRootDockWindow */ + KDockWidget* undockCandidate = 0L; /* pUndockCandidate */ + QWidget* pW = static_cast<QWidget*>( ( *it ) ); + + // find the oldest ancestor of the current dockwidget that can be undocked + while ( !pW->isTopLevel() ) + { + if ( ::qt_cast<KDockWidget*>( pW ) || pW->inherits( "KDockWidget_Compat::KDockWidget" ) ) + { + undockCandidate = static_cast<KDockWidget*>( pW ); + if ( undockCandidate->enableDocking() != KDockWidget::DockNone ) + rootDockWindow = undockCandidate; + } + pW = pW->parentWidget(); + } + + if ( rootDockWindow ) + { + // if that oldest ancestor is not already in the list, append it + bool found = false; + if ( !rootDockWidgetList->isEmpty() ) + { + QPtrListIterator<KDockWidget> it2( *rootDockWidgetList ); + for ( ; it2.current() && !found; ++it2 ) + { + dockWindow = it2.current(); + if ( dockWindow == rootDockWindow ) + found = true; + } + } + + if ( !found || rootDockWidgetList->isEmpty() ) + { + rootDockWidgetList->append( dockWindow ); + kdDebug(760) << k_funcinfo << "Appending " << rootDockWindow << " to our list of " << + "root dock windows" << endl; + QPoint p = rootDockWindow->mapToGlobal( rootDockWindow->pos() ) - rootDockWindow->pos(); + QRect r( p.x(), p.y() + m_undockPositioningOffset.y(), + rootDockWindow->width() - windowTitleHeight - frameBorderWidth * 2, + rootDockWindow->height() - windowTitleHeight - frameBorderWidth * 2 ); + positionList->append( r ); + } + } + ++it; + } + delete pObjList; +} + +/** + * undocks all view windows (unix-like) + */ +void KMdiMainFrm::switchToToplevelMode() +{ + if ( m_mdiMode == KMdi::ToplevelMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::ToplevelMode ); + return ; + } + + KMdi::MdiMode oldMdiMode = m_mdiMode; + + const int frameBorderWidth = 7; // @todo: Can we / do we need to ask the window manager? + setUndockPositioningOffset( QPoint( 0, ( m_pTaskBar ? m_pTaskBar->height() : 0 ) + frameBorderWidth ) ); + + // 1.) select the dockwidgets to be undocked and store their geometry + QPtrList<KDockWidget> rootDockWidgetList; + QValueList<QRect> positionList; + + // 2.) undock the MDI views of KMDI + switch( oldMdiMode ) + { + case KMdi::ChildframeMode: + finishChildframeMode(); + break; + case KMdi::TabPageMode: + finishTabPageMode(); + break; + case KMdi::IDEAlMode: + finishIDEAlMode(); + findRootDockWidgets( &rootDockWidgetList, &positionList ); + break; + default: + break; //do nothing + } + + // 3.) undock all these found oldest ancestors (being KDockWidgets) + QPtrListIterator<KDockWidget> kdwit( rootDockWidgetList ); + for ( ; ( *kdwit ); ++kdwit ) + ( *kdwit )->undock(); + + // 4.) recreate the MDI childframe area and hide it + if ( oldMdiMode == KMdi::TabPageMode || oldMdiMode == KMdi::IDEAlMode ) + { + if ( !m_pDockbaseAreaOfDocumentViews ) + { + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + } + // set this dock to main view + setView( m_pDockbaseAreaOfDocumentViews ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + } + // QApplication::sendPostedEvents(); //why do we need to empty the event queue? + if ( !parentWidget() ) + { + //if we don't have a parent widget ( which i expect we wouldn't ) + //make sure we take into account the size of the docks provided by + //QMainWindow + int topDockHeight = topDock() ? topDock()->height() : 0; + int bottomDockHeight = bottomDock() ? bottomDock()->height() : 0; + int menuBarHeight = hasMenuBar() ? menuBar()->height() : 0; + if ( m_pDocumentViews->count() != 0 ) + setFixedHeight( height() - m_pDockbaseAreaOfDocumentViews->height() ); + else + { + kdDebug(760) << k_funcinfo << "height is: " << height() << endl; + kdDebug(760) << k_funcinfo << "top dock height: " << topDockHeight << endl; + kdDebug(760) << k_funcinfo << "bottom dock height: " << bottomDockHeight << endl; + kdDebug(760) << k_funcinfo << "menu bar height: " << menuBarHeight << endl; + kdDebug(760) << k_funcinfo << "dock base area height: " << m_pDockbaseAreaOfDocumentViews->height() << endl; + setFixedHeight( topDockHeight + menuBarHeight ); + } + } + + //FIXME although i don't know what to fix + // 5. show the child views again + QPtrListIterator<KMdiChildView> kmdicvit( *m_pDocumentViews ); + for ( kmdicvit.toFirst(); ( *kmdicvit ); ++kmdicvit ) + { +#ifdef Q_WS_X11 + XSetTransientForHint( qt_xdisplay(), ( *kmdicvit )->winId(), winId() ); +#endif + ( *kmdicvit )->show(); + } + + // 6.) reset all memorized positions of the undocked ones and show them again + QValueList<QRect>::Iterator qvlqrit; + QValueList<QRect>::Iterator qvlEnd = positionList.end(); + for ( kmdicvit.toFirst(), qvlqrit = positionList.begin() ; ( *kmdicvit ) && qvlqrit != qvlEnd; ++kmdicvit, ++qvlqrit ) + { + ( *kmdicvit )->setGeometry( ( *qvlqrit ) ); + ( *kmdicvit )->show(); + } + + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockNone ); + m_mdiMode = KMdi::ToplevelMode; + + kdDebug(760) << k_funcinfo << "Switch to toplevel mode completed" << endl; + emit mdiModeHasBeenChangedTo( KMdi::ToplevelMode ); + +} + +void KMdiMainFrm::finishToplevelMode() +{ + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); +} + +/** + * docks all view windows (Windows-like) + */ +void KMdiMainFrm::switchToChildframeMode() +{ + if ( m_mdiMode == KMdi::ChildframeMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::ChildframeMode ); + return ; + } + + QPtrList<KDockWidget> rootDockWidgetList; + QValueList<QRect> positionList; + + if ( m_mdiMode == KMdi::TabPageMode ) + { + kdDebug(760) << k_funcinfo << "finishing tab page mode" << endl; + // select the dockwidgets to be undocked and store their geometry + findRootDockWidgets( &rootDockWidgetList, &positionList ); + kdDebug(760) << k_funcinfo << "Found " << rootDockWidgetList.count() << " widgets to undock" << endl; + + // undock all these found oldest ancestors (being KDockWidgets) + QPtrListIterator<KDockWidget> it( rootDockWidgetList ); + for ( ; ( *it ) ; ++it ) + ( *it )->undock(); + + finishTabPageMode(); + } + else if ( m_mdiMode == KMdi::ToplevelMode ) + { + finishToplevelMode(); + } + else if ( m_mdiMode == KMdi::IDEAlMode ) + { + kdDebug(760) << k_funcinfo << "finishing ideal mode" << endl; + finishIDEAlMode( false ); + + // select the dockwidgets to be undocked and store their geometry + findRootDockWidgets( &rootDockWidgetList, &positionList ); + kdDebug(760) << k_funcinfo << "Found " << rootDockWidgetList.count() << " widgets to undock" << endl; + + // undock all these found oldest ancestors (being KDockWidgets) + QPtrListIterator<KDockWidget> it( rootDockWidgetList ); + for ( ; ( *it ) ; ++it ) + ( *it )->undock(); + + m_mdiMode = KMdi::TabPageMode; + finishTabPageMode(); + m_mdiMode = KMdi::IDEAlMode; + } + + if ( !m_pDockbaseAreaOfDocumentViews ) + { + // cover KMdi's childarea by a dockwidget + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + kdDebug(760) << k_funcinfo << "childarea is now covered by a dockwidget" << endl; + } + + if ( m_pDockbaseAreaOfDocumentViews->isTopLevel() ) + { + // set this dock to main view + setView( m_pDockbaseAreaOfDocumentViews ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + kdDebug(760) << k_funcinfo << "Dock base area has been set to the main view" << endl; + } + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); //JW + m_pDockbaseAreaOfDocumentViews->show(); + + if ( ( m_mdiMode == KMdi::TabPageMode ) || ( m_mdiMode == KMdi::IDEAlMode ) ) + { + kdDebug(760) << k_funcinfo << "trying to dock back the undock toolviews" << endl; + QPtrListIterator<KDockWidget> it( rootDockWidgetList ); + for ( ; ( *it ); ++it ) + ( *it )->dockBack(); + } + + if ( m_mdiMode == KMdi::ToplevelMode && m_pTempDockSession ) + { + // restore the old dock scenario which we memorized at the time we switched to toplevel mode + kdDebug(760) << k_funcinfo << "Restoring old dock scenario memorized from toplevel mode" << endl; + QDomElement oldDockState = m_pTempDockSession->namedItem( "cur_dock_state" ).toElement(); + readDockConfig( oldDockState ); + } + + KMdi::MdiMode oldMdiMode = m_mdiMode; + m_mdiMode = KMdi::ChildframeMode; + + //FIXME although i don't know what to fix. + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + KMdiChildView* pView = ( *it ); + if ( !pView->isToolView() && pView->isAttached() ) + attachWindow( pView, true ); + } + for ( it.toFirst(); ( *it ); ++it ) + { + KMdiChildView* pView = ( *it ); + if ( !pView->isToolView() ) + pView->show(); + } + if ( ( oldMdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + setMinimumHeight( m_oldMainFrmMinHeight ); + setMaximumHeight( m_oldMainFrmMaxHeight ); + resize( width(), m_oldMainFrmHeight ); + m_oldMainFrmHeight = 0; + kdDebug(760) << k_funcinfo << "left top level mode completely" << endl; + emit leftTopLevelMode(); + } + emit mdiModeHasBeenChangedTo( KMdi::ChildframeMode ); +} + +void KMdiMainFrm::finishChildframeMode() +{ + // save the old dock scenario of the dockwidget-like tool views to a DOM tree + kdDebug(760) << k_funcinfo << "saving the current dock scenario" << endl; + delete m_pTempDockSession; + m_pTempDockSession = new QDomDocument( "docksession" ); + QDomElement curDockState = m_pTempDockSession->createElement( "cur_dock_state" ); + m_pTempDockSession->appendChild( curDockState ); + writeDockConfig( curDockState ); + + // detach all non-tool-views to toplevel + kdDebug(760) << k_funcinfo << "detaching all document views and moving them to toplevel" << endl; + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + KMdiChildView* pView = ( *it ); + if ( pView->isToolView() ) + continue; + if ( pView->isAttached() ) + { + if ( pView->isMaximized() ) + pView->mdiParent()->setGeometry( 0, 0, m_pMdi->width(), m_pMdi->height() ); + detachWindow( pView, false ); + } + } +} + +/** + * Docks all view windows (Windows-like) + */ +void KMdiMainFrm::switchToTabPageMode() +{ + if ( m_mdiMode == KMdi::TabPageMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::TabPageMode ); + return ; // nothing need to be done + } + + switch( m_mdiMode ) + { + case KMdi::ChildframeMode: + finishChildframeMode(); + break; + case KMdi::ToplevelMode: + finishToplevelMode(); + break; + case KMdi::IDEAlMode: + finishIDEAlMode( false ); + emit mdiModeHasBeenChangedTo( KMdi::TabPageMode ); + m_mdiMode = KMdi::TabPageMode; + return; + break; + default: + break; + } + + setupTabbedDocumentViewSpace(); + m_mdiMode = KMdi::TabPageMode; + if ( m_pCurrentWindow ) + m_pCurrentWindow->setFocus(); + + m_pTaskBar->switchOn( false ); + + if ( m_pClose ) + { + QObject::connect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + if ( m_pDocumentViews->count() > 0 ) + m_pClose->show(); + } + else + kdDebug(760) << "close button nonexistant. strange things might happen" << endl; + + kdDebug(760) << "Switch to tab page mode complete" << endl; + emit mdiModeHasBeenChangedTo( KMdi::TabPageMode ); +} + +void KMdiMainFrm::finishTabPageMode() +{ + // if tabified, release all views from their docking covers + if ( m_mdiMode == KMdi::TabPageMode ) + { + m_pClose->hide(); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; it.current(); ++it ) + { + KMdiChildView* pView = it.current(); + if ( pView->isToolView() ) + continue; + kdDebug(760) << "KMdiMainFrm::finishTabPageMode: in loop" << endl; + QSize mins = pView->minimumSize(); + QSize maxs = pView->maximumSize(); + QSize sz = pView->size(); + QWidget* pParent = pView->parentWidget(); + QPoint p( pParent->mapToGlobal( pParent->pos() ) - pParent->pos() + m_undockPositioningOffset ); + m_documentTabWidget->removePage( pView ); + pView->reparent( 0, 0, p ); + // pView->reparent(0,0,p); + pView->resize( sz ); + pView->setMinimumSize( mins.width(), mins.height() ); + pView->setMaximumSize( maxs.width(), maxs.height() ); + // ((KDockWidget*)pParent)->undock(); // this destroys the dockwiget cover, too + // pParent->close(); + // delete pParent; + // if (centralWidget() == pParent) { + // setCentralWidget(0L); // avoid dangling pointer + // } + } + delete m_documentTabWidget; + m_documentTabWidget = 0; + m_pTaskBar->switchOn( true ); + } +} + + + +void KMdiMainFrm::setupTabbedDocumentViewSpace() +{ + // resize to childframe mode size of the mainwindow if we were in toplevel mode + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + setMinimumHeight( m_oldMainFrmMinHeight ); + setMaximumHeight( m_oldMainFrmMaxHeight ); + resize( width(), m_oldMainFrmHeight ); + m_oldMainFrmHeight = 0; + //qDebug("TopLevelMode off"); + emit leftTopLevelMode(); + QApplication::sendPostedEvents(); + + // restore the old dock szenario which we memorized at the time we switched to toplevel mode + if ( m_pTempDockSession ) + { + QDomElement oldDockState = m_pTempDockSession->namedItem( "cur_dock_state" ).toElement(); + readDockConfig( oldDockState ); + } + } + +#if 0 + if ( m_pDockbaseOfTabPage != m_pDockbaseAreaOfDocumentViews ) + { + delete m_pDockbaseOfTabPage; + m_pDockbaseOfTabPage = m_pDockbaseAreaOfDocumentViews; + } +#endif + delete m_documentTabWidget; + m_documentTabWidget = new KMdiDocumentViewTabWidget( m_pDockbaseAreaOfDocumentViews ); + connect( m_documentTabWidget, SIGNAL( currentChanged( QWidget* ) ), this, SLOT( slotDocCurrentChanged( QWidget* ) ) ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_documentTabWidget ); + m_documentTabWidget->show(); + QPtrListIterator<KMdiChildView> it4( *m_pDocumentViews ); + for ( ; it4.current(); ++it4 ) + { + KMdiChildView* pView = it4.current(); + m_documentTabWidget->addTab( pView, pView->icon() ? *( pView->icon() ) : QPixmap(), pView->tabCaption() ); + /* + connect(pView,SIGNAL(iconOrCaptionUdpated(QWidget*,QPixmap,const QString&)), + m_documentTabWidget,SLOT(updateView(QWidget*,QPixmap,const QString&))); + */ + connect( pView, SIGNAL( iconUpdated( QWidget*, QPixmap ) ), m_documentTabWidget, SLOT( updateIconInView( QWidget*, QPixmap ) ) ); + connect( pView, SIGNAL( captionUpdated( QWidget*, const QString& ) ), m_documentTabWidget, SLOT( updateCaptionInView( QWidget*, const QString& ) ) ); + + } +} + + +void KMdiMainFrm::setIDEAlModeStyle( int flags ) +{ + d->m_styleIDEAlMode = flags; // see KMultiTabBar for the first 3 bits + if ( m_leftContainer ) + { + KMdiDockContainer * tmpL = ( KMdiDockContainer* ) ( m_leftContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpL ) + tmpL->setStyle( flags ); + } + + if ( m_rightContainer ) + { + KMdiDockContainer * tmpR = ( KMdiDockContainer* ) ( m_rightContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpR ) + tmpR->setStyle( flags ); + } + + if ( m_topContainer ) + { + KMdiDockContainer * tmpT = ( KMdiDockContainer* ) ( m_topContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpT ) + tmpT->setStyle( flags ); + } + + if ( m_bottomContainer ) + { + KMdiDockContainer * tmpB = ( KMdiDockContainer* ) ( m_bottomContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpB ) + tmpB->setStyle( flags ); + } +} + +void KMdiMainFrm::setToolviewStyle( int flag ) +{ + if ( m_mdiMode == KMdi::IDEAlMode ) + { + setIDEAlModeStyle( flag ); + } + d->m_toolviewStyle = flag; + bool toolviewExists = false; + QMap<QWidget*, KMdiToolViewAccessor*>::Iterator it; + for ( it = m_pToolViews->begin(); it != m_pToolViews->end(); ++it ) + { + KDockWidget *dockWidget = dynamic_cast<KDockWidget*>( it.data()->wrapperWidget() ); + if ( dockWidget ) + { + switch ( flag ) + { + case KMdi::IconOnly: + dockWidget->setTabPageLabel( QString::null ); + dockWidget->setPixmap( *( it.data()->wrappedWidget()->icon() ) ); + break; + case KMdi::TextOnly: + dockWidget->setPixmap(); //FIXME: Does not hide the icon in the IDEAl mode. + dockWidget->setTabPageLabel( it.data()->wrappedWidget()->caption() ); + break; + case KMdi::TextAndIcon: + dockWidget->setPixmap( *( it.data()->wrappedWidget()->icon() ) ); + dockWidget->setTabPageLabel( it.data()->wrappedWidget()->caption() ); + default: + break; + } + toolviewExists = true; + } + } + + if ( toolviewExists ) + { + //workaround for the above FIXME to make switching to TextOnly mode work in IDEAl as well. Be sure that this version of switch* is called. + if ( m_mdiMode == KMdi::IDEAlMode && flag == KMdi::TextOnly ) + { + KMdiMainFrm::switchToTabPageMode(); + KMdiMainFrm::switchToIDEAlMode(); + } + else + { + writeDockConfig(); + readDockConfig(); + } + } +} + +/** + * Docks all view windows (Windows-like) + */ +void KMdiMainFrm::switchToIDEAlMode() +{ + kdDebug(760) << k_funcinfo << "switching to IDEAl mode" << endl; + + if ( m_mdiMode == KMdi::IDEAlMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::IDEAlMode ); + return ; // nothing need to be done + } + + switch( m_mdiMode ) + { + case KMdi::ChildframeMode: + finishChildframeMode(); + break; + case KMdi::ToplevelMode: + finishToplevelMode(); + break; + case KMdi::TabPageMode: + m_mdiMode = KMdi::IDEAlMode; + setupToolViewsForIDEALMode(); + emit mdiModeHasBeenChangedTo( KMdi::IDEAlMode ); + return; + break; + default: + break; + } + + setupTabbedDocumentViewSpace(); + m_mdiMode = KMdi::IDEAlMode; + setupToolViewsForIDEALMode(); + + if ( m_pCurrentWindow ) + m_pCurrentWindow->setFocus(); + + m_pTaskBar->switchOn( false ); + + if ( m_pClose ) + { + QObject::connect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + if ( m_pDocumentViews->count() > 0 ) + m_pClose->show(); + } + else + kdWarning(760) << k_funcinfo << "close button pointer does not exist!" << endl; + + kdDebug(760) << k_funcinfo << "switch to IDEAl mode complete" << endl; + + emit mdiModeHasBeenChangedTo( KMdi::IDEAlMode ); +} + + +void KMdiMainFrm::dockToolViewsIntoContainers( QPtrList<KDockWidget>& widgetsToReparent, KDockWidget *container ) +{ + QPtrListIterator<KDockWidget> it( widgetsToReparent ); + for ( ; ( *it ); ++it ) + { + ( *it )->manualDock( container, KDockWidget::DockCenter, 20 ); + ( *it )->loseFormerBrotherDockWidget(); + } +} + +void KMdiMainFrm::findToolViewsDockedToMain( QPtrList<KDockWidget>* list, KDockWidget::DockPosition dprtmw ) +{ + KDockWidget* mainDock = getMainDockWidget(); + if ( mainDock->parentDockTabGroup() ) + { + mainDock = dynamic_cast<KDockWidget*>( mainDock->parentDockTabGroup()->parent() ); + // FIXME: will likely crash below due to unchecked cast + } + + if ( !mainDock ) + { + kdDebug(760) << k_funcinfo << "mainDock invalid. No main dock widget found." << endl; + return; + } + + KDockWidget* widget = mainDock->findNearestDockWidget( dprtmw ); + if ( widget && widget->parentDockTabGroup() ) + { + widget = static_cast<KDockWidget*>( widget->parentDockTabGroup() ->parent() ); + + if ( widget ) + { + KDockTabGroup* tg = dynamic_cast<KDockTabGroup*>( widget->getWidget() ); + if ( tg ) + { + kdDebug(760) << k_funcinfo << "KDockTabGroup found" << endl; + for ( int i = 0;i < tg->count();i++ ) + list->append( static_cast<KDockWidget*>( tg->page( i ) ) ); + } + else + list->append( widget ); + } + else + kdDebug(760) << k_funcinfo << "no widget found" << endl; + } + else + kdDebug(760) << "No main dock widget found" << endl; +} + + +void KMdiMainFrm::setupToolViewsForIDEALMode() +{ + m_leftContainer = createDockWidget( "KMdiDock::leftDock", SmallIcon( "misc" ), 0L, "Left Dock" ); + m_rightContainer = createDockWidget( "KMdiDock::rightDock", SmallIcon( "misc" ), 0L, "Right Dock" ); + m_topContainer = createDockWidget( "KMdiDock::topDock", SmallIcon( "misc" ), 0L, "Top Dock" ); + m_bottomContainer = createDockWidget( "KMdiDock::bottomDock", SmallIcon( "misc" ), 0L, "Bottom Dock" ); + + KDockWidget *mainDock = getMainDockWidget(); + KDockWidget *w = mainDock; + if ( mainDock->parentDockTabGroup() ) + w = static_cast<KDockWidget*>( mainDock->parentDockTabGroup()->parent() ); + + QPtrList<KDockWidget> leftReparentWidgets; + QPtrList<KDockWidget> rightReparentWidgets; + QPtrList<KDockWidget> bottomReparentWidgets; + QPtrList<KDockWidget> topReparentWidgets; + + if ( mainDock->parentDockTabGroup() ) + mainDock = static_cast<KDockWidget*>( mainDock->parentDockTabGroup() ->parent() ); + + findToolViewsDockedToMain( &leftReparentWidgets, KDockWidget::DockLeft ); + findToolViewsDockedToMain( &rightReparentWidgets, KDockWidget::DockRight ); + findToolViewsDockedToMain( &bottomReparentWidgets, KDockWidget::DockBottom ); + findToolViewsDockedToMain( &topReparentWidgets, KDockWidget::DockTop ); + + mainDock->setEnableDocking( KDockWidget::DockNone ); //::DockCorner); + mainDock->setDockSite( KDockWidget::DockCorner ); + + + KMdiDockContainer *tmpDC; + m_leftContainer->setWidget( tmpDC = new KMdiDockContainer( m_leftContainer, this, KDockWidget::DockLeft, d->m_styleIDEAlMode ) ); + m_leftContainer->setEnableDocking( KDockWidget::DockLeft ); + m_leftContainer->manualDock( mainDock, KDockWidget::DockLeft, 20 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleLeft() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_rightContainer->setWidget( tmpDC = new KMdiDockContainer( m_rightContainer, this, KDockWidget::DockRight, d->m_styleIDEAlMode ) ); + m_rightContainer->setEnableDocking( KDockWidget::DockRight ); + m_rightContainer->manualDock( mainDock, KDockWidget::DockRight, 80 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleRight() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_topContainer->setWidget( tmpDC = new KMdiDockContainer( m_topContainer, this, KDockWidget::DockTop, d->m_styleIDEAlMode ) ); + m_topContainer->setEnableDocking( KDockWidget::DockTop ); + m_topContainer->manualDock( mainDock, KDockWidget::DockTop, 20 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleTop() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_bottomContainer->setWidget( tmpDC = new KMdiDockContainer( m_bottomContainer, this, KDockWidget::DockBottom, d->m_styleIDEAlMode ) ); + m_bottomContainer->setEnableDocking( KDockWidget::DockBottom ); + m_bottomContainer->manualDock( mainDock, KDockWidget::DockBottom, 80 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleBottom() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_leftContainer->setDockSite( KDockWidget::DockCenter ); + m_rightContainer->setDockSite( KDockWidget::DockCenter ); + m_topContainer->setDockSite( KDockWidget::DockCenter ); + m_bottomContainer->setDockSite( KDockWidget::DockCenter ); + + dockToolViewsIntoContainers( leftReparentWidgets, m_leftContainer ); + dockToolViewsIntoContainers( rightReparentWidgets, m_rightContainer ); + dockToolViewsIntoContainers( bottomReparentWidgets, m_bottomContainer ); + dockToolViewsIntoContainers( topReparentWidgets, m_topContainer ); + + + dockManager->setSpecialLeftDockContainer( m_leftContainer ); + dockManager->setSpecialRightDockContainer( m_rightContainer ); + dockManager->setSpecialTopDockContainer( m_topContainer ); + dockManager->setSpecialBottomDockContainer( m_bottomContainer ); + + + ( ( KMdiDockContainer* ) ( m_leftContainer->getWidget() ) ) ->hideIfNeeded(); + ( ( KMdiDockContainer* ) ( m_rightContainer->getWidget() ) ) ->hideIfNeeded(); + ( ( KMdiDockContainer* ) ( m_topContainer->getWidget() ) ) ->hideIfNeeded(); + ( ( KMdiDockContainer* ) ( m_bottomContainer->getWidget() ) ) ->hideIfNeeded(); + +} + + + +void KMdiMainFrm::finishIDEAlMode( bool full ) +{ + // if tabified, release all views from their docking covers + if ( m_mdiMode == KMdi::IDEAlMode ) + { + assert( m_pClose ); + m_pClose->hide(); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + + + QStringList leftNames; + leftNames = prepareIdealToTabs( m_leftContainer ); + int leftWidth = m_leftContainer->width(); + + QStringList rightNames; + rightNames = prepareIdealToTabs( m_rightContainer ); + int rightWidth = m_rightContainer->width(); + + QStringList topNames; + topNames = prepareIdealToTabs( m_topContainer ); + int topHeight = m_topContainer->height(); + + QStringList bottomNames; + bottomNames = prepareIdealToTabs( m_bottomContainer ); + int bottomHeight = m_bottomContainer->height(); + + + kdDebug(760) << "leftNames" << leftNames << endl; + kdDebug(760) << "rightNames" << rightNames << endl; + kdDebug(760) << "topNames" << topNames << endl; + kdDebug(760) << "bottomNames" << bottomNames << endl; + + delete m_leftContainer; + m_leftContainer = 0; + delete m_rightContainer; + m_rightContainer = 0; + delete m_bottomContainer; + m_bottomContainer = 0; + delete m_topContainer; + m_topContainer = 0; + + + idealToolViewsToStandardTabs( bottomNames, KDockWidget::DockBottom, bottomHeight ); + idealToolViewsToStandardTabs( leftNames, KDockWidget::DockLeft, leftWidth ); + idealToolViewsToStandardTabs( rightNames, KDockWidget::DockRight, rightWidth ); + idealToolViewsToStandardTabs( topNames, KDockWidget::DockTop, topHeight ); + + QApplication::sendPostedEvents(); + + if ( !full ) + return ; + + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; it.current(); ++it ) + { + KMdiChildView* pView = it.current(); + if ( pView->isToolView() ) + continue; + QSize mins = pView->minimumSize(); + QSize maxs = pView->maximumSize(); + QSize sz = pView->size(); + QWidget* pParent = pView->parentWidget(); + QPoint p( pParent->mapToGlobal( pParent->pos() ) - pParent->pos() + m_undockPositioningOffset ); + pView->reparent( 0, 0, p ); + pView->reparent( 0, 0, p ); + pView->resize( sz ); + pView->setMinimumSize( mins.width(), mins.height() ); + pView->setMaximumSize( maxs.width(), maxs.height() ); + KDockWidget* pDockW = 0L; + // find the oldest ancestor of the current dockwidget that can be undocked + do + { + if ( pParent->inherits( "KDockWidget" ) || pParent->inherits( "KDockWidget_Compat::KDockWidget" ) ) + { + pDockW = ( KDockWidget* ) pParent; + pDockW->undock(); // this destroys the dockwiget cover, too + if ( pParent != m_pDockbaseAreaOfDocumentViews ) + { + pParent->close(); + delete pParent; + } + } + else + { + pParent = pParent->parentWidget(); + } + } + while ( pParent && !pDockW ); + if ( centralWidget() == pParent ) + { + setCentralWidget( 0L ); // avoid dangling pointer + } + } + m_pTaskBar->switchOn( true ); + + } + +} + +QStringList KMdiMainFrm::prepareIdealToTabs( KDockWidget* container ) +{ + KDockContainer * pDW = dynamic_cast<KDockContainer*>( container->getWidget() ); + QStringList widgetNames = ( ( KMdiDockContainer* ) pDW ) ->containedWidgets(); + for ( QStringList::iterator it = widgetNames.begin();it != widgetNames.end();++it ) + { + KDockWidget* dw = ( KDockWidget* ) manager() ->getDockWidgetFromName( *it ); + dw->undock(); + dw->setLatestKDockContainer( 0 ); + dw->loseFormerBrotherDockWidget(); + } + return widgetNames; +} + +void KMdiMainFrm::idealToolViewsToStandardTabs( QStringList widgetNames, KDockWidget::DockPosition pos, int size ) +{ + Q_UNUSED( size ) + + KDockWidget * mainDock = getMainDockWidget(); + if ( mainDock->parentDockTabGroup() ) + { + mainDock = static_cast<KDockWidget*>( mainDock->parentDockTabGroup() ->parent() ); + } + + if ( widgetNames.count() > 0 ) + { + QStringList::iterator it = widgetNames.begin(); + KDockWidget *dwpd = manager() ->getDockWidgetFromName( *it ); + if ( !dwpd ) + { + kdDebug(760) << "Fatal error in finishIDEAlMode" << endl; + return ; + } + dwpd->manualDock( mainDock, pos, 20 ); + ++it; + for ( ;it != widgetNames.end();++it ) + { + KDockWidget *tmpdw = manager() ->getDockWidgetFromName( *it ); + if ( !tmpdw ) + { + kdDebug(760) << "Fatal error in finishIDEAlMode" << endl; + return ; + } + tmpdw->manualDock( dwpd, KDockWidget::DockCenter, 20 ); + } + +#if 0 + QWidget *wid = dwpd->parentDockTabGroup(); + if ( !wid ) + wid = dwpd; + wid->setGeometry( 0, 0, 20, 20 ); + /* wid->resize( + ((pos==KDockWidget::DockLeft) || (pos==KDockWidget::DockRight))?size:wid->width(), + ((pos==KDockWidget::DockLeft) || (pos==KDockWidget::DockRight))?wid->height():size); + */ +#endif + + } + +} + + +/** + * redirect the signal for insertion of buttons to an own slot + * that means: If the menubar (where the buttons should be inserted) is given, + * QextMDI can insert them automatically. + * Otherwise only signals can be emitted to tell the outside that + * someone must do this job itself. + */ +void KMdiMainFrm::setMenuForSDIModeSysButtons( KMenuBar* pMenuBar ) +{ + if ( m_bSDIApplication ) // there are no buttons in the menubar in this mode (although the view is always maximized) + return ; + + m_pMainMenuBar = pMenuBar; + if ( m_pMainMenuBar == 0L ) + return ; // use setMenuForSDIModeSysButtons( 0L) for unsetting the external main menu! + + if ( !m_pUndock ) + m_pUndock = new QToolButton( pMenuBar ); + if ( !m_pRestore ) + m_pRestore = new QToolButton( pMenuBar ); + if ( !m_pMinimize ) + m_pMinimize = new QToolButton( pMenuBar ); + if ( !m_pClose ) + m_pClose = new QToolButton( pMenuBar ); + m_pUndock->setAutoRaise( false ); + m_pMinimize->setAutoRaise( false ); + m_pRestore->setAutoRaise( false ); + m_pClose->setAutoRaise( false ); + + setSysButtonsAtMenuPosition(); + + delete m_pUndockButtonPixmap; + delete m_pMinButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + // create the decoration pixmaps + if ( frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + m_pUndockButtonPixmap = new QPixmap( win_undockbutton ); + m_pMinButtonPixmap = new QPixmap( win_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( win_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( win_closebutton ); + } + else if ( frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + m_pUndockButtonPixmap = new QPixmap( kde_undockbutton ); + m_pMinButtonPixmap = new QPixmap( kde_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde_closebutton ); + m_pUndock->setAutoRaise( true ); + m_pMinimize->setAutoRaise( true ); + m_pRestore->setAutoRaise( true ); + m_pClose->setAutoRaise( true ); + } + else if ( frameDecorOfAttachedViews() == KMdi::KDELook ) + { + m_pUndockButtonPixmap = new QPixmap( kde2_undockbutton ); + m_pMinButtonPixmap = new QPixmap( kde2_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2_closebutton ); + } + else + { // kde2laptop look + m_pUndockButtonPixmap = new QPixmap( kde2laptop_undockbutton ); + m_pMinButtonPixmap = new QPixmap( kde2laptop_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2laptop_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2laptop_closebutton ); + } + + m_pUndock->hide(); + m_pMinimize->hide(); + m_pRestore->hide(); + m_pClose->hide(); + + m_pUndock->setPixmap( *m_pUndockButtonPixmap ); + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + m_pRestore->setPixmap( *m_pRestoreButtonPixmap ); + m_pClose->setPixmap( *m_pCloseButtonPixmap ); +} + +void KMdiMainFrm::setSysButtonsAtMenuPosition() +{ + if ( m_pMainMenuBar == 0L ) + return ; + if ( m_pMainMenuBar->parentWidget() == 0L ) + return ; + + int menuW = m_pMainMenuBar->parentWidget() ->width(); + int h; + int y; + if ( frameDecorOfAttachedViews() == KMdi::Win95Look ) + h = 16; + else if ( frameDecorOfAttachedViews() == KMdi::KDE1Look ) + h = 20; + else if ( frameDecorOfAttachedViews() == KMdi::KDELook ) + h = 16; + else + h = 14; + y = m_pMainMenuBar->height() / 2 - h / 2; + + if ( frameDecorOfAttachedViews() == KMdi::KDELaptopLook ) + { + int w = 27; + m_pUndock->setGeometry( ( menuW - ( w * 3 ) - 5 ), y, w, h ); + m_pMinimize->setGeometry( ( menuW - ( w * 2 ) - 5 ), y, w, h ); + m_pRestore->setGeometry( ( menuW - w - 5 ), y, w, h ); + } + else + { + m_pUndock->setGeometry( ( menuW - ( h * 4 ) - 5 ), y, h, h ); + m_pMinimize->setGeometry( ( menuW - ( h * 3 ) - 5 ), y, h, h ); + m_pRestore->setGeometry( ( menuW - ( h * 2 ) - 5 ), y, h, h ); + m_pClose->setGeometry( ( menuW - h - 5 ), y, h, h ); + } +} + +/** Activates the next open view */ +void KMdiMainFrm::activateNextWin() +{ + KMdiIterator<KMdiChildView*>* it = createIterator(); + KMdiChildView* aWin = activeWindow(); + for ( it->first(); !it->isDone(); it->next() ) + { + if ( it->currentItem() == aWin ) + { + it->next(); + if ( !it->currentItem() ) + { + it->first(); + } + if ( it->currentItem() ) + { + activateView( it->currentItem() ); + } + break; + } + } + delete it; +} + +/** Activates the previous open view */ +void KMdiMainFrm::activatePrevWin() +{ + KMdiIterator<KMdiChildView*>* it = createIterator(); + KMdiChildView* aWin = activeWindow(); + for ( it->first(); !it->isDone(); it->next() ) + { + if ( it->currentItem() == aWin ) + { + it->prev(); + if ( !it->currentItem() ) + { + it->last(); + } + if ( it->currentItem() ) + { + activateView( it->currentItem() ); + } + break; + } + } + delete it; +} + +/** Activates the view we accessed the most time ago */ +void KMdiMainFrm::activateFirstWin() +{ + m_bSwitching= true; // flag that we are currently switching between windows + KMdiIterator<KMdiChildView*>* it = createIterator(); + QMap<QDateTime, KMdiChildView*> m; + for ( it->first(); !it->isDone(); it->next() ) + { + m.insert( it->currentItem() ->getTimeStamp(), it->currentItem() ); + } + + if ( !activeWindow() ) + return ; + + QDateTime current = activeWindow() ->getTimeStamp(); + QMap<QDateTime, KMdiChildView*>::iterator pos( m.find( current ) ); + QMap<QDateTime, KMdiChildView*>::iterator newPos = pos; + if ( pos != m.end() ) + { + ++newPos; + } + if ( newPos != m.end() ) + { // look ahead + ++pos; + } + else + { + pos = m.begin(); + } + activateView( pos.data() ); + delete it; +} + +/** Activates the previously accessed view before this one was activated */ +void KMdiMainFrm::activateLastWin() +{ + m_bSwitching= true; // flag that we are currently switching between windows + KMdiIterator<KMdiChildView*>* it = createIterator(); + QMap<QDateTime, KMdiChildView*> m; + for ( it->first(); !it->isDone(); it->next() ) + { + m.insert( it->currentItem() ->getTimeStamp(), it->currentItem() ); + } + + if ( !activeWindow() ) + return ; + + QDateTime current = activeWindow() ->getTimeStamp(); + QMap<QDateTime, KMdiChildView*>::iterator pos( m.find( current ) ); + if ( pos != m.begin() ) + { + --pos; + } + else + { + pos = m.end(); + --pos; + } + activateView( pos.data() ); + delete it; +} + +/** Activates the view with a certain index (TabPage mode only) */ +void KMdiMainFrm::activateView( int index ) +{ + KMdiChildView * pView = m_pDocumentViews->first(); + for ( int i = 0; pView && ( i < index ); i++ ) + { + pView = m_pDocumentViews->next(); + } + if ( pView ) + { + pView->activate(); + } +} + +/** turns the system buttons for maximize mode (SDI mode) on, and connects them with the current child frame */ +void KMdiMainFrm::setEnableMaximizedChildFrmMode( bool enableMaxChildFrameMode ) +{ + if ( enableMaxChildFrameMode ) + { + kdDebug(760) << k_funcinfo << "Turning on maximized child frame mode" << endl; + m_bMaximizedChildFrmMode = true; + + KMdiChildFrm* pCurrentChild = m_pMdi->topChild(); + + //If we have no child or there is no menubar, we do nothing + if ( !pCurrentChild || !m_pMainMenuBar ) + return ; + + QObject::connect( m_pUndock, SIGNAL( clicked() ), pCurrentChild, SLOT( undockPressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), pCurrentChild, SLOT( minimizePressed() ) ); + QObject::connect( m_pRestore, SIGNAL( clicked() ), pCurrentChild, SLOT( maximizePressed() ) ); + m_pMinimize->show(); + m_pUndock->show(); + m_pRestore->show(); + + if ( frameDecorOfAttachedViews() == KMdi::KDELaptopLook ) + { + m_pMainMenuBar->insertItem( QPixmap( kde2laptop_closebutton_menu ), m_pMdi->topChild(), SLOT( closePressed() ), 0, -1, 0 ); + } + else + { + m_pMainMenuBar->insertItem( *pCurrentChild->icon(), pCurrentChild->systemMenu(), -1, 0 ); + if ( m_pClose ) + { + QObject::connect( m_pClose, SIGNAL( clicked() ), pCurrentChild, SLOT( closePressed() ) ); + m_pClose->show(); + } + else + kdDebug(760) << k_funcinfo << "no close button. things won't behave correctly" << endl; + } + } + else + { + if ( !m_bMaximizedChildFrmMode ) + return ; // already set, nothing to do + + kdDebug(760) << k_funcinfo << "Turning off maximized child frame mode" << endl; + m_bMaximizedChildFrmMode = false; + + KMdiChildFrm* pFrmChild = m_pMdi->topChild(); + if ( pFrmChild && pFrmChild->m_pClient && pFrmChild->state() == KMdiChildFrm::Maximized ) + { + pFrmChild->m_pClient->restore(); + switchOffMaximizeModeForMenu( pFrmChild ); + } + } +} + +/** turns the system buttons for maximize mode (SDI mode) off, and disconnects them */ +void KMdiMainFrm::switchOffMaximizeModeForMenu( KMdiChildFrm* oldChild ) +{ + // if there is no menubar given, those system buttons aren't possible + if ( !m_pMainMenuBar ) + return ; + + m_pMainMenuBar->removeItem( m_pMainMenuBar->idAt( 0 ) ); + + if ( oldChild ) + { + Q_ASSERT( m_pClose ); + QObject::disconnect( m_pUndock, SIGNAL( clicked() ), oldChild, SLOT( undockPressed() ) ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), oldChild, SLOT( minimizePressed() ) ); + QObject::disconnect( m_pRestore, SIGNAL( clicked() ), oldChild, SLOT( maximizePressed() ) ); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), oldChild, SLOT( closePressed() ) ); + } + m_pUndock->hide(); + m_pMinimize->hide(); + m_pRestore->hide(); + m_pClose->hide(); +} + +/** reconnects the system buttons form maximize mode (SDI mode) with the new child frame */ +void KMdiMainFrm::updateSysButtonConnections( KMdiChildFrm* oldChild, KMdiChildFrm* newChild ) +{ + //qDebug("updateSysButtonConnections"); + // if there is no menubar given, those system buttons aren't possible + if ( !m_pMainMenuBar ) + return ; + + if ( newChild ) + { + if ( frameDecorOfAttachedViews() == KMdi::KDELaptopLook ) + m_pMainMenuBar->insertItem( QPixmap( kde2laptop_closebutton_menu ), newChild, SLOT( closePressed() ), 0, -1, 0 ); + else + m_pMainMenuBar->insertItem( *newChild->icon(), newChild->systemMenu(), -1, 0 ); + } + + if ( oldChild ) + { + m_pMainMenuBar->removeItem( m_pMainMenuBar->idAt( 1 ) ); + Q_ASSERT( m_pClose ); + QObject::disconnect( m_pUndock, SIGNAL( clicked() ), oldChild, SLOT( undockPressed() ) ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), oldChild, SLOT( minimizePressed() ) ); + QObject::disconnect( m_pRestore, SIGNAL( clicked() ), oldChild, SLOT( maximizePressed() ) ); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), oldChild, SLOT( closePressed() ) ); + } + if ( newChild ) + { + Q_ASSERT( m_pClose ); + QObject::connect( m_pUndock, SIGNAL( clicked() ), newChild, SLOT( undockPressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), newChild, SLOT( minimizePressed() ) ); + QObject::connect( m_pRestore, SIGNAL( clicked() ), newChild, SLOT( maximizePressed() ) ); + QObject::connect( m_pClose, SIGNAL( clicked() ), newChild, SLOT( closePressed() ) ); + } +} + +/** Shows the view taskbar. This should be connected with your "View" menu. */ +bool KMdiMainFrm::isViewTaskBarOn() +{ + if ( m_pTaskBar ) + return m_pTaskBar->isSwitchedOn(); + else + return false; +} + +/** Shows the view taskbar. This should be connected with your "View" menu. */ +void KMdiMainFrm::showViewTaskBar() +{ + if ( m_pTaskBar ) + m_pTaskBar->switchOn( true ); +} + +/** Hides the view taskbar. This should be connected with your "View" menu. */ +void KMdiMainFrm::hideViewTaskBar() +{ + if ( m_pTaskBar ) + m_pTaskBar->switchOn( false ); +} + +//=============== fillWindowMenu ===============// +void KMdiMainFrm::fillWindowMenu() +{ + bool tabPageMode = false; + if ( m_mdiMode == KMdi::TabPageMode ) + tabPageMode = true; + + bool IDEAlMode = false; + if ( m_mdiMode == KMdi::IDEAlMode ) + IDEAlMode = true; + + bool noViewOpened = false; + if ( m_pDocumentViews->isEmpty() ) + noViewOpened = true; + + // construct the menu and its submenus + if ( !m_bClearingOfWindowMenuBlocked ) + m_pWindowMenu->clear(); + + d->closeWindowAction->plug(m_pWindowMenu); + + int closeAllId = m_pWindowMenu->insertItem( i18n( "Close &All" ), this, SLOT( closeAllViews() ) ); + if ( noViewOpened ) + { + d->closeWindowAction->setEnabled(false); + m_pWindowMenu->setItemEnabled( closeAllId, false ); + } + + if ( !tabPageMode && !IDEAlMode ) + { + int iconifyId = m_pWindowMenu->insertItem( i18n( "&Minimize All" ), this, SLOT( iconifyAllViews() ) ); + if ( noViewOpened ) + m_pWindowMenu->setItemEnabled( iconifyId, false ); + } + + m_pWindowMenu->insertSeparator(); + m_pWindowMenu->insertItem( i18n( "&MDI Mode" ), m_pMdiModeMenu ); + m_pMdiModeMenu->clear(); + m_pMdiModeMenu->insertItem( i18n( "&Toplevel Mode" ), this, SLOT( switchToToplevelMode() ) ); + m_pMdiModeMenu->insertItem( i18n( "C&hildframe Mode" ), this, SLOT( switchToChildframeMode() ) ); + m_pMdiModeMenu->insertItem( i18n( "Ta&b Page Mode" ), this, SLOT( switchToTabPageMode() ) ); + m_pMdiModeMenu->insertItem( i18n( "I&DEAl Mode" ), this, SLOT( switchToIDEAlMode() ) ); + switch ( m_mdiMode ) + { + case KMdi::ToplevelMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 0 ), true ); + break; + case KMdi::ChildframeMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 1 ), true ); + break; + case KMdi::TabPageMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 2 ), true ); + break; + case KMdi::IDEAlMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 3 ), true ); + break; + default: + break; + } + + m_pWindowMenu->insertSeparator(); + if ( !tabPageMode && !IDEAlMode ) + { + int placMenuId = m_pWindowMenu->insertItem( i18n( "&Tile" ), m_pPlacingMenu ); + m_pPlacingMenu->clear(); + m_pPlacingMenu->insertItem( i18n( "Ca&scade Windows" ), m_pMdi, SLOT( cascadeWindows() ) ); + m_pPlacingMenu->insertItem( i18n( "Cascade &Maximized" ), m_pMdi, SLOT( cascadeMaximized() ) ); + m_pPlacingMenu->insertItem( i18n( "Expand &Vertically" ), m_pMdi, SLOT( expandVertical() ) ); + m_pPlacingMenu->insertItem( i18n( "Expand &Horizontally" ), m_pMdi, SLOT( expandHorizontal() ) ); + m_pPlacingMenu->insertItem( i18n( "Tile &Non-Overlapped" ), m_pMdi, SLOT( tileAnodine() ) ); + m_pPlacingMenu->insertItem( i18n( "Tile Overla&pped" ), m_pMdi, SLOT( tilePragma() ) ); + m_pPlacingMenu->insertItem( i18n( "Tile V&ertically" ), m_pMdi, SLOT( tileVertically() ) ); + if ( m_mdiMode == KMdi::ToplevelMode ) + { + m_pWindowMenu->setItemEnabled( placMenuId, false ); + } + m_pWindowMenu->insertSeparator(); + int dockUndockId = m_pWindowMenu->insertItem( i18n( "&Dock/Undock" ), m_pDockMenu ); + m_pDockMenu->clear(); + m_pWindowMenu->insertSeparator(); + if ( noViewOpened ) + { + m_pWindowMenu->setItemEnabled( placMenuId, false ); + m_pWindowMenu->setItemEnabled( dockUndockId, false ); + } + } + int entryCount = m_pWindowMenu->count(); + + // for all child frame windows: give an ID to every window and connect them in the end with windowMenuItemActivated() + int i = 100; + KMdiChildView* pView = 0L; + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + QValueList<QDateTime> timeStamps; + for ( ; it.current(); ++it ) + { + pView = it.current(); + QDateTime timeStamp( pView->getTimeStamp() ); + + if ( pView->isToolView() ) + { + continue; + } + + QString item; + // set titles of minimized windows in brackets + if ( pView->isMinimized() ) + { + item += "("; + item += pView->caption(); + item += ")"; + } + else + { + item += " "; + item += pView->caption(); + } + + // insert the window entry sorted by access time + unsigned int indx; + unsigned int windowItemCount = m_pWindowMenu->count() - entryCount; + bool inserted = false; + QString tmpString; + QValueList<QDateTime>::iterator timeStampIterator = timeStamps.begin(); + for ( indx = 0; indx <= windowItemCount; indx++, ++timeStampIterator ) + { + bool putHere = false; + if ( ( *timeStampIterator ) < timeStamp ) + { + putHere = true; + timeStamps.insert( timeStampIterator, timeStamp ); + } + if ( putHere ) + { + m_pWindowMenu->insertItem( item, pView, SLOT( slot_clickedInWindowMenu() ), 0, -1, indx + entryCount ); + if ( pView == m_pCurrentWindow ) + { + m_pWindowMenu->setItemChecked( m_pWindowMenu->idAt( indx + entryCount ), true ); + } + pView->setWindowMenuID( i ); + if ( !tabPageMode ) + { + m_pDockMenu->insertItem( item, pView, SLOT( slot_clickedInDockMenu() ), 0, -1, indx ); + if ( pView->isAttached() ) + { + m_pDockMenu->setItemChecked( m_pDockMenu->idAt( indx ), true ); + } + } + inserted = true; + break; + indx = windowItemCount + 1; // break the loop + } + } + if ( !inserted ) + { // append it + m_pWindowMenu->insertItem( item, pView, SLOT( slot_clickedInWindowMenu() ), 0, -1, windowItemCount + entryCount ); + if ( pView == m_pCurrentWindow ) + { + m_pWindowMenu->setItemChecked( m_pWindowMenu->idAt( windowItemCount + entryCount ), true ); + } + pView->setWindowMenuID( i ); + if ( !tabPageMode ) + { + m_pDockMenu->insertItem( item, pView, SLOT( slot_clickedInDockMenu() ), 0, -1, windowItemCount ); + if ( pView->isAttached() ) + { + m_pDockMenu->setItemChecked( m_pDockMenu->idAt( windowItemCount ), true ); + } + } + } + i++; + } +} + +//================ windowMenuItemActivated ===============// + +void KMdiMainFrm::windowMenuItemActivated( int id ) +{ + if ( id < 100 ) + return ; + id -= 100; + KMdiChildView *pView = m_pDocumentViews->at( id ); + if ( !pView ) + return ; + if ( pView->isMinimized() ) + pView->minimize(); + if ( m_mdiMode != KMdi::TabPageMode ) + { + KMdiChildFrm * pTopChild = m_pMdi->topChild(); + if ( pTopChild ) + { + if ( ( pView == pTopChild->m_pClient ) && pView->isAttached() ) + { + return ; + } + } + } + activateView( pView ); +} + +//================ dockMenuItemActivated ===============// + +void KMdiMainFrm::dockMenuItemActivated( int id ) +{ + if ( id < 100 ) + return ; + id -= 100; + KMdiChildView *pView = m_pDocumentViews->at( id ); + if ( !pView ) + return ; + if ( pView->isMinimized() ) + pView->minimize(); + if ( pView->isAttached() ) + { + detachWindow( pView, true ); + } + else + { // is detached + attachWindow( pView, true ); + } +} + +//================ popupWindowMenu ===============// + +void KMdiMainFrm::popupWindowMenu( QPoint p ) +{ + if ( !isFakingSDIApplication() ) + { + m_pWindowMenu->popup( p ); + } +} + +//================ dragEndTimeOut ===============// +void KMdiMainFrm::dragEndTimeOut() +{ + // send drag end to all concerned views. + KMdiChildView * pView; + for ( m_pDocumentViews->first(); ( pView = m_pDocumentViews->current() ) != 0L; m_pDocumentViews->next() ) + { + KMdiChildFrmDragEndEvent dragEndEvent( 0L ); + QApplication::sendEvent( pView, &dragEndEvent ); + } +} + +//================ setFrameDecorOfAttachedViews ===============// + +void KMdiMainFrm::setFrameDecorOfAttachedViews( int frameDecor ) +{ + switch ( frameDecor ) + { + case 0: + m_frameDecoration = KMdi::Win95Look; + break; + case 1: + m_frameDecoration = KMdi::KDE1Look; + break; + case 2: + m_frameDecoration = KMdi::KDELook; + break; + case 3: + m_frameDecoration = KMdi::KDELaptopLook; + break; + default: + qDebug( "unknown MDI decoration" ); + break; + } + setMenuForSDIModeSysButtons( m_pMainMenuBar ); + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; it.current(); ++it ) + { + KMdiChildView* pView = it.current(); + if ( pView->isToolView() ) + continue; + if ( pView->isAttached() ) + pView->mdiParent() ->redecorateButtons(); + } +} + +void KMdiMainFrm::fakeSDIApplication() +{ + m_bSDIApplication = true; + if ( m_pTaskBar ) + m_pTaskBar->close(); + m_pTaskBar = 0L; +} + +void KMdiMainFrm::closeViewButtonPressed() +{ + KMdiChildView * pView = activeWindow(); + if ( pView ) + { + pView->close(); + } +} + +void KMdiMainFrm::setManagedDockPositionModeEnabled( bool enabled ) +{ + m_managedDockPositionMode = enabled; +} + +void KMdiMainFrm::setActiveToolDock( KMdiDockContainer* td ) +{ + if ( td == d->activeDockPriority[ 0 ] ) + return ; + if ( d->activeDockPriority[ 0 ] == 0 ) + { + d->activeDockPriority[ 0 ] = td; + // d->focusList=new KMdiFocusList(this); + // if (m_pMdi) d->focusList->addWidgetTree(m_pMdi); + // if (m_documentTabWidget) d->focusList->addWidgetTree(m_documentTabWidget); + return ; + } + for ( int dst = 3, src = 2;src >= 0;dst--, src-- ) + { + if ( d->activeDockPriority[ src ] == td ) + src--; + if ( src < 0 ) + break; + d->activeDockPriority[ dst ] = d->activeDockPriority[ src ]; + } + d->activeDockPriority[ 0 ] = td; +} + +void KMdiMainFrm::removeFromActiveDockList( KMdiDockContainer* td ) +{ + for ( int i = 0;i < 4;i++ ) + { + if ( d->activeDockPriority[ i ] == td ) + { + for ( ;i < 3;i++ ) + d->activeDockPriority[ i ] = d->activeDockPriority[ i + 1 ]; + d->activeDockPriority[ 3 ] = 0; + break; + } + } + /* + if (d->activeDockPriority[0]==0) { + if (d->focusList) d->focusList->restore(); + delete d->focusList; + d->focusList=0; + } + */ +} + +void KMdiMainFrm::prevToolViewInDock() +{ + KMdiDockContainer * td = d->activeDockPriority[ 0 ]; + if ( !td ) + return ; + td->prevToolView(); +} + +void KMdiMainFrm::nextToolViewInDock() +{ + KMdiDockContainer * td = d->activeDockPriority[ 0 ]; + if ( !td ) + return ; + td->nextToolView(); +} + +KMdi::TabWidgetVisibility KMdiMainFrm::tabWidgetVisibility() +{ + if ( m_documentTabWidget ) + return m_documentTabWidget->tabWidgetVisibility(); + + return KMdi::NeverShowTabs; +} + +void KMdiMainFrm::setTabWidgetVisibility( KMdi::TabWidgetVisibility visibility ) +{ + if ( m_documentTabWidget ) + m_documentTabWidget->setTabWidgetVisibility( visibility ); +} + +KTabWidget * KMdiMainFrm::tabWidget() const +{ + return m_documentTabWidget; +} + +#include "kmdimainfrm.moc" + +// vim: ts=2 sw=2 et +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdimainfrm.h b/kmdi/kmdimainfrm.h new file mode 100644 index 000000000..a72a654d3 --- /dev/null +++ b/kmdi/kmdimainfrm.h @@ -0,0 +1,879 @@ +//---------------------------------------------------------------------------- +// filename : kmdimainfrm.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// 2000-2003 maintained by the KDevelop project +// patches : */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDIMAINFRM_H_ +#define _KMDIMAINFRM_H_ + +#include <kparts/dockmainwindow.h> +#include <kmenubar.h> +#include <kpopupmenu.h> + +#include <qptrlist.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdom.h> +#include <qguardedptr.h> + +#include "kmditaskbar.h" +#include "kmdichildarea.h" +#include "kmdichildview.h" +#include "kmdiiterator.h" +#include "kmdilistiterator.h" +#include "kmdinulliterator.h" +#include "kmditoolviewaccessor.h" + +class QTimer; +class QPopupMenu; +class QMenuBar; + + +class QToolButton; + +namespace KMDIPrivate +{ +class KMDIGUIClient; +} + +class KMdiDockContainer; +class KMdiMainFrmPrivate; + +/** + * @short Internal class + * + * This special event is needed because the view has to inform the main frame that it`s being closed. + */ +class KMDI_EXPORT KMdiViewCloseEvent : public QCustomEvent +{ +public: + KMdiViewCloseEvent( KMdiChildView* pWnd ) : QCustomEvent( QEvent::User, pWnd ) {} +}; + +/** + * \short Base class for all your special main frames. + * + * It contains the child frame area (QMainWindow's central widget) and a child view taskbar + * for switching the MDI views. Most methods are virtual functions for later overriding. + * + * Basically, this class provides functionality for docking/undocking view windows and + * manages the taskbar. Usually a developer will only need to know about this class and + * \ref KMdiChildView. + * + * \par General usage + * + * Your program mainwidget should inherit KMdiMainFrm. Then usually you'll just need + * addWindow() and removeWindowFromMdi() to control the views. + * \code + * class MyMainWindow : public KMdiMainFrm + * { .... }; + * \endcode + * + * to define your main window class and + * + * \code + * MyMainWindow mainframe; + * qApp->setMainWidget(&mainframe); + * mainframe->addWindow(view1); // put it under MDI control + * mainframe->addWindow(view2); + * \endcode + * + * when you wish to use your main window class. The above example also adds a few windows + * to the frame. + * + * KMdiMainFrm will provide the "Window" menu needed in common MDI applications. Just + * insert it in your main menu: + * + * \code + * if ( !isFakingSDIApplication() ) + * { + * menuBar()->insertItem( i18n( "&Window" ), windowMenu() ); + * } + * \endcode + * + * To synchronize the positions of the MDI control buttons inserted in your mainmenu: + * \code + * void B_MainModuleWidget::initMenuBar() + * { + * setMenuForSDIModeSysButtons( menuBar() ); + * } + * ... + * void B_MainModuleWidget::resizeEvent ( QResizeEvent *e ) + * { + * KMdiMainFrm::resizeEvent( e ); + * setSysButtonsAtMenuPosition(); + * } + * \endcode + * + * \par Dynamic mode switching + * + * Dynamic switching of the MDI mode can be done via the following functions: + * - switchToChildframeMode() + * - switchToToplevelMode() + * - switchToTabPageMode() + * - switchToIDEAlMode() + * + * The MDI mode can be gotten using mdiMode(). If you need to fake the look of an SDI application + * use fakeSDIApplication() to fake it and isFakingSDIApplication() to query whether or not an SDI + * interface is being faked. + * + * You can dynamically change the shape of the attached MDI views using setFrameDecorOfAttachedViews(). + * + * Additionally, here's a hint how to restore the mainframe's settings from config file: + * \code + * + * // restore MDI mode (toplevel, childframe, tabpage) + * int mdiMode = config->readIntEntry( "mainmodule session", "MDI mode", KMdi::ChildframeMode); + * switch (mdiMode) { + * case KMdi::ToplevelMode: + * { + * int childFrmModeHt = config->readIntEntry( "mainmodule session", "Childframe mode height", desktop()->height() - 50); + * mainframe->resize( m_pMdiMainFrm->width(), childFrmModeHt); + * mainframe->switchToToplevelMode(); + * } + * break; + * case KMdi::ChildframeMode: + * break; + * case KMdi::TabPageMode: + * { + * int childFrmModeHt = m_pCfgFileManager->readIntEntry( "mainmodule session", "Childframe mode height", desktop()->height() - 50); + * mainframe->resize( m_pMdiMainFrm->width(), childFrmModeHt); + * mainframe->switchToTabPageMode(); + * } + * break; + * default: + * break; + * } + * + * // restore a possible maximized Childframe mode + * bool maxChildFrmMode = config->readBoolEntry( "mainmodule session", "maximized childframes", true); + * mainframe->setEnableMaximizedChildFrmMode(maxChildFrmMode); + * \endcode + * The maximized-Childframe mode means that currently all views are maximized in Childframe mode's application desktop. + * + * \par Managing views + * + * This class provides placing algorithms in Childframe mode. The following is a list of the window placement functions + * - tilePragma() - Tile the windows and allow them to overlap + * - tileAnodine() - Tile the windows but don't allow them to overlap + * - tileVertically() - Tile the windows vertically + * - cascadeWindows() - cascade windows + * - cascadeMaximized() - cascade windows and maximize their viewing area + * - expandVertical() - expand all the windows to use the most amount of vertical space + * - expandHorizontal() - expand all the windows to use the most amount of horizontal space + * + * activateView(KMdiChildView*) and activateView(int index) set the appropriate MDI child view as the active + * one. It will be raised, will get an active MDI frame and will get the focus. Call activeView() to find out what the + * current MDI view is. + * + * Use detachWindow() and attachWindow() for docking the MDI views to desktop and back. + * + * Connect accels of your program with activatePrevWin(), activateNextWin() and activateView(int index). + * + * Note: KMdiChildViews can be added in 2 meanings: Either as a normal child view (usually containing + * user document views) or as a tool-view (usually containing status, info or control widgets). + * The tool-views can be added as floating dockwidgets or as stay-on-top desktop windows in tool style. + * + * Also, pay attention to the fact that when you click on the close button of MDI views that their + * close event should be redirected to closeWindow(). Otherwise the mainframe class will + * not get noticed about the deleted view and a dangling pointer will remain in the MDI control. The + * closeWindow() or the removeWindowFromMdi() method is for that issue. The difference is closeWindow() + * deletes the view object. So if your application wants to control that by itself, call removeWindowFromMdi() + * and call delete by yourself. See also KMdiChildView::closeEvent() for that issue. + * + * Here's an example how you can suggest things for the adding of views to the MDI control via flags: + * \code + * m_mapOfMdiWidgets.insert( pWnd, mh ); + * unsigned int mdiFlags = KMdi::StandardAdd; + * + * if ( !show ) + * mdiFlags |= KMdi::Hide; + * + * if ( !attach ) + * mdiFlags |= KMdi::Detach; + * + * if ( minimize ) + * mdiFlags |= KMdi::Minimize; + * + * if ( bToolWindow) + * mdiFlags |= KMdi::ToolWindow; + * + * if ( m_pMdiMainFrm->isFakingSDIApplication() ) + * { + * if ( attach ) //fake an SDI app + * mdiFlags |= KMdi::Maximize; + * } + * else + * { + * m_pMdiMainFrm->addWindow( pWnd, QPoint(20, 20), KMdi::AddWindowFlags(mdiFlags)); + * return; + * } + * m_pMdiMainFrm->addWindow( pWnd, KMdi::AddWindowFlags(mdiFlags)); + * \endcode + */ +class KMDI_EXPORT KMdiMainFrm : public KParts::DockMainWindow +{ + friend class KMdiChildView; + friend class KMdiTaskBar; + Q_OBJECT + + friend class KMdiToolViewAccessor; + // attributes +protected: + KMdi::MdiMode m_mdiMode; + KMdiChildArea *m_pMdi; + KMdiTaskBar *m_pTaskBar; + QPtrList<KMdiChildView> *m_pDocumentViews; + QMap<QWidget*, KMdiToolViewAccessor*> *m_pToolViews; + KMdiChildView *m_pCurrentWindow; + QPopupMenu *m_pWindowPopup; + QPopupMenu *m_pTaskBarPopup; + QPopupMenu *m_pWindowMenu; + QPopupMenu *m_pDockMenu; + QPopupMenu *m_pMdiModeMenu; + QPopupMenu *m_pPlacingMenu; + KMenuBar *m_pMainMenuBar; + + QPixmap *m_pUndockButtonPixmap; + QPixmap *m_pMinButtonPixmap; + QPixmap *m_pRestoreButtonPixmap; + QPixmap *m_pCloseButtonPixmap; + + QToolButton *m_pUndock; + QToolButton *m_pMinimize; + QToolButton *m_pRestore; + QToolButton *m_pClose; + QPoint m_undockPositioningOffset; + bool m_bMaximizedChildFrmMode; + int m_oldMainFrmHeight; + int m_oldMainFrmMinHeight; + int m_oldMainFrmMaxHeight; + static KMdi::FrameDecor m_frameDecoration; + bool m_bSDIApplication; + KDockWidget* m_pDockbaseAreaOfDocumentViews; + QDomDocument* m_pTempDockSession; + bool m_bClearingOfWindowMenuBlocked; + + QTimer* m_pDragEndTimer; + + bool m_bSwitching; + + KDockWidget* m_leftContainer; + KDockWidget* m_rightContainer; + KDockWidget* m_topContainer; + KDockWidget* m_bottomContainer; + + +private: + KMdiMainFrmPrivate* d; + KMDIPrivate::KMDIGUIClient* m_mdiGUIClient; + bool m_managedDockPositionMode; + + // methods +public: + KMdiMainFrm( QWidget* parentWidget, const char* name = "", KMdi::MdiMode mdiMode = KMdi::ChildframeMode, WFlags flags = WType_TopLevel | WDestructiveClose ); + virtual ~KMdiMainFrm(); + + /** + * Control whether or not the standard MDI menu is displayed + * when a context menu is displayed + */ + void setStandardMDIMenuEnabled( bool showModeMenu = true ); + + void setManagedDockPositionModeEnabled( bool enabled ); + + /** + * Returns whether the application's MDI views are in maximized state or not. + */ + bool isInMaximizedChildFrmMode() { return m_bMaximizedChildFrmMode; } + + /** + * Returns the MDI mode. This can be one of the enumerations KMdi::MdiMode. + */ + KMdi::MdiMode mdiMode() { return m_mdiMode; } + + /** + * Returns the focused attached MDI view. + */ + KMdiChildView* activeWindow(); + + /** + * Returns a popup menu filled according to the MDI view state. You can override this + * method to insert additional entries there. The popup menu is usually popuped when the user + * clicks with the right mouse button on a taskbar entry. The default entries are: + * Undock/Dock, Restore/Maximize/Minimize, Close and an empty sub-popup ( windowPopup() ) + * menu called Operations. + */ + virtual QPopupMenu * taskBarPopup( KMdiChildView *pWnd, bool bIncludeWindowPopup = false ); + + /** + * Returns a popup menu with only a title "Window". You can fill it with own operations entries + * on the MDI view. This popup menu is inserted as last menu item in taskBarPopup() . + */ + virtual QPopupMenu * windowPopup( KMdiChildView *pWnd, bool bIncludeTaskbarPopup = true ); + + /** + * Called in the constructor (forces a resize of all MDI views) + */ + virtual void applyOptions(); + + /** + * Returns the KMdiChildView belonging to the given caption string. + */ + KMdiChildView * findWindow( const QString& caption ); + + enum ExistsAs {DocumentView, ToolView, AnyView}; + /** + * Returns whether this MDI child view is under MDI control (using addWindow() ) or not. + */ + bool windowExists( KMdiChildView *pWnd, ExistsAs as ); + + /** + * Catches certain Qt events and processes it here. + * Currently, here this catches only the KMdiViewCloseEvent (a KMdi user event) which is sent + * from itself in childWindowCloseRequest() right after a KMdiChildView::closeEvent() . + * The reason for this event to itself is simple: It just wants to break the function call stack. + * It continues the processing with calling closeWindow() . + * You see, a close() is translated to a closeWindow() . + * It is necessary that the main frame has to start an MDI view close action because it must + * remove the MDI view from MDI control, additionally. + * + * This method calls QMainWindow::event , additionally. + */ + virtual bool event( QEvent* e ); + + /** + * If there's a main menubar given, it will create the 4 maximize mode buttons there (undock, minimize, restore, close). + */ + virtual void setSysButtonsAtMenuPosition(); + + /** + * Returns the height of the taskbar. + */ + virtual int taskBarHeight() { return m_pTaskBar ? m_pTaskBar->height() : 0; } + + /** + * Sets an offset value that is used on detachWindow() . The undocked window + * is visually moved on the desktop by this offset. + */ + virtual void setUndockPositioningOffset( QPoint offset ) { m_undockPositioningOffset = offset; } + + /** + * If you don't want to know about the inner structure of the KMdi system, you can use + * this iterator to handle with the MDI view list in a more abstract way. + * The iterator hides what special data structure is used in KMdi. + * The caller must delete the iterator once he does not need it anymore. + */ + // FIXME And what exactly are we supposed to fix? -mattr + KMdiIterator<KMdiChildView*>* createIterator() + { + if ( m_pDocumentViews == 0L ) + { + return new KMdiNullIterator<KMdiChildView*>(); + } + else + { + return new KMdiListIterator<KMdiChildView>( *m_pDocumentViews ); + } + } + + /** + * Deletes an KMdiIterator created in the KMdi library (needed for the windows dll problem). + */ + void deleteIterator( KMdiIterator<KMdiChildView*>* pIt ) + { + delete pIt; + } + + /** + * Returns a popup menu that contains the MDI controlled view list. + * Additionally, this menu provides some placing actions for these views. + * Usually, you insert this popup menu in your main menubar as "Window" menu. + */ + QPopupMenu* windowMenu() const { return m_pWindowMenu; }; + + /** + * Sets a background color for the MDI view area widget. + */ + virtual void setBackgroundColor( const QColor &c ) { m_pMdi->setBackgroundColor( c ); } + + /** + * Sets a background pixmap for the MDI view area widget. + */ + virtual void setBackgroundPixmap( const QPixmap &pm ) { m_pMdi->setBackgroundPixmap( pm ); } + + /** + * Sets a size that is used as the default size for a newly to the MDI system added KMdiChildView . + * By default this size is 600x400. So all non-resized added MDI views appear in that size. + */ + void setDefaultChildFrmSize( const QSize& sz ) { m_pMdi->m_defaultChildFrmSize = sz; } + + /** + * Returns the default size for a newly added KMdiChildView. See setDefaultChildFrmSize() . + */ + QSize defaultChildFrmSize() { return m_pMdi->m_defaultChildFrmSize; } + + /** + * Do nothing when in Toplevel mode + */ + virtual void setMinimumSize( int minw, int minh ); + + /** + * Returns the Childframe mode height of this. Makes only sense when in Toplevel mode. + */ + int childFrameModeHeight() { return m_oldMainFrmHeight; }; + /** + * Tells the MDI system a QMenu where it can insert buttons for + * the system menu, undock, minimize, restore actions. + * If no such menu is given, KMdi simply overlays the buttons + * at the upper right-hand side of the main widget. + */ + virtual void setMenuForSDIModeSysButtons( KMenuBar* menuBar = 0 ); + + /** + * @return the decoration of the window frame of docked (attached) MDI views + */ + static int frameDecorOfAttachedViews() { return m_frameDecoration; } + + /** + * An SDI application user interface is faked: + * @li an opened view is always maximized + * @li buttons for maximized childframe mode aren't inserted in the main menubar + * @li taskbar and windowmenu are not created/updated + */ + void fakeSDIApplication(); + + /** + * @returns if we are faking an SDI application (fakeSDIApplication()) + */ + bool isFakingSDIApplication() const { return m_bSDIApplication; } + + virtual bool eventFilter( QObject *obj, QEvent *e ); + void findRootDockWidgets( QPtrList<KDockWidget>* pRootDockWidgetList, QValueList<QRect>* pPositionList ); + + /** We're switching something.*/ + void setSwitching( const bool switching ) { m_bSwitching = switching; } + bool switching( void ) const { return m_bSwitching; } + +public slots: + /** + * addWindow demands a KMdiChildView. This method wraps every QWidget in such an object and + * this way you can put every widget under MDI control. + */ + KMdiChildView* createWrapper( QWidget *view, const QString& name, const QString& shortName ); + + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param pWnd the parent view. + * \param flags the flags for the view such as: + * \li whether the view should be attached or detached. + * \li whether the view should be shown or hidden + * \li whether the view should be maximized, minimized or restored (normalized) + * \li whether the view should be added as tool view (stay-on-top and toplevel) or added as document-type view. + */ + virtual void addWindow( KMdiChildView* pWnd, int flags = KMdi::StandardAdd ); + + //KDE4: merge the two methods + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param pWnd the parent view. + * \param flags + * You can specify here whether: + * \li the view should be attached or detached. + * \li shown or hidden + * \li maximized, minimized or restored (normalized) + * \li added as tool view (stay-on-top and toplevel) or added as + * document-type view. + * \param index the index of the tab we should insert the new tab after. + * If index == -1 then the tab will just be appended to the end. + * Using this parameter in childview mode has no effect. + * \since 3.3 + */ + void addWindow( KMdiChildView* pWnd, int flags, int index ); + + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param pWnd the parent view. + * \param pos move the child view to the specified position + * \param flags the flags for the view such as: + * \li whether the view should be attached or detached. + * \li whether the view should be shown or hidden + * \li whether the view should be maximized, minimized or restored (normalized) + * \li whether the view should be added as tool view (stay-on-top and toplevel) or + * added as document-type view. + */ + virtual void addWindow( KMdiChildView* pWnd, QPoint pos, int flags = KMdi::StandardAdd ); + + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param pWnd the parent view. + * \param rectNormal Sets the geometry for this child view + * \param flags the flags for the view such as: + * \li whether the view should be attached or detached. + * \li whether the view should be shown or hidden + * \li whether the view should be maximized, minimized or restored (normalized) + * \li whether the view should be added as tool view (stay-on-top and toplevel) or + * added as document-type view. + */ + virtual void addWindow( KMdiChildView* pWnd, QRect rectNormal, int flags = KMdi::StandardAdd ); + + /** + * Usually called from addWindow() when adding a tool view window. It reparents the given widget + * as toplevel and stay-on-top on the application's main widget. + */ + virtual KMdiToolViewAccessor *addToolWindow( QWidget* pWnd, KDockWidget::DockPosition pos = KDockWidget::DockNone, + QWidget* pTargetWnd = 0L, int percent = 50, const QString& tabToolTip = 0, + const QString& tabCaption = 0 ); + + virtual void deleteToolWindow( QWidget* pWnd ); + virtual void deleteToolWindow( KMdiToolViewAccessor *accessor ); + + /** + * Using this method you have to use the setWidget method of the access object, and it is very recommendet, that you use + * the widgetContainer() method for the parent of your newly created widget + */ + KMdiToolViewAccessor *createToolWindow(); + + /** + * Removes a KMdiChildView from the MDI system and from the main frame`s control. + * The caller is responsible for deleting the view. If the view is not deleted it will + * be reparented to 0 + */ + virtual void removeWindowFromMdi( KMdiChildView *pWnd ); + + /** + * Removes a KMdiChildView from the MDI system and from the main frame`s control. + * Note: The view will be deleted! + */ + virtual void closeWindow( KMdiChildView *pWnd, bool layoutTaskBar = true ); + + /** + * Switches the KMdiTaskBar on and off. + */ + virtual void slot_toggleTaskBar(); + + /** + * Makes a main frame controlled undocked KMdiChildView docked. + * Doesn't work on KMdiChildView which aren't added to the MDI system. + * Use addWindow() for that. + */ + virtual void attachWindow( KMdiChildView *pWnd, bool bShow = true, bool bAutomaticResize = false ); + + /** + * Makes a docked KMdiChildView undocked. + * The view window still remains under the main frame's MDI control. + */ + virtual void detachWindow( KMdiChildView *pWnd, bool bShow = true ); + + /** + * Someone wants that the MDI view to be closed. This method sends a KMdiViewCloseEvent to itself + * to break the function call stack. See also event() . + */ + virtual void childWindowCloseRequest( KMdiChildView *pWnd ); + + /** + * Close all views + */ + virtual void closeAllViews(); + + /** + * Iconfiy all views + */ + virtual void iconifyAllViews(); + + /** + * Closes the view of the active (topchild) window + */ + virtual void closeActiveView(); + + /** + * Undocks all view windows (unix-like) + */ + virtual void switchToToplevelMode(); + virtual void finishToplevelMode(); + + /** + * Docks all view windows (Windows-like) + */ + virtual void switchToChildframeMode(); + virtual void finishChildframeMode(); + + /** + * Docks all view windows (Windows-like) + */ + virtual void switchToTabPageMode(); + virtual void finishTabPageMode(); + + /** + * Docks all view windows. Toolviews use dockcontainers + */ + virtual void switchToIDEAlMode(); + virtual void finishIDEAlMode( bool full = true ); + + /** + * Sets the appearance of the IDEAl mode. See KMultiTabBar styles for the first 3 bits. + * @deprecated use setToolviewStyle(int flags) instead + */ + void setIDEAlModeStyle( int flags ) KDE_DEPRECATED; + //KDE4: Get rid of the above. + /** + * Sets the appearance of the toolview tabs. + * @param flags See KMdi::ToolviewStyle. + * @since 3.3 + */ + void setToolviewStyle( int flags ); + /** + * @return if the view taskbar should be shown if there are MDI views + */ + bool isViewTaskBarOn(); + + /** + * Shows the view taskbar. This should be connected with your "View" menu. + */ + virtual void showViewTaskBar(); + + /** + * Hides the view taskbar. This should be connected with your "View" menu. + */ + virtual void hideViewTaskBar(); + + /** + * Update of the window menu contents. + */ + virtual void fillWindowMenu(); + + /** + * Cascades the windows without resizing them. + */ + virtual void cascadeWindows() { m_pMdi->cascadeWindows(); } + + /** + * Cascades the windows resizing them to the maximum available size. + */ + virtual void cascadeMaximized() { m_pMdi->cascadeMaximized(); } + + /** + * Maximizes only in vertical direction. + */ + virtual void expandVertical() { m_pMdi->expandVertical(); } + + /** + * Maximizes only in horizontal direction. + */ + virtual void expandHorizontal() { m_pMdi->expandHorizontal(); } + + /** + * Tile Pragma + */ + virtual void tilePragma() { m_pMdi->tilePragma(); } + + /** + * Tile Anodine + */ + virtual void tileAnodine() { m_pMdi->tileAnodine(); } + + /** + * Tile Vertically + */ + virtual void tileVertically() { m_pMdi->tileVertically(); } + + /** + * Sets the decoration of the window frame of docked (attached) MDI views + * @deprecated Will be removed in KDE 4 + */ + virtual void setFrameDecorOfAttachedViews( int frameDecor ); + + /** + * If in Childframe mode, we can switch between maximized or restored shown MDI views + */ + virtual void setEnableMaximizedChildFrmMode( bool bEnable ); + + /** + * Activates the next open view + */ + virtual void activateNextWin(); + + /** + * Activates the previous open view + */ + virtual void activatePrevWin(); + + /** + * Activates the view first viewed concerning to the access time. + */ + virtual void activateFirstWin(); + + /** + * Activates the view last viewed concerning to the access time. + */ + virtual void activateLastWin(); + + /** + * Activates the view with the tab page index (TabPage mode only) + */ + virtual void activateView( int index ); + +private: + void setupToolViewsForIDEALMode(); + void setupTabbedDocumentViewSpace(); + class KMdiDocumentViewTabWidget * m_documentTabWidget; + +protected: + + virtual void resizeEvent( QResizeEvent * ); + + /** + * Creates a new MDI taskbar (showing the MDI views as taskbar entries) and shows it. + */ + virtual void createTaskBar(); + + /** + * Creates the MDI view area and connects some signals and slots with the KMdiMainFrm widget. + */ + virtual void createMdiManager(); + + /** + * prevents fillWindowMenu() from m_pWindowMenu->clear(). You have to care for it by yourself. + * This is useful if you want to add some actions in your overridden fillWindowMenu() method. + */ + void blockClearingOfWindowMenu( bool bBlocked ) { m_bClearingOfWindowMenuBlocked = bBlocked; } + + void findToolViewsDockedToMain( QPtrList<KDockWidget>* list, KDockWidget::DockPosition dprtmw ); + void dockToolViewsIntoContainers( QPtrList<KDockWidget>& widgetsToReparent, KDockWidget *container ); + QStringList prepareIdealToTabs( KDockWidget* container ); + void idealToolViewsToStandardTabs( QStringList widgetNames, KDockWidget::DockPosition pos, int sizee ); + + /** Get tabwidget visibility */ + KMdi::TabWidgetVisibility tabWidgetVisibility(); + + /** Set tabwidget visibility */ + void setTabWidgetVisibility( KMdi::TabWidgetVisibility ); + + /** Returns the tabwidget used in IDEAl and Tabbed modes. Returns 0 in other modes. */ + class KTabWidget * tabWidget() const; + + +protected slots: // Protected slots + /** + * Sets the focus to this MDI view, raises it, activates its taskbar button and updates + * the system buttons in the main menubar when in maximized (Maximize mode). + */ + virtual void activateView( KMdiChildView *pWnd ); + + /** + * Activates the MDI view (see activateView() ) and popups the taskBar popup menu (see taskBarPopup() ). + */ + virtual void taskbarButtonRightClicked( KMdiChildView *pWnd ); + + /** + * Turns the system buttons for maximize mode (SDI mode) off, and disconnects them + */ + void switchOffMaximizeModeForMenu( KMdiChildFrm* oldChild ); + + /** + * Reconnects the system buttons form maximize mode (SDI mode) with the new child frame + */ + void updateSysButtonConnections( KMdiChildFrm* oldChild, KMdiChildFrm* newChild ); + + /** + * Usually called when the user clicks an MDI view item in the "Window" menu. + */ + void windowMenuItemActivated( int id ); + + /** + * Usually called when the user clicks an MDI view item in the sub-popup menu "Docking" of the "Window" menu. + */ + void dockMenuItemActivated( int id ); + + /** + * Popups the "Window" menu. See also windowPopup() . + */ + void popupWindowMenu( QPoint p ); + + /** + * The timer for main widget moving has elapsed -> send drag end to all concerned views. + */ + void dragEndTimeOut(); + + /** + * internally used to handle click on view close button (TabPage mode, only) + */ + void closeViewButtonPressed(); + +signals: + /** + * Signals the last attached KMdiChildView has been closed + */ + void lastChildFrmClosed(); + + /** + * Signals the last KMdiChildView (that is under MDI control) has been closed + */ + void lastChildViewClosed(); + + /** + * Signals that the Toplevel mode has been left + */ + void leftTopLevelMode(); + + /** + * Signals that a child view has been detached (undocked to desktop) + */ + void childViewIsDetachedNow( QWidget* ); + + /** Signals we need to collapse the overlapped containers */ + void collapseOverlapContainers(); + + /** Signals the MDI mode has been changed */ + void mdiModeHasBeenChangedTo( KMdi::MdiMode ); + + void viewActivated( KMdiChildView* ); + void viewDeactivated( KMdiChildView* ); + +public slots: + void prevToolViewInDock(); + void nextToolViewInDock(); + +private slots: + void setActiveToolDock( KMdiDockContainer* ); + void removeFromActiveDockList( KMdiDockContainer* ); + void slotDocCurrentChanged( QWidget* ); + void verifyToplevelHeight(); +#define protected public +signals: +#undef protected + + void toggleTop(); + void toggleLeft(); + void toggleRight(); + void toggleBottom(); +}; + +#endif //_KMDIMAINFRM_H_ + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmdinulliterator.h b/kmdi/kmdinulliterator.h new file mode 100644 index 000000000..3c976caac --- /dev/null +++ b/kmdi/kmdinulliterator.h @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------------- +// filename : kmdinulliterator.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 02/2000 by Massimo Morin +// changes : 02/2000 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Massimo Morin (mmorin@schedsys.com) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDINULLITERATOR_H_ +#define _KMDINULLITERATOR_H_ + +#include "kmdiiterator.h" + +template <class Item> +class KMdiNullIterator : public KMdiIterator<Item> { +public: + KMdiNullIterator() {}; + virtual void first() {} + virtual void last() {} + virtual void next() {} + virtual void prev() {} + virtual bool isDone() const { return true; } + virtual Item currentItem() const { + /* should really never go inside here */ + return 0; + } +}; + +#endif // _KMDINULLITERATOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmditaskbar.cpp b/kmdi/kmditaskbar.cpp new file mode 100644 index 000000000..2b86c0c85 --- /dev/null +++ b/kmdi/kmditaskbar.cpp @@ -0,0 +1,390 @@ +//---------------------------------------------------------------------------- +// filename : kmditaskbar.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#include "kmditaskbar.h" +#include "kmditaskbar.moc" + +#include "kmdimainfrm.h" +#include "kmdichildview.h" +#include "kmdidefines.h" + +#include <qtooltip.h> +#include <qlabel.h> +#include <qwidget.h> +#include <qstyle.h> + +#include <qnamespace.h> + +/* + @quickhelp: KMdiTaskBar + @widget: Taskbar + This window lists the currently open windows.<br> + Each button corresponds to a single MDI (child) window.<br> + The button is enabled (clickable) when the window is docked , and can be + pressed to bring it to the top of the other docked windows.<br> + The button text becomes red when new output is shown in the window and it is not the active one.<br> +*/ + +//#################################################################### +// +// KMdiTaskBarButton +// +//#################################################################### +KMdiTaskBarButton::KMdiTaskBarButton( KMdiTaskBar *pTaskBar, KMdiChildView *win_ptr ) + : QPushButton( pTaskBar ), + m_actualText( "" ) +{ + setToggleButton( true ); + m_pWindow = win_ptr; + QToolTip::add + ( this, win_ptr->caption() ); + setFocusPolicy( NoFocus ); +} + +KMdiTaskBarButton::~KMdiTaskBarButton() +{} + +void KMdiTaskBarButton::mousePressEvent( QMouseEvent* e ) +{ + switch ( e->button() ) + { + case QMouseEvent::LeftButton: + emit leftMouseButtonClicked( m_pWindow ); + break; + case QMouseEvent::RightButton: + emit rightMouseButtonClicked( m_pWindow ); + break; + default: + break; + } + emit clicked( m_pWindow ); +} + +/** slot version of setText */ +void KMdiTaskBarButton::setNewText( const QString& s ) +{ + setText( s ); + emit buttonTextChanged( 0 ); +} + +void KMdiTaskBarButton::setText( const QString& s ) +{ + m_actualText = s; + QButton::setText( s ); +} + +void KMdiTaskBarButton::fitText( const QString& origStr, int newWidth ) +{ + QButton::setText( m_actualText ); + + int actualWidth = sizeHint().width(); + int realLetterCount = origStr.length(); + int newLetterCount = ( newWidth * realLetterCount ) / actualWidth; + int w = newWidth + 1; + QString s = origStr; + while ( ( w > newWidth ) && ( newLetterCount >= 1 ) ) + { + if ( newLetterCount < realLetterCount ) + { + if ( newLetterCount > 3 ) + s = origStr.left( newLetterCount / 2 ) + "..." + origStr.right( newLetterCount / 2 ); + else + { + if ( newLetterCount > 1 ) + s = origStr.left( newLetterCount ) + ".."; + else + s = origStr.left( 1 ); + } + } + QFontMetrics fm = fontMetrics(); + w = fm.width( s ); + newLetterCount--; + } + + QButton::setText( s ); +} + +QString KMdiTaskBarButton::actualText() const +{ + return m_actualText; +} + +//#################################################################### +// +// KMdiTaskBar +// +//#################################################################### + +KMdiTaskBar::KMdiTaskBar( KMdiMainFrm *parent, QMainWindow::ToolBarDock dock ) + : KToolBar( parent, "KMdiTaskBar", /*honor_style*/ false, /*readConfig*/ true ) + , m_pCurrentFocusedWindow( 0 ) + , m_pStretchSpace( 0 ) + , m_layoutIsPending( false ) + , m_bSwitchedOn( false ) +{ + m_pFrm = parent; + m_pButtonList = new QPtrList<KMdiTaskBarButton>; + m_pButtonList->setAutoDelete( true ); + //QT30 setFontPropagation(QWidget::SameFont); + setMinimumWidth( 1 ); + setFocusPolicy( NoFocus ); + parent->moveToolBar( this, dock ); //XXX obsolete! +} + +KMdiTaskBar::~KMdiTaskBar() +{ + delete m_pButtonList; +} + +KMdiTaskBarButton * KMdiTaskBar::addWinButton( KMdiChildView *win_ptr ) +{ + if ( m_pStretchSpace ) + { + delete m_pStretchSpace; + m_pStretchSpace = 0L; + setStretchableWidget( 0L ); + } + + KMdiTaskBarButton *b = new KMdiTaskBarButton( this, win_ptr ); + QObject::connect( b, SIGNAL( clicked() ), win_ptr, SLOT( setFocus() ) ); + QObject::connect( b, SIGNAL( clicked( KMdiChildView* ) ), this, SLOT( setActiveButton( KMdiChildView* ) ) ); + QObject::connect( b, SIGNAL( leftMouseButtonClicked( KMdiChildView* ) ), m_pFrm, SLOT( activateView( KMdiChildView* ) ) ); + QObject::connect( b, SIGNAL( rightMouseButtonClicked( KMdiChildView* ) ), m_pFrm, SLOT( taskbarButtonRightClicked( KMdiChildView* ) ) ); + QObject::connect( b, SIGNAL( buttonTextChanged( int ) ), this, SLOT( layoutTaskBar( int ) ) ); + m_pButtonList->append( b ); + b->setToggleButton( true ); + b->setText( win_ptr->tabCaption() ); + + layoutTaskBar(); + + m_pStretchSpace = new QLabel( this, "empty" ); + m_pStretchSpace->setText( "" ); + setStretchableWidget( m_pStretchSpace ); + m_pStretchSpace->show(); + + if ( m_bSwitchedOn ) + { + b->show(); + show(); + } + return b; +} + +void KMdiTaskBar::removeWinButton( KMdiChildView *win_ptr, bool haveToLayoutTaskBar ) +{ + KMdiTaskBarButton * b = getButton( win_ptr ); + if ( b ) + { + m_pButtonList->removeRef( b ); + if ( haveToLayoutTaskBar ) + layoutTaskBar(); + } + if ( m_pButtonList->count() == 0 ) + { + if ( m_pStretchSpace != 0L ) + { + delete m_pStretchSpace; + m_pStretchSpace = 0L; + hide(); + } + } +} + +void KMdiTaskBar::switchOn( bool bOn ) +{ + m_bSwitchedOn = bOn; + if ( !bOn ) + { + hide(); + } + else + { + if ( m_pButtonList->count() > 0 ) + { + show(); + } + else + { + hide(); + } + } +} + +KMdiTaskBarButton * KMdiTaskBar::getButton( KMdiChildView *win_ptr ) +{ + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + return b; + } + return 0; +} + +KMdiTaskBarButton * KMdiTaskBar::getNextWindowButton( bool bRight, KMdiChildView *win_ptr ) +{ + if ( bRight ) + { + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + { + b = m_pButtonList->next(); + if ( !b ) + b = m_pButtonList->first(); + if ( win_ptr != b->m_pWindow ) + return b; + else + return 0; + } + } + } + else + { + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + { + b = m_pButtonList->prev(); + if ( !b ) + b = m_pButtonList->last(); + if ( win_ptr != b->m_pWindow ) + return b; + else + return 0; + } + } + } + return 0; +} + +void KMdiTaskBar::setActiveButton( KMdiChildView *win_ptr ) +{ + KMdiTaskBarButton * newPressedButton = 0L; + KMdiTaskBarButton* oldPressedButton = 0L; + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + newPressedButton = b; + if ( b->m_pWindow == m_pCurrentFocusedWindow ) + oldPressedButton = b; + } + + if ( newPressedButton != 0L && newPressedButton != oldPressedButton ) + { + if ( oldPressedButton != 0L ) + oldPressedButton->toggle(); // switch off + newPressedButton->toggle(); // switch on + m_pCurrentFocusedWindow = win_ptr; + } +} + +void KMdiTaskBar::layoutTaskBar( int taskBarWidth ) +{ + if ( m_layoutIsPending ) + return ; + m_layoutIsPending = true; + + if ( !taskBarWidth ) + // no width is given + taskBarWidth = width(); + + // calculate current width of all taskbar buttons + int allButtonsWidth = 0; + KMdiTaskBarButton *b = 0; + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + allButtonsWidth += b->width(); + } + + // calculate actual width of all taskbar buttons + int allButtonsWidthHint = 0; + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + QFontMetrics fm = b->fontMetrics(); + QString s = b->actualText(); + QSize sz = fm.size( ShowPrefix, s ); + int w = sz.width() + 6; + int h = sz.height() + sz.height() / 8 + 10; + w += h; + allButtonsWidthHint += w; + } + + // if there's enough space, use actual width + int buttonCount = m_pButtonList->count(); + int tbHandlePixel; + tbHandlePixel = style().pixelMetric( QStyle::PM_DockWindowHandleExtent, this ); + int buttonAreaWidth = taskBarWidth - tbHandlePixel - style().pixelMetric( QStyle::PM_DefaultFrameWidth, this ) - 5; + if ( ( ( allButtonsWidthHint ) <= buttonAreaWidth ) || ( width() < parentWidget() ->width() ) ) + { + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + b->setText( b->actualText() ); + if ( b->width() != b->sizeHint().width() ) + { + b->setFixedWidth( b->sizeHint().width() ); + b->show(); + } + } + } + else + { + // too many buttons for actual width + int newButtonWidth; + if ( buttonCount != 0 ) + newButtonWidth = buttonAreaWidth / buttonCount; + else + newButtonWidth = 0; + if ( orientation() == Qt::Vertical ) + newButtonWidth = 80; + if ( newButtonWidth > 0 ) + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + b->fitText( b->actualText(), newButtonWidth ); + if ( b->width() != newButtonWidth ) + { + b->setFixedWidth( newButtonWidth ); + b->show(); + } + } + } + m_layoutIsPending = false; +} + +void KMdiTaskBar::resizeEvent( QResizeEvent* rse ) +{ + if ( !m_layoutIsPending ) + { + if ( m_pButtonList->count() != 0 ) + { + layoutTaskBar( rse->size().width() ); + } + } + KToolBar::resizeEvent( rse ); +} + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/kmdi/kmditaskbar.h b/kmdi/kmditaskbar.h new file mode 100644 index 000000000..f485fb864 --- /dev/null +++ b/kmdi/kmditaskbar.h @@ -0,0 +1,219 @@ +//---------------------------------------------------------------------------- +// filename : kmditaskbar.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDITASKBAR_H_ +#define _KMDITASKBAR_H_ + +#include <ktoolbar.h> +#include <qptrlist.h> +#include <qpixmap.h> +#include <qlabel.h> +#include <qpushbutton.h> + +#include "kmdidefines.h" + +class KMdiMainFrm; +class KMdiChildView; +class KMdiTaskBar; + +class KMdiTaskBarButtonPrivate; + +/** + * @short Internal class. + * + * It's a special kind of QPushButton catching mouse clicks. + * And you have the ability to abbreviate the text that it fits in the button. + */ +class KMDI_EXPORT KMdiTaskBarButton : public QPushButton +{ + Q_OBJECT + // methods +public: + /** + * Constructor (sets to toggle button, adds a tooltip (caption) and sets to NoFocus + */ + KMdiTaskBarButton( KMdiTaskBar *pTaskBar, KMdiChildView *win_ptr ); + /** + * Destructor + */ + ~KMdiTaskBarButton(); + /** + * text() returns the possibly abbreviated text including the dots in it. But actualText() returns the full text. + */ + QString actualText() const; + /** + * Given the parameter newWidth this function possibly abbreviates the parameter string and sets a new button text. + */ + void fitText( const QString&, int newWidth ); + /** + * Sets the text and avoids any abbreviation. Memorizes that text in m_actualText, too. + */ + void setText( const QString& ); +signals: + /** + * Emitted when the button has been clicked. Internally connected to setFocus of the according MDI view. + */ + void clicked( KMdiChildView* ); + /** + * Internally connected with KMdiMainFrm::activateView + */ + void leftMouseButtonClicked( KMdiChildView* ); + /** + * Internally connected with KMdiMainFrm::taskbarButtonRightClicked + */ + void rightMouseButtonClicked( KMdiChildView* ); + /** + * Emitted when the button text has changed. Internally connected with KMdiTaskBar::layoutTaskBar + */ + void buttonTextChanged( int ); +public slots: + /** + * A slot version of setText + */ + void setNewText( const QString& ); +protected slots: + /** + * Reimplemented from its base class to catch right and left mouse button clicks + */ + void mousePressEvent( QMouseEvent* ); + + // attributes +public: + /** + * The according MDI view + */ + KMdiChildView *m_pWindow; +protected: + /** + * Internally we must remember the real text because the button text can be abbreviated. + */ + QString m_actualText; + +private: + KMdiTaskBarButtonPrivate *d; +}; + + +class KMdiTaskBarPrivate; +/** + * @short Internal class. + * + * It's a special kind of QToolBar that acts as taskbar for child views. + * KMdiTaskBarButtons can be added or removed dynamically.<br> + * The button sizes are adjusted dynamically, as well. + */ +class KMDI_EXPORT KMdiTaskBar : public KToolBar +{ + Q_OBJECT +public: + /** + * Constructor (NoFocus, minimum width = 1, an internal QPtrList of taskbar buttons (autodelete)) + */ + KMdiTaskBar( KMdiMainFrm *parent, QMainWindow::ToolBarDock dock ); + /** + * Destructor (deletes the taskbar button list) + */ + ~KMdiTaskBar(); + /** + *Add a new KMdiTaskBarButton . The width doesn't change. + * If there's not enough space, all taskbar buttons will be resized to a new smaller size. + * Probably button texts must be abbreviated now. + */ + KMdiTaskBarButton * addWinButton( KMdiChildView *win_ptr ); + /** + * Removes a KMdiTaskBarButton and deletes it. If the rest of the buttons are smaller + * than they usually are, all those buttons will be resized in a way that the new free size is used as well. + */ + void removeWinButton( KMdiChildView *win_ptr, bool haveToLayoutTaskBar = true ); + /** + * Returns the neighbor taskbar button of the taskbar button of the MDI view given by parameter + * bRight specifies the side, of course left is used if bRight is false. + */ + KMdiTaskBarButton * getNextWindowButton( bool bRight, KMdiChildView *win_ptr ); + /** + * Get the button belonging to the MDI view given as parameter. + */ + KMdiTaskBarButton * getButton( KMdiChildView *win_ptr ); + /** + * Switch it on or off. + */ + void switchOn( bool bOn ); + /** + * @return whether switched on or off. + */ + bool isSwitchedOn() const + { + return m_bSwitchedOn; + }; +protected: + /** + * Reimplemented from its base class to call layoutTaskBar, additionally. + */ + void resizeEvent( QResizeEvent* ); +protected slots: + /** + * Checks if all buttons fits into this. If not, it recalculates all button widths + * in a way that all buttons fits into the taskbar and have got equal width. + * The text of the buttons will be abbreviated when nessecary, all buttons get a + * fixed width and show() is called for each one. + * If one drags the taskbar to a vertical orientation, the button width is set to 80 pixel. + */ + void layoutTaskBar( int taskBarWidth = 0 ); +public slots: + /** + * Pushes the desired taskbar button down (switch on), the old one is released (switched off). + * Actually it's a radiobutton group behavior. + */ + void setActiveButton( KMdiChildView *win_ptr ); +protected: + /** + * A list of taskbar buttons. + * Note: Each button stands for one MDI view (toolviews doesn't have got a taskbar button). + */ + QPtrList<KMdiTaskBarButton>* m_pButtonList; + /** + * The belonging MDI mainframe (parent widget of this) + */ + KMdiMainFrm* m_pFrm; + /** + * The MDI view belonging to the currently pressed taskbar button + */ + KMdiChildView* m_pCurrentFocusedWindow; + /** + * A stretchable widget used as 'space' at the end of a half filled taskbar + */ + QLabel* m_pStretchSpace; + bool m_layoutIsPending; + bool m_bSwitchedOn; + +private: + KMdiTaskBarPrivate *d; +}; + +#endif //_KMDITASKBAR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmditoolviewaccessor.cpp b/kmdi/kmditoolviewaccessor.cpp new file mode 100644 index 000000000..f9921e18c --- /dev/null +++ b/kmdi/kmditoolviewaccessor.cpp @@ -0,0 +1,269 @@ +//---------------------------------------------------------------------------- +// filename : kmditoolviewaccessor.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 08/2003 by Joseph Wenninger (jowenn@kde.org) +// changes : --- +// patches : --- +// +// copyright : (C) 2003 by Joseph Wenninger (jowenn@kde.org) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef NO_KDE +# include <kdebug.h> +#endif +#include "kmditoolviewaccessor_p.h" +#include "kmdiguiclient.h" +#include "kmdimainfrm.h" + +#include "kmditoolviewaccessor.h" +#include "kmditoolviewaccessor_p.h" + +KMdiToolViewAccessor::KMdiToolViewAccessor( KMdiMainFrm *parent, QWidget *widgetToWrap, const QString& tabToolTip, const QString& tabCaption ) + : QObject( parent ) +{ + mdiMainFrm = parent; + d = new KMdiToolViewAccessorPrivate(); + if ( widgetToWrap->inherits( "KDockWidget" ) ) + { + d->widgetContainer = dynamic_cast<KDockWidget*>( widgetToWrap ); + d->widget = d->widgetContainer->getWidget(); + } + else + { + d->widget = widgetToWrap; + QString finalTabCaption; + if ( tabCaption == 0 ) + { + finalTabCaption = widgetToWrap->caption(); + if ( finalTabCaption.isEmpty() && !widgetToWrap->icon() ) + { + finalTabCaption = widgetToWrap->name(); + } + } + else + { + finalTabCaption = tabCaption; + } + d->widgetContainer = parent->createDockWidget( widgetToWrap->name(), + ( widgetToWrap->icon() ? ( *( widgetToWrap->icon() ) ) : QPixmap() ), + 0L, // parent + widgetToWrap->caption(), + finalTabCaption ); + d->widgetContainer->setWidget( widgetToWrap ); + if ( tabToolTip != 0 ) + { + d->widgetContainer->setToolTipString( tabToolTip ); + } + } + //mdiMainFrm->m_pToolViews->insert(d->widget,this); + if ( mdiMainFrm->m_mdiGUIClient ) + mdiMainFrm->m_mdiGUIClient->addToolView( this ); + else + kdDebug( 760 ) << "mdiMainFrm->m_mdiGUIClient == 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl; + + d->widget->installEventFilter( this ); +} + +KMdiToolViewAccessor::KMdiToolViewAccessor( KMdiMainFrm *parent ) +{ + mdiMainFrm = parent; + d = new KMdiToolViewAccessorPrivate(); +} + +KMdiToolViewAccessor::~KMdiToolViewAccessor() +{ + if ( mdiMainFrm->m_pToolViews ) + mdiMainFrm->m_pToolViews->remove + ( d->widget ); + delete d; + +} + +QWidget *KMdiToolViewAccessor::wrapperWidget() +{ + if ( !d->widgetContainer ) + { + d->widgetContainer = mdiMainFrm->createDockWidget( "KMdiToolViewAccessor::null", QPixmap() ); + connect( d->widgetContainer, SIGNAL( widgetSet( QWidget* ) ), this, SLOT( setWidgetToWrap( QWidget* ) ) ); + } + return d->widgetContainer; +} + +QWidget *KMdiToolViewAccessor::wrappedWidget() +{ + return d->widget; +} + + +void KMdiToolViewAccessor::setWidgetToWrap( QWidget *widgetToWrap, const QString& tabToolTip, const QString& tabCaption ) +{ + Q_ASSERT( !( d->widget ) ); + Q_ASSERT( !widgetToWrap->inherits( "KDockWidget" ) ); + disconnect( d->widgetContainer, SIGNAL( widgetSet( QWidget* ) ), this, SLOT( setWidgetToWrap( QWidget* ) ) ); + delete d->widget; + d->widget = widgetToWrap; + KDockWidget *tmp = d->widgetContainer; + + QString finalTabCaption; + if ( tabCaption == 0 ) + { + finalTabCaption = widgetToWrap->caption(); + if ( finalTabCaption.isEmpty() && !widgetToWrap->icon() ) + { + finalTabCaption = widgetToWrap->name(); + } + } + else + { + finalTabCaption = tabCaption; + } + + if ( !tmp ) + { + tmp = mdiMainFrm->createDockWidget( widgetToWrap->name(), + widgetToWrap->icon() ? ( *( widgetToWrap->icon() ) ) : QPixmap(), + 0L, // parent + widgetToWrap->caption(), + finalTabCaption ); + d->widgetContainer = tmp; + if ( tabToolTip != 0 ) + { + d->widgetContainer->setToolTipString( tabToolTip ); + } + } + else + { + tmp->setCaption( widgetToWrap->caption() ); + tmp->setTabPageLabel( finalTabCaption ); + tmp->setPixmap( widgetToWrap->icon() ? ( *( widgetToWrap->icon() ) ) : QPixmap() ); + tmp->setName( widgetToWrap->name() ); + if ( tabToolTip != 0 ) + { + d->widgetContainer->setToolTipString( tabToolTip ); + } + } + tmp->setWidget( widgetToWrap ); + mdiMainFrm->m_pToolViews->insert( widgetToWrap, this ); + if ( mdiMainFrm->m_mdiGUIClient ) + mdiMainFrm->m_mdiGUIClient->addToolView( this ); + else + kdDebug( 760 ) << "mdiMainFrm->m_mdiGUIClient == 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl; + + d->widget->installEventFilter( this ); +} + + +bool KMdiToolViewAccessor::eventFilter( QObject *, QEvent *e ) +{ + if ( e->type() == QEvent::IconChange ) + { + d->widgetContainer->setPixmap( d->widget->icon() ? ( *d->widget->icon() ) : QPixmap() ); + } + return false; +} + +void KMdiToolViewAccessor::placeAndShow( KDockWidget::DockPosition pos, QWidget* pTargetWnd , int percent ) +{ + place( pos, pTargetWnd, percent ); + show(); +} +void KMdiToolViewAccessor::place( KDockWidget::DockPosition pos, QWidget* pTargetWnd , int percent ) +{ + Q_ASSERT( d->widgetContainer ); + if ( !d->widgetContainer ) + return ; + if ( pos == KDockWidget::DockNone ) + { + d->widgetContainer->setEnableDocking( KDockWidget::DockNone ); + d->widgetContainer->reparent( mdiMainFrm, Qt::WType_TopLevel | Qt::WType_Dialog, QPoint( 0, 0 ), true ); //pToolView->isVisible()); + } + else + { // add (and dock) the toolview as DockWidget view + + KDockWidget* pCover = d->widgetContainer; + + KDockWidget* pTargetDock = 0L; + if ( pTargetWnd->inherits( "KDockWidget" ) || pTargetWnd->inherits( "KDockWidget_Compat::KDockWidget" ) ) + { + pTargetDock = ( KDockWidget* ) pTargetWnd; + } + + // Should we dock to ourself? + bool DockToOurself = false; + if ( mdiMainFrm->m_pDockbaseAreaOfDocumentViews ) + { + if ( pTargetWnd == mdiMainFrm->m_pDockbaseAreaOfDocumentViews->getWidget() ) + { + DockToOurself = true; + pTargetDock = mdiMainFrm->m_pDockbaseAreaOfDocumentViews; + } + else if ( pTargetWnd == mdiMainFrm->m_pDockbaseAreaOfDocumentViews ) + { + DockToOurself = true; + pTargetDock = mdiMainFrm->m_pDockbaseAreaOfDocumentViews; + } + } + // this is not inheriting QWidget*, its plain impossible that this condition is true + //if (pTargetWnd == this) DockToOurself = true; + if ( !DockToOurself ) + if ( pTargetWnd != 0L ) + { + pTargetDock = mdiMainFrm->dockManager->findWidgetParentDock( pTargetWnd ); + if ( !pTargetDock ) + { + if ( pTargetWnd->parentWidget() ) + { + pTargetDock = mdiMainFrm->dockManager->findWidgetParentDock( pTargetWnd->parentWidget() ); + } + } + } + if ( !pTargetDock || pTargetWnd == mdiMainFrm->getMainDockWidget() ) + { + if ( mdiMainFrm->m_managedDockPositionMode && ( mdiMainFrm->m_pMdi || mdiMainFrm->m_documentTabWidget ) ) + { + KDockWidget * dw1 = pTargetDock->findNearestDockWidget( pos ); + if ( dw1 ) + pCover->manualDock( dw1, KDockWidget::DockCenter, percent ); + else + pCover->manualDock ( pTargetDock, pos, 20 ); + return ; + } + } + pCover->manualDock( pTargetDock, pos, percent ); + //check pCover->show(); + } +} + +void KMdiToolViewAccessor::hide() +{ + Q_ASSERT( d->widgetContainer ); + if ( !d->widgetContainer ) + return ; + d->widgetContainer->undock(); +} + +void KMdiToolViewAccessor::show() +{ + Q_ASSERT( d->widgetContainer ); + if ( !d->widgetContainer ) + return ; + d->widgetContainer->makeDockVisible(); +} + + +#ifndef NO_INCLUDE_MOCFILES +#include "kmditoolviewaccessor.moc" +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmditoolviewaccessor.h b/kmdi/kmditoolviewaccessor.h new file mode 100644 index 000000000..d5bd49a74 --- /dev/null +++ b/kmdi/kmditoolviewaccessor.h @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// filename : kmditoolviewaccessor.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 08/2003 by Joseph Wenninger (jowenn@kde.org) +// changes : --- +// patches : --- +// +// copyright : (C) 2003 by Joseph Wenninger (jowenn@kde.org) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- +#ifndef _KMDITOOLVIEWACCESSOR_H_ +#define _KMDITOOLVIEWACCESSOR_H_ + +#include <qwidget.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdatetime.h> + +#include <kdockwidget.h> + +namespace KMDIPrivate +{ +class KMDIGUIClient; +} + + +class KMDI_EXPORT KMdiToolViewAccessor : public QObject +{ + Q_OBJECT + + + friend class KMdiMainFrm; + friend class KMDIPrivate::KMDIGUIClient; + +private: + /** + * Internally used by KMdiMainFrm to store a temporary information that the method + * activate() is unnecessary and that it can by escaped. + * This saves from unnecessary calls when activate is called directly. + */ + bool m_bInterruptActivation; + /** + * Internally used to prevent cycles between KMdiMainFrm::activateView() and KMdiChildView::activate(). + */ + bool m_bMainframesActivateViewIsPending; + /** + * + */ + bool m_bFocusInEventIsPending; + +private: + KMdiToolViewAccessor( class KMdiMainFrm *parent , QWidget *widgetToWrap, const QString& tabToolTip = 0, const QString& tabCaption = 0 ); + KMdiToolViewAccessor( class KMdiMainFrm *parent ); +public: + ~KMdiToolViewAccessor(); + QWidget *wrapperWidget(); + QWidget *wrappedWidget(); + void place( KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L, int percent = 50 ); + void placeAndShow( KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L, int percent = 50 ); + void show(); +public slots: + void setWidgetToWrap( QWidget* widgetToWrap, const QString& tabToolTip = 0, const QString& tabCaption = 0 ); + void hide(); +private: + class KMdiToolViewAccessorPrivate *d; + class KMdiMainFrm *mdiMainFrm; + +protected: + bool eventFilter( QObject *o, QEvent *e ); +}; + + +#endif //_KMDITOOLVIEWACCESSOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/kmdi/kmditoolviewaccessor_p.h b/kmdi/kmditoolviewaccessor_p.h new file mode 100644 index 000000000..913b88541 --- /dev/null +++ b/kmdi/kmditoolviewaccessor_p.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// filename : kmditoolviewaccessor_p.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 08/2003 by Joseph Wenninger (jowenn@kde.org) +// changes : --- +// patches : --- +// +// copyright : (C) 2003 by Joseph Wenninger (jowenn@kde.org) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + + +#ifndef KMDI_TOOLVIEW_ACCESSOR_PRIVATE_H_ +#define KMDI_TOOLVIEW_ACCESSOR_PRIVATE_H_ + + +#include <qwidget.h> +#include <kdockwidget.h> +#include <qguardedptr.h> +#include <kaction.h> + +class KMDI_EXPORT KMdiToolViewAccessorPrivate { +public: + KMdiToolViewAccessorPrivate() { + widgetContainer=0; + widget=0; + } + ~KMdiToolViewAccessorPrivate() { + delete action; + if (!widgetContainer.isNull()) widgetContainer->undock(); + delete (KDockWidget*)widgetContainer; + } + QGuardedPtr<KDockWidget> widgetContainer; + QWidget* widget; + QGuardedPtr<KAction> action; +}; + + +#endif + + diff --git a/kmdi/res/filenew.xpm b/kmdi/res/filenew.xpm new file mode 100644 index 000000000..b261800d6 --- /dev/null +++ b/kmdi/res/filenew.xpm @@ -0,0 +1,27 @@ +/* XPM */ +#ifndef _FILENEW_XPM_ +#define _FILENEW_XPM_ + +static const char *filenew[] = { +"10 14 5 1", +" c None", +". c #000000", +"+ c #FFFFFF", +"@ c #DCDCDC", +"# c #C0C0C0", +"....... ", +".++++@@. ", +".++++#+@. ", +".++++#++@.", +".++++#....", +".+++++###.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".........."}; + +#endif diff --git a/kmdi/res/kde2_closebutton.xpm b/kmdi/res/kde2_closebutton.xpm new file mode 100644 index 000000000..5c05e7149 --- /dev/null +++ b/kmdi/res/kde2_closebutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_CLOSEBUTTON_XPM_ +#define _KDE2_CLOSEBUTTON_XPM_ + +static const char* kde2_closebutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +"............", +"...#....#...", +"..###..###..", +"...######...", +"....####....", +"....####....", +"...######...", +"..###..###..", +"...#....#...", +"............", +"............"}; + +#endif diff --git a/kmdi/res/kde2_maxbutton.xpm b/kmdi/res/kde2_maxbutton.xpm new file mode 100644 index 000000000..c8ef81139 --- /dev/null +++ b/kmdi/res/kde2_maxbutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_MAXBUTTON_XPM_ +#define _KDE2_MAXBUTTON_XPM_ + +static const char* kde2_maxbutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +"............", +"..########..", +"..########..", +"..##....##..", +"..##....##..", +"..##....##..", +"..##....##..", +"..########..", +"..########..", +"............", +"............"}; + +#endif diff --git a/kmdi/res/kde2_minbutton.xpm b/kmdi/res/kde2_minbutton.xpm new file mode 100644 index 000000000..98669195d --- /dev/null +++ b/kmdi/res/kde2_minbutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_MINBUTTON_XPM_ +#define _KDE2_MINBUTTON_XPM_ + +static const char* kde2_minbutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +"............", +"............", +"............", +"....####....", +"....####....", +"....####....", +"....####....", +"............", +"............", +"............", +"............"}; + +#endif diff --git a/kmdi/res/kde2_restorebutton.xpm b/kmdi/res/kde2_restorebutton.xpm new file mode 100644 index 000000000..a6e01fcba --- /dev/null +++ b/kmdi/res/kde2_restorebutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_RESTOREBUTTON_XPM_ +#define _KDE2_RESTOREBUTTON_XPM_ + +static const char* kde2_restorebutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +".########...", +".########...", +".##....##...", +".##.########", +".##.########", +".#####....##", +".#####....##", +"....##....##", +"....########", +"....########", +"............"}; + +#endif diff --git a/kmdi/res/kde2_undockbutton.xpm b/kmdi/res/kde2_undockbutton.xpm new file mode 100644 index 000000000..711bf01cc --- /dev/null +++ b/kmdi/res/kde2_undockbutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_UNDOCKBUTTON_XPM_ +#define _KDE2_UNDOCKBUTTON_XPM_ + +static const char* kde2_undockbutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +".#####......", +".#####......", +".####.......", +".#####......", +".##.###.....", +".....###....", +"......###...", +".......###..", +"........##..", +"............", +"............"}; + +#endif diff --git a/kmdi/res/kde2laptop_closebutton.xpm b/kmdi/res/kde2laptop_closebutton.xpm new file mode 100644 index 000000000..6801e4e33 --- /dev/null +++ b/kmdi/res/kde2laptop_closebutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_CLOSEBUTTON_XPM_ +#define _KDE2LAPTOP_CLOSEBUTTON_XPM_ + +static const char* kde2laptop_closebutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +".......#....#.......", +"......###..###......", +".......######.......", +"........####........", +"........####........", +".......######.......", +"......###..###......", +".......#....#......."}; + +#endif diff --git a/kmdi/res/kde2laptop_closebutton_menu.xpm b/kmdi/res/kde2laptop_closebutton_menu.xpm new file mode 100644 index 000000000..9d0712319 --- /dev/null +++ b/kmdi/res/kde2laptop_closebutton_menu.xpm @@ -0,0 +1,25 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_CLOSEBUTTON_MENU_XPM_ +#define _KDE2LAPTOP_CLOSEBUTTON_MENU_XPM_ + +static const char* kde2laptop_closebutton_menu[]={ +"27 14 3 1", +". s None c None", +"+ c #303030", +"# c #000000", +"##########################.", +"#........................#+", +"#........................#+", +"#.........#....#.........#+", +"#........###..###........#+", +"#.........######.........#+", +"#..........####..........#+", +"#..........####..........#+", +"#.........######.........#+", +"#........###..###........#+", +"#.........#....#.........#+", +"#........................#+", +"##########################+", +".++++++++++++++++++++++++++"}; + +#endif diff --git a/kmdi/res/kde2laptop_maxbutton.xpm b/kmdi/res/kde2laptop_maxbutton.xpm new file mode 100644 index 000000000..b8ce6de2c --- /dev/null +++ b/kmdi/res/kde2laptop_maxbutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_MAXBUTTON_XPM_ +#define _KDE2LAPTOP_MAXBUTTON_XPM_ + +static const char* kde2laptop_maxbutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +"........##..........", +".......####.........", +"......######........", +".....########.......", +".....########.......", +"....................", +".....########.......", +".....########......."}; + +#endif diff --git a/kmdi/res/kde2laptop_minbutton.xpm b/kmdi/res/kde2laptop_minbutton.xpm new file mode 100644 index 000000000..6bcf76c57 --- /dev/null +++ b/kmdi/res/kde2laptop_minbutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_MINBUTTON_XPM_ +#define _KDE2LAPTOP_MINBUTTON_XPM_ + +static const char* kde2laptop_minbutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +"......########......", +"......########......", +"....................", +"......########......", +"......########......", +".......######.......", +"........####........", +".........##........."}; + +#endif diff --git a/kmdi/res/kde2laptop_restorebutton.xpm b/kmdi/res/kde2laptop_restorebutton.xpm new file mode 100644 index 000000000..803ce6db4 --- /dev/null +++ b/kmdi/res/kde2laptop_restorebutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_RESTOREBUTTON_XPM_ +#define _KDE2LAPTOP_RESTOREBUTTON_XPM_ + +static const char* kde2laptop_restorebutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +".......##...........", +"........##..........", +".....##..##.........", +".....###..##........", +".....####..##.......", +".....#####..#.......", +".....######.........", +".....#######........"}; + +#endif diff --git a/kmdi/res/kde2laptop_undockbutton.xpm b/kmdi/res/kde2laptop_undockbutton.xpm new file mode 100644 index 000000000..1f23ecaf8 --- /dev/null +++ b/kmdi/res/kde2laptop_undockbutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_UNDOCKBUTTON_XPM_ +#define _KDE2LAPTOP_UNDOCKBUTTON_XPM_ + +static const char* kde2laptop_undockbutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +".....######.........", +".....#####..........", +".....####...........", +".....#####..........", +".....##.###.........", +".....#...###........", +"..........###.......", +"...........##......."}; + +#endif diff --git a/kmdi/res/kde_closebutton.xpm b/kmdi/res/kde_closebutton.xpm new file mode 100644 index 000000000..e714359a8 --- /dev/null +++ b/kmdi/res/kde_closebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_CLOSEBUTTON_XPM_ +#define _KDE_CLOSEBUTTON_XPM_ + +static const char *kde_closebutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c white", +"X c #707070", +/* pixels */ +" ", +" ", +" .X .X ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .XX.XX ", +" .XXX ", +" .XXX ", +" .XX.XX ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .X .X ", +" ", +" "}; + +#endif diff --git a/kmdi/res/kde_maxbutton.xpm b/kmdi/res/kde_maxbutton.xpm new file mode 100644 index 000000000..2af3bf882 --- /dev/null +++ b/kmdi/res/kde_maxbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_MAXBUTTON_XPM_ +#define _KDE_MAXBUTTON_XPM_ + +static const char *kde_maxbutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c white", +"X c #707070", +/* pixels */ +" ", +" ", +" ........... ", +" .XXXXXXXXXX ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X........X ", +" .XXXXXXXXXX ", +" ", +" ", +" "}; + +#endif diff --git a/kmdi/res/kde_minbutton.xpm b/kmdi/res/kde_minbutton.xpm new file mode 100644 index 000000000..c4e609ae7 --- /dev/null +++ b/kmdi/res/kde_minbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_MINBUTTON_XPM_ +#define _KDE_MINBUTTON_XPM_ + +static const char *kde_minbutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c white", +"X c #707070", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ... ", +" . X ", +" .XX ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; + +#endif diff --git a/kmdi/res/kde_restorebutton.xpm b/kmdi/res/kde_restorebutton.xpm new file mode 100644 index 000000000..4ec185133 --- /dev/null +++ b/kmdi/res/kde_restorebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_RESTOREBUTTON_XPM_ +#define _KDE_RESTOREBUTTON_XPM_ + +static const char *kde_restorebutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c #707070", +"X c white", +/* pixels */ +" ", +" ", +" ........... ", +" .XXXXXXXXXX ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X........X ", +" .XXXXXXXXXX ", +" ", +" ", +" "}; + +#endif diff --git a/kmdi/res/kde_undockbutton.xpm b/kmdi/res/kde_undockbutton.xpm new file mode 100644 index 000000000..de97e9e77 --- /dev/null +++ b/kmdi/res/kde_undockbutton.xpm @@ -0,0 +1,27 @@ +/* XPM */ +#ifndef _KDE_UNDOCKBUTTON_XPM_ +#define _KDE_UNDOCKBUTTON_XPM_ + +static const char *kde_undockbutton[]={ +"16 16 3 1", +". c None", +"# c #ffffff", +"a c #707070", +"................", +"................", +"..#aaaaaaa......", +"..#aa#####......", +"..#aaa..........", +"..#a#aa.........", +"..#a.#aa........", +"..#a..#aa.......", +"..#a...#aa......", +"..#a....#aa.....", +".........#aa....", +"..........#aa...", +"...........#aa..", +"............#...", +"................", +"................"}; + +#endif diff --git a/kmdi/res/win_closebutton.xpm b/kmdi/res/win_closebutton.xpm new file mode 100644 index 000000000..d8be02435 --- /dev/null +++ b/kmdi/res/win_closebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_CLOSEBUTTON_XPM_ +#define _WIN_CLOSEBUTTON_XPM_ + +static const char *win_closebutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaa..aaaa..aa#.", +"baaaa..aa..aaa#.", +"baaaaa....aaaa#.", +"baaaaaa..aaaaa#.", +"baaaaa....aaaa#.", +"baaaa..aa..aaa#.", +"baaa..aaaa..aa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/kmdi/res/win_maxbutton.xpm b/kmdi/res/win_maxbutton.xpm new file mode 100644 index 000000000..95e501a82 --- /dev/null +++ b/kmdi/res/win_maxbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_MAXBUTTON_XPM_ +#define _WIN_MAXBUTTON_XPM_ + +static const char *win_maxbutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baa.........aa#.", +"baa.........aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.........aa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/kmdi/res/win_minbutton.xpm b/kmdi/res/win_minbutton.xpm new file mode 100644 index 000000000..1e8787e78 --- /dev/null +++ b/kmdi/res/win_minbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_MINBUTTON_XPM_ +#define _WIN_MINBUTTON_XPM_ + +static const char *win_minbutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaa......aaaa#.", +"baaa......aaaa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/kmdi/res/win_restorebutton.xpm b/kmdi/res/win_restorebutton.xpm new file mode 100644 index 000000000..87bb5b30f --- /dev/null +++ b/kmdi/res/win_restorebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_RESTOREBUTTON_XPM_ +#define _WIN_RESTOREBUTTON_XPM_ + +static const char *win_restorebutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baaaa......aaa#.", +"baaaa......aaa#.", +"baaaa.aaaa.aaa#.", +"baa......a.aaa#.", +"baa......a.aaa#.", +"baa.aaaa...aaa#.", +"baa.aaaa.aaaaa#.", +"baa.aaaa.aaaaa#.", +"baa......aaaaa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/kmdi/res/win_undockbutton.xpm b/kmdi/res/win_undockbutton.xpm new file mode 100644 index 000000000..386ebd8a9 --- /dev/null +++ b/kmdi/res/win_undockbutton.xpm @@ -0,0 +1,26 @@ +/* XPM */ +#ifndef _WIN_UNDOCKBUTTON_XPM_ +#define _WIN_UNDOCKBUTTON_XPM_ + +static const char* win_undockbutton[]={ +"16 14 4 1", +"b c #808080", +"# c #000000", +"a c None", +". c #ffffff", +"...............#", +".aaaaaaaaaaaaab#", +".aaaaaaaaaaaaab#", +".aaa####aaaaaab#", +".aaa###aaaaaaab#", +".aaa####aaaaaab#", +".aaa#a###aaaaab#", +".aaaaaa###aaaab#", +".aaaaaaa###aaab#", +".aaaaaaaa###aab#", +".aaaaaaaaa#aaab#", +".aaaaaaaaaaaaab#", +".bbbbbbbbbbbbbb#", +"################"}; + +#endif diff --git a/kmdi/test/Makefile.am b/kmdi/test/Makefile.am new file mode 100644 index 000000000..73e0b8a13 --- /dev/null +++ b/kmdi/test/Makefile.am @@ -0,0 +1,10 @@ +check_PROGRAMS = kfourchildren +METASOURCES = AUTO + +INCLUDES = -I$(top_srcdir)/kmdi -I.. $(all_includes) + +kfourchildren_SOURCES = hello.cpp main.cpp mainwidget.cpp +kfourchildren_LDFLAGS = -no-undefined $(all_libraries) +kfourchildren_LDADD = $(top_builddir)/kmdi/libkmdi.la \ + $(top_builddir)/kutils/libkutils.la + diff --git a/kmdi/test/README b/kmdi/test/README new file mode 100644 index 000000000..0cdeae7ef --- /dev/null +++ b/kmdi/test/README @@ -0,0 +1,16 @@ +This example shows the use of KMdi. +Either you inherit your views from KMdiChildView or you wrap your common widgets by KMdiChildViews. +Your main widget must inherit from KMdiMainFrm. + + + +Call + qmake kFourChildren -o Makefile + make +to build the example app. +Likely you must set the environment variable KDEDIR (to e.g. /opt/kde3). + + + +Find more details on: + http://www.geocities.com/gigafalk/qextmdi.htm diff --git a/kmdi/test/hello.cpp b/kmdi/test/hello.cpp new file mode 100644 index 000000000..f3a10f65c --- /dev/null +++ b/kmdi/test/hello.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** $Id$ +** +** Copyright (C) 1992-1999 Troll Tech AS. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#include "hello.h" +#include <qpushbutton.h> +#include <qtimer.h> +#include <qpainter.h> +#include <qpixmap.h> + +/* + Constructs a Hello widget. Starts a 40 ms animation timer. +*/ + +Hello::Hello( const char *title, const char *text, QWidget *parentWidget ) + : KMdiChildView(title, parentWidget), t(text), b(0) +{ + QTimer *timer = new QTimer(this); + QObject::connect( timer, SIGNAL(timeout()), SLOT(animate()) ); + timer->start( 40 ); + + resize( 260, 130 ); +} + + +/* + This private slot is called each time the timer fires. +*/ + +void Hello::animate() +{ + b = (b + 1) & 15; + repaint( false ); +} + + +/* + Handles mouse button release events for the Hello widget. + + We emit the clicked() signal when the mouse is released inside + the widget. +*/ + +void Hello::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( rect().contains( e->pos() ) ) + emit clicked(); +} + + +/* + Handles paint events for the Hello widget. + + Flicker-free update. The text is first drawn in the pixmap and the + pixmap is then blt'ed to the screen. +*/ + +void Hello::paintEvent( QPaintEvent * ) +{ + static int sin_tbl[16] = { + 0, 38, 71, 92, 100, 92, 71, 38, 0, -38, -71, -92, -100, -92, -71, -38}; + + if ( t.isEmpty() ) + return; + + // 1: Compute some sizes, positions etc. + QFontMetrics fm = fontMetrics(); + int w = fm.width(t) + 20; + int h = fm.height() * 2; + int pmx = width()/2 - w/2; + int pmy = height()/2 - h/2; + + // 2: Create the pixmap and fill it with the widget's background + QPixmap pm( w, h ); + pm.fill( this, pmx, pmy ); + + // 3: Paint the pixmap. Cool wave effect + QPainter p; + int x = 10; + int y = h/2 + fm.descent(); + int i = 0; + p.begin( &pm ); + p.setFont( font() ); + while ( !t[i].isNull() ) { + int i16 = (b+i) & 15; + p.setPen( QColor((15-i16)*16,255,255,QColor::Hsv) ); + p.drawText( x, y-sin_tbl[i16]*h/800, t.mid(i,1), 1 ); + x += fm.width( t[i] ); + i++; + } + p.end(); + + // 4: Copy the pixmap to the Hello widget + bitBlt( this, pmx, pmy, &pm ); +} + +#include "hello.moc" + diff --git a/kmdi/test/hello.h b/kmdi/test/hello.h new file mode 100644 index 000000000..59c18f3f2 --- /dev/null +++ b/kmdi/test/hello.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** $Id$ +** +** Copyright (C) 1992-1999 Troll Tech AS. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#ifndef HELLO_H +#define HELLO_H + +#include <qstring.h> +#include <kmdichildview.h> + +class QWidget; +class QMouseEvent; +class QPaintEvent; + +class Hello : public KMdiChildView +{ + Q_OBJECT +public: + Hello( const char *title, const char *text, QWidget* parentWidget = 0 ); +signals: + void clicked(); +protected: + void mouseReleaseEvent( QMouseEvent * ); + void paintEvent( QPaintEvent * ); +private slots: + void animate(); +private: + QString t; + int b; +}; + +#endif diff --git a/kmdi/test/main.cpp b/kmdi/test/main.cpp new file mode 100644 index 000000000..95d9c2f83 --- /dev/null +++ b/kmdi/test/main.cpp @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------------- +// filename : main.cpp +//---------------------------------------------------------------------------- +// Project : Qt MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// stand-alone Qt extension set of +// classes and a Qt-based library +// 02/2000 by Massimo Morin (mmorin@schedsys.com) +// +// copyright : (C) 1999-2000 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +//---------------------------------------------------------------------------- + +#ifndef NO_KDE +# include <kapplication.h> + KApplication* theApp; +#else +# include <qapplication.h> + QApplication* theApp; +#endif + +//#include <iostream.h> +#include "mainwidget.h" +#include "hello.h" + +#define SHOW(v) cout << #v << " -> " << v << endl; + +int main( int argc, char **argv ) +{ +#ifndef NO_KDE + KApplication a(argc,argv,"KFourChildren"); +#else + QApplication a(argc,argv); +#endif + theApp = &a; + + RestartWidget* restartWidget = new RestartWidget; + MainWidget* mainWdg = new MainWidget(restartWidget->dockConfig,restartWidget->mdimode); + restartWidget->setWindow(mainWdg); + + Hello* h1 = new Hello( "Hello1", "Click the right mouse button on the mainframe!", mainWdg); + h1->setTabCaption("Tab changed"); + h1->setBackgroundColor( Qt::white ); + mainWdg->addWindow( h1); +// SHOW(h1->caption()); +// SHOW(h1->tabCaption()); + + QWidget* w = new QWidget(mainWdg); + KMdiChildView* h2 = mainWdg->createWrapper(w, "I'm a common but wrapped QWidget!", "Hello2"); + mainWdg->addWindow( h2 ); +// SHOW(h2->caption()); +// SHOW(h2->tabCaption()); + + Hello* h3 = new Hello( "Hello3", "Dock me using the taskbar button context menu!", 0); + h3->setBackgroundColor( Qt::white ); + h3->setFont( QFont("times",20,QFont::Bold) ); + mainWdg->addWindow( h3, KMdi::Detach ); // undock this! + h3->setGeometry( 20, 20, 400, 100); + + Hello* h4 = new Hello( "Hello4", "Hello world!", mainWdg); + h4->setMDICaption("Hello4 both changed"); + h4->setFont( QFont("times",32,QFont::Bold) ); + mainWdg->addWindow( h4); +// SHOW(h4->caption()); +// SHOW(h4->tabCaption()); + + Hello* h5 = new Hello( "Hello5", "I'm not a MDI widget :-("); + h5->setGeometry(40, 40, 400, 100); + h5->setFont( QFont("times",20,QFont::Bold) ); + h5->setCaption("MDI Test Application"); + h5->show(); + +#if 0 + KMdiIterator<KMdiChildView*> *it = mainWdg->createIterator(); + for ( it->first(); !it->isDone(); it->next()) { + //cout << "--> " << it->currentItem()->caption() << endl; + + } + //delete it; +#endif + + mainWdg->resize(500,500); + a.setMainWidget( restartWidget ); + restartWidget->show(); + mainWdg->show(); + + mainWdg->cascadeWindows(); + return a.exec(); +} diff --git a/kmdi/test/mainwidget.cpp b/kmdi/test/mainwidget.cpp new file mode 100644 index 000000000..872f9df27 --- /dev/null +++ b/kmdi/test/mainwidget.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + mainwidget.cpp - description + ------------------- + begin : Mon Nov 8 1999 + copyright : (C) 1999 by Falk Brettschneider + email : falkbr@kdevelop.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <qlayout.h> +#include <qmenubar.h> +#include <qtoolbar.h> +#include <qmultilineedit.h> +#include <qlistview.h> +#include <qfile.h> +#include <kmdimainfrm.h> +#include <kmditoolviewaccessor.h> + +#include "mainwidget.h" + +MainWidget::MainWidget(QDomElement& dockConfig,KMdi::MdiMode mode) +: KMdiMainFrm(0L, "theMDIMainFrm",mode) + ,m_dockConfig(dockConfig) +{ + setIDEAlModeStyle(1); // KDEV3 + + dockManager->setReadDockConfigMode(KDockManager::RestoreAllDockwidgets); + initMenu(); + + if (m_dockConfig.hasChildNodes()) { + readDockConfig(m_dockConfig); + } + + QMultiLineEdit* mle = new QMultiLineEdit(0L,"theMultiLineEditWidget"); + mle->setText("This is a QMultiLineEdit widget."); + addToolWindow( mle, KDockWidget::DockBottom, m_pMdi, 70); + + QMultiLineEdit* mle2 = new QMultiLineEdit(0L,"theMultiLineEditWidget2"); + addToolWindow( mle2, KDockWidget::DockCenter, mle, 70); + + QMultiLineEdit* mle3 = new QMultiLineEdit(0L,"theMultiLineEditWidget3"); + addToolWindow( mle3, KDockWidget::DockCenter, mle, 70); + + QMultiLineEdit* mle4 = new QMultiLineEdit(0L,"theMultiLineEditWidget4"); + addToolWindow( mle4, KDockWidget::DockCenter, mle, 70); + + KMdiToolViewAccessor *tva=createToolWindow(); + tva->setWidgetToWrap(new QMultiLineEdit(tva->wrapperWidget(),"theMultiLineEditWidget5")); + tva->placeAndShow(KDockWidget::DockCenter,mle,70); + + QListView* lv = new QListView(0L,"theListViewWidget"); +#include "../res/filenew.xpm" + lv->setIcon(filenew); + lv->addColumn("Test", 50); + lv->addColumn("KMDI", 70); + new QListViewItem(lv,QString("test"),QString("test")); + addToolWindow( lv, KDockWidget::DockLeft, m_pMdi, 35, "1"); + + QListView* lv2 = new QListView(0L,"theListViewWidget2"); + lv2->setIcon(filenew); + lv2->addColumn("Test2", 50); + lv2->addColumn("KMDI2", 70); + new QListViewItem(lv,QString("test2"),QString("test2")); + addToolWindow( lv2, KDockWidget::DockCenter, lv, 35, "2"); + + QListView* lv3 = new QListView(0L,"theListViewWidget3"); + lv3->setIcon(filenew); + lv3->addColumn("Test3", 50); + lv3->addColumn("KMDI3", 70); + new QListViewItem(lv,QString("test3"),QString("test3")); + addToolWindow( lv3, KDockWidget::DockCenter, lv, 35, "3"); + + dockManager->finishReadDockConfig(); + + setMenuForSDIModeSysButtons( menuBar()); +} + +MainWidget::~MainWidget() +{ + writeDockConfig(m_dockConfig); + QDomDocument doc = m_dockConfig.ownerDocument(); + QString s = doc.toString(); + QFile f("/tmp/dc.txt"); + f.open(IO_ReadWrite); + f.writeBlock(s.latin1(), s.length()); + f.close(); +} + +void MainWidget::initMenu() +{ + menuBar()->insertItem("&Window", windowMenu()); + menuBar()->insertItem("&Docking", dockHideShowMenu()); +} + +/** additionally fit the system menu button position to the menu position */ +void MainWidget::resizeEvent( QResizeEvent *pRSE) +{ + KMdiMainFrm::resizeEvent( pRSE); + setSysButtonsAtMenuPosition(); +} + +RestartWidget::RestartWidget():KMainWindow() +{ + mdimode=KMdi::ChildframeMode; + QVBoxLayout* bl = new QVBoxLayout(this); + QLabel* l = new QLabel("This is for the testing of\nKMdiMainFrm::read/writeDockConfig().\n", this); + QCheckBox* b1 = new QCheckBox("KMdiMainFrm close/restart", this); + b1->toggle(); + QObject::connect(b1, SIGNAL(stateChanged(int)), this, SLOT(onStateChanged(int))); + bl->add(l); + bl->add(b1); + bl->setMargin(10); + bl->activate(); + show(); + + dockConfig = domDoc.createElement("dockConfig"); + domDoc.appendChild(dockConfig); +} + +void RestartWidget::onStateChanged(int on) +{ + if (on) { + m_w = new MainWidget(dockConfig,mdimode); + m_w->resize(500,500); + m_w->show(); + } + else { + mdimode=m_w->mdiMode(); + m_w->close(); + delete m_w; + } + +} + +void RestartWidget::setWindow(MainWidget *w) { + m_w=w; +} + +#include "mainwidget.moc" diff --git a/kmdi/test/mainwidget.h b/kmdi/test/mainwidget.h new file mode 100644 index 000000000..d8f61c1cb --- /dev/null +++ b/kmdi/test/mainwidget.h @@ -0,0 +1,71 @@ +/*************************************************************************** + mainwidget.h - description + ------------------- + begin : Mon Nov 8 1999 + copyright : (C) 1999 by Falk Brettschneider + email : falkbr@kdevelop.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef MAINWIDGET_H +#define MAINWIDGET_H + +#include <qcheckbox.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qdom.h> +#include <kmdimainfrm.h> + +/** + *@author Falk Brettschneider + */ +class MainWidget : public KMdiMainFrm +{ + Q_OBJECT +public: + MainWidget(QDomElement& dockConfig,KMdi::MdiMode mode); + virtual ~MainWidget(); + void initMenu(); + +protected: // Protected methods + virtual void resizeEvent( QResizeEvent *pRSE); +private: + QDomElement m_dockConfig; +}; + + + +/** + *@author Falk Brettschneider + * This allows me to test KMdiMainFrm::read/writeDockConfig by + * closing and restarting the MainWidget via checkbox click. + */ +class RestartWidget : public KMainWindow +{ + Q_OBJECT +// methods +public: + RestartWidget(); + void setWindow(MainWidget *w); + +private slots: + void onStateChanged(int on); + +// attributes +public: + QDomDocument domDoc; + QDomElement dockConfig; + KMdi::MdiMode mdimode; +private: + MainWidget *m_w; +}; + +#endif |