0

I have started database loading in non-GUI thread with QtCuncurrent::run. In this nonGui thread I have to create QStandardItemModel* and after that I received model in GUI thread with

model = modelWatcher.result();

on QFutureWatcher finished() signal. It works pretty (UI is builded successfully), but itemChanged() signal is not emitted on item data changes (checkbox state changed). When I creates the model in GUI thread, there are no collisions. Connect works without assert fails:

bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onFolderStateChanged(QStandardItem*)), static_cast<Qt::ConnectionType>(Qt::UniqueConnection));
Q_ASSERT(ok);

As I can see in that thread (there are no code samples and I misunderstood the main idea) I can't to create model (part of Qt5Gui) in nonGui thread. But it works for me! Ui is builded) Also I have to declare sended type with:

qRegisterMetaType<QStandardItemModel*>("QStandardItemModel*");

And my other sends like:

qRegisterMetaType<QList<QTreeWidgetItem*> >("QList<QTreeWidgetItem*>");

works good (though its also Qt5Gui part).

I dont understand how can I **get the model from nonGui thread with full functionality** like itemChanged signals? Its something like emit mysignal(QStandardItemModel*); ? In that case, why other tasks works fine without any emit`s ? including currentChanged signals etc.

Community
  • 1
  • 1
Meteo ir3
  • 449
  • 8
  • 21

2 Answers2

1

When I send model from nonGui thread, some signals have been lost, because model pointer and related data is incorrect if I'm not mistaken. Also QStandardItemModel - is a part of Qt5Gui and its not threadsafe. It means, that model and view should be collected in GUI thread, and data must be sended from worker thread and binded to the model in GUI thread. Its not simple in my situation - I have big tree and I don't want to create my own struct for parsing the tree - but it is a "true way"). I'm using more simple decision - I just sends the parentItem pointer to the new model in GUI thread - and it works. If anybody knows how to send tree structure from worker thread simple - please tell it in this thread) In any case - using text-represented data transfer between threads - its more preferred method (like JSON/XML...any yourself representation, based on indexes of items, listed in ``QList>` etc...)

Meteo ir3
  • 449
  • 8
  • 21
0

Have you tried this ?

bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this,
SLOT(onFolderStateChanged(QStandardItem*)),
static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)); 
Fryz
  • 2,119
  • 2
  • 25
  • 45
  • May be I need to make model->moveToThread(this->thread()); or something else.. ? If I will create the model in UI thread, I need to send all depended data into GUI thread from worker thread, Is it right way? – Meteo ir3 Jul 06 '16 at 07:54
  • Indeed, if you want your slot to be executed in a separate non GUI thread, the worker thread approach is recommanded, as described here http://doc.qt.io/qt-5/qthread.html – Fryz Jul 06 '16 at 10:26
  • QtConcurrent is a more high-level API than QThread. I don't say QThread is better or worse, it's different and you decide what is the best solution for your particular problem. Maybe you can use both API's in your case, so i would say that you may choose what is more convenient for you. – Fryz Jul 06 '16 at 14:03