[SOLVED] Program crashes when loading data from a .bin file to QTableView when a button is pressed



  • Hi,

    I have three buttons, Add, Save and Load, I also have two inputFields and a QTableView. The Add button adds data from the input fields to the tableview, the Save and Load well, saves and loads the data to a .bin file.

    Lets pretend for a moment that I already saved some data to the file...

    For some reason if I open the program and try to load the data from the file the program crashes, but if I open the program and start adding empty rows (enough for the data in the file) to the table and then press the load button it works fine, it loads the data from the .bin file.

    Any idea what could be wrong?

    FYI, if I delete the for loops from the load function and press the load button I can see that it actually draws the rows needed to load the data, that tells me that there is something wrong with the for loop but I cannot figure this out.

    Here is the code

    Constructor
    @ model = new QStandardItemModel (this);
    ui->tableView->setModel(model);@

    Add Function

    @ QStandardItem *userInput = new QStandardItem(ui->lineEdit->text());
    QStandardItem *userInput2= new QStandardItem(ui->lineEdit_2->text());

    QList<QStandardItem*> row;
    row <<userInput << userInput2;
    
    model->appendRow(row);@
    

    Save Function

    @
    QFile file("/Users/UserName/Practicing/Resource_Files/someFile.bin");
    if (file.open(QIODevice::WriteOnly))
    {
    QDataStream stream(&file);
    qint32 n = model->rowCount();
    qint32 m = model->columnCount();
    stream << n << m;

       for (int i=0; i<n; ++i)
        {
             for (int j=0; j<m; j++)
            {
                  model->item(i,j)->write(stream);
             }
        }
                   file.close();
    

    }@

    Load Function

    @
    QFile file("/Users/UserName/Practicing/Resource_Files/someFile.bin");
    if (file.open(QIODevice::ReadOnly))
    {
    QDataStream stream(&file);
    qint32 n, m;
    stream >> n >> m;

        model->setRowCount(n);
        model->setColumnCount(m);
    
     for (int i=0; i<n; ++i)
         {
            for (int j=0; j<m; j++)
            {
                model->item(i,j)->read(stream); // here may be the problem
            }
        }
    
     file.close();
    }@
    

    Any Idea what am I doing wrong?


  • Lifetime Qt Champion

    Hi,

    You set the row and column count but that doesn't create the item in there.

    Have a look at the "QTableWidget's documentation":http://qt-project.org/doc/qt-4.8/qtablewidget.html#details



  • First of all thank you for your reply. I'm reading the documentation but it doesn't click.

    bq. Items are created ouside the table (with no parent widget) and inserted into the table with setItem():

    Can you give me another clue?

    FYI,
    I'm using a QTableView not a QTableWidget


  • Lifetime Qt Champion

    Sorry I misread, but I think the answer is still relevant, you modify the row & column count of the model and try to access the items without creating them first.



  • bq. you modify the row & column count of the model and try to access the items without creating them

    Sorry but I don't get this, the items were created here by streaming data from the file, no?
    @stream >> n >> m;@

    Sorry if I don't see the obvious but this is the first time I use MV.


  • Lifetime Qt Champion

    When you write the item to the file you are writing the data and the flags of the item.

    When you want to read, you have to provide an item to read these data and flags.

    @model->item(i,j)@

    points to a null item


  • Moderators

    [quote author="fs_tigre" date="1375973884"]bq. you modify the row & column count of the model and try to access the items without creating them

    Sorry but I don't get this, the items were created here by streaming data from the file, no?
    @stream >> n >> m;@

    Sorry if I don't see the obvious but this is the first time I use MV.[/quote]

    What SGaist is referring to is that you are assuming in your load function that the model is already completely initialized/populated.

    Let's assume you have a model of size 10 rows and 20 cols. If you write those and load them again without destroying model, it will work. If you load a smaller model, let's say 8 rows and 12 cols, it will work.

    If you load a larger model (or when have not a model initialized already) you will fail. Let's assume 12 rows and 20 cols, when you had previously a 10 by 20 model. Where should row 11 and 12 come from?

    You use item(i,j) but you did not assign memory in the section you are showing us. Certainly you may do this somewhere else, but is creating in general a problem.

    [edit, was a bit slow, but basically the same answer as SGaist, but giving you also the hint, why it does work sometimes]



  • Ok, make sense. I basically added a for loop to create empty rows and it works fine, but for some reason I have a filling that this can be optimized.

    Is this how you would do it?

    Load Funtion:

    @QFile file&#40;"/Users/UserName/Practicing/Resource_Files/someFile.bin"&#41;;
    if (file.open(QIODevice::ReadOnly&#41;&#41;
    {
       QDataStream stream(&file&#41;;
        qint32 n, m;
        stream >> n >> m;
    
        // new for loop starts here
        for (int e=0; e<n; ++e&#41;
            {
               for (int e=0; e<m; e++)
               {
                   QStandardItem *item1 = new QStandardItem("");
                   QStandardItem *item2 = new QStandardItem("");
    
                   QList<QStandardItem*> row;
                   row <<item1 << item2;
                   model->appendRow(row);
               }
           }
         // new for loop ends here
    
        model->setRowCount(n);
        model->setColumnCount(m);
    
     for (int i=0; i<n; ++i)
         {
            for (int j=0; j<m; j++)
            {
                model->item(i,j)->read(stream);
            }
        }
    
     file.close();
    }@

  • Lifetime Qt Champion

    Something like that ?
    @
    QDataStream stream(&file);
    qint32 row, col;
    stream >> row >> col;
    model->setRowCount(row);
    model->setColumnCount(col);

        // new for loop starts here
        for (int i = 0; i < row ; ++i) {
               for (int j = 0; j < col; j++) {
                   QStandardItem *item = new QStandardItem;
                   item->read(stream);
                   model->setItem(i, j, item);
               }
           }
    

    @



  • I knew that the way I did it wasn't the best way. Thanks a lot for your help!


  • Lifetime Qt Champion

    You're welcome !

    If everything if fine now, can you update the thread's title to solved ? So other forum users may know a solution has been found :)


Log in to reply
 

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