Results 1 to 4 of 4

Thread: QSortFilterProxyModel crash with mapToSource()

  1. #1
    Join Date
    Jan 2010
    Posts
    11
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Windows

    Default 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
    Qt Code:
    1. #include <QtGui>
    2. #include <QtSql>
    3. #include "mainwindow.h"
    4. MainWindow::MainWindow()
    5. {
    6. createOtherDock();
    7. createColorDock();
    8. }
    9. //---------------------------------------------------------------------------
    10. void MainWindow::createOtherDock()
    11. {
    12. QDockWidget *dock = new QDockWidget(tr("Other"), this);
    13.  
    14. otherModel = new QSqlRelationalTableModel(this);
    15. otherModel->setTable("other");
    16. otherModel->select();
    17.  
    18. otherView = new QTableView(dock);
    19. otherView->setModel(otherModel);
    20.  
    21. QSortFilterProxyModel *MyProxyModel = new QSortFilterProxyModel(this);
    22. MyProxyModel->setSourceModel(otherModel);
    23. MyProxyModel->sort(1, Qt::DescendingOrder);
    24. otherView->setModel(MyProxyModel);
    25.  
    26. connect(otherView->selectionModel(),
    27. SIGNAL(currentRowChanged(const QModelIndex &,
    28. const QModelIndex &)),
    29. this, SLOT(RowClicked(const QModelIndex &,
    30. const QModelIndex &)));
    31.  
    32. dock->setWidget(otherView);
    33. addDockWidget(Qt::RightDockWidgetArea, dock);
    34. }
    35. //---------------------------------------------------------------------------
    36. void MainWindow::createColorDock()
    37. {
    38. QDockWidget *dock = new QDockWidget(tr("Color"), this);
    39.  
    40. colorModel = new QSqlRelationalTableModel(this);
    41. colorModel->setTable("color");
    42. colorModel->setRelation(color_Other, QSqlRelation("other", "id", "name"));
    43. colorModel->select();
    44.  
    45. colorView = new QTableView(dock);
    46. colorView->setModel(colorModel);
    47.  
    48. dock->setWidget(colorView);
    49. addDockWidget(Qt::RightDockWidgetArea, dock);
    50. }
    51. //---------------------------------------------------------------------------
    52. void MainWindow::RowClicked(const QModelIndex & newIndex, const QModelIndex & oldIndex)
    53. {
    54. QModelIndex proxyIndex;
    55. int id;
    56.  
    57. if (newIndex.isValid())
    58. {
    59. // --->>>> the next line crashes <<<--- //
    60. proxyIndex = MyProxyModel->mapToSource(newIndex);
    61. if (proxyIndex.isValid())
    62. {
    63. QSqlRecord record = otherModel->record(proxyIndex.row());
    64. id = record.value("id").toInt();
    65. filterColorView(id);
    66. }
    67. }
    68. }
    69. //---------------------------------------------------------------------------
    70. void MainWindow::filterColorView(int id)
    71. {
    72. colorModel->setFilter(QString("color.otherid = %1").arg(id));
    73. colorModel->select();
    74. colorView->horizontalHeader()->setVisible(colorModel->rowCount() > 0);
    75. }
    To copy to clipboard, switch view to plain text mode 

    Header for mainwindow.spp
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QtGui>
    5. #include <QtSql>
    6.  
    7. enum {
    8. other_Id = 0,
    9. other_Name = 1,
    10. };
    11. enum {
    12. color_Id = 0,
    13. color_Name = 1,
    14. color_Other = 2,
    15. };
    16.  
    17. class MainWindow : public QMainWindow
    18. {
    19. Q_OBJECT
    20.  
    21. public:
    22. MainWindow();
    23. void filterColorView(int id);
    24.  
    25. private slots:
    26. void RowClicked(const QModelIndex &, const QModelIndex &);
    27. private:
    28. void createOtherDock();
    29. void createColorDock();
    30.  
    31.  
    32. QTableView *otherView;
    33. QTableView *colorView;
    34.  
    35. QSortFilterProxyModel *MyProxyModel;
    36. };
    37.  
    38. #endif
    To copy to clipboard, switch view to plain text mode 


    main.cpp including data creation:
    Qt Code:
    1. #include <QApplication>
    2. #include <QtGui>
    3. #include <QtSql>
    4.  
    5. #include "mainwindow.h"
    6. //---------------------------------------------------------------------------
    7. bool Connect()
    8. {
    9. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    10. db.setDatabaseName("data.dat");
    11. if (!db.open())
    12. {
    13. QMessageBox::warning(0, QObject::tr("Error"), db.lastError().text());
    14. return (false);
    15. }
    16. return (true);
    17. }
    18. //---------------------------------------------------------------------------
    19. void createDataBase()
    20. {
    21. QSqlQuery query;
    22. query.exec("DROP TABLE other");
    23. query.exec("DROP TABLE color");
    24.  
    25. query.exec("CREATE TABLE other ("
    26. "id INTEGER PRIMARY KEY AUTOINCREMENT, "
    27. "name VARCHAR(10) NOT NULL)");
    28.  
    29. query.exec("CREATE TABLE color ("
    30. "id INTEGER PRIMARY KEY AUTOINCREMENT, "
    31. "name VARCHAR(40) NOT NULL, "
    32. "otherid INTEGER NOT NULL, "
    33. "FOREIGN KEY (otherid) REFERENCES other)");
    34.  
    35. query.prepare("INSERT INTO other (id, name) "
    36. "VALUES (:id, :name)");
    37. query.bindValue(":id", 1);
    38. query.bindValue(":name", "A");
    39. query.exec();
    40. query.bindValue(":id", 2);
    41. query.bindValue(":name", "b");
    42. query.exec();
    43. query.bindValue(":id", 3);
    44. query.bindValue(":name", "C");
    45. query.exec();
    46.  
    47. query.prepare("INSERT INTO color (id, name, otherid) "
    48. "VALUES (:id, :name, :otherid)");
    49. query.bindValue(":id", 1);
    50. query.bindValue(":name", "Red");
    51. query.bindValue(":otherid", 1);
    52. query.exec();
    53. query.bindValue(":id", 2);
    54. query.bindValue(":name", "Green");
    55. query.bindValue(":otherid", 2);
    56. query.exec();
    57. query.bindValue(":id", 3);
    58. query.bindValue(":name", "Blue");
    59. query.bindValue(":otherid", 3);
    60. query.exec();
    61. }
    62. //---------------------------------------------------------------------------
    63.  
    64. int main(int argc, char *argv[])
    65. {
    66. QApplication app(argc, argv);
    67.  
    68. bool existingData = QFile::exists("data.dat");
    69. if (!Connect())
    70. {
    71. return(1);
    72. }
    73. if (!existingData)
    74. {
    75. createDataBase();
    76. }
    77. MainWindow Window;
    78. Window.show();
    79. // Window.filterColorView();
    80. return app.exec();
    81. }
    To copy to clipboard, switch view to plain text mode 

    project file for Qt Creator:
    Qt Code:
    1. QT += sql
    2. SOURCES += main.cpp \
    3. mainwindow.cpp
    4. HEADERS += mainwindow.h
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: QSortFilterProxyModel crash with mapToSource()

    I think you need to change line 21 in mainwindow.cpp to:
    Qt Code:
    1. MyProxyModel = new QSortFilterProxyModel(this);
    To copy to clipboard, switch view to plain text mode 
    You've already declared *MyProxyModel in your header file.
    HTH

  3. The following user says thank you to norobro for this useful post:

    Armin (6th February 2010)

  4. #3
    Join Date
    Jan 2010
    Posts
    11
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSortFilterProxyModel crash with mapToSource()

    Thanks a lot norobro, this was really a stupid mistake from myself.
    Have a nice day
    Armin

  5. #4
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default 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
    Last edited by norobro; 6th February 2010 at 20:08. Reason: typo

Similar Threads

  1. QSortFilterProxyModel - crash
    By steg90 in forum Qt Programming
    Replies: 3
    Last Post: 4th June 2008, 14:14
  2. QAbstractProxyModel::mapToSource performance issues
    By maximAL in forum Qt Programming
    Replies: 2
    Last Post: 14th January 2008, 22:48
  3. Using QSortFilterProxyModel
    By Jennie Bystrom in forum Qt Programming
    Replies: 3
    Last Post: 6th December 2007, 10:28
  4. QSortFilterProxyModel - filterKeyColumn
    By SirBabyface in forum Qt Programming
    Replies: 1
    Last Post: 7th September 2007, 16:09
  5. QSortFilterProxyModel
    By evgenM in forum Qt Programming
    Replies: 1
    Last Post: 18th March 2007, 11:53

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.