PDA

View Full Version : Dynamically change position of grid layout items



embeddedmz
3rd July 2019, 17:10
Hi,

I'm using this method to change the position of 2 widgets placed in a grid layout, I took the code from https://stackoverflow.com/questions/33140244/dynamically-change-position-of-grid-layout-items


void MyApp::swapWidgets(QGridLayout* grid, QWidget* widgetA, QWidget *widgetB)
{
if (!grid)
{
return;
}

int indexA = grid->indexOf(widgetA);
int indexB = grid->indexOf(widgetB);
int row1, column1, rowSpan1, columnSpan1;
int row2, column2, rowSpan2, columnSpan2;

grid->getItemPosition(indexA, &row1, &column1, &rowSpan1, &columnSpan1);
grid->getItemPosition(indexB, &row2, &column2, &rowSpan2, &columnSpan2);

grid->takeAt(indexA);
grid->takeAt(indexB);

grid->addWidget(widgetB, row1, column1, rowSpan1, columnSpan1);
grid->addWidget(widgetA, row2, column2, rowSpan2, columnSpan2);
}

All my widgets belong to the auto-generated GUI class (from the UI file).

I ran Valgrind and I noticed leaks when this function gets called, the number of leaks is strangely lower than the calls to the swapWidgets method :



==24440== 88 bytes in 1 blocks are definitely lost in loss record 11,181 of 15,003
==24440== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==24440== by 0x1E8BA469: QLayoutPrivate::createWidgetItem(QLayout const*, QWidget*) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E8B95F0: QGridLayout::addWidget(QWidget*, int, int, int, int, QFlags<Qt::AlignmentFlag>) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x4AA313: Ui_MyApp::setupUi(QWidget*) (==24440== 88 bytes in 1 blocks are definitely lost in loss record 11,181 of 15,003
==24440== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==24440== by 0x1E8BA469: QLayoutPrivate::createWidgetItem(QLayout const*, QWidget*) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E8B95F0: QGridLayout::addWidget(QWidget*, int, int, int, int, QFlags<Qt::AlignmentFlag>) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x4AA313: Ui_MyApp::setupUi(QWidget*) (ui_MyApp.h:997)
==24440== by 0x47D361: MyApp::MyApp(QWidget*) (MyApp.cpp:89)
==24440== by 0x47AA51: main (main.cpp:36)
==24440== .h:997)
==24440== by 0x47D361: MyApp::MyApp(QWidget*) (MyApp.cpp:89)
==24440== by 0x47AA51: main (main.cpp:36)
==24440==
==24440== 88 bytes in 1 blocks are definitely lost in loss record 11,182 of 15,003
==24440== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==24440== by 0x1E8BA469: QLayoutPrivate::createWidgetItem(QLayout const*, QWidget*) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E8B95F0: QGridLayout::addWidget(QWidget*, int, int, int, int, QFlags<Qt::AlignmentFlag>) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x49746D: MyApp::swapWidgets(QGridLayout*, QWidget*, QWidget*) (MyApp.cpp:3765)
==24440== by 0x4807E8: MyApp::ConnectSignalsSlots()::{lambda(bool)#15}::o perator()(bool) const (MyApp.cpp:758)
==24440== by 0x49ACF8: QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<bool>, void, MyApp::ConnectSignalsSlots()::{lambda(bool)#15}>::call({lambda(bool)#15}&, void**) (qobjectdefs_impl.h:130)
==24440== by 0x49A82C: void QtPrivate::Functor<MyApp::ConnectSignalsSlots()::{lambda(bool)#15}, 1>::call<QtPrivate::List<bool>, void>({lambda(bool)#15}&, void*, {lambda(bool)#15}&*) (qobjectdefs_impl.h:240)
==24440== by 0x49A3DB: QtPrivate::QFunctorSlotObject<MyApp::ConnectSignalsSlots()::{lambda(bool)#15}, 1, QtPrivate::List<bool>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobject_impl.h:168)
==24440== by 0x1F4DB8B2: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib64/libQt5Core.so.5.9.2)
==24440== by 0x1E994F41: QAbstractButton::clicked(bool) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E995179: ??? (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E996732: ??? (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440==
==24440== 88 bytes in 1 blocks are definitely lost in loss record 11,183 of 15,003
==24440== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==24440== by 0x1E8BA469: QLayoutPrivate::createWidgetItem(QLayout const*, QWidget*) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E8B95F0: QGridLayout::addWidget(QWidget*, int, int, int, int, QFlags<Qt::AlignmentFlag>) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x4974A4: MyApp::swapWidgets(QGridLayout*, QWidget*, QWidget*) (MyApp.cpp:3766)
==24440== by 0x4807E8: MyApp::ConnectSignalsSlots()::{lambda(bool)#15}::o perator()(bool) const (MyApp.cpp:758)
==24440== by 0x49ACF8: QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<bool>, void, MyApp::ConnectSignalsSlots()::{lambda(bool)#15}>::call({lambda(bool)#15}&, void**) (qobjectdefs_impl.h:130)
==24440== by 0x49A82C: void QtPrivate::Functor<MyApp::ConnectSignalsSlots()::{lambda(bool)#15}, 1>::call<QtPrivate::List<bool>, void>({lambda(bool)#15}&, void*, {lambda(bool)#15}&*) (qobjectdefs_impl.h:240)
==24440== by 0x49A3DB: QtPrivate::QFunctorSlotObject<MyApp::ConnectSignalsSlots()::{lambda(bool)#15}, 1, QtPrivate::List<bool>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobject_impl.h:168)
==24440== by 0x1F4DB8B2: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib64/libQt5Core.so.5.9.2)
==24440== by 0x1E994F41: QAbstractButton::clicked(bool) (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E995179: ??? (in /usr/lib64/libQt5Widgets.so.5.9.2)
==24440== by 0x1E996732: ??? (in /usr/lib64/libQt5Widgets.so.5.9.2)

What can I change in swapWidgets() to fix that leak ?

The first leak above, shows that the GUI object (autogeneratged) is no longer the owner of something (QGridLayout or QWidget, I dunno) manipulated by swapWidgets.

d_stranz
3rd July 2019, 19:38
I am guessing that the leaks are the two QLayoutItem instances returned by the takeAt() calls. You can simply add a local variable to store the return value then call delete() on it.

Qt's semantics for most takeAt() type calls is that ownership of whatever is being taken is transferred to the caller, so it is the caller's responsibility to clean up.

embeddedmz
4th July 2019, 10:42
Thank you very much, the leaks are gone !