QGraphicsWidget: overload two margins-setters with actual QMarginsF overloads

Replace manual memory management with unique_ptr and manual
re-implementations of QMarginsF with The Real Thing™.

The only noticeable difference should be that the checks for 0 now use
qFuzzyCompare() (by way of QMarginsF::isNull() and its operator==).

[ChangeLog][QtWidgets][QGraphicsWidget] Added QMarginsF overloads of
setContentsMargins() and setWindowFrameMargins().

Change-Id: I6b3bb87015fa52fdde245b7528cca4b8f9ce41e1
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Marc Mutz 2019-05-24 21:41:17 +02:00
parent 0eb26c1443
commit ca0c9f82cb
4 changed files with 67 additions and 60 deletions

View File

@ -473,8 +473,9 @@ relayoutChildrenAndReturn:
*/
/*!
Sets the widget's contents margins to \a left, \a top, \a right and \a
bottom.
\since 5.14
Sets the widget's contents margins to \a margins.
Contents margins are used by the assigned layout to define the placement
of subwidgets and layouts. Margins are particularly useful for widgets
@ -488,23 +489,17 @@ relayoutChildrenAndReturn:
\sa getContentsMargins(), setGeometry()
*/
void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
void QGraphicsWidget::setContentsMargins(QMarginsF margins)
{
Q_D(QGraphicsWidget);
if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0)
if (!d->margins && margins.isNull())
return;
d->ensureMargins();
if (left == d->margins[d->Left]
&& top == d->margins[d->Top]
&& right == d->margins[d->Right]
&& bottom == d->margins[d->Bottom])
if (*d->margins == margins)
return;
d->margins[d->Left] = left;
d->margins[d->Top] = top;
d->margins[d->Right] = right;
d->margins[d->Bottom] = bottom;
*d->margins = margins;
if (QGraphicsLayout *l = d->layout)
l->invalidate();
@ -515,6 +510,17 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre
QApplication::sendEvent(this, &e);
}
/*!
\overload
Sets the widget's contents margins to \a left, \a top, \a right and \a
bottom.
*/
void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
{
setContentsMargins({left, top, right, bottom});
}
/*!
Gets the widget's contents margins. The margins are stored in \a left, \a
top, \a right and \a bottom, as pointers to qreals. Each argument can
@ -528,18 +534,19 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right,
if (left || top || right || bottom)
d->ensureMargins();
if (left)
*left = d->margins[d->Left];
*left = d->margins->left();
if (top)
*top = d->margins[d->Top];
*top = d->margins->top();
if (right)
*right = d->margins[d->Right];
*right = d->margins->right();
if (bottom)
*bottom = d->margins[d->Bottom];
*bottom = d->margins->bottom();
}
/*!
Sets the widget's window frame margins to \a left, \a top, \a right and
\a bottom. The default frame margins are provided by the style, and they
\since 5.14
Sets the widget's window frame margins to \a margins.
The default frame margins are provided by the style, and they
depend on the current window flags.
If you would like to draw your own window decoration, you can set your
@ -547,29 +554,32 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right,
\sa unsetWindowFrameMargins(), getWindowFrameMargins(), windowFrameRect()
*/
void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
void QGraphicsWidget::setWindowFrameMargins(QMarginsF margins)
{
Q_D(QGraphicsWidget);
if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0)
if (!d->windowFrameMargins && margins.isNull())
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;
const bool unchanged = *d->windowFrameMargins == margins;
if (d->setWindowFrameMargins && unchanged)
return;
if (!unchanged)
prepareGeometryChange();
d->windowFrameMargins[d->Left] = left;
d->windowFrameMargins[d->Top] = top;
d->windowFrameMargins[d->Right] = right;
d->windowFrameMargins[d->Bottom] = bottom;
*d->windowFrameMargins = margins;
d->setWindowFrameMargins = true;
}
/*!
\overload
Sets the widget's window frame margins to \a left, \a top, \a right and
\a bottom.
*/
void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
{
setWindowFrameMargins({left, top, right, bottom});
}
/*!
Gets the widget's window frame margins. The margins are stored in \a left,
\a top, \a right and \a bottom as pointers to qreals. Each argument can
@ -583,13 +593,13 @@ void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *righ
if (left || top || right || bottom)
d->ensureWindowFrameMargins();
if (left)
*left = d->windowFrameMargins[d->Left];
*left = d->windowFrameMargins->left();
if (top)
*top = d->windowFrameMargins[d->Top];
*top = d->windowFrameMargins->top();
if (right)
*right = d->windowFrameMargins[d->Right];
*right = d->windowFrameMargins->right();
if (bottom)
*bottom = d->windowFrameMargins[d->Bottom];
*bottom = d->windowFrameMargins->bottom();
}
/*!
@ -624,8 +634,8 @@ QRectF QGraphicsWidget::windowFrameGeometry() const
{
Q_D(const QGraphicsWidget);
return d->windowFrameMargins
? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
? geometry().adjusted(-d->windowFrameMargins->left(), -d->windowFrameMargins->top(),
d->windowFrameMargins->right(), d->windowFrameMargins->bottom())
: geometry();
}
@ -638,8 +648,8 @@ QRectF QGraphicsWidget::windowFrameRect() const
{
Q_D(const QGraphicsWidget);
return d->windowFrameMargins
? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
? rect().adjusted(-d->windowFrameMargins->left(), -d->windowFrameMargins->top(),
d->windowFrameMargins->right(), d->windowFrameMargins->bottom())
: rect();
}
@ -751,8 +761,8 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
if (d->layout) {
QSizeF marginSize(0,0);
if (d->margins) {
marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right],
d->margins[d->Top] + d->margins[d->Bottom]);
marginSize = QSizeF(d->margins->left() + d->margins->right(),
d->margins->top() + d->margins->bottom());
}
sh = d->layout->effectiveSizeHint(which, constraint - marginSize);
sh += marginSize;
@ -1320,7 +1330,7 @@ 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->windowFrameMargins
? d->windowFrameMargins[d->Left] : 0;
? d->windowFrameMargins->left() : 0;
Qt::WindowFrameSection s = Qt::NoSection;
if (x <= left + cornerMargin) {
@ -1347,7 +1357,7 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
if (s == Qt::NoSection) {
QRectF r1 = r;
r1.setHeight(d->windowFrameMargins
? d->windowFrameMargins[d->Top] : 0);
? d->windowFrameMargins->top() : 0);
if (r1.contains(pos))
s = Qt::TitleBarArea;
}

View File

@ -111,9 +111,11 @@ public:
inline QRectF rect() const { return QRectF(QPointF(), size()); }
void setContentsMargins(qreal left, qreal top, qreal right, qreal bottom);
void setContentsMargins(QMarginsF margins);
void getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const override;
void setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom);
void setWindowFrameMargins(QMarginsF margins);
void getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const;
void unsetWindowFrameMargins();
QRectF windowFrameGeometry() const;

View File

@ -51,6 +51,8 @@
#include <QtWidgets/QStyleOptionTitleBar>
#include <QtWidgets/QGraphicsSceneMouseEvent>
#include <private/qmemory_p.h>
QT_BEGIN_NAMESPACE
void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags)
@ -109,8 +111,6 @@ QGraphicsWidgetPrivate::QGraphicsWidgetPrivate()
QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
{
// Remove any lazily allocated data
delete[] margins;
delete[] windowFrameMargins;
delete windowData;
}
@ -122,11 +122,8 @@ QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
*/
void QGraphicsWidgetPrivate::ensureMargins() const
{
if (!margins) {
margins = new qreal[4];
for (int i = 0; i < 4; ++i)
margins[i] = 0;
}
if (!margins)
margins = qt_make_unique<QMarginsF>();
}
/*!
@ -137,11 +134,8 @@ void QGraphicsWidgetPrivate::ensureMargins() const
*/
void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
{
if (!windowFrameMargins) {
windowFrameMargins = new qreal[4];
for (int i = 0; i < 4; ++i)
windowFrameMargins[i] = 0;
}
if (!windowFrameMargins)
windowFrameMargins = qt_make_unique<QMarginsF>();
}
/*!
@ -372,8 +366,8 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve
bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
QPointF pos = event->pos();
if (windowFrameMargins) {
pos.rx() += windowFrameMargins[Left];
pos.ry() += windowFrameMargins[Top];
pos.rx() += windowFrameMargins->left();
pos.ry() += windowFrameMargins->top();
}
bar.subControls = QStyle::SC_TitleBarCloseButton;
if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
@ -669,8 +663,8 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
QStyleOptionTitleBar bar;
// make sure that the coordinates (rect and pos) we send to the style are positive.
if (windowFrameMargins) {
pos.rx() += windowFrameMargins[Left];
pos.ry() += windowFrameMargins[Top];
pos.rx() += windowFrameMargins->left();
pos.ry() += windowFrameMargins->top();
}
initStyleOptionTitleBar(&bar);
bar.rect = q->windowFrameRect().toRect();

View File

@ -60,6 +60,8 @@
#include <QtWidgets/qsizepolicy.h>
#include <QtWidgets/qstyle.h>
#include <memory>
QT_REQUIRE_CONFIG(graphicsview);
QT_BEGIN_NAMESPACE
@ -78,8 +80,7 @@ public:
qreal titleBarHeight(const QStyleOptionTitleBar &options) const;
// Margins
enum {Left, Top, Right, Bottom};
mutable qreal *margins;
mutable std::unique_ptr<QMarginsF> margins;
void ensureMargins() const;
void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene = nullptr);
@ -193,7 +194,7 @@ public:
void ensureWindowData();
bool setWindowFrameMargins;
mutable qreal *windowFrameMargins;
mutable std::unique_ptr<QMarginsF> windowFrameMargins;
void ensureWindowFrameMargins() const;
#ifndef QT_NO_ACTION