Unsolved table.selectRow no doing anything
-
Hi and welcome to devnet,
The first thing to do:
- gather the full setup information from your user as:
-- PyQt version
-- Running OS (precise version)
-- Python version
-- How was your application installed
-- How was PyQt installed
Etc.
- gather the full setup information from your user as:
-
My user is on Windows 10.
I distribute the software using pyinstaller. The installer is made using Python 3.7.4 and PyQt5.15, running on Windows 10 with all the latest patches.
-
I've been doing some more debugging and theorising.
During during <process the changes>, what I actually do is unload a Qt database, run non-Qt database code from another library, and then reload the database in Qt.
Not sure if it's related, but when I try to remove the Qt database, I get this error:
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
However, I think I'm taking every precaution:
self.table.setModel(QtGui.QStandardItemModel()) del self.card_model # (The previous model for the table) self.card_model = None connection_name = self.qt_db.connectionName() self.qt_db.close() del self.qt_db QtSql.QSqlDatabase.removeDatabase(connection_name)
All my queries were also in local variables in other functions, so they should be out of scope at that point.
What am I doing wrong?
-
You are keeping a copy of a QSqlDatabase. Do not do that. QSqlDatabase handles that. You have a note in the documentation explaining why you get that message.
-
No longer stored qt_db as a class variable. Unloading code is changed to
self.table.setModel(QtGui.QStandardItemModel()) del self.card_model self.card_model = None QtSql.QSqlDatabase.removeDatabase(\ QtSql.QSqlDatabase.database().connectionName())
Does not help with the error message...
-
Then please provide a minimal runnable code example that shows the issue.
-
I've done some more debugging and it looks like the database stuff is a red herring. First of all, I have the same warnings on my machine, and they don't affect the row selection.
Also, I now had the user execute the following code after the database has been unloaded and reloaded, and the model and the table have been completely reinitialised from scratch:
def page_up_down_edit(self, up_down): <...database manipulation stuff...> self.table.selectRow(current_row + shift) QtWidgets.QMessageBox(text=f"Exit: selected_rows {current_row+shift} {self.table.selectionModel().selectedRows()}").exec_() return
This shows a dialog on his machine displaying "Exit: selected_rows 435 []". So, no row gets selected, even though that's exactly what the previous command should do....
-
Are you sure about the values of
current_row
andshift
? -
Yes, that's entirely expected.
I am destroying and recreating the model and the table from scratch inbetween, though. Could it be related to that in any way? Or does the selectRow statement take a while to get into effect?
-
Do you really need to destroy everything every time ?
-
Yes, because I need to release access to the Qt database, so I have to invalidate the model.
Meanwhile, I managed to get rid of a consistent 'qt_sql_default_connection' still in use' warning (I was still holding on to a variable containing the model), but that has had zero effect....
self.table.selectRow(current_row + shift) does not do anything in that place in my code (at least on my user's machine), and no error message gets written to the console either.
I tried all sorts of things, like rearranging my code, in the hope that I could work around this, but to no avail....
My guess is that there's a very subtle bug in Qt that causes this, but as it only happens on some machines and in a quite specific scenario that cannot be be reduced to a simple runnable test case, it will be very difficult to track down what's happening.
Unless people here have some brilliant insight or new things to try?
-
One thing you can do is to just clear the model content rather than replacing the whole model object.
What type of database are you using ?
-
It's an sqlite database.
I do this when I unload the Qt view of the database:
self.table.setModel(QtGui.QStandardItemModel()) del self.card_model self.card_model = None
And when I reload, I do
self.card_model = CardModel(component_manager=self.component_manager) self.card_model.setTable("cards") <...> self.table.setModel(self.card_model)
-
That looks pretty convoluted. Can you explain why you remove the connection ?
-
Because the backend library I use to process the necessary changes to the database is pure Python, so I need to release Qt's lock on the database first, have the Python library change the database, and then reload the database in Qt.
-
@PeterB74
I will say this then: if you are saying you are actually using non-Qt Python stuff to execute the database updates/access I wonder why you are also trying to useQSqlDatabase
at all? Maybe you should go via the Python level model? Closing and re-opening the connection/database/model is an "expensive" operation. Just a thought, I admit I don't know your full situation. -
I don't think replacing a fast C++ Qt direct database access with a slow Python wrapper is a good idea :-)
Updates to the database happen relatively infrequently, but scrolling through it and filtering is very common.
-
@PeterB74
And you think the time taken to process the data in-memory in C++ versus in Python outweighs the time taken to access the data in the database across the library/protocol?Anyway, best of luck.
-
The overhead of performing function calls in Python is very big because of the dynamical typing, and you need hundreds of calls to display a reasonable part of your table.
I tried it out, and scrolling becomes unbearingly slow... Accessing the database while staying in C is way more efficient than C calling Python which then calls C again.
-
@PeterB74
Point taken! I can only say I used Python/PyQt to do SQL database read/writes/attached as model for Qt views and found it fine for large data (obviously with suitable paging for views if required). But I wasn't doing any Python<->C++ (other, of course, than what's going on in Qt C++ code).