QSortFilterProxyModel crash with mapToSource()
Hello,
I have the following problem: I use 2 tables where the second table has acolumn containing an index to the first (relation to id of entries in forst table). When I select an entry in the first table, the corresponding entry in the second one should be filtered. This works fine without QSortFilterProxyModel. If I use a QSortFilterProxyModel then I have to remap the selected index from the tableview to the datamodel using the QSortFilterProxyModel 's mapToSource(), but this call crashes for some reason. Searching for solution fails, so I hope I get one here.
In the source I just used native QSortFilterProxyModel , in my application I reimplemented it using a custom sort, I think this is not important, error is the same, so I tried to create a small compilable example with data etc, because the Signal "currentRowChanged" is fired immediately after start so the example crashes immediately (used debugger to find out that mapToSource() is the reason).
Hope I could make clear the problem, thanks in advance for any hints to solve that problem
Armin
Here is the code:
mainwindow.cpp with the "problem" in line 60
Code:
#include <QtGui>
#include <QtSql>
#include "mainwindow.h"
MainWindow::MainWindow()
{
createOtherDock();
createColorDock();
}
//---------------------------------------------------------------------------
void MainWindow::createOtherDock()
{
otherModel->setTable("other");
otherModel->select();
otherView->setModel(otherModel);
MyProxyModel->setSourceModel(otherModel);
MyProxyModel->sort(1, Qt::DescendingOrder);
otherView->setModel(MyProxyModel);
connect(otherView->selectionModel(),
dock->setWidget(otherView);
addDockWidget(Qt::RightDockWidgetArea, dock);
}
//---------------------------------------------------------------------------
void MainWindow::createColorDock()
{
colorModel->setTable("color");
colorModel
->setRelation
(color_Other,
QSqlRelation("other",
"id",
"name"));
colorModel->select();
colorView->setModel(colorModel);
dock->setWidget(colorView);
addDockWidget(Qt::RightDockWidgetArea, dock);
}
//---------------------------------------------------------------------------
{
int id;
if (newIndex.isValid())
{
// --->>>> the next line crashes <<<--- //
proxyIndex = MyProxyModel->mapToSource(newIndex);
if (proxyIndex.isValid())
{
QSqlRecord record
= otherModel
->record
(proxyIndex.
row());
id = record.value("id").toInt();
filterColorView(id);
}
}
}
//---------------------------------------------------------------------------
void MainWindow::filterColorView(int id)
{
colorModel
->setFilter
(QString("color.otherid = %1").
arg(id
));
colorModel->select();
colorView->horizontalHeader()->setVisible(colorModel->rowCount() > 0);
}
Header for mainwindow.spp
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
#include <QtSql>
enum {
other_Id = 0,
other_Name = 1,
};
enum {
color_Id = 0,
color_Name = 1,
color_Other = 2,
};
{
Q_OBJECT
public:
MainWindow();
void filterColorView(int id);
private slots:
private:
void createOtherDock();
void createColorDock();
};
#endif
main.cpp including data creation:
Code:
#include <QApplication>
#include <QtGui>
#include <QtSql>
#include "mainwindow.h"
//---------------------------------------------------------------------------
bool Connect()
{
db.setDatabaseName("data.dat");
if (!db.open())
{
return (false);
}
return (true);
}
//---------------------------------------------------------------------------
void createDataBase()
{
query.exec("DROP TABLE other");
query.exec("DROP TABLE color");
query.exec("CREATE TABLE other ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(10) NOT NULL)");
query.exec("CREATE TABLE color ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name VARCHAR(40) NOT NULL, "
"otherid INTEGER NOT NULL, "
"FOREIGN KEY (otherid) REFERENCES other)");
query.prepare("INSERT INTO other (id, name) "
"VALUES (:id, :name)");
query.bindValue(":id", 1);
query.bindValue(":name", "A");
query.exec();
query.bindValue(":id", 2);
query.bindValue(":name", "b");
query.exec();
query.bindValue(":id", 3);
query.bindValue(":name", "C");
query.exec();
query.prepare("INSERT INTO color (id, name, otherid) "
"VALUES (:id, :name, :otherid)");
query.bindValue(":id", 1);
query.bindValue(":name", "Red");
query.bindValue(":otherid", 1);
query.exec();
query.bindValue(":id", 2);
query.bindValue(":name", "Green");
query.bindValue(":otherid", 2);
query.exec();
query.bindValue(":id", 3);
query.bindValue(":name", "Blue");
query.bindValue(":otherid", 3);
query.exec();
}
//---------------------------------------------------------------------------
int main(int argc, char *argv[])
{
bool existingData
= QFile::exists("data.dat");
if (!Connect())
{
return(1);
}
if (!existingData)
{
createDataBase();
}
MainWindow Window;
Window.show();
// Window.filterColorView();
return app.exec();
}
project file for Qt Creator:
Code:
QT += sql
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
Re: QSortFilterProxyModel crash with mapToSource()
I think you need to change line 21 in mainwindow.cpp to:You've already declared *MyProxyModel in your header file.
HTH
Re: QSortFilterProxyModel crash with mapToSource()
Thanks a lot norobro, this was really a stupid mistake from myself.
Have a nice day
Armin
Re: QSortFilterProxyModel crash with mapToSource()
Armin,
You're welcome. The same thing happens to me. Sometimes, looking at my own code, I see what I expect to see not what is actually there.
Norm