В моем приложении QSqlTableModel
заполнено таблицей из соединения MySQL. Чтобы показать его содержимое, я использую QTableView
; и чтобы редактировать и отображать его, я вложил в подкласс QStyledItemDelegate
.
Мне нужно иметь возможность редактировать всю строку модели. Для этого я использую метод QModelIndex::sibling
, чтобы получить / установить все значения в этой строке независимо от того, какая пара (строка / столбец) «активировала» делегат.
С этим я могу построить подкласс QDialog
(мой редактор делегатов) и заполнить его текущими значениями выбранной строки. А затем разрешите пользователю редактировать содержимое и после принятия изменений или отмены их, в зависимости от того, нажал ли пользователь «сохранить» или «отменить».
Проблема в том, что я использую QAbstractItemModel::setData
для сохранения изменений обратно в модель. Но при определенных условиях (пока неизвестных) этот метод вызывает QAbstractItemDelegate::setEditorData
, который перезаписывает новый контент, который находится в подклассе QDialog
для старого контента, присутствующего в настоящее время в модели.
Когда это происходит, любой следующий вызов QAbstractItemModel::setData
запишет содержимое, содержащееся в модели, само по себе, а не новое значение, выбранное пользователем, поскольку предыдущий вызов QAbstractItemDelegate::setEditorData
привел к потере подкласса QDialog
вся информация, выбранная пользователем, из столбца, соответствующего QAbstractItemModel::setData
, который вызвал проблему.
Кто-нибудь знает, как предотвратить возникновение этой проблемы?
Некий код:
QWidget *MedicationDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
{
EditMedicationDialog *editor = new EditMedicationDialog(parent);
editor->setAttribute(Qt::WA_DeleteOnClose, true);
editor->setModal(true);
connect(editor, SIGNAL(accepted()), this, SLOT(editorAccepted()));
connect(editor, SIGNAL(rejected()), this, SLOT(editorRejected()));
return editor;
}
void MedicationDelegate::setEditorData(QWidget *uncastedEditor, const QModelIndex& index) const
{
int currentRow = index.row();
QModelIndex drugClassIndex = index.sibling(currentRow, MedicationModel::DrugClass);
QModelIndex drugIndex = index.sibling(currentRow, MedicationModel::Drug);
QModelIndex dosageIndex = index.sibling(currentRow, MedicationModel::Dosage);
QModelIndex amountIndex = index.sibling(currentRow, MedicationModel::Amount);
QModelIndex scheduleIndex = index.sibling(currentRow, MedicationModel::Schedule);
QModelIndex frequencyIndex = index.sibling(currentRow, MedicationModel::Frequency);
QString drugClass = index.model()->data(drugClassIndex, Qt::DisplayRole).toString();
QString drug = index.model()->data(drugIndex, Qt::DisplayRole).toString();
QString dosage = index.model()->data(dosageIndex, Qt::DisplayRole).toString();
QString amount = index.model()->data(amountIndex, Qt::DisplayRole).toString();
QString schedule = index.model()->data(scheduleIndex, Qt::DisplayRole).toString();
QString frequency = index.model()->data(frequencyIndex, Qt::DisplayRole).toString();
EditMedicationDialog *editor = qobject_cast<EditMedicationDialog*>(uncastedEditor);
// these methods sets the current row values in the editor
editor->setDrugClass(drugClass);
editor->setDrug(drug);
editor->setDosage(dosage);
editor->setAmount(amount);
editor->setSchedule(schedule);
editor->setFrequency(frequency);
}
void MedicationDelegate::setModelData(QWidget *uncastedEditor, QAbstractItemModel *model, const QModelIndex& index) const
{
int currentRow = index.row();
QModelIndex drugClassIndex = index.sibling(currentRow, MedicationModel::DrugClass);
QModelIndex drugIndex = index.sibling(currentRow, MedicationModel::Drug);
QModelIndex dosageIndex = index.sibling(currentRow, MedicationModel::Dosage);
QModelIndex amountIndex = index.sibling(currentRow, MedicationModel::Amount);
QModelIndex scheduleIndex = index.sibling(currentRow, MedicationModel::Schedule);
QModelIndex frequencyIndex = index.sibling(currentRow, MedicationModel::Frequency);
EditMedicationDialog *editor = qobject_cast<EditMedicationDialog*>(uncastedEditor);
model->setData(drugClassIndex, editor->drugClass());
model->setData(drugIndex, editor->drug()); // HERE
model->setData(dosageIndex, editor->dosage());
model->setData(amountIndex, editor->amount());
model->setData(scheduleIndex, editor->schedule());
model->setData(frequencyIndex, editor->frequency());
}
Строка с комментарием "ЗДЕСЬ" вызывает проблему (согласно отладке).
РЕДАКТИРОВАТЬ (новая информация): Я просто понимаю, что QAbstractItemModel::setData
всегда вызывается сразу после того, как столбец, вызвавший «редактирование», сохраняется. Я всегда давал два клика в колонке «наркотик». Поэтому QAbstractItemDelegate::setEditorData
вызывается после этого издания.
Спасибо.