Freeing allocated memory with Qt toolbars and actions - c++

Do I need to free Qt toolbars and actions?
I created them this way
QToolBar *tb = new QToolBar(this);
tb->setWindowTitle(tr("Edit Actions"));
addToolBar(tb);
QAction *a;
a = actionUndo = new QAction(...ecc..);
are these deallocated automatically or do I need to free them up?

In short, yes they are deallocated automatically as part of the Qt framework as it appears you are properly passing in the parent (i.e. this in your case). Also, in the case of the QToolBar, calling addToolBar will cause it to be 're-parented' if it didn't already have a correct parent.

Related

Would this QChangesOpacityEffect usage cause a potential memory leak? (but only way to force repaint...)

So, I am working with some QWidgets inside a QMdiArea, and i want to play with the opacity og a graphicview inside the QWidgets with a dial, using the QGraphicsOpacityEffect.
This is the slot that receives the dial signal to set the new opacity:
void MainWindow::changeWindow1Transparency(int dialValue)
{
QGraphicsOpacityEffect* op = new QGraphicsOpacityEffect(ui->graphicsView); //Potential memory leak here
op->setOpacity(qreal(dialValue)/255);
ui->graphicsView->setGraphicsEffect(op);
ui->graphicsView->repaint();
}
This is the only way i've managed to make the opacity change immediately when turning the dial. But I fear that this might cause a memory leak because of the new constantly creating new effects.
I have tried to set this QGraphicOpacityEffect *op as an attribute of the class. But then, when I turn the dial, the opacity doesn't change immediately but only when I move the window around the QMdiArea. The same happens when calling the QGraphicsView->GraphicsEffects().. Any ideas on why this is happening? how could I prevent the memory leak and at the same time force that the opacity changes immediately with the dial?
Thanks!
There shouldn't be a memory leak as long as you pass a parent object to your QGraphicsOpacityEffect or set a widget with the effect.
The way you've set it up ui->graphicsView->setGraphicsEffect(op), According to QWidget::setGraphicsEffect:
Sets effect as the widget's effect. If there already is an effect installed on this widget, QWidget will delete the existing effect before installing the new effect.
You've got yourself a guarantee that the intermediate objects will be deleted. With regards to the final GraphicsEffect, as your ui->graphicsView widget is destroyed, so does the GraphicsOpacityEffect (see Qt Object Trees and Ownership).
As for forcing the opacity changes to your dial, try adding repaint(); to your slot. This will repaint your entire widget. (And after that, also try parentWidget()->repaint() as the parent sometimes needs a little nudging.)
As Jeremy Friesner mentions in the comments and as you've tried before, it may be more efficient to set QGraphicOpacityEffect *op as a member of the class, calling op->setOpacity(x) in your slot without having to create a new effect each time the slot is triggered. Keep in mind the repaint semantics above.

Will QWizard delete QWizardPage or will it leak?

If I have QWizard, and I instantiate this without specifying parent, will it delete its pages when it goes out of scope or will they leak?
{
WelcomeWizard wiz;
wiz.addPage(new QWizardPage);
}
I think QWizard will delete them however I would really appreciate any more detailed explanation.
QWizard::addPage internally calls setPage, which calls page->setParent(...) as one of the first things done.
So yes, the wizard does take ownership of the pages, and they will be subject to normal QObject lifetimes. Deleting the wizard will delete all of the pages.
Yes Qt automatically deletes the child of a widget when the parent is deleting

What is the purpose of QWidget's parent?

If I subclassed any widget the usual pattern is:
ZTabWidget::ZTabWidget(QWidget *parent):QTabWidget(parent){
blah ... blah ...
}
The usual pattern is:
WidgetB widgetb = new WidgetB(widgeta)
widgeta.addWidget(widgetb);
Is there any harm in having all my widgets assigned MainWindow as their respective parent - even though, following the trails of addWidget hierarchy, most of those widgets have another widget as the addWidget parent:
WidgetB widgetb = new WidgetB(mainWindow)
widgeta.addWidget(widgetb);
The reason I wish to do this is because mainWindow holds all the main items of the application and that I could have my any of my subclassed widgets reference those items.
In fact, I am thinking of a proxy widget that is merely used to hold some common references and use that proxy widget as the common parent of all my widgets. Any problem in that?
Exactly, what is the use of having registered a parent for a QWidget? Is the parent even used internally?
Does the addWidget parent have to be the same as the constructor parent?
There are actually two aspects two your questions:
Memory management
The tree-like organization of QWidgets (and in fact of any QObjects) is part of the memory management strategy used within the Qt-Framework. Assigning a QObject to a parent means that ownership of the child object is transferred to the parent object. If the parent is deleted, all its children are also deleted. From the docs:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor. You can look for an object by name and optionally type
using findChild() or findChildren().
This means you can organize your widgets in any way that seems sensible to you (as long as you don't introduce memory leaks). I think, however, that it is a common practice to assign all the widgets to their respective container (either explicitly, or better, using methods like addWidget).
If a widget is assigned to a QLayout using addWidget, then ownership of the widget is transferred to the layout (which in turn is probably owned by another surrounding layout or the main window). So yes, the relationship defined by this method includes the more general parent-child relationship described above.
Now, as soon as the main window gets destroyed, basically the whole tree of QObjects is deleted as you'd expect.
Consequently, if you leave an object "parentless", it is your own responsibility to delete it.
GUI semantics
As Frank noted correctly, in some contexts the parent-child relationship between QWidgets also bears a semantically meaning to the GUI framework. An example of this are modal dialogs, who block their parent as long as they stay open.

Qt Widget Memory Management

So I'm a little confused about Qt's memory management. I was looking at the beginning samples and tutorials and saw this
QApplication app(argc, argv);
QWidget window;
QLabel *label = new QLabel(QApplication::translate("windowlayout", "Name:"));
QLineEdit *lineEdit = new QLineEdit();
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(label);
layout->addWidget(lineEdit);
window.setLayout(layout);
window.setWindowTitle(
QApplication::translate("windowlayout", "Window layout"));
window.show();
return app.exec();
Which is just fine except that I don't see any freeing of memory when they create the new widgets, now is this just for the tutorial so they don't confuse people or is the memory management handled automatically by Qt. Cause looking at this I would have to believe that there was a memory leak because nothing was getting freed.
Widgets are destroyed by their parents (when you call layout->addWidget, for example, layout takes ownership of the passed widget), when those are destroyed. In your case, window will get destroyed at the end of the scope (when app.exec returns), which in turn will destroy the layout, which in turn will destroy label and the edit box.
Object Trees & Ownership in Qt docs.
Qt builds an internal tree of things (layouts, widgets, dialogs, ...) that are freed, whenever Qt thinks this is ok. This hierarchy is built with the parent-parameter in the constructor of "things" or whenever the responsibility is transferred by some other function call (like addWidget). So you are not even allowed to delete "things", when Qt or some widget has taken over responsibility. See the docs in Qt on this.
In Qt objects are freed based on the hierarchy. i.e. When QObject is freed all it's children will be freed (based on the parents passed as arguments to object constructor).

How to change/swap the layout of a widget?

I am working on an application in which I need to change the layout of my current tab when a radio button is pressed.
I am using the following code to swap the layout:
changed_layout = new QVBoxLayout;
label1 = new QLabel(string);
delete main_layout;
changed_layout->addWidget(label1);
setLayout(changed_layout);
But when I click the button the software exits (crashes).
You shouldn't try to directly delete QObjects with delete, call ojbect->deleteLater() and set your pointer to null. The Qt framework will safely delete the object after any slots have been exited and control has returned to the event loop.
In your code, change the line delete main_layout; to:
main_layout->deleteLater();
main_layout = NULL;
Update:
The comment from Steve S is correct. To quote Qt docs for setLayout()..
If there already is a layout manager
installed on this widget, QWidget
won't let you install another. You
must first delete the existing layout
manager (returned by layout()) before
you can call setLayout() with the new
layout.layout.
Since setLayout() is a special case of reparenting widgets, we must delete the old layout first and then set the new layout. We would have to be very sure of the signal/slot call stack we are in to call delete().
An alternative would be to setup the new layout as much as possible and then connect a slot to the old layouts destroyed() signal and then call deleteLater() on it. In the slot for the destroyed() signal you should be able to call setLayout() with the new layout.
If this sounds complicated, it's because it is. Changing and destroying layouts at runtime is unusual. If I found that I had to do something like this, I would probably create something like a gridLayout at the top of the hierarcy with the different layouts I would need set inside it and then move the child widgets from layout to layout without having to create and destroy them at runtime.