Sorting QObject children - qt

i noticed that QObject::children() method return a const reference to QObjectList, that contains the children of the qobject. Will it be safe to cast away the constness and sort the list with qSort?
Thanks
Anton

No, you should not do this. This is the definition of QObject::children():
inline const QObjectList &children() const { return d_ptr->children; }
This means you directly get the reference of the internal objectlist.
And the documentation says:
Note that the list order changes when
QWidget children are raised or
lowered. A widget that is raised
becomes the last object in the list,
and a widget that is lowered becomes
the first object in the list.
It looks like a bad idea to mess with this list.

Maybe. But why risk it? Can't you just copy the QObjectList and sort your local copy?

Related

How to pass a QTextEdit to signal/slot mechanism

I have read some topics here about signals and slots and its parameters but found nothing about following problem:
I am working with Qt 5.7
I simply have 2 classes, inside 1st, I want to emit signal with string message and location(or specific object) where to display it.
Now it is like this: I have 1st class where I emit signal :
emit signalWriteToTextEdit("hallo","textEdit_3");
What I want to do is somehow pass as the second argument an object like textEdit. No QString as its now.
Inside 2nd class is the slot:
void writeToTextEdit(QString info, QString where){
where.append(info); //I would like to do something like this
}
Just dont know how to consider that second parameter "where" as accessible object for example textEdit, so I could change its content.
I am thinking also if this is possible:
Is there some method for Ui object like finding elements by name?
Is it possible to go with foreach over all elements in ui and check their names...? I tried but dont know how to go through that.
If its not clear, I will explain more
After a little digging, I came across the QObject::findChild function. This will allow a string lookup recursively through the UI, those I am unsure of performance.
Edit for more detail:
Returns the child of this object that can be cast into type T and that is called name, or 0 if there is no such object. Omitting the name argument causes all object names to be matched. The search is performed recursively.
If there is more than one child matching the search, the most direct
ancestor is returned. If there are several direct ancestors, it is
undefined which one will be returned. In that case, findChildren()
should be used.
Just use QWidget* or QObject* (if it is not always a widget) as the argument type
signals:
void writeToTextEdit(const QString &what, QWidget *where)
or if it is always a QTextEdit even more specifically
signals:
void writeToTextEdit(const QString &what, QTextEdit *where)
Though it is not clear why the code needs to emit a signal if it has access to the target object, it could simply call setText directly

Qt QAbstractItemModel function data() called with undefined role

I want to create a custom list using QListView and so I had to extend QListView, QItemDelegate and QAbstractListModel and then implement the specific methods, along with QAbstractItemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const.
It displays correctly on the screen at first glance, but the problem occurs after populating the list model.,The function data(index,role) is called 4-5 times per item model with different roles (some of them undefined roles/out of range/probably random). And it occurs not only after the initialization of the list model! When I hover a list element, the view calls data(index,role) with the correct index and role but right afterwards it is called again with an unexpected role value.
It seems an awkward behavior. I couldn't find the source of the strange calls. I put logs in every method of my custom classes to be sure that I'm not calling by mistake the data(index,role) method with wrong values.
Does anyone have some ideas where to look at or why this strange calls occur?
EDIT
The source of the "strange" calls is in:
QSize CDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
return QSize(QItemDelegate::sizeHint(option, index));
}
somehow when calling QItemDelegate::sizeHint() it triggers data() with different role values.
In my case I have defined role values starting from 0(0,1,2,3). According to #Jens those values are reserved. Changing the starting value of my custom roles solved my problem.
Custom roles start at 0x100, 0..3 are roles defined by Qt. See the list of roles in qnamespace.h. 13 for example ist SizeHintRole.
The different role calls stem from the interns of QListView, which is trying to figure out, how the cells should be displayed. Example: If you want to change the font of a row, you simply add the switch for FontRole to your data() implementation and pass back a bold font whenever something is important and should be displayed in bold.

What is an appropriate place to initialize QWidgets?

What is the best way (place) to initialize QWidgets, when you add them programmatically?
I can think of ways to do it:
1) Create instances in the definition file and then initialize them in the initializer list. This seems to be the right way, but it becomes kind of sloppy the more QWidgets you need to add to the Window.
class SomeWindow : QDialog{
...
private:
QLabel label1;
QLabel label2;
...
}
SomeWindow::SomeWindow(...) : QDialog(...),
label('label1 text'), label('label2 text')
{
...
layout.addWidget(&label1);
layout.addWidget(&label2);
...
}
2) Coming from C# I tend to like this, but it seem to generate memory leak...
SomeWindow::SomeWindow(...) : QDialog(...)
{
QLabel* label1 = new QLabel('label1 text');
QLabel* label2 = new QLabel('label2 text');
...
layout.addWidget(label1);
layout.addWidget(label2);
...
}
Is there a better way to do this that I'm missing?
I appologize for the newbie question.
Qt use his own system to delete parent-children QObject derived classes. When you delete object, all children are deleted too.
With the first code, you have 2 destructions (in destructor of SomeWindow and with QObject system), then this code is illegal (only with Qt ; with C++ standard code, it's good)
With the second code, labels are delete by QObject system, you don't have memory leak. No need to keep pointer on objects.
#Jairo
Setting parent in constructor is not the only way to add children to objects. In particular, here, QLayout::addWidget reparent objets (if layout is correctly child of object)
#msgmaxim
Be carefull, layout must not be local variable in constructor
An advantage to having pointers to widgets in the headers, rather than the actual objects, is that you don't need to include all the headers for the widgets, but just forward declare them. This increases compilation time, which can be considerably noticeable in large projects.
In addition, if you have a dialog and are just adding a lot of widgets, such as a QLabel, you can make the code neater by doing this in the implementation: -
layout.addWidget(new QLabel('label1 text'));
layout.addWidget(new QLabel('label2 text'));
layout.addWidget(new QLabel('label3 text'));
layout.addWidget(new QLabel('label4 text'));
As has been mentioned, Qt's parent system will take care of cleaning up the widgets when their parent is deleted.
Of-course, if you want to change a property, such as the text, you'd then need to find the widget from the layout's children, but often QLabel, as its name implies, just labels an item and its properties aren't changed.
Two ways are good in order to initialize a new widget.
First case you have labels as objects. So when SomeWindow is destroyed, they will be destroyed automatically too. Remember, if you have pointer to widgets instead objects, you will need (and can) to delete the labels into destructor of dialog.
SomeWindow::~SomeWindow()
{
delete label1;
label2.deleteLater(); // A safer way to delete a widget. Thread-safe.
}
And second case there will be a memory leak because you have no way to delete the widget into destructor. But if you define a parent for labels, they will be delete when parent is delete too. Take a look to QWidget documentation.
If parent is 0, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted.
Moreover, anytime a object constructor ask you for a parent QWidget or QObject, you can think that Qt will delete the object when the parent is deleted.
I am a newbey as well, but I hope this help you.

Storing pointers using QListWidgetItem::setData

I have a QListWidget of calendars. Each QListWidgetItem is logically associated with an instance of Calendar, which is a class that belongs to the Model side of the application.
Can I store this association in the form of a pointer using QListWidgetItem::setData? When I attempt to do this, I get the following error:
error: 'QVariant::QVariant(void*)' is private
There is another constructor for void*: QVariant::QVariant(int typeOrUserType, const void * copy) where you should pass an unique integer to represent the pointer type.
But as stated by the documentation, you could declare your pointer type with Q_DECLARE_METATYPE(Calendar*) and use QVariant::fromValue<Calendar*>(...) and QVariant::value<Calendar*>() to store and retrieve the value.
Or instead, because you are using a QListWidget instead of a regular model, you can just subclass QListWidgetItem, and add a Calendar* member variable with the required accessors, to avoid the overhead of using QVariant.
I would suggest looking at this solution as well, which I think is quite elegant:
(there are minor syntax errors, but you will spot them quickly or the compiler will issue an error)
https://web.archive.org/web/20171025163314/http://blog.bigpixel.ro/2010/04/storing-pointer-in-qvariant/

How to remove item from QQueue at index i

How to remove item from QQueue at index i.
Being that QQueue is based on and will work like a std::queue, which is a FIFO (First-in First-out container), it seems you may need to rethink your usage of QQueue.
To remove the head item, use
QQueue::dequeue()
To remove an item at index i (using QList inherited functions)
QQueue::removeAt( int i )
If you need to do this, rethink your QQueue usage please.
(see Qt Documentation)
QQueue inherits QList<T>, so you can use void QList::removeAt(index) inherited method.
Qt documentation for,
T QQueue::dequeue ()
states that, Removes the head item in the queue and returns it. This function assumes that the queue isn't empty.
Hope it helps.
Edit:
If you want to remove item from a specific index, use QList instead.
There are functions like,
void QList::removeAt ( int i )
and
T QList::takeAt ( int i )
which you can make use depending upon your need..

Resources