src/gui/graphicsview/qgraphicswidget_p.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qglobal.h"
       
    43 
       
    44 #ifndef QT_NO_GRAPHICSVIEW
       
    45 
       
    46 #include <QtCore/qdebug.h>
       
    47 #include "qgraphicswidget_p.h"
       
    48 #include "qgraphicslayout.h"
       
    49 #include "qgraphicsscene_p.h"
       
    50 #include <QtGui/qapplication.h>
       
    51 #include <QtGui/qgraphicsscene.h>
       
    52 #include <QtGui/qstyleoption.h>
       
    53 #include <QtGui/QStyleOptionTitleBar>
       
    54 #include <QtGui/QGraphicsSceneMouseEvent>
       
    55 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
    56 # include <QMacStyle>
       
    57 #endif
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags)
       
    62 {
       
    63     Q_Q(QGraphicsWidget);
       
    64 
       
    65     attributes = 0;
       
    66     isWidget = 1; // QGraphicsItem::isWidget() returns true.
       
    67     focusNext = focusPrev = q;
       
    68     focusPolicy = Qt::NoFocus;
       
    69 
       
    70     adjustWindowFlags(&wFlags);
       
    71     windowFlags = wFlags;
       
    72 
       
    73     q->setParentItem(parentItem);
       
    74     q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
       
    75     q->setGraphicsItem(q);
       
    76 
       
    77     resolveLayoutDirection();
       
    78     q->unsetWindowFrameMargins();
       
    79     q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
       
    80     q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
       
    81 }
       
    82 
       
    83 qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
       
    84 {
       
    85     Q_Q(const QGraphicsWidget);
       
    86     int height = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
       
    87 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
    88     if (qobject_cast<QMacStyle*>(q->style())) {
       
    89         height -=4;
       
    90     }
       
    91 #endif
       
    92     return (qreal)height;
       
    93 }
       
    94 
       
    95 /*!
       
    96     \internal
       
    97 */
       
    98 QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
       
    99 {
       
   100     // Remove any lazily allocated data
       
   101     delete[] margins;
       
   102     delete[] windowFrameMargins;
       
   103     delete windowData;
       
   104 }
       
   105 
       
   106 /*!
       
   107     \internal
       
   108 
       
   109      Ensures that margins is allocated.
       
   110      This function must be called before any dereferencing.
       
   111 */
       
   112 void QGraphicsWidgetPrivate::ensureMargins() const
       
   113 {
       
   114     if (!margins) {
       
   115         margins = new qreal[4];
       
   116         for (int i = 0; i < 4; ++i)
       
   117             margins[i] = 0;
       
   118     }
       
   119 }
       
   120 
       
   121 /*!
       
   122     \internal
       
   123 
       
   124      Ensures that windowFrameMargins is allocated.
       
   125      This function must be called before any dereferencing.
       
   126 */
       
   127 void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
       
   128 {
       
   129     if (!windowFrameMargins) {
       
   130         windowFrameMargins = new qreal[4];
       
   131         for (int i = 0; i < 4; ++i)
       
   132             windowFrameMargins[i] = 0;
       
   133     }
       
   134 }
       
   135 
       
   136 /*!
       
   137     \internal
       
   138 
       
   139      Ensures that windowData is allocated.
       
   140      This function must be called before any dereferencing.
       
   141 */
       
   142 void QGraphicsWidgetPrivate::ensureWindowData()
       
   143 {
       
   144     if (!windowData)
       
   145         windowData = new WindowData;
       
   146 }
       
   147 
       
   148 void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette)
       
   149 {
       
   150     if (this->palette == palette && this->palette.resolve() == palette.resolve())
       
   151         return;
       
   152     updatePalette(palette);
       
   153 }
       
   154 
       
   155 void QGraphicsWidgetPrivate::resolvePalette(uint inheritedMask)
       
   156 {
       
   157     inheritedPaletteResolveMask = inheritedMask;
       
   158     QPalette naturalPalette = naturalWidgetPalette();
       
   159     QPalette resolvedPalette = palette.resolve(naturalPalette);
       
   160     updatePalette(resolvedPalette);
       
   161 }
       
   162 
       
   163 void QGraphicsWidgetPrivate::updatePalette(const QPalette &palette)
       
   164 {
       
   165     Q_Q(QGraphicsWidget);
       
   166     // Update local palette setting.
       
   167     this->palette = palette;
       
   168 
       
   169     // Calculate new mask.
       
   170     if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
       
   171         inheritedPaletteResolveMask = 0;
       
   172     int mask = palette.resolve() | inheritedPaletteResolveMask;
       
   173 
       
   174     // Propagate to children.
       
   175     for (int i = 0; i < children.size(); ++i) {
       
   176         QGraphicsItem *item = children.at(i);
       
   177         if (item->isWidget()) {
       
   178             QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
       
   179             if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
       
   180                 w->d_func()->resolvePalette(mask);
       
   181         } else {
       
   182             item->d_ptr->resolvePalette(mask);
       
   183         }
       
   184     }
       
   185 
       
   186     // Notify change.
       
   187     QEvent event(QEvent::PaletteChange);
       
   188     QApplication::sendEvent(q, &event);
       
   189 }
       
   190 
       
   191 void QGraphicsWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
       
   192 {
       
   193     Q_Q(QGraphicsWidget);
       
   194     if ((direction == Qt::RightToLeft) == (testAttribute(Qt::WA_RightToLeft)))
       
   195         return;
       
   196     q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
       
   197 
       
   198     // Propagate this change to all children.
       
   199     for (int i = 0; i < children.size(); ++i) {
       
   200         QGraphicsItem *item = children.at(i);
       
   201         if (item->isWidget()) {
       
   202             QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
       
   203             if (widget->parentWidget() && !widget->testAttribute(Qt::WA_SetLayoutDirection))
       
   204                 widget->d_func()->setLayoutDirection_helper(direction);
       
   205         }
       
   206     }
       
   207 
       
   208     // Send the notification event to this widget item.
       
   209     QEvent e(QEvent::LayoutDirectionChange);
       
   210     QApplication::sendEvent(q, &e);
       
   211 }
       
   212 
       
   213 void QGraphicsWidgetPrivate::resolveLayoutDirection()
       
   214 {
       
   215     Q_Q(QGraphicsWidget);
       
   216     if (q->testAttribute(Qt::WA_SetLayoutDirection)) {
       
   217         return;
       
   218     }
       
   219     if (QGraphicsWidget *parentWidget = q->parentWidget()) {
       
   220         setLayoutDirection_helper(parentWidget->layoutDirection());
       
   221     } else if (scene) {
       
   222         // ### shouldn't the scene have a layoutdirection really? how does
       
   223         // ### QGraphicsWidget get changes from QApplication::layoutDirection?
       
   224         setLayoutDirection_helper(QApplication::layoutDirection());
       
   225     } else {
       
   226         setLayoutDirection_helper(QApplication::layoutDirection());
       
   227     }
       
   228 }
       
   229 
       
   230 QPalette QGraphicsWidgetPrivate::naturalWidgetPalette() const
       
   231 {
       
   232     Q_Q(const QGraphicsWidget);
       
   233     QPalette palette;
       
   234     if (QGraphicsWidget *parent = q->parentWidget()) {
       
   235         palette = parent->palette();
       
   236     } else if (scene) {
       
   237         palette = scene->palette();
       
   238     }
       
   239     palette.resolve(0);
       
   240     return palette;
       
   241 }
       
   242 
       
   243 void QGraphicsWidgetPrivate::setFont_helper(const QFont &font)
       
   244 {
       
   245     if (this->font == font && this->font.resolve() == font.resolve())
       
   246         return;
       
   247     updateFont(font);
       
   248 }
       
   249 
       
   250 void QGraphicsWidgetPrivate::resolveFont(uint inheritedMask)
       
   251 {
       
   252     inheritedFontResolveMask = inheritedMask;
       
   253     QFont naturalFont = naturalWidgetFont();
       
   254     QFont resolvedFont = font.resolve(naturalFont);
       
   255     updateFont(resolvedFont);
       
   256 }
       
   257 
       
   258 void QGraphicsWidgetPrivate::updateFont(const QFont &font)
       
   259 {
       
   260     Q_Q(QGraphicsWidget);
       
   261     // Update the local font setting.
       
   262     this->font = font;
       
   263 
       
   264     // Calculate new mask.
       
   265     if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
       
   266         inheritedFontResolveMask = 0;
       
   267     int mask = font.resolve() | inheritedFontResolveMask;
       
   268 
       
   269     // Propagate to children.
       
   270     for (int i = 0; i < children.size(); ++i) {
       
   271         QGraphicsItem *item = children.at(i);
       
   272         if (item->isWidget()) {
       
   273             QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
       
   274             if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
       
   275                 w->d_func()->resolveFont(mask);
       
   276         } else {
       
   277             item->d_ptr->resolveFont(mask);
       
   278         }
       
   279     }
       
   280 
       
   281     if (!polished)
       
   282         return;
       
   283     // Notify change.
       
   284     QEvent event(QEvent::FontChange);
       
   285     QApplication::sendEvent(q, &event);
       
   286 }
       
   287 
       
   288 QFont QGraphicsWidgetPrivate::naturalWidgetFont() const
       
   289 {
       
   290     Q_Q(const QGraphicsWidget);
       
   291     QFont naturalFont; // ### no application font support
       
   292     if (QGraphicsWidget *parent = q->parentWidget()) {
       
   293         naturalFont = parent->font();
       
   294     } else if (scene) {
       
   295         naturalFont = scene->font();
       
   296     }
       
   297     naturalFont.resolve(0);
       
   298     return naturalFont;
       
   299 }
       
   300 
       
   301 void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *option)
       
   302 {
       
   303     Q_Q(QGraphicsWidget);
       
   304     ensureWindowData();
       
   305     q->initStyleOption(option);
       
   306     option->rect.setHeight(titleBarHeight(*option));
       
   307     option->titleBarFlags = windowFlags;
       
   308     option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
       
   309     option->activeSubControls = windowData->hoveredSubControl;
       
   310     bool isActive = q->isActiveWindow();
       
   311     if (isActive) {
       
   312         option->state |= QStyle::State_Active;
       
   313         option->titleBarState = Qt::WindowActive;
       
   314         option->titleBarState |= QStyle::State_Active;
       
   315     } else {
       
   316         option->state &= ~QStyle::State_Active;
       
   317         option->titleBarState = Qt::WindowNoState;
       
   318     }
       
   319     QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar");
       
   320     QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0);
       
   321     option->text = QFontMetrics(windowTitleFont).elidedText(
       
   322         windowData->windowTitle, Qt::ElideRight, textRect.width());
       
   323 }
       
   324 
       
   325 void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
       
   326 {
       
   327     bool customize =  (*flags & (Qt::CustomizeWindowHint
       
   328             | Qt::FramelessWindowHint
       
   329             | Qt::WindowTitleHint
       
   330             | Qt::WindowSystemMenuHint
       
   331             | Qt::WindowMinimizeButtonHint
       
   332             | Qt::WindowMaximizeButtonHint
       
   333             | Qt::WindowContextHelpButtonHint));
       
   334 
       
   335     uint type = (*flags & Qt::WindowType_Mask);
       
   336     if (customize)
       
   337         ;
       
   338     else if (type == Qt::Dialog || type == Qt::Sheet)
       
   339         *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint;
       
   340     else if (type == Qt::Tool)
       
   341         *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
       
   342     else if (type == Qt::Window || type == Qt::SubWindow)
       
   343         *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
       
   344                   | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
       
   345 }
       
   346 
       
   347 void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   348 {
       
   349     Q_Q(QGraphicsWidget);
       
   350     ensureWindowData();
       
   351     if (windowData->grabbedSection != Qt::NoSection) {
       
   352         if (windowData->grabbedSection == Qt::TitleBarArea) {
       
   353             windowData->buttonSunken = false;
       
   354             QStyleOptionTitleBar bar;
       
   355             initStyleOptionTitleBar(&bar);
       
   356             // make sure that the coordinates (rect and pos) we send to the style are positive.
       
   357             bar.rect = q->windowFrameRect().toRect();
       
   358             bar.rect.moveTo(0,0);
       
   359             bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
       
   360             QPointF pos = event->pos();
       
   361             if (windowFrameMargins) {
       
   362                 pos.rx() += windowFrameMargins[Left];
       
   363                 pos.ry() += windowFrameMargins[Top];
       
   364             }
       
   365             bar.subControls = QStyle::SC_TitleBarCloseButton;
       
   366             if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
       
   367                                            QStyle::SC_TitleBarCloseButton,
       
   368                                            event->widget()).contains(pos.toPoint())) {
       
   369                 q->close();
       
   370             }
       
   371         }
       
   372         if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
       
   373             windowData->grabbedSection = Qt::NoSection;
       
   374         event->accept();
       
   375     }
       
   376 }
       
   377 
       
   378 void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent *event)
       
   379 {
       
   380     Q_Q(QGraphicsWidget);
       
   381     if (event->button() != Qt::LeftButton)
       
   382         return;
       
   383 
       
   384     ensureWindowData();
       
   385     windowData->startGeometry = q->geometry();
       
   386     windowData->grabbedSection = q->windowFrameSectionAt(event->pos());
       
   387     ensureWindowData();
       
   388     if (windowData->grabbedSection == Qt::TitleBarArea
       
   389         && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
       
   390         windowData->buttonSunken = true;
       
   391         q->update();
       
   392     }
       
   393     event->setAccepted(windowData->grabbedSection != Qt::NoSection);
       
   394 }
       
   395 
       
   396 /*!
       
   397   Used to calculate the
       
   398   Precondition:
       
   399   \a widget should support either hfw or wfh
       
   400 
       
   401   If \a heightForWidth is set to false, this function will query the width for height
       
   402   instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted
       
   403   as minimum width and maximum width.
       
   404  */
       
   405 static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh,
       
   406                                    const QGraphicsWidget *widget,
       
   407                                    bool heightForWidth = true)
       
   408 {
       
   409     qreal minimumHeightForWidth = -1;
       
   410     const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy();
       
   411     const bool hasHFW = sp.hasHeightForWidth();
       
   412     if (hasHFW == heightForWidth) {
       
   413         minimumHeightForWidth = hasHFW
       
   414                                 ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
       
   415                                 : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width();    //"width" is here height!
       
   416     } else {
       
   417         // widthForHeight
       
   418         const qreal constraint = width;
       
   419         while (maxh - minh > 0.1) {
       
   420             qreal middle = minh + (maxh - minh)/2;
       
   421             // ### really bad, if we are a widget with a layout it will call
       
   422             // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call
       
   423             // sizeHint three times because of how the cache works
       
   424             qreal hfw = hasHFW
       
   425                         ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height()
       
   426                         : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width();
       
   427             if (hfw > constraint) {
       
   428                 minh = middle;
       
   429             } else if (hfw <= constraint) {
       
   430                 maxh = middle;
       
   431             }
       
   432         }
       
   433         minimumHeightForWidth = maxh;
       
   434     }
       
   435     return minimumHeightForWidth;
       
   436 }
       
   437 
       
   438 static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw,
       
   439                                    const QGraphicsWidget *widget)
       
   440 {
       
   441     return minimumHeightForWidth(height, minw, maxw, widget, false);
       
   442 }
       
   443 
       
   444 static QSizeF closestAcceptableSize(const QSizeF &proposed,
       
   445                                     const QGraphicsWidget *widget)
       
   446 {
       
   447     const QSizeF current = widget->size();
       
   448 
       
   449     qreal minw = proposed.width();
       
   450     qreal maxw = current.width();
       
   451     qreal minh = proposed.height();
       
   452     qreal maxh = current.height();
       
   453 
       
   454     qreal middlew = maxw;
       
   455     qreal middleh = maxh;
       
   456     qreal min_hfw;
       
   457     min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget);
       
   458 
       
   459     do {
       
   460         if (maxw - minw < 0.1) {
       
   461             // we still havent found anything, cut off binary search
       
   462             minw = maxw;
       
   463             minh = maxh;
       
   464         }
       
   465         middlew = minw + (maxw - minw)/2.0;
       
   466         middleh = minh + (maxh - minh)/2.0;
       
   467 
       
   468         min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
       
   469 
       
   470         if (min_hfw > middleh) {
       
   471             minw = middlew;
       
   472             minh = middleh;
       
   473         } else if (min_hfw <= middleh) {
       
   474             maxw = middlew;
       
   475             maxh = middleh;
       
   476         }
       
   477     } while (maxw != minw);
       
   478 
       
   479     min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
       
   480 
       
   481     QSizeF result;
       
   482     if (min_hfw < maxh) {
       
   483         result = QSizeF(middlew, min_hfw);
       
   484     } else {
       
   485         // Needed because of the cut-off we do above.
       
   486         result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh);
       
   487     }
       
   488     return result;
       
   489 }
       
   490 
       
   491 static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
       
   492                                               QRectF *rect, Qt::WindowFrameSection section,
       
   493                                               const QSizeF &min, const QSizeF &max,
       
   494                                               const QGraphicsWidget *widget)
       
   495 {
       
   496     const QRectF proposedRect = *rect;
       
   497     qreal width = qBound(min.width(), proposedRect.width(), max.width());
       
   498     qreal height = qBound(min.height(), proposedRect.height(), max.height());
       
   499 
       
   500     QSizePolicy sp = widget->sizePolicy();
       
   501     if (const QGraphicsLayout *l = widget->layout()) {
       
   502         sp = l->sizePolicy();
       
   503     }
       
   504     const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight();
       
   505 
       
   506     const bool widthChanged = proposedRect.width() < widget->size().width();
       
   507     const bool heightChanged = proposedRect.height() < widget->size().height();
       
   508 
       
   509     if (hasHFW) {
       
   510         if (widthChanged || heightChanged) {
       
   511             const qreal minh = min.height();
       
   512             const qreal maxh = max.height();
       
   513             const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget);
       
   514             if (proposedHFW > proposedRect.height()) {
       
   515                 QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
       
   516                 width = effectiveSize.width();
       
   517                 height = effectiveSize.height();
       
   518             }
       
   519         }
       
   520     }
       
   521 
       
   522     switch (section) {
       
   523     case Qt::LeftSection:
       
   524         rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
       
   525                       qRound(width), startGeometry.height());
       
   526         break;
       
   527     case Qt::TopLeftSection:
       
   528         rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height),
       
   529                       qRound(width), qRound(height));
       
   530         break;
       
   531     case Qt::TopSection:
       
   532         rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height),
       
   533                       startGeometry.width(), qRound(height));
       
   534         break;
       
   535     case Qt::TopRightSection:
       
   536         rect->setTop(rect->bottom() - qRound(height));
       
   537         rect->setWidth(qRound(width));
       
   538         break;
       
   539     case Qt::RightSection:
       
   540         rect->setWidth(qRound(width));
       
   541         break;
       
   542     case Qt::BottomRightSection:
       
   543         rect->setWidth(qRound(width));
       
   544         rect->setHeight(qRound(height));
       
   545         break;
       
   546     case Qt::BottomSection:
       
   547         rect->setHeight(qRound(height));
       
   548         break;
       
   549     case Qt::BottomLeftSection:
       
   550         rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
       
   551                       qRound(width), qRound(height));
       
   552         break;
       
   553     default:
       
   554         break;
       
   555     }
       
   556 }
       
   557 
       
   558 void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event)
       
   559 {
       
   560     Q_Q(QGraphicsWidget);
       
   561     ensureWindowData();
       
   562     if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
       
   563         return;
       
   564 
       
   565     QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos());
       
   566     QLineF parentDelta(q->mapToParent(delta.p1()), q->mapToParent(delta.p2()));
       
   567     QLineF parentXDelta(q->mapToParent(QPointF(delta.p1().x(), 0)), q->mapToParent(QPointF(delta.p2().x(), 0)));
       
   568     QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y())));
       
   569 
       
   570     QRectF newGeometry;
       
   571     switch (windowData->grabbedSection) {
       
   572     case Qt::LeftSection:
       
   573         newGeometry = QRectF(windowData->startGeometry.topLeft()
       
   574                              + QPointF(parentXDelta.dx(), parentXDelta.dy()),
       
   575                              windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
       
   576         break;
       
   577     case Qt::TopLeftSection:
       
   578         newGeometry = QRectF(windowData->startGeometry.topLeft()
       
   579                              + QPointF(parentDelta.dx(), parentDelta.dy()),
       
   580                              windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
       
   581         break;
       
   582     case Qt::TopSection:
       
   583         newGeometry = QRectF(windowData->startGeometry.topLeft()
       
   584                              + QPointF(parentYDelta.dx(), parentYDelta.dy()),
       
   585                              windowData->startGeometry.size() - QSizeF(0, delta.dy()));
       
   586         break;
       
   587     case Qt::TopRightSection:
       
   588         newGeometry = QRectF(windowData->startGeometry.topLeft()
       
   589                              + QPointF(parentYDelta.dx(), parentYDelta.dy()),
       
   590                              windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
       
   591         break;
       
   592     case Qt::RightSection:
       
   593         newGeometry = QRectF(windowData->startGeometry.topLeft(),
       
   594                              windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
       
   595         break;
       
   596     case Qt::BottomRightSection:
       
   597         newGeometry = QRectF(windowData->startGeometry.topLeft(),
       
   598                              windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
       
   599         break;
       
   600     case Qt::BottomSection:
       
   601         newGeometry = QRectF(windowData->startGeometry.topLeft(),
       
   602                              windowData->startGeometry.size() + QSizeF(0, delta.dy()));
       
   603         break;
       
   604     case Qt::BottomLeftSection:
       
   605         newGeometry = QRectF(windowData->startGeometry.topLeft()
       
   606                              + QPointF(parentXDelta.dx(), parentXDelta.dy()),
       
   607                              windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
       
   608         break;
       
   609     case Qt::TitleBarArea:
       
   610         newGeometry = QRectF(windowData->startGeometry.topLeft()
       
   611                              + QPointF(parentDelta.dx(), parentDelta.dy()),
       
   612                              windowData->startGeometry.size());
       
   613         break;
       
   614     case Qt::NoSection:
       
   615         break;
       
   616     }
       
   617 
       
   618     if (windowData->grabbedSection != Qt::NoSection) {
       
   619         _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
       
   620                                           windowData->grabbedSection,
       
   621                                           q->effectiveSizeHint(Qt::MinimumSize),
       
   622                                           q->effectiveSizeHint(Qt::MaximumSize),
       
   623                                           q);
       
   624         q->setGeometry(newGeometry);
       
   625     }
       
   626 }
       
   627 
       
   628 void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent *event)
       
   629 {
       
   630     Q_Q(QGraphicsWidget);
       
   631     if (!hasDecoration())
       
   632         return;
       
   633 
       
   634     ensureWindowData();
       
   635 
       
   636     if (q->rect().contains(event->pos())) {
       
   637         if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
       
   638             windowFrameHoverLeaveEvent(event);
       
   639         return;
       
   640     }
       
   641 
       
   642     bool wasMouseOver = windowData->buttonMouseOver;
       
   643     QRect oldButtonRect = windowData->buttonRect;
       
   644     windowData->buttonRect = QRect();
       
   645     windowData->buttonMouseOver = false;
       
   646     QPointF pos = event->pos();
       
   647     QStyleOptionTitleBar bar;
       
   648     // make sure that the coordinates (rect and pos) we send to the style are positive.
       
   649     if (windowFrameMargins) {
       
   650         pos.rx() += windowFrameMargins[Left];
       
   651         pos.ry() += windowFrameMargins[Top];
       
   652     }
       
   653     initStyleOptionTitleBar(&bar);
       
   654     bar.rect = q->windowFrameRect().toRect();
       
   655     bar.rect.moveTo(0,0);
       
   656     bar.rect.setHeight(int(titleBarHeight(bar)));
       
   657 
       
   658     Qt::CursorShape cursorShape = Qt::ArrowCursor;
       
   659     bool needsSetCursorCall = true;
       
   660     switch (q->windowFrameSectionAt(event->pos())) {
       
   661         case Qt::TopLeftSection:
       
   662         case Qt::BottomRightSection:
       
   663             cursorShape = Qt::SizeFDiagCursor;
       
   664             break;
       
   665         case Qt::TopRightSection:
       
   666         case Qt::BottomLeftSection:
       
   667             cursorShape = Qt::SizeBDiagCursor;
       
   668             break;
       
   669         case Qt::LeftSection:
       
   670         case Qt::RightSection:
       
   671             cursorShape = Qt::SizeHorCursor;
       
   672             break;
       
   673         case Qt::TopSection:
       
   674         case Qt::BottomSection:
       
   675             cursorShape = Qt::SizeVerCursor;
       
   676             break;
       
   677         case Qt::TitleBarArea:
       
   678             windowData->buttonRect = q->style()->subControlRect(
       
   679                 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
       
   680 #ifdef Q_WS_MAC
       
   681             // On mac we should hover if we are in the 'area' of the buttons
       
   682             windowData->buttonRect |= q->style()->subControlRect(
       
   683                 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
       
   684             windowData->buttonRect |= q->style()->subControlRect(
       
   685                 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
       
   686 #endif
       
   687             if (windowData->buttonRect.contains(pos.toPoint()))
       
   688                 windowData->buttonMouseOver = true;
       
   689             event->ignore();
       
   690             break;
       
   691         default:
       
   692             needsSetCursorCall = false;
       
   693             event->ignore();
       
   694         }
       
   695 #ifndef QT_NO_CURSOR
       
   696     if (needsSetCursorCall)
       
   697         q->setCursor(cursorShape);
       
   698 #endif
       
   699     // update buttons if we hover over them
       
   700     windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
       
   701     if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
       
   702         windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;
       
   703 
       
   704     if (windowData->buttonMouseOver != wasMouseOver) {
       
   705         if (!oldButtonRect.isNull())
       
   706             q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
       
   707         if (!windowData->buttonRect.isNull())
       
   708             q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
       
   709     }
       
   710 }
       
   711 
       
   712 void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event)
       
   713 {
       
   714     Q_UNUSED(event);
       
   715     Q_Q(QGraphicsWidget);
       
   716     if (hasDecoration()) {
       
   717         // ### restore the cursor, don't override it
       
   718 #ifndef QT_NO_CURSOR
       
   719         q->unsetCursor();
       
   720 #endif
       
   721 
       
   722         ensureWindowData();
       
   723 
       
   724         bool needsUpdate = false;
       
   725         if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton
       
   726             || windowData->buttonMouseOver)
       
   727             needsUpdate = true;
       
   728 
       
   729         // update the hover state (of buttons etc...)
       
   730         windowData->hoveredSubControl = QStyle::SC_None;
       
   731         windowData->buttonMouseOver = false;
       
   732         windowData->buttonRect = QRect();
       
   733         if (needsUpdate)
       
   734             q->update(windowData->buttonRect);
       
   735     }
       
   736 }
       
   737 
       
   738 bool QGraphicsWidgetPrivate::hasDecoration() const
       
   739 {
       
   740     return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint);
       
   741 }
       
   742 
       
   743 /**
       
   744  * is called after a reparent has taken place to fix up the focus chain(s)
       
   745  */
       
   746 void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene)
       
   747 {
       
   748     Q_Q(QGraphicsWidget);
       
   749 
       
   750     Q_ASSERT(focusNext && focusPrev);
       
   751 
       
   752     QGraphicsWidget *n = q;     //last one in 'new' list
       
   753     QGraphicsWidget *o = 0;     //last one in 'old' list
       
   754 
       
   755     QGraphicsWidget *w = focusNext;
       
   756 
       
   757     QGraphicsWidget *firstOld = 0;
       
   758     bool wasPreviousNew = true;
       
   759     
       
   760     while (w != q) {
       
   761         bool isCurrentNew = q->isAncestorOf(w);
       
   762         if (isCurrentNew) {
       
   763             if (!wasPreviousNew) {
       
   764                 n->d_func()->focusNext = w;
       
   765                 w->d_func()->focusPrev = n;
       
   766             }
       
   767             n = w;
       
   768         } else /*if (!isCurrentNew)*/ {
       
   769             if (wasPreviousNew) {
       
   770                 if (o) {
       
   771                     o->d_func()->focusNext = w;
       
   772                     w->d_func()->focusPrev = o;
       
   773                 } else {
       
   774                     firstOld = w;
       
   775                 }
       
   776             }
       
   777             o = w;
       
   778         }
       
   779         w = w->d_func()->focusNext;
       
   780         wasPreviousNew = isCurrentNew;
       
   781     }
       
   782 
       
   783     // repair the 'old' chain
       
   784     if (firstOld) {
       
   785         o->d_func()->focusNext = firstOld;
       
   786         firstOld->d_func()->focusPrev = o;
       
   787     }
       
   788 
       
   789     // update tabFocusFirst for oldScene if the item is going to be removed from oldScene
       
   790     if (newParent)
       
   791         newScene = newParent->scene();
       
   792     QGraphicsScene *oldScene = q->scene();
       
   793     if (oldScene && newScene != oldScene)
       
   794         oldScene->d_func()->tabFocusFirst = firstOld;
       
   795 
       
   796     QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0;
       
   797     QGraphicsWidget *topLevel = 0;
       
   798     if (topLevelItem && topLevelItem->isWidget())
       
   799         topLevel = static_cast<QGraphicsWidget *>(topLevelItem);
       
   800 
       
   801     if (topLevel && newParent) {
       
   802         QGraphicsWidget *last = topLevel->d_func()->focusPrev;
       
   803         // link last with new chain
       
   804         last->d_func()->focusNext = q;
       
   805         focusPrev = last;
       
   806 
       
   807         // link last in chain with
       
   808         topLevel->d_func()->focusPrev = n;
       
   809         n->d_func()->focusNext = topLevel;
       
   810     } else {
       
   811         // q is the start of the focus chain
       
   812         n->d_func()->focusNext = q;
       
   813         focusPrev = n;
       
   814     }
       
   815 
       
   816 }
       
   817 
       
   818 void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
       
   819 {
       
   820     delete (this->layout);
       
   821     layout = l;
       
   822     if (!l) {
       
   823         Q_Q(QGraphicsWidget);
       
   824         q->updateGeometry();
       
   825     }
       
   826 }
       
   827 
       
   828 QT_END_NAMESPACE
       
   829 
       
   830 #endif //QT_NO_GRAPHICSVIEW