src/gui/widgets/qworkspace.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qworkspace.h"
00025 #ifndef QT_NO_WORKSPACE
00026 #include "qapplication.h"
00027 #include "qbitmap.h"
00028 #include "qcursor.h"
00029 #include "qdatetime.h"
00030 #include "qdesktopwidget.h"
00031 #include "qevent.h"
00032 #include "qhash.h"
00033 #include "qicon.h"
00034 #include "qimage.h"
00035 #include "qlabel.h"
00036 #include "qlayout.h"
00037 #include "qmenubar.h"
00038 #include "qmenu.h"
00039 #include "qpainter.h"
00040 #include "qpointer.h"
00041 #include "qscrollbar.h"
00042 #include "qstyle.h"
00043 #include "qstyleoption.h"
00044 #include "qtoolbutton.h"
00045 #include "qtooltip.h"
00046 #include "qdebug.h"
00047 #include <private/qwidget_p.h>
00048 #include <private/qwidgetresizehandler_p.h>
00049 #include <private/qlayoutengine_p.h>
00050 
00051 class QWorkspaceTitleBarPrivate;
00052 class QWorkspaceTitleBar : public QWidget
00053 {
00054     Q_OBJECT
00055     Q_DECLARE_PRIVATE(QWorkspaceTitleBar)
00056     Q_PROPERTY(bool autoRaise READ autoRaise WRITE setAutoRaise)
00057     Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
00058 
00059 public:
00060     QWorkspaceTitleBar (QWidget *w, QWidget *parent, Qt::WindowFlags f = 0);
00061     ~QWorkspaceTitleBar();
00062 
00063     bool isActive() const;
00064     bool usesActiveColor() const;
00065 
00066     bool isMovable() const;
00067     void setMovable(bool);
00068 
00069     bool autoRaise() const;
00070     void setAutoRaise(bool);
00071 
00072     QWidget *window() const;
00073     bool isTool() const;
00074 
00075     QSize sizeHint() const;
00076     QStyleOptionTitleBar getStyleOption() const;
00077 
00078 public slots:
00079     void setActive(bool);
00080 
00081 signals:
00082     void doActivate();
00083     void doNormal();
00084     void doClose();
00085     void doMaximize();
00086     void doMinimize();
00087     void doShade();
00088     void showOperationMenu();
00089     void popupOperationMenu(const QPoint&);
00090     void doubleClicked();
00091 
00092 protected:
00093     bool event(QEvent *);
00094     void contextMenuEvent(QContextMenuEvent *);
00095     void mousePressEvent(QMouseEvent *);
00096     void mouseDoubleClickEvent(QMouseEvent *);
00097     void mouseReleaseEvent(QMouseEvent *);
00098     void mouseMoveEvent(QMouseEvent *);
00099     void enterEvent(QEvent *e);
00100     void leaveEvent(QEvent *e);
00101     void paintEvent(QPaintEvent *p);
00102 
00103 private:
00104     Q_DISABLE_COPY(QWorkspaceTitleBar)
00105 };
00106 
00107 
00108 class QWorkspaceTitleBarPrivate : public QWidgetPrivate
00109 {
00110     Q_DECLARE_PUBLIC(QWorkspaceTitleBar)
00111 public:
00112     QWorkspaceTitleBarPrivate()
00113         :
00114         lastControl(QStyle::SC_None),
00115 #ifndef QT_NO_TOOLTIP
00116         toolTip(0),
00117 #endif
00118         act(0), window(0), movable(1), pressed(0), autoraise(0), moving(0)
00119     {
00120     }
00121 
00122     Qt::WindowFlags flags;
00123     QStyle::SubControl buttonDown;
00124     QStyle::SubControl lastControl;
00125     QPoint moveOffset;
00126 #ifndef QT_NO_TOOLTIP
00127     QToolTip *toolTip;
00128 #endif
00129     bool act                    :1;
00130     QPointer<QWidget> window;
00131     bool movable            :1;
00132     bool pressed            :1;
00133     bool autoraise          :1;
00134     bool moving : 1;
00135 
00136     int titleBarState() const;
00137     QStyleOptionTitleBar getStyleOption() const;
00138     void readColors();
00139 };
00140 
00141 inline int QWorkspaceTitleBarPrivate::titleBarState() const
00142 {
00143     Q_Q(const QWorkspaceTitleBar);
00144     uint state = window ? window->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState);
00145     state |= uint((act && q->isActiveWindow()) ? QStyle::State_Active : QStyle::State_None);
00146     return (int)state;
00147 }
00148 
00149 QStyleOptionTitleBar QWorkspaceTitleBarPrivate::getStyleOption() const
00150 {
00151     Q_Q(const QWorkspaceTitleBar);
00152     QStyleOptionTitleBar opt;
00153     opt.init(q);
00154     //################
00155     if (window && (flags & Qt::WindowTitleHint)) {
00156         opt.text = window->windowTitle();
00157         QIcon icon = window->windowIcon();
00158         QSize s = icon.actualSize(QSize(64, 64));
00159         opt.icon = icon.pixmap(s);
00160     }
00161     opt.subControls = QStyle::SC_All;
00162     opt.activeSubControls = QStyle::SC_None;
00163     opt.titleBarState = titleBarState();
00164     opt.titleBarFlags = flags;
00165     opt.state &= ~QStyle::State_MouseOver;
00166     return opt;
00167 }
00168 
00169 QWorkspaceTitleBar::QWorkspaceTitleBar(QWidget *w, QWidget *parent, Qt::WindowFlags f)
00170     : QWidget(*new QWorkspaceTitleBarPrivate, parent, Qt::FramelessWindowHint)
00171 {
00172     Q_D(QWorkspaceTitleBar);
00173     if (f == 0 && w)
00174         f = w->windowFlags();
00175     d->flags = f;
00176     d->window = w;
00177     d->buttonDown = QStyle::SC_None;
00178     d->act = 0;
00179     if (w) {
00180         if (w->maximumSize() != QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX))
00181             d->flags &= ~Qt::WindowMaximizeButtonHint;
00182         setWindowTitle(w->windowTitle());
00183     }
00184 
00185     d->readColors();
00186     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
00187     setMouseTracking(true);
00188     setAutoRaise(style()->styleHint(QStyle::SH_TitleBar_AutoRaise, 0, this));
00189 }
00190 
00191 QWorkspaceTitleBar::~QWorkspaceTitleBar()
00192 {
00193 }
00194 
00195 QStyleOptionTitleBar QWorkspaceTitleBar::getStyleOption() const
00196 {
00197     return d_func()->getStyleOption();
00198 }
00199 
00200 #ifdef Q_WS_WIN
00201 static inline QRgb colorref2qrgb(COLORREF col)
00202 {
00203     return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
00204 }
00205 #endif
00206 
00207 void QWorkspaceTitleBarPrivate::readColors()
00208 {
00209     Q_Q(QWorkspaceTitleBar);
00210     QPalette pal = q->palette();
00211 
00212     bool colorsInitialized = false;
00213 
00214 #ifdef Q_WS_WIN // ask system properties on windows
00215 #ifndef SPI_GETGRADIENTCAPTIONS
00216 #define SPI_GETGRADIENTCAPTIONS 0x1008
00217 #endif
00218 #ifndef COLOR_GRADIENTACTIVECAPTION
00219 #define COLOR_GRADIENTACTIVECAPTION 27
00220 #endif
00221 #ifndef COLOR_GRADIENTINACTIVECAPTION
00222 #define COLOR_GRADIENTINACTIVECAPTION 28
00223 #endif
00224     if (QApplication::desktopSettingsAware()) {
00225         pal.setColor(QPalette::Active, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)));
00226         pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)));
00227         pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
00228         pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
00229         if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
00230             colorsInitialized = true;
00231             BOOL gradient;
00232             QT_WA({
00233                 SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
00234             } , {
00235                 SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
00236             });
00237             if (gradient) {
00238                 pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
00239                 pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
00240             } else {
00241                 pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight));
00242                 pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight));
00243             }
00244         }
00245     }
00246 #endif // Q_WS_WIN
00247     if (!colorsInitialized) {
00248         pal.setColor(QPalette::Active, QPalette::Highlight,
00249                       pal.color(QPalette::Active, QPalette::Highlight));
00250         pal.setColor(QPalette::Active, QPalette::Base,
00251                       pal.color(QPalette::Active, QPalette::Highlight));
00252         pal.setColor(QPalette::Inactive, QPalette::Highlight,
00253                       pal.color(QPalette::Inactive, QPalette::Dark));
00254         pal.setColor(QPalette::Inactive, QPalette::Base,
00255                       pal.color(QPalette::Inactive, QPalette::Dark));
00256         pal.setColor(QPalette::Inactive, QPalette::HighlightedText,
00257                       pal.color(QPalette::Inactive, QPalette::Window));
00258     }
00259 
00260     q->setPalette(pal);
00261     q->setActive(act);
00262 }
00263 
00264 void QWorkspaceTitleBar::mousePressEvent(QMouseEvent *e)
00265 {
00266     Q_D(QWorkspaceTitleBar);
00267     if (!d->act)
00268         emit doActivate();
00269     if (e->button() == Qt::LeftButton) {
00270         if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
00271             && !rect().adjusted(5, 5, -5, 0).contains(e->pos())) {
00272             // propagate border events to the QWidgetResizeHandler
00273             e->ignore();
00274             return;
00275         }
00276 
00277         d->pressed = true;
00278         QStyleOptionTitleBar opt = d->getStyleOption();
00279         QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
00280                                                                  e->pos(), this);
00281         switch (ctrl) {
00282         case QStyle::SC_TitleBarSysMenu:
00283             if (d->flags & Qt::WindowSystemMenuHint) {
00284                 d->buttonDown = QStyle::SC_None;
00285                 static QTime *t = 0;
00286                 static QWorkspaceTitleBar *tc = 0;
00287                 if (!t)
00288                     t = new QTime;
00289                 if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
00290                     emit showOperationMenu();
00291                     t->start();
00292                     tc = this;
00293                 } else {
00294                     tc = 0;
00295                     emit doClose();
00296                     return;
00297                 }
00298             }
00299             break;
00300 
00301         case QStyle::SC_TitleBarShadeButton:
00302         case QStyle::SC_TitleBarUnshadeButton:
00303             if (d->flags & Qt::WindowShadeButtonHint)
00304                 d->buttonDown = ctrl;
00305             break;
00306 
00307         case QStyle::SC_TitleBarNormalButton:
00308                 d->buttonDown = ctrl;
00309             break;
00310 
00311         case QStyle::SC_TitleBarMinButton:
00312             if (d->flags & Qt::WindowMinimizeButtonHint)
00313                 d->buttonDown = ctrl;
00314             break;
00315 
00316         case QStyle::SC_TitleBarMaxButton:
00317             if (d->flags & Qt::WindowMaximizeButtonHint)
00318                 d->buttonDown = ctrl;
00319             break;
00320 
00321         case QStyle::SC_TitleBarCloseButton:
00322             if (d->flags & Qt::WindowSystemMenuHint)
00323                 d->buttonDown = ctrl;
00324             break;
00325 
00326         case QStyle::SC_TitleBarLabel:
00327             d->buttonDown = ctrl;
00328             d->moveOffset = mapToParent(e->pos());
00329             break;
00330 
00331         default:
00332             break;
00333         }
00334         update();
00335     } else {
00336         d->pressed = false;
00337     }
00338 }
00339 
00340 void QWorkspaceTitleBar::contextMenuEvent(QContextMenuEvent *e)
00341 {
00342     QStyleOptionTitleBar opt = d_func()->getStyleOption();
00343     QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(),
00344                                                              this);
00345     if(ctrl == QStyle::SC_TitleBarLabel || ctrl == QStyle::SC_TitleBarSysMenu) {
00346         e->accept();
00347         emit popupOperationMenu(e->globalPos());
00348     } else {
00349         e->ignore();
00350     }
00351 }
00352 
00353 void QWorkspaceTitleBar::mouseReleaseEvent(QMouseEvent *e)
00354 {
00355     Q_D(QWorkspaceTitleBar);
00356     if (!d->window) {
00357         // could have been deleted as part of a double click event on the sysmenu
00358         return;
00359     }
00360     if (e->button() == Qt::LeftButton && d->pressed) {
00361         if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
00362             && !rect().adjusted(5, 5, -5, 0).contains(e->pos())) {
00363             // propagate border events to the QWidgetResizeHandler
00364             e->ignore();
00365             d->buttonDown = QStyle::SC_None;
00366             d->pressed = false;
00367             return;
00368         }
00369         e->accept();
00370         QStyleOptionTitleBar opt = d->getStyleOption();
00371         QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
00372                                                                  e->pos(), this);
00373 
00374         if (d->pressed) {
00375             update();
00376             d->pressed = false;
00377             d->moving = false;
00378         }
00379         if (ctrl == d->buttonDown) {
00380             d->buttonDown = QStyle::SC_None;
00381             switch(ctrl) {
00382             case QStyle::SC_TitleBarShadeButton:
00383             case QStyle::SC_TitleBarUnshadeButton:
00384                 if(d->flags & Qt::WindowShadeButtonHint)
00385                     emit doShade();
00386                 break;
00387 
00388             case QStyle::SC_TitleBarNormalButton:
00389                 if(d->flags & Qt::WindowMinMaxButtonsHint)
00390                     emit doNormal();
00391                 break;
00392 
00393             case QStyle::SC_TitleBarMinButton:
00394                 if(d->flags & Qt::WindowMinimizeButtonHint) {
00395                     if (d->window && d->window->isMinimized())
00396                         emit doNormal();
00397                     else
00398                         emit doMinimize();
00399                 }
00400                 break;
00401 
00402             case QStyle::SC_TitleBarMaxButton:
00403                 if(d->flags & Qt::WindowMaximizeButtonHint) {
00404                     if(d->window && d->window->isMaximized())
00405                         emit doNormal();
00406                     else
00407                         emit doMaximize();
00408                 }
00409                 break;
00410 
00411             case QStyle::SC_TitleBarCloseButton:
00412                 if(d->flags & Qt::WindowSystemMenuHint) {
00413                     d->buttonDown = QStyle::SC_None;
00414                     emit doClose();
00415                     return;
00416                 }
00417                 break;
00418 
00419             default:
00420                 break;
00421             }
00422         }
00423     } else {
00424         e->ignore();
00425     }
00426 }
00427 
00428 void QWorkspaceTitleBar::mouseMoveEvent(QMouseEvent *e)
00429 {
00430     Q_D(QWorkspaceTitleBar);
00431     e->ignore();
00432     if ((e->buttons() & Qt::LeftButton) && style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, 0)
00433         && !rect().adjusted(5, 5, -5, 0).contains(e->pos()) && !d->pressed) {
00434         // propagate border events to the QWidgetResizeHandler
00435         return;
00436     }
00437 
00438     QStyleOptionTitleBar opt = d->getStyleOption();
00439     QStyle::SubControl under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
00440                                                                     e->pos(), this);
00441     if(under_mouse != d->lastControl) {
00442         d->lastControl = under_mouse;
00443         update();
00444     }
00445 
00446     switch (d->buttonDown) {
00447     case QStyle::SC_None:
00448         break;
00449     case QStyle::SC_TitleBarSysMenu:
00450         break;
00451     case QStyle::SC_TitleBarLabel:
00452         if (d->buttonDown == QStyle::SC_TitleBarLabel && d->movable && d->pressed) {
00453             if (d->moving || (d->moveOffset - mapToParent(e->pos())).manhattanLength() >= 4) {
00454                 d->moving = true;
00455                 QPoint p = mapFromGlobal(e->globalPos());
00456 
00457                 QWidget *parent = d->window ? d->window->parentWidget() : 0;
00458                 if(parent && parent->inherits("QWorkspaceChild")) {
00459                     QWidget *workspace = parent->parentWidget();
00460                     p = workspace->mapFromGlobal(e->globalPos());
00461                     if (!workspace->rect().contains(p)) {
00462                         if (p.x() < 0)
00463                             p.rx() = 0;
00464                         if (p.y() < 0)
00465                             p.ry() = 0;
00466                         if (p.x() > workspace->width())
00467                             p.rx() = workspace->width();
00468                         if (p.y() > workspace->height())
00469                             p.ry() = workspace->height();
00470                     }
00471                 }
00472 
00473                 QPoint pp = p - d->moveOffset;
00474                 if (!parentWidget()->isMaximized())
00475                     parentWidget()->move(pp);
00476             }
00477         }
00478         e->accept();
00479         break;
00480     default:
00481         break;
00482     }
00483 }
00484 
00485 bool QWorkspaceTitleBar::isTool() const
00486 {
00487     Q_D(const QWorkspaceTitleBar);
00488     return (d->flags & Qt::WindowType_Mask) == Qt::Tool;
00489 }
00490 
00491 // from qwidget.cpp
00492 extern QString qt_setWindowTitle_helperHelper(const QString &, QWidget*);
00493 
00494 void QWorkspaceTitleBar::paintEvent(QPaintEvent *)
00495 {
00496     Q_D(QWorkspaceTitleBar);
00497     QStyleOptionTitleBar opt = d->getStyleOption();
00498     opt.subControls = QStyle::SC_TitleBarLabel;
00499     opt.activeSubControls = d->buttonDown;
00500 
00501     if (d->window && (d->flags & Qt::WindowTitleHint)) {
00502         QString title = qt_setWindowTitle_helperHelper(opt.text, d->window);
00503         int maxw = style()->subControlRect(QStyle::CC_TitleBar, &opt, QStyle::SC_TitleBarLabel,
00504                                        this).width();
00505         opt.text = fontMetrics().elidedText(title, Qt::ElideRight, maxw);
00506     }
00507 
00508     if (d->flags & Qt::WindowSystemMenuHint) {
00509         opt.subControls |= QStyle::SC_TitleBarSysMenu | QStyle::SC_TitleBarCloseButton;
00510         if (d->window && (d->flags & Qt::WindowShadeButtonHint)) {
00511             if (d->window->isMinimized())
00512                 opt.subControls |= QStyle::SC_TitleBarUnshadeButton;
00513             else
00514                 opt.subControls |= QStyle::SC_TitleBarShadeButton;
00515         }
00516         if (d->window && (d->flags & Qt::WindowMinMaxButtonsHint)) {
00517             if(d->window && d->window->isMinimized())
00518                 opt.subControls |= QStyle::SC_TitleBarNormalButton;
00519             else
00520                 opt.subControls |= QStyle::SC_TitleBarMinButton;
00521         }
00522         if (d->window && (d->flags & Qt::WindowMaximizeButtonHint) && !d->window->isMaximized())
00523             opt.subControls |= QStyle::SC_TitleBarMaxButton;
00524     }
00525 
00526     QStyle::SubControl under_mouse = QStyle::SC_None;
00527     under_mouse = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
00528                                                      mapFromGlobal(QCursor::pos()), this);
00529     if ((d->buttonDown == under_mouse) && d->pressed) {
00530         opt.state |= QStyle::State_Sunken;
00531     } else if( autoRaise() && under_mouse != QStyle::SC_None && !d->pressed) {
00532         opt.activeSubControls = under_mouse;
00533         opt.state |= QStyle::State_MouseOver;
00534     }
00535     opt.palette.setCurrentColorGroup(usesActiveColor() ? QPalette::Active : QPalette::Inactive);
00536 
00537     QPainter p(this);
00538     style()->drawComplexControl(QStyle::CC_TitleBar, &opt, &p, this);
00539 }
00540 
00541 void QWorkspaceTitleBar::mouseDoubleClickEvent(QMouseEvent *e)
00542 {
00543     Q_D(QWorkspaceTitleBar);
00544     if (e->button() != Qt::LeftButton) {
00545         e->ignore();
00546         return;
00547     }
00548     e->accept();
00549     QStyleOptionTitleBar opt = d->getStyleOption();
00550     switch (style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, e->pos(), this)) {
00551     case QStyle::SC_TitleBarLabel:
00552         emit doubleClicked();
00553         break;
00554 
00555     case QStyle::SC_TitleBarSysMenu:
00556         if (d->flags & Qt::WindowSystemMenuHint)
00557             emit doClose();
00558         break;
00559 
00560     default:
00561         break;
00562     }
00563 }
00564 
00565 void QWorkspaceTitleBar::leaveEvent(QEvent *)
00566 {
00567     Q_D(QWorkspaceTitleBar);
00568     d->lastControl = QStyle::SC_None;
00569     if(autoRaise() && !d->pressed)
00570         update();
00571 }
00572 
00573 void QWorkspaceTitleBar::enterEvent(QEvent *)
00574 {
00575     Q_D(QWorkspaceTitleBar);
00576     if(autoRaise() && !d->pressed)
00577         update();
00578     QEvent e(QEvent::Leave);
00579     QApplication::sendEvent(parentWidget(), &e);
00580 }
00581 
00582 void QWorkspaceTitleBar::setActive(bool active)
00583 {
00584     Q_D(QWorkspaceTitleBar);
00585     if (d->act == active)
00586         return ;
00587 
00588     d->act = active;
00589     update();
00590 }
00591 
00592 bool QWorkspaceTitleBar::isActive() const
00593 {
00594     Q_D(const QWorkspaceTitleBar);
00595     return d->act;
00596 }
00597 
00598 bool QWorkspaceTitleBar::usesActiveColor() const
00599 {
00600     return (isActive() && isActiveWindow()) ||
00601         (!window() && QWidget::window()->isActiveWindow());
00602 }
00603 
00604 QWidget *QWorkspaceTitleBar::window() const
00605 {
00606     Q_D(const QWorkspaceTitleBar);
00607     return d->window;
00608 }
00609 
00610 bool QWorkspaceTitleBar::event(QEvent *e)
00611 {
00612     Q_D(QWorkspaceTitleBar);
00613     if (e->type() == QEvent::ApplicationPaletteChange) {
00614         d->readColors();
00615     } else if (e->type() == QEvent::WindowActivate
00616                || e->type() == QEvent::WindowDeactivate) {
00617         if (d->act)
00618             update();
00619     }
00620     return QWidget::event(e);
00621 }
00622 
00623 void QWorkspaceTitleBar::setMovable(bool b)
00624 {
00625     Q_D(QWorkspaceTitleBar);
00626     d->movable = b;
00627 }
00628 
00629 bool QWorkspaceTitleBar::isMovable() const
00630 {
00631     Q_D(const QWorkspaceTitleBar);
00632     return d->movable;
00633 }
00634 
00635 void QWorkspaceTitleBar::setAutoRaise(bool b)
00636 {
00637     Q_D(QWorkspaceTitleBar);
00638     d->autoraise = b;
00639 }
00640 
00641 bool QWorkspaceTitleBar::autoRaise() const
00642 {
00643     Q_D(const QWorkspaceTitleBar);
00644     return d->autoraise;
00645 }
00646 
00647 QSize QWorkspaceTitleBar::sizeHint() const
00648 {
00649     Q_D(const QWorkspaceTitleBar);
00650     ensurePolished();
00651     QStyleOptionTitleBar opt = d->getStyleOption();
00652     QRect menur = style()->subControlRect(QStyle::CC_TitleBar, &opt,
00653                                           QStyle::SC_TitleBarSysMenu, this);
00654     return QSize(menur.width(), style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this));
00655 }
00656 
00722 class QWorkspaceChild : public QWidget
00723 {
00724     Q_OBJECT
00725 
00726     friend class QWorkspacePrivate;
00727     friend class QWorkspace;
00728     friend class QWorkspaceTitleBar;
00729 
00730 public:
00731     QWorkspaceChild(QWidget* window, QWorkspace* parent=0, Qt::WindowFlags flags = 0);
00732     ~QWorkspaceChild();
00733 
00734     void setActive(bool);
00735     bool isActive() const;
00736 
00737     void adjustToFullscreen();
00738 
00739     QWidget* windowWidget() const;
00740     QWidget* iconWidget() const;
00741 
00742     void doResize();
00743     void doMove();
00744 
00745     QSize sizeHint() const;
00746     QSize minimumSizeHint() const;
00747 
00748     QSize baseSize() const;
00749 
00750     int frameWidth() const;
00751 
00752     void show();
00753 
00754     bool isWindowOrIconVisible() const;
00755 
00756 signals:
00757     void showOperationMenu();
00758     void popupOperationMenu(const QPoint&);
00759 
00760 public slots:
00761     void activate();
00762     void showMinimized();
00763     void showMaximized();
00764     void showNormal();
00765     void showShaded();
00766     void internalRaise();
00767     void titleBarDoubleClicked();
00768 
00769 protected:
00770     void enterEvent(QEvent *);
00771     void leaveEvent(QEvent *);
00772     void childEvent(QChildEvent*);
00773     void resizeEvent(QResizeEvent *);
00774     void moveEvent(QMoveEvent *);
00775     bool eventFilter(QObject *, QEvent *);
00776 
00777     void paintEvent(QPaintEvent *);
00778     void changeEvent(QEvent *);
00779 
00780 private:
00781     void updateMask();
00782 
00783     Q_DISABLE_COPY(QWorkspaceChild)
00784 
00785     QWidget *childWidget;
00786     QWidgetResizeHandler *widgetResizeHandler;
00787     QWorkspaceTitleBar *titlebar;
00788     QPointer<QWorkspaceTitleBar> iconw;
00789     QSize windowSize;
00790     QSize shadeRestore;
00791     QSize shadeRestoreMin;
00792     bool act                  :1;
00793     bool shademode            :1;
00794 };
00795 
00796 int QWorkspaceChild::frameWidth() const
00797 {
00798     return contentsRect().left();
00799 }
00800 
00801 
00802 
00803 class QWorkspacePrivate : public QWidgetPrivate {
00804     Q_DECLARE_PUBLIC(QWorkspace)
00805 public:
00806     QWorkspaceChild* active;
00807     QList<QWorkspaceChild *> windows;
00808     QList<QWorkspaceChild *> focus;
00809     QList<QWidget *> icons;
00810     QWorkspaceChild* maxWindow;
00811     QRect maxRestore;
00812     QPointer<QFrame> maxcontrols;
00813     QPointer<QMenuBar> maxmenubar;
00814     QHash<int, const char*> shortcutMap;
00815 
00816     int px;
00817     int py;
00818     QWidget *becomeActive;
00819     QPointer<QLabel> maxtools;
00820     QString topTitle;
00821 
00822     QMenu *popup, *toolPopup;
00823     enum WSActs { RestoreAct, MoveAct, ResizeAct, MinimizeAct, MaximizeAct, CloseAct, StaysOnTopAct, ShadeAct, NCountAct };
00824     QAction *actions[NCountAct];
00825 
00826     QScrollBar *vbar, *hbar;
00827     QWidget *corner;
00828     int yoffset, xoffset;
00829     QBrush background;
00830 
00831     void init();
00832     void insertIcon(QWidget* w);
00833     void removeIcon(QWidget* w);
00834     void place(QWidget*);
00835 
00836     QWorkspaceChild* findChild(QWidget* w);
00837     void showMaximizeControls();
00838     void hideMaximizeControls();
00839     void activateWindow(QWidget* w, bool change_focus = true);
00840     void hideChild(QWorkspaceChild *c);
00841     void showWindow(QWidget* w);
00842     void maximizeWindow(QWidget* w);
00843     void minimizeWindow(QWidget* w);
00844     void normalizeWindow(QWidget* w);
00845 
00846     QRect updateWorkspace();
00847 
00848 private:
00849     void _q_normalizeActiveWindow();
00850     void _q_minimizeActiveWindow();
00851     void _q_showOperationMenu();
00852     void _q_popupOperationMenu(const QPoint&);
00853     void _q_operationMenuActivated(QAction *);
00854     void _q_scrollBarChanged();
00855     void _q_updateActions();
00856     bool inTitleChange;
00857 };
00858 
00859 static bool isChildOf(QWidget * child, QWidget * parent)
00860 {
00861     if (!parent || !child)
00862         return false;
00863     QWidget * w = child;
00864     while(w && w != parent)
00865         w = w->parentWidget();
00866     return w != 0;
00867 }
00868 
00872 QWorkspace::QWorkspace(QWidget *parent)
00873     : QWidget(*new QWorkspacePrivate, parent, 0)
00874 {
00875     Q_D(QWorkspace);
00876     d->init();
00877 }
00878 
00879 #ifdef QT3_SUPPORT
00880 
00884 QWorkspace::QWorkspace(QWidget *parent, const char *name)
00885     : QWidget(*new QWorkspacePrivate, parent, 0)
00886 {
00887     Q_D(QWorkspace);
00888     setObjectName(QString::fromAscii(name));
00889     d->init();
00890 }
00891 #endif // QT3_SUPPORT
00892 
00896 void
00897 QWorkspacePrivate::init()
00898 {
00899     Q_Q(QWorkspace);
00900 
00901     maxcontrols = 0;
00902     active = 0;
00903     maxWindow = 0;
00904     maxtools = 0;
00905     px = 0;
00906     py = 0;
00907     becomeActive = 0;
00908     popup = new QMenu(q);
00909     toolPopup = new QMenu(q);
00910     popup->setObjectName(QLatin1String("qt_internal_mdi_popup"));
00911     toolPopup->setObjectName(QLatin1String("qt_internal_mdi_tool_popup"));
00912 
00913     actions[QWorkspacePrivate::RestoreAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarNormalButton)),
00914                                                          QWorkspace::tr("&Restore"), q);
00915     actions[QWorkspacePrivate::MoveAct] = new QAction(QWorkspace::tr("&Move"), q);
00916     actions[QWorkspacePrivate::ResizeAct] = new QAction(QWorkspace::tr("&Size"), q);
00917     actions[QWorkspacePrivate::MinimizeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarMinButton)),
00918                                                           QWorkspace::tr("Mi&nimize"), q);
00919     actions[QWorkspacePrivate::MaximizeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarMaxButton)),
00920                                                           QWorkspace::tr("Ma&ximize"), q);
00921     actions[QWorkspacePrivate::CloseAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarCloseButton)),
00922                                                           QWorkspace::tr("&Close")
00923 #ifndef QT_NO_SHORTCUT
00924                                                           +QLatin1Char('\t')+(QString)QKeySequence(Qt::CTRL+Qt::Key_F4)
00925 #endif
00926                                                           ,q);
00927     QObject::connect(actions[QWorkspacePrivate::CloseAct], SIGNAL(triggered()), q, SLOT(closeActiveWindow()));
00928     actions[QWorkspacePrivate::StaysOnTopAct] = new QAction(QWorkspace::tr("Stay on &Top"), q);
00929     actions[QWorkspacePrivate::StaysOnTopAct]->setChecked(true);
00930     actions[QWorkspacePrivate::ShadeAct] = new QAction(QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarShadeButton)),
00931                                                           QWorkspace::tr("Sh&ade"), q);
00932 
00933     QObject::connect(popup, SIGNAL(aboutToShow()), q, SLOT(_q_updateActions()));
00934     QObject::connect(popup, SIGNAL(triggered(QAction*)), q, SLOT(_q_operationMenuActivated(QAction*)));
00935     popup->addAction(actions[QWorkspacePrivate::RestoreAct]);
00936     popup->addAction(actions[QWorkspacePrivate::MoveAct]);
00937     popup->addAction(actions[QWorkspacePrivate::ResizeAct]);
00938     popup->addAction(actions[QWorkspacePrivate::MinimizeAct]);
00939     popup->addAction(actions[QWorkspacePrivate::MaximizeAct]);
00940     popup->addSeparator();
00941     popup->addAction(actions[QWorkspacePrivate::CloseAct]);
00942 
00943     QObject::connect(toolPopup, SIGNAL(aboutToShow()), q, SLOT(_q_updateActions()));
00944     QObject::connect(toolPopup, SIGNAL(triggered(QAction*)), q, SLOT(_q_operationMenuActivated(QAction*)));
00945     toolPopup->addAction(actions[QWorkspacePrivate::MoveAct]);
00946     toolPopup->addAction(actions[QWorkspacePrivate::ResizeAct]);
00947     toolPopup->addAction(actions[QWorkspacePrivate::StaysOnTopAct]);
00948     toolPopup->addSeparator();
00949     toolPopup->addAction(actions[QWorkspacePrivate::ShadeAct]);
00950     toolPopup->addAction(actions[QWorkspacePrivate::CloseAct]);
00951 
00952 #ifndef QT_NO_SHORTCUT
00953     // Set up shortcut bindings (id -> slot), most used first
00954     QList <QKeySequence> shortcuts = QKeySequence::keyBindings(QKeySequence::NextChild);
00955     foreach (QKeySequence seq, shortcuts)
00956         shortcutMap.insert(q->grabShortcut(seq), "activateNextWindow");
00957 
00958     shortcuts = QKeySequence::keyBindings(QKeySequence::PreviousChild);
00959     foreach (QKeySequence seq, shortcuts)
00960         shortcutMap.insert(q->grabShortcut(seq), "activatePreviousWindow");
00961 
00962     shortcuts = QKeySequence::keyBindings(QKeySequence::Close);
00963     foreach (QKeySequence seq, shortcuts)
00964         shortcutMap.insert(q->grabShortcut(seq), "closeActiveWindow");
00965 
00966     shortcutMap.insert(q->grabShortcut(QKeySequence("ALT+-")), "_q_showOperationMenu");
00967 #endif // QT_NO_SHORTCUT
00968 
00969     q->setBackgroundRole(QPalette::Dark);
00970     q->setAutoFillBackground(true);
00971     q->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
00972 
00973     hbar = vbar = 0;
00974     corner = 0;
00975     xoffset = yoffset = 0;
00976 
00977     q->window()->installEventFilter(q);
00978 
00979     inTitleChange = false;
00980     updateWorkspace();
00981 }
00982 
00987 QWorkspace::~QWorkspace()
00988 {
00989 }
00990 
00992 QSize QWorkspace::sizeHint() const
00993 {
00994     QSize s(QApplication::desktop()->size());
00995     return QSize(s.width()*2/3, s.height()*2/3);
00996 }
00997 
00998 
00999 #ifdef QT3_SUPPORT
01000 
01004 void QWorkspace::setPaletteBackgroundColor(const QColor & c)
01005 {
01006     setBackground(c);
01007 }
01008 
01013 void QWorkspace::setPaletteBackgroundPixmap(const QPixmap & pm)
01014 {
01015     setBackground(pm);
01016 }
01017 #endif // QT3_SUPPORT
01018 
01023 QBrush QWorkspace::background() const
01024 {
01025     Q_D(const QWorkspace);
01026     if (d->background.style() == Qt::NoBrush)
01027         return palette().dark();
01028     return d->background;
01029 }
01030 
01031 void QWorkspace::setBackground(const QBrush &background)
01032 {
01033     Q_D(QWorkspace);
01034     d->background = background;
01035     setAttribute(Qt::WA_OpaquePaintEvent, background.style() == Qt::NoBrush);
01036     update();
01037 }
01038 
01049 QWidget * QWorkspace::addWindow(QWidget *w, Qt::WindowFlags flags)
01050 {
01051     Q_D(QWorkspace);
01052     if (!w)
01053         return 0;
01054 
01055     w->setAutoFillBackground(true);
01056 
01057     QWidgetPrivate::adjustFlags(flags);
01058 
01059 #if 0
01060     bool wasMaximized = w->isMaximized();
01061     bool wasMinimized = w->isMinimized();
01062 #endif
01063     bool hasSize = w->testAttribute(Qt::WA_Resized);
01064     int x = w->x();
01065     int y = w->y();
01066     bool hasPos = w->testAttribute(Qt::WA_Moved);
01067     QSize s = w->size().expandedTo(qSmartMinSize(w));
01068     if (!hasSize && w->sizeHint().isValid())
01069         w->adjustSize();
01070 
01071     QWorkspaceChild* child = new QWorkspaceChild(w, this, flags);
01072     child->setObjectName(QLatin1String("qt_workspacechild"));
01073     child->installEventFilter(this);
01074 
01075     connect(child, SIGNAL(popupOperationMenu(QPoint)),
01076             this, SLOT(_q_popupOperationMenu(QPoint)));
01077     connect(child, SIGNAL(showOperationMenu()),
01078             this, SLOT(_q_showOperationMenu()));
01079     d->windows.append(child);
01080     if (child->isVisibleTo(this))
01081         d->focus.append(child);
01082     child->internalRaise();
01083 
01084     if (!hasPos)
01085         d->place(child);
01086     if (!hasSize)
01087         child->adjustSize();
01088     if (hasPos)
01089         child->move(x, y);
01090 
01091     return child;
01092 
01093 #if 0
01094     if (wasMaximized)
01095         w->showMaximized();
01096     else if (wasMinimized)
01097         w->showMinimized();
01098     else if (!hasBeenHidden)
01099         d->activateWindow(w);
01100 
01101     d->updateWorkspace();
01102     return child;
01103 #endif
01104 }
01105 
01107 void QWorkspace::childEvent(QChildEvent * e)
01108 {
01109     Q_D(QWorkspace);
01110     if (e->removed()) {
01111         if (d->windows.removeAll(static_cast<QWorkspaceChild*>(e->child()))) {
01112             d->focus.removeAll(static_cast<QWorkspaceChild*>(e->child()));
01113             if (d->maxWindow == e->child())
01114                 d->maxWindow = 0;
01115             d->updateWorkspace();
01116         }
01117     }
01118 }
01119 
01121 #ifndef QT_NO_WHEELEVENT
01122 void QWorkspace::wheelEvent(QWheelEvent *e)
01123 {
01124     Q_D(QWorkspace);
01125     if (!scrollBarsEnabled())
01126         return;
01127     // the scrollbars are children of the workspace, so if we receive
01128     // a wheel event we redirect to the scrollbars using a direct event
01129     // call, /not/ using sendEvent() because if the scrollbar ignores the
01130     // event QApplication::sendEvent() will propagate the event to the parent widget,
01131     // which is us, who /just/ sent it.
01132     if (d->vbar && d->vbar->isVisible() && !(e->modifiers() & Qt::AltModifier))
01133         d->vbar->event(e);
01134     else if (d->hbar && d->hbar->isVisible())
01135         d->hbar->event(e);
01136 }
01137 #endif
01138 
01139 void QWorkspacePrivate::activateWindow(QWidget* w, bool change_focus)
01140 {
01141     Q_Q(QWorkspace);
01142     if (!w) {
01143         active = 0;
01144         emit q->windowActivated(0);
01145         return;
01146     }
01147     if (!q->isVisible()) {
01148         becomeActive = w;
01149         return;
01150     }
01151 
01152     if (active && active->windowWidget() == w) {
01153         if (!isChildOf(q->focusWidget(), w)) // child window does not have focus
01154             active->setActive(true);
01155         return;
01156     }
01157 
01158     active = 0;
01159     // First deactivate all other workspace clients
01160     QList<QWorkspaceChild *>::Iterator it(windows.begin());
01161     while (it != windows.end()) {
01162         QWorkspaceChild* c = *it;
01163         ++it;
01164         if (c->windowWidget() == w)
01165             active = c;
01166         else
01167             c->setActive(false);
01168     }
01169 
01170     if (!active)
01171         return;
01172 
01173     // Then activate the new one, so the focus is stored correctly
01174     active->setActive(true);
01175 
01176     if (!active)
01177         return;
01178 
01179     if (maxWindow && maxWindow != active && active->windowWidget() &&
01180         (active->windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint))
01181         active->showMaximized();
01182 
01183     active->internalRaise();
01184 
01185     if (change_focus) {
01186   int from = focus.indexOf(active);
01187         if (from >= 0)
01188             focus.move(from, focus.size() - 1);
01189     }
01190 
01191     updateWorkspace();
01192     emit q->windowActivated(w);
01193 }
01194 
01195 
01202 QWidget* QWorkspace::activeWindow() const
01203 {
01204     Q_D(const QWorkspace);
01205     return d->active? d->active->windowWidget() : 0;
01206 }
01207 
01213 void QWorkspace::setActiveWindow(QWidget *w)
01214 {
01215     Q_D(QWorkspace);
01216     d->activateWindow(w, true);
01217     if (w && w->isMinimized())
01218         w->setWindowState(w->windowState() & ~Qt::WindowMinimized);
01219 }
01220 
01221 void QWorkspacePrivate::place(QWidget *w)
01222 {
01223     Q_Q(QWorkspace);
01224 
01225     QList<QWidget *> widgets;
01226     for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it)
01227         if (*it != w)
01228             widgets.append(*it);
01229 
01230     int overlap, minOverlap = 0;
01231     int possible;
01232 
01233     QRect r1(0, 0, 0, 0);
01234     QRect r2(0, 0, 0, 0);
01235     QRect maxRect = q->rect();
01236     int x = maxRect.left(), y = maxRect.top();
01237     QPoint wpos(maxRect.left(), maxRect.top());
01238 
01239     bool firstPass = true;
01240 
01241     do {
01242         if (y + w->height() > maxRect.bottom()) {
01243             overlap = -1;
01244         } else if(x + w->width() > maxRect.right()) {
01245             overlap = -2;
01246         } else {
01247             overlap = 0;
01248 
01249             r1.setRect(x, y, w->width(), w->height());
01250 
01251             QWidget *l;
01252             QList<QWidget *>::Iterator it(widgets.begin());
01253             while (it != widgets.end()) {
01254                 l = *it;
01255                 ++it;
01256 
01257                 if (maxWindow == l)
01258                     r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
01259                 else
01260                     r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
01261                                             QRect(l->x(), l->y(), l->width(), l->height()));
01262 
01263                 if (r2.intersects(r1)) {
01264                     r2.setCoords(qMax(r1.left(), r2.left()),
01265                                  qMax(r1.top(), r2.top()),
01266                                  qMin(r1.right(), r2.right()),
01267                                  qMin(r1.bottom(), r2.bottom())
01268                                 );
01269 
01270                     overlap += (r2.right() - r2.left()) *
01271                                (r2.bottom() - r2.top());
01272                 }
01273             }
01274         }
01275 
01276         if (overlap == 0) {
01277             wpos = QPoint(x, y);
01278             break;
01279         }
01280 
01281         if (firstPass) {
01282             firstPass = false;
01283             minOverlap = overlap;
01284         } else if (overlap >= 0 && overlap < minOverlap) {
01285             minOverlap = overlap;
01286             wpos = QPoint(x, y);
01287         }
01288 
01289         if (overlap > 0) {
01290             possible = maxRect.right();
01291             if (possible - w->width() > x) possible -= w->width();
01292 
01293             QWidget *l;
01294             QList<QWidget *>::Iterator it(widgets.begin());
01295             while (it != widgets.end()) {
01296                 l = *it;
01297                 ++it;
01298                 if (maxWindow == l)
01299                     r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
01300                 else
01301                     r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
01302                                             QRect(l->x(), l->y(), l->width(), l->height()));
01303 
01304                 if((y < r2.bottom()) && (r2.top() < w->height() + y)) {
01305                     if(r2.right() > x)
01306                         possible = possible < r2.right() ?
01307                                    possible : r2.right();
01308 
01309                     if(r2.left() - w->width() > x)
01310                         possible = possible < r2.left() - w->width() ?
01311                                    possible : r2.left() - w->width();
01312                 }
01313             }
01314 
01315             x = possible;
01316         } else if (overlap == -2) {
01317             x = maxRect.left();
01318             possible = maxRect.bottom();
01319 
01320             if (possible - w->height() > y) possible -= w->height();
01321 
01322             QWidget *l;
01323             QList<QWidget *>::Iterator it(widgets.begin());
01324             while (it != widgets.end()) {
01325                 l = *it;
01326                 ++it;
01327                 if (maxWindow == l)
01328                     r2 = QStyle::visualRect(q->layoutDirection(), maxRect, maxRestore);
01329                 else
01330                     r2 = QStyle::visualRect(q->layoutDirection(), maxRect,
01331                                             QRect(l->x(), l->y(), l->width(), l->height()));
01332 
01333                 if(r2.bottom() > y)
01334                     possible = possible < r2.bottom() ?
01335                                possible : r2.bottom();
01336 
01337                 if(r2.top() - w->height() > y)
01338                     possible = possible < r2.top() - w->height() ?
01339                                possible : r2.top() - w->height();
01340             }
01341 
01342             y = possible;
01343         }
01344     }
01345     while(overlap != 0 && overlap != -1);
01346 
01347     QRect resultRect = w->geometry();
01348     resultRect.moveTo(wpos);
01349     w->setGeometry(QStyle::visualRect(q->layoutDirection(), maxRect, resultRect));
01350     updateWorkspace();
01351 }
01352 
01353 
01354 void QWorkspacePrivate::insertIcon(QWidget* w)
01355 {
01356     Q_Q(QWorkspace);
01357     if (!w || icons.contains(w))
01358         return;
01359     icons.append(w);
01360     if (w->parentWidget() != q) {
01361         w->setParent(q, 0);
01362         w->move(0,0);
01363     }
01364     QRect cr = updateWorkspace();
01365     int x = 0;
01366     int y = cr.height() - w->height();
01367 
01368     QList<QWidget *>::Iterator it(icons.begin());
01369     while (it != icons.end()) {
01370         QWidget* i = *it;
01371         ++it;
01372         if (x > 0 && x + i->width() > cr.width()){
01373             x = 0;
01374             y -= i->height();
01375         }
01376 
01377         if (i != w &&
01378             i->geometry().intersects(QRect(x, y, w->width(), w->height())))
01379             x += i->width();
01380     }
01381     w->move(x, y);
01382 
01383     if (q->isVisibleTo(q->parentWidget())) {
01384         w->show();
01385         w->lower();
01386     }
01387     updateWorkspace();
01388 }
01389 
01390 
01391 void QWorkspacePrivate::removeIcon(QWidget* w)
01392 {
01393     if (icons.removeAll(w))
01394         w->hide();
01395 }
01396 
01397 
01399 void QWorkspace::resizeEvent(QResizeEvent *)
01400 {
01401     Q_D(QWorkspace);
01402     if (d->maxWindow) {
01403         d->maxWindow->adjustToFullscreen();
01404         if (d->maxWindow->windowWidget())
01405             d->maxWindow->windowWidget()->overrideWindowState(Qt::WindowMaximized);
01406     }
01407     d->updateWorkspace();
01408 }
01409 
01411 void QWorkspace::showEvent(QShowEvent *e)
01412 {
01413     Q_D(QWorkspace);
01414     if (d->maxWindow)
01415         d->showMaximizeControls();
01416     QWidget::showEvent(e);
01417     if (d->becomeActive) {
01418         d->activateWindow(d->becomeActive);
01419         d->becomeActive = 0;
01420     } else if (d->windows.count() > 0 && !d->active) {
01421         d->activateWindow(d->windows.first()->windowWidget());
01422     }
01423 
01424 //     // force a frame repaint - this is a workaround for what seems to be a bug
01425 //     // introduced when changing the QWidget::show() implementation. Might be
01426 //     // a windows bug as well though.
01427 //     for (int i = 0; i < d->windows.count(); ++i) {
01428 //  QWorkspaceChild* c = d->windows.at(i);
01429 //         c->update(c->rect());
01430 //     }
01431 
01432     d->updateWorkspace();
01433 }
01434 
01436 void QWorkspace::hideEvent(QHideEvent *)
01437 {
01438     Q_D(QWorkspace);
01439     if (!isVisible())
01440         d->hideMaximizeControls();
01441 }
01442 
01444 void QWorkspace::paintEvent(QPaintEvent *)
01445 {
01446     Q_D(QWorkspace);
01447 
01448     if (d->background.style() != Qt::NoBrush) {
01449         QPainter p(this);
01450         p.fillRect(0, 0, width(), height(), d->background);
01451     }
01452 }
01453 
01454 void QWorkspacePrivate::minimizeWindow(QWidget* w)
01455 {
01456     QWorkspaceChild* c = findChild(w);
01457 
01458     if (!w || !(w->windowFlags() & Qt::WindowMinimizeButtonHint))
01459         return;
01460 
01461     if (c) {
01462         bool wasMax = false;
01463         if (c == maxWindow) {
01464             wasMax = true;
01465             maxWindow = 0;
01466             hideMaximizeControls();
01467             for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it) {
01468                 QWorkspaceChild* c = *it;
01469                 if (c->titlebar)
01470                     c->titlebar->setMovable(true);
01471                 c->widgetResizeHandler->setActive(true);
01472             }
01473         }
01474         c->hide();
01475         if (wasMax)
01476             c->setGeometry(maxRestore);
01477         if (!focus.contains(c))
01478             focus.append(c);
01479         insertIcon(c->iconWidget());
01480 
01481         if (!maxWindow)
01482             activateWindow(w);
01483 
01484         updateWorkspace();
01485 
01486         w->overrideWindowState(Qt::WindowMinimized);
01487         c->overrideWindowState(Qt::WindowMinimized);
01488     }
01489 }
01490 
01491 void QWorkspacePrivate::normalizeWindow(QWidget* w)
01492 {
01493     Q_Q(QWorkspace);
01494     QWorkspaceChild* c = findChild(w);
01495     if (!w)
01496         return;
01497     if (c) {
01498         w->overrideWindowState(Qt::WindowNoState);
01499         hideMaximizeControls();
01500         if (!maxmenubar || q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q) || !maxWindow) {
01501             if (w->minimumSize() != w->maximumSize())
01502                 c->widgetResizeHandler->setActive(true);
01503             if (c->titlebar)
01504                 c->titlebar->setMovable(true);
01505         }
01506         w->overrideWindowState(Qt::WindowNoState);
01507         c->overrideWindowState(Qt::WindowNoState);
01508 
01509         if (c == maxWindow) {
01510             c->setGeometry(maxRestore);
01511             maxWindow = 0;
01512         } else {
01513             if (c->iconw)
01514                 removeIcon(c->iconw->parentWidget());
01515             c->show();
01516         }
01517 
01518         hideMaximizeControls();
01519         for (QList<QWorkspaceChild *>::Iterator it(windows.begin()); it != windows.end(); ++it) {
01520             QWorkspaceChild* c = *it;
01521             if (c->titlebar)
01522                 c->titlebar->setMovable(true);
01523             if (c->childWidget && c->childWidget->minimumSize() != c->childWidget->maximumSize())
01524                 c->widgetResizeHandler->setActive(true);
01525         }
01526         activateWindow(w, true);
01527         updateWorkspace();
01528     }
01529 }
01530 
01531 void QWorkspacePrivate::maximizeWindow(QWidget* w)
01532 {
01533     Q_Q(QWorkspace);
01534     QWorkspaceChild* c = findChild(w);
01535 
01536     if (!w || !(w->windowFlags() & Qt::WindowMaximizeButtonHint))
01537         return;
01538 
01539     if (!c || c == maxWindow)
01540         return;
01541 
01542     bool updatesEnabled = q->updatesEnabled();
01543     q->setUpdatesEnabled(false);
01544 
01545     if (c->iconw && icons.contains(c->iconw->parentWidget()))
01546         normalizeWindow(w);
01547     QRect r(c->geometry());
01548     QWorkspaceChild *oldMaxWindow = maxWindow;
01549     maxWindow = c;
01550 
01551     showMaximizeControls();
01552 
01553     c->adjustToFullscreen();
01554     c->show();
01555     c->internalRaise();
01556     if (oldMaxWindow != c) {
01557         if (oldMaxWindow) {
01558             oldMaxWindow->setGeometry(maxRestore);
01559             oldMaxWindow->overrideWindowState(Qt::WindowNoState);
01560             if(oldMaxWindow->windowWidget())
01561                 oldMaxWindow->windowWidget()->overrideWindowState(Qt::WindowNoState);
01562         }
01563         maxRestore = r;
01564     }
01565 
01566     activateWindow(w);
01567 
01568     if(!maxmenubar || q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
01569         if (!active && becomeActive) {
01570             active = (QWorkspaceChild*)becomeActive->parentWidget();
01571             active->setActive(true);
01572             becomeActive = 0;
01573             emit q->windowActivated(active->windowWidget());
01574         }
01575         c->widgetResizeHandler->setActive(false);
01576         if (c->titlebar)
01577             c->titlebar->setMovable(false);
01578     }
01579     updateWorkspace();
01580 
01581     w->overrideWindowState(Qt::WindowMaximized);
01582     c->overrideWindowState(Qt::WindowMaximized);
01583     q->setUpdatesEnabled(updatesEnabled);
01584 }
01585 
01586 void QWorkspacePrivate::showWindow(QWidget* w)
01587 {
01588     if (w->isMinimized() && (w->windowFlags() & Qt::WindowMinimizeButtonHint))
01589         minimizeWindow(w);
01590     else if ((maxWindow || w->isMaximized()) && w->windowFlags() & Qt::WindowMaximizeButtonHint)
01591         maximizeWindow(w);
01592     else if (w->windowFlags() & Qt::WindowMaximizeButtonHint)
01593         normalizeWindow(w);
01594     else
01595         w->parentWidget()->show();
01596     if (maxWindow)
01597         maxWindow->internalRaise();
01598     updateWorkspace();
01599 }
01600 
01601 
01602 QWorkspaceChild* QWorkspacePrivate::findChild(QWidget* w)
01603 {
01604     QList<QWorkspaceChild *>::Iterator it(windows.begin());
01605     while (it != windows.end()) {
01606         QWorkspaceChild* c = *it;
01607         ++it;
01608         if (c->windowWidget() == w)
01609             return c;
01610     }
01611     return 0;
01612 }
01613 
01621 QWidgetList QWorkspace::windowList(WindowOrder order) const
01622 {
01623     Q_D(const QWorkspace);
01624     QWidgetList windows;
01625     if (order == StackingOrder) {
01626         QObjectList cl = children();
01627         for (int i = 0; i < cl.size(); ++i) {
01628             QWorkspaceChild *c = qobject_cast<QWorkspaceChild*>(cl.at(i));
01629             if (c && c->isWindowOrIconVisible())
01630                 windows.append(c->windowWidget());
01631         }
01632     } else {
01633         QList<QWorkspaceChild *>::ConstIterator it(d->windows.begin());
01634         while (it != d->windows.end()) {
01635             QWorkspaceChild* c = *it;
01636             ++it;
01637             if (c && c->isWindowOrIconVisible())
01638                 windows.append(c->windowWidget());
01639         }
01640     }
01641     return windows;
01642 }
01643 
01644 
01646 bool QWorkspace::event(QEvent *e)
01647 {
01648 #ifndef QT_NO_SHORTCUT
01649     Q_D(QWorkspace);
01650     if (e->type() == QEvent::Shortcut) {
01651         QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
01652         const char *theSlot = d->shortcutMap.value(se->shortcutId(), 0);
01653         if (theSlot)
01654             QMetaObject::invokeMethod(this, theSlot);
01655     } else
01656 #endif
01657     if (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut){
01658         return true;
01659     }
01660     return QWidget::event(e);
01661 }
01662 
01664 bool QWorkspace::eventFilter(QObject *o, QEvent * e)
01665 {
01666     Q_D(QWorkspace);
01667     static QTime* t = 0;
01668     static QWorkspace* tc = 0;
01669     if (o == d->maxtools) {
01670         switch (e->type()) {
01671         case QEvent::MouseButtonPress:
01672             {
01673                 QMenuBar* b = (QMenuBar*)o->parent();
01674                 if (!t)
01675                     t = new QTime;
01676                 if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
01677                     if (isRightToLeft()) {
01678                         QPoint p = b->mapToGlobal(QPoint(b->x() + b->width(), b->y() + b->height()));
01679                         p.rx() -= d->popup->sizeHint().width();
01680                         d->_q_popupOperationMenu(p);
01681                     } else {
01682                         d->_q_popupOperationMenu(b->mapToGlobal(QPoint(b->x(), b->y() + b->height())));
01683                     }
01684                     t->start();
01685                     tc = this;
01686                 } else {
01687                     tc = 0;
01688                     closeActiveWindow();
01689                 }
01690                 return true;
01691             }
01692         default:
01693             break;
01694         }
01695         return QWidget::eventFilter(o, e);
01696     }
01697     switch (e->type()) {
01698     case QEvent::HideToParent:
01699         break;
01700     case QEvent::ShowToParent:
01701         if (QWorkspaceChild *c = qobject_cast<QWorkspaceChild*>(o))
01702             if (!d->focus.contains(c))
01703                 d->focus.append(c);
01704         d->updateWorkspace();
01705         break;
01706     case QEvent::WindowTitleChange:
01707         if (!d->inTitleChange) {
01708             if (o == window())
01709                 d->topTitle = window()->windowTitle();
01710             if (d->maxWindow && d->maxWindow->windowWidget() && d->topTitle.size()) {
01711                 d->inTitleChange = true;
01712                 window()->setWindowTitle(tr("%1 - [%2]")
01713                                          .arg(d->topTitle).arg(d->maxWindow->windowWidget()->windowTitle()));
01714                 d->inTitleChange = false;
01715             }
01716         }
01717         break;
01718 
01719     case QEvent::ModifiedChange:
01720         if (o == d->maxWindow)
01721             window()->setWindowModified(d->maxWindow->isWindowModified());
01722         break;
01723 
01724     case QEvent::Close:
01725         if (o == window())
01726         {
01727             QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
01728             while (it != d->windows.end()) {
01729                 QWorkspaceChild* c = *it;
01730                 ++it;
01731                 if (c->shademode)
01732                     c->showShaded();
01733             }
01734         } else if (qobject_cast<QWorkspaceChild*>(o)) {
01735             d->popup->hide();
01736         }
01737         d->updateWorkspace();
01738         break;
01739     default:
01740         break;
01741     }
01742     return QWidget::eventFilter(o, e);
01743 }
01744 
01745 static QMenuBar *findMenuBar(QWidget *w)
01746 {
01747     // don't search recursively to avoid finding a menubar of a
01748     // mainwindow that happens to be a workspace window (like
01749     // a mainwindow in designer)
01750     QList<QObject *> children = w->children();
01751     for (int i = 0; i < children.count(); ++i) {
01752         QMenuBar *bar = qobject_cast<QMenuBar *>(children.at(i));
01753         if (bar)
01754             return bar;
01755     }
01756     return 0;
01757 }
01758 
01759 void QWorkspacePrivate::showMaximizeControls()
01760 {
01761     Q_Q(QWorkspace);
01762     Q_ASSERT(maxWindow);
01763 
01764     // merge windowtitle and modified state
01765     if (!topTitle.size())
01766         topTitle = q->window()->windowTitle();
01767 
01768     if (maxWindow->windowWidget()) {
01769         QString docTitle = maxWindow->windowWidget()->windowTitle();
01770         if (topTitle.size() && docTitle.size()) {
01771             inTitleChange = true;
01772             q->window()->setWindowTitle(QWorkspace::tr("%1 - [%2]").arg(topTitle).arg(docTitle));
01773             inTitleChange = false;
01774         }
01775         q->window()->setWindowModified(maxWindow->windowWidget()->isWindowModified());
01776     }
01777 
01778     if (!q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
01779         QMenuBar* b = 0;
01780 
01781         // Do a breadth-first search first on every parent,
01782         QWidget* w = q->parentWidget();
01783         while (w) {
01784             b = findMenuBar(w);
01785             if (b)
01786                 break;
01787             w = w->parentWidget();
01788         }
01789 
01790         // last attempt.
01791         if (!b)
01792             b = findMenuBar(q->window());
01793 
01794         if (!b)
01795             return;
01796 
01797         if (!maxcontrols) {
01798             maxmenubar = b;
01799             maxcontrols = new QFrame(q->window());
01800             maxcontrols->setObjectName(QLatin1String("qt_maxcontrols"));
01801             QHBoxLayout* l = new QHBoxLayout(maxcontrols);
01802             l->setMargin(maxcontrols->frameWidth());
01803             l->setSpacing(0);
01804             if (maxWindow->windowWidget() &&
01805                 (maxWindow->windowWidget()->windowFlags() & Qt::WindowMinimizeButtonHint)) {
01806                 QToolButton* iconB = new QToolButton(maxcontrols);
01807                 iconB->setObjectName(QLatin1String("iconify"));
01808 #ifndef QT_NO_TOOLTIP
01809                 iconB->setToolTip(QWorkspace::tr("Minimize"));
01810 #endif
01811                 l->addWidget(iconB);
01812                 iconB->setFocusPolicy(Qt::NoFocus);
01813                 QPixmap pm = q->style()->standardPixmap(QStyle::SP_TitleBarMinButton);
01814                 iconB->setIcon(pm);
01815                 iconB->setIconSize(pm.size());
01816                 QObject::connect(iconB, SIGNAL(clicked()),
01817                                  q, SLOT(_q_minimizeActiveWindow()));
01818             }
01819 
01820             QToolButton* restoreB = new QToolButton(maxcontrols);
01821             restoreB->setObjectName(QLatin1String("restore"));
01822 #ifndef QT_NO_TOOLTIP
01823             restoreB->setToolTip(QWorkspace::tr("Restore Down"));
01824 #endif
01825             l->addWidget(restoreB);
01826             restoreB->setFocusPolicy(Qt::NoFocus);
01827             QPixmap pm = q->style()->standardPixmap(QStyle::SP_TitleBarNormalButton);
01828             restoreB->setIcon(pm);
01829             restoreB->setIconSize(pm.size());
01830             QObject::connect(restoreB, SIGNAL(clicked()),
01831                              q, SLOT(_q_normalizeActiveWindow()));
01832 
01833             l->addSpacing(2);
01834             QToolButton* closeB = new QToolButton(maxcontrols);
01835             closeB->setObjectName(QLatin1String("close"));
01836 #ifndef QT_NO_TOOLTIP
01837             closeB->setToolTip(QWorkspace::tr("Close"));
01838 #endif
01839             l->addWidget(closeB);
01840             closeB->setFocusPolicy(Qt::NoFocus);
01841             pm = q->style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
01842             closeB->setIcon(pm);
01843             closeB->setIconSize(pm.size());
01844             QObject::connect(closeB, SIGNAL(clicked()),
01845                              q, SLOT(closeActiveWindow()));
01846 
01847             maxcontrols->setFixedSize(maxcontrols->minimumSizeHint());
01848         }
01849 
01850         b->setCornerWidget(maxcontrols);
01851         if (b->isVisible())
01852             maxcontrols->show();
01853         if (!active && becomeActive) {
01854             active = (QWorkspaceChild*)becomeActive->parentWidget();
01855             active->setActive(true);
01856             becomeActive = 0;
01857             emit q->windowActivated(active->windowWidget());
01858         }
01859         if (active) {
01860             if (!maxtools) {
01861                 maxtools = new QLabel(q->window());
01862                 maxtools->setObjectName(QLatin1String("qt_maxtools"));
01863                 maxtools->installEventFilter(q);
01864             }
01865             if (active->windowWidget() && !active->windowWidget()->windowIcon().isNull()) {
01866                 QIcon icon = active->windowWidget()->windowIcon();
01867                 int iconSize = maxcontrols->size().height();
01868                 maxtools->setPixmap(icon.pixmap(QSize(iconSize, iconSize)));
01869             } else {
01870                 QPixmap pm = q->style()->standardPixmap(QStyle::SP_TitleBarMenuButton);
01871                 if (pm.isNull()) {
01872                     pm = QPixmap(14,14);
01873                     pm.fill(Qt::black);
01874                 }
01875                 maxtools->setPixmap(pm);
01876             }
01877             b->setCornerWidget(maxtools, Qt::TopLeftCorner);
01878             if (b->isVisible())
01879                 maxtools->show();
01880         }
01881     }
01882 }
01883 
01884 
01885 void QWorkspacePrivate::hideMaximizeControls()
01886 {
01887     Q_Q(QWorkspace);
01888     if (maxmenubar && !q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) {
01889         if (maxmenubar) {
01890             maxmenubar->setCornerWidget(0, Qt::TopLeftCorner);
01891             maxmenubar->setCornerWidget(0, Qt::TopRightCorner);
01892         }
01893         maxcontrols->deleteLater();
01894         maxtools->deleteLater();
01895     }
01896 
01897     //unmerge the titlebar/modification state
01898     if (topTitle.size()) {
01899         inTitleChange = true;
01900         q->window()->setWindowTitle(topTitle);
01901         inTitleChange = false;
01902     }
01903     q->window()->setWindowModified(false);
01904 }
01905 
01911 void QWorkspace::closeActiveWindow()
01912 {
01913     Q_D(QWorkspace);
01914     if (d->maxWindow && d->maxWindow->windowWidget())
01915         d->maxWindow->windowWidget()->close();
01916     else if (d->active && d->active->windowWidget())
01917         d->active->windowWidget()->close();
01918     d->updateWorkspace();
01919 }
01920 
01929 void QWorkspace::closeAllWindows()
01930 {
01931     Q_D(QWorkspace);
01932     bool did_close = true;
01933     QList<QWorkspaceChild *>::const_iterator it = d->windows.constBegin();
01934     while (it != d->windows.constEnd() && did_close) {
01935         QWorkspaceChild *c = *it;
01936         ++it;
01937         if (c->windowWidget() && !c->windowWidget()->isHidden())
01938             did_close = c->windowWidget()->close();
01939     }
01940 }
01941 
01942 void QWorkspacePrivate::_q_normalizeActiveWindow()
01943 {
01944     if (maxWindow)
01945         maxWindow->showNormal();
01946     else if (active)
01947         active->showNormal();
01948 }
01949 
01950 void QWorkspacePrivate::_q_minimizeActiveWindow()
01951 {
01952     if (maxWindow)
01953         maxWindow->showMinimized();
01954     else if (active)
01955         active->showMinimized();
01956 }
01957 
01958 void QWorkspacePrivate::_q_showOperationMenu()
01959 {
01960     Q_Q(QWorkspace);
01961     if  (!active || !active->windowWidget())
01962         return;
01963     Q_ASSERT((active->windowWidget()->windowFlags() & Qt::WindowSystemMenuHint));
01964     QPoint p;
01965     QMenu *popup = (active->titlebar && active->titlebar->isTool()) ? toolPopup : this->popup;
01966     if (q->isRightToLeft()) {
01967         p = QPoint(active->windowWidget()->mapToGlobal(QPoint(active->windowWidget()->width(),0)));
01968         p.rx() -= popup->sizeHint().width();
01969     } else {
01970         p = QPoint(active->windowWidget()->mapToGlobal(QPoint(0,0)));
01971     }
01972     if (!active->isVisible()) {
01973         p = active->iconWidget()->mapToGlobal(QPoint(0,0));
01974         p.ry() -= popup->sizeHint().height();
01975     }
01976     _q_popupOperationMenu(p);
01977 }
01978 
01979 void QWorkspacePrivate::_q_popupOperationMenu(const QPoint&  p)
01980 {
01981     if (!active || !active->windowWidget() || !(active->windowWidget()->windowFlags() & Qt::WindowSystemMenuHint))
01982         return;
01983     if (active->titlebar && active->titlebar->isTool())
01984         toolPopup->popup(p);
01985     else
01986         popup->popup(p);
01987 }
01988 
01989 void QWorkspacePrivate::_q_updateActions()
01990 {
01991     Q_Q(QWorkspace);
01992     for (int i = 1; i < NCountAct-1; i++) {
01993         bool enable = active != 0;
01994         actions[i]->setEnabled(enable);
01995     }
01996 
01997     if (!active || !active->windowWidget())
01998         return;
01999 
02000     QWidget *windowWidget = active->windowWidget();
02001     bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize();
02002     actions[QWorkspacePrivate::ResizeAct]->setEnabled(canResize);
02003     actions[QWorkspacePrivate::MinimizeAct]->setEnabled((windowWidget->windowFlags() & Qt::WindowMinimizeButtonHint));
02004     actions[QWorkspacePrivate::MaximizeAct]->setEnabled((windowWidget->windowFlags() & Qt::WindowMaximizeButtonHint) && canResize);
02005 
02006     if (active == maxWindow) {
02007         actions[QWorkspacePrivate::MoveAct]->setEnabled(false);
02008         actions[QWorkspacePrivate::ResizeAct]->setEnabled(false);
02009         actions[QWorkspacePrivate::MaximizeAct]->setEnabled(false);
02010         actions[QWorkspacePrivate::RestoreAct]->setEnabled(true);
02011     } else if (active->isVisible()){
02012         actions[QWorkspacePrivate::RestoreAct]->setEnabled(false);
02013     } else {
02014         actions[QWorkspacePrivate::MoveAct]->setEnabled(false);
02015         actions[QWorkspacePrivate::ResizeAct]->setEnabled(false);
02016         actions[QWorkspacePrivate::MinimizeAct]->setEnabled(false);
02017         actions[QWorkspacePrivate::RestoreAct]->setEnabled(true);
02018     }
02019     if (active->shademode) {
02020         actions[QWorkspacePrivate::ShadeAct]->setIcon(
02021             QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarUnshadeButton)));
02022         actions[QWorkspacePrivate::ShadeAct]->setText(QWorkspace::tr("&Unshade"));
02023     } else {
02024         actions[QWorkspacePrivate::ShadeAct]->setIcon(
02025             QIcon(q->style()->standardPixmap(QStyle::SP_TitleBarShadeButton)));
02026         actions[QWorkspacePrivate::ShadeAct]->setText(QWorkspace::tr("Sh&ade"));
02027     }
02028     actions[QWorkspacePrivate::StaysOnTopAct]->setEnabled(!active->shademode && canResize);
02029     actions[QWorkspacePrivate::StaysOnTopAct]->setChecked(
02030         (active->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint));
02031 }
02032 
02033 void QWorkspacePrivate::_q_operationMenuActivated(QAction *action)
02034 {
02035     if (!active)
02036         return;
02037     if(action == actions[QWorkspacePrivate::RestoreAct]) {
02038         active->showNormal();
02039     } else if(action == actions[QWorkspacePrivate::MoveAct]) {
02040         active->doMove();
02041     } else if(action == actions[QWorkspacePrivate::ResizeAct]) {
02042         if (active->shademode)
02043             active->showShaded();
02044         active->doResize();
02045     } else if(action == actions[QWorkspacePrivate::MinimizeAct]) {
02046         active->showMinimized();
02047     } else if(action == actions[QWorkspacePrivate::MaximizeAct]) {
02048         active->showMaximized();
02049     } else if(action == actions[QWorkspacePrivate::ShadeAct]) {
02050         active->showShaded();
02051     } else if(action == actions[QWorkspacePrivate::StaysOnTopAct]) {
02052         if(QWidget* w = active->windowWidget()) {
02053             if ((w->windowFlags() & Qt::WindowStaysOnTopHint)) {
02054                 w->overrideWindowFlags(w->windowFlags() & ~Qt::WindowStaysOnTopHint);
02055             } else {
02056                 w->overrideWindowFlags(w->windowFlags() | Qt::WindowStaysOnTopHint);
02057                 w->parentWidget()->raise();
02058             }
02059         }
02060     }
02061 }
02062 
02063 
02064 void QWorkspacePrivate::hideChild(QWorkspaceChild *c)
02065 {
02066     Q_Q(QWorkspace);
02067 
02068 //     bool updatesEnabled = q->updatesEnabled();
02069 //     q->setUpdatesEnabled(false);
02070     focus.removeAll(c);
02071     QRect restore;
02072     if (maxWindow == c)
02073         restore = maxRestore;
02074     if (active == c) {
02075         q->setFocus();
02076         q->activatePreviousWindow();
02077     }
02078     if (active == c)
02079         activateWindow(0);
02080     if (maxWindow == c) {
02081         hideMaximizeControls();
02082         maxWindow = 0;
02083     }
02084     c->hide();
02085     if (!restore.isEmpty())
02086         c->setGeometry(restore);
02087 //     q->setUpdatesEnabled(updatesEnabled);
02088 }
02089 
02096 void QWorkspace::activateNextWindow()
02097 {
02098     Q_D(QWorkspace);
02099 
02100     if (d->focus.isEmpty())
02101         return;
02102     if (!d->active) {
02103         if (d->focus.first())
02104             d->activateWindow(d->focus.first()->windowWidget(), false);
02105         return;
02106     }
02107 
02108     int a = d->focus.indexOf(d->active) + 1;
02109 
02110     a = a % d->focus.count();
02111 
02112     if (d->focus.at(a))
02113         d->activateWindow(d->focus.at(a)->windowWidget(), false);
02114     else
02115         d->activateWindow(0);
02116 }
02117 
02124 void QWorkspace::activatePreviousWindow()
02125 {
02126     Q_D(QWorkspace);
02127 
02128     if (d->focus.isEmpty())
02129         return;
02130     if (!d->active) {
02131         if (d->focus.last())
02132             d->activateWindow(d->focus.first()->windowWidget(), false);
02133         else
02134             d->activateWindow(0);
02135         return;
02136     }
02137 
02138     int a = d->focus.indexOf(d->active) - 1;
02139     if (a < 0)
02140         a = d->focus.count()-1;
02141 
02142     if (d->focus.at(a))
02143         d->activateWindow(d->focus.at(a)->windowWidget(), false);
02144     else
02145         d->activateWindow(0);
02146 }
02147 
02148 
02164 void QWorkspace::cascade()
02165 {
02166     Q_D(QWorkspace);
02167     blockSignals(true);
02168     if  (d->maxWindow)
02169         d->maxWindow->showNormal();
02170 
02171     if (d->vbar) {
02172         d->vbar->blockSignals(true);
02173         d->vbar->setValue(0);
02174         d->vbar->blockSignals(false);
02175         d->hbar->blockSignals(true);
02176         d->hbar->setValue(0);
02177         d->hbar->blockSignals(false);
02178         d->_q_scrollBarChanged();
02179     }
02180 
02181     const int xoffset = 13;
02182     const int yoffset = 20;
02183 
02184     // make a list of all relevant mdi clients
02185     QList<QWorkspaceChild *> widgets;
02186     QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
02187     QWorkspaceChild* wc = 0;
02188 
02189     for (it = d->focus.begin(); it != d->focus.end(); ++it) {
02190         wc = *it;
02191         if (wc->windowWidget()->isVisibleTo(this) && !(wc->titlebar && wc->titlebar->isTool()))
02192             widgets.append(wc);
02193     }
02194 
02195     int x = 0;
02196     int y = 0;
02197 
02198     it = widgets.begin();
02199     while (it != widgets.end()) {
02200         QWorkspaceChild *child = *it;
02201         ++it;
02202 
02203         QSize prefSize = child->windowWidget()->sizeHint().expandedTo(qSmartMinSize(child->windowWidget()));
02204         if (!prefSize.isValid())
02205             prefSize = child->windowWidget()->size();
02206         prefSize = prefSize.expandedTo(qSmartMinSize(child->windowWidget()));
02207         if (prefSize.isValid())
02208             prefSize += QSize(child->baseSize().width(), child->baseSize().height());
02209 
02210         int w = prefSize.width();
02211         int h = prefSize.height();
02212 
02213         child->showNormal();
02214         if (y + h > height())
02215             y = 0;
02216         if (x + w > width())
02217             x = 0;
02218         child->setGeometry(x, y, w, h);
02219         x += xoffset;
02220         y += yoffset;
02221         child->internalRaise();
02222     }
02223     d->updateWorkspace();
02224     blockSignals(false);
02225 }
02226 
02232 void QWorkspace::tile()
02233 {
02234     Q_D(QWorkspace);
02235     blockSignals(true);
02236     QWidget *oldActive = d->active ? d->active->windowWidget() : 0;
02237     if  (d->maxWindow)
02238         d->maxWindow->showNormal();
02239 
02240     if (d->vbar) {
02241         d->vbar->blockSignals(true);
02242         d->vbar->setValue(0);
02243         d->vbar->blockSignals(false);
02244         d->hbar->blockSignals(true);
02245         d->hbar->setValue(0);
02246         d->hbar->blockSignals(false);
02247         d->_q_scrollBarChanged();
02248     }
02249 
02250     int rows = 1;
02251     int cols = 1;
02252     int n = 0;
02253     QWorkspaceChild* c;
02254 
02255     QList<QWorkspaceChild *>::Iterator it(d->windows.begin());
02256     while (it != d->windows.end()) {
02257         c = *it;
02258         ++it;
02259         if (!c->windowWidget()->isHidden()
02260             && !(c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)
02261             && !c->iconw)
02262             n++;
02263     }
02264 
02265     while (rows * cols < n) {
02266         if (cols <= rows)
02267             cols++;
02268         else
02269             rows++;
02270     }
02271     int add = cols * rows - n;
02272     bool* used = new bool[cols*rows];
02273     for (int i = 0; i < rows*cols; i++)
02274         used[i] = false;
02275 
02276     int row = 0;
02277     int col = 0;
02278     int w = width() / cols;
02279     int h = height() / rows;
02280 
02281     it = d->windows.begin();
02282     while (it != d->windows.end()) {
02283         c = *it;
02284         ++it;
02285         if (c->iconw || c->windowWidget()->isHidden() || (c->titlebar && c->titlebar->isTool()))
02286             continue;
02287         if (!row && !col) {
02288             w -= c->baseSize().width();
02289             h -= c->baseSize().height();
02290         }
02291         if ((c->windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
02292             QPoint p = c->pos();
02293             if (p.x()+c->width() < 0)
02294                 p.setX(0);
02295             if (p.x() > width())
02296                 p.setX(width() - c->width());
02297             if (p.y() + 10 < 0)
02298                 p.setY(0);
02299             if (p.y() > height())
02300                 p.setY(height() - c->height());
02301 
02302             if (p != c->pos())
02303                 c->QWidget::move(p);
02304         } else {
02305             c->showNormal();
02306             used[row*cols+col] = true;
02307             QSize sz(w, h);
02308             QSize bsize(c->baseSize());
02309             sz = sz.expandedTo(c->windowWidget()->minimumSize()).boundedTo(c->windowWidget()->maximumSize());
02310             sz += bsize;
02311 
02312       if ( add ) {
02313                 if (sz.height() == h + bsize.height()) // no relevant constrains
02314                     sz.rheight() *= 2;
02315     used[(row+1)*cols+col] = true;
02316     add--;
02317       }
02318 
02319             c->setGeometry(col*w + col*bsize.width(), row*h + row*bsize.height(), sz.width(), sz.height());
02320 
02321             while(row < rows && col < cols && used[row*cols+col]) {
02322                 col++;
02323                 if (col == cols) {
02324                     col = 0;
02325                     row++;
02326                 }
02327             }
02328         }
02329     }
02330     delete [] used;
02331 
02332     d->activateWindow(oldActive);
02333     d->updateWorkspace();
02334     blockSignals(false);
02335 }
02336 
02342 void QWorkspace::arrangeIcons()
02343 {
02344     Q_D(QWorkspace);
02345 
02346     QRect cr = d->updateWorkspace();
02347     int x = 0;
02348     int y = -1;
02349 
02350     QList<QWidget *>::Iterator it(d->icons.begin());
02351     while (it != d->icons.end()) {
02352         QWidget* i = *it;
02353         if (y == -1)
02354             y = cr.height() - i->height();
02355         if (x > 0 && x + i->width() > cr.width()) {
02356             x = 0;
02357             y -= i->height();
02358         }
02359         i->move(x, y);
02360         x += i->width();
02361         ++it;
02362     }
02363     d->updateWorkspace();
02364 }
02365 
02366 
02367 QWorkspaceChild::QWorkspaceChild(QWidget* window, QWorkspace *parent, Qt::WindowFlags flags)
02368     : QWidget(parent,
02369              Qt::FramelessWindowHint | Qt::SubWindow)
02370 {
02371     setAttribute(Qt::WA_DeleteOnClose);
02372     setAttribute(Qt::WA_NoMousePropagation);
02373     setMouseTracking(true);
02374     act = false;
02375     iconw = 0;
02376     shademode = false;
02377     titlebar = 0;
02378     setAutoFillBackground(true);
02379 
02380     setBackgroundRole(QPalette::Window);
02381     if (window) {
02382         if (flags)
02383             window->setParent(this, flags & ~Qt::WindowType_Mask);
02384         else
02385             window->setParent(this);
02386     }
02387 
02388     if (window && (flags & (Qt::WindowTitleHint
02389           | Qt::WindowSystemMenuHint
02390           | Qt::WindowMinimizeButtonHint
02391           | Qt::WindowMaximizeButtonHint
02392           | Qt::WindowContextHelpButtonHint))) {
02393         titlebar = new QWorkspaceTitleBar(window, this, flags);
02394         connect(titlebar, SIGNAL(doActivate()),
02395                  this, SLOT(activate()));
02396         connect(titlebar, SIGNAL(doClose()),
02397                  window, SLOT(close()));
02398         connect(titlebar, SIGNAL(doMinimize()),
02399                  this, SLOT(showMinimized()));
02400         connect(titlebar, SIGNAL(doNormal()),
02401                  this, SLOT(showNormal()));
02402         connect(titlebar, SIGNAL(doMaximize()),
02403                  this, SLOT(showMaximized()));
02404         connect(titlebar, SIGNAL(popupOperationMenu(QPoint)),
02405                  this, SIGNAL(popupOperationMenu(QPoint)));
02406         connect(titlebar, SIGNAL(showOperationMenu()),
02407                  this, SIGNAL(showOperationMenu()));
02408         connect(titlebar, SIGNAL(doShade()),
02409                  this, SLOT(showShaded()));
02410         connect(titlebar, SIGNAL(doubleClicked()),
02411                  this, SLOT(titleBarDoubleClicked()));
02412     }
02413 
02414     setMinimumSize(128, 0);
02415     int fw =  style()->pixelMetric(QStyle::PM_MDIFrameWidth, 0, this);
02416     setContentsMargins(fw, fw, fw, fw);
02417 
02418     childWidget = window;
02419     if (!childWidget)
02420         return;
02421 
02422     setWindowTitle(childWidget->windowTitle());
02423 
02424     QPoint p;
02425     QSize s;
02426     QSize cs;
02427 
02428     bool hasBeenResized = childWidget->testAttribute(Qt::WA_Resized);
02429 
02430     if (!hasBeenResized)
02431         cs = childWidget->sizeHint().expandedTo(childWidget->minimumSizeHint()).expandedTo(childWidget->minimumSize()).boundedTo(childWidget->maximumSize());
02432     else
02433         cs = childWidget->size();
02434 
02435     windowSize = cs;
02436 
02437     int th = titlebar ? titlebar->sizeHint().height() : 0;
02438     if (titlebar) {
02439         if (!childWidget->windowIcon().isNull())
02440             titlebar->setWindowIcon(childWidget->windowIcon());
02441 
02442         if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
02443             th -= contentsRect().y();
02444 
02445         p = QPoint(contentsRect().x(),
02446                     th + contentsRect().y());
02447         s = QSize(cs.width() + 2*frameWidth(),
02448                    cs.height() + 2*frameWidth() + th);
02449     } else {
02450         p = QPoint(contentsRect().x(), contentsRect().y());
02451         s = QSize(cs.width() + 2*frameWidth(),
02452                    cs.height() + 2*frameWidth());
02453     }
02454 
02455     childWidget->move(p);
02456     resize(s);
02457 
02458     childWidget->installEventFilter(this);
02459 
02460     widgetResizeHandler = new QWidgetResizeHandler(this, window);
02461     widgetResizeHandler->setSizeProtection(!parent->scrollBarsEnabled());
02462     widgetResizeHandler->setFrameWidth(frameWidth());
02463     connect(widgetResizeHandler, SIGNAL(activate()),
02464              this, SLOT(activate()));
02465     if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
02466         widgetResizeHandler->setExtraHeight(th + contentsRect().y() - 2*frameWidth());
02467     else
02468         widgetResizeHandler->setExtraHeight(th + contentsRect().y() - frameWidth());
02469     if (childWidget->minimumSize() == childWidget->maximumSize())
02470         widgetResizeHandler->setActive(QWidgetResizeHandler::Resize, false);
02471     setBaseSize(baseSize());
02472 }
02473 
02474 QWorkspaceChild::~QWorkspaceChild()
02475 {
02476     if (iconw)
02477         delete iconw->parentWidget();
02478 
02479     QWorkspace *workspace = qobject_cast<QWorkspace*>(parentWidget());
02480     if (workspace) {
02481         workspace->d_func()->focus.removeAll(this);
02482         if (workspace->d_func()->active == this)
02483             workspace->activatePreviousWindow();
02484         if (workspace->d_func()->active == this)
02485             workspace->d_func()->activateWindow(0);
02486         if (workspace->d_func()->maxWindow == this) {
02487             workspace->d_func()->hideMaximizeControls();
02488             workspace->d_func()->maxWindow = 0;
02489         }
02490     }
02491 }
02492 
02493 void QWorkspaceChild::moveEvent(QMoveEvent *)
02494 {
02495     ((QWorkspace*)parentWidget())->d_func()->updateWorkspace();
02496 }
02497 
02498 void QWorkspaceChild::resizeEvent(QResizeEvent *)
02499 {
02500     bool wasMax = isMaximized();
02501     QRect r = contentsRect();
02502     QRect cr;
02503 
02504     updateMask();
02505 
02506     if (titlebar) {
02507         int th = titlebar->sizeHint().height();
02508         QRect tbrect(0, 0, width(), th);
02509         if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
02510             tbrect = QRect(r.x(), r.y(), r.width(), th);
02511         titlebar->setGeometry(tbrect);
02512 
02513         if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
02514             th -= frameWidth();
02515         cr = QRect(r.x(), r.y() + th + (shademode ? (frameWidth() * 3) : 0),
02516                     r.width(), r.height() - th);
02517     } else {
02518         cr = r;
02519     }
02520 
02521     if (!childWidget)
02522         return;
02523 
02524     bool doContentsResize = (windowSize == childWidget->size()
02525                              || !(childWidget->testAttribute(Qt::WA_Resized) && childWidget->testAttribute(Qt::WA_PendingResizeEvent))
02526                              ||childWidget->isMaximized());
02527 
02528     windowSize = cr.size();
02529     childWidget->move(cr.topLeft());
02530     if (doContentsResize)
02531         childWidget->resize(cr.size());
02532     ((QWorkspace*)parentWidget())->d_func()->updateWorkspace();
02533 
02534     if (wasMax) {
02535         overrideWindowState(Qt::WindowMaximized);
02536         childWidget->overrideWindowState(Qt::WindowMaximized);
02537     }
02538 }
02539 
02540 QSize QWorkspaceChild::baseSize() const
02541 {
02542     int th = titlebar ? titlebar->sizeHint().height() : 0;
02543     if (style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar))
02544         th -= frameWidth();
02545     return QSize(2*frameWidth(), 2*frameWidth() + th);
02546 }
02547 
02548 QSize QWorkspaceChild::sizeHint() const
02549 {
02550     if (!childWidget)
02551         return QWidget::sizeHint() + baseSize();
02552 
02553     QSize prefSize = windowWidget()->sizeHint().expandedTo(windowWidget()->minimumSizeHint());
02554     prefSize = prefSize.expandedTo(windowWidget()->minimumSize()).boundedTo(windowWidget()->maximumSize());
02555     prefSize += baseSize();
02556 
02557     return prefSize;
02558 }
02559 
02560 QSize QWorkspaceChild::minimumSizeHint() const
02561 {
02562     if (!childWidget)
02563         return QWidget::minimumSizeHint() + baseSize();
02564     QSize s = childWidget->minimumSize();
02565     if (s.isEmpty())
02566         s = childWidget->minimumSizeHint();
02567     return s + baseSize();
02568 }
02569 
02570 void QWorkspaceChild::activate()
02571 {
02572     ((QWorkspace*)parentWidget())->d_func()->activateWindow(windowWidget());
02573 }
02574 
02575 bool QWorkspaceChild::eventFilter(QObject * o, QEvent * e)
02576 {
02577     if (!isActive()
02578         && (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::FocusIn)) {
02579         if (iconw) {
02580             ((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
02581             if (iconw) {
02582                 ((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
02583                 delete iconw->parentWidget();
02584                 iconw = 0;
02585             }
02586         }
02587         activate();
02588     }
02589 
02590     // for all widgets except the window, that's the only thing we
02591     // process, and if we have no childWidget we skip totally
02592     if (o != childWidget || childWidget == 0)
02593         return false;
02594 
02595     switch (e->type()) {
02596     case QEvent::ShowToParent:
02597         if (((QWorkspace*)parentWidget())->d_func()->focus.indexOf(this) < 0)
02598             ((QWorkspace*)parentWidget())->d_func()->focus.append(this);
02599 
02600         if (windowWidget() && (windowWidget()->windowFlags() & Qt::WindowStaysOnTopHint)) {
02601             internalRaise();
02602             show();
02603         }
02604         ((QWorkspace*)parentWidget())->d_func()->showWindow(windowWidget());
02605         break;
02606     case QEvent::WindowStateChange: {
02607         if (static_cast<QWindowStateChangeEvent*>(e)->isOverride())
02608             break;
02609         Qt::WindowStates state = windowWidget()->windowState();
02610 
02611         if (state & Qt::WindowMinimized) {
02612             ((QWorkspace*)parentWidget())->d_func()->minimizeWindow(windowWidget());
02613         } else if (state & Qt::WindowMaximized) {
02614             if (windowWidget()->maximumSize().isValid() &&
02615                 (windowWidget()->maximumWidth() < parentWidget()->width() ||
02616                  windowWidget()->maximumHeight() < parentWidget()->height())) {
02617                 windowWidget()->resize(windowWidget()->maximumSize());
02618                 windowWidget()->overrideWindowState(Qt::WindowNoState);
02619                 if (titlebar)
02620                     titlebar->update();
02621                 break;
02622             }
02623             if ((windowWidget()->windowFlags() & Qt::WindowMaximizeButtonHint))
02624                 ((QWorkspace*)parentWidget())->d_func()->maximizeWindow(windowWidget());
02625             else
02626                 ((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
02627         } else {
02628             ((QWorkspace*)parentWidget())->d_func()->normalizeWindow(windowWidget());
02629             if (iconw) {
02630                 ((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
02631                 delete iconw->parentWidget();
02632             }
02633         }
02634     } break;
02635     case QEvent::HideToParent:
02636     {
02637         QWidget * w = iconw;
02638         if (w && (w = w->parentWidget())) {
02639             ((QWorkspace*)parentWidget())->d_func()->removeIcon(w);
02640             delete w;
02641         }
02642         ((QWorkspace*)parentWidget())->d_func()->hideChild(this);
02643     } break;
02644     case QEvent::WindowIconChange:
02645         {
02646             QWorkspace* ws = (QWorkspace*)parentWidget();
02647             if (ws->d_func()->maxtools && ws->d_func()->maxWindow == this) {
02648                 int iconSize = ws->d_func()->maxtools->size().height();
02649                 ws->d_func()->maxtools->setPixmap(childWidget->windowIcon().pixmap(QSize(iconSize, iconSize)));
02650             }
02651         }
02652         // fall through
02653     case QEvent::WindowTitleChange:
02654         setWindowTitle(windowWidget()->windowTitle());
02655         if (titlebar)
02656             titlebar->update();
02657         if (iconw)
02658             iconw->update();
02659         break;
02660     case QEvent::ModifiedChange:
02661         setWindowModified(windowWidget()->isWindowModified());
02662         if (titlebar)
02663             titlebar->update();
02664         if (iconw)
02665             iconw->update();
02666         break;
02667     case QEvent::Resize:
02668         {
02669             QResizeEvent* re = (QResizeEvent*)e;
02670             if (re->size() != windowSize && !shademode) {
02671                 resize(re->size() + baseSize());
02672                 childWidget->update(); //workaround
02673             }
02674         }
02675         break;
02676 
02677     case QEvent::WindowDeactivate:
02678         if (titlebar && titlebar->isActive()) {
02679             update();
02680         }
02681         break;
02682 
02683     case QEvent::WindowActivate:
02684         if (titlebar && titlebar->isActive()) {
02685             update();
02686         }
02687         break;
02688 
02689     default:
02690         break;
02691     }
02692 
02693     return QWidget::eventFilter(o, e);
02694 }
02695 
02696 void QWorkspaceChild::childEvent(QChildEvent* e)
02697 {
02698     if (e->type() == QEvent::ChildRemoved && e->child() == childWidget) {
02699         childWidget = 0;
02700         if (iconw) {
02701             ((QWorkspace*)parentWidget())->d_func()->removeIcon(iconw->parentWidget());
02702             delete iconw->parentWidget();
02703         }
02704         close();
02705     }
02706 }
02707 
02708 
02709 void QWorkspaceChild::doResize()
02710 {
02711     widgetResizeHandler->doResize();
02712 }
02713 
02714 void QWorkspaceChild::doMove()
02715 {
02716     widgetResizeHandler->doMove();
02717 }
02718 
02719 void QWorkspaceChild::enterEvent(QEvent *)
02720 {
02721 }
02722 
02723 void QWorkspaceChild::leaveEvent(QEvent *)
02724 {
02725 #ifndef QT_NO_CURSOR
02726     if (!widgetResizeHandler->isButtonDown())
02727         setCursor(Qt::ArrowCursor);
02728 #endif
02729 }
02730 
02731 void QWorkspaceChild::paintEvent(QPaintEvent *)
02732 {
02733     QPainter p(this);
02734     QStyleOptionFrame opt;
02735     opt.rect = rect();
02736     opt.palette = palette();
02737     opt.state = QStyle::State_None;
02738     opt.lineWidth = style()->pixelMetric(QStyle::PM_MDIFrameWidth, 0, this);
02739     opt.midLineWidth = 1;
02740 
02741     if (titlebar && titlebar->isActive() && isActiveWindow())
02742         opt.state |= QStyle::State_Active;
02743 
02744     style()->drawPrimitive(QStyle::PE_FrameWindow, &opt, &p, this);
02745 }
02746 
02747 void QWorkspaceChild::changeEvent(QEvent *ev)
02748 {
02749     if(ev->type() == QEvent::StyleChange) {
02750         resizeEvent(0);
02751         if (iconw) {
02752             QFrame *frame = qobject_cast<QFrame*>(iconw->parentWidget());
02753             Q_ASSERT(frame);
02754             if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar)) {
02755                 frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
02756                 frame->resize(196+2*frame->frameWidth(), 20 + 2*frame->frameWidth());
02757             } else {
02758                 frame->resize(196, 20);
02759             }
02760         }
02761         updateMask();
02762     }
02763     QWidget::changeEvent(ev);
02764 }
02765 
02766 void QWorkspaceChild::setActive(bool b)
02767 {
02768     if (!childWidget)
02769         return;
02770 
02771     bool hasFocus = isChildOf(window()->focusWidget(), this);
02772     if (act == b && (act == hasFocus))
02773         return;
02774 
02775     act = b;
02776 
02777     if (titlebar)
02778         titlebar->setActive(act);
02779     if (iconw)
02780         iconw->setActive(act);
02781     update();
02782 
02783     QList<QWidget*> wl = qFindChildren<QWidget*>(childWidget);
02784     if (act) {
02785         for (int i = 0; i < wl.size(); ++i) {
02786             QWidget *w = wl.at(i);
02787             w->removeEventFilter(this);
02788         }
02789         if (!hasFocus) {
02790             QWidget *lastfocusw = childWidget->focusWidget();
02791             if (lastfocusw && lastfocusw->focusPolicy() != Qt::NoFocus) {
02792                 lastfocusw->setFocus();
02793             } else if (childWidget->focusPolicy() != Qt::NoFocus) {
02794                 childWidget->setFocus();
02795             } else {
02796                 // find something, anything, that accepts focus, and use that.
02797                 for (int i = 0; i < wl.size(); ++i) {
02798                     QWidget *w = wl.at(i);
02799                     if(w->focusPolicy() != Qt::NoFocus) {
02800                         w->setFocus();
02801                         hasFocus = true;
02802                         break;
02803                     }
02804                 }
02805                 if (!hasFocus)
02806                     setFocus();
02807             }
02808         }
02809     } else {
02810         for (int i = 0; i < wl.size(); ++i) {
02811             QWidget *w = wl.at(i);
02812             w->removeEventFilter(this);
02813             w->installEventFilter(this);
02814         }
02815     }
02816 }
02817 
02818 bool QWorkspaceChild::isActive() const
02819 {
02820     return act;
02821 }
02822 
02823 QWidget* QWorkspaceChild::windowWidget() const
02824 {
02825     return childWidget;
02826 }
02827 
02828 bool QWorkspaceChild::isWindowOrIconVisible() const
02829 {
02830     return childWidget && (!isHidden()  || (iconw && !iconw->isHidden()));
02831 }
02832 
02833 void QWorkspaceChild::updateMask()
02834 {
02835     QStyleOptionTitleBar titleBarOptions;
02836     titleBarOptions.rect = rect();
02837     titleBarOptions.titleBarFlags = windowFlags();
02838     titleBarOptions.titleBarState = windowState();
02839 
02840     QStyleHintReturnMask frameMask;
02841     if (style()->styleHint(QStyle::SH_WindowFrame_Mask, &titleBarOptions, this, &frameMask)) {
02842         setMask(frameMask.region);
02843     } else if (!mask().isEmpty()) {
02844         clearMask();
02845     }
02846 
02847     if (iconw) {
02848         QFrame *frame = qobject_cast<QFrame *>(iconw->parentWidget());
02849         Q_ASSERT(frame);
02850 
02851         titleBarOptions.rect = frame->rect();
02852         titleBarOptions.titleBarFlags = frame->windowFlags();
02853         titleBarOptions.titleBarState = frame->windowState() | Qt::WindowMinimized;
02854         if (style()->styleHint(QStyle::SH_WindowFrame_Mask, &titleBarOptions, frame, &frameMask)) {
02855             frame->setMask(frameMask.region);
02856         } else if (!frame->mask().isEmpty()) {
02857             frame->clearMask();
02858         }
02859     }
02860 }
02861 
02862 QWidget* QWorkspaceChild::iconWidget() const
02863 {
02864     if (!iconw) {
02865         QWorkspaceChild* that = (QWorkspaceChild*) this;
02866 
02867         QFrame* frame = new QFrame(that, Qt::Window);
02868         QVBoxLayout *vbox = new QVBoxLayout(frame);
02869         vbox->setMargin(0);
02870         QWorkspaceTitleBar *tb = new QWorkspaceTitleBar(windowWidget(), frame);
02871         vbox->addWidget(tb);
02872         tb->setObjectName(QLatin1String("_workspacechild_icon_"));
02873         QStyleOptionTitleBar opt = tb->getStyleOption();
02874         int th = style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, tb);
02875         int iconSize = style()->pixelMetric(QStyle::PM_MDIMinimizedWidth, 0, this);
02876         if (!style()->styleHint(QStyle::SH_TitleBar_NoBorder, 0, titlebar)) {
02877             frame->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
02878             frame->resize(iconSize+2*frame->frameWidth(), th+2*frame->frameWidth());
02879         } else {
02880             frame->resize(iconSize, th);
02881         }
02882 
02883         that->iconw = tb;
02884         that->updateMask();
02885         iconw->setActive(isActive());
02886 
02887         connect(iconw, SIGNAL(doActivate()),
02888                  this, SLOT(activate()));
02889         connect(iconw, SIGNAL(doClose()),
02890                  windowWidget(), SLOT(close()));
02891         connect(iconw, SIGNAL(doNormal()),
02892                  this, SLOT(showNormal()));
02893         connect(iconw, SIGNAL(doMaximize()),
02894                  this, SLOT(showMaximized()));
02895         connect(