destroy non-Qwidget member variable in custom QWidget - qt

For a custom QWidget class that contains both QWidget member variable and non-widget member variable, what is the proper way to write the destructor of the class? For example, I have
class CustomWidget: public QWidget {
Q_OBJECT
public:
QWidget* x_widget;
SomeOtherClass* x_non_widget;
}
and set the parent of x_widget to this when creating it, how should I write the destructor? Should I just put delete x_non_widget in the destructor?

QWidget inherits from QObject, so if its parent is set, then the object gets deleted automatically when the parent is being destroyed. Since you set this as parent, then the child x_widget gets automatically deleted when the parent CustomWidget instance is deleted. So no destructor is needed in this case.
Note however that if you put a widget into a layout, then it is re-parented (if it already had a parent) to the widget which holds the layout. But I guess this is not your case.
If your non-widget object is derived from QObject then you can set its parent too. And then you do not need to delete it in destructor because it will be deleted automatically the same way as widgets.
If your non-widget is not derived from QObject or you do not want to set a parent for it (for any reason, e.g. you move it to a thread), then you can wrap it in some owning/strong smart pointer such as std::unique_ptr, std::shared_ptr or QScopedPointer. Then it will be deleted automatically via the smart pointer. You do not need to delete it in the destructor either.
And only if you do not want to wrap it in any such an owning/strong smartpointer, you need to delete it in the destructor manually.
PS: Aside from the question you have, for non-owned members kept by pointer inherited from QObject you can also benefit from using QPointer, which is an extremely handy class which ensures automatic nullification of the pointer when the object gets deleted anywhere in the code. So no more invalid pointers to deleted QObjects... But unlike owning/strong smart pointers, QPointer does not ensure automatic object deletion.

Related

Issue regarding setting parent of widget in Qt

From this post here, in general:
All QObjects will delete their own child objects automatically. (See
docs here.) QWidgets are QObjects. So as long as you establish a
parent/child relationship, you do not need to manually delete your
objects. To do that, simply pass a pointer to the parent object to the
constructor:
QLabel *label1 = new QLabel; // <<- NEED TO DELETE
QLabel *label2 = new QLabel(some_parent_obj); // Will be deleted when some_parent_obj is deleted
So some questions arises:
Does every widget necessary needed/required a parent? If no, what are the exceptions? If yes, what happens to widgets without parent?
I asked this because from examples in Qt Docs, some example widgets have parents (QLabel example) but some doesn't (QBarChart example, and also QFont, QColor, etc...).
So I'm wondering if there's an exception, or those widgets just don't need any parents, or if I declare them with new for some reason, I have to delete afterward.
And vice versa...
Does a widget without parent guarantee to cause a memory leak (or something similar) when the widget which it stays in (not necessary its parent) is deleted? Or if it's removed from a layout without any deletion happening?
Because from my experience with my code, I've created probably quite a lot (~100) of widgets and other stuffs without neither setting any parent (nor using delete afterward), and the project appears to run fine without any stalls even after a while (the effect might be underlying though, as I haven't run Memcheck), hence this question is here.
Does every widget necessary needed/required a parent?
If you want them to be deleted automatically - yes. But...
If no, what are the exceptions? If yes, what happens to widgets without parent?
You do not need to provide a parent to widget if you attach it to layout using QLayout::addWidget. If you look into source code, you'll see that when you do so, it automatically attaches layout's parent as widget's parent(unless you didn't attach layout to any widget).
But if you leave the widget created with new without parent and do not attach to anything - it is leaking memory. You must delete it either using delete or QObject::deleteLater. The last option is recommended when object has any connections.
Does a widget without parent guarantee to cause a memory leak (or something similar) when the widget which it stays in (not necessary its parent) is deleted? Or if it's removed from a layout without any deletion happening?
As I already mention QLayout::addWidget sets parent for added widget, so the answer is no. Also note, that when you call QLayout::removeWidget, it removes only QLayoutItem from layout, but widget's parent stays the same as it was after calling QLayout::addWidget.

How to make QPushButton to be in checked state by default?

I am using QPushButton.setCheckable(True), by default button is not checked, but I want it to be checked from the beginning. I couldn't find anything in the documentation.
As the name says, setCheckable sets if the button is checkable or not.
setChecked() sets whether a checkable button is actually checked or not.
Remember that most Qt classes inherit from a superclass (so it also inherits all its properties and functions), you can check the inheritance in the header of the documentation, and there's also a link named "List of all members, including inherited members".
The full inheritance of QPushButton is:
QPushButton > QAbstractButton > QWidget > QObject, QPaintDevice
So, it means that QPushButtons also has all functions and properties of QAbstractButton, QWidget, QObject and QPaintDevice.
This also means that if you really want to know what a class does, you should better study all the documentation related to all the classes it inherits from.

QMainWindow and ownership takeover policy

I stumbled upon this in the documentation for QMainWindow::setMenuBar(QMenuBar * menuBar):
Note: QMainWindow takes ownership of the menuBar pointer and deletes it at the appropriate time.
Example code (in a method of a class deriving from QMainWindow):
QMenuBar * menuBar = new QMenuBar(this);
setMenuBar(menuBar) // <-- immediately transfer ownership
// use menuBar pointer to add actions, menus, and what not
Can I still rely on my local pointer to my QMenuBar after a call to setMenuBar? I mean, is it completely guaranteed?
When I delete my QMainWindow derived class, the QMenuBar object is also deleted because the QMainWindow is set as its parent when constructing it - but what policy lies in the later "ownership takeover" through setMenuBar other than a copy of reference/pointer?
Yes, it's safe to use that pointer as long as the object that took ownership is alive.
The fact that QMainWindow "takes ownership" of the menu means that it will take care of deleting it when it is not needed anymore. This is very common for Qt, see the Object Trees & Ownership documentation.
That being said, your sample code could be rewritten like this:
QMenuBar *menu = menuBar();
This will create an empty menu if necessary, so you don't have to worry about any transfer of ownership. Just call that member function whenever you need to act on the windows's menu bar.

I want to extend dropEvent() (QListWidget), should I completely reimplement it?

I have a QListWidget and I have set it to accept drops, the mode to be DragDrop etc and I can move QListWidgetItems all around the place (inside the QListWidget of course).
I like this behavior and I want it to let it as is, but I also want my QListWidget to accept drops from a QTreeWidget as well. If I attempt to reimplement the dropEvent() of my QListWidget then I lose the default behavior.
Is there any way to just extend the current behavior so as to have both drag-drop between listwidget items and drag-drop from the treewidget to the listwidget or I have to completely re-write both behaviors in my dropEvent() reimplementation?
Thanks a lot for any answers :)
Two ways:
implement a standalone event filter and make it act upon QEvent::Drop. Install it on your original QListWidget. Return false so that the original dropEvent() handler is called afterwards.
inherit from QListWidget, reimplement dropEvent(evt) and as a last statement, call QListWidget::dropEvent(evt);. Your original behavior will be retained.
No.
Subclass QListWidget, reimplement
virtual void QListWidget::dropEvent ( QDropEvent * event )
and explicitly call
QListWidget::dropEvent(event);
whenever you need the default behavior.
How to call a parent class function from derived class function?

Is there a gracefully way to expose slots of child widgets?

In my custom widget, there are seven labels included as child widgets. Their texts and text formats should be set by user of the parent widget. I created 14 slots to accomplish this:
void setCenterText(const QString &text) {
ui->labelCenter->setText(text);
}
void setRightText(const QString &text);
...
Can it be done via something like: connect(parent, slot(a), child, slot(b)) and a signal connected to the parent slot is automatically forwarded to the child widget?
Can it be done via something like: connect(parent, slot(a), child,
slot(b)) and a signal connected to the parent slot is automatically
forwarded to the child widget?
You can't connect slots to slots, but more importantly, without specifying the target widget in another argument, there is no way for the parent widget to know which child needs modifying.
Although what you are doing is laborious, it is a basic tennant of aggregate-based component building, and it does offer advantages - primarily the ability to very finely tune exactly what child widget properties are exposed to the programmer.

Resources