I have problem with loading QAbstractListModel
items to QML GridView
asynchronously. When I execute method that loads items to model I have to wait for every item is loaded. How can I get items dynamically (i.e. one by one)?
I have pretty big model objects with 17 fields (QString
and QStringList
's). Objects are contained in custom model:
class MyListModel : public QAbstractListModel
{
Q_OBJECT
public:
enum ListItemRole {
IdRole = Qt::UserRole,
VisualIndexRole,
NameRole,
...
};
MyListModel(QObject *parent = 0)
: QAbstractListModel(parent)
{
}
int rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_data.size();
}
QVariant data(const QModelIndex &index, int role) const
{
if( !index.isValid() || index.row() >= m_data.size() || index.row() < 0)
return QVariant();
switch(role) {
case NameRole:
return QVariant(m_data.at(index.row())->name());
...
(rest of the roles)
...
}
}
QHash<int, QByteArray> roleNames() const
{
QHash<int, QByteArray> roles;
roles[IdRole] = "folderName";
...
return roles;
}
private:
QList<Item*> m_data;
}
I'm inserting items to model by append method:
void append(Item *item)
{
beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
m_data.append(item);
endInsertRows();
}
Items is created in loop in other function. This function loads data from 3 JSON files. It takes about 2 seconds to load 50 items.
On top of this list model, there are two QSortFilterProxyModel
's responsible for sorting and filtering view. Filtering model is registered as QML type and used in GridView
.
What I tried:
- Use
QtConcurrent::run()
method for function that create item - FAIL ( view not refreshed after every item) - Make
QThread
for every list item, and load it withWorker
class - FAIL ( crashes and strange behavior of application, i.e. empty items, empty spaces between delegates and - as in the first point - not async) - Move model to
QThread
and use item creating loop inWorker
class - Partiall Success ( when I useQCoreApplication::processEvents(QEventLoop::AllEvents,100);
as a sleep function I could get one by one items, but there is heavy performance issues and - as i read - it is not good approach)
Is there any possible workarounds for my problem?