QTableView::setModel(NULL) crash application ???



  • hi guys , I have QTableView crashing , the code is like this

    @
    QAbstractItemModel* model = tableView()->model();
    tableView()->setModel( NULL );
    @

    when I debug , it crashed when setModel(NULL) runs , and it said
    ASSERT:"visualRow != -1" in file itemviews\qtableview.cpp ,
    and I found it strange that if I don't modify the data from tableview , then it won't crash when I debug here
    while if I modify the data from tableview , it will crash here , is this a qt bug or my code's bug . someone could
    give me some good suggestions , thank you very much ~~

    EDIT: please use @-tags for code highlighting, Gerolf



  • I don't understand your problem. If you set the model to NULL then there is nothing to be modified. If you do it nontheless, it's no surprise that your app crashes.



  • It's not supposed to crash. Please make a complete testcase.



  • but when I debug it , it crash at the setModel(NULL) and assert "visualRow != -1" , does this mean before I setModel(NULL) , I should hide all rows in tableView , if I don't hide , it will crash , do you have met such situations ?



  • I cannot reproduce this. Further investigation is not possible with your very tiny code snippets.

    The following code works perfectly for me:

    ---------- nullmodeltest.h ----------

    @
    #ifndef NULLMODELTEST_H
    #define NULLMODELTEST_H

    #include <QWidget>

    class QTableView;
    class QStandardItemModel;
    class QPushButton;

    class NullModelTest : public QWidget
    {
    Q_OBJECT
    public:
    explicit NullModelTest(QWidget *parent = 0);

    public slots:
    void changeModel();

    protected:
    QTableView *view;
    QStandardItemModel *model;
    QPushButton *button;
    };

    #endif // NULLMODELTEST_H
    @

    ---------- nullmodeltest.cpp ----------

    @
    #include "nullmodeltest.h"
    #include <QLayout>
    #include <QTableView>
    #include <QStandardItemModel>
    #include <QPushButton>
    #include <QDebug>

    NullModelTest::NullModelTest(QWidget *parent) :
    QWidget(parent)
    {
    QVBoxLayout *lay = new QVBoxLayout(this);
    view = new QTableView;
    lay->addWidget(view);

    button = new QPushButton;
    button->setText("change model");
    lay->addWidget(button);
    
    connect(button, SIGNAL(clicked()), this, SLOT(changeModel()));
    
    int numRows = 5;
    int numCols = 4;
    model = new QStandardItemModel(numRows, numCols, this);
    for(int r = 0; r < numRows; ++r)
        for(int c = 0; c < numCols; ++c)
            model->setItem(r, c, new QStandardItem(QString("cell %1/%2").arg(r).arg(c)));
    
    view->setModel(model);
    

    }

    void NullModelTest::changeModel()
    {
    qDebug() << "NullModelTest::changeModel() ----- triggered -----";
    qDebug() << "NullModelTest::changeModel(): old model=" << view->model();
    if(view->model())
    view->setModel(0);
    else
    view->setModel(model);
    qDebug() << "NullModelTest::changeModel(): new model=" << view->model();
    }
    @

    ---------- main.cpp ----------

    @
    #include <QApplication>
    #include "nullmodeltest.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    NullModelTest nmt;
    nmt.show();
    
    return a.exec&#40;&#41;;
    

    }
    @



  • thanks , Volker , I also did the simple testing like you , it won't crash , in the project , it involves a lot of other code , like delegates , a little complicated , but when I debug the crash , it crash at the setModel(NULL), and I didn't find where the other code crashed , I will pay more time on it , thanks very much ~~



  • [quote author="brucewuu" date="1309690384"]thanks , Volker , I also did the simple testing like you , it won't crash , in the project , it involves a lot of other code , like delegates , a little complicated , but when I debug the crash , it crash at the setModel(NULL), and I didn't find where the other code crashed , I will pay more time on it , thanks very much ~~[/quote]

    So it is time to create a

    • short
    • complete
    • compilable

    example for us that demonstrates the problem. Our crystal balls are on summer vacation, so unfortunately, we cannot guess what's going wrong...

    Oh, and experience tells us that your chances are good to find the mistake yourself while preparing the example :-)



  • thanks , Volker , I will try to find the problem ~~



  • I'm having the same issue. setModel(NULL) crashes with:

    ASSERT: "visualRow != -1" in file itemviews\qtableview.cpp, line 1568

    It seems to crash if setModel(NULL) is called while an item in the table view is being edited.

    I don't know much more about it right now. I found this thread while trying to find info about the problem.

    Qt 4.8 on Windows 7



  • I made a test case and can consistently reproduce the problem. It happens when the following conditions (at least) are true:

    1. The table is in edit mode (e.g. you are typing text in a cell and have not accepted the changes yet).
    2. setModel(NULL) is called from the mousePressed event of another control.

    It does not happen when setModel(NULL) is called from the clicked() signal of a push button.

    Please let me know if I should start a new thread for this, and I will repost this there.

    Here is a program that shows the problem. Click the table cell to begin editing it, and while it is being edited, click inside the frame on the right to crash the program (start an empty Qt project, create an empty cpp file and paste this all in there):

    main.cpp
    @#include <QtGui/QApplication>
    #include <QMainWindow>
    #include <QTableView>
    #include <QHBoxLayout>
    #include <QAbstractTableModel>

    class TestModel : public QAbstractTableModel {
    public:

    explicit TestModel (QWidget *parent) :
        QAbstractTableModel(parent),
        value_("Edit Me")
    {
    }
    
    int rowCount (const QModelIndex &parent) const {
        return parent.isValid() ? 0 : 1;
    }
    
    int columnCount (const QModelIndex &parent) const {
        return parent.isValid() ? 0 : 1;
    }
    
    Qt::ItemFlags flags (const QModelIndex &index) const {
        return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
    }
    
    QVariant data (const QModelIndex &index, int role) const {
        return (role == Qt::DisplayRole || role == Qt::EditRole) ? QVariant(value_) : QVariant::Invalid;
    }
    
    bool setData (const QModelIndex &index, const QVariant &value, int role) {
        if (role == Qt::EditRole) {
            value_ = value.toString();
            dataChanged(index, index);
            return true;
        } else
            return false;
    }
    

    private:

    QString value_;
    

    };

    class NullModelMousePressedFrame : public QFrame {

    public:

    explicit NullModelMousePressedFrame (QTableView *view) :
        view_(view)
    {
    }
    
    void mousePressEvent (QMouseEvent *event) {
        view_->setModel(NULL);
    }
    

    private:

    QTableView *view_;
    

    };

    int main (int argc, char **argv) {

    QApplication app(argc, argv);
    
    QHBoxLayout *layout = new QHBoxLayout();
    
    QTableView *table = new QTableView();
    table->setModel(new TestModel(table));
    layout->addWidget(table);
    
    NullModelMousePressedFrame *frame = new NullModelMousePressedFrame(table);
    frame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
    frame->setMinimumWidth(100);
    frame->setMaximumWidth(100);
    frame->setFrameShape(QFrame::StyledPanel);
    frame->setFrameShadow(QFrame::Sunken);
    layout->addWidget(frame);
    
    QMainWindow *window = new QMainWindow();
    window->setCentralWidget(new QFrame());
    window->centralWidget()->setLayout(layout);
    window->setWindowTitle("Click blank area on right while editing table.");
    window->show();
    
    return app.exec(&#41;;
    

    }
    @



  • A workaround is to call setFocus() in the mousePressEvent() before setting the model to NULL. Clearly some kind of issue with QTableView's assumptions during / just before a focus change. This is also suggested by the fact that the assertion failure is in QTableView::moveCursor (http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/itemviews/qtableview.cpp line 1561, although that's 4.7 not 4.8).

    Anyways this makes the above example not crash:

    @ void mousePressEvent (QMouseEvent *event) {
    setFocus(); // workaround (must be before setModel)
    view_->setModel(NULL);
    }
    @



  • This an old post but may be for colleagues who may face the the same challenge. I faced the same scenario that led me to this Thread. My tableview was attached to a proxy model and a delegate. The table content was controlled by a mapper index where by each time the mapper changes...the content had to change. THUS I had to empty the tableview with view->setModel(NULL) (otherwise a static persistentEditor was being created especially the first index(i.e index(0,0)) once current Mapper Index was changed) Like jCipriani noted...The Crash only happens when the current tableview index is left blank ...but then for my case it was crashing only when other indexes having some data before the Mapper Index...changed

    Well, I solved it by emptying the tableview before submitAll() or revertAll() QSqlRelationalTableModel functions! Also before you close the window make sure to setFocus() on another widget (other than the tableview) on the window. All these are workarounds but If someone has a better solution please explain. I hope this helps someone!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.