Add icon from array to QListWidget item - c++

I've written a loop which adds some items to my QListWidget. Now I want them to have an icon from my qrc file. For this I would use a loop in which I add a unique icon to each item.
void Test::Query()
{
ui->listWidget_Available->clear();
QString CmdList[4] = {"kcmshell4 --list|grep -q kcm_grub2",
"kcmshell4 --list|grep -q kcm_networkmanagement",
"which pastebunz",
"[ -z $ink3_ver ]"};
QString NameList[4] = {"kcm_grub2",
"kcm_networkmanagement",
"pastebunz",
"Shellmenu"};
QString IconList[4] = {":/icons/icons/GNU.png",
":/icons/icons/networkmanager.png",
":/icons/icons/edit-paste.png",
":/icons/icons/menu.png"};
QIcon ItemIcon;
int iCntSize = sizeof(CmdList) / sizeof(CmdList[0]);
Next thing is to clear the List:
for(int iItem = 0; iItem < iCntSize; iItem++)
{
ui->listWidget_Available->addItem(NameList[iItem]);
ui->listWidget_Available->item(iItem)->setCheckState(Qt::PartiallyChecked);
}
Now the ugly part:
for(int iRow = 0; iRow < iCntSize; iRow++)
{
int BarValue = ui->progressBar->value();
ui->progressBar->setValue(BarValue+(100/iCntSize));
QString status = QString("Processing index %1 of %2. Name: %3").arg(iRow).arg(iCntSize).arg(NameList[iRow]);
qDebug() << status << (BarValue+25);
And here is my problem:
ItemIcon.addFile(IconList[iRow], QSize(), QIcon::Normal, QIcon::Off);
ui->listWidget_Available->item(iRow)->setIcon(ItemIcon); <--- how to do THIS?
How can I do this?
ui->textEdit_Informations->append("Searching for "+NameList[iRow]);
mProcess = new QProcess();
mProcess->start("/bin/bash", QStringList() << "-c" << QString(CmdList[iRow]));
mProcess->waitForFinished();
if ( mProcess->exitStatus() == QProcess::CrashExit )
{
ui->textEdit_Informations->setTextColor(Qt::red);
ui->textEdit_Informations->append("\t[FATAL]");
}
else if ( mProcess->exitCode() != 0 )
{
ui->textEdit_Informations->setTextColor(Qt::magenta);
ui->textEdit_Informations->append("\t[MISSED]");
ui->listWidget_Available->item(iRow)->setCheckState(Qt::Unchecked);
}
else if ( mProcess->exitCode() == 0 )
{
ui->textEdit_Informations->setTextColor(Qt::green);
ui->textEdit_Informations->append("\t[FOUND]");
ui->listWidget_Available->item(iRow)->setCheckState(Qt::Checked);
}
ui->textEdit_Informations->setTextColor(Qt::white);
}
}
Any suggestions?

You should use the constructor and a new QIcon each time instead of QIcon::addFile:
QIcon ItemIcon(IconList[iRow]);
ui->listWidget_Available->item(iRow)->setIcon(ItemIcon);
addFile would only be useful if you had a different image for each state of the item the icon is in (normal, activated, disabled, ...).

Related

How to move QListWidgetItem?

How to move QListWidgetItem and do not miss Item widget?
This works when drag & drop but can't do the same job on button.
removeItemWidget( item(row) );
QCoreApplication::removePostedEvents (p_widget,QEvent::DeferredDelete );
I remove widget which is shown in Item and make a patch in the way that remove delete signal from queue. in this way I can move Widget to another item
int DropList::moveWidget(int row, int pos)
{
const int new_row = row+pos;
if(count()>1 && row>=0 && row <count() && new_row>=0 && new_row<count())
{
// A->B
DropListItem *pA = widgetByRow(row);
DropListItem *pB = widgetByRow(new_row);
if(pB->isMovable() && pA->isMovable())
{
removeItemWidget(item(new_row));
removeItemWidget(item(row));
QCoreApplication::removePostedEvents (pB,QEvent::DeferredDelete );
QCoreApplication::removePostedEvents (pA,QEvent::DeferredDelete );
setItemWidget(item(new_row),pA);
setItemWidget(item(row),pB);
}
emit changed();
return new_row;
}
return 0;
}
parameters are row - is an item row and pos +1, +2 ,-1 ,....

Automatically add/remove widgets in QGridLayout with fixed column width?

Say I'm creating an image gallery view that has 3 columns (i.e. it displays 3 images on each row). I can add new images to the end by using division and remainder:
int row = images.size() / 3;
int col = images.size() % 3;
gridLayout->addWidget(myImage, row, col);
The problem arises when I want to remove an image from the middle; it now leaves that middle row with just two images instead of "shifting" everything back and filling each row with 3 images (except the last row).
It seems like QGridLayout doesn't have too many features, am I missing something here or is the only option to implement everything myself? Or am I using the wrong tool (QGridLayout) in the first place?
AFAIK, there is no auto-relayout in QGridLayout. I'm even not sure whether QGridLayout is intended for this purpose.
IMHO, QTableView or QTableWidget might be the better choice.
(Concerning this, QAbstractItemModel::moveRows() comes into my mind.)
However, this doesn't mean that it cannot be achieved.
I made an MCVE to demonstrate this – testQDeleteFromLayoutShift.cc:
#include <cassert>
#include <vector>
#include <QtWidgets>
// comment out to get rid of console diagnostic output
#define DIAGNOSTICS
class PushButton: public QPushButton {
public:
PushButton(const QString &text, QWidget *pQParent = nullptr):
QPushButton(text)
{ }
#ifdef DIAGNOSTICS
virtual ~PushButton() { qDebug() << "Destroyed:" << this << text(); }
#else // (not) DIAGNOSTICS
virtual ~PushButton() = default;
#endif // DIAGNOSTICS
};
// number of columns in grid
const int wGrid = 3;
// fill grid with a certain amount of buttons
std::vector<QPushButton*> fillGrid(QGridLayout &qGrid)
{
const int hGrid = 5;
std::vector<QPushButton*> pQBtns; pQBtns.reserve(wGrid * hGrid);
unsigned id = 0;
for (int row = 0; row < hGrid; ++row) {
for (int col = 0; col < wGrid; ++col) {
QPushButton *pQBtn = new PushButton(QString("Widget %1").arg(++id));
qGrid.addWidget(pQBtn, row, col);
pQBtns.push_back(pQBtn);
}
}
#ifdef DIAGNOSTICS
qDebug() << "qGrid.parent().children().count():"
<< dynamic_cast<QWidget*>(qGrid.parent())->children().count();
qDebug() << "qGrid.count():"
<< qGrid.count();
#endif // DIAGNOSTICS
return pQBtns;
}
// delete a button from grid (shifting the following)
void deleteFromGrid(QGridLayout &qGrid, QPushButton *pQBtn)
{
qDebug() << "Delete button" << pQBtn->text();
// find index of widget in grid
int i = 0;
const int n = qGrid.count();
while (i < n && qGrid.itemAt(i)->widget() != pQBtn) ++i;
assert(i < n);
// find item position in grid
int row = -1, col = -1, rowSpan = 0, colSpan = 0;
qGrid.getItemPosition(i, &row, &col, &rowSpan, &colSpan);
// remove button from layout
QLayoutItem *pQItemBtn = qGrid.itemAt(i);
qGrid.removeItem(pQItemBtn);
// reposition all following button layouts
for (int j = i + 1; j < n; ++j) {
QLayoutItem *pQItem = qGrid.takeAt(i);
const int row = (j - 1) / wGrid, col = (j - 1) % wGrid;
qGrid.addItem(pQItem, row, col);
}
delete pQBtn;
#if 1 // diagnostics
qDebug() << "qGrid.parent().children().count():"
<< dynamic_cast<QWidget*>(qGrid.parent())->children().count();
qDebug() << "qGrid.count():"
<< qGrid.count();
#endif // 0
}
// application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QWidget qWin;
qWin.setWindowTitle(QString::fromUtf8("Demo Delete from QGridLayout (with shift)"));
QGridLayout qGrid;
qWin.setLayout(&qGrid);
std::vector<QPushButton*> pQBtns = fillGrid(qGrid);
qWin.show();
// install signal handlers
for (QPushButton *const pQBtn : pQBtns) {
QObject::connect(pQBtn, &QPushButton::clicked,
[&qGrid, pQBtn](bool) {
QTimer::singleShot(0, [&qGrid, pQBtn]() {
deleteFromGrid(qGrid, pQBtn);
});
});
}
// runtime loop
return app.exec();
}
A Qt project file to build this – testQDeleteFromLayoutShift.pro:
SOURCES = testQDeleteFromLayoutShift.cc
QT += widgets
Output in Windows 10 (built with VS2017):
Qt Version: 5.13.0
qGrid.parent().children().count(): 16
qGrid.count(): 15
After clicking on button “Widget 8”:
Delete button "Widget 8"
Destroyed: QPushButton(0x25521e3ef10) "Widget 8"
qGrid.parent().children().count(): 15
qGrid.count(): 14
After clicking on button “Widget 6”
Delete button "Widget 6"
Destroyed: QPushButton(0x25521e3f7d0) "Widget 6"
qGrid.parent().children().count(): 14
qGrid.count(): 13
After clicking on button “Widget 12”
Delete button "Widget 12"
Destroyed: QPushButton(0x25521e46ad0) "Widget 12"
qGrid.parent().children().count(): 13
qGrid.count(): 12
Notes:
I used lambdas for the signal handlers of QPushButton::clicked() to pass the related QGridLayout and QPushButton* to the handler deleteFromGrid() – IMHO the most convenient way.
deleteFromGrid() is called via a QTimer::singleShot() with delay 0. If I would call deleteFromGrid() in the signal handler of QPushButton::clicked() directly, this would result in some kind of Harakiri due to the last line in deleteFromGrid(): delete pQBtn;.
The nested lambdas might look a bit scaring, sorry.
While writing this answer I recalled an older of mine:
SO: qgridlayout add and remove sub layouts
which might be of interest.

Qt - Updating in the function called by QSignalMapper

I have a QTreeWidget in which each of its items has a QComboBox in a column. I have connected it to a slot with a QSignalMapper, and I'm successfully retrieving both the item and the index in the combobox when it is triggered. I did it like this:
foreach(Workplace *wp, allWorkplaces){
QTreeWidgetItem *workplaceItem = new QTreeWidgetItem;
workplaceItem->setText(0, wp->workplaceName());
workplaceItem->setText(1, wp->workplaceDescription());
myWorkplaceUi->treeWidget->addTopLevelItem(workplaceItem);
QComboBox *combo = new QComboBox();
combo->addItems(allShiftModels);
combo->setAutoFillBackground(true);
ShiftModel *shiftModel = qobject_cast<ShiftModel *>(wp->usedShiftModel);
myWorkplaceUi->treeWidget->setItemWidget(workplaceItem,2, combo);
if(shiftModel && !shiftModel->shiftModelName().isEmpty()){
qDebug()<<"after the cast: "<< shiftModel->shiftModelName();
combo->setCurrentIndex(combo->findText(shiftModel->shiftModelName(), Qt::MatchExactly));
}else{
combo->setCurrentIndex(combo->findText("None", Qt::MatchExactly));
}
connect(combo, SIGNAL(currentIndexChanged(int)), signalMapper, SLOT(map()));
signalMapper->setMapping(combo, QString("%1").arg(wp->workplaceName()));
}
connect(signalMapper, SIGNAL(mapped(const QString &)),this, SLOT(changed(const QString &)));
My objective is, after retrieving both the Workplace and the ShiftModel, to update them in the instances of my already created Workplaces. So, basically, I try to find the Workplace and the ShiftModel that were selected, because depending on the ShiftModel selected, I will change a pointer to the ShiftModel in the Workplace class:
class Workplace : public QObject
{
Q_OBJECT
public:
(...)
ShiftModel *usedShiftModel;
(...)
}
And the changed slot:
void workplacesdialog::changed(QString position){
QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
QList<ShiftModel*> allShiftModels = this->myProject->myFactory->listShiftModels();
foreach(Workplace* workplace, allWorkplaces){
foreach(ShiftModel *shiftmodel, allShiftModels){
qDebug() <<"workplace:"<< workplace->workplaceName();
qDebug() <<"shiftmodel:"<< shiftmodel->shiftModelName();
QString wp = position;
QTreeWidgetItem* item=(QTreeWidgetItem*)myWorkplaceUi->treeWidget->findItems(wp,Qt::MatchExactly,0).at(0);
QComboBox *combo = (QComboBox*)myWorkplaceUi->treeWidget->itemWidget(item,2);
if(combo && item){
QString sm = combo->currentText();
qDebug() << "selected shiftmodel "<< sm << " on workplace "<< wp;
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
workplace->usedShiftModel = shiftmodel;
break;
}
else{
workplace->usedShiftModel = 0;
return;
}
}else{
qDebug() << "cast failed!";
return;
}
}
}
}
So, my problem with this is, when I click one of the comboboxes, successfully retrieve both the item and index selected, but then, when I try to traverse them with the two foreach loops in the slot, it does not work as I expected. I hoped that every time I clicked on an index in one of the comboboxes, this would be called, and it is. Although, for some reason, the method I'm using to match what the user selected with what was already instatiated doesn't work.
Also, it looks like it only hits both the 1st workplace on the allWorkplaces list as well as the 1st shiftmodel on the ShiftModels list, and this is my problem.
If anyone knows how to fix this or has any ideas to share, please let me know. Thank you.
The problem is this:
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
workplace->usedShiftModel = shiftmodel;
break;
}
else{
workplace->usedShiftModel = 0;
return;
}
If either the workplace name does not match, or the shift model name does not match, the relation between the work place and its currently linked shift model is removed and your function returns.
I could restructure the two for-loops for you, but there is an easier and less error-prone way:
Note: I marked some code paths with "TODO" which I skipped due to lack of time. You should be able to figure them out yourself though.
// Set up hashes for quick lookup
QHash< QString, Workplace* > workplaceHash;
QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
foreach( Workplace* workplace, allWorkplaces )
{
workplaceHash.insert( workplace, workplace->workplaceName() );
}
// TODO: Do a similar thing for the shift models here
// Find the selected workplace
if( !workplaceHash.contains( position ) )
{
// TODO: Error handling (An unknown/No workplace was selected)
return;
}
// else: A valid workplace was selected
Workplace* selectedWorkplace = workplaceHash.value( position );
// TODO: Retrieve the name of the shift model (stored in variable sm)
// Find the selected shiftmodel
if( !shiftplaceHash.contains( sm ) )
{
// No shift model was selected
selectedWorkplace->usedShiftModel= 0;
return;
}
// Else: Both work place and shift model were selected
Shiftplace* selectedShiftModel = shiftplaceHash.value( sm );
selectedWorkplace->usedShiftModel = selectedShiftModel;
A few ideas for refactoring:
You could maybe do the creation of the hashes outside of this method and store them in member variables. Just make sure that the hash is always updated when a workplace is added or removed.
You could make spotting errors easier by extracting parts of the code into separate methods, e.g. QString getSelectedShiftModelName() etc.
So, In the end I figured out my loops were really messed up... This is working now:
void workplacesdialog::changed(QString position){
QList<Workplace* > allWorkplaces = this->myProject->listMyWorkplaces();
QList<ShiftModel*> allShiftModels = this->myProject->myFactory->listShiftModels();
qDebug() << allWorkplaces.size() << " workplaces";
qDebug() << allShiftModels.size() << " ShiftModels";
QString wp = position;
QString sm;
QTreeWidgetItem* item=(QTreeWidgetItem*)myWorkplaceUi->treeWidget->findItems(wp,Qt::MatchExactly,0).at(0);
QComboBox *combo = (QComboBox*)myWorkplaceUi->treeWidget->itemWidget(item,2);
if(combo && item){
sm = combo->currentText();
qDebug() << "selected shiftmodel "<< sm << " on workplace "<< wp;
}else{
qDebug() << "cast failed!";
return;
}
foreach(Workplace* workplace, allWorkplaces){
foreach(ShiftModel *shiftmodel, allShiftModels){
qDebug() <<"workplace:"<< workplace->workplaceName();
qDebug() <<"shiftmodel:"<< shiftmodel->shiftModelName();
if(workplace->workplaceName()==wp && shiftmodel->shiftModelName()==sm){
qDebug() << "found match!: "<< wp << " >>>>> " << sm;
workplace->usedShiftModel = shiftmodel;
return;
}else if(workplace->workplaceName()==wp && sm=="None"){
qDebug() << "clear match: "<< wp << " >>>>> " << sm;
workplace->usedShiftModel = 0;
return;
}
}
}
}

QTableWidget - setCellWidget missing addition?

I am just trying to add widgets into my table widget and I am trying the code below but all the time I run the program, the first widget is added but the rest is not added. Can you please help me for this situation ?
if(req.at(index).request.CodedValue.size() > 1 )
{
int rowNumber = -1;
for ( int paramNumber = 0 ; paramNumber < req.at(index).request.params.size(); paramNumber++)
{
if(req[index].request.params[paramNumber].semantic == "DATA")
{
rowNumber++;
QComboBox* reqComboBox = new QComboBox();
QLineEdit* tableReqLineEdit = new QLineEdit();
for ( int codedCounter = 0; codedCounter < req.at(index).request.CodedValue.at(paramNumber).trams.size(); codedCounter++)
{
// you should look for the subfunctions and add according to them
reqComboBox->addItem((req[index].request.CodedValue[paramNumber].trams[codedCounter].valueName));
QObject::connect(reqComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(on_tableCombobox_currentIndex());
}
ui.tableWidget->setCellWidget(rowNumber,1,reqComboBox);
}
}
}
Use qDebug in order to see how many times the for loop is executed. Probably it is executed only once:
#include <QDebug>
...
rowNumber++;
qDebug() << rowNumber;
...
Try the following:
for (int i=0; i<ui.tableWidget->rowCount(); i++)
{
ui.tableWidget->setCellWidget(i,1,new QLineEdit);
}
How many line edits do you see?
Notice that you should use the setRowCount in order to set the number of rows of your table widget.

Maintaining checkedstatus inheritance in a QTreeView

I'm trying to do something basic : you have a QTreeView. 1st depth are folders only, 2nd depth are files only. I want to have a check box with the checked status next to each item. Files are either checked or unchecked, folders can also be partiallyChecked depending on their files; all in all quite natural I believe.
The way I though I should go was using a QStandardItemModel and populate it with a custom subclass of QStandardItem : DescriptionFileItem. Maybe that was a bad idea, if there's an easier way please enlight me.
I tried using signals and slots so that my signal CheckStateChanged on a file would be connected to a slot UpdateCheckedStateOnChildStateChanged on its containing folder. This required my DescriptionFileItem to inherit from QObject as well (BTW, I was surprised that QStandardItem did not inherit from QObject). I initially hoped this would work seamlessly with the provided base classes but it did not : emitDataChanged() didn't seem to trigger my model's dataChanged() signal...
Using the model's dataChanged signals directly didn't work either: it's call is protected so you can't use it without subclassing (I think that's my next move unless somebody can help me get it right).
At the moment I have a signal -> slot connection that won't work and I have no idea why; compile and link work ok. Here's the code; perhapps you'll spot my mistakes easily. I'm leaving some commented lines so you can maybe see what I did wrong in a previous attempt. Thanks for your input!
#ifndef DESCRIPTIONFILEITEM_H
#define DESCRIPTIONFILEITEM_H
#include <QStandardItem>
#include <Qt>
class DescriptionFileItem : public QObject, public QStandardItem
{
Q_OBJECT
public:
explicit DescriptionFileItem(const QString & text, bool isFileName=false, QObject* parent = 0);
void setData ( const QVariant & value, int role = Qt::UserRole + 1 );
QVariant data( int role = Qt::UserRole + 1 ) const;
QString text;
Qt::CheckState checkedState;
bool isFileName;
signals:
void CheckStateChanged();
public slots:
void UpdateCheckedStateOnChildStateChanged();
};
#endif // DESCRIPTIONFILEITEM_H
Corresponding .cpp :
#include "DescriptionFileItem.h"
DescriptionFileItem::DescriptionFileItem(const QString & text, bool isFileName, QObject* parent):
QObject(parent),QStandardItem(text)
{
this->isFileName = isFileName;
checkedState = Qt::Checked;
}
void DescriptionFileItem::setData ( const QVariant & value, int role){
if(role == Qt::CheckStateRole){
Qt::CheckState newCheckState = (Qt::CheckState)value.toInt();
checkedState = newCheckState;
if(isFileName){
if(newCheckState == Qt::Unchecked || newCheckState == Qt::Checked){
for(int i = 0; i<rowCount(); i++){
DescriptionFileItem* child = (DescriptionFileItem*)QStandardItem::child(i);
QModelIndex childIndex = child->index();
child->model()->setData(childIndex,newCheckState, Qt::CheckStateRole);
//child->setCheckState(newCheckState);
//child->setData(newCheckState,Qt::CheckStateRole);
}
/*if(rowCount()>1){
emit this->model()->dataChanged(this->child(0)->index(),this->child(rowCount()-1)->index());
}else{
emit this->model()->dataChanged(this->child(0)->index(),this->child(0)->index());
}*/
}
}else{
emit CheckStateChanged();
}
//emit this->model()->dataChanged(this->index(),this->index());
}else{
QStandardItem::setData(value,role);
}
}
QVariant DescriptionFileItem::data( int role ) const{
if (role == Qt::CheckStateRole){
return checkedState;
}
return QStandardItem::data(role);
}
void DescriptionFileItem::UpdateCheckedStateOnChildStateChanged()
{
Qt::CheckState min = Qt::Checked;
Qt::CheckState max = Qt::Unchecked;
Qt::CheckState childState;
for(int i = 0; i<rowCount(); i++){
DescriptionFileItem* child = (DescriptionFileItem*)QStandardItem::child(i);
childState = (Qt::CheckState) child->data(Qt::CheckStateRole).toInt();
min = min>childState ? childState: min;
max = max<childState ? childState: max;
}
if(min >= max)
setData(min, Qt::CheckStateRole);
else
setData(Qt::PartiallyChecked, Qt::CheckStateRole);
}
And the construction of the connection / tree:
DescriptionFileItem* descFileStdItem = new DescriptionFileItem(descriptionFileName, true);
descFileStdItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsTristate);
descriptionFileSIModel.appendRow(descFileStdItem);
typedef pair<string,int> indexType;
foreach(indexType index,dataFile->indexes){
DescriptionFileItem* key_xItem = new DescriptionFileItem(index.first.c_str());
descFileStdItem->appendRow(key_xItem);
key_xItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
QObject::connect(key_xItem,SIGNAL(CheckStateChanged()),descFileStdItem,SLOT(UpdateCheckedStateOnModelDataChanged()));
}
EDIT: final answer, thanks to stu (see below)
void DataLoadWidget::ModelItemChanged(QStandardItem *item)
{
QStandardItem* parent = item->parent();
if(parent == 0){
//folder state changed--> update children if not partially selected
Qt::CheckState newState = item->checkState();
if(newState != Qt::PartiallyChecked){
for (int i = 0; i < item->rowCount(); i++)
{
item->child(i)->setCheckState(newState);
}
}
}
else{//child item changed--> count parent's children that are checked
int checkCount = 0;
for (int i = 0; i < parent->rowCount(); i++)
{
if (parent->child(i)->checkState() == Qt::Checked)
checkCount++;
}
if(checkCount == 0)
parent->setCheckState(Qt::Unchecked);
else if (checkCount == parent->rowCount())
parent->setCheckState(Qt::Checked);
else
parent->setCheckState(Qt::PartiallyChecked);
}
}
Unless I've misunderstood your question it seems that your solution is massively over-complicated. You should be able to do this trivially with the default QStandardItemModel implementation.
How about something like this (error handling omitted)?
QObject::connect(model, SIGNAL(itemChanged(QStandardItem*)), someObject, SLOT(modelItemChanged(QStandardItem*)));
And then in the signal handler:
void modelItemChanged(QStandardItem* item)
{
QStandardItem* parent = item->parent();
int checkCount = 0;
int rowCount = parent->rowCount();
for (int i = 0; i < rowCount; i++)
{
if (parent->child(i)->checkState() == Qt::Checked)
checkCount++;
}
switch (checkCount)
{
case 0:
parent->setCheckState(Qt::Unchecked);
break;
case rowCount:
parent->setCheckState(Qt::Checked);
break;
default:
parent->setCheckState(Qt::PartiallyChecked);
}
}
This is by no means optimal but it may be good enough for your purposes.