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