diff options
Diffstat (limited to 'src/kvirc/ui/kvi_mdimanager.cpp')
-rw-r--r-- | src/kvirc/ui/kvi_mdimanager.cpp | 1126 |
1 files changed, 1126 insertions, 0 deletions
diff --git a/src/kvirc/ui/kvi_mdimanager.cpp b/src/kvirc/ui/kvi_mdimanager.cpp new file mode 100644 index 00000000..feddca11 --- /dev/null +++ b/src/kvirc/ui/kvi_mdimanager.cpp @@ -0,0 +1,1126 @@ +//============================================================================= +// +// File : kvi_mdimanager.cpp +// Creation date : Wed Jun 21 2000 17:28:04 by Szymon Stefanek +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 2000-2003 Szymon Stefanek (pragma at kvirc dot net) +// +// 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 opinion) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, write to the Free Software Foundation, +// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//============================================================================= + +#define __KVIRC__ + +#include "kvi_debug.h" +#include "kvi_settings.h" +#include "kvi_mdimanager.h" +#include "kvi_mdichild.h" +#include "kvi_locale.h" +#include "kvi_options.h" +#include "kvi_iconmanager.h" +#include "kvi_frame.h" +#include "kvi_menubar.h" +#include "kvi_mdicaption.h" +#include "kvi_app.h" + +#include "kvi_tal_popupmenu.h" +#include <qmenubar.h> +#include <qlayout.h> +#include <qpainter.h> +#include <math.h> +#include <qcursor.h> +#include <qdrawutil.h> +#include <qevent.h> + +#ifdef COMPILE_USE_QT4 + #include "kvi_tal_hbox.h" +#endif + +#ifdef COMPILE_PSEUDO_TRANSPARENCY + #include <qpixmap.h> + extern QPixmap * g_pShadedParentGlobalDesktopBackground; +#endif + + + + +KviMdiManager::KviMdiManager(QWidget * parent,KviFrame * pFrm,const char * name) +: KviTalScrollView(parent) +{ + setFrameShape(NoFrame); + m_pZ = new KviPointerList<KviMdiChild>; + m_pZ->setAutoDelete(true); + + m_pFrm = pFrm; + + m_iSdiIconItemId = 0; + m_iSdiCloseItemId = 0; + m_iSdiRestoreItemId = 0; + m_iSdiMinimizeItemId = 0; + m_pSdiIconButton = 0; + m_pSdiCloseButton = 0; + m_pSdiRestoreButton = 0; + m_pSdiMinimizeButton = 0; +#ifdef COMPILE_USE_QT4 + m_pSdiControls = 0; +#endif + + m_pWindowPopup = new KviTalPopupMenu(this); + connect(m_pWindowPopup,SIGNAL(activated(int)),this,SLOT(menuActivated(int))); + connect(m_pWindowPopup,SIGNAL(aboutToShow()),this,SLOT(fillWindowPopup())); + m_pTileMethodPopup = new KviTalPopupMenu(this); + connect(m_pTileMethodPopup,SIGNAL(activated(int)),this,SLOT(tileMethodMenuActivated(int))); + +#ifdef COMPILE_USE_QT4 + viewport()->setAutoFillBackground(false); +#else + viewport()->setBackgroundMode(QWidget::NoBackground); +#endif + setStaticBackground(true); + resizeContents(width(),height()); + +#ifdef COMPILE_USE_QT4 + setFocusPolicy(Qt::NoFocus); + viewport()->setFocusPolicy(Qt::NoFocus); +#else + setFocusPolicy(QWidget::NoFocus); + viewport()->setFocusPolicy(QWidget::NoFocus); +#endif + + connect(g_pApp,SIGNAL(reloadImages()),this,SLOT(reloadImages())); +} + +KviMdiManager::~KviMdiManager() +{ + delete m_pZ; +} + +void KviMdiManager::reloadImages() +{ + for(KviMdiChild * c = m_pZ->first();c;c = m_pZ->next()) + { + c->reloadImages(); + } +} + +bool KviMdiManager::focusNextPrevChild(bool bNext) +{ + //bug("FFFFFF"); + // this is a QScrollView bug... it doesn't pass this + // event to the toplevel window + return m_pFrm->focusNextPrevChild(bNext); +} + +void KviMdiManager::drawContents(QPainter *p,int x,int y,int w,int h) +{ + //debug("MY DRAW CONTENTS (%d,%d,%d,%d)",x,y,w,h); + QRect r(x,y,w,h); + +#ifdef COMPILE_PSEUDO_TRANSPARENCY + if(g_pShadedParentGlobalDesktopBackground) + { + QPoint pnt = viewport()->mapToGlobal(contentsToViewport(r.topLeft())); + p->drawTiledPixmap(r,*(g_pShadedParentGlobalDesktopBackground),pnt); + return; + } +#endif + + if(KVI_OPTION_PIXMAP(KviOption_pixmapMdiBackground).pixmap()) + { + p->drawTiledPixmap(r,*(KVI_OPTION_PIXMAP(KviOption_pixmapMdiBackground).pixmap())); + } else { + p->fillRect(r,KVI_OPTION_COLOR(KviOption_colorMdiBackground)); + } +} + +void KviMdiManager::manageChild(KviMdiChild * lpC,bool bCascade,QRect *setGeom) +{ + __range_valid(lpC); + + m_pZ->insert(0,lpC); //hidden -> last in the Z order + + if(bCascade) + { + QPoint p = getCascadePoint(m_pZ->count()-1); + addChild(lpC,p.x(),p.y()); + } else { + // FIXME: is this right ? + QPoint p = lpC->pos(); + if(p.x() < 0)p.setX(0); + if(p.y() < 0)p.setY(0); + addChild(lpC,p.x(),p.y()); + + if(setGeom) + { + if(setGeom->left() < 0)setGeom->setLeft(0); + if(setGeom->top() < 0)setGeom->setTop(0); + moveChild(lpC,setGeom->x(),setGeom->y()); + lpC->setGeometry(*setGeom); + } + } + + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); +} + +void KviMdiManager::showAndActivate(KviMdiChild * lpC) +{ + lpC->show(); + setTopChild(lpC,true); + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); +} + +void KviMdiManager::setTopChild(KviMdiChild *lpC,bool bSetFocus) +{ + __range_valid(lpC); + // The following check fails safely at startup.... + // __range_valid(lpC->isVisible() || lpC->testWState(WState_ForceHide)); + + KviMdiChild * pOldTop = m_pZ->last(); + if(pOldTop != lpC) + { + m_pZ->setAutoDelete(false); + + if(!m_pZ->removeRef(lpC)) + { + m_pZ->setAutoDelete(true); + return; // no such child ? + } + + // disable the labels of all the other children + //for(KviMdiChild *pC=m_pZ->first();pC;pC=m_pZ->next()) + //{ + // pC->captionLabel()->setActive(false); + //} + KviMdiChild * pMaximizedChild = pOldTop; + if(pOldTop) + { + pOldTop->captionLabel()->setActive(false); + if(pOldTop->m_state != KviMdiChild::Maximized)pMaximizedChild=0; + } + + m_pZ->setAutoDelete(true); + m_pZ->append(lpC); + + if(pMaximizedChild)lpC->maximize(); //do not animate the change + lpC->raise(); + if(pMaximizedChild)pMaximizedChild->restore(); + } + + if(bSetFocus) + { + if(!lpC->hasFocus()) + { + lpC->setFocus(); + /* + if(topLevelWidget()->isActiveWindow()) + { + + } + */ + } + } +} + +void KviMdiManager::focusInEvent(QFocusEvent *) +{ + focusTopChild(); +} + +void KviMdiManager::destroyChild(KviMdiChild *lpC,bool bFocusTopChild) +{ + bool bWasMaximized = lpC->state() == KviMdiChild::Maximized; + disconnect(lpC); + lpC->blockSignals(true); +#ifdef _KVI_DEBUG_CHECK_RANGE_ + //Report invalid results in a debug session + __range_valid(m_pZ->removeRef(lpC)); +#else + m_pZ->removeRef(lpC); +#endif + if(bWasMaximized) + { + KviMdiChild * c=topChild(); + if(c) + { + if(c->state() != KviMdiChild::Minimized)c->maximize(); + else { + // minimized top child...the last one + leaveSDIMode(); + } + } else { + // SDI state change + leaveSDIMode(); + } + } + if(bFocusTopChild)focusTopChild(); + + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); + updateContentsSize(); +} + +KviMdiChild * KviMdiManager::highestChildExcluding(KviMdiChild * pChild) +{ + KviMdiChild * c = m_pZ->last(); + while(c && (c == pChild))c = m_pZ->prev(); + return c; +} + +QPoint KviMdiManager::getCascadePoint(int indexOfWindow) +{ + QPoint pnt(0,0); + if(indexOfWindow==0)return pnt; + KviMdiChild *lpC=m_pZ->first(); + int step=(lpC ? (lpC->captionLabel()->heightHint()+KVI_MDICHILD_BORDER) : 20); + int availableHeight=viewport()->height()-(lpC ? lpC->minimumSize().height() : KVI_MDICHILD_MIN_HEIGHT); + int availableWidth=viewport()->width()-(lpC ? lpC->minimumSize().width() : KVI_MDICHILD_MIN_WIDTH); + int ax=0; + int ay=0; + for(int i=0;i<indexOfWindow;i++) + { + ax+=step; + ay+=step; + if(ax>availableWidth)ax=0; + if(ay>availableHeight)ay=0; + } + pnt.setX(ax); + pnt.setY(ay); + return pnt; +} + +void KviMdiManager::mousePressEvent(QMouseEvent *e) +{ + //Popup the window menu + if(e->button() & Qt::RightButton)m_pWindowPopup->popup(mapToGlobal(e->pos())); +} + +void KviMdiManager::childMoved(KviMdiChild *) +{ + updateContentsSize(); +} + +void KviMdiManager::maximizeChild(KviMdiChild * lpC) +{ + // the children must be moved once by the means of QScrollView::moveChild() + // so the QScrollView internal structures get updated with the negative + // position of the widget, otherwise, when restoring with moveChild() + // it will refuse to move it back to the original position + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + moveChild(lpC,-KVI_MDICHILD_HIDDEN_EDGE, + -(KVI_MDICHILD_HIDDEN_EDGE + KVI_MDICHILD_SPACING + lpC->m_pCaption->heightHint())); + + lpC->setGeometry( + -KVI_MDICHILD_HIDDEN_EDGE, + -(KVI_MDICHILD_HIDDEN_EDGE + KVI_MDICHILD_SPACING + lpC->m_pCaption->heightHint()), + viewport()->width() + (KVI_MDICHILD_HIDDEN_EDGE * 2), //KVI_MDICHILD_DOUBLE_HIDDEN_EDGE, + viewport()->height() + (KVI_MDICHILD_HIDDEN_EDGE * 2) + lpC->m_pCaption->heightHint() + KVI_MDICHILD_SPACING); + + if(isInSDIMode())updateSDIMode(); + else { + enterSDIMode(lpC); + // make sure that the child is focused + lpC->setFocus(); + } + + // fixme: we could hide all the other children now! +} + + + +void KviMdiManager::resizeEvent(QResizeEvent *e) +{ + //If we have a maximized children at the top , adjust its size + KviTalScrollView::resizeEvent(e); + KviMdiChild *lpC=m_pZ->last(); + if(lpC) + { + if(lpC->state()==KviMdiChild::Maximized) + { + // SDI mode + lpC->resize(viewport()->width() + (KVI_MDICHILD_HIDDEN_EDGE * 2), + viewport()->height() + lpC->m_pCaption->heightHint() + (KVI_MDICHILD_HIDDEN_EDGE * 2) + KVI_MDICHILD_SPACING); + return; + } else { + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); + } + } + updateContentsSize(); +} + + +/* +void KviMdiManager::childMaximized(KviMdiChild * lpC) +{ + if(lpC == m_pZ->last()) + { + enterSDIMode(lpC); + } + updateContentsSize(); +} +*/ + +void KviMdiManager::childMinimized(KviMdiChild * lpC,bool bWasMaximized) +{ + __range_valid(lpC); + if(m_pZ->findRef(lpC) == -1)return; + if(m_pZ->count() > 1) + { + m_pZ->setAutoDelete(false); +#ifdef _KVI_DEBUG_CHECK_RANGE_ + //Report invalid results in a debug session + __range_valid(m_pZ->removeRef(lpC)); +#else + m_pZ->removeRef(lpC); +#endif + m_pZ->setAutoDelete(true); + m_pZ->insert(0,lpC); + if(bWasMaximized) + { + // Need to maximize the top child + lpC = m_pZ->last(); + if(!lpC)return; //?? + if(lpC->state()==KviMdiChild::Minimized) + { + if(bWasMaximized)leaveSDIMode(); + return; + } + lpC->maximize(); //do nrot animate the change + } else { + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); + } + focusTopChild(); + } else { + // Unique window minimized...it won't loose the focus...!! + setFocus(); //Remove focus from the child + if(bWasMaximized)leaveSDIMode(); + } + updateContentsSize(); +} + +void KviMdiManager::childRestored(KviMdiChild * lpC,bool bWasMaximized) +{ + if(bWasMaximized) + { + if(lpC != m_pZ->last())return; // do nothing in this case + leaveSDIMode(); + updateContentsSize(); + } + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); +} + +void KviMdiManager::focusTopChild() +{ + KviMdiChild *lpC=m_pZ->last(); + if(!lpC)return; + if(!lpC->isVisible())return; + // if(lpC->state()==KviMdiChild::Minimized)return; + // debug("Focusing top child %s",lpC->name()); + //disable the labels of all the other children + for(KviMdiChild *pC=m_pZ->first();pC;pC=m_pZ->next()) + { + if(pC != lpC) + pC->captionLabel()->setActive(false); + } + lpC->raise(); + if(!lpC->hasFocus())lpC->setFocus(); +} + +void KviMdiManager::minimizeActiveChild() +{ + KviMdiChild * lpC = m_pZ->last(); + if(!lpC)return; + if(lpC->state() != KviMdiChild::Minimized)lpC->minimize(); +} + +void KviMdiManager::restoreActiveChild() +{ + KviMdiChild * lpC = m_pZ->last(); + if(!lpC)return; + if(lpC->state() == KviMdiChild::Maximized)lpC->restore(); +} + +void KviMdiManager::closeActiveChild() +{ + KviMdiChild * lpC = m_pZ->last(); + if(!lpC)return; + lpC->closeRequest(); +} + +void KviMdiManager::updateContentsSize() +{ + KviMdiChild * c = m_pZ->last(); + if(c) + { + if(c->state() == KviMdiChild::Maximized) + { + return; + } + } + + int fw = frameWidth() * 2; + int mx = width() - fw; + int my = height() - fw; + + for(c = m_pZ->first();c;c = m_pZ->next()) + { + if(c->isVisible()) + { + int x = childX(c) + c->width(); + if(x > mx)mx = x; + int y = childY(c) + c->height(); + if(y > my)my = y; + } + } + + resizeContents(mx,my); +} + + +void KviMdiManager::updateSDIMode() +{ + + KviMdiChild * lpC = m_pZ->last(); + + if(m_pSdiCloseButton) + m_pSdiCloseButton->setEnabled(lpC ? lpC->closeEnabled() : false); + +// This would result in an addictional main menu bar entry on MacOSX which would trigger a popup menu and not +// a submenu. Due to the optical reasons it is removed here. +// The same popup is triggered by right clicking on the window name in the channel window list. +#ifndef Q_OS_MACX + KviMenuBar * b = m_pFrm->mainMenuBar(); + + const QPixmap * pix = lpC ? lpC->icon() : 0; + if(!pix)pix = g_pIconManager->getSmallIcon(KVI_SMALLICON_NONE); + else if(pix->isNull())pix = g_pIconManager->getSmallIcon(KVI_SMALLICON_NONE); + + if(!m_pSdiIconButton) + { + m_pSdiIconButton = new KviMenuBarToolButton(b,*pix,"nonne"); + connect(m_pSdiIconButton,SIGNAL(clicked()),this,SLOT(activeChildSystemPopup())); +#ifdef COMPILE_USE_QT4 + // This is an obscure, undocumented and internal function in QT4 QMenuBar + // I won't be surprised if this disappears.... + b->setCornerWidget(m_pSdiIconButton,Qt::TopLeftCorner); + m_pSdiIconButton->show(); +#else + m_iSdiIconItemId = b->insertItem(m_pSdiIconButton,-1,0); +#endif + connect(m_pSdiIconButton,SIGNAL(destroyed()),this,SLOT(sdiIconButtonDestroyed())); + } else { + m_pSdiIconButton->setPixmap(*pix); + } +#endif //Q_OS_MACX +} + +void KviMdiManager::activeChildSystemPopup() +{ + KviMdiChild * lpC = m_pZ->last(); + if(!lpC)return; + QPoint pnt; + if(m_pSdiIconButton) + { + pnt = m_pSdiIconButton->mapToGlobal(QPoint(0,m_pSdiIconButton->height())); + } else { + pnt = QCursor::pos(); + } + lpC->emitSystemPopupRequest(pnt); +} + +bool KviMdiManager::isInSDIMode() +{ + return (m_pSdiCloseButton != 0); +} + + +void KviMdiManager::enterSDIMode(KviMdiChild *lpC) +{ + if(!m_pSdiCloseButton) + { + KviMenuBar * b = m_pFrm->mainMenuBar(); + + QWidget * pButtonParent; + +#ifdef COMPILE_USE_QT4 + m_pSdiControls = new KviTalHBox(b); + m_pSdiControls->setMargin(0); + m_pSdiControls->setSpacing(2); + m_pSdiControls->setAutoFillBackground(false); + pButtonParent = m_pSdiControls; +#else + pButtonParent = b; +#endif + m_pSdiMinimizeButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),"btnminimize"); + connect(m_pSdiMinimizeButton,SIGNAL(clicked()),this,SLOT(minimizeActiveChild())); +#ifndef COMPILE_USE_QT4 + m_iSdiMinimizeItemId = b->insertItem(m_pSdiMinimizeButton,-1,b->count()); +#endif + connect(m_pSdiMinimizeButton,SIGNAL(destroyed()),this,SLOT(sdiMinimizeButtonDestroyed())); + + m_pSdiRestoreButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),"btnrestore"); + connect(m_pSdiRestoreButton,SIGNAL(clicked()),this,SLOT(restoreActiveChild())); +#ifndef COMPILE_USE_QT4 + m_iSdiRestoreItemId = b->insertItem(m_pSdiRestoreButton,-1,b->count()); +#endif + connect(m_pSdiRestoreButton,SIGNAL(destroyed()),this,SLOT(sdiRestoreButtonDestroyed())); + + m_pSdiCloseButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),"btnclose"); + connect(m_pSdiCloseButton,SIGNAL(clicked()),this,SLOT(closeActiveChild())); +#ifndef COMPILE_USE_QT4 + m_iSdiCloseItemId = b->insertItem(m_pSdiCloseButton,-1,b->count()); +#endif + connect(m_pSdiCloseButton,SIGNAL(destroyed()),this,SLOT(sdiCloseButtonDestroyed())); + +#ifdef COMPILE_USE_QT4 + // This is an obscure, undocumented and internal function in QT4 QMenuBar + // I won't be surprised if this disappears.... + b->setCornerWidget(m_pSdiControls,Qt::TopRightCorner); + // The show below SHOULD force a re-layout of the menubar.. + // but it doesn't work when the KviFrame is still hidden (at startup) + // We handle this BUG in showEvent() + m_pSdiControls->show(); +#else + m_pSdiRestoreButton->show(); + m_pSdiMinimizeButton->show(); + m_pSdiCloseButton->show(); +#endif + emit enteredSdiMode(); + + setVScrollBarMode(KviTalScrollView::AlwaysOff); + setHScrollBarMode(KviTalScrollView::AlwaysOff); + } + + updateSDIMode(); +} +void KviMdiManager::relayoutMenuButtons() +{ +#ifdef COMPILE_USE_QT4 + // force a re-layout of the menubar in Qt4 (see the note in enterSDIMode()) + // by resetting the corner widget + if(m_pSdiControls) + { + m_pFrm->mainMenuBar()->setCornerWidget(0,Qt::TopRightCorner); + m_pFrm->mainMenuBar()->setCornerWidget(m_pSdiControls,Qt::TopRightCorner); + } + // also force an activation of the top MdiChild since it probably didn't get it yet + KviMdiChild * c = topChild(); + if(c) + c->activate(false); +#endif +} + + +void KviMdiManager::sdiIconButtonDestroyed() +{ + m_iSdiIconItemId = 0; + m_pSdiIconButton = 0; +} + +void KviMdiManager::sdiMinimizeButtonDestroyed() +{ + m_iSdiMinimizeItemId = 0; + m_pSdiMinimizeButton = 0; +} + +void KviMdiManager::sdiRestoreButtonDestroyed() +{ + m_iSdiRestoreItemId = 0; + m_pSdiRestoreButton = 0; +} + +void KviMdiManager::sdiCloseButtonDestroyed() +{ + m_iSdiCloseItemId = 0; + m_pSdiCloseButton = 0; +} + +void KviMdiManager::leaveSDIMode() +{ + __range_valid(m_pSdiCloseButton); + +#ifdef COMPILE_USE_QT4 + if(m_pSdiControls) + { + delete m_pSdiControls; + m_pSdiControls = 0; + } + if(m_pSdiIconButton) + { + m_pSdiIconButton->hide(); // this will force a QMenuBar relayout + delete m_pSdiIconButton; + m_pSdiIconButton = 0; + } +#else + if(m_iSdiIconItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiIconItemId); + if(m_iSdiCloseItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiCloseItemId); + if(m_iSdiRestoreItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiRestoreItemId); + if(m_iSdiMinimizeItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiMinimizeItemId); +#endif + + setVScrollBarMode(KviTalScrollView::Auto); + setHScrollBarMode(KviTalScrollView::Auto); + + emit leftSdiMode(); +} + +#define KVI_TILE_METHOD_ANODINE 0 +#define KVI_TILE_METHOD_PRAGMA4HOR 1 +#define KVI_TILE_METHOD_PRAGMA4VER 2 +#define KVI_TILE_METHOD_PRAGMA6HOR 3 +#define KVI_TILE_METHOD_PRAGMA6VER 4 +#define KVI_TILE_METHOD_PRAGMA9HOR 5 +#define KVI_TILE_METHOD_PRAGMA9VER 6 + +#define KVI_NUM_TILE_METHODS 7 + +void KviMdiManager::fillWindowPopup() +{ + m_pWindowPopup->clear(); + + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CASCADEWINDOWS)),(__tr2qs("&Cascade Windows")),this,SLOT(cascadeWindows())); + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CASCADEWINDOWS)),(__tr2qs("Cascade &Maximized")),this,SLOT(cascadeMaximized())); + + m_pWindowPopup->insertSeparator(); + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("&Tile Windows")),this,SLOT(tile())); + + m_pTileMethodPopup->clear(); + int id = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AUTOTILEWINDOWS)),(__tr2qs("&Auto Tile")),this,SLOT(toggleAutoTile())); + m_pTileMethodPopup->setItemChecked(id,KVI_OPTION_BOOL(KviOption_boolAutoTileWindows)); + m_pTileMethodPopup->setItemParameter(id,-1); + m_pTileMethodPopup->insertSeparator(); + int ids[KVI_NUM_TILE_METHODS]; + ids[KVI_TILE_METHOD_ANODINE] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Anodine's Full Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_ANODINE],KVI_TILE_METHOD_ANODINE); + ids[KVI_TILE_METHOD_PRAGMA4HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 4-Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA4HOR],KVI_TILE_METHOD_PRAGMA4HOR); + ids[KVI_TILE_METHOD_PRAGMA4VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 4-Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA4VER],KVI_TILE_METHOD_PRAGMA4VER); + ids[KVI_TILE_METHOD_PRAGMA6HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 6-Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA6HOR],KVI_TILE_METHOD_PRAGMA6HOR); + ids[KVI_TILE_METHOD_PRAGMA6VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 6-Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA6VER],KVI_TILE_METHOD_PRAGMA6VER); + ids[KVI_TILE_METHOD_PRAGMA9HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 9-Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA9HOR],KVI_TILE_METHOD_PRAGMA9HOR); + ids[KVI_TILE_METHOD_PRAGMA9VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 9-Grid"))); + m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA9VER],KVI_TILE_METHOD_PRAGMA9VER); + + if(KVI_OPTION_UINT(KviOption_uintTileMethod) >= KVI_NUM_TILE_METHODS)KVI_OPTION_UINT(KviOption_uintTileMethod) = KVI_TILE_METHOD_PRAGMA9HOR; + m_pTileMethodPopup->setItemChecked(ids[KVI_OPTION_UINT(KviOption_uintTileMethod)],true); + + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Tile Met&hod")),m_pTileMethodPopup); + + m_pWindowPopup->insertSeparator(); + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXVERTICAL)),(__tr2qs("Expand &Vertically")),this,SLOT(expandVertical())); + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXHORIZONTAL)),(__tr2qs("Expand &Horizontally")),this,SLOT(expandHorizontal())); + + m_pWindowPopup->insertSeparator(); + m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),(__tr2qs("Mi&nimize All")),this,SLOT(minimizeAll())); +// m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),(__tr2qs("&Restore all")),this,SLOT(restoreAll())); +// + m_pWindowPopup->insertSeparator(); + int i=100; + QString szItem; + QString szCaption; + for(KviMdiChild *lpC=m_pZ->first();lpC;lpC=m_pZ->next()) + { + szItem.setNum(((uint)i)-99); + szItem+=". "; + + szCaption = lpC->plainCaption(); + if(szCaption.length() > 30) + { + QString trail = szCaption.right(12); + szCaption.truncate(12); + szCaption+="..."; + szCaption+=trail; + } + + if(lpC->state()==KviMdiChild::Minimized) + { + szItem+="("; + szItem+=szCaption; + szItem+=")"; + } else szItem+=szCaption; + const QPixmap * pix = lpC->icon(); + if(pix && !(pix->isNull()))m_pWindowPopup->insertItem(*pix,szItem,i); + else m_pWindowPopup->insertItem(szItem,i); + m_pWindowPopup->setItemChecked(i,((uint)i)==(m_pZ->count()+99)); + i++; + } +} + +void KviMdiManager::menuActivated(int id) +{ + if(id<100)return; + id-=100; + __range_valid(((uint)id) < m_pZ->count()); + KviMdiChild *lpC=m_pZ->at(id); + if(!lpC)return; + if(lpC->state()==KviMdiChild::Minimized)lpC->restore(); + setTopChild(lpC,true); +} + +void KviMdiManager::ensureNoMaximized() +{ + KviMdiChild * lpC; + + for(lpC=m_pZ->first();lpC;lpC=m_pZ->next()) + { + if(lpC->state()==KviMdiChild::Maximized)lpC->restore(); + } +} + +void KviMdiManager::tileMethodMenuActivated(int id) +{ + int idx = m_pTileMethodPopup->itemParameter(id); + if(idx < 0)idx = 0; + if(idx >= KVI_NUM_TILE_METHODS)idx = KVI_TILE_METHOD_PRAGMA9VER; + KVI_OPTION_UINT(KviOption_uintTileMethod) = idx; + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile(); +} + +void KviMdiManager::cascadeWindows() +{ + ensureNoMaximized(); + // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + int idx=0; + KviPointerList<KviMdiChild> list(*m_pZ); + list.setAutoDelete(false); + while(!list.isEmpty()) + { + KviMdiChild *lpC=list.first(); + if(lpC->state() != KviMdiChild::Minimized) + { + QPoint p = getCascadePoint(idx); + moveChild(lpC,p.x(),p.y()); + lpC->resize(lpC->sizeHint()); + idx++; + } + list.removeFirst(); + } + focusTopChild(); + updateContentsSize(); +} + +void KviMdiManager::cascadeMaximized() +{ + ensureNoMaximized(); + // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + int idx=0; + KviPointerList<KviMdiChild> list(*m_pZ); + + list.setAutoDelete(false); + while(!list.isEmpty()) + { + KviMdiChild *lpC=list.first(); + if(lpC->state() != KviMdiChild::Minimized) + { + QPoint pnt(getCascadePoint(idx)); + moveChild(lpC,pnt.x(),pnt.y()); + QSize curSize(viewport()->width() - pnt.x(),viewport()->height() - pnt.y()); + if((lpC->minimumSize().width() > curSize.width()) || + (lpC->minimumSize().height() > curSize.height()))lpC->resize(lpC->minimumSize()); + else lpC->resize(curSize); + idx++; + } + list.removeFirst(); + } + focusTopChild(); + updateContentsSize(); +} + +void KviMdiManager::expandVertical() +{ + ensureNoMaximized(); + // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + KviPointerList<KviMdiChild> list(*m_pZ); + list.setAutoDelete(false); + while(!list.isEmpty()) + { + KviMdiChild *lpC=list.first(); + if(lpC->state() != KviMdiChild::Minimized) + { + moveChild(lpC,lpC->x(),0); + lpC->resize(lpC->width(),viewport()->height()); + } + list.removeFirst(); + } + + focusTopChild(); + updateContentsSize(); +} + +void KviMdiManager::expandHorizontal() +{ + ensureNoMaximized(); + // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + KviPointerList<KviMdiChild> list(*m_pZ); + list.setAutoDelete(false); + while(!list.isEmpty()) + { + KviMdiChild *lpC=list.first(); + if(lpC->state() != KviMdiChild::Minimized) + { + moveChild(lpC,0,lpC->y()); + lpC->resize(viewport()->width(),lpC->height()); + } + list.removeFirst(); + } + focusTopChild(); + updateContentsSize(); +} + +void KviMdiManager::minimizeAll() +{ + KviPointerList<KviMdiChild> list(*m_pZ); + list.setAutoDelete(false); + m_pFrm->setActiveWindow((KviWindow*)m_pFrm->firstConsole()); + while(!list.isEmpty()) + { + KviMdiChild *lpC=list.first(); + if(lpC->state() != KviMdiChild::Minimized)lpC->minimize(); + list.removeFirst(); + } + focusTopChild(); + updateContentsSize(); +} + +/* +void KviMdiManager::restoreAll() +{ + int idx=0; + KviPointerList<KviMdiChild> list(*m_pZ); + list.setAutoDelete(false); + while(!list.isEmpty()) + { + KviMdiChild *lpC=list.first(); + if(lpC->state() != KviMdiChild::Normal && (!(lpC->plainCaption()).contains("CONSOLE") )) + lpC->restore(); + list.removeFirst(); + } + focusTopChild(); + updateContentsSize(); +} +*/ + +int KviMdiManager::getVisibleChildCount() +{ + int cnt=0; + for(KviMdiChild *lpC=m_pZ->first();lpC;lpC=m_pZ->next()) + { + if(lpC->state() != KviMdiChild::Minimized)cnt++; + } + return cnt; +} + +void KviMdiManager::tile() +{ + switch(KVI_OPTION_UINT(KviOption_uintTileMethod)) + { + case KVI_TILE_METHOD_ANODINE: tileAnodine(); break; + case KVI_TILE_METHOD_PRAGMA4HOR: tileAllInternal(4,true); break; + case KVI_TILE_METHOD_PRAGMA4VER: tileAllInternal(4,false); break; + case KVI_TILE_METHOD_PRAGMA6HOR: tileAllInternal(6,true); break; + case KVI_TILE_METHOD_PRAGMA6VER: tileAllInternal(6,false); break; + case KVI_TILE_METHOD_PRAGMA9HOR: tileAllInternal(9,true); break; + case KVI_TILE_METHOD_PRAGMA9VER: tileAllInternal(9,false); break; + default: + KVI_OPTION_UINT(KviOption_uintTileMethod) = KVI_TILE_METHOD_PRAGMA9HOR; + tileAllInternal(9,true); + break; + } +} + +void KviMdiManager::toggleAutoTile() +{ + if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows)) + { + KVI_OPTION_BOOL(KviOption_boolAutoTileWindows) = false; + } else { + KVI_OPTION_BOOL(KviOption_boolAutoTileWindows) = true; + tile(); + } +} + + +void KviMdiManager::tileAllInternal(int maxWnds,bool bHorizontal) +{ + //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 * pColstable = bHorizontal ? colstable : rowstable; + int * pRowstable = bHorizontal ? rowstable : colstable; + int * pColrecall = bHorizontal ? colrecall : rowrecall; + int * pRowrecall = bHorizontal ? rowrecall : colrecall; + + ensureNoMaximized(); + // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + KviMdiChild *lpTop=topChild(); + int numVisible=getVisibleChildCount(); + + if(numVisible<1)return; + + int numToHandle=((numVisible > maxWnds) ? maxWnds : numVisible); + int xQuantum=viewport()->width()/pColstable[numToHandle-1]; + if(xQuantum < ((lpTop->minimumSize().width() > KVI_MDICHILD_MIN_WIDTH) ? lpTop->minimumSize().width() : KVI_MDICHILD_MIN_WIDTH)){ + if(pColrecall[numToHandle-1]==0)debug("Tile : Not enouh space"); + else tileAllInternal(pColrecall[numToHandle-1],bHorizontal); + return; + } + int yQuantum=viewport()->height()/pRowstable[numToHandle-1]; + if(yQuantum < ((lpTop->minimumSize().height() > KVI_MDICHILD_MIN_HEIGHT) ? lpTop->minimumSize().height() : KVI_MDICHILD_MIN_HEIGHT)){ + if(pRowrecall[numToHandle-1]==0)debug("Tile : Not enough space"); + else tileAllInternal(pRowrecall[numToHandle-1],bHorizontal); + return; + } + int curX=0; + int curY=0; + int curRow=1; + int curCol=1; + int curWin=1; + + for(KviMdiChild * lpC=m_pZ->first();lpC;lpC=m_pZ->next()) + { + if(lpC->state()!=KviMdiChild::Minimized) + { + if((curWin%numToHandle)==0) + { + moveChild(lpC,curX,curY); + lpC->resize(xQuantum * lastwindw[numToHandle-1],yQuantum); + } else { + moveChild(lpC,curX,curY); + lpC->resize(xQuantum,yQuantum); + } + //example : 12 windows : 3 cols 3 rows + if(curCol<pColstable[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<pRowstable[numToHandle-1]) + { //curRow<3 + curY+=yQuantum; //add a row + curRow++; // + } else { + curY=0; //restart from beginning + curRow=1; // + } + } + curWin++; + } + } + if(lpTop)lpTop->setFocus(); + updateContentsSize(); +} + +void KviMdiManager::tileAnodine() +{ + ensureNoMaximized(); + // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct + resizeContents(visibleWidth(),visibleHeight()); + updateScrollBars(); + g_pApp->sendPostedEvents(); + if(g_pApp->closingDown())return; + + KviMdiChild *lpTop=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=viewport()->width()/numCols; + int yQuantum=viewport()->height()/numRows[numCurCol]; + + for(KviMdiChild * lpC=m_pZ->first();lpC;lpC=m_pZ->next()) + { + if(lpC->state() != KviMdiChild::Minimized) + { + moveChild(lpC,curX,curY); + lpC->resize(xQuantum,yQuantum); + numCurRow++; + curY+=yQuantum; + if(numCurRow==numRows[numCurCol]) + { + numCurRow=0; + numCurCol++; + curY=0; + curX+=xQuantum; + if(numCurCol!=numCols)yQuantum=viewport()->height()/numRows[numCurCol]; + } + } + } + delete[] numRows; + if(lpTop)lpTop->setFocus(); + updateContentsSize(); +} + + |