Вот как я решил исходную задачу автора темы. Здесь код на Java, на C++ переписать не состовит труда. Сделано с помощью специальной прокси-модели, добавляющей в конец одну строчку и при установке данных в нее добавляющей новую строчку в конец исходной модели, а затем делегирующей ей установку данных.
import com.trolltech.qt.core.QModelIndex;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QAbstractTableModel;
public class AutoAddProxyTableModel extends QAbstractTableModel {
private QAbstractTableModel sourceModel;
public AutoAddProxyTableModel() {
}
public AutoAddProxyTableModel(QAbstractTableModel sourceModel) {
setSourceModel(sourceModel);
}
@Override
public int rowCount(QModelIndex parent) {
if (sourceModel == null)
return 0;
return sourceModel.rowCount(parent)+1;
}
@Override
public int columnCount(QModelIndex parent) {
if (sourceModel == null)
return 0;
return sourceModel.columnCount(parent);
}
@Override
public Object data(QModelIndex index, int role) {
if (sourceModel == null)
return null;
if (index == null)
return sourceModel.data(index, role);
if (isExtraRow(index)) {
if (role == Qt.ItemDataRole.DisplayRole) {
return tr("<enter value to add>");
}
return null;
}
return sourceModel.data(index, role);
}
@Override
public Object headerData(int section, Qt.Orientation orientation, int role) {
if (sourceModel == null)
return super.headerData(section, orientation, role);
return sourceModel.headerData(section, orientation, role);
}
/**
* Если устанавливаются данные в последную ячейку, то в исходную таблицу
* вставляется новая строка и эти данные заносятся в нее.
* @param index
* @param value
* @param role
* @return
*/
@Override
public boolean setData(QModelIndex index, Object value, int role) {
if (sourceModel == null)
return super.setData(index, value, role);
if (index == null)
return sourceModel.setData(index, value, role);
if (isExtraRow(index)) {
// Ключевой момент - при установке данных в дополнительную ячейку
// создаем в исходной модели строку.
beginInsertRows(null, index.row(), index.row());
sourceModel.insertRow(index.row());
endInsertRows();
}
return sourceModel.setData(index, value, role);
}
@Override
public Qt.ItemFlags flags(QModelIndex index) {
if (sourceModel == null)
return Qt.ItemFlag.createQFlags();
return sourceModel.flags(index);
}
public final void setSourceModel(QAbstractTableModel sourceModel) {
this.sourceModel = sourceModel;
}
public final QAbstractTableModel sourceModel() {
return this.sourceModel;
}
@Override
public boolean removeRows(int row, int count, QModelIndex parent) {
if (sourceModel == null)
return false;
// Убеждаемся, что наша строка не будет удалена.
count = Math.min(row+count, sourceModel.rowCount()) - row;
// Предыдущей операцией количество могло стать отрицательным
if (count <= 0)
return false;
beginRemoveRows(parent, row, row+count-1);
boolean result = sourceModel.removeRows(row, count, parent);
endRemoveRows();
return result;
}
@Override
public boolean removeColumns(int row, int count, QModelIndex parent) {
if (sourceModel == null)
return false;
return sourceModel.removeColumns(row, count, parent);
}
private boolean isExtraRow(QModelIndex index) {
return index.row() == rowCount()-1;
}
}