Cool_Coder
Cool_Coder

Reputation: 5083

Initialising data into custom model from QAbstractTableModel in Qt?

I am a beginner in Qt's Model/View Framework. I am having trouble using a QAbstractTableModel subclass (MyModel) with a QTableView. After creating MyModel object I want to set it to have 2 rows & 2 columns. I have a initialise function which sets all the class variables & then emits the dataChanged() SIGNAL but still the View is not showing anything.

class MyModel : QAbstractTableModel
{
     public:
       MyModel();
       Initialise(double **a, int r, int c);

     private:
       int row;
       int column;
       double **array;
}

MyModel::Initialise(double **a, int r, int c)
{
     array = a;
     row = r;
     column = c;
     emit dataChanged(index(0, 0), index(r - 1, c - 1));
}

I have re-implemented all the required functions for read only access. But still I am getting a blank window. Created the above code in Notepad for illustration purpose, so please ignore syntax errors. I could not find any example in Qt SDK for creating custom model from QAbstractTableModel. So please let me know what is the correct method of initialising data into a model.

EDIT:

QVariant TableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();//currently it is returning from here, why???

    switch(role)
    {
        case Qt::DisplayRole:
        {
        if(index.column()==0)
            return QString::number(array[index.row()][index.column()]);
        break;
        }
    }
}

Upvotes: 0

Views: 2959

Answers (2)

Tab
Tab

Reputation: 815

To initialize data in Table you have to redefine data function, rowCount and clumnCount along with constructor of Model . suppose you have data int mydataarray[r][c] that is initialized in constructor.

   TableModel::TableModel(int r,int c, double **initialdata)
{
    R = r;
    C = c;
    mydataarray= initialdata;
}

QVariant TableModel::data(const QModelIndex &index, int role) const
{
    switch(role)
    {
    case Qt::DisplayRole:
        if(index.column()==0)
        {
        return QString::number(maydataarray[index.row()][index.column()]);
        }
        break;
}

To set number of rows and column redefine

int TableModel::rowCount(const QModelIndex &parent= QModelIndex()) const
{
    return R;//R is number of initial rows
}

int TableModel::columnCount(const QModelIndex &parent= QModelIndex()) const
{
    return C;//C is number of initial columns
}

in initialize function that actually you can use to modify but you have to insert rows and columns in model if they are exceeding the initial r and c

    void TableModel::Initialize(double **a, int r, int c)
    {
    QModelIndex m = createIndex(0,0);

    if(r>this->rowCount(m)||c>this->columnCount(m))
    {
        QMessageBox m1;
        m1.setText("Exciding r/c "+ QString::number(m.row())+QString::number(m.column()));
        m1.exec();
        return;//add logic to insert exceeding rows and columns here before calling dataChange() function
    }

  mydataarray =a;

    QModelIndex n = createIndex(r-1,c-1);
    this->dataChanged(createIndex(0,0),n);
}

refer this for further

Upvotes: 0

Pavel Strakhov
Pavel Strakhov

Reputation: 40512

dataChanged signal forces the view to update existing items. It doesn't tell it that the row or column count has changed. You should use layoutAboutToBeChanged and layoutChanged signals instead. You can use them without any parameters.

Make sure that you implemented rowCount and columnCount virtual functions properly.

I don't know why index.isValid() is false in your function. Check the index's model(), row() and column() properties to find out why exactly it is not valid. Generally, it's possible for a view to call data functions with arbitrary arguments. Since your view thinks that your model is empty, all indexes are most likely invalid. When you see any rows and columns in the view, you would begin to receive valid indexes.

Also if the initialization is performed only once, it's better to do it before you assign the model to the view.

And do not use double**. Use automatic memory managing (e.g. QVector) instead. It is C++, after all.

Upvotes: 4

Related Questions