QWidget findChildren when objectname contains a specific string - c++

How do you list all childs from a qwidget that contain a specific string inside de objectname?
For example, if I have:
"general_widget", with children:
"label_name_1"
"label__1"
"label_name_2"
"label_id_2"
"label_name_3"
"label_id_3"
"label_name_4"
"label_id_4"
I would like to get a list of all children that contain "name" as part of the objectName, and another list with all children that contain "id". Thanks!

Have a simple function like this:
QList<QWidget *> widgets(QWidget * parent, QString search)
{
QRegularExpression exp(search);
return parent->findChildren<QWidget *>(exp);
}
and given a QWidget * widget you can call it this way:
auto name_list = widgets(widget, "name");
auto id_list = widgets(widget, "id");

Use findChildren() along with objectName().contains() , for example:
QList<QWidget*> subwidgets = this->findChildren<QWidget*>();
QListIterator<QWidget*> it(subwidgets); // iterate through the list of widgets
QWidget *awiget;
while (it.hasNext()) {
awiget = it.next(); // take each widget in the list
if (awiget->objectName().contains("name")){
qDebug() << awiget->objectName();
}
}

Related

QT5 C++, Is there a way I can get the current text of a widget within a qlist container

I need to retrieve the text in the order in which they appear on the user form. I am trying as below:
QString line = "QLineEdit";
QString combo = "QComboBox";
QList<QWidget *> childWidgets = ui->frame_3->findChildren<QWidget *>();
QStringList data;
for(auto widget : childWidgets){
if(widget->metaObject()->className() == line || widget->metaObject()->className() == combo){
data.append(widget->text()); //append the text of the lineEdits and ComboBoxes to data
}
}
I get the following compile error from the above code:
"no member named 'text' in QWidget
Since you pointed out the QWidget base class does not have a text member function you will need to access the QComboBox and QLineEdit directly to get the current text.
QList<QWidget *> childWidgets = ui->frame_3->findChildren<QWidget *>();
QStringList data;
for(auto widget : childWidgets){
auto combo = dynamic_cast<QComboBox*>(widget);
if (combo) {
data << combo->currentText(); // currentText() returns the text from the combobox
}
else {
auto lineEdit = dynamic_cast<QLineEdit*>(widget);
if (lineEdit) {
data << lineEdit->text(); // A line edit has a text() member.
}
}
}
This code does not handle ordering. I believe the order is in the same order as added to the parent.

QT - Can I dynamically point to GUI's labels using a variable passed into a method?

I'm creating an inventory and want to reference my inventory Forms QLabels with the name of the item passed into my method.
The QLabels and the names of the items are the same so I wanted to reduce if statements by referencing a QLabel depending on the name of the item passed in.
void Zork::on_btnTake_clicked()
{
Item *item = new Item(ui->takeItem->currentText().toStdString());
Colin->addItemToInventory(item);
inventory_screen->addItem(item->getDescription()); //Enables the Item in the Inventory
currentRoom->deleteItem(item);
ui->takeItem->removeItem(ui->takeItem->currentIndex()); //Only remove the item in the foreground of combobox at the time take button was clicked
}
Calls this Method addItemToInventory(item):
void Inventory_Ui:: addItem(string itemName){
myUi->itemName->setText(QString::fromStdString(itemName));
}
I am unable to do so as itemName is not a member of Ui, although itemName does contain members of Ui.
Example:
In my Inventory_Ui Form I have 6 labels, one named broken_bottle. I want to pass broken_bottle into the method's parameter itemName and them use that as a reference so at run-time it would look like myUi->broken_bottle->setText...
I think I follow what you are asking to do. I would access it with findChild or findChildren.
http://doc.qt.io/qt-5/qobject.html#findChild
http://doc.qt.io/qt-5/qobject.html#findChildren
QList <QLabel *> labels = ui->myForm()->findChildren<QLabel*>();
QLabel* targetLabel = 0;
foreach(QLabel * label, labels)
{
if(label->text() == ui->takeItem->currentText())
{
targetLabel = label;
break;
}
}
if(targetLabel != 0)
{
// ... do something with targetLabel
}
or...
QList <QLabel *> labels = ui->myForm()->findChildren<QLabel*>();
foreach(QLabel * label, labels)
label->setObjectName(label->text());
// later
QLabel * targetLabel = ui->myForm()->findChild<QLabel*>("text of label");
if(targetLabel)
// use it
Or if you are connecting all these labels to the same slot, you can figure some of it out using the sender static method.
http://doc.qt.io/qt-5/qobject.html#sender
void MainWindow::on_takeItem_currentTextChanged()
{
QLabel* targetLabel = qobject_cast<QLabel*>QObject::sender();
if(targetLabel)
// do something with it
}
Hope that helps.

How to get clicked/selected items of a QTreeWidget

I'm currently looking to a way to get the name of the selected items of a QTreeWidget.
I have create multiple QTreeWidgetItems to generate a file browser-like.
I need to know how to get the name of the folder selected.
I have found the
this->MyTree->selectedItems();
to get it but I'm not able to store the feedback which is supposed to be a QList format.
Any examples on how to store the selectedItems list ?
From the Qt documentation: QTreeWidget Class Reference , QTreeWidgetItem Class Reference
selectedItems() is a function of QTreeWidget.
QList QTreeWidget::selectedItems () const
Returns a list of all selected non-hidden items.
text() is a function of QTreeWidgetItem
QString QTreeWidgetItem::text ( int column ) const
Returns the text in the specified column.
Define a list of QTreeWidgetItem to store return value of selectedItems() .
For each item in the list use text() function to get it's string.
QList<QTreeWidgetItem *> itemList;
itemList = this->MyTree->selectedItems();
foreach(QTreeWidgetItem *item, itemList)
{
QString str = item->text();
//str is what you want
}
{
...
connect(treeWidget, &QTreeWidget::itemClicked, this, &MyForm::onItemClicked);
connect(treeWidget, &QTreeWidget::itemActivated, this, &MyForm::onItemClicked);
}
void MyForm::onItemClicked(QTreeWidgetItem *item, int) {
if (item == item0) {
stackedWidget->setCurrentWidget(widget0);
}
else if (item == item1) {
stackedWidget->setCurrentWidget(widget1);
}
}

Getting variable from widget in a QListWidget

I have a custom QWidget class called VideoWidget. Its source file looks something like this:
VideoWidget::VideoWidget(QWidget *parent, string test) :
QWidget(parent)
{
pathname=test;
QLabel *label= new QLabel(pathname.c_str(), this);
//...
}
string VideoWidget::getFilePath(){
return pathname;
}
In my MainWindow class I add the VideoWidget to a QListWidget through looping through a xml file and getting the string argument from that file like this:
QDomNode node = rootXML.firstChild();
while( !node.isNull() )
{
if( node.isElement() )
{
QDomElement element = node.toElement();
VideoWidget* mytest = new VideoWidget(this, element.attribute( "Pathname", "not set").toStdString());
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(150,100));
ui->myList->addItem(item);
ui->myList->setItemWidget(item,mytest);
}
node = node.nextSibling();
}
This correctly fills my QListWidget with the VideoWidget where all the labels have a different value.
Now I'd like to get the pathname variable everytime I doubleclick on a item in the QListWidget like this:
connect(ui->myList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(playClip(QModelIndex)));
void MainWindow::playClip(QModelIndex index){
QListWidgetItem* item = ui->myList->itemAt(0,index.row());
VideoWidget* widget = dynamic_cast<VideoWidget*>(ui->myList->itemWidget(item));
cout << widget->getFilePath() << endl;
}
My problem is that widget->getFilePath() always returns the same value for every clicked widget. It is the value of the first time I set pathname=test;. What am I missing here?
This is probably mistake:
QListWidgetItem* item = ui->myList->itemAt(0,index.row());
Method "itemAt" takes x and y coordinates, not indexes. Use "takeItem" instead.
Next thing I want to say is that this part:
ui->myList->itemWidget(item)
is useless. You can convert "item" directly.
And last - use qobject_cast since you use Qt. And never use dynamic_case (especially when you anyway do not check result against NULL).

sort qtreewidget toplevel item base on a child data

i have a qtreewidget with toplevelitems. each toplevelitem has 4 childeren, each child has special value, first child of all toplevelitems is its parrent cost, i want to sort this toplevelitems base on this cost, but i don't know how to do this? my idea is to keep this toplevelitems and their cost in a map and add and take them each time a toplevelitem is added, but i'm looking for a better way.
thanks in advance.
By default, tree widget sorts items according to their texts, however you can change it by overriding the operator<() of the QTreeWidgetItem. Below is the example of custom QTreeWidgetItem with specific operator (see comments):
class TreeWidgetItem : public QTreeWidgetItem
{
public:
// The constructors. Add more, if needed.
TreeWidgetItem(QTreeWidget *parent, const QStringList &strings,
int type = Type)
: QTreeWidgetItem(parent, strings, type)
{}
TreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings,
int type = Type)
: QTreeWidgetItem(parent, strings, type)
{}
// Compares two tree widget items. The logic can be changed.
bool operator<(const QTreeWidgetItem& other) const
{
// Get the price - the first child node
int price1 = 0;
if (childCount() > 0)
{
QTreeWidgetItem *firstChild = child(0);
price1 = firstChild->text(0).toInt();
}
// Get the second price - the first child node
int price2 = 0;
if (other.childCount() > 0)
{
QTreeWidgetItem *firstChild = other.child(0);
price2 = firstChild->text(0).toInt();
}
// Compare two prices.
return price1 < price2;
}
};
And here is how this class can be used with QTreeWidget:
// The sortable tree widget.
QTreeWidget tw;
tw.setSortingEnabled(true);
QTreeWidgetItem *item1 = new TreeWidgetItem(&tw, QStringList() << "Item1");
QTreeWidgetItem *child1 = new TreeWidgetItem(item1, QStringList() << "10");
QTreeWidgetItem *item2 = new TreeWidgetItem(&tw, QStringList() << "Item2");
QTreeWidgetItem *child2 = new TreeWidgetItem(item2, QStringList() << "11");
tw.show();