You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kvirc/src/kvirc/ui/kvi_mdichild.cpp

577 lines
16 KiB

//=============================================================================
//
// File : kvi_mdichild.cpp
// Creation date : Wed Jun 21 2000 17:35:45 by Szymon Stefanek
//
// This file is part of the KVirc irc client distribution
// Copyright (C) 1999-2007 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__
#define _KVI_DEBUG_CHECK_RANGE_
#include "kvi_debug.h"
#include "kvi_mdichild.h"
#include "kvi_mdimanager.h"
#include "kvi_string.h"
#include "kvi_locale.h"
#include "kvi_options.h"
#include "kvi_settings.h"
#include "kvi_iconmanager.h"
#include "kvi_window.h"
#include "kvi_mdicaption.h"
#include <tqcursor.h>
#include <tqnamespace.h>
#include <tqapplication.h>
#include <tqfontmetrics.h>
#include "kvi_pointerlist.h"
#include <tqpixmap.h>
#include <tqstyle.h>
#include <tqpainter.h>
#include "kvi_tal_popupmenu.h"
#ifndef COMPILE_USE_QT4
#include <tqobjectlist.h>
#endif
#include <tqevent.h>
#ifdef Q_OS_MACX
#include "kvi_app.h" //Needed for g_pApp
#ifdef COMPILE_USE_QT4
#include <TQDesktopWidget>
#endif
#endif
#ifdef COMPILE_PSEUDO_TRANSPARENCY
extern TQPixmap * g_pShadedChildGlobalDesktopBackground;
#endif
#define KVI_MDI_NORESIZE 0
#define KVI_MDI_RESIZE_TOP 1
#define KVI_MDI_RESIZE_LEFT 2
#define KVI_MDI_RESIZE_RIGHT 4
#define KVI_MDI_RESIZE_BOTTOM 8
#define KVI_MDI_RESIZE_TOPLEFT (1|2)
#define KVI_MDI_RESIZE_TOPRIGHT (1|4)
#define KVI_MDI_RESIZE_BOTTOMLEFT (8|2)
#define KVI_MDI_RESIZE_BOTTOMRIGHT (8|4)
KviMdiChild::KviMdiChild(KviMdiManager * par,const char * name)
: TQFrame(par->viewport(),name ? name : "mdi_child")
{
setFrameStyle(TQFrame::StyledPanel | TQFrame::Raised);
setFrameShape(NoFrame);
m_pManager = par;
m_pCaption = new KviMdiCaption(this,"mdi_caption");
m_bResizeMode = false;
m_iResizeCorner = KVI_MDI_NORESIZE;
m_iLastCursorCorner = KVI_MDI_NORESIZE;
m_pClient = 0;
m_state = Normal;
m_restoredGeometry = TQRect(10,10,100,100);
setMouseTracking(true);
setMinimumSize(KVI_MDICHILD_MIN_WIDTH,KVI_MDICHILD_MIN_HEIGHT);
#ifdef COMPILE_USE_QT4
setAutoFillBackground(true);
#endif
}
KviMdiChild::~KviMdiChild()
{
if(m_pClient)delete m_pClient;
}
void KviMdiChild::reloadImages()
{
m_pCaption->reloadImages();
}
TQRect KviMdiChild::restoredGeometry()
{
if(m_state == Maximized)return m_restoredGeometry;
else return TQRect(x(),y(),width(),height());
// else return tqgeometry();
}
#ifdef COMPILE_USE_QT4
void KviMdiChild::setBackgroundRole(TQPalette::ColorRole)
{
// hack
TQFrame::setBackgroundRole(TQPalette::Window);
}
#else
void KviMdiChild::setBackgroundMode(TQWidget::BackgroundMode)
{
// hack
TQFrame::setBackgroundMode(TQWidget::PaletteBackground);
}
#endif
void KviMdiChild::setIcon(const TQPixmap &pix)
{
m_pCaption->setSystemIcon(pix);
if((m_state == Maximized) && (m_pManager->topChild() == this))
{
m_pManager->updateSDIMode();
}
}
const TQPixmap * KviMdiChild::icon()
{
return m_pCaption->systemIcon();
}
void KviMdiChild::enableClose(bool bEnable)
{
m_pCaption->enableClose(bEnable);
if((m_state == Maximized) && (m_pManager->topChild() == this))
{
m_pManager->updateSDIMode();
}
}
bool KviMdiChild::closeEnabled()
{
return m_pCaption->closeEnabled();
}
void KviMdiChild::setCaption(const TQString & plain,const TQString & xmlActive,const TQString & xmlInactive)
{
m_szPlainCaption = plain;
m_szXmlActiveCaption = xmlActive;
m_szXmlInactiveCaption = xmlInactive;
//m_pCaptionLabel->setActive(m_pCaptionLabel->active());
m_pCaption->update();
}
void KviMdiChild::maximize()
{
if(m_state == Minimized)restore(); // restore first
if(m_state == Normal)m_restoredGeometry = tqgeometry();
m_state = Maximized;
manager()->maximizeChild(this);
}
void KviMdiChild::restore()
{
if(m_restoredGeometry.x() < 0)m_restoredGeometry.setX(0);
if(m_restoredGeometry.y() < 0)m_restoredGeometry.setY(0);
// ensure coherency
if(m_restoredGeometry.width() < 5)m_restoredGeometry.setWidth(5);
if(m_restoredGeometry.height() < 5)m_restoredGeometry.setHeight(5);
/*
if((m_restoredGeometry.x() + m_restoredGeometry.width()) > m_pManager->width())
m_restoredGeometry.setWidth(m_pManager->width() - m_restoredGeometry.x());
if((m_restoredGeometry.y() + m_restoredGeometry.height()) > m_pManager->height())
m_restoredGeometry.setHeight(m_pManager->height() - m_restoredGeometry.y());
*/
switch(m_state)
{
case Maximized:
m_pManager->moveChild(this,m_restoredGeometry.x(),m_restoredGeometry.y());
resize(m_restoredGeometry.width(),m_restoredGeometry.height());
m_state = Normal;
m_pManager->childRestored(this,true);
break;
case Minimized:
m_pManager->moveChild(this,m_restoredGeometry.x(),m_restoredGeometry.y());
resize(m_restoredGeometry.width(),m_restoredGeometry.height());
show();
m_state = Normal;
m_pManager->childRestored(this,false);
break;
case Normal:
m_state = Normal;
if(!isVisible())show();
return;
break;
}
}
void KviMdiChild::minimize()
{
switch(m_state)
{
case Maximized:
hide();
m_state = Minimized;
m_pManager->childMinimized(this,true);
break;
case Normal:
m_restoredGeometry = tqgeometry();
hide();
m_state = Minimized;
m_pManager->childMinimized(this,false);
break;
case Minimized:
m_state = Minimized;
if(isVisible())hide();
return;
break;
}
}
void KviMdiChild::closeRequest()
{
if(closeEnabled())if(m_pClient)m_pClient->close();
}
/*
void KviMdiChild::systemPopupAboutToShow()
{
m_pSystemPopup->clear();
if(m_state != Maximized)m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXIMIZE)),__tr("&Maximize"),this,TQT_SLOT(maximize()));
if(m_state != Minimized)m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),__tr("M&inimize"),this,TQT_SLOT(minimize()));
if(m_state != Normal)m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),__tr("&Restore"),this,TQT_SLOT(restore()));
if(closeEnabled())
{
m_pSystemPopup->insertSeparator();
m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),__tr("&Close"),this,TQT_SLOT(closeRequest()));
}
}
*/
void KviMdiChild::moveEvent(TQMoveEvent *e)
{
#ifdef COMPILE_PSEUDO_TRANSPARENCY
if(m_pClient && g_pShadedChildGlobalDesktopBackground)
{
if(m_pClient->inherits("KviWindow")) // actually this is always the case
{
((KviWindow *)m_pClient)->updateBackgrounds();
}
}
#endif
TQFrame::moveEvent(e);
}
void KviMdiChild::systemPopupSlot()
{
if(sender()->inherits(TQTOOLBUTTON_OBJECT_NAME_STRING))
{
emit systemPopupRequest(((TQToolButton *)sender())->mapToGlobal(TQPoint(0,((TQToolButton *)sender())->height())));
} else {
emit systemPopupRequest(m_pCaption->mapToGlobal(TQPoint(5,5)));
}
}
void KviMdiChild::resizeEvent(TQResizeEvent *e)
{
int s = m_pCaption->heightHint();
m_pCaption->setGeometry(KVI_MDICHILD_BORDER,KVI_MDICHILD_BORDER,
width() - (KVI_MDICHILD_BORDER << 1),s);
if(m_pClient)
{
int yPos = KVI_MDICHILD_BORDER + s + KVI_MDICHILD_SPACING;
m_pClient->setGeometry(KVI_MDICHILD_BORDER,yPos,
width() - (KVI_MDICHILD_BORDER << 1),height() - (yPos + KVI_MDICHILD_BORDER));
}
TQFrame::resizeEvent(e);
}
void KviMdiChild::mousePressEvent(TQMouseEvent *e)
{
if(m_state == Maximized)return;
m_iResizeCorner=getResizeCorner(e->pos().x(),e->pos().y());
if(m_iResizeCorner != KVI_MDI_NORESIZE)
{
grabMouse(getResizeCursor(m_iResizeCorner));
m_bResizeMode = true;
}
}
void KviMdiChild::mouseReleaseEvent(TQMouseEvent *)
{
m_iResizeCorner=KVI_MDI_NORESIZE;
m_iLastCursorCorner=KVI_MDI_NORESIZE;
if(m_bResizeMode)
{
m_bResizeMode = false;
releaseMouse();
}
//if(TQApplication::overrideCursor())TQApplication::restoreOverrideCursor();
}
TQCursor KviMdiChild::getResizeCursor(int resizeCorner)
{
switch (resizeCorner)
{
case KVI_MDI_RESIZE_LEFT:
case KVI_MDI_RESIZE_RIGHT:
return TQt::sizeHorCursor;
break;
case KVI_MDI_RESIZE_TOP:
case KVI_MDI_RESIZE_BOTTOM:
return TQt::sizeVerCursor;
break;
case KVI_MDI_RESIZE_TOPLEFT:
case KVI_MDI_RESIZE_BOTTOMRIGHT:
return TQt::sizeFDiagCursor;
break;
case KVI_MDI_RESIZE_BOTTOMLEFT:
case KVI_MDI_RESIZE_TOPRIGHT:
return TQt::sizeBDiagCursor;
break;
default:
return TQt::arrowCursor;
break;
}
}
void KviMdiChild::mouseMoveEvent(TQMouseEvent *e)
{
if(e->state() & Qt::LeftButton)
{
if(m_iResizeCorner && (m_state != Maximized))resizeWindowOpaque(m_iResizeCorner);
} else {
setResizeCursor(getResizeCorner(e->pos().x(), e->pos().y()));
}
}
void KviMdiChild::setResizeCursor(int resizeCorner)
{
if(resizeCorner == m_iLastCursorCorner)
return; //Don't do it twice
m_iLastCursorCorner = resizeCorner;
if(resizeCorner == KVI_MDI_NORESIZE)
{
setCursor(getResizeCursor(resizeCorner));
//if(TQApplication::overrideCursor())TQApplication::restoreOverrideCursor();
} else {
if(m_state != Maximized)
{
setCursor(getResizeCursor(resizeCorner));
//TQApplication::setOverrideCursor(getResizeCursor(resizeCorner),true);
}
}
}
void KviMdiChild::leaveEvent(TQEvent *)
{
if(!m_bResizeMode)
{
m_iResizeCorner=KVI_MDI_NORESIZE;
m_iLastCursorCorner=KVI_MDI_NORESIZE;
//if(TQApplication::overrideCursor())TQApplication::restoreOverrideCursor();
} else {
if(m_iResizeCorner != KVI_MDI_NORESIZE)resizeWindowOpaque(m_iResizeCorner);
}
}
void KviMdiChild::calculateResizeRect(int resizeCorner,TQPoint mousePos,TQRect &resizeRect,int minWidth,int minHeight)
{
switch(resizeCorner)
{
case KVI_MDI_RESIZE_LEFT:
resizeRect.setLeft(mousePos.x() - 1);
if(resizeRect.width() < minWidth)resizeRect.setLeft(resizeRect.right() - minWidth);
if(resizeRect.x() < 0)resizeRect.setX(0);
break;
case KVI_MDI_RESIZE_RIGHT:
resizeRect.setRight(mousePos.x() + 1);
if(resizeRect.width() < minWidth)resizeRect.setRight(resizeRect.left() + minWidth);
break;
case KVI_MDI_RESIZE_TOP:
resizeRect.setTop(mousePos.y() - 1);
if(resizeRect.height() < minHeight)resizeRect.setTop(resizeRect.bottom() - minHeight);
if(resizeRect.y() < 0)resizeRect.setY(0);
break;
case KVI_MDI_RESIZE_BOTTOM:
resizeRect.setBottom(mousePos.y() + 1);
if(resizeRect.height() < minHeight)resizeRect.setBottom(resizeRect.top() + minHeight);
break;
case KVI_MDI_RESIZE_BOTTOMRIGHT:
resizeRect.setBottom(mousePos.y() + 1);
if(resizeRect.height() < minHeight)resizeRect.setBottom(resizeRect.top() + minHeight);
resizeRect.setRight(mousePos.x() + 1);
if(resizeRect.width() < minWidth)resizeRect.setRight(resizeRect.left() + minWidth);
break;
case KVI_MDI_RESIZE_TOPRIGHT:
resizeRect.setTop(mousePos.y() - 1);
if(resizeRect.height() < minHeight)resizeRect.setTop(resizeRect.bottom() - minHeight);
if(resizeRect.y() < 0)resizeRect.setY(0);
resizeRect.setRight(mousePos.x() + 1);
if(resizeRect.width() < minWidth)resizeRect.setRight(resizeRect.left() + minWidth);
break;
case KVI_MDI_RESIZE_BOTTOMLEFT:
resizeRect.setBottom(mousePos.y() + 1);
if(resizeRect.height() < minHeight)resizeRect.setBottom(resizeRect.top() + minHeight);
resizeRect.setLeft(mousePos.x() - 1);
if(resizeRect.width() < minWidth)resizeRect.setLeft(resizeRect.right() - minWidth);
if(resizeRect.x() < 0)resizeRect.setX(0);
break;
case KVI_MDI_RESIZE_TOPLEFT:
resizeRect.setTop(mousePos.y() - 1);
if(resizeRect.height() < minHeight)resizeRect.setTop(resizeRect.bottom() - minHeight);
if(resizeRect.y() < 0)resizeRect.setY(0);
resizeRect.setLeft(mousePos.x() - 1);
if(resizeRect.width() < minWidth)resizeRect.setLeft(resizeRect.right() - minWidth);
if(resizeRect.x() < 0)resizeRect.setX(0);
break;
}
}
void KviMdiChild::calculateMinimumSize(int &minWidth,int &minHeight)
{
if(m_pClient){
minWidth = m_pClient->minimumSize().width() + (KVI_MDICHILD_BORDER << 1);
minHeight = m_pClient->minimumSize().height()+ (KVI_MDICHILD_BORDER << 1)+
m_pCaption->heightHint() + KVI_MDICHILD_SPACING;
}
if(minWidth<KVI_MDICHILD_MIN_WIDTH)minWidth=KVI_MDICHILD_MIN_WIDTH;
if(minHeight<KVI_MDICHILD_MIN_HEIGHT)minHeight=KVI_MDICHILD_MIN_HEIGHT;
}
void KviMdiChild::resizeWindowOpaque(int resizeCorner)
{
int minWidth=0;
int minHeight=0;
TQRect resizeRect(m_pManager->childX(this),m_pManager->childY(this),width(),height());
calculateMinimumSize(minWidth,minHeight);
TQPoint mousePos = m_pManager->viewportToContents(m_pManager->viewport()->mapFromGlobal(TQCursor::pos()));
calculateResizeRect(resizeCorner,mousePos,resizeRect,minWidth,minHeight);
m_pManager->moveChild(this,resizeRect.x(),resizeRect.y());
resize(resizeRect.width(),resizeRect.height());
m_pManager->childMoved(this);
if(m_state == Maximized)
{
m_state=Normal;
m_pManager->childRestored(this,true);
}
}
int KviMdiChild::getResizeCorner(int ax,int ay)
{
int ret = KVI_MDI_NORESIZE;
if((ax>0)&&(ax<(KVI_MDICHILD_BORDER+2))) ret |= KVI_MDI_RESIZE_LEFT;
if((ax<width())&&(ax>(width()-(KVI_MDICHILD_BORDER+2)))) ret |= KVI_MDI_RESIZE_RIGHT;
if((ay>0)&&(ay<(KVI_MDICHILD_BORDER+2))) ret |= KVI_MDI_RESIZE_TOP;
if((ay<(height()))&&(ay>(height()-(KVI_MDICHILD_BORDER+2)))) ret |= KVI_MDI_RESIZE_BOTTOM;
return ret;
}
void KviMdiChild::setClient(TQWidget *w)
{
__range_valid(m_pClient==0);
__range_valid(w!=0);
m_pClient = w;
//resize to match the client
int clientYPos=m_pCaption->heightHint()+KVI_MDICHILD_SPACING+KVI_MDICHILD_BORDER;
resize(w->width()+(KVI_MDICHILD_BORDER << 1),w->height()+KVI_MDICHILD_BORDER+clientYPos);
//Reparent if needed
if(TQT_BASE_OBJECT(w->parent())!=TQT_BASE_OBJECT(this)){
//reparent to this widget , no flags , point , show it
TQPoint pnt2(KVI_MDICHILD_BORDER,clientYPos);
w->reparent(this,pnt2,true);
} else w->move(KVI_MDICHILD_BORDER,clientYPos);
setFocusProxy(w);
m_pCaption->setFocusProxy(w);
/*
m_pMinimizeButton->setFocusProxy(w);
m_pMaximizeButton->setFocusProxy(w);
m_pCloseButton->setFocusProxy(w);
m_pIconButton->setFocusProxy(w);
*/
//linkChildren(w);
if(m_pClient->minimumSize().width() > KVI_MDICHILD_MIN_WIDTH &&
m_pClient->minimumSize().height() > KVI_MDICHILD_MIN_HEIGHT){
setMinimumWidth(m_pClient->minimumSize().width() + (KVI_MDICHILD_BORDER << 1));
setMinimumHeight(m_pClient->minimumSize().height()+ (KVI_MDICHILD_BORDER << 1) +
m_pCaption->heightHint() + KVI_MDICHILD_SPACING);
}
KviStr tmp(KviStr::Format,"mdi_child_%s",w->name());
setName(tmp.ptr());
}
void KviMdiChild::unsetClient()
{
__range_valid(m_pClient!=0);
if(!m_pClient)return;
//reparent to desktop widget , no flags , point , show it
//unlinkChildren(m_pClient);
setFocusProxy(0); //remove the focus proxy...
//Kewl...the reparent function has a small prob now..
//the new toplelvel widgets gets not reenabled for dnd
#ifndef Q_OS_MACX
m_pClient->reparent(0,m_pClient->mapToGlobal(TQPoint(0,0)),true);
#else
TQRect r = g_pApp->desktop()->availableGeometry(m_pClient);
r.moveBy(0, 22);
m_pClient->reparent(0,r.topLeft(),true);
#endif
m_pClient=0;
setName("mdi_child");
}
void KviMdiChild::activate(bool bSetFocus)
{
if(!m_pCaption->active())m_pCaption->setActive(true);
if(m_pManager->topChild() != this)
m_pManager->setTopChild(this,bSetFocus);
else if(bSetFocus)setFocus();
}
void KviMdiChild::focusInEvent(TQFocusEvent *)
{
// We gained focus by click , tab or from the caption label
// Bring this child to top
m_pCaption->setActive(true);
m_pManager->setTopChild(this,false); //Do not focus by now...
/*The client is our focusProxy ! it should be focused by TQt !*/
#ifdef _KVI_DEBUG_CLASS_NAME_
__range_valid(focusProxy() == m_pClient);
#endif
}
TQSize KviMdiChild::sizeHint()
{
if(m_pClient)
{
TQSize s = m_pClient->sizeHint();
TQSize ret(s.width() + (KVI_MDICHILD_BORDER << 1),
s.height() + (KVI_MDICHILD_BORDER << 1) + KVI_MDICHILD_SPACING + m_pCaption->heightHint());
return ret;
}
return TQFrame::sizeHint();
}