-4

I am making a library managent software using Qt5. I have defined functions to open and save a library and add a book.

I recently included tabs in my main window so that like notepad++, we can work simultaneously with different libraries. the first library file opens fine but the second one gives me a segmentation fault(found this using the debugger)

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QFileDialog>
#include <QTextStream>
#include "form.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model.resize(1);

    model[0] = new QStandardItemModel(l.numOfBooks(), 3, this);
    model[0]->setHorizontalHeaderItem(0, new QStandardItem( QString("Name") ));
    model[0]->setHorizontalHeaderItem(1, new QStandardItem( QString("Author") ));
    model[0]->setHorizontalHeaderItem(2, new QStandardItem( QString("UID") ));

    ui->tableView->setModel(model[0]);
    model[0]->setRowCount(0);

    showMaximized();

    fileName.resize(0);

    ui->tabWidget->removeTab(1);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_actionAdd_Book_triggered()
{
    d = new Dialog(this);

    connect(d, SIGNAL(bookDetailsEntered(book&)), this, SLOT(onBookDetailsEntered(book&)));

    d->exec();
}

void MainWindow :: onBookDetailsEntered(book& b)
{
    d->close();
    delete d;

    l.addBook(b);
    model[ui->tabWidget->currentIndex()]->insertRow(model[ui->tabWidget->currentIndex()]->rowCount(QModelIndex()));

    QStandardItem *name = new QStandardItem(b.getName());
    model[ui->tabWidget->currentIndex()]->setItem(model[ui->tabWidget->currentIndex()]->rowCount() - 1, 0, name);

    QStandardItem *author = new QStandardItem(b.getAuthor());
    model[ui->tabWidget->currentIndex()]->setItem(model[ui->tabWidget->currentIndex()]->rowCount() - 1, 1, author);

    QStandardItem *uid = new QStandardItem(b.getUid());
    model[ui->tabWidget->currentIndex()]->setItem(model[ui->tabWidget->currentIndex()]->rowCount() - 1, 2, uid);

    ui->tableView->resizeColumnsToContents();
}

void MainWindow::on_actionSave_triggered()
{
    QString fn;

    if(fileName[ui->tabWidget->currentIndex()] == "")
        fn = QFileDialog::getSaveFileName(this, "Save");
    else
        fn = fileName[ui->tabWidget->currentIndex()];

    QFile file;

    if(fn.right(3) == ".lc")
    {
        file.setFileName(fn);
        if(!file.open(QFile::WriteOnly))
            QMessageBox :: warning(this, "Oops!", "Unable to open the file");
    }
    else
    {
        fn += ".lc";
        file.setFileName(fn);

        if(!file.open(QFile::WriteOnly))
            QMessageBox :: warning(this, "Oops!", "Unable to open the file");
    }

    //use tableview here
    QTextStream out(&file);

    for(int i = 0; i < model[ui->tabWidget->currentIndex()]->rowCount(); ++i)
    {
        QString s = "";

        QModelIndex index = model[ui->tabWidget->currentIndex()]->index(i, 0, QModelIndex());
        s += model[ui->tabWidget->currentIndex()]->data(index).toString();
        s += " ~ ";

        index = model[ui->tabWidget->currentIndex()]->index(i, 1, QModelIndex());
        s += model[ui->tabWidget->currentIndex()]->data(index).toString();
        s += " ~ ";

        index = model[ui->tabWidget->currentIndex()]->index(i, 2, QModelIndex());
        s += model[ui->tabWidget->currentIndex()]->data(index).toString();
        s += "\n";

        out << s;
    }

    file.flush();
    file.close();
}

void MainWindow::on_actionOpen_triggered()
{
    //ui->label->setText("");

    //model->removeRows(0, model->rowCount());

    QString fn = QFileDialog :: getOpenFileName(this, "Open");
    QFile file(fn);

    fn = fn.right(fn.length() - fn.lastIndexOf('/') - 1);

    if(ui->tabWidget->tabText(ui->tabWidget->currentIndex()) != "Unnamed")
    {
        ui->tabWidget->addTab(new Form(), fn);
        ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
    }
    else
        ui->tabWidget->setTabText(ui->tabWidget->currentIndex(), fn);

    //resize arrays to fit things in

    fileName.resize(ui->tabWidget->count());
    fileName[ui->tabWidget->count() - 1] = fn;

    model.resize(ui->tabWidget->count());

    if(!file.open(QFile::ReadOnly))
    {
        QMessageBox :: warning(this, "Oops!", "File not open. Check if file exists");
        return;
    }

    //use table view here

    QTextStream in(&file);

    while(!in.atEnd())
    {
        QString s = in.readLine();

        int i;
        for(i = 0; s.at(i) != "~"; ++i);

        QString name = s.left(i - 1);

        for(i = name.length() + 3; s.at(i) != "~"; ++i);

        QString author = s.mid(name.length() + 3, (i - 1) - (name.length() + 3) );

        QString uid = s.right(s.length() - (i + 2));

        //display it
        model[ui->tabWidget->currentIndex()] -> insertRow(model[ui->tabWidget->currentIndex()]->rowCount(QModelIndex()));

        //name of the book
        QStandardItem* n = new QStandardItem(name);
        model[ui->tabWidget->currentIndex()]->setItem(model[ui->tabWidget->currentIndex()]->rowCount() - 1, 0, n);

        //author
        QStandardItem* a = new QStandardItem(author);
        model[ui->tabWidget->currentIndex()]->setItem(model[ui->tabWidget->currentIndex()]->rowCount() - 1, 1, a);

        //uid
        QStandardItem* u = new QStandardItem(uid);
        model[ui->tabWidget->currentIndex()]->setItem(model[ui->tabWidget->currentIndex()]->rowCount() - 1, 2, u);
    }

    file.close();
}


void MainWindow::on_actionName_triggered()
{
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);
}

void MainWindow::on_actionAuthor_triggered()
{
    ui->tableView->sortByColumn(1, Qt::AscendingOrder);
}


void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
    QMessageBox::StandardButton reply = QMessageBox :: warning(this, "Warning: ", "You will not ba able to get back details if you close without saving. Do you want to continue?",
                                                               QMessageBox :: Yes | QMessageBox :: No);

    if(reply == QMessageBox :: Yes)
        ui->tabWidget->removeTab(index);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "library.h"
#include "dialog.h"
#include <QStandardItem>

using namespace std;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private slots:
    void on_actionAdd_Book_triggered();
    void onBookDetailsEntered(book& b);

    void on_actionSave_triggered();

    void on_actionOpen_triggered();
    void on_actionName_triggered();

    void on_actionAuthor_triggered();

    void on_tabWidget_tabCloseRequested(int index);

private:
    Ui::MainWindow *ui;
    library l;
    Dialog *d;
    vector <QStandardItemModel *>model;
    vector<QString> fileName;
};

#endif // MAINWINDOW_H

line 169 of mainwindow.cpp i.e.

model[ui->tabWidget->currentIndex()] -> insertRow(model[ui->tabWidget->currentIndex()]->rowCount(QModelIndex()));

gives this error.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Hemil
  • 916
  • 9
  • 27
  • You could show the complete error message. – eyllanesc Apr 07 '18 at 06:31
  • @eyllanesc thank you again for being for help. I have updated the question with the screenshot of the message – Hemil Apr 07 '18 at 06:41
  • 1
    That error message is because you are accessing memory that you have not reserved, check for example that the model size is greater than the currentIndex() value, or that the model that is saved in the currentIndex() position within the model is initialized, there are many causes, the solution will find it debugging. – eyllanesc Apr 07 '18 at 06:44
  • I resize my model be4 in line 141 : model.resize(ui->tabWidget->count()); @ellyanesc – Hemil Apr 07 '18 at 06:53
  • let's say that you have your 5 QStandardItemModel, and you change the size as your comment indicates, with what QStandardItemModel are the new positions filled? with QStandardItemModel null, and you want to use the insertRow method to a QStandardItemModel null. Do you think it's right? If you are going to change the size of the QVector you must also create new models for the new positions – eyllanesc Apr 07 '18 at 06:58
  • I also find it strange because you create so many models. I think you should have a model and filter the data with QSortProxyModel for each page. Review the following example: http://doc.qt.io/qt-5/qtwidgets-itemviews-addressbook-example.html – eyllanesc Apr 07 '18 at 07:07
  • I think i will rethink the structure and make the program again @eyllanesc – Hemil Apr 07 '18 at 07:09
  • Consider extracting a [mcve]. – Ulrich Eckhardt Apr 07 '18 at 07:40

1 Answers1

1

You have the std::vector MainWindow::model with the size 1 and it seems that you are trying to access an index, which is out of the vectors boundary (ui->tabWidget->currentIndex()). You have a dependency between ui->tabWidget and your model vector, which can result into such index problems.

When restructuring your program, I recommend you to think about deriving a subclass from QAbstractTableModel (it seems like you have over and over again the same data for your each book so a table seems appropriate). You probably can even use the predefined QSqlTableModel class, which needs you to use a sql driver (sqlite would probably fit your needs best), but which avoids you to write any new code to save your data into a file or to load it from a file.

tangoal
  • 724
  • 1
  • 9
  • 28