I find solution!
First i add new method to model
void QComboBoxModel::append(int index, QString value)
{
int newRow = this->values.count();
this->beginInsertRows(QModelIndex(), newRow, newRow);
values.append(QPair<int,QString>(index,value));
endInsertRows();
}
Now on button click method changed to this
void MainWindow::on_pushButton_clicked()
{
qDebug() << "Clicked!";
newidx++;
QString strIdx = QString().number(newidx);
model->append(newidx,"new item " + strIdx );
}
Point is to use beginInsertRows
and endInsertRows
to notify model that data actually changed!
Now all worked as expected!
Now you also can modify append method to batch add rows to it, but i think if you add many rows it better just recreate model and reassign it to combobox.
Update 1:
Also keep in mind, that you update values
QList
inside model, so if you add
qDebug() << values;
in on_pushButton_clicked()
method, you always see
(QPair(-1,"Select item"), QPair(10,"item1(0)"), QPair(11,"item1(1)"), QPair(21,"item1(2)"), QPair(32,"item1(3)"), QPair(44,"item1(4)"))
Update 2:
Also i update populate
method
void QComboBoxModel::populate(const QList<QPair<int,QString>> &newValues)
{
int oldIdx = this->values.count();
int newIdx = newValues.count();
this->beginInsertRows(QModelIndex(), oldIdx, newIdx);
this->values = newValues;
endInsertRows();
}
Now you can just work with values
list
void MainWindow::on_pushButton_clicked()
{
qDebug() << "Clicked!";
newidx++;
QString strIdx = QString().number(newidx);
values.append(QPair<int,QString>(newidx,"new item " + strIdx));
model->populate(values);
qDebug() << values;
}
Update 3:
Now, i find one big problem - i did not use pointer inside model, so when i pass QList to model it just create copy instead use already created, so i rewrite model and other code:
Model
#ifndef QCOMBOBOXMODEL_H
#define QCOMBOBOXMODEL_H
#include <QModelIndex>
class QComboBoxModel : public QAbstractListModel
{
public:
QComboBoxModel(QObject *parent=nullptr);
int rowCount(const QModelIndex &) const;
QVariant data(const QModelIndex &index, int role) const;
void populate(QList<QPair<int,QString>> *newValues);
void append(int index, QString value);
private:
QList<QPair<int,QString>> *values;
};
#endif // QCOMBOBOXMODEL_H
#include "qcomboboxmodel.h"
#include <QModelIndex>
#include <QDebug>
QComboBoxModel::QComboBoxModel(QObject *parent)
:QAbstractListModel(parent)
{
values = new QList<QPair<int,QString>>();
}
int QComboBoxModel::rowCount(const QModelIndex &) const
{
return values->count();
}
QVariant QComboBoxModel::data( const QModelIndex &index, int role ) const
{
QVariant value;
switch ( role )
{
case Qt::DisplayRole: //string
{
value = this->values->value(index.row()).second;
}
break;
case Qt::UserRole: //data
{
value = this->values->value(index.row()).first;
}
break;
default:
break;
}
return value;
}
void QComboBoxModel::populate(QList<QPair<int,QString>> *newValues)
{
int oldIdx = this->values->count();
int newIdx = newValues->count();
this->beginInsertRows(QModelIndex(), oldIdx, newIdx);
this->values = newValues;
endInsertRows();
}
void QComboBoxModel::append(int index, QString value)
{
int newRow = this->values->count();
this->beginInsertRows(QModelIndex(), newRow, newRow);
values->append(QPair<int,QString>(index,value));
endInsertRows();
}
Main form
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "qcomboboxmodel.h"
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_comboBox_currentIndexChanged(int index);
void on_comboBox_currentIndexChanged(const QString &arg1);
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
int newidx;
QList<QPair<int,QString>> *values;
QComboBoxModel *model;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "qcomboboxmodel.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
values = new QList<QPair<int,QString>>();
values->append(QPair<int,QString>(-1,"Select item"));
values->append(QPair<int,QString>(10,"item1(0)"));
values->append(QPair<int,QString>(11,"item1(1)"));
values->append(QPair<int,QString>(21,"item1(2)"));
values->append(QPair<int,QString>(32,"item1(3)"));
values->append(QPair<int,QString>(44,"item1(4)"));
newidx = 50;
model = new QComboBoxModel();
model->populate(values);
this->ui->comboBox->setModel(model);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
qDebug() << ui->comboBox->itemData(index).value<int>();
}
void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
qDebug() << arg1;
}
void MainWindow::on_pushButton_clicked()
{
qDebug() << "Clicked!";
newidx++;
QString strIdx = QString().number(newidx);
values->append(QPair<int,QString>(newidx,"new item " + strIdx));
model->populate(values);
qDebug() << values->toStdList();
}
Now all looks just fine and works as intended!