diff options
Diffstat (limited to 'kmdi/kmdimainfrm.cpp')
-rw-r--r-- | kmdi/kmdimainfrm.cpp | 2937 |
1 files changed, 2937 insertions, 0 deletions
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; |