src/gui/graphicsview/qgraphicswidget_p.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,830 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+#ifndef QT_NO_GRAPHICSVIEW
+
+#include <QtCore/qdebug.h>
+#include "qgraphicswidget_p.h"
+#include "qgraphicslayout.h"
+#include "qgraphicsscene_p.h"
+#include <QtGui/qapplication.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qstyleoption.h>
+#include <QtGui/QStyleOptionTitleBar>
+#include <QtGui/QGraphicsSceneMouseEvent>
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+# include <QMacStyle>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags)
+{
+    Q_Q(QGraphicsWidget);
+
+    attributes = 0;
+    isWidget = 1; // QGraphicsItem::isWidget() returns true.
+    focusNext = focusPrev = q;
+    focusPolicy = Qt::NoFocus;
+
+    adjustWindowFlags(&wFlags);
+    windowFlags = wFlags;
+
+    q->setParentItem(parentItem);
+    q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
+    q->setGraphicsItem(q);
+
+    resolveLayoutDirection();
+    q->unsetWindowFrameMargins();
+    q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+    q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+}
+
+qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
+{
+    Q_Q(const QGraphicsWidget);
+    int height = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+    if (qobject_cast<QMacStyle*>(q->style())) {
+        height -=4;
+    }
+#endif
+    return (qreal)height;
+}
+
+/*!
+    \internal
+*/
+QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
+{
+    // Remove any lazily allocated data
+    delete[] margins;
+    delete[] windowFrameMargins;
+    delete windowData;
+}
+
+/*!
+    \internal
+
+     Ensures that margins is allocated.
+     This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureMargins() const
+{
+    if (!margins) {
+        margins = new qreal[4];
+        for (int i = 0; i < 4; ++i)
+            margins[i] = 0;
+    }
+}
+
+/*!
+    \internal
+
+     Ensures that windowFrameMargins is allocated.
+     This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
+{
+    if (!windowFrameMargins) {
+        windowFrameMargins = new qreal[4];
+        for (int i = 0; i < 4; ++i)
+            windowFrameMargins[i] = 0;
+    }
+}
+
+/*!
+    \internal
+
+     Ensures that windowData is allocated.
+     This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureWindowData()
+{
+    if (!windowData)
+        windowData = new WindowData;
+}
+
+void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette)
+{
+    if (this->palette == palette && this->palette.resolve() == palette.resolve())
+        return;
+    updatePalette(palette);
+}
+
+void QGraphicsWidgetPrivate::resolvePalette(uint inheritedMask)
+{
+    inheritedPaletteResolveMask = inheritedMask;
+    QPalette naturalPalette = naturalWidgetPalette();
+    QPalette resolvedPalette = palette.resolve(naturalPalette);
+    updatePalette(resolvedPalette);
+}
+
+void QGraphicsWidgetPrivate::updatePalette(const QPalette &palette)
+{
+    Q_Q(QGraphicsWidget);
+    // Update local palette setting.
+    this->palette = palette;
+
+    // Calculate new mask.
+    if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
+        inheritedPaletteResolveMask = 0;
+    int mask = palette.resolve() | inheritedPaletteResolveMask;
+
+    // Propagate to children.
+    for (int i = 0; i < children.size(); ++i) {
+        QGraphicsItem *item = children.at(i);
+        if (item->isWidget()) {
+            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
+            if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
+                w->d_func()->resolvePalette(mask);
+        } else {
+            item->d_ptr->resolvePalette(mask);
+        }
+    }
+
+    // Notify change.
+    QEvent event(QEvent::PaletteChange);
+    QApplication::sendEvent(q, &event);
+}
+
+void QGraphicsWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
+{
+    Q_Q(QGraphicsWidget);
+    if ((direction == Qt::RightToLeft) == (testAttribute(Qt::WA_RightToLeft)))
+        return;
+    q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
+
+    // Propagate this change to all children.
+    for (int i = 0; i < children.size(); ++i) {
+        QGraphicsItem *item = children.at(i);
+        if (item->isWidget()) {
+            QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+            if (widget->parentWidget() && !widget->testAttribute(Qt::WA_SetLayoutDirection))
+                widget->d_func()->setLayoutDirection_helper(direction);
+        }
+    }
+
+    // Send the notification event to this widget item.
+    QEvent e(QEvent::LayoutDirectionChange);
+    QApplication::sendEvent(q, &e);
+}
+
+void QGraphicsWidgetPrivate::resolveLayoutDirection()
+{
+    Q_Q(QGraphicsWidget);
+    if (q->testAttribute(Qt::WA_SetLayoutDirection)) {
+        return;
+    }
+    if (QGraphicsWidget *parentWidget = q->parentWidget()) {
+        setLayoutDirection_helper(parentWidget->layoutDirection());
+    } else if (scene) {
+        // ### shouldn't the scene have a layoutdirection really? how does
+        // ### QGraphicsWidget get changes from QApplication::layoutDirection?
+        setLayoutDirection_helper(QApplication::layoutDirection());
+    } else {
+        setLayoutDirection_helper(QApplication::layoutDirection());
+    }
+}
+
+QPalette QGraphicsWidgetPrivate::naturalWidgetPalette() const
+{
+    Q_Q(const QGraphicsWidget);
+    QPalette palette;
+    if (QGraphicsWidget *parent = q->parentWidget()) {
+        palette = parent->palette();
+    } else if (scene) {
+        palette = scene->palette();
+    }
+    palette.resolve(0);
+    return palette;
+}
+
+void QGraphicsWidgetPrivate::setFont_helper(const QFont &font)
+{
+    if (this->font == font && this->font.resolve() == font.resolve())
+        return;
+    updateFont(font);
+}
+
+void QGraphicsWidgetPrivate::resolveFont(uint inheritedMask)
+{
+    inheritedFontResolveMask = inheritedMask;
+    QFont naturalFont = naturalWidgetFont();
+    QFont resolvedFont = font.resolve(naturalFont);
+    updateFont(resolvedFont);
+}
+
+void QGraphicsWidgetPrivate::updateFont(const QFont &font)
+{
+    Q_Q(QGraphicsWidget);
+    // Update the local font setting.
+    this->font = font;
+
+    // Calculate new mask.
+    if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
+        inheritedFontResolveMask = 0;
+    int mask = font.resolve() | inheritedFontResolveMask;
+
+    // Propagate to children.
+    for (int i = 0; i < children.size(); ++i) {
+        QGraphicsItem *item = children.at(i);
+        if (item->isWidget()) {
+            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
+            if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
+                w->d_func()->resolveFont(mask);
+        } else {
+            item->d_ptr->resolveFont(mask);
+        }
+    }
+
+    if (!polished)
+        return;
+    // Notify change.
+    QEvent event(QEvent::FontChange);
+    QApplication::sendEvent(q, &event);
+}
+
+QFont QGraphicsWidgetPrivate::naturalWidgetFont() const
+{
+    Q_Q(const QGraphicsWidget);
+    QFont naturalFont; // ### no application font support
+    if (QGraphicsWidget *parent = q->parentWidget()) {
+        naturalFont = parent->font();
+    } else if (scene) {
+        naturalFont = scene->font();
+    }
+    naturalFont.resolve(0);
+    return naturalFont;
+}
+
+void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *option)
+{
+    Q_Q(QGraphicsWidget);
+    ensureWindowData();
+    q->initStyleOption(option);
+    option->rect.setHeight(titleBarHeight(*option));
+    option->titleBarFlags = windowFlags;
+    option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
+    option->activeSubControls = windowData->hoveredSubControl;
+    bool isActive = q->isActiveWindow();
+    if (isActive) {
+        option->state |= QStyle::State_Active;
+        option->titleBarState = Qt::WindowActive;
+        option->titleBarState |= QStyle::State_Active;
+    } else {
+        option->state &= ~QStyle::State_Active;
+        option->titleBarState = Qt::WindowNoState;
+    }
+    QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar");
+    QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0);
+    option->text = QFontMetrics(windowTitleFont).elidedText(
+        windowData->windowTitle, Qt::ElideRight, textRect.width());
+}
+
+void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
+{
+    bool customize =  (*flags & (Qt::CustomizeWindowHint
+            | Qt::FramelessWindowHint
+            | Qt::WindowTitleHint
+            | Qt::WindowSystemMenuHint
+            | Qt::WindowMinimizeButtonHint
+            | Qt::WindowMaximizeButtonHint
+            | Qt::WindowContextHelpButtonHint));
+
+    uint type = (*flags & Qt::WindowType_Mask);
+    if (customize)
+        ;
+    else if (type == Qt::Dialog || type == Qt::Sheet)
+        *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint;
+    else if (type == Qt::Tool)
+        *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
+    else if (type == Qt::Window || type == Qt::SubWindow)
+        *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+                  | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
+}
+
+void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_Q(QGraphicsWidget);
+    ensureWindowData();
+    if (windowData->grabbedSection != Qt::NoSection) {
+        if (windowData->grabbedSection == Qt::TitleBarArea) {
+            windowData->buttonSunken = false;
+            QStyleOptionTitleBar bar;
+            initStyleOptionTitleBar(&bar);
+            // make sure that the coordinates (rect and pos) we send to the style are positive.
+            bar.rect = q->windowFrameRect().toRect();
+            bar.rect.moveTo(0,0);
+            bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
+            QPointF pos = event->pos();
+            if (windowFrameMargins) {
+                pos.rx() += windowFrameMargins[Left];
+                pos.ry() += windowFrameMargins[Top];
+            }
+            bar.subControls = QStyle::SC_TitleBarCloseButton;
+            if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
+                                           QStyle::SC_TitleBarCloseButton,
+                                           event->widget()).contains(pos.toPoint())) {
+                q->close();
+            }
+        }
+        if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
+            windowData->grabbedSection = Qt::NoSection;
+        event->accept();
+    }
+}
+
+void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_Q(QGraphicsWidget);
+    if (event->button() != Qt::LeftButton)
+        return;
+
+    ensureWindowData();
+    windowData->startGeometry = q->geometry();
+    windowData->grabbedSection = q->windowFrameSectionAt(event->pos());
+    ensureWindowData();
+    if (windowData->grabbedSection == Qt::TitleBarArea
+        && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
+        windowData->buttonSunken = true;
+        q->update();
+    }
+    event->setAccepted(windowData->grabbedSection != Qt::NoSection);
+}
+
+/*!
+  Used to calculate the
+  Precondition:
+  \a widget should support either hfw or wfh
+
+  If \a heightForWidth is set to false, this function will query the width for height
+  instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted
+  as minimum width and maximum width.
+ */
+static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh,
+                                   const QGraphicsWidget *widget,
+                                   bool heightForWidth = true)
+{
+    qreal minimumHeightForWidth = -1;
+    const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy();
+    const bool hasHFW = sp.hasHeightForWidth();
+    if (hasHFW == heightForWidth) {
+        minimumHeightForWidth = hasHFW
+                                ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
+                                : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width();    //"width" is here height!
+    } else {
+        // widthForHeight
+        const qreal constraint = width;
+        while (maxh - minh > 0.1) {
+            qreal middle = minh + (maxh - minh)/2;
+            // ### really bad, if we are a widget with a layout it will call
+            // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call
+            // sizeHint three times because of how the cache works
+            qreal hfw = hasHFW
+                        ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height()
+                        : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width();
+            if (hfw > constraint) {
+                minh = middle;
+            } else if (hfw <= constraint) {
+                maxh = middle;
+            }
+        }
+        minimumHeightForWidth = maxh;
+    }
+    return minimumHeightForWidth;
+}
+
+static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw,
+                                   const QGraphicsWidget *widget)
+{
+    return minimumHeightForWidth(height, minw, maxw, widget, false);
+}
+
+static QSizeF closestAcceptableSize(const QSizeF &proposed,
+                                    const QGraphicsWidget *widget)
+{
+    const QSizeF current = widget->size();
+
+    qreal minw = proposed.width();
+    qreal maxw = current.width();
+    qreal minh = proposed.height();
+    qreal maxh = current.height();
+
+    qreal middlew = maxw;
+    qreal middleh = maxh;
+    qreal min_hfw;
+    min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget);
+
+    do {
+        if (maxw - minw < 0.1) {
+            // we still havent found anything, cut off binary search
+            minw = maxw;
+            minh = maxh;
+        }
+        middlew = minw + (maxw - minw)/2.0;
+        middleh = minh + (maxh - minh)/2.0;
+
+        min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
+
+        if (min_hfw > middleh) {
+            minw = middlew;
+            minh = middleh;
+        } else if (min_hfw <= middleh) {
+            maxw = middlew;
+            maxh = middleh;
+        }
+    } while (maxw != minw);
+
+    min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
+
+    QSizeF result;
+    if (min_hfw < maxh) {
+        result = QSizeF(middlew, min_hfw);
+    } else {
+        // Needed because of the cut-off we do above.
+        result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh);
+    }
+    return result;
+}
+
+static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
+                                              QRectF *rect, Qt::WindowFrameSection section,
+                                              const QSizeF &min, const QSizeF &max,
+                                              const QGraphicsWidget *widget)
+{
+    const QRectF proposedRect = *rect;
+    qreal width = qBound(min.width(), proposedRect.width(), max.width());
+    qreal height = qBound(min.height(), proposedRect.height(), max.height());
+
+    QSizePolicy sp = widget->sizePolicy();
+    if (const QGraphicsLayout *l = widget->layout()) {
+        sp = l->sizePolicy();
+    }
+    const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight();
+
+    const bool widthChanged = proposedRect.width() < widget->size().width();
+    const bool heightChanged = proposedRect.height() < widget->size().height();
+
+    if (hasHFW) {
+        if (widthChanged || heightChanged) {
+            const qreal minh = min.height();
+            const qreal maxh = max.height();
+            const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget);
+            if (proposedHFW > proposedRect.height()) {
+                QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
+                width = effectiveSize.width();
+                height = effectiveSize.height();
+            }
+        }
+    }
+
+    switch (section) {
+    case Qt::LeftSection:
+        rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
+                      qRound(width), startGeometry.height());
+        break;
+    case Qt::TopLeftSection:
+        rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height),
+                      qRound(width), qRound(height));
+        break;
+    case Qt::TopSection:
+        rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height),
+                      startGeometry.width(), qRound(height));
+        break;
+    case Qt::TopRightSection:
+        rect->setTop(rect->bottom() - qRound(height));
+        rect->setWidth(qRound(width));
+        break;
+    case Qt::RightSection:
+        rect->setWidth(qRound(width));
+        break;
+    case Qt::BottomRightSection:
+        rect->setWidth(qRound(width));
+        rect->setHeight(qRound(height));
+        break;
+    case Qt::BottomSection:
+        rect->setHeight(qRound(height));
+        break;
+    case Qt::BottomLeftSection:
+        rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
+                      qRound(width), qRound(height));
+        break;
+    default:
+        break;
+    }
+}
+
+void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_Q(QGraphicsWidget);
+    ensureWindowData();
+    if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
+        return;
+
+    QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos());
+    QLineF parentDelta(q->mapToParent(delta.p1()), q->mapToParent(delta.p2()));
+    QLineF parentXDelta(q->mapToParent(QPointF(delta.p1().x(), 0)), q->mapToParent(QPointF(delta.p2().x(), 0)));
+    QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y())));
+
+    QRectF newGeometry;
+    switch (windowData->grabbedSection) {
+    case Qt::LeftSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft()
+                             + QPointF(parentXDelta.dx(), parentXDelta.dy()),
+                             windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
+        break;
+    case Qt::TopLeftSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft()
+                             + QPointF(parentDelta.dx(), parentDelta.dy()),
+                             windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
+        break;
+    case Qt::TopSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft()
+                             + QPointF(parentYDelta.dx(), parentYDelta.dy()),
+                             windowData->startGeometry.size() - QSizeF(0, delta.dy()));
+        break;
+    case Qt::TopRightSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft()
+                             + QPointF(parentYDelta.dx(), parentYDelta.dy()),
+                             windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
+        break;
+    case Qt::RightSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft(),
+                             windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
+        break;
+    case Qt::BottomRightSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft(),
+                             windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
+        break;
+    case Qt::BottomSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft(),
+                             windowData->startGeometry.size() + QSizeF(0, delta.dy()));
+        break;
+    case Qt::BottomLeftSection:
+        newGeometry = QRectF(windowData->startGeometry.topLeft()
+                             + QPointF(parentXDelta.dx(), parentXDelta.dy()),
+                             windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
+        break;
+    case Qt::TitleBarArea:
+        newGeometry = QRectF(windowData->startGeometry.topLeft()
+                             + QPointF(parentDelta.dx(), parentDelta.dy()),
+                             windowData->startGeometry.size());
+        break;
+    case Qt::NoSection:
+        break;
+    }
+
+    if (windowData->grabbedSection != Qt::NoSection) {
+        _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
+                                          windowData->grabbedSection,
+                                          q->effectiveSizeHint(Qt::MinimumSize),
+                                          q->effectiveSizeHint(Qt::MaximumSize),
+                                          q);
+        q->setGeometry(newGeometry);
+    }
+}
+
+void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_Q(QGraphicsWidget);
+    if (!hasDecoration())
+        return;
+
+    ensureWindowData();
+
+    if (q->rect().contains(event->pos())) {
+        if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
+            windowFrameHoverLeaveEvent(event);
+        return;
+    }
+
+    bool wasMouseOver = windowData->buttonMouseOver;
+    QRect oldButtonRect = windowData->buttonRect;
+    windowData->buttonRect = QRect();
+    windowData->buttonMouseOver = false;
+    QPointF pos = event->pos();
+    QStyleOptionTitleBar bar;
+    // make sure that the coordinates (rect and pos) we send to the style are positive.
+    if (windowFrameMargins) {
+        pos.rx() += windowFrameMargins[Left];
+        pos.ry() += windowFrameMargins[Top];
+    }
+    initStyleOptionTitleBar(&bar);
+    bar.rect = q->windowFrameRect().toRect();
+    bar.rect.moveTo(0,0);
+    bar.rect.setHeight(int(titleBarHeight(bar)));
+
+    Qt::CursorShape cursorShape = Qt::ArrowCursor;
+    bool needsSetCursorCall = true;
+    switch (q->windowFrameSectionAt(event->pos())) {
+        case Qt::TopLeftSection:
+        case Qt::BottomRightSection:
+            cursorShape = Qt::SizeFDiagCursor;
+            break;
+        case Qt::TopRightSection:
+        case Qt::BottomLeftSection:
+            cursorShape = Qt::SizeBDiagCursor;
+            break;
+        case Qt::LeftSection:
+        case Qt::RightSection:
+            cursorShape = Qt::SizeHorCursor;
+            break;
+        case Qt::TopSection:
+        case Qt::BottomSection:
+            cursorShape = Qt::SizeVerCursor;
+            break;
+        case Qt::TitleBarArea:
+            windowData->buttonRect = q->style()->subControlRect(
+                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
+#ifdef Q_WS_MAC
+            // On mac we should hover if we are in the 'area' of the buttons
+            windowData->buttonRect |= q->style()->subControlRect(
+                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
+            windowData->buttonRect |= q->style()->subControlRect(
+                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
+#endif
+            if (windowData->buttonRect.contains(pos.toPoint()))
+                windowData->buttonMouseOver = true;
+            event->ignore();
+            break;
+        default:
+            needsSetCursorCall = false;
+            event->ignore();
+        }
+#ifndef QT_NO_CURSOR
+    if (needsSetCursorCall)
+        q->setCursor(cursorShape);
+#endif
+    // update buttons if we hover over them
+    windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
+    if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
+        windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;
+
+    if (windowData->buttonMouseOver != wasMouseOver) {
+        if (!oldButtonRect.isNull())
+            q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
+        if (!windowData->buttonRect.isNull())
+            q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
+    }
+}
+
+void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_UNUSED(event);
+    Q_Q(QGraphicsWidget);
+    if (hasDecoration()) {
+        // ### restore the cursor, don't override it
+#ifndef QT_NO_CURSOR
+        q->unsetCursor();
+#endif
+
+        ensureWindowData();
+
+        bool needsUpdate = false;
+        if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton
+            || windowData->buttonMouseOver)
+            needsUpdate = true;
+
+        // update the hover state (of buttons etc...)
+        windowData->hoveredSubControl = QStyle::SC_None;
+        windowData->buttonMouseOver = false;
+        windowData->buttonRect = QRect();
+        if (needsUpdate)
+            q->update(windowData->buttonRect);
+    }
+}
+
+bool QGraphicsWidgetPrivate::hasDecoration() const
+{
+    return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint);
+}
+
+/**
+ * is called after a reparent has taken place to fix up the focus chain(s)
+ */
+void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene)
+{
+    Q_Q(QGraphicsWidget);
+
+    Q_ASSERT(focusNext && focusPrev);
+
+    QGraphicsWidget *n = q;     //last one in 'new' list
+    QGraphicsWidget *o = 0;     //last one in 'old' list
+
+    QGraphicsWidget *w = focusNext;
+
+    QGraphicsWidget *firstOld = 0;
+    bool wasPreviousNew = true;
+    
+    while (w != q) {
+        bool isCurrentNew = q->isAncestorOf(w);
+        if (isCurrentNew) {
+            if (!wasPreviousNew) {
+                n->d_func()->focusNext = w;
+                w->d_func()->focusPrev = n;
+            }
+            n = w;
+        } else /*if (!isCurrentNew)*/ {
+            if (wasPreviousNew) {
+                if (o) {
+                    o->d_func()->focusNext = w;
+                    w->d_func()->focusPrev = o;
+                } else {
+                    firstOld = w;
+                }
+            }
+            o = w;
+        }
+        w = w->d_func()->focusNext;
+        wasPreviousNew = isCurrentNew;
+    }
+
+    // repair the 'old' chain
+    if (firstOld) {
+        o->d_func()->focusNext = firstOld;
+        firstOld->d_func()->focusPrev = o;
+    }
+
+    // update tabFocusFirst for oldScene if the item is going to be removed from oldScene
+    if (newParent)
+        newScene = newParent->scene();
+    QGraphicsScene *oldScene = q->scene();
+    if (oldScene && newScene != oldScene)
+        oldScene->d_func()->tabFocusFirst = firstOld;
+
+    QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0;
+    QGraphicsWidget *topLevel = 0;
+    if (topLevelItem && topLevelItem->isWidget())
+        topLevel = static_cast<QGraphicsWidget *>(topLevelItem);
+
+    if (topLevel && newParent) {
+        QGraphicsWidget *last = topLevel->d_func()->focusPrev;
+        // link last with new chain
+        last->d_func()->focusNext = q;
+        focusPrev = last;
+
+        // link last in chain with
+        topLevel->d_func()->focusPrev = n;
+        n->d_func()->focusNext = topLevel;
+    } else {
+        // q is the start of the focus chain
+        n->d_func()->focusNext = q;
+        focusPrev = n;
+    }
+
+}
+
+void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
+{
+    delete (this->layout);
+    layout = l;
+    if (!l) {
+        Q_Q(QGraphicsWidget);
+        q->updateGeometry();
+    }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_GRAPHICSVIEW