summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjasplin <qt-info@nokia.com>2009-05-07 08:09:14 (GMT)
committerjasplin <qt-info@nokia.com>2009-05-07 08:11:45 (GMT)
commit515991426832a6333f2fd9e639bd4c83e2b27cef (patch)
treece4896d65b77cc355631945e336e71ac8d37db7a
parent73b519015e16d0cd265a1955419e409ba74ce3e4 (diff)
downloadQt-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.cpp134
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem_p.h8
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp98
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp249
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h68
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;