To get a list of all the QWidgets created in an application we can simply call QApplication::allWidgets().
I've read the documentation, and I haven't found anything like this to get a list of all QObjects. If an application creates stand-alone QObjects that are not QWidgets I have no such function to use.
Is there a method to obtain such a list?
To begin with it's important to understand the difference between the QObject and QWidget classes.
class QObject
QObject instances have a pointer to their parent which may or may not be a null pointer. It's quite legitimate to create a QObject instance without a parent so long as you understand that it is your responsibility for that instance's lifetime i.e. if you don't delete it you will leak memory.
class QWidget
Although it appears you can create a QWidget without a parent, you can't. When you create an instance of a QWidget "without a parent" (i.e. by supplying a null pointer or letting it default to a null pointer) it's parent effectively gets set to your application's QApplication1 instance.
Is there a method to obtain such a list?
No. The reason QApplication::allWidgets() works is due to the fact that all QWidget instances have a pointer to them which is stored in your single QApplication instance. There is no central store of QObject pointers and therefore no in-built way of retrieving them.
One way around this is to ensure yourself that all QObjects instances (or instances of classes which inherit QObject) have a valid parent. Then you can use the QObject functions children(), findChild() and findChildren() to get pointers to these objects.
These are powerful tools, and like anything powerful, use them with care! Make sure you understand C++ object life spans before you use these in production code.
Notes:
QApplication inherits from QCoreApplication which inherits from QObject. There are some restrictions placed on how QApplication is used by the Qt framework.
Related
In a debug build I would like particular objects of my program to register themselves in some global registry so I can have a view in my app detecting them and showing theirs statuses.
As all of them are QObjects I was wondering if there is a clever way of registering them in some global QObjects list (which I am not aware of). I cannot use regular hierarchy as some of these objects simply never become a child of any other QObject.
Since QApplication inherits QObject you could just set your active QApplication as parent of all QObjects not fitting into your normal application tree. After closing all windows you could then check all children of QApplication for leaked QObjects by calling const QObjectList & QObject::children() const.
I have a fairly complex MVC structured application and I want a convenient way to update a QStatusBar from almost any part of it. My understanding is that I would have to pass around a lot of references to my QStatusBar or set up a bunch of signals in my controllers. It would get messy.
I also understand that QApplication is essentially a singleton. Would it be an acceptable idea to add a slot to it so that I could get the instance of QApplication from anywhere and emit to it?
Alternatively, what is a reasonable way to communicate global-ish things in my application without littering the controllers and views with references to widgets parented elsewhere?
How about implement singleton, that allow communication between components and gui, something like:
#include <statuscontroller.h>
StatusController::instance()->setStatus("Status string");
In this case only StatusController contain pointer to QStatusBar and available globally in gui thread.
With QObject as base class for StatusController you could use signals and slots.
When using a Qt container as Qlist, Qvector etc to hold some class (say a complex class with many data members and logics) and calling insert/append/push_back will the object added to the container be inserted to the container or it will be copied (cctor) ?
Suppose it is copied then If I dynamically allocate it and pass a pointer then only the pointer will be copied? And if I pass the object itself then I need to free the memory I've allocated before because the object is copied ?
I could some official documentation so I'm asking here...
Thanks
In the case of QObject derived objects, you have to use dynamic allocation and just put pointers in the container, because such objects have unique identities and as such are prohibited from copying. In that case only the pointer is copied around, which is just an integer, the copying of which has no effect on the actual object it points to. With dynamically allocated objects you have to either manage lifetime manually or use Qt's parent/child functionality to have objects "collected" by their parent objects.
The values stored in the various containers can be of any assignable data type. To qualify, a type must provide a default constructor, a
copy constructor, and an assignment operator. This covers most data
types you are likely to want to store in a container, including basic
types such as int and double, pointer types, and Qt data types such as
QString, QDate, and QTime, but it doesn't cover QObject or any QObject
subclass (QWidget, QDialog, QTimer, etc.). If you attempt to
instantiate a QList, the compiler will complain that
QWidget's copy constructor and assignment operators are disabled.
As the quoted text above indicates, when placing the actual instances in a container, copying of the object will occur. In this case you don't have to manually delete anything, since the source of the copy would typically be a local object and often a temporary, of which the compiler will take care.
"Placement new" is a C++ feature you can use to specify the place the object is constructed in memory, but it comes at complexity of managing it and some limitations. The advantages of placement new and memory pools rarely outweigh the increase of complexity and loss of flexibility.
Why the QMainWindow's destructor is not virtual? If I inherit a class MainWindow from QMainWindow and have some pointer attribute on it I can't delete the memory using MainWindow's destructor.
QMainWindow's destructor is an override of an already existing destructor (QWidget::~QWidget()) which in turn is an override of a virtual destructor (virtual QObject::~QObject()). Thus, QMainWindow::~QMainWindow() is virtual. The same rules apply as with normal member functions.
QObject's destructor has been declared as virtual. QMainWindow is derived from QObject indirectly. I belive QMainWindow's destruct does not need virtual in this case. Did you set breakpoint in QMainWindow's destructor while deleting your derived class?
This is a defect in Qt (failure to adhere to CBP); it is best practice to always carry-over modifiers, especially virtual, in all derived classes, exactly to avoid this kind of problem.
NOT carrying-over the the virtual declaration means that, as a user, I have to not just lookup the class, but also ALL it's parents, to make sure the method(s) I want to override are virtual or not. A little laziness by the developers costs me lots of time.
Arguments about 'maintainability' are irrelevant; it makes the class harder to use (there will be many, MANY more users than maintainers...)
Can a class inherited from QThread and having run method can have other methods and can it be used like another normal ( not inherited from QThread) class?
Yes, a class that inherits from QThread is still a normal class. However, care must be taken to synchronize calls to member functions that occur in a different thread context (i.e. calls from outside of the run method) as necessary. Read about Thread Support in Qt for more details. Herb Sutter has a nice collection of articles discussing different aspects of concurrency as well.