c++ – qt 2 models with delegate combobox

I have two models, Users (First Name, Last Name, Country) and Countries (Name). I made a delegate for the combobox in the Country field of the Users table. How can I fill it with data from the Country table?

Country.cpp

#include "Country.h"

Country::Country()
{

}

void Country::setName(const QString name)
{
    m_name = name;
}

QString Country::getName() const
{
    return m_name;
}

CountryTable.cpp

#include "CountryTable.h"

CountryTable::CountryTable(QObject  *parent) : QAbstractTableModel (parent)
{
    listOfCountries = new QList <Country> ();
}

int CountryTable::columnCount(const QModelIndex  & parent) const {
    return 1;
}

int CountryTable::rowCount(const QModelIndex & parent) const {
    return listOfCountries->size();
}

QVariant  CountryTable::data(const QModelIndex & index, int role) const {
   if (index.isValid() && role == Qt ::DisplayRole)
       return getData(index.row(), index.column());
   return QVariant ();
}

QVariant  CountryTable::getData(int num, int position) const {

    switch (position) {
        case 0:
            return QVariant (listOfCountries->at(num).getName());
        default:
            return QVariant ();
    }
}

bool CountryTable::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid()) {
        return false;
    }

    Country &country = this->getCountry(index);


    switch (index.column()) {
        case 0:
            country.setName(value.toString());
            break;
        default:
            return false;
    }

    emit dataChanged(index, index);

    return true;
}


QVariant  CountryTable::headerData(int section, Qt ::Orientation orientation, int role) const {
    if (role != Qt ::DisplayRole)
        return QVariant ();
    if (orientation == Qt ::Vertical)
        return QVariant (section + 1);
    else
        switch (section) {
            case 0:
                return QVariant ("Name");
            default:
                return QVariant ();
        }
}

Qt ::ItemFlags CountryTable::flags(const QModelIndex  & index) const {
    return Qt ::ItemIsSelectable | Qt ::ItemIsEnabled | Qt ::ItemIsEditable;
}

Country& CountryTable::getCountry(const QModelIndex  & index) const {
    return (*listOfCountries)[index.row()];
}

void CountryTable::addCountry(Country& newCountry) {
    beginInsertRows(QModelIndex (), listOfCountries->size(), listOfCountries->size());
    listOfCountries->append(newCountry);
    endInsertRows();
}

void CountryTable::delCountry(const QModelIndex &index) {
    beginRemoveRows(QModelIndex (), index.row(), index.row());
    listOfCountries->removeAt(index.row());
    endRemoveRows();
}

User.cpp

#include "User.h"
QVector<User*> User::usersList;

User::User()
{
    usersList.push_back(this);
}

User::~User()
{
}

void User::setName(const QString name)
{
    m_name = name;
}

void User::setSurname(const QString surname)
{
    m_surname = surname;
}

void User::setCountry(const QString country)
{
    m_country = country;
}

QString User::getName() const
{
    return m_name;
}

QString User::getSurname() const
{
    return m_surname;
}

QString User::getCountry() const
{
    return m_country;
}

QVector<User*> User::getAllUsers()
{
    return usersList;
}

UsersTable.cpp

#include "UsersTable.h"
#include <QDebug>

UsersTable::UsersTable(QObject  *parent) : QAbstractTableModel (parent)
{
    listOfUsers = new QList <User> ();
}

int UsersTable::columnCount(const QModelIndex  & parent) const {
    return 3;
}

int UsersTable::rowCount(const QModelIndex & parent) const {
    return listOfUsers->size();
}

QVariant  UsersTable::data(const QModelIndex & index, int role) const {
   if (index.isValid() && role == Qt ::DisplayRole)
       return getData(index.row(), index.column());
   return QVariant ();
}

QVariant  UsersTable::getData(int num, int position) const {

    switch (position) {
        case 0:
            return QVariant (listOfUsers->at(num).getName());
        case 1:
            return QVariant (listOfUsers->at(num).getSurname());
        case 2:
            return QVariant (listOfUsers->at(num).getCountry());
        default:
            return QVariant ();
    }
}

bool UsersTable::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid()) {
        return false;
    }

    User &user = this->getUser(index);


    switch (index.column()) {
        case 0:
            user.setName(value.toString());
            break;
        case 1:
            user.setSurname(value.toString());
            break;
        case 2:
            user.setCountry(value.toString());
            break;
        default:
            return false;
    }

    emit dataChanged(index, index);

    return true;
}


QVariant  UsersTable::headerData(int section, Qt ::Orientation orientation, int role) const {
    if (role != Qt ::DisplayRole)
        return QVariant ();
    if (orientation == Qt ::Vertical)
        return QVariant (section + 1);
    else
        switch (section) {
            case 0:
                return QVariant ("Name");
            case 1:
                return QVariant ("Surname");
            case 2:
                return QVariant ("Country");
            default:
                return QVariant ();
        }
}

Qt ::ItemFlags UsersTable::flags(const QModelIndex  & index) const {
    return Qt ::ItemIsSelectable | Qt ::ItemIsEnabled | Qt ::ItemIsEditable;
}

User& UsersTable::getUser(const QModelIndex  & index) const {
    return (*listOfUsers)[index.row()];
}

void UsersTable::addUser(User& newUser) {
    beginInsertRows(QModelIndex (), listOfUsers->size(), listOfUsers->size());
    listOfUsers->append(newUser);
    endInsertRows();
}

void UsersTable::delUser(const QModelIndex  & index) {
    beginRemoveRows(QModelIndex (), index.row(), index.row());
    listOfUsers->removeAt(index.row());
    endRemoveRows();
}

DelegateComboBox.cpp

#include "DelegateComboBox.h"
#include <QLineEdit>
#include <QComboBox>
#include <QDebug>

DelegateComboBox::DelegateComboBox(const QStringList &country, QObject *parent)
    :QStyledItemDelegate(parent), countryList(country)
{  }

QWidget* DelegateComboBox::createEditor(QWidget *parent,
                                        const QStyleOptionViewItem &option,
                                        const QModelIndex &index) const
{
    QComboBox *comboBox = new QComboBox(parent);
    comboBox->addItems(countryList);
    comboBox->setCurrentIndex(-1);
    return comboBox;
}


void DelegateComboBox::setEditorData(QWidget *editor,
                                     const QModelIndex &index) const
{
    QString text = index.model()->data(index, Qt::EditRole).toString();
    QComboBox *comboBox = static_cast<QComboBox*>(editor);

    if(text.isEmpty()){

        QLineEdit *edit=new QLineEdit;
        QFont font=edit->font();
        font.setBold(true);
        font.setItalic(true);
        edit->setFont(font);
        edit->setPlaceholderText("Select country");
        comboBox->setLineEdit(edit);
        comboBox->lineEdit()->setReadOnly(true);
        return;
    }

    int idx=comboBox->findText(text);
    comboBox->setCurrentIndex(idx);
}


void DelegateComboBox::setModelData(QWidget *editor,
                                    QAbstractItemModel *model,
                                    const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString text = comboBox->currentText();
    model->setData(index, text, Qt::EditRole);
}


void DelegateComboBox::updateEditorGeometry(QWidget *editor,
                                            const QStyleOptionViewItem &option,
                                            const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

MainWindow.cpp

dataTable = new UsersTable(this);
view = new QTableView (this);
view->setModel(dataTable);
view->resizeColumnsToContents();
add = new QPushButton ("Add new User");
del = new QPushButton ("Delete selected User");
showQDebug = new QPushButton ("Show");
QWidget  *box = new QWidget ();
QVBoxLayout  *layout = new QVBoxLayout ();
layout->addWidget(view);
QHBoxLayout  *buttonLayout = new QHBoxLayout ();
layout->addLayout(buttonLayout);
buttonLayout->addWidget(add);
buttonLayout->addWidget(del);
buttonLayout->addWidget(showQDebug);
box->setLayout(layout);
setCentralWidget(box);
setWindowTitle("Table of Users");

QStringList country;
country<<"Burundi"<<"Burkina Faso"<<"Cambodia"<<"Cameroon";
auto delegate = new DelegateComboBox(country);
view->setItemDelegateForColumn(2, delegate);



connect(add, SIGNAL(clicked()), this, SLOT(addButtonClicked()));
connect(del, SIGNAL(clicked()), this, SLOT(delButtonClicked()));
connect(showQDebug, SIGNAL(clicked()), this, SLOT(showUsersData()));

As you can see, in the MainWindow file, now I just write the data manually to the QStringList. Tell me how to take data from the Country model?


my attempts

CountriesTable.h

static QList<Country>* getAllCountries();
private:
   static QList <Country> *allCountries;

CountriesTable.cpp

QList <Country> *CountriesTable::allCountries;
QList<Country>* CountriesTable::getAllCountries() {
   return allCountries;
}

to add and remove

void CountriesTable::addCountry(Country& newCountry) {
    beginInsertRows(QModelIndex (), listOfCountries->size(), listOfCountries->size());
    listOfCountries->append(newCountry);
    endInsertRows();
    allCountries->append(newCountry);
}
 
void CountryTable::delCountry(const QModelIndex &index) {
    beginRemoveRows(QModelIndex (), index.row(), index.row());
    listOfCountries->removeAt(index.row());
    endRemoveRows();
    allCountries->removeAt(index.row());
}

And then I tried in the constructor of the delegate of the combobox to somehow use the static method that I created, but it didn’t work out for me (((

DelegateComboBox::DelegateComboBox(QObject *parent)
    :QStyledItemDelegate(parent)
{  
......CountryTable::getAllCountries(); ......
}

Leave a Comment