Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Problem to access QStandardItemModel object



  • I have built a class which contains an object "QTreeView" linked to an object "QStandardItemModel".
    Inside this class, a button is linked to a "slot function" which inserts lines in the "QTreeView" and it works very well.
    But if I call this function from outside this object, it crashes because the functions of the object "QStandardItemModel" are not accessible anymore. And I don't understand why...

    The image below shows the very simple interface:

    • The object "QTreeView" with 2 columns
    • The left button "Insert Line" which belongs to the same class as the "QStandardItemModel" and the "QTreeView". This button is linked to a function "void InsertLine()" with QObject::connect process. This button works.
    • The button at the bottom "Test" does not belong to this class: it is connected to an intermediate function which calls the method "InsertLine()". This button does not work.
      0_1567190382667_View_interface.png

    The line which causes the crash is:

    nbColumns = SIM_table.columnCount();
    

    The header file of the main class "mainwindow.h" is:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include "blocktablefields.h"
    
    #include <QMainWindow>
    #include <QPushButton>
    #include <QStandardItemModel>
    #include <QTreeView>
    
    QT_BEGIN_NAMESPACE
    class QAction;
    class QLabel;
    class QMenu;
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow();
    
    private slots:
        void Test();
    
    
    private:
        QWidget *centralWidget;
        QVBoxLayout *vertLayout_Main;
    
        BlockTableFields *BTF_test;
        QPushButton *BT_test;
    
    };
    
    #endif
    

    The corresponding .cpp file:

    
    #include <QtWidgets>
    
    #include "mainwindow.h"
    
    MainWindow::MainWindow()
    {
    
        QString titleTest;
        QList<QString> *listHeaders;
    
        // Initializations
        titleTest = QString("Tests");
        listHeaders = new QList<QString>;
        listHeaders->push_back("Field 1");
        listHeaders->push_back("Field 2");
    
        vertLayout_Main = new QVBoxLayout();
        BlockTableFields *BTF_test = new BlockTableFields(this, &titleTest, listHeaders);
        vertLayout_Main->addWidget(BTF_test);
    
        BT_test = new QPushButton("Test");
        QObject::connect(BT_test, SIGNAL(clicked()), this, SLOT(Test()));
        vertLayout_Main->addWidget(BT_test);
    
        centralWidget = new QWidget;
        setCentralWidget(centralWidget);
        centralWidget->setLayout(vertLayout_Main);
    
        setWindowTitle(tr("Test"));
        resize(400, 200);
    }
    
    void MainWindow::Test()
    {
        BTF_test->InsertLine();
    }
    
    

    The header file of the class which contains the objects "QTreeView" and "QStandardItemModel" is:

    #ifndef BLOCKTABLEFIELDS_H
    #define BLOCKTABLEFIELDS_H
    
    #include <QWidget>
    #include <QLabel>
    #include <QBoxLayout>
    #include <QPushButton>
    #include <QStandardItemModel>
    #include <QTreeView>
    
    class BlockTableFields : public QWidget
    {
        Q_OBJECT
    public:
        explicit BlockTableFields(QWidget *parent = nullptr, QString *blockTitle = nullptr, QList<QString> *listHeaders = nullptr);
    
    signals:
    
    
    public slots:
        void InitTable();
        void InsertLine();
    
    private:
        QLabel *LB_title;
        QStandardItemModel SIM_table;
        QTreeView *TV_table;
    
        QPushButton *BT_AddLineBefore;
    
        // Layouts
        QHBoxLayout *horizLayout_All;
        QVBoxLayout *vertLayout_Text;
        QVBoxLayout *vertLayout_Buttons;
    };
    
    #endif // BLOCKTABLEFIELDS_H
    
    

    The corresponding .cpp file:

    #include "blocktablefields.h"
    
    BlockTableFields::BlockTableFields(QWidget *parent, QString *blockTitle, QList<QString> *listHeaders) : QWidget(parent)
    {
        int numHeader;
    
        // Title
        LB_title = new QLabel();
        if (blockTitle != nullptr)
        {
            LB_title->setText(*blockTitle);
        }
    
        // Headers
        // if no header is given, a table with only 1 column is built, with an empty header
        // else, the number of columns is fixed by the number of headers
        if ((listHeaders != nullptr) && (listHeaders->size() > 0))
        {
            SIM_table.setColumnCount(int(listHeaders->size()));
            for (numHeader = 0; numHeader < int(listHeaders->size()); numHeader++)
            {
                SIM_table.setHeaderData(numHeader, Qt::Horizontal, listHeaders->at(numHeader));
            }
        }
        else
        {
            SIM_table.setColumnCount(1);
            SIM_table.setHeaderData(0, Qt::Horizontal, QObject::tr(""));
        }
    
        // Creation of the first line
        InitTable();
    
        // Creation of the link between SIM_table and TV_table
        TV_table = new QTreeView;
        TV_table->setRootIsDecorated(false);
        TV_table->setAlternatingRowColors(true);
        TV_table->setModel(&SIM_table);
    
        // Buttons
        vertLayout_Buttons = new QVBoxLayout();
        // Add new line before the current line
        BT_AddLineBefore = new QPushButton("Insert Line");
        QObject::connect(BT_AddLineBefore, SIGNAL(clicked()), this, SLOT(InsertLine()));
        vertLayout_Buttons->addWidget(BT_AddLineBefore);
    
        // Spaces at the beginning and the end
        vertLayout_Buttons->insertStretch(0);
        vertLayout_Buttons->addStretch();
    
        // Vertical Layout (Title and field for text)
        vertLayout_Text = new QVBoxLayout();
        vertLayout_Text->addWidget(LB_title);
        vertLayout_Text->addWidget(TV_table);
    
        // Main Layout
        horizLayout_All = new QHBoxLayout();
        this->setLayout(horizLayout_All);
        horizLayout_All->addLayout(vertLayout_Buttons);
        horizLayout_All->addLayout(vertLayout_Text);
    
    }
    
    void BlockTableFields::InitTable()
    {
        int numColumn;
        QStandardItem *defaultItem = new QStandardItem(QString(""));
        QList<QStandardItem *> defaultLine;
        for (numColumn = 0; numColumn < SIM_table.columnCount(); numColumn++){ defaultLine.push_back(defaultItem); }
        SIM_table.insertRow(0, defaultLine);
    }
    
    void BlockTableFields::InsertLine()
    {
        QModelIndex tableIndex;
        int numLine = 0, numColumn, nbColumns;
        QStandardItem *defaultItem = new QStandardItem(QString(""));
        QList<QStandardItem *> defaultLine;
        nbColumns = SIM_table.columnCount();
        for (numColumn = 0; numColumn < nbColumns; numColumn++){ defaultLine.push_back(defaultItem); }
    
        tableIndex = TV_table->currentIndex();
        if (tableIndex.isValid())
        {
            numLine = tableIndex.row();
            SIM_table.insertRow(numLine, defaultLine);
            tableIndex = SIM_table.index(numLine, tableIndex.column());
            TV_table->setCurrentIndex(tableIndex);
        }
        else
        {
            numLine = 0;
            SIM_table.insertRow(numLine, defaultLine);
            tableIndex = SIM_table.index(numLine, 0);
            TV_table->setCurrentIndex(tableIndex);
        }
    }
    
    

    The complete project (very light) can be downloaded here:
    Complete_project

    If someone can tell me why it does not work, it would be very usefull for me!
    Thank you in advance for your help!
    Laurent


  • Qt Champions 2019

    Your member MainWindow ::BTF_test is not initialized.
    Apart from this you're leaking listHeaders (don't know why you need a pointer here) and your InitTable does not set anything correct since you're setting the same item on more than one cell which is not allowed.



  • @christian-ehrlicher
    Thank you very much for your answer !
    Indeed, there was a double declaration of "BTF_test" which was the cause of my problem.
    I will check the other points you mentionned to avoid new bugs.


Log in to reply