diff options
author | jasplin <qt-info@nokia.com> | 2009-05-07 08:09:14 (GMT) |
---|---|---|
committer | jasplin <qt-info@nokia.com> | 2009-05-07 08:11:45 (GMT) |
commit | 515991426832a6333f2fd9e639bd4c83e2b27cef (patch) | |
tree | ce4896d65b77cc355631945e336e71ac8d37db7a | |
parent | 73b519015e16d0cd265a1955419e409ba74ce3e4 (diff) | |
download | Qt-515991426832a6333f2fd9e639bd4c83e2b27cef.zip Qt-515991426832a6333f2fd9e639bd4c83e2b27cef.tar.gz Qt-515991426832a6333f2fd9e639bd4c83e2b27cef.tar.bz2 |
Reduced memory footprint of QGraphicsWidget.
This commit reduces the memory footprint of QGraphicsWidget by
around 40% (from around 663 bytes to around 409 bytes - measured
using /proc/<pid>/statm on Linux - see 'man 5 proc').
The technique used is to lazily allocate (on the heap) certain
data structures (i.e. not allocate them unless they are needed):
- QGraphicsLayoutItemPrivate::userSizeHints
=> used only if the size, width, or height is explicitly set
- QGraphicsWidgetPrivate::margins
=> used only if the contents margins are accessed
- QGraphicsWidgetPrivate::windowFrameMargins
=> used only if the window frame margins are accessed
- QGraphicsWidgetPrivate::windowData
=> used only if the graphics widget is a window
In addition, a few unused data members (and related code) were removed:
- QGraphicsWidgetPrivate::contentsRect
- QGraphicsWidgetPrivate::mouseDelta
- QGraphicsWidgetPrivate::*LayoutItemMargin
Reviewed-by: andreas
Task-number: 251592
-rw-r--r-- | src/gui/graphicsview/qgraphicslayoutitem.cpp | 134 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicslayoutitem_p.h | 8 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget.cpp | 98 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget_p.cpp | 249 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget_p.h | 68 |
5 files changed, 298 insertions, 259 deletions
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index eaa97ff..e058292 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -108,13 +108,22 @@ static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qre \internal */ QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout) - : parent(par), isLayout(layout), ownedByLayout(false), graphicsItem(0) + : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0) { } /*! \internal */ +QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate() +{ + // Remove any lazily allocated data + delete[] userSizeHints; +} + +/*! + \internal +*/ void QGraphicsLayoutItemPrivate::init() { sizeHintCacheDirty = true; @@ -132,7 +141,8 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) for (int i = 0; i < Qt::NSizeHints; ++i) { cachedSizeHints[i] = constraint; - combineSize(cachedSizeHints[i], userSizeHints[i]); + if (userSizeHints) + combineSize(cachedSizeHints[i], userSizeHints[i]); } QSizeF &minS = cachedSizeHints[Qt::MinimumSize]; @@ -198,6 +208,58 @@ QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const } /*! + \internal + + Ensures that userSizeHints is allocated. + This function must be called before any dereferencing. +*/ +void QGraphicsLayoutItemPrivate::ensureUserSizeHints() +{ + if (!userSizeHints) + userSizeHints = new QSizeF[Qt::NSizeHints]; +} + +/*! + \internal + + Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint. + */ +void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size) +{ + Q_Q(QGraphicsLayoutItem); + + if (userSizeHints) { + if (size == userSizeHints[which]) + return; + } else if (!size.isValid()) { + return; + } + + ensureUserSizeHints(); + userSizeHints[which] = size; + q->updateGeometry(); +} + +/*! + \internal + + Sets the width of the user size hint \a which to \a width. + */ +void QGraphicsLayoutItemPrivate::setSizeComponent( + Qt::SizeHint which, SizeComponent component, qreal value) +{ + Q_Q(QGraphicsLayoutItem); + ensureUserSizeHints(); + qreal &userValue = (component == Width) + ? userSizeHints[which].rwidth() + : userSizeHints[which].rheight(); + if (value == userValue) + return; + userValue = value; + q->updateGeometry(); +} + +/*! \class QGraphicsLayoutItem \brief The QGraphicsLayoutItem class can be inherited to allow your custom items to be managed by layouts. @@ -381,12 +443,7 @@ QSizePolicy QGraphicsLayoutItem::sizePolicy() const */ void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size) { - Q_D(QGraphicsLayoutItem); - if (size == d->userSizeHints[Qt::MinimumSize]) - return; - - d->userSizeHints[Qt::MinimumSize] = size; - updateGeometry(); + d_ptr->setSize(Qt::MinimumSize, size); } /*! @@ -416,12 +473,7 @@ QSizeF QGraphicsLayoutItem::minimumSize() const */ void QGraphicsLayoutItem::setMinimumWidth(qreal width) { - Q_D(QGraphicsLayoutItem); - qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rwidth(); - if (width == userSizeHint) - return; - userSizeHint = width; - updateGeometry(); + d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width); } /*! @@ -431,12 +483,7 @@ void QGraphicsLayoutItem::setMinimumWidth(qreal width) */ void QGraphicsLayoutItem::setMinimumHeight(qreal height) { - Q_D(QGraphicsLayoutItem); - qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rheight(); - if (height == userSizeHint) - return; - userSizeHint = height; - updateGeometry(); + d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height); } @@ -450,12 +497,7 @@ void QGraphicsLayoutItem::setMinimumHeight(qreal height) */ void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size) { - Q_D(QGraphicsLayoutItem); - if (size == d->userSizeHints[Qt::PreferredSize]) - return; - - d->userSizeHints[Qt::PreferredSize] = size; - updateGeometry(); + d_ptr->setSize(Qt::PreferredSize, size); } /*! @@ -485,12 +527,7 @@ QSizeF QGraphicsLayoutItem::preferredSize() const */ void QGraphicsLayoutItem::setPreferredHeight(qreal height) { - Q_D(QGraphicsLayoutItem); - qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rheight(); - if (height == userSizeHint) - return; - userSizeHint = height; - updateGeometry(); + d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height); } /*! @@ -500,12 +537,7 @@ void QGraphicsLayoutItem::setPreferredHeight(qreal height) */ void QGraphicsLayoutItem::setPreferredWidth(qreal width) { - Q_D(QGraphicsLayoutItem); - qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rwidth(); - if (width == userSizeHint) - return; - userSizeHint = width; - updateGeometry(); + d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width); } /*! @@ -519,12 +551,7 @@ void QGraphicsLayoutItem::setPreferredWidth(qreal width) */ void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size) { - Q_D(QGraphicsLayoutItem); - if (size == d->userSizeHints[Qt::MaximumSize]) - return; - - d->userSizeHints[Qt::MaximumSize] = size; - updateGeometry(); + d_ptr->setSize(Qt::MaximumSize, size); } /*! @@ -554,12 +581,7 @@ QSizeF QGraphicsLayoutItem::maximumSize() const */ void QGraphicsLayoutItem::setMaximumWidth(qreal width) { - Q_D(QGraphicsLayoutItem); - qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rwidth(); - if (width == userSizeHint) - return; - userSizeHint = width; - updateGeometry(); + d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width); } /*! @@ -569,12 +591,7 @@ void QGraphicsLayoutItem::setMaximumWidth(qreal width) */ void QGraphicsLayoutItem::setMaximumHeight(qreal height) { - Q_D(QGraphicsLayoutItem); - qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rheight(); - if (height == userSizeHint) - return; - userSizeHint = height; - updateGeometry(); + d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height); } /*! @@ -732,6 +749,11 @@ QRectF QGraphicsLayoutItem::contentsRect() const */ QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const { + Q_D(const QGraphicsLayoutItem); + + if (!d->userSizeHints && constraint.isValid()) + return constraint; + // ### should respect size policy??? return d_ptr->effectiveSizeHints(constraint)[which]; } diff --git a/src/gui/graphicsview/qgraphicslayoutitem_p.h b/src/gui/graphicsview/qgraphicslayoutitem_p.h index fab0f39..dc044e6 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem_p.h +++ b/src/gui/graphicsview/qgraphicslayoutitem_p.h @@ -63,16 +63,20 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutItemPrivate { Q_DECLARE_PUBLIC(QGraphicsLayoutItem) public: - virtual ~QGraphicsLayoutItemPrivate() {} + virtual ~QGraphicsLayoutItemPrivate(); QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout); void init(); QSizeF *effectiveSizeHints(const QSizeF &constraint) const; QGraphicsItem *parentItem() const; + void ensureUserSizeHints(); + void setSize(Qt::SizeHint which, const QSizeF &size); + enum SizeComponent { Width, Height }; + void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value); QSizePolicy sizePolicy; QGraphicsLayoutItem *parent; - QSizeF userSizeHints[Qt::NSizeHints]; + QSizeF *userSizeHints; mutable QSizeF cachedSizeHints[Qt::NSizeHints]; mutable QSizeF cachedConstraint; diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 66930f2..702e0b6 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -459,17 +459,19 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre { Q_D(QGraphicsWidget); - if (left == d->leftMargin - && top == d->topMargin - && right == d->rightMargin - && bottom == d->bottomMargin) { + if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0) + return; + d->ensureMargins(); + if (left == d->margins[d->Left] + && top == d->margins[d->Top] + && right == d->margins[d->Right] + && bottom == d->margins[d->Bottom]) return; - } - d->leftMargin = left; - d->topMargin = top; - d->rightMargin = right; - d->bottomMargin = bottom; + d->margins[d->Left] = left; + d->margins[d->Top] = top; + d->margins[d->Right] = right; + d->margins[d->Bottom] = bottom; if (QGraphicsLayout *l = d->layout) l->invalidate(); @@ -490,14 +492,16 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const { Q_D(const QGraphicsWidget); + if (left || top || right || bottom) + d->ensureMargins(); if (left) - *left = d->leftMargin; + *left = d->margins[d->Left]; if (top) - *top = d->topMargin; + *top = d->margins[d->Top]; if (right) - *right = d->rightMargin; + *right = d->margins[d->Right]; if (bottom) - *bottom = d->bottomMargin; + *bottom = d->margins[d->Bottom]; } /*! @@ -513,16 +517,23 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right, void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom) { Q_D(QGraphicsWidget); - bool unchanged = left == d->leftWindowFrameMargin && top == d->topWindowFrameMargin - && right == d->rightWindowFrameMargin && bottom == d->bottomWindowFrameMargin; + + if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0) + return; + d->ensureWindowFrameMargins(); + bool unchanged = + d->windowFrameMargins[d->Left] == left + && d->windowFrameMargins[d->Top] == top + && d->windowFrameMargins[d->Right] == right + && d->windowFrameMargins[d->Bottom] == bottom; if (d->setWindowFrameMargins && unchanged) return; if (!unchanged) prepareGeometryChange(); - d->leftWindowFrameMargin = left; - d->topWindowFrameMargin = top; - d->rightWindowFrameMargin = right; - d->bottomWindowFrameMargin = bottom; + d->windowFrameMargins[d->Left] = left; + d->windowFrameMargins[d->Top] = top; + d->windowFrameMargins[d->Right] = right; + d->windowFrameMargins[d->Bottom] = bottom; d->setWindowFrameMargins = true; } @@ -536,14 +547,16 @@ void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const { Q_D(const QGraphicsWidget); + if (left || top || right || bottom) + d->ensureWindowFrameMargins(); if (left) - *left = d->leftWindowFrameMargin; + *left = d->windowFrameMargins[d->Left]; if (top) - *top = d->topWindowFrameMargin; + *top = d->windowFrameMargins[d->Top]; if (right) - *right = d->rightWindowFrameMargin; + *right = d->windowFrameMargins[d->Right]; if (bottom) - *bottom = d->bottomWindowFrameMargin; + *bottom = d->windowFrameMargins[d->Bottom]; } /*! @@ -577,8 +590,10 @@ void QGraphicsWidget::unsetWindowFrameMargins() QRectF QGraphicsWidget::windowFrameGeometry() const { Q_D(const QGraphicsWidget); - return geometry().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin, - d->rightWindowFrameMargin, d->bottomWindowFrameMargin); + return d->windowFrameMargins + ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top], + d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom]) + : geometry(); } /*! @@ -589,8 +604,10 @@ QRectF QGraphicsWidget::windowFrameGeometry() const QRectF QGraphicsWidget::windowFrameRect() const { Q_D(const QGraphicsWidget); - return rect().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin, - d->rightWindowFrameMargin, d->bottomWindowFrameMargin); + return d->windowFrameMargins + ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top], + d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom]) + : rect(); } /*! @@ -699,7 +716,10 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c QSizeF sh; if (d->layout) { sh = d->layout->effectiveSizeHint(which, constraint); - sh += QSizeF(d->leftMargin + d->rightMargin, d->topMargin + d->bottomMargin); + if (d->margins) { + sh += QSizeF(d->margins[d->Left] + d->margins[d->Right], + d->margins[d->Top] + d->margins[d->Bottom]); + } } else { switch (which) { case Qt::MinimumSize: @@ -1127,7 +1147,8 @@ bool QGraphicsWidget::windowFrameEvent(QEvent *event) d->windowFrameMousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); break; case QEvent::GraphicsSceneMouseMove: - if (d->grabbedSection != Qt::NoSection) { + d->ensureWindowData(); + if (d->windowData->grabbedSection != Qt::NoSection) { d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); event->accept(); } @@ -1182,7 +1203,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) const qreal cornerMargin = 20; //### Not sure of this one, it should be the same value for all edges. - const qreal windowFrameWidth = d->leftWindowFrameMargin; + const qreal windowFrameWidth = d->windowFrameMargins + ? d->windowFrameMargins[d->Left] : 0; Qt::WindowFrameSection s = Qt::NoSection; if (x <= left + cornerMargin) { @@ -1208,7 +1230,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) } if (s == Qt::NoSection) { QRectF r1 = r; - r1.setHeight(d->topWindowFrameMargin); + r1.setHeight(d->windowFrameMargins + ? d->windowFrameMargins[d->Top] : 0); if (r1.contains(pos)) s = Qt::TitleBarArea; } @@ -1316,7 +1339,8 @@ bool QGraphicsWidget::event(QEvent *event) case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: case QEvent::GraphicsSceneMouseDoubleClick: - if (d->hasDecoration() && d->grabbedSection != Qt::NoSection) + d->ensureWindowData(); + if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection) return windowFrameEvent(event); break; case QEvent::GraphicsSceneHoverEnter: @@ -1669,12 +1693,13 @@ bool QGraphicsWidget::isActiveWindow() const void QGraphicsWidget::setWindowTitle(const QString &title) { Q_D(QGraphicsWidget); - d->windowTitle = title; + d->ensureWindowData(); + d->windowData->windowTitle = title; } QString QGraphicsWidget::windowTitle() const { Q_D(const QGraphicsWidget); - return d->windowTitle; + return d->windowData ? d->windowData->windowTitle : QString(); } /*! @@ -2110,11 +2135,12 @@ void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGrap QStyleOptionTitleBar bar; bar.QStyleOption::operator=(*option); d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state - if (d->buttonMouseOver) + d->ensureWindowData(); + if (d->windowData->buttonMouseOver) bar.state |= QStyle::State_MouseOver; else bar.state &= ~QStyle::State_MouseOver; - if (d->buttonSunken) + if (d->windowData->buttonSunken) bar.state |= QStyle::State_Sunken; else bar.state &= ~QStyle::State_Sunken; diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 4b41a31..8ced47a 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -89,56 +89,57 @@ qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options return (qreal)height; } -void QGraphicsWidgetPrivate::getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const +/*! + \internal +*/ +QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate() { - if (left) - *left = leftLayoutItemMargin; - if (top) - *top = topLayoutItemMargin; - if (right) - *right = rightLayoutItemMargin; - if (bottom) - *bottom = bottomLayoutItemMargin; + // Remove any lazily allocated data + delete[] margins; + delete[] windowFrameMargins; + delete windowData; } -void QGraphicsWidgetPrivate::setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom) -{ - if (leftLayoutItemMargin == left - && topLayoutItemMargin == top - && rightLayoutItemMargin == right - && bottomLayoutItemMargin == bottom) - return; +/*! + \internal - Q_Q(QGraphicsWidget); - leftLayoutItemMargin = left; - topLayoutItemMargin = top; - rightLayoutItemMargin = right; - bottomLayoutItemMargin = bottom; - q->updateGeometry(); + 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; + } } -void QGraphicsWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt) +/*! + \internal + + Ensures that windowFrameMargins is allocated. + This function must be called before any dereferencing. +*/ +void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const { - Q_Q(QGraphicsWidget); - QStyleOption myOpt; - if (!opt) { - q->initStyleOption(&myOpt); - myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary - opt = &myOpt; + if (!windowFrameMargins) { + windowFrameMargins = new qreal[4]; + for (int i = 0; i < 4; ++i) + windowFrameMargins[i] = 0; } +} - QRect liRect = q->style()->subElementRect(element, opt, /* q */ 0); - if (liRect.isValid()) { - leftLayoutItemMargin = (opt->rect.left() - liRect.left()); - topLayoutItemMargin = (opt->rect.top() - liRect.top()); - rightLayoutItemMargin = (liRect.right() - opt->rect.right()); - bottomLayoutItemMargin = (liRect.bottom() - opt->rect.bottom()); - } else { - leftLayoutItemMargin = 0; - topLayoutItemMargin = 0; - rightLayoutItemMargin = 0; - bottomLayoutItemMargin = 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) @@ -297,11 +298,12 @@ QFont QGraphicsWidgetPrivate::naturalWidgetFont() const 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 = hoveredSubControl; + option->activeSubControls = windowData->hoveredSubControl; bool isActive = q->isActiveWindow(); if (isActive) { option->state |= QStyle::State_Active; @@ -313,7 +315,8 @@ void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *optio } QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar"); QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0); - option->text = QFontMetrics(windowTitleFont).elidedText(windowTitle, Qt::ElideRight, textRect.width()); + option->text = QFontMetrics(windowTitleFont).elidedText( + windowData->windowTitle, Qt::ElideRight, textRect.width()); } void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags) @@ -341,9 +344,10 @@ void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags) void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_Q(QGraphicsWidget); - if (grabbedSection != Qt::NoSection) { - if (grabbedSection == Qt::TitleBarArea) { - buttonSunken = false; + 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. @@ -351,8 +355,10 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve bar.rect.moveTo(0,0); bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar)); QPointF pos = event->pos(); - pos.rx() += leftWindowFrameMargin; - pos.ry() += topWindowFrameMargin; + 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, @@ -361,7 +367,7 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve } } if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons())) - grabbedSection = Qt::NoSection; + windowData->grabbedSection = Qt::NoSection; event->accept(); } } @@ -372,35 +378,16 @@ void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent if (event->button() != Qt::LeftButton) return; - startGeometry = q->geometry(); - grabbedSection = q->windowFrameSectionAt(event->pos()); - switch (grabbedSection) { - case Qt::LeftSection: - case Qt::TopLeftSection: - mouseDelta = event->pos() - q->rect().topLeft(); - break; - case Qt::TopSection: - case Qt::TopRightSection: - mouseDelta = event->pos() - q->rect().topRight(); - break; - case Qt::RightSection: - case Qt::BottomRightSection: - mouseDelta = event->pos() - q->rect().bottomRight(); - break; - case Qt::BottomSection: - case Qt::BottomLeftSection: - mouseDelta = event->pos() - q->rect().bottomLeft(); - break; - case Qt::TitleBarArea: - if (hoveredSubControl == QStyle::SC_TitleBarCloseButton) { - buttonSunken = true; - q->update(); - } - break; - case Qt::NoSection: - break; + 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(grabbedSection != Qt::NoSection); + event->setAccepted(windowData->grabbedSection != Qt::NoSection); } static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, @@ -455,7 +442,8 @@ static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_Q(QGraphicsWidget); - if (!(event->buttons() & Qt::LeftButton) || hoveredSubControl != QStyle::SC_TitleBarLabel) + ensureWindowData(); + if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel) return; QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos()); @@ -464,49 +452,56 @@ void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y()))); QRectF newGeometry; - switch (grabbedSection) { + switch (windowData->grabbedSection) { case Qt::LeftSection: - newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()), - startGeometry.size() - QSizeF(delta.dx(), delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft() + + QPointF(parentXDelta.dx(), parentXDelta.dy()), + windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy())); break; case Qt::TopLeftSection: - newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()), - startGeometry.size() - QSizeF(delta.dx(), delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft() + + QPointF(parentDelta.dx(), parentDelta.dy()), + windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy())); break; case Qt::TopSection: - newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()), - startGeometry.size() - QSizeF(0, delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft() + + QPointF(parentYDelta.dx(), parentYDelta.dy()), + windowData->startGeometry.size() - QSizeF(0, delta.dy())); break; case Qt::TopRightSection: - newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()), - startGeometry.size() - QSizeF(-delta.dx(), delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft() + + QPointF(parentYDelta.dx(), parentYDelta.dy()), + windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy())); break; case Qt::RightSection: - newGeometry = QRectF(startGeometry.topLeft(), - startGeometry.size() + QSizeF(delta.dx(), 0)); + newGeometry = QRectF(windowData->startGeometry.topLeft(), + windowData->startGeometry.size() + QSizeF(delta.dx(), 0)); break; case Qt::BottomRightSection: - newGeometry = QRectF(startGeometry.topLeft(), - startGeometry.size() + QSizeF(delta.dx(), delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft(), + windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy())); break; case Qt::BottomSection: - newGeometry = QRectF(startGeometry.topLeft(), - startGeometry.size() + QSizeF(0, delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft(), + windowData->startGeometry.size() + QSizeF(0, delta.dy())); break; case Qt::BottomLeftSection: - newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()), - startGeometry.size() - QSizeF(delta.dx(), -delta.dy())); + newGeometry = QRectF(windowData->startGeometry.topLeft() + + QPointF(parentXDelta.dx(), parentXDelta.dy()), + windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy())); break; case Qt::TitleBarArea: - newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()), - startGeometry.size()); + newGeometry = QRectF(windowData->startGeometry.topLeft() + + QPointF(parentDelta.dx(), parentDelta.dy()), + windowData->startGeometry.size()); break; case Qt::NoSection: break; } - if (grabbedSection != Qt::NoSection) { - _q_boundGeometryToSizeConstraints(startGeometry, &newGeometry, grabbedSection, + if (windowData->grabbedSection != Qt::NoSection) { + _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry, + windowData->grabbedSection, q->effectiveSizeHint(Qt::MinimumSize), q->effectiveSizeHint(Qt::MaximumSize)); q->setGeometry(newGeometry); @@ -519,21 +514,25 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent if (!hasDecoration()) return; + ensureWindowData(); + if (q->rect().contains(event->pos())) { - if (buttonMouseOver || hoveredSubControl != QStyle::SC_None) + if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None) windowFrameHoverLeaveEvent(event); return; } - bool wasMouseOver = buttonMouseOver; - QRect oldButtonRect = buttonRect; - buttonRect = QRect(); - buttonMouseOver = false; + 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. - pos.rx() += leftWindowFrameMargin; - pos.ry() += topWindowFrameMargin; + if (windowFrameMargins) { + pos.rx() += windowFrameMargins[Left]; + pos.ry() += windowFrameMargins[Top]; + } initStyleOptionTitleBar(&bar); bar.rect = q->windowFrameRect().toRect(); bar.rect.moveTo(0,0); @@ -559,14 +558,17 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent cursorShape = Qt::SizeVerCursor; break; case Qt::TitleBarArea: - buttonRect = q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0); + 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 - buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0); - buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0); + 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 (buttonRect.contains(pos.toPoint())) - buttonMouseOver = true; + if (windowData->buttonRect.contains(pos.toPoint())) + windowData->buttonMouseOver = true; event->ignore(); break; default: @@ -578,15 +580,15 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent q->setCursor(cursorShape); #endif // update buttons if we hover over them - hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0); - if (hoveredSubControl != QStyle::SC_TitleBarCloseButton) - hoveredSubControl = QStyle::SC_TitleBarLabel; + windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0); + if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton) + windowData->hoveredSubControl = QStyle::SC_TitleBarLabel; - if (buttonMouseOver != wasMouseOver) { + if (windowData->buttonMouseOver != wasMouseOver) { if (!oldButtonRect.isNull()) q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft())); - if (!buttonRect.isNull()) - q->update(QRectF(buttonRect).translated(q->windowFrameRect().topLeft())); + if (!windowData->buttonRect.isNull()) + q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft())); } } @@ -600,16 +602,19 @@ void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent q->unsetCursor(); #endif + ensureWindowData(); + bool needsUpdate = false; - if (hoveredSubControl == QStyle::SC_TitleBarCloseButton || buttonMouseOver) + if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton + || windowData->buttonMouseOver) needsUpdate = true; // update the hover state (of buttons etc...) - hoveredSubControl = QStyle::SC_None; - buttonMouseOver = false; - buttonRect = QRect(); + windowData->hoveredSubControl = QStyle::SC_None; + windowData->buttonMouseOver = false; + windowData->buttonRect = QRect(); if (needsUpdate) - q->update(buttonRect); + q->update(windowData->buttonRect); } } diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h index 53eaa31..3509a54 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.h +++ b/src/gui/graphicsview/qgraphicswidget_p.h @@ -73,14 +73,7 @@ class Q_GUI_EXPORT QGraphicsWidgetPrivate : public QGraphicsItemPrivate Q_DECLARE_PUBLIC(QGraphicsWidget) public: QGraphicsWidgetPrivate() - : leftMargin(0), - topMargin(0), - rightMargin(0), - bottomMargin(0), - leftLayoutItemMargin(0), - topLayoutItemMargin(0), - rightLayoutItemMargin(0), - bottomLayoutItemMargin(0), + : margins(0), layout(0), inheritedPaletteResolveMask(0), inheritedFontResolveMask(0), @@ -92,40 +85,23 @@ public: focusPrev(0), focusChild(0), windowFlags(0), - hoveredSubControl(QStyle::SC_None), - grabbedSection(Qt::NoSection), - buttonMouseOver(false), - buttonSunken(false), + windowData(0), setWindowFrameMargins(false), - leftWindowFrameMargin(0), - topWindowFrameMargin(0), - rightWindowFrameMargin(0), - bottomWindowFrameMargin(0) + windowFrameMargins(0) { } + virtual ~QGraphicsWidgetPrivate(); void init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags); qreal titleBarHeight(const QStyleOptionTitleBar &options) const; // Margins - qreal leftMargin; - qreal topMargin; - qreal rightMargin; - qreal bottomMargin; - QRectF contentsRect; - - // Layout item margins - void getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const; - void setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom); - void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); + enum {Left, Top, Right, Bottom}; + mutable qreal *margins; + void ensureMargins() const; void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene = 0); void setLayout_helper(QGraphicsLayout *l); - qreal leftLayoutItemMargin; - qreal topLayoutItemMargin; - qreal rightLayoutItemMargin; - qreal bottomLayoutItemMargin; - // Layouts QGraphicsLayout *layout; void setLayoutDirection_helper(Qt::LayoutDirection direction); @@ -208,20 +184,26 @@ public: // Windows Qt::WindowFlags windowFlags; - QString windowTitle; - QStyle::SubControl hoveredSubControl; - Qt::WindowFrameSection grabbedSection; - uint buttonMouseOver : 1; - uint buttonSunken : 1; - QPointF mouseDelta; // to compensate for small error when interactively resizing - QRectF startGeometry; - QRect buttonRect; + struct WindowData { + QString windowTitle; + QStyle::SubControl hoveredSubControl; + Qt::WindowFrameSection grabbedSection; + uint buttonMouseOver : 1; + uint buttonSunken : 1; + QRectF startGeometry; + QRect buttonRect; + WindowData() + : hoveredSubControl(QStyle::SC_None) + , grabbedSection(Qt::NoSection) + , buttonMouseOver(false) + , buttonSunken(false) + {} + } *windowData; + void ensureWindowData(); bool setWindowFrameMargins; - qreal leftWindowFrameMargin; - qreal topWindowFrameMargin; - qreal rightWindowFrameMargin; - qreal bottomWindowFrameMargin; + mutable qreal *windowFrameMargins; + void ensureWindowFrameMargins() const; #ifndef QT_NO_ACTION QList<QAction *> actions; |