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

Loop not working with model



  • Hello again!

    In an app I have a tableWidget what is filled with items. It looks like thistable view.JPG
    To be able to translate all the items and other reasons ,i want to replace this by a QAbstractTableModel.
    I have searched all the examples and took one which fitted best for my purpose but all I try the output is always only one column.![alt text](model_view.JPG image url)
    I can do 9 columns but they are filled all the same. What can I do?```
    mymodel.h

    #ifndef MYMODEL_H
    #define MYMODEL_H
    
    
    #include <QAbstractTableModel>
    
    
    const int COLS= 6;
    const int ROWS= 9;
    class MyModel : public QAbstractTableModel
    {
     Q_OBJECT
    public:
    MyModel(QObject *parent = 0 );
     void populateData(const QList<QString> &contactNames);
     int rowCount(const QModelIndex &parent = QModelIndex())const;
     int columnCount(const QModelIndex &parent = QModelIndex())const  ;
        QVariant data( const QModelIndex &index, int role = Qt::DisplayRole)const ;
    
    private:
     QList<QString> tm_contact_name;
    
      QList<QString> contactNames;
     QString m_gridData[ROWS][COLS];  //holds text entered into QTableView
    
    signals:
        void editCompleted( QString &);
    };
    #endif // MyModel_H
    
    

    mymodel.cpp

    // mymodel.cpp
    #include <QMainwindow>
    
    #include "mymodel.h"
    #include <QAbstractTableModel>
    #include <QStringList>
    #include <QString>
    #include <QList>
    
    MyModel::MyModel(QObject *parent) : QAbstractTableModel (parent)
    {
    
    }
    
    
    // Create a method to populate the model with data:
    void MyModel::populateData(const QList<QString> &contactNames)
    {
        tm_contact_name.clear();
        tm_contact_name = contactNames;
    
        return;
    }
    
    int MyModel::rowCount(const QModelIndex &parent)const
     {
    
        Q_UNUSED(parent);
       return tm_contact_name.length();
        //return 6;
    }
    
    int MyModel::columnCount(const QModelIndex &parent)const
     {
    
        Q_UNUSED(parent);
        return 1;
    
        //return 3;
    }
    
    QVariant MyModel::data(const QModelIndex &index, int role)const
    {
        int row = index.row();
        int col = index.column();
    
        // generate a log message when this method gets called
    
    
        switch(role){
        case Qt::DisplayRole:
    { if (!index.isValid() || role != Qt::DisplayRole) {
                return QVariant();
            }
     for (col=1;col<9; col++)
    
         // if (col=1 && col<9)
                {
              // if (row=0 && row<6  )
        for (row=0; row<6 ; row++)
                {
                   return tm_contact_name[row];//[index.row()];
    
                }
    
    }
    
    }
            break;
    
    
        case Qt::CheckStateRole:
    
            if (row == 0 && col == 0) //add a checkbox to cell(0,0)
                {
                return Qt::Checked;
                  }
            else
                  {
             return Qt::Unchecked;
                 }
        }
        return QVariant();
    }
    
    

    Part of mainwindow.cpp


  • Lifetime Qt Champion

    So where do you set your model data / from where do you call populateData()? I would guess the vector is filled wrong. Add a debug output there or make a breakpoint and take a look at the content of the variable.



  • @Leopold below virtual function of the model class when you are overriding provides the data for the index with different roles

    QVariant MyModel::data(const QModelIndex &index, int role)const
    

    In current implementation you are using for loop in data member function which is not correct..

    (in spite of for loop which is having return statement )



  • Thank you both,
    i will have a look to it this evening.


  • Qt Champions 2017

    @Leopold said in Loop not working with model:

    for (row=0; row<6 ; row++)
    

    What is this for?

    tm_contact_name.length()

    That doesn't even make any sense. What is .length() on a QList<>?



  • @kshegunov
    the amount of entries in the list, in my case its 54.
    I want 9 columns with 6 rows like the example.
    When I uncommand the for loops and if loops I get the column with all the entries from QlistQString.
    When I set columnCount to 9 I get 9 columns all with the same entries.

    ![alt text](column1.JPG image url)```
    case Qt::DisplayRole:
    { if (!index.isValid() || role != Qt::DisplayRole) {
    return QVariant();
    }

    //for (row=0; row<6 ; row++)
    // if (col=1 && col<9)
    // {
    // if (row=0 && row<6 )
    // for (col=1;col<9; col++)

         //   {
               return tm_contact_name[row];//[index.row()];
                //row++:
         //   }
      // col++;
    

    //}

    }
    break;


  • Qt Champions 2017

    @Leopold said in Loop not working with model:

    When I uncommand the for loops and if loops I get the column with all the entries from QlistQString.
    When I set columnCount to 9 I get 9 columns all with the same entries.

    Of course you do, because you don't handle both the row and the column that was passed to you. You take the row'th element from the list (why the row I don't even know). How are you supposed to have 9 columns from a list to begin with?



  • Excuse me, I do not understand what you want to say.
    If I have a construct like this for loops I can usually fill a table with. Item 1 to 6 in column 1, if item> 6 take column 2, now Item 7to 12, now increase columns and so on.



  • @Leopold
    From your commented lines you say you uncomment:

    // if (col=1 && col<9)
    

    The above will always be true, and assigns col to 1.

    // if (row=0 && row<6 )
    

    The above will always be true, and assigns row to 0.

    If you actually want help with this: remove all your commented-out lines, they are just confusing. Show the exact lines which you are actually using, and what incorrect behaviour is observed.



  • @JonB
    this is my actual code:

    // mymodel.cpp
    #include <QMainwindow>
    
    #include "mymodel.h"
    #include <QAbstractTableModel>
    #include <QStringList>
    #include <QString>
    #include <QList>
    
    MyModel::MyModel(QObject *parent) : QAbstractTableModel (parent)
    {
    
    }
    
    
    // Create a method to populate the model with data:
    void MyModel::populateData(const QList<QString> &contactNames)
    {
              tm_contact_name.clear();
              tm_contact_name = contactNames;
    
        return;
    }
    
    int MyModel::rowCount(const QModelIndex &parent)const
     {
    
        Q_UNUSED(parent);
       return tm_contact_name.length();
        //return 6;
    }
    
    int MyModel::columnCount(const QModelIndex &parent)const
     {
    
        Q_UNUSED(parent);
        return 1;
    
        //return 3;
    }
    
    QVariant MyModel::data(const QModelIndex &index, int role)const
    
    {
        int row = index.row();
        int col = index.column();
    
       switch(role)
    
       {
        case Qt::DisplayRole:
        { if (!index.isValid() || role != Qt::DisplayRole)
           {
                return QVariant();
           }
    
           for (int row =0; row <6; row++)
               {
               for (int col= 1; col < 9; col++)
    
            return tm_contact_name[index.row()];
    
                }
    
    	}
            break;
    
    
    	{ 
    	case Qt::CheckStateRole:
    
            if (row == 0 && col == 0) //add a checkbox to cell(0,0)
                {
                return Qt::Checked;
                }
            else
                 {
             return Qt::Unchecked;
                 }
        }
        return QVariant();
       }
    
    }
    

    This is what I get:![alt text](column1.JPG image url)



  • Sorry, I couldn`t continue writing. You see I have drawn the slider downwards.
    The complete QListQString is in one column, I want it divided into 9 columns and 6 rows like the example in my first thread.



  • @Leopold
    I think you are saying:

    • You have a QStringList
    • You want to treat it as representing rows and columns, with each row containing 9 columns
    • You want to know what element is at (index.row(), index.column())

    [That's what you say. But your code also has columnCount() return 1;. Why do you put that in code if you say you want 9 columns?]

    So simple math is

    int offset = index.row() * 9 + index.column();
    return tm_contact_name[offset];    // or tm_contact_name.at(offset) if it is a `QStringList`
    

    ?
    No loops. Just basic arithmetic.


  • Lifetime Qt Champion

    Hi
    Also

    int MyModel::columnCount(const QModelIndex &parent)const
     {
    
        Q_UNUSED(parent);
        return 1;
    
        //return 3;
    }
    

    tells it to use one col so that should be fixed.

    and this too

    int MyModel::rowCount(const QModelIndex &parent)const
     {
    
        Q_UNUSED(parent);
       return tm_contact_name.length();
        //return 6;
    }
    

    should also return the wanted number of rows. tm_contact_name.length(); will return ALL strings you have
    but that is not the number of rows.

    Then the view will ask you
    give me data for
    0,0
    0,1
    0,2
    etc.
    for all cols, for all rows.
    So data function must return one "data" for each combination of row and col. ( as nagesh explained)
    So we cant use a for loop as we give the data one by one so to speak.
    Since you have all the names in one big list, you must calculate an offset as JonB shows
    to return the right col data since your internal list is not ordered as you want it to be displayed.


Log in to reply