diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-09-08 00:14:12 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-09-08 00:14:12 (GMT) |
commit | f6c08f5e68c90338a8402c0912cd6be72e84b1e6 (patch) | |
tree | d928f975e686b752cd1fc47eca812f376d9d0a03 /src/gui/graphicsview | |
parent | 276a44c0867a76a90b425baa8dcbda733d25b3fb (diff) | |
parent | 0cbbc9cb9e87a3a39ee1597f4cea1c2b77d8f8da (diff) | |
download | Qt-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.cpp | 36 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget.cpp | 6 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget_p.cpp | 164 |
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); } } |