Search code examples
c++qtqt5qstandarditemmodel

Append Class to QStandardItemModel


How can I append my items of class BundleItem to the QListView's QStandardItem model? When they are appended, I only want to use the BundleItem's Name property to be displayed in the listview. I would like a pointer to the actual item to live in the UserRole of the model so when a user double clicks and item in the list, for now it would just print to the debugger console or something similar.

#include "mainwindow.h"
#include <QVBoxLayout>
#include <QListView>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QAbstractItemModel>

struct BundleItem {
  QString name;
  QString nickname;
  QString team;

  // Constructor
  BundleItem(QString name,
             QString nickname,
             QString team):
      name(name), nickname(nickname), team(team)
  {}
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    auto *proxyModel = new QSortFilterProxyModel;
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);

    auto *widget = new QWidget(this);
    auto *lay = new QVBoxLayout(widget);
    auto *listview = new QListView();

    auto *model = new QStandardItemModel();
    proxyModel->setSourceModel(model);
    listview->setModel(proxyModel);

    // add Item to list
    BundleItem("Kevin", "Kev", "Coyotes");
    BundleItem("Michael", "Mike", "Walkers");

    lay->addWidget(listview);
    setCentralWidget(widget);
}

MainWindow::~MainWindow()
{

}

Solution

  • The easy version to do it is inheritance from QStandardItem class.

    struct BundleItem : public QStandardItem {
      QString name;
      QString nickname;
      QString team;
    
      BundleItem(QString name,
                 QString nickname,
                 QString team):
          QStandardItem(name), // call constructor of base class - name will be displayed in listview
          name(name), nickname(nickname), team(team)
      {}
    };
    

    Remember to call QStandardItem constructor in ctor of BundleItem and passing name as its parameter.

    Lines to add your items to ListView are:

    model->appendRow (new BundleItem("Kevin", "Kev", "Coyotes"));
    model->appendRow (new BundleItem("Michael", "Mike", "Walkers"));
    

    and it is all, you have listview filled by two items : Kevin and Michael.

    If you want to handle double-click action, you can use in your slot

    handleDoubleClick (const QModelIndex&); // declaration of your slot
    

    method QStandardItemModel::indexFromItem(const QModelIndex&) which takes QModelIndex (pass index from slot) as parameter and returns pointer to QStandardItem. You need only to cast this pointer to BundleItem then you have access to other members of your class.