Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QStandardItemModel in QTableView
QtWS25 Last Chance

QStandardItemModel in QTableView

Scheduled Pinned Locked Moved General and Desktop
7 Posts 3 Posters 4.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    maximus
    wrote on last edited by
    #1

    Hi,

    I'm wondering if it's possible to retrieve the item selected in a QTableView (not just the row, the real object)
    I'll explain a little bit.

    I'm building a QTableView using the model/view architecture. I add a few object in the model and this is shown in the view.
    Here is an example of the view populated with 2 objects:
    https://www.dropbox.com/s/94sdayh0q5y4vfz/workoutList.png

    When an item is double clicked in this view, I want to fire an action with the item that has been selected. My question is, when i'm populating the listView, I only add QString in it, never add the reference or the "real" object. How can I retrieve the object after that? Is there a way to add the real object in the Model, not just QString of the attributes?
    Here is the corresponding code.
    Sorry if it's a newbie question, I'm a Java guy... In java we could do this with annotation in the object class and no need to specify number of row, column as it is detected it with the object proprieties and list size..

    Thanks !

    @//------
    void MainWindow::on_tableView_workout_doubleClicked(const QModelIndex &index) {

    // get Workout selected (object)
    // open Workout window with this object
    
    qDebug() << "Clicked!" << QString::number(index.row());
    qDebug() << index.model();
    

    }

    // ----- Building the QTableView/Model
    QList<Workout*> lstWork = new QList<Workout>();

    double timeInterval[5] = {1,1,1,1,1};
    int powerInterval[5] = {150,200,175,300,250};
    Workout *workout = new Workout(5, timeInterval, powerInterval, "KillerWorkout", "PowerVelo", Workout::Endurance);
    lstWork->append(workout);
    
    double timeInterval2[6] = {1,1,1,1,1,2};
    int powerInterval2[6] = {150,200,175,300,250,240};
    Workout *workout2 = new Workout(6, timeInterval2, powerInterval2, "testMax", "PowerVelo", Workout::Tempo);
    lstWork->append(workout2);
    
    
    QStringList headerList;
    headerList << "Name" << "Created by" << "Type" << "Length (minutes)" << "Max power";
    modelListWorkout = new QStandardItemModel(lstWork->count(), headerList.count(), this);
    
    for (int row = 0; row < lstWork->count(); row++) {
    
        modelListWorkout->setItem(row, 0, new QStandardItem(lstWork->at(row)->getName()));
        modelListWorkout->setItem(row, 1, new QStandardItem(lstWork->at(row)->getCreatedBy()));
        modelListWorkout->setItem(row, 2, new QStandardItem(lstWork->at(row)->getTypeToString()));
        modelListWorkout->setItem(row, 3, new QStandardItem(QString::number(lstWork->at(row)->getTotalLength())));
        modelListWorkout->setItem(row, 4, new QStandardItem(QString::number(lstWork->at(row)->getMaxPower())));
    
        for (int column = 0; column &lt; headerList.count(); column++) {
            modelListWorkout-&gt;setHorizontalHeaderLabels(headerList);
        }
    }
    
    
    ui->tableView_workout->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableView_workout->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableView_workout->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableView_workout->setModel(modelListWorkout);@
    

    Free Indoor Cycling Software - https://maximumtrainer.com

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      You could use "QStandardItem::setData":http://qt-project.org/doc/qt-4.8/qstandarditem.html#setData to keep your data close to your items

      Hope it helps

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • M Offline
        M Offline
        maximus
        wrote on last edited by
        #3

        Thanks for your answer,

        setData use a QVariant not a QObject?
        Guess I have to use something else. Because my Data is a custom class (Workout)

        Maybe I could add a item key in the row (not show it), and this key would be a pointer to my object, kind of like a QHashMap.
        I'll try that and keep you updated, thanks for your help!
        @
        QStandardItem *item = new QStandardItem();
        item->setData(lstWork->at(row)); //not legal@


        Free Indoor Cycling Software - https://maximumtrainer.com

        1 Reply Last reply
        0
        • JeroentjehomeJ Offline
          JeroentjehomeJ Offline
          Jeroentjehome
          wrote on last edited by
          #4

          Hi,
          Maybe it's just asking for you to subclass the QAbstractTableModel and control the data yourself instead of relying on the QStandardItemModel to do this. That way you are able to do all you want to achieve within your model. It's a natural next step in exploring the model/view capabilities.

          Greetz, Jeroen

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            QVariant is designed to store custom type (as long as you provide the needed code)

            Have a look at QVariant::fromValue().

            As Jeroen@home wrote, implementing your own model is also a good alternative to have control over your data.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • M Offline
              M Offline
              maximus
              wrote on last edited by
              #6

              Thanks for your help guys,

              I already started implementing my own model. it's not 100% complete but seems to work fine.
              One last question about this, I would like my model to be generic, so I can re-use it with different object
              Because now my model is specific to <Workout> :
              @QList<Workout> lstWorkout; // not generic@

              I would like it to be generic so I don't need to do 4-5 implementations of QAbstractTableModel. Example: I'll use a table of <User>, a table of <Profile>, etc..
              The way I have coded MyTableModel.cpp, I can't seem to find a way to do it generic, as a lot of the function are hard-coded ; headerData,() data()..
              If anyone ever experienced this problem feel free to share, thanks ;)

              MyTableModel.H
              @#ifndef MYTABLEMODEL_H
              #define MYTABLEMODEL_H

              #include <QAbstractTableModel>
              #include "workout.h"

              class MyTableModel : public QAbstractTableModel {
              Q_OBJECT

              public:
              MyTableModel(QObject *parent = 0);

              void setListWorkout(QList<Workout>);
              
              int rowCount(const QModelIndex &parent = QModelIndex()) const;
              int columnCount(const QModelIndex &parent = QModelIndex()) const;
              QVariant data(const QModelIndex &index, int role) const;
              QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
              
              Workout getWorkoutAtRow(const QModelIndex &index);
              

              private:
              QList<Workout> lstWorkout;

              };

              #endif // MYTABLEMODEL_H@

              MyTableModel.cpp

              @#include "mytablemodel.h"
              #include "workout.h"
              #include <QDebug>

              MyTableModel::MyTableModel(QObject *parent) : QAbstractTableModel(parent) {
              }

              // -----------------------------------------------------------------
              QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const {

              if (role != Qt::DisplayRole)
                  return QVariant();
              
              if (orientation == Qt::Vertical) {
                  return QString::number(section);
              }
              else {
                  switch (section) {
                  case 0 :
                      return "Name";
                      break;
                  case 1:
                      return "Created by";
                      break;
                  case 2:
                      return "Type";
                      break;
                  case 3:
                      return "Length (minutes)";
                      break;
                  case 4:
                      return "Max power";
                      break;
                  default :
                      return "horizontal";
              
                  }
              }
              

              }
              // -----------------------------------------------------------------
              void MyTableModel::setListWorkout(QList<Workout> lstWorkout) {

              beginResetModel();
              this->lstWorkout = lstWorkout;
              endResetModel();
              

              }

              // -----------------------------------------------------------------
              Workout MyTableModel::getWorkoutAtRow(const QModelIndex &index) {

              //    if (index.row() > lstWorkout.size()) {
              //        return NULL;
              //    }
              return lstWorkout.at(index.row());
              

              }

              // -----------------------------------------------------------------
              int MyTableModel::rowCount(const QModelIndex &parent) const {

              if (lstWorkout.isEmpty()) {
                  return 0;
              }
              else {
                  return lstWorkout.size();
              }
              

              }

              // -----------------------------------------------------------------
              int MyTableModel::columnCount(const QModelIndex &parent) const {

              if (lstWorkout.isEmpty()) {
                  return 0;
              }
              else {
                  return 5;  //TODO: count object private attributes
              }
              

              }

              // -----------------------------------------------------------------
              QVariant MyTableModel::data(const QModelIndex &index, int role) const {

              if (!index.isValid())
                  return QVariant();
              
              if (index.row() >= lstWorkout.size())
                  return QVariant();
              
              if (role == Qt::DisplayRole) {
              
                  Workout work = lstWorkout.at(index.row());
              
                  switch (index.column()) {
                  case 0 :
                      return work.getName();
                      break;
                  case 1:
                      return work.getCreatedBy();
                  case 2:
                      return work.getTypeToString();
                  case 3 :
                      return work.getTotalLength();
                  case 4:
                      return work.getMaxPower();
                  default:
                      return "default";
              
                  }
              }
              else
                  return QVariant();
              

              }@


              Free Indoor Cycling Software - https://maximumtrainer.com

              1 Reply Last reply
              0
              • JeroentjehomeJ Offline
                JeroentjehomeJ Offline
                Jeroentjehome
                wrote on last edited by
                #7

                Hi,
                You codes looks the most basic way you need it to be. When getting deeper in it, you will increase functionality and control even further.
                Maybe just a small tip, but do not place so many return statements in a single function. The code is correct, but for reading it it's a bit confusing. Where will the code break, will allocated data be deleted properly etc.

                To answer your question, it's complicated to implement a 'standard' model to control custom data. Maybe there is a way to implement it with template classes, but I think the specifics of every custom model will not be able to be implemented.
                Also, why would you want a single model to control different user models? Not every model has the same headers/data etc. When you want this, it's better to stick to the QStandardItemModel. That's setup independant of custom models, but then again, your option for QObject * control etc will not work, but QVariant is able to do hold the QObject * or a pointer to any other class.

                Greetz, Jeroen

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved