Plug new leaks in tst_QFormLayout

The new takeRow() functions return a pair of pointers to
QLayoutItems and, as the name particle 'take' suggests,
releases ownership of these layout items. Which in turn
means that the caller of the function is supposed to deal
with them.

This was not done here.

To fix, write a RAII class that takes ownership of the
returned layout items, deleting them when it goes out of
scope or gets a new value assigned (only move special
member functions are implemented, making the class move
-only).

Deleting the QLayoutItems is not so easy, though:
QFormLayout has a special function for clearing the
QLayoutItems out, so it appears that just calling their
destructors is not going to fly (though I don't know off
the top of the head why that should be a problem).

Solve this, for now, by adding the layout items back into
a temporary QFormLayout for destruction.

Change-Id: If862989207b20f1e3f757c19ec9d498c4491184f
Reviewed-by: Samuel Gaist <samuel.gaist@edeltech.ch>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2016-09-28 10:44:25 +02:00
parent 512934f7e7
commit 080daae7cd

View File

@ -51,6 +51,44 @@ static inline void setFrameless(QWidget *w)
w->setWindowFlags(flags);
}
struct QFormLayoutTakeRowResultHolder {
QFormLayoutTakeRowResultHolder(QFormLayout::TakeRowResult result) Q_DECL_NOTHROW
: labelItem(result.labelItem),
fieldItem(result.fieldItem)
{
}
~QFormLayoutTakeRowResultHolder()
{
// re-use a QFormLayout to recursively reap the QLayoutItems:
QFormLayout disposer;
if (labelItem)
disposer.setItem(0, QFormLayout::LabelRole, labelItem);
if (fieldItem)
disposer.setItem(0, QFormLayout::FieldRole, fieldItem);
}
QFormLayoutTakeRowResultHolder(QFormLayoutTakeRowResultHolder &&other) Q_DECL_NOTHROW
: labelItem(other.labelItem),
fieldItem(other.fieldItem)
{
other.labelItem = nullptr;
other.fieldItem = nullptr;
}
QFormLayoutTakeRowResultHolder &operator=(QFormLayoutTakeRowResultHolder &&other) Q_DECL_NOTHROW
{
swap(other);
return *this;
}
void swap(QFormLayoutTakeRowResultHolder &other) Q_DECL_NOTHROW
{
qSwap(labelItem, other.labelItem);
qSwap(fieldItem, other.fieldItem);
}
QLayoutItem *labelItem;
QLayoutItem *fieldItem;
};
class tst_QFormLayout : public QObject
{
Q_OBJECT
@ -814,7 +852,7 @@ void tst_QFormLayout::takeRow()
QCOMPARE(layout->count(), 3);
QCOMPARE(layout->rowCount(), 2);
QFormLayout::TakeRowResult result = layout->takeRow(1);
QFormLayoutTakeRowResultHolder result = layout->takeRow(1);
QVERIFY(w2);
QVERIFY(result.fieldItem);
@ -853,7 +891,7 @@ void tst_QFormLayout::takeRow_QWidget()
QCOMPARE(layout->count(), 3);
QCOMPARE(layout->rowCount(), 2);
QFormLayout::TakeRowResult result = layout->takeRow(w1);
QFormLayoutTakeRowResultHolder result = layout->takeRow(w1);
QVERIFY(w1);
QVERIFY(result.fieldItem);
@ -898,7 +936,7 @@ void tst_QFormLayout::takeRow_QLayout()
QCOMPARE(layout->count(), 3);
QCOMPARE(layout->rowCount(), 2);
QFormLayout::TakeRowResult result = layout->takeRow(l1);
QFormLayoutTakeRowResultHolder result = layout->takeRow(l1);
QVERIFY(l1);
QVERIFY(w1);