00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "kmdichildarea.h"
00029 #include "kmdichildarea.moc"
00030
00031 #include "kmdidefines.h"
00032
00033 #include <kconfig.h>
00034 #include <kglobal.h>
00035
00036 #include <math.h>
00037 #include <qpopupmenu.h>
00038
00039
00041
00043
00044
00045
00046 KMdiChildArea::KMdiChildArea(QWidget *parent)
00047 :QFrame(parent, "kmdi_childarea")
00048 {
00049 setFrameStyle(QFrame::Panel|QFrame::Sunken);
00050 m_captionFont = QFont();
00051 QFontMetrics fm(m_captionFont);
00052 m_captionFontLineSpacing = fm.lineSpacing();
00053 KMdiChildArea::getCaptionColors( palette(), m_captionActiveBackColor, m_captionActiveForeColor,
00054 m_captionInactiveBackColor, m_captionInactiveForeColor );
00055
00056
00057
00058
00059 m_pZ = new QPtrList<KMdiChildFrm>;
00060 m_pZ->setAutoDelete(true);
00061 setFocusPolicy(ClickFocus);
00062 m_defaultChildFrmSize = QSize(400,300);
00063 }
00064
00065
00066
00067 KMdiChildArea::~KMdiChildArea()
00068 {
00069 delete m_pZ;
00070 }
00071
00072
00073
00074 void KMdiChildArea::manageChild(KMdiChildFrm *lpC,bool bShow,bool bCascade)
00075 {
00076 KMdiChildFrm * top=topChild();
00077 if (m_pZ->findRef(lpC)!=-1) {
00078 m_pZ->take();
00079 while (m_pZ->findNext(lpC)!=-1)
00080 m_pZ->take();
00081 }
00082
00083 if (bShow)
00084 m_pZ->append(lpC);
00085 else
00086 m_pZ->insert(0,lpC);
00087
00088 if(bCascade)lpC->move(getCascadePoint(m_pZ->count()-1));
00089 if(bShow){
00090 if(top){
00091 if(top->state() == KMdiChildFrm::Maximized){
00092 emit sysButtonConnectionsMustChange( top,lpC);
00093 top->setState(KMdiChildFrm::Normal,false);
00094 lpC->setState(KMdiChildFrm::Maximized,false);
00095 }
00096 }
00097 lpC->show();
00098 focusTopChild();
00099 }
00100 }
00101
00102
00103
00104 void KMdiChildArea::destroyChild(KMdiChildFrm *lpC,bool bFocusTopChild)
00105 {
00106 bool bWasMaximized = lpC->state() == KMdiChildFrm::Maximized;
00107
00108
00109 QObject::disconnect(lpC);
00110 lpC->blockSignals(true);
00111 m_pZ->setAutoDelete(false);
00112 m_pZ->removeRef(lpC);
00113
00114
00115 KMdiChildFrm* newTopChild = topChild();
00116 if (bWasMaximized){
00117 if (newTopChild) {
00118 newTopChild->setState(KMdiChildFrm::Maximized,false);
00119 emit sysButtonConnectionsMustChange(lpC, newTopChild);
00120 }
00121 else {
00122 emit noMaximizedChildFrmLeft(lpC);
00123 }
00124 }
00125 delete lpC;
00126 m_pZ->setAutoDelete(true);
00127
00128 if (bFocusTopChild)
00129 focusTopChild();
00130 }
00131
00132
00133
00134 void KMdiChildArea::destroyChildButNotItsView(KMdiChildFrm *lpC,bool bFocusTopChild)
00135 {
00136 bool bWasMaximized = lpC->state() == KMdiChildFrm::Maximized;
00137
00138
00139 QObject::disconnect(lpC);
00140 lpC->unsetClient();
00141 m_pZ->setAutoDelete(false);
00142 m_pZ->removeRef(lpC);
00143
00144
00145 KMdiChildFrm* newTopChild = topChild();
00146 if (bWasMaximized){
00147 if (newTopChild) {
00148 newTopChild->setState(KMdiChildFrm::Maximized,false);
00149 emit sysButtonConnectionsMustChange(lpC, newTopChild);
00150 }
00151 else {
00152 emit noMaximizedChildFrmLeft(lpC);
00153 }
00154 }
00155 delete lpC;
00156 m_pZ->setAutoDelete(true);
00157
00158 if (bFocusTopChild)
00159 focusTopChild();
00160 }
00161
00162
00163
00164 void KMdiChildArea::setTopChild(KMdiChildFrm *lpC,bool )
00165 {
00166 if(m_pZ->last() != lpC){
00167 m_pZ->setAutoDelete(false);
00168 if (lpC) {
00169 m_pZ->removeRef(lpC);
00170 }
00171
00172 for(KMdiChildFrm *pC=m_pZ->first();pC;pC=m_pZ->next()){
00173 pC->m_pCaption->setActive(false);
00174 }
00175 if (!lpC) {
00176 return;
00177 }
00178
00179 KMdiChildFrm *pMaximizedChild = m_pZ->last();
00180 if (pMaximizedChild && pMaximizedChild->m_state != KMdiChildFrm::Maximized) {
00181 pMaximizedChild = 0L;
00182 }
00183 m_pZ->setAutoDelete(true);
00184 m_pZ->append(lpC);
00185 int nChildAreaMinW = 0, nChildAreaMinH = 0;
00186 int nChildAreaMaxW = QWIDGETSIZE_MAX, nChildAreaMaxH = QWIDGETSIZE_MAX;
00187 if ( (pMaximizedChild != 0L) && (lpC->m_pClient != 0L) ) {
00188 nChildAreaMinW = lpC->m_pClient->minimumWidth();
00189 nChildAreaMinH = lpC->m_pClient->minimumHeight();
00191
00192
00193 }
00194 setMinimumSize(nChildAreaMinW, nChildAreaMinH);
00195 setMaximumSize(nChildAreaMaxW, nChildAreaMaxH);
00196 if (pMaximizedChild) {
00197 const bool bDontAnimate = false;
00198
00199 lpC->setState(KMdiChildFrm::Maximized, bDontAnimate);
00200 qApp->sendPostedEvents();
00201
00202 pMaximizedChild->setState(KMdiChildFrm::Normal, bDontAnimate);
00203 qApp->processOneEvent();
00204 emit sysButtonConnectionsMustChange( pMaximizedChild, lpC);
00205 }
00206 else {
00207 lpC->raise();
00208 }
00209 QFocusEvent::setReason(QFocusEvent::Other);
00210 lpC->m_pClient->setFocus();
00211 }
00212 }
00213
00214
00215
00216 void KMdiChildArea::resizeEvent(QResizeEvent* e)
00217 {
00218
00219 KMdiChildFrm *lpC=m_pZ->last();
00220 if(lpC){
00221 if(lpC->m_state == KMdiChildFrm::Maximized) {
00222 int clientw = 0, clienth = 0;
00223 if (lpC->m_pClient != 0L) {
00224 clientw = lpC->m_pClient->width();
00225 clienth = lpC->m_pClient->height();
00226 }
00227 lpC->resize( width() + KMDI_CHILDFRM_DOUBLE_BORDER,
00228 height() + lpC->m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER);
00229 }
00230 }
00231 layoutMinimizedChildren();
00232 QWidget::resizeEvent(e);
00233 }
00234
00235
00236
00237 void KMdiChildArea::mousePressEvent(QMouseEvent *e)
00238 {
00239
00240 if(e->button() & RightButton)
00241 emit popupWindowMenu( mapToGlobal( e->pos()));
00242 }
00243
00244
00245
00246 QPoint KMdiChildArea::getCascadePoint(int indexOfWindow)
00247 {
00248 if (indexOfWindow < 0) {
00249 indexOfWindow = m_pZ->count();
00250 }
00251 QPoint pnt(0,0);
00252 if(indexOfWindow==0)return pnt;
00253
00254 bool bTopLevelMode = false;
00255 if( height() == 1)
00256 bTopLevelMode = true;
00257
00258 KMdiChildFrm *lpC=m_pZ->first();
00259 int step=(lpC ? lpC->m_pCaption->heightHint()+KMDI_CHILDFRM_BORDER : 20);
00260 int h=(bTopLevelMode ? QApplication::desktop()->height() : height());
00261 int w=(bTopLevelMode ? QApplication::desktop()->width() : width());
00262
00263 int availableHeight=h-(lpC ? lpC->minimumSize().height() : m_defaultChildFrmSize.height());
00264 int availableWidth=w-(lpC ? lpC->minimumSize().width() : m_defaultChildFrmSize.width());
00265 int ax=0;
00266 int ay=0;
00267 for(int i=0;i<indexOfWindow;i++){
00268 ax+=step;
00269 ay+=step;
00270 if(ax>availableWidth)ax=0;
00271 if(ay>availableHeight)ay=0;
00272 }
00273 pnt.setX(ax);
00274 pnt.setY(ay);
00275 return pnt;
00276 }
00277
00278
00279
00280 void KMdiChildArea::childMinimized(KMdiChildFrm *lpC,bool bWasMaximized)
00281 {
00282 if(m_pZ->findRef(lpC) == -1)return;
00283 if(m_pZ->count() > 1){
00284 m_pZ->setAutoDelete(false);
00285 m_pZ->removeRef(lpC);
00286 m_pZ->setAutoDelete(true);
00287 m_pZ->insert(0,lpC);
00288 if(bWasMaximized){
00289
00290 lpC = m_pZ->last();
00291 if(!lpC)return;
00292 if(lpC->m_state==KMdiChildFrm::Minimized)return;
00293 lpC->setState(KMdiChildFrm::Maximized,false);
00294 }
00295 focusTopChild();
00296 } else {
00297 setFocus();
00298 }
00299 }
00300
00301
00302
00303 void KMdiChildArea::focusTopChild()
00304 {
00305 KMdiChildFrm *lpC=m_pZ->last();
00306 if(!lpC) {
00307 emit lastChildFrmClosed();
00308 return;
00309 }
00310
00311 for(KMdiChildFrm *pC=m_pZ->first();pC;pC=m_pZ->next()){
00312 if(pC != lpC)pC->m_pCaption->setActive(false);
00313 }
00314 lpC->raise();
00315 if (!lpC->m_pClient->hasFocus()) {
00316 lpC->m_pClient->activate();
00317 }
00318 }
00319
00320
00321
00322 void KMdiChildArea::cascadeWindows()
00323 {
00324 int idx=0;
00325 QPtrList<KMdiChildFrm> list(*m_pZ);
00326 list.setAutoDelete(false);
00327 while(!list.isEmpty()){
00328 KMdiChildFrm *lpC=list.first();
00329 if(lpC->m_state != KMdiChildFrm::Minimized){
00330 if(lpC->m_state==KMdiChildFrm::Maximized)lpC->restorePressed();
00331 lpC->move(getCascadePoint(idx));
00332 idx++;
00333 }
00334 list.removeFirst();
00335 }
00336 focusTopChild();
00337 }
00338
00339
00340
00341 void KMdiChildArea::cascadeMaximized()
00342 {
00343 int idx=0;
00344 QPtrList<KMdiChildFrm> list(*m_pZ);
00345
00346 list.setAutoDelete(false);
00347 while(!list.isEmpty()){
00348 KMdiChildFrm *lpC=list.first();
00349 if(lpC->m_state != KMdiChildFrm::Minimized){
00350 if(lpC->m_state==KMdiChildFrm::Maximized)lpC->restorePressed();
00351 QPoint pnt(getCascadePoint(idx));
00352 lpC->move(pnt);
00353 QSize curSize(width()-pnt.x(),height()-pnt.y());
00354 if((lpC->minimumSize().width() > curSize.width()) ||
00355 (lpC->minimumSize().height() > curSize.height()))lpC->resize(lpC->minimumSize());
00356 else lpC->resize(curSize);
00357 idx++;
00358 }
00359 list.removeFirst();
00360 }
00361 focusTopChild();
00362 }
00363
00364 void KMdiChildArea::expandVertical()
00365 {
00366 int idx=0;
00367 QPtrList<KMdiChildFrm> list(*m_pZ);
00368 list.setAutoDelete(false);
00369 while(!list.isEmpty()){
00370 KMdiChildFrm *lpC=list.first();
00371 if(lpC->m_state != KMdiChildFrm::Minimized){
00372 if(lpC->m_state==KMdiChildFrm::Maximized)lpC->restorePressed();
00373 lpC->setGeometry(lpC->x(),0,lpC->width(),height());
00374 idx++;
00375 }
00376 list.removeFirst();
00377 }
00378 focusTopChild();
00379 }
00380
00381 void KMdiChildArea::expandHorizontal()
00382 {
00383 int idx=0;
00384 QPtrList<KMdiChildFrm> list(*m_pZ);
00385 list.setAutoDelete(false);
00386 while(!list.isEmpty()){
00387 KMdiChildFrm *lpC=list.first();
00388 if(lpC->m_state != KMdiChildFrm::Minimized){
00389 if(lpC->m_state==KMdiChildFrm::Maximized)lpC->restorePressed();
00390 lpC->setGeometry(0,lpC->y(),width(),lpC->height());
00391 idx++;
00392 }
00393 list.removeFirst();
00394 }
00395 focusTopChild();
00396 }
00397
00398
00399
00400 int KMdiChildArea::getVisibleChildCount() const
00401 {
00402 int cnt=0;
00403 for(KMdiChildFrm *lpC=m_pZ->first();lpC;lpC=m_pZ->next()){
00404 if ((lpC->m_state != KMdiChildFrm::Minimized) &&
00405 (lpC->isVisible())) cnt++;
00406 }
00407 return cnt;
00408 }
00409
00410
00411
00412 void KMdiChildArea::tilePragma()
00413 {
00414 tileAllInternal(9);
00415 }
00416
00417
00418
00419 void KMdiChildArea::tileAllInternal(int maxWnds)
00420 {
00421
00422 static int colstable[9]={ 1,1,1,2,2,2,3,3,3 };
00423 static int rowstable[9]={ 1,2,3,2,3,3,3,3,3 };
00424 static int lastwindw[9]={ 1,1,1,1,2,1,3,2,1 };
00425 static int colrecall[9]={ 0,0,0,3,3,3,6,6,6 };
00426 static int rowrecall[9]={ 0,0,0,0,4,4,4,4,4 };
00427
00428 KMdiChildFrm *lpTop = topChild();
00429 int numVisible = getVisibleChildCount();
00430 if (numVisible<1) return;
00431 int numToHandle = ((numVisible > maxWnds) ? maxWnds : numVisible);
00432 int xQuantum = width()/colstable[numToHandle-1];
00433 if (xQuantum < ((lpTop->minimumSize().width() > m_defaultChildFrmSize.width()) ? lpTop->minimumSize().width() : m_defaultChildFrmSize.width())) {
00434 if (colrecall[numToHandle-1] != 0) {
00435 tileAllInternal(colrecall[numToHandle-1]);
00436 return;
00437 }
00438 }
00439 int yQuantum=height()/rowstable[numToHandle-1];
00440 if (yQuantum < ((lpTop->minimumSize().height() > m_defaultChildFrmSize.height()) ? lpTop->minimumSize().height() : m_defaultChildFrmSize.height())) {
00441 if (rowrecall[numToHandle-1] != 0) {
00442 tileAllInternal(rowrecall[numToHandle-1]);
00443 return;
00444 }
00445 }
00446 int curX=0;
00447 int curY=0;
00448 int curRow=1;
00449 int curCol=1;
00450 int curWin=1;
00451 for (KMdiChildFrm *lpC=m_pZ->first();lpC;lpC=m_pZ->next()) {
00452 if (lpC->m_state!=KMdiChildFrm::Minimized) {
00453
00454 if (lpC->m_state==KMdiChildFrm::Maximized)
00455 lpC->restorePressed();
00456 if ((curWin%numToHandle)==0)
00457 lpC->setGeometry(curX,curY,xQuantum * lastwindw[numToHandle-1],yQuantum);
00458 else
00459 lpC->setGeometry(curX,curY,xQuantum,yQuantum);
00460
00461 if (curCol<colstable[numToHandle-1]) {
00462 curX+=xQuantum;
00463 curCol++;
00464 }
00465 else {
00466 curX = 0;
00467 curCol = 1;
00468 if (curRow < rowstable[numToHandle-1]) {
00469 curY += yQuantum;
00470 curRow++;
00471 }
00472 else {
00473 curY = 0;
00474 curRow = 1;
00475 }
00476 }
00477 curWin++;
00478 }
00479 }
00480 if (lpTop)
00481 lpTop->m_pClient->activate();
00482 }
00483
00484 void KMdiChildArea::tileAnodine()
00485 {
00486 KMdiChildFrm *lpTop=topChild();
00487 int numVisible=getVisibleChildCount();
00488 if(numVisible<1)return;
00489 int numCols=int(sqrt((double)numVisible));
00490
00491 int *numRows=new int[numCols];
00492 int numCurCol=0;
00493 while(numCurCol<numCols){
00494 numRows[numCurCol]=numCols;
00495 numCurCol++;
00496 }
00497 int numDiff=numVisible-(numCols*numCols);
00498 int numCurDiffCol=numCols;
00499 while(numDiff>0){
00500 numCurDiffCol--;
00501 numRows[numCurDiffCol]++;
00502 if(numCurDiffCol<1)numCurDiffCol=numCols;
00503 numDiff--;
00504 }
00505 numCurCol=0;
00506 int numCurRow=0;
00507 int curX=0;
00508 int curY=0;
00509
00510
00511
00512 int xQuantum=width()/numCols;
00513 int yQuantum=height()/numRows[numCurCol];
00514 for(KMdiChildFrm *lpC=m_pZ->first();lpC;lpC=m_pZ->next()){
00515 if(lpC->m_state != KMdiChildFrm::Minimized){
00516 if(lpC->m_state==KMdiChildFrm::Maximized)lpC->restorePressed();
00517 lpC->setGeometry(curX,curY,xQuantum,yQuantum);
00518 numCurRow++;
00519 curY+=yQuantum;
00520 if(numCurRow==numRows[numCurCol]){
00521 numCurRow=0;
00522 numCurCol++;
00523 curY=0;
00524 curX+=xQuantum;
00525 if(numCurCol!=numCols)yQuantum=height()/numRows[numCurCol];
00526 }
00527 }
00528 }
00529 delete[] numRows;
00530 if (lpTop) {
00531 lpTop->m_pClient->activate();
00532 }
00533 }
00534
00535
00536 void KMdiChildArea::tileVertically()
00537 {
00538 KMdiChildFrm *lpTop=topChild();
00539 int numVisible=getVisibleChildCount();
00540 if(numVisible<1)return;
00541
00542 int w = width() / numVisible;
00543 int lastWidth = 0;
00544 if( numVisible > 1)
00545 lastWidth = width() - (w * (numVisible - 1));
00546 else
00547 lastWidth = w;
00548 int h = height();
00549 int posX = 0;
00550 int countVisible = 0;
00551
00552 for(KMdiChildFrm *lpC=m_pZ->first();lpC;lpC=m_pZ->next()){
00553 if(lpC->m_state != KMdiChildFrm::Minimized){
00554 if(lpC->m_state==KMdiChildFrm::Maximized)lpC->restorePressed();
00555 countVisible++;
00556 if( countVisible < numVisible) {
00557 lpC->setGeometry( posX, 0, w, h);
00558 posX += w;
00559 }
00560 else {
00561 lpC->setGeometry( posX, 0, lastWidth, h);
00562 }
00563 }
00564 }
00565 if (lpTop) {
00566 lpTop->m_pClient->activate();
00567 }
00568 }
00569
00570
00571 void KMdiChildArea::layoutMinimizedChildren()
00572 {
00573 int posX = 0;
00574 int posY = height();
00575 for(KMdiChildFrm* child = m_pZ->first(); child ; child = m_pZ->next())
00576 {
00577 if( child->state() == KMdiChildFrm::Minimized) {
00578 if( ( posX > 0) && ( posX + child->width() > width()) )
00579 {
00580 posX = 0;
00581 posY -= child->height();
00582 }
00583 child->move( posX, posY - child->height());
00584 posX = child->geometry().right();
00585 }
00586 }
00587 }
00588
00589
00590 void KMdiChildArea::setMdiCaptionFont(const QFont &fnt)
00591 {
00592 m_captionFont = fnt;
00593 QFontMetrics fm(m_captionFont);
00594 m_captionFontLineSpacing = fm.lineSpacing();
00595
00596 for (KMdiChildFrm *pC = m_pZ->first(); pC; pC = m_pZ->next()) {
00597 pC->doResize();
00598 }
00599 }
00600
00601 void KMdiChildArea::setMdiCaptionActiveForeColor(const QColor &clr)
00602 {
00603 m_captionActiveForeColor = clr;
00604 }
00605
00606 void KMdiChildArea::setMdiCaptionActiveBackColor(const QColor &clr)
00607 {
00608 m_captionActiveBackColor = clr;
00609 }
00610
00611 void KMdiChildArea::setMdiCaptionInactiveForeColor(const QColor &clr)
00612 {
00613 m_captionInactiveForeColor = clr;
00614 }
00615
00616 void KMdiChildArea::setMdiCaptionInactiveBackColor(const QColor &clr)
00617 {
00618 m_captionInactiveBackColor = clr;
00619 }
00620
00621
00622
00623
00624
00625
00626 #if defined(Q_WS_WIN)
00627 #include "qt_windows.h"
00628 QRgb qt_colorref2qrgb(COLORREF col)
00629 {
00630 return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
00631 }
00632
00633
00634 #ifndef SPI_GETGRADIENTCAPTIONS
00635 # define SPI_GETGRADIENTCAPTIONS 0x1008
00636 #endif
00637 #ifndef COLOR_GRADIENTACTIVECAPTION
00638 # define COLOR_GRADIENTACTIVECAPTION 27
00639 #endif
00640 #ifndef COLOR_GRADIENTINACTIVECAPTION
00641 # define COLOR_GRADIENTINACTIVECAPTION 28
00642 #endif
00643 #endif
00644
00645 void KMdiChildArea::getCaptionColors( const QPalette &pal,
00646 QColor &activeBG, QColor &activeFG, QColor &inactiveBG, QColor &inactiveFG )
00647 {
00648 QColor def_activeBG = pal.active().highlight();
00649 QColor def_activeFG = pal.active().highlightedText();
00650 QColor def_inactiveBG = pal.inactive().dark();
00651 QColor def_inactiveFG = pal.inactive().brightText();
00652
00653 if ( QApplication::desktopSettingsAware() ) {
00654 #if defined(Q_WS_WIN)
00655
00656 activeBG = qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION));
00657 activeFG = qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT));
00658 inactiveBG = qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION));
00659 inactiveFG = qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
00660 #else
00661
00662 KConfig *cfg = KGlobal::config();
00663 cfg->setGroup( "WM" );
00664 activeBG = cfg->readColorEntry("activeBackground", &def_activeBG);
00665 activeFG = cfg->readColorEntry("activeForeground", &def_activeFG);
00666 inactiveBG = cfg->readColorEntry("inactiveBackground", &def_inactiveBG);
00667 inactiveFG = cfg->readColorEntry("inactiveForeground", &def_inactiveFG);
00668 #endif
00669 }
00670 else {
00671 activeBG = def_activeBG;
00672 activeFG = def_activeFG;
00673 inactiveBG = def_inactiveBG;
00674 inactiveFG = def_inactiveFG;
00675 }
00676 }
00677
00678
00679