multithreading - How can I query asynchronously via a QSqlQueryModel? -


i wish query sql database via qsqlquerymodel (pyqqt 5/qt 5.2) asynchronously, gui doesn't block. how can accomplished? maybe through multithreading? please provide code of how this. if using qsqlquerymodel asynchronously isn't practical, feel free provide alternatives (should usable qtableview though).

my (synchronous) code looks shown beneath. main script bin/app.py loads gui/__init__.py , executes main method. in turn uses gui.models.table load data database. problem gui.models.table queries database synchronously , locks gui in meantime.

bin/app.py:

import os.path import sys  sys.path.insert(0, os.path.abspath(os.path.join(     os.path.dirname(__file__), "..")))  import gui   if __name__ == "__main__":     gui.main() 

gui/__init__.py:

import sys import os.path pyqt5 import uic pyqt5 import qtcore, qtwidgets  gui import models   class mainwindow(qtwidgets.qmainwindow):     def __init__(self):         super(mainwindow, self).__init__()         uic.loadui(os.path.join(os.path.dirname(__file__), 'app.ui'), self)         self.tableview.setmodel(models.table(self))   def main():     app = qtwidgets.qapplication(sys.argv)     w = mainwindow()     w.show()     app.exec_() 

gui/models.py:

import os.path pyqt5.qtcore import * pyqt5.qtsql import *   class table(qsqlquerymodel):     def __init__(self, parent=none):         super(table, self).__init__(parent)          pth = os.path.abspath(os.path.join(os.path.dirname(__file__), "..",                                            "test.sqlite"))         db = qsqldatabase.adddatabase("qsqlite")         db.setdatabasename(pth)         if not db.open():             raise exception("couldn't open database '{}'".format(pth))         try:             self.setquery("select * test")         finally:             db.close() 

unfortunately, typical database driver qt (or else, really) uses synchronous. qt views unfortunately don't know how deal models in foreign threads.

the solution requires shim proxy model, subclassing qidentityproxymodel. first step in implementation shim of source model's method calls blocking qmetaobject::invokemethod calls. needed correct, if not asynchronous yet. it' expose safe interface model lives in thread.

the next step provide asynchronous veneer on of functionality. suppose want make data method asynchronous. is:

  1. for each role, have cache of variant values keyed model index.

  2. on datachanged signal source model, cache values changed, across roles. data call needs queued in model's thread - more on later.

  3. in data, if there's cache hit, return it. otherwise return null variant , queue data call in model's thread.

your proxy should have private method called cachedata called queued calls. in answer, i've detailed how queue functor calls in thread. leveraging that, data call queuing method can like:

void threadsafeproxymodel::queuedatacall(const qmodelindex & index, int role) {   int row = index.row();   int column = index.column();   void * data = index.internalpointer();   postmetacall(sourcemodel()->thread(), [this, row, column, data, role]{     qvariant data = sourcemodel()->data(createindex(row, column, data), role);     qmetaobject::invoke(this, "cachedata",                          q_arg(qvariant, data), q_arg(int, role),                         q_arg(int, row), q_arg(int, column), q_arg(void*, data));   }); } 

this sketch. it'd involved, doable, , still maintaining semantics of real model.


Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

How to get multiresult with multicondition in Sql Server -