I'm a beginner at Qt and I'm struggling to populate a QStandardItemModel from an XML file.
I've tried the following and the entire project runs successfully but the QtableView does not display the data.
Here is my main.cpp:
void readXml(const QString& fileName) {
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text)) {
qDebug() << "Cannot read file" << file.errorString();
return;
}
StockItems* stockitems = new StockItems;
XmlStockItemsReader xmlReader(stockitems);
if(!xmlReader.read(&file))
qDebug() << "Parse error in file " << xmlReader.errorString();
else {
stockitems->print();
stockitems->populateStockModel();
}
}
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
StockItems si;
//! Change this to match the path of your project
QString path = "C:\\unisa\\cos3711\\FIConcession";
readXml(path + "\\stockitems.xml");
si.show();
return app.exec();
}
In stockitems.cpp I have the following function:
void StockItems::populateStockModel() {
foreach(Item* item, m_items) {
QList<QStandardItem*> newRow;
QStandardItem *stockID = new QStandardItem(QString("%1").arg(item->stockID()));
QStandardItem *desc = new QStandardItem(QString("%2").arg(item->desc()));
QStandardItem *price = new QStandardItem(QString("%3").arg(item->price()));
newRow.append(stockID);
newRow.append(desc);
newRow.append(price);
stockModel->appendRow(newRow);
}
}
If I do some debugging I can see that the stockID, desc and prices are correctly read, so the problem must lie somewhere with updating the stockModel.
My main StockItems Constructor is as follows:
StockItems::StockItems(QWidget *parent) :
QDialog(parent),
ui(new Ui::StockItems)
{
ui->setupUi(this);
stockModel = new QStandardItemModel(0, 3);
// Set Model Headers
stockModel->setHeaderData(0, Qt::Horizontal, "Stock ID", Qt::DisplayRole);
stockModel->setHeaderData(1, Qt::Horizontal, "Description", Qt::DisplayRole);
stockModel->setHeaderData(2, Qt::Horizontal, "Price", Qt::DisplayRole);
// Link Model to Table View
ui->tvStock->setModel(stockModel);
}
I have an add button which contains the following onclick code which works as expected so I'm just not sure if I'm referencing the stockModel correctly.
QList<QStandardItem*> newRow;
QStandardItem* stockID = new QStandardItem(QString("%1").arg(ui->tbStockId->text()));
QStandardItem* desc = new QStandardItem(QString("%2").arg(ui->tbDesc->text()));
QStandardItem* price = new QStandardItem(QString("%3").arg(ui->sbPrice->text()));
newRow.append(stockID);
newRow.append(desc);
newRow.append(price);
stockModel->appendRow(newRow);
Finally I think this might help, my stockitems.h file:
class StockItems : public QDialog
{
Q_OBJECT
public:
explicit StockItems(QWidget *parent = 0);
~StockItems();
void populateStockModel();
void addItem(Item* item);
void print() const;
private slots:
void on_btnAdd_clicked();
void on_btnDelete_clicked();
private:
Ui::StockItems *ui;
QStandardItemModel *stockModel;
QList<Item*> m_items;
};
This is a lot and please let me know if I should provide anything else but I'm really lost as to how to populate this model correctly.
Thanks for any guidance!
Your readXml function does not populate the StockItems instance that you create in your main function, but a completely new StockItems instance that isn't used anywhere.
For example, instead of
StockItems* stockitems = new StockItems;
in your readXml function, let readXml take another StockItems argument, and use that:
void readXml(const QString& fileName, StockItems *stockItems) {
// do everything here as before, except for the
// StockItems* stockitems = new StockItems;
...
}
int main(int argc, char* argv[]) {
...
readXml(path + "\\stockitems.xml", &si);
si.show();
...
}
Related
I've been trying to learn c++ and qt framework by doing a point of sale software project.my main window has couple of tabs and with in one tab i have a qpushbutton which open a newpurchase dialog which takes input from user to record a new purchase from supplier.this newpurchase dialog has a lineedit which, when recieves product barcode from a barcode reader ,triggers another quanity dialog which, user can use to enter the quantity of the product. but when i click ok on the button box of the quantity dialog instead of closing just the quantity dialog ,it closes the newpurchase dialog as well.i debugged the qt application and it shows that a qpushbutton (which saves and closes the newpurchase dialog)on the newpuchase dialog gets triggered automatically.additionally this behaviour is only spotted when quantity dialog is triggered through the barcode lineedit,i have another lineedit which accepts description of the product and triggers the same quantity dialog ,but clicking ok button when quantity dialog is triggered through description lineedit does not closes the newpurchase dialog or trigger the qpushbutton which saves and closes the newpurchase dialog.im attaching the screen shots of the dialog and code for the dialogs
on mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
newpurchase mypurchase;
connect(&mypurchase,SIGNAL(purchase_added()),this,SLOT(update_view()));
mypurchase.exec();
}
newpurchase dialog
newpurchase.cpp
#include "newpurchase.h"
#include "ui_newpurchase.h"
#include <QtDebug>
#include <qtablewidget.h>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QCompleter>
#include <QObject>
#include <QWidget>
#include <QDate>
newpurchase::newpurchase(QWidget *parent) :
QDialog(parent),
ui(new Ui::newpurchase)
{
ui->setupUi(this);
QSqlQuery qry;
qry.prepare("select description from product");
if(!qry.exec())
{
qDebug() << "error getting description from product";
}
QStringList items;
while(qry.next())
{
items <<qry.value(0).toString();
}
QCompleter *completer =new QCompleter(items,this);
completer->setCaseSensitivity(Qt::CaseInsensitive);
ui->lineEdit_descripion->setCompleter(completer);
connect(completer,static_cast<void (QCompleter::*)(const QString&)>(&QCompleter::activated),
[&](const QString &text)->void
{
newpurchase::clear(text);
});
QSqlQuery supqry;
supqry.prepare("select supplier_name from supplier");
if(!supqry.exec())
{
qDebug() << "error getting suppliername from supplier";
}
QStringList supitems;
while(supqry.next())
{
supitems <<supqry.value(0).toString();
}
QCompleter *supcompleter =new QCompleter(supitems,this);
supcompleter->setCaseSensitivity(Qt::CaseInsensitive);
ui->lineEdit_sup->setCompleter(supcompleter);
}
newpurchase::~newpurchase()
{
delete ui;
}
void newpurchase::on_lineEdit_barcode_returnPressed()
{
if(!ui->lineEdit_sale->text().isEmpty() && !ui->lineEdit_sup->text().isEmpty() && !ui->lineEdit_inv->text().isEmpty())
{
quantity_dialog quandialog;
connect(&quandialog,SIGNAL(purdetails(QString)),this,SLOT(code(QString)));
quandialog.exec();
}
else
{
Errdialog myerror("please provide supplier and invoice" );
myerror.exec();
}
}
void newpurchase::saveDataIntoTable(QString item,double price,int quantity,QString code,QString date)
{
double rupee =price*quantity*1.00;
//qDebug() <<date;
QString mrp= QString::number(rupee,'f',2);
QString qty= QString::number(quantity);
QString prc= QString::number(price);
// QString kod= QString::number(code);
if (!ui->tableWidget)
return;
const int currentRow = ui->tableWidget->rowCount();
ui->tableWidget->setRowCount(currentRow + 1);
ui->tableWidget->setItem(currentRow, 0, new QTableWidgetItem(item));
ui->tableWidget->setItem(currentRow, 1, new QTableWidgetItem(prc));
ui->tableWidget->setItem(currentRow, 2, new QTableWidgetItem(qty));
ui->tableWidget->setItem(currentRow, 3, new QTableWidgetItem(mrp));
ui->tableWidget->setItem(currentRow, 4, new QTableWidgetItem(code));
ui->tableWidget->setItem(currentRow, 5, new QTableWidgetItem(date));
double total=ui->label_3->text().toDouble();
total = total+rupee;
ui->label_3->setText(QString::number(total,'f',2));
}
void newpurchase::clear(QString item)
{
if(!item.isEmpty())
{
if(!ui->lineEdit_des->text().isEmpty() && !ui->lineEdit_sup->text().isEmpty() && !ui->lineEdit_inv->text().isEmpty())
{
quantity_dialog quandialog;
connect(&quandialog,SIGNAL(purdetails(QString)),this,SLOT(descr(QString)));
quandialog.exec();
}
else
{
Errdialog myerror("please provide supplier and invoice" );
myerror.exec();
}
}
}
void newpurchase::descr(QString q)
{
QStringList elements = q.split(':');
QSqlQuery qry;
qry.prepare("select * from product where description='"+ui->lineEdit_des->text()+"'");
if(!qry.exec())
{
qDebug() << "error getting table product";
}
if (qry.next())
{
QString result=qry.value(1).toString();
double cost= elements[1].toDouble();
QString itemco=qry.value(2).toString();
int quan=elements[0].toInt();
QString mfd=elements[2];
saveDataIntoTable(result,cost,quan,itemco,mfd);
ui->lineEdit_des->clear();
}
}
void newpurchase::on_pushButton_clicked()
{
QItemSelectionModel *select =ui->tableWidget->selectionModel();
int row = select->selectedRows().takeFirst().row();
double rupee=ui->tableWidget->item(row,3)->text().toDouble();
ui->tableWidget->removeRow(row);
double total=ui->label_3->text().toDouble();
total = total-rupee;
ui->label_3->setText(QString::number(total,'f',2));
}
void newpurchase::on_lineEdit_des_returnPressed()
{
}
void newpurchase::code(QString q)
{
QStringList elements = q.split(':');
QSqlQuery qry;
qry.prepare("select * from product where code="+ui->lineEdit_sale->text());
if(!qry.exec())
{
qDebug() << "error getting table product";
}
if (qry.next())
{
QString result=qry.value(1).toString();
double cost= elements[2].toDouble();
QString itemco=qry.value(2).toString();
int quan=elements[0].toInt();
QString mfd=elements[1];
saveDataIntoTable(result,cost,quan,itemco,mfd);
}
ui->lineEdit_sale->clear();
}
void newpurchase::on_pushButton_2_clicked()
{
QString datetime= QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
QString supplier=ui->lineEdit_sup->text();
QString invoice=ui->lineEdit_inv->text();
int numrow=ui->tableWidget->rowCount();
// qDebug() << numrow;
for (int i = 0; i < numrow; i++)
{
QSqlQuery query;
query.prepare("SELECT MAX(Id) FROM stock_transaction");
if(!query.exec())
{
qDebug() << "error getting id";
}
int id=0 ;
if (query.next())
{
id=query.value(0).toInt()+1;
}
QString coder=ui->tableWidget->item(i,4)->text();
QString qua=ui->tableWidget->item(i,2)->text();
double rate=ui->tableWidget->item(i,1)->text().toDouble();
QString date= ui->tableWidget->item(i,5)->text();
QString d=QString::number(id);
QString batch=supplier+"_"+invoice+"_"+d;
QSqlQuery querysale;
querysale.prepare("INSERT INTO stock_transaction(id,code,stock,mfd,supplier,invoice,cost,date_time) VALUES(:id,:code,:stock,:mfd,:supplier,:invoice,:cost,:date_time)");
querysale.bindValue(":id", id);
querysale.bindValue(":code",coder);
querysale.bindValue(":stock", qua.toInt());
querysale.bindValue(":mfd",date);
querysale.bindValue(":supplier", supplier);
querysale.bindValue(":invoice", invoice);
querysale.bindValue(":cost", rate*1.00);
querysale.bindValue(":date_time", datetime);
if(!querysale.exec())
{
qDebug() << "error recording sale";
}
}
emit this->purchase_added();
close();
}
quantity dialog
quantity.cpp
#include "quantity_dialog.h"
#include "ui_quantity_dialog.h"
quantity_dialog::quantity_dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::quantity_dialog)
{
ui->setupUi(this);
ui->lineEdit_quan->setFocus();
ui->buttonBox->setEnabled(false);
connect(ui->lineEdit_quan, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
connect(ui->dateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(checkLineEdits()));
connect(ui->lineEdit_3, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
}
quantity_dialog::~quantity_dialog()
{
delete ui;
}
void quantity_dialog::on_buttonBox_accepted()
{
emit purdetails(ui->lineEdit_quan->text()+":"+ui->dateEdit->text()+":"+ui->lineEdit_3->text());
ui->lineEdit_quan->clear();
}
Please let me know if i can provide any other details
the auto default property of the autoclicking qpushbutton was set.changing this property solved my issue
I am trying to run some code when I select a new index in a QTreeView
In RoverPlanner.h
namespace Ui {
class RoverPlanner;
}
class RoverPlanner : public QWidget
{
Q_OBJECT
public:
explicit RoverPlanner(QWidget *parent = nullptr);
void save_paths_from_tree(QTreeView* treeView);
void load_paths_into_tree(QTreeView* treeView);
std::vector<cuarl_path::Path> get_paths(const char* filename) const;
void update_segment_editor();
cuarl_path::Segment* addSegment();
~RoverPlanner();
private Q_SLOTS:
void treeSelectionChanged(const QModelIndex& prevIndex, const QModelIndex& nextIndex);
private:
Ui::RoverPlanner *ui;
};
In RoverPlanner.cpp
RoverPlanner::RoverPlanner(QWidget *parent) :
QWidget(parent),
ui(new Ui::RoverPlanner)
{
ui->setupUi(this);
QPushButton* btnLoadPaths = this->findChild<QPushButton*>("btn_load_paths");
QPushButton* btnSavePaths = this->findChild<QPushButton*>("btn_save_paths");
QPushButton* btnExecutePath = this->findChild<QPushButton*>("btn_execute_path" );
QPushButton* btnAddSegment = this->findChild<QPushButton*>("btn_add_to_path");
QTreeView* treeView = this->findChild<QTreeView*>("tree_paths");
connect(btnLoadPaths, &QPushButton::clicked, this, [=]() { load_paths_into_tree(treeView); });
connect(treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &RoverPlanner::treeSelectionChanged); // This does not seem to properly bind the index chan
}
void RoverPlanner::treeSelectionChanged(const QModelIndex &prevIndex, const QModelIndex &nextIndex) {
std::cout << "Test" << std::endl;
}
//other functions
When I click on the items, it does not output anything in the console
I'm confused because this seems to be the way to correctly connect the treeview selected index changed. What did I do wrong?
selectionModel gets replaced each time a new model is set for QTreeView.
void QAbstractItemView::setModel(QAbstractItemModel *model):
This function will create and set a new selection model, replacing any model that was previously set with setSelectionModel().
That means you need to reconnect the &QItemSelectionModel::currentChanged signal each time you set a new model.
Starting from the popular Qt SimpleTreeModel, I want to be able to update the entire tree view with new data. The example only populates the tree view once on start up, it does not update the tree view afterwards.
I have made some edits to the example (treeview is now in a dialog so I can press "PushButton" to update treeview) and when I update the tree view, the top most TreeItems become the child TreeItems for each topmost TreeItem. When I update the treeview in this case, before and after should be the same as it is the same data, I don't see why before and after would be different. The screenshots below better illustrate the problem:
Before Updating
After Updating, you can see below that if I click on a item that is used multiple times, they all highlight, which makes sense as they are all (probably) pointing to the same item (I'm not sure how).
My edits to the SimpleTreeModel are below:
main.cpp
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(simpletreemodel);
QApplication app(argc, argv);
Dialog dialog;
dialog.show();
return app.exec();
}
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include <QFile>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
QFile file(":/default.txt");
file.open(QIODevice::ReadOnly);
model = new TreeModel(file.readAll());
file.close();
ui->treeView->setModel(model);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_pushButton_clicked()
{
model->redrawAll();
}
treeitem.cpp (exactly the same as example except with new function below)
void TreeItem::removeChildren() {
m_childItems.clear();
}
treemodel.cpp (exactly the same as example except with new functions below). I am removing all children from rootItem so I can put completely new data on a each update.
TreeModel::TreeModel(const QString &data, QObject *parent)
: QAbstractItemModel(parent)
{
QList<QVariant> rootData;
this->data1 = data;
rootData << "Title" << "Summary";
rootItem = new TreeItem(rootData);
setupModelData(data.split(QString("\n")), rootItem);
}
void TreeModel::redrawAll() {
rootItem->removeChildren();
setupModelData(data1.split(QString("\n")), rootItem);
emit dataChanged(QModelIndex(), QModelIndex());
}
EDIT: I have modified the redrawAll function to below. The result is the same screenshot after updating as the previous TreeModel::redrawAll() function with emit dataChanged(QModelIndex(), QModelIndex()).
void TreeModel::redrawAll() {
// beginResetModel();
rootItem->removeChildren();
QFile file(":/default.txt");
file.open(QIODevice::ReadOnly);
QString data = file.readAll();
setupModelData(data.split(QString("\n")), rootItem);
file.close();
// endResetModel();
// emit dataChanged(QModelIndex(), QModelIndex());
qDebug() << "TreeModel::redrawAll() " << rowCount() << columnCount();
// the output is TreeModel::redrawAll() 6 2
QModelIndex topLeft = this->index(0, 0);
QModelIndex bottomRight = this->index(rowCount(), columnCount());
emit dataChanged(topLeft, bottomRight);
}
The dataChanged() signal that you emit is nonsense. Not only is the invalid index range not allowed, but dataChanged() only indicates a change in contents of the data items, not in the structure of the tree. You seem to be changing the structure as well.
Since you seem to be changing the contents the entire model, you should indicate that you've reset the model:
void TreeModel::redrawAll() {
beginResetModel();
...
endResetModel();
}
How should i store data which is going into a TreeView? A Dictionary (QHash)? Plain Text? JSON?
My Hierarchy would be something like:
{
'Cloth': {
'Tissue':None,
'Leather': {
'Bandage': None
}
},
'Smoke': {
'White':{
'Smallscale': None,
'Largescale':None
}
}
}
Actions:
When I click a leaf-Element it will retrieve the Fullpath, like "Smoke/White/Smallscale" and this will be used as a key to place a SQL-Query.
I would use QStandardItem for every entry and when clicked, I would recursively call their parents, till I hit root.
Any thoughts?
Do you know QJsonTreeWidget?
Of course you don't need to use that library, but I do think you should use JSON in any case. It's almost a standard nowadays and very useful when we're working with trees.
Boost also has a wonderful library to work with JSON.
You can use one of the json library (like cajun) to parse json file.
This is the Qt part:
#include <QtGui>
#include <QTreeView>
class SimpleTreeView :public QTreeView
{
Q_OBJECT
public:
SimpleTreeView(QWidget *parent = 0);
public slots:
void slot_item_clicked(const QModelIndex &idx);
private:
QStandardItemModel *model;
};
#include <simpletreeview.h>
#include <qmessagebox.h>
#include <qobject.h>
SimpleTreeView::SimpleTreeView(QWidget *parent) : QTreeView(parent)
{
model = new QStandardItemModel(2,1);
QStandardItem *item1 = new QStandardItem("Cloth");
QStandardItem *item2 = new QStandardItem("Smoke");
model->setItem(0, 0, item1);
model->setItem(1, 0, item2);
QStandardItem *item3 = new QStandardItem("White");
item2->appendRow(item3);
QStandardItem *leaf = new QStandardItem("Smallscale");
leaf->setData("Smoke/White/Smallscale");
item3->appendRow(leaf);
setModel(model);
connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slot_item_clicked(const QModelIndex &)));
}
void SimpleTreeView::slot_item_clicked(const QModelIndex & idx)
{
QString strData = model->itemFromIndex(idx)->data().toString();
QMessageBox::information(NULL, "Title", strData, QMessageBox::Yes, QMessageBox::Yes);
}
// main.cpp
#include <QApplication>
#include <simpletreeview.h>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
SimpleTreeView view;
view.show();
return app.exec();
}
I'm use QTreeView to get the images path, then I'm use QListView to display the images that in specific path as thumbnail.
The problem in the period, create and display the thumbnail images.
The previous process, take a long time to done, depend on the number of images.
And for that reason I decided to use the threads, maybe helps to prevent the hung up which occur in application and increase the speed of create and display the thumbnail images.
void mainWidget::on_treeView_clicked(const QModelIndex &index){
filesModel->clear();
QFileSystemModel *sysModel = qobject_cast<QFileSystemModel*>(ui->treeView->model());
QDir dir(sysModel->filePath(ui->treeView->currentIndex()));
QFileInfoList filesList = dir.entryInfoList(QStringList() << "*.jpg" << "*.jpeg" << "*.tif" << "*.png" << "*.gif" << "*.bmp" ,QDir::Files);
int filesCount = filesList.size();
for(int i=0;i<filesCount;i++){
QPixmap originalImage(filesList[i].filePath());
if(!originalImage.isNull()){
QPixmap scaledImage = originalImage.scaled(150, 120);
filesModel->setItem(i, new QStandardItem(QIcon(scaledImage), filesList[i].baseName()));
}
}
}
How can I use threads with the previous code ?
I believe that a simple and correct approach is using QtConcurrent as the following:
Note: If you are using Qt 5 you will need to add QT += concurrent to the .pro file.
Header:
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#include <QtConcurrent>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void UpdateItem(int, QImage);
private slots:
void on_treeView_clicked(const QModelIndex &);
void List(QFileInfoList filesList, QSize size);
void setThumbs(int index, QImage img);
private:
Ui::MainWindow *ui;
QFileSystemModel *model;
QStandardItemModel *filesmodel;
QFuture<void> thread;
bool running;
};
CPP file:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThreadPool::globalInstance()->setMaxThreadCount(1);
model = new QFileSystemModel(this);
model->setRootPath("\\");
filesmodel = new QStandardItemModel(this);
ui->treeView->setModel(model);
ui->listView->setModel(filesmodel);
connect(this, SIGNAL(UpdateItem(int,QImage)), SLOT(setThumbs(int,QImage)));
ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
running = false;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_treeView_clicked(const QModelIndex&)
{
filesmodel->clear();
running = false;
thread.waitForFinished();
QDir dir(model->filePath(ui->treeView->currentIndex()));
QFileInfoList filesList = dir.entryInfoList(QStringList() << "*.jpg" << "*.jpeg" << "*.tif" << "*.png" << "*.gif" << "*.bmp", QDir::Files);
int filesCount = filesList.size();
QPixmap placeholder = QPixmap(ui->listView->iconSize());
placeholder.fill(Qt::gray);
for (int i = 0; i < filesCount; i++)
filesmodel->setItem(i, new QStandardItem(QIcon(placeholder), filesList[i].baseName()));
running = true;
thread = QtConcurrent::run(this, &MainWindow::List, filesList, ui->listView->iconSize());
}
void MainWindow::List(QFileInfoList filesList, QSize size)
{
int filesCount = filesList.size();
for (int i = 0; running && i < filesCount; i++)
{
QImage originalImage(filesList[i].filePath());
if (!originalImage.isNull())
{
QImage scaledImage = originalImage.scaled(size);
if (!running) return;
emit UpdateItem(i, scaledImage);
}
}
}
void MainWindow::setThumbs(int index, QImage img)
{
QIcon icon = QIcon(QPixmap::fromImage(img));
QStandardItem *item = filesmodel->item(index);
filesmodel->setItem(index, new QStandardItem(icon, item->text()));
}
You don't have to use threads to keep your application responsive in this case. Use QCoreApplication::processEvents() in the loop to keep the application responsive. QCoreApplication::processEvents() will process all the events in the event queue of the thread which calls it.
This is an older thread, but still comes up in Google. Check out the answer to this related question. I found the use of QIdentityProxyModel to be a bit more elegant, as it allowed QFileSystemModel to be used as the list view's model.