开发者

Passing QModelIndex cross Thread queued connection

WMIQuery::wmiquery(WMI::WMITable* table, const QString& query, WMI::ProgressIndicator* progressIndicator)

This is the Function signature. and I am calling it through QtConcurrent::run

QFuture<quint32> future = QtConcurrent::run(WMI::WMIQuery::wmiquery, _table, query);

The architecture is quite simple. Expected number of rows that will be returned by the query is known. query is ran parallelly and on each record fetch a row is added to table: WMI::WMITable* WMI::WMITable is a Simple QObject Table Data Structure . it emits rowsAboutToBeInserted(QModelIndex, int, int) and rowsInserted(QModelIndex, int, int) upon row addition.

On the other hand ProgressIndicator in instantiated on main thread and the table is passed to its ctor . it gets the expected total number of rows from WMI::WMIQuery::wmiquery() through ProgressIndicator::setRecordCount(quint64 count). it has a slot rowAdded() which emits the progress out of 100 by doing some simple mathematics. In its ctor it connects

connect(_table, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowAdded()));

What I think. as WMI::WMIQuery::wmiquery() i running on a different thread (on QThreadPo开发者_Python百科ol) this connection is a cross thread queued connection . am I correct ?

I am getting the following error at runtime

QObject::connect: Cannot queue arguments of type 'QModelIndex'

(Make sure 'QModelIndex' is registered using qRegisterMetaType().)

What should I do ? as my SLOT(rowAdded()) does not require the 3 arguments of SIGNAL(rowsInserted(QModelIndex,int,int)) should I make another signal like rowInserted() and emit it whenever I am emitting rowsInserted(QModelIndex,int,int) and use this SIGNAL instead for this coinnection

You may ask why I am using model like signals like rowsInserted(QModelIndex,int,int) in the table data structure. cause I do also have a model that is connected to this table. which will also be updated row by row. however I think that is immater in this regard.


Before emitting a signal across a thread boundary with a non-trivial argument type (like QModelIndex), you must first call this:

qRegisterMetaType<QModelIndex>("QModelIndex");

That prepares Qt to be able to emit the signal across a thread boundary.

Normally you would do this in main() or somewhere that only runs once, before calling emit, but after your QApplication has been instantiated.

This is only necessary for types that are non-trivial. For example, a signal like this would not require you to call qRegisterMetaType()

signals:
   void mySignal(int foo, int bar);

But a signal like this does require qRegisterMetaType():

signals:
   void mySignal(QModelIndex);

For more info, see the Qt docs here: http://doc.qt.nokia.com/latest/qmetatype.html#qRegisterMetaType


I know this is rather late, but I wanted to be sure someone mentioned it: QModelIndex is not meant to be queued, for the same reason that it's not meant to be stored and used later in other ways. That is, if the model changes before you use the QModelIndex, you will get undefined behavior. If you need queued events with model indices, you should probably use QPersistentModelIndex. Not really relevant to the original question, but may be of use to someone who lands here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜