summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2009-09-08 00:14:12 (GMT)
committerMartin Jones <martin.jones@nokia.com>2009-09-08 00:14:12 (GMT)
commitf6c08f5e68c90338a8402c0912cd6be72e84b1e6 (patch)
treed928f975e686b752cd1fc47eca812f376d9d0a03 /src/gui/graphicsview
parent276a44c0867a76a90b425baa8dcbda733d25b3fb (diff)
parent0cbbc9cb9e87a3a39ee1597f4cea1c2b77d8f8da (diff)
downloadQt-f6c08f5e68c90338a8402c0912cd6be72e84b1e6.zip
Qt-f6c08f5e68c90338a8402c0912cd6be72e84b1e6.tar.gz
Qt-f6c08f5e68c90338a8402c0912cd6be72e84b1e6.tar.bz2
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into kinetic-declarativeui
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp36
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp6
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp164
3 files changed, 166 insertions, 40 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 1d55534..8bd3648 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -303,13 +303,17 @@
drop shadow effects and for decoration objects that follow the parent
item's geometry without drawing on top of it.
- \value ItemUsesExtendedStyleOption The item makes use of either the
- exposedRect or matrix member of the QStyleOptionGraphicsItem. Implementers
- of QGraphicsItem subclasses should set that flag if this data is required.
- By default, the exposedRect is initialized to the item's boundingRect and
- the matrix is untransformed. Enable this flag for more fine-grained values.
- Use QStyleOptionGraphicsItem::levelOfDetailFromTransform() for a more
- fine-grained value.
+ \value ItemUsesExtendedStyleOption The item makes use of either
+ \l{QStyleOptionGraphicsItem::}{exposedRect} or
+ \l{QStyleOptionGraphicsItem::}{matrix} in QStyleOptionGraphicsItem. By default,
+ the \l{QStyleOptionGraphicsItem::}{exposedRect} is initialized to the item's
+ boundingRect() and the \l{QStyleOptionGraphicsItem::}{matrix} is untransformed.
+ You can enable this flag for the style options to be set up with more
+ fine-grained values.
+ Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
+ and always initialized to 1. Use
+ QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need a higher
+ value.
\value ItemHasNoContents The item does not paint anything (i.e., calling
paint() on the item has no effect). You should set this flag on items that
@@ -926,7 +930,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
}
QGraphicsItem *lastSubFocusItem = subFocusItem;
- if (subFocusItem) {
+ if (subFocusItem && !inDestructor) {
// Update the child focus chain; when reparenting an item that has a
// focus child, ensure that that focus child clears its focus child
// chain from our parents before it's reparented.
@@ -4779,7 +4783,7 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
{
Q_ASSERT(inSetPosHelper);
- if (!(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
+ if (inDestructor || !(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
return; // Not clipped by any ancestor.
// Find closest clip ancestor and transform.
@@ -4796,10 +4800,14 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
if (clipParent && clipParent->d_ptr->inDestructor)
return;
- // thisToParentTransform is now the same as q->itemTransform(clipParent), except
- // that the new position (which is not yet set on the item) is taken into account.
- Q_ASSERT(clipParent);
- Q_ASSERT(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ // Ensure no parents are currently being deleted. This can only
+ // happen if the item is moved by a dying ancestor.
+ QGraphicsItem *p = clipParent;
+ while (p) {
+ if (p->d_ptr->inDestructor)
+ return;
+ p = p->d_ptr->parent;
+ }
// From here everything is calculated in clip parent's coordinates.
const QRectF parentBoundingRect(clipParent->boundingRect());
@@ -6861,6 +6869,8 @@ void QGraphicsItem::removeFromIndex()
*/
void QGraphicsItem::prepareGeometryChange()
{
+ if (d_ptr->inDestructor)
+ return;
if (d_ptr->scene) {
d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true;
d_ptr->geometryChanged = 1;
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index afabf49..d0f3b99 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -687,11 +687,13 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
Q_D(const QGraphicsWidget);
QSizeF sh;
if (d->layout) {
- sh = d->layout->effectiveSizeHint(which, constraint);
+ QSizeF marginSize(0,0);
if (d->margins) {
- sh += QSizeF(d->margins[d->Left] + d->margins[d->Right],
+ marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right],
d->margins[d->Top] + d->margins[d->Bottom]);
}
+ sh = d->layout->effectiveSizeHint(which, constraint - marginSize);
+ sh += marginSize;
} else {
switch (which) {
case Qt::MinimumSize:
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 787bbb1..bf826a9 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -393,49 +393,162 @@ void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent
event->setAccepted(windowData->grabbedSection != Qt::NoSection);
}
+/*!
+ Used to calculate the
+ Precondition:
+ \a widget should support either hfw or wfh
+
+ If \a heightForWidth is set to false, this function will query the width for height
+ instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted
+ as minimum width and maximum width.
+ */
+static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh,
+ const QGraphicsWidget *widget,
+ bool heightForWidth = true)
+{
+ qreal minimumHeightForWidth = -1;
+ const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy();
+ const bool hasHFW = sp.hasHeightForWidth();
+ if (hasHFW == heightForWidth) {
+ minimumHeightForWidth = hasHFW
+ ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
+ : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width(); //"width" is here height!
+ } else {
+ // widthForHeight
+ const qreal constraint = width;
+ while (maxh - minh > 0.1) {
+ qreal middle = minh + (maxh - minh)/2;
+ // ### really bad, if we are a widget with a layout it will call
+ // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call
+ // sizeHint three times because of how the cache works
+ qreal hfw = hasHFW
+ ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height()
+ : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width();
+ if (hfw > constraint) {
+ minh = middle;
+ } else if (hfw <= constraint) {
+ maxh = middle;
+ }
+ }
+ minimumHeightForWidth = maxh;
+ }
+ return minimumHeightForWidth;
+}
+
+static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw,
+ const QGraphicsWidget *widget)
+{
+ return minimumHeightForWidth(height, minw, maxw, widget, false);
+}
+
+static QSizeF closestAcceptableSize(const QSizeF &proposed,
+ const QGraphicsWidget *widget)
+{
+ const QSizeF current = widget->size();
+
+ qreal minw = proposed.width();
+ qreal maxw = current.width();
+ qreal minh = proposed.height();
+ qreal maxh = current.height();
+
+ qreal middlew = maxw;
+ qreal middleh = maxh;
+ qreal min_hfw;
+ min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget);
+
+ do {
+ if (maxw - minw < 0.1) {
+ // we still havent found anything, cut off binary search
+ minw = maxw;
+ minh = maxh;
+ }
+ middlew = minw + (maxw - minw)/2.0;
+ middleh = minh + (maxh - minh)/2.0;
+
+ min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
+
+ if (min_hfw > middleh) {
+ minw = middlew;
+ minh = middleh;
+ } else if (min_hfw <= middleh) {
+ maxw = middlew;
+ maxh = middleh;
+ }
+ } while (maxw != minw);
+
+ min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
+
+ QSizeF result;
+ if (min_hfw < maxh) {
+ result = QSizeF(middlew, min_hfw);
+ } else {
+ // Needed because of the cut-off we do above.
+ result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh);
+ }
+ return result;
+}
+
static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
QRectF *rect, Qt::WindowFrameSection section,
- const QSizeF &min, const QSizeF &max)
+ const QSizeF &min, const QSizeF &max,
+ const QGraphicsWidget *widget)
{
- int height;
- int width;
+ const QRectF proposedRect = *rect;
+ qreal width = qBound(min.width(), proposedRect.width(), max.width());
+ qreal height = qBound(min.height(), proposedRect.height(), max.height());
+
+ QSizePolicy sp = widget->sizePolicy();
+ if (const QGraphicsLayout *l = widget->layout()) {
+ sp = l->sizePolicy();
+ }
+ const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight();
+
+ const bool widthChanged = proposedRect.width() < widget->size().width();
+ const bool heightChanged = proposedRect.height() < widget->size().height();
+
+ if (hasHFW) {
+ if (widthChanged || heightChanged) {
+ const qreal minh = min.height();
+ const qreal maxh = max.height();
+ const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget);
+ if (proposedHFW > proposedRect.height()) {
+ QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
+ width = effectiveSize.width();
+ height = effectiveSize.height();
+ }
+ }
+ }
+
switch (section) {
case Qt::LeftSection:
- width = qRound(qBound(min.width(), rect->width(), max.width()));
- rect->setRect(startGeometry.right() - width, startGeometry.top(),
- width, startGeometry.height());
+ rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
+ qRound(width), startGeometry.height());
break;
case Qt::TopLeftSection:
- width = qRound(qBound(min.width(), rect->width(), max.width()));
- height = qRound(qBound(min.height(), rect->height(), max.height()));
- rect->setRect(startGeometry.right() - width, startGeometry.bottom() - height,
- width, height);
+ rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height),
+ qRound(width), qRound(height));
break;
case Qt::TopSection:
- height = qRound(qBound(min.height(), rect->height(), max.height()));
- rect->setRect(startGeometry.left(), startGeometry.bottom() - height,
- startGeometry.width(), height);
+ rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height),
+ startGeometry.width(), qRound(height));
break;
case Qt::TopRightSection:
- height = qRound(qBound(min.height(), rect->height(), max.height()));
- rect->setTop(rect->bottom() - height);
- rect->setWidth(qBound(min.width(), rect->width(), max.width()));
+ rect->setTop(rect->bottom() - qRound(height));
+ rect->setWidth(qRound(width));
break;
case Qt::RightSection:
- rect->setWidth(qBound(min.width(), rect->width(), max.width()));
+ rect->setWidth(qRound(width));
break;
case Qt::BottomRightSection:
- rect->setWidth(qBound(min.width(), rect->width(), max.width()));
- rect->setHeight(qBound(min.height(), rect->height(), max.height()));
+ rect->setWidth(qRound(width));
+ rect->setHeight(qRound(height));
break;
case Qt::BottomSection:
- rect->setHeight(qBound(min.height(), rect->height(), max.height()));
+ rect->setHeight(qRound(height));
break;
case Qt::BottomLeftSection:
- height = qRound(qBound(min.height(), rect->height(), max.height()));
- width = qRound(qBound(min.width(), rect->width(), max.width()));
- rect->setRect(startGeometry.right() - width, startGeometry.top(),
- width, height);
+ rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
+ qRound(width), qRound(height));
break;
default:
break;
@@ -506,7 +619,8 @@ void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent
_q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
windowData->grabbedSection,
q->effectiveSizeHint(Qt::MinimumSize),
- q->effectiveSizeHint(Qt::MaximumSize));
+ q->effectiveSizeHint(Qt::MaximumSize),
+ q);
q->setGeometry(newGeometry);
}
}