Multiples QSqlQueryModel and QTableView
Hi, I'm making multiples queries to a database by just pressing a QPushButton and reading the query from a QLineEdit. I need to show that queries in a QTabWidget that has multiples QTableViews each one in a different tab. I created a QThread, an in the run() a send a signal with one dynamic model to the QDialog where I have the QTabWidget. Here's the code:
Code:
class GeneralSearchThread
: public QThread{
Q_OBJECT
public:
explicit GeneralSearchThread
( QObject *parent
= 0 );
~GeneralSearchThread();
void makeQuery
( const QString &query
);
signals:
void modelReadytoRead
( QSqlQueryModel *model
);
//this signal will be connected to the QDialog.
public slots:
protected:
void run();
private:
};
GeneralSearchThread
::GeneralSearchThread( QObject *parent
) : QThread( parent
){
}
GeneralSearchThread::~GeneralSearchThread()
{
wait();
qDeleteAll(listaModels); /// I get the problem here!!!
listaModels.clear(); /// I get the problem here!!!
}
void GeneralSearchThread
::makeQuery( const QString &query
) {
queryString = query;
start();
}
void GeneralSearchThread::run()
{
if( db.open() )
{
model->setQuery( queryString, db );
listaModels.append( model );
emit modelReadytoRead( model );
db.close();
}
}
The question here, is that I'm creating the QSqlQueryModels dynamically and trying to store them in a QList (which I call listaModels) and delete it in the destructor of the QThread. But I get a problem of Segmentation fault . But when I put away the lines inside the destructor I get no problems, but I'm afraid of a memory leak. Does anyone know how to solve this problem?, the QSqlQueryModels get deleted when the driver is closed and I'm re-deleting them?. Thanks a lot in advanced.
Extra Info: Driver: QMYSQL3, OS: Ubuntu 9.04, gcc version 4.4.1, Qt version 4.6.
Re: Multiples QSqlQueryModel and QTableView
Look, your models got a "db" parameter in their constructors, but it's lifitime is only to run function finish. Maybe model's destructor want to read or write to QSqlDatabase ?
Re: Multiples QSqlQueryModel and QTableView
I believe your problem may be caused by db.close(); on line 52. Your query model objects are pointers that are remaining in scope with a reference to this QSqlDatabase object after it has been closed.
Quote:
void QSqlDatabase::close ()
Closes the database connection, freeing any resources acquired, and invalidating any existing QSqlQuery objects that are used with the database.
This will also affect copies of this QSqlDatabase object.
See also removeDatabase().
Perhaps using a persistent database connection which remains in scope until after you delete your query models will work better. You can close your database connection in the deconstructor after deleting the queries. Unless you need connections to multiple different databases from the same thread this would also be more efficient as you won't need to constantly open and close connections as well.
Re: Multiples QSqlQueryModel and QTableView
Hi borisbn and ajg85 thanks a lot for the answers, they help me to find out the right answer. All I had to do was just like ajg85 said: using a persistent database connection which remains in scope. Also I've found a better way to delete the models QSqlQueryModel and the QTableViews. The QTableViews are deleted when I delete the QTabWidget because the QTabWidget gets the QTableViews as childs by using the inserTab function. For the QSqlQueryModels, I used a QList of QSharedPointers and I don't have to worry for delete them. I include the code for those who had the same problem:
The .h:
Code:
class GeneralSearchThread
: public QThread{
Q_OBJECT
public:
explicit GeneralSearchThread
( QObject *parent
= 0 );
~GeneralSearchThread();
void makeQuery
( const QString &query
);
signals:
protected:
void run();
private:
QList< QSharedPointer<QSqlQueryModel> > sqlQueryModelList; // God bless templates.
};
The .cpp:
Code:
GeneralSearchThread
::GeneralSearchThread( QObject *parent
) : QThread( parent
){
}
GeneralSearchThread::~GeneralSearchThread()
{
wait();
}
void GeneralSearchThread
::makeQuery( const QString &query
) {
queryString = query;
start();
}
void GeneralSearchThread::run()
{
if( db.open() )
{
QSharedPointer<QSqlQueryModel> model
= QSharedPointer<QSqlQueryModel>
( new QSqlQueryModel );
sqlQueryModelList.append( model );
model.data()->setQuery( queryString, db );
emit modelReadytoRead( model.data() );
db.close();
}
}
To two things. First: there wasn't any problem by calling the db.close() method at the end of the run() method of the QThread.
Second: In my QDialog, in the .h I created a QSqlDatabase db; variable, and in the .cpp in the destructor, I call the db.close() method. I did not call any removeDatabase().
That's all, thanks a lot guys for the answers, Now I run my program and I don't get any nasty message in the console, I just get the beautiful exited with code 0.