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
#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);
}
#include <QtGui>
#include <QtSql>
#include "mainwindow.h"
MainWindow::MainWindow()
{
createOtherDock();
createColorDock();
}
//---------------------------------------------------------------------------
void MainWindow::createOtherDock()
{
QDockWidget *dock = new QDockWidget(tr("Other"), this);
otherModel = new QSqlRelationalTableModel(this);
otherModel->setTable("other");
otherModel->select();
otherView = new QTableView(dock);
otherView->setModel(otherModel);
QSortFilterProxyModel *MyProxyModel = new QSortFilterProxyModel(this);
MyProxyModel->setSourceModel(otherModel);
MyProxyModel->sort(1, Qt::DescendingOrder);
otherView->setModel(MyProxyModel);
connect(otherView->selectionModel(),
SIGNAL(currentRowChanged(const QModelIndex &,
const QModelIndex &)),
this, SLOT(RowClicked(const QModelIndex &,
const QModelIndex &)));
dock->setWidget(otherView);
addDockWidget(Qt::RightDockWidgetArea, dock);
}
//---------------------------------------------------------------------------
void MainWindow::createColorDock()
{
QDockWidget *dock = new QDockWidget(tr("Color"), this);
colorModel = new QSqlRelationalTableModel(this);
colorModel->setTable("color");
colorModel->setRelation(color_Other, QSqlRelation("other", "id", "name"));
colorModel->select();
colorView = new QTableView(dock);
colorView->setModel(colorModel);
dock->setWidget(colorView);
addDockWidget(Qt::RightDockWidgetArea, dock);
}
//---------------------------------------------------------------------------
void MainWindow::RowClicked(const QModelIndex & newIndex, const QModelIndex & oldIndex)
{
QModelIndex proxyIndex;
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);
}
To copy to clipboard, switch view to plain text mode
Header for mainwindow.spp
#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
#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,
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
void filterColorView(int id);
private slots:
void RowClicked(const QModelIndex &, const QModelIndex &);
private:
void createOtherDock();
void createColorDock();
QSqlRelationalTableModel *otherModel;
QSqlRelationalTableModel *colorModel;
QTableView *otherView;
QTableView *colorView;
QSortFilterProxyModel *MyProxyModel;
};
#endif
To copy to clipboard, switch view to plain text mode
main.cpp including data creation:
#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();
}
#include <QApplication>
#include <QtGui>
#include <QtSql>
#include "mainwindow.h"
//---------------------------------------------------------------------------
bool Connect()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("data.dat");
if (!db.open())
{
QMessageBox::warning(0, QObject::tr("Error"), db.lastError().text());
return (false);
}
return (true);
}
//---------------------------------------------------------------------------
void createDataBase()
{
QSqlQuery query;
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[])
{
QApplication app(argc, argv);
bool existingData = QFile::exists("data.dat");
if (!Connect())
{
return(1);
}
if (!existingData)
{
createDataBase();
}
MainWindow Window;
Window.show();
// Window.filterColorView();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
project file for Qt Creator:
QT += sql
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
QT += sql
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
To copy to clipboard, switch view to plain text mode
Bookmarks