QCombobox для foreign keys

Рейтинг: 1Ответов: 1Опубликовано: 18.01.2023

Возникла следующая проблема. Я написал приложение, использующее БД. Изначально для отображения таблиц использовалась QSqlRelationalTableModel и foreign keys можно было изменять и добавлять внутри самого tableView. Выглядело это примерно так: введите сюда описание изображения Но ввиду некоторых причин было решено сделать редактирование данных БД с помощью форм. Так вот вопрос, как мне передать в QCombobox формы при клике на tableView все используемыe в этой ячейке foreign keys? Чтобы было примерно вот так (отображаться должны не индексы, а объекты на которые индексы ссылаются):введите сюда описание изображения

В первом случае код выглядел так:

    model->setTable(sql_query);
    model->setRelation(1, QSqlRelation("my_schema.aircrafts","id_aircraft","registration_number"));
    model->setRelation(3, QSqlRelation("my_schema.airports","id_airport","name_airport"));
    model->setRelation(4, QSqlRelation("my_schema.airports","id_airport","name_airport"));
    model->setHeaderData(0, Qt::Horizontal, "Номер маршрута", Qt::DisplayRole);
    model->setHeaderData(1, Qt::Horizontal, "Самолет", Qt::DisplayRole);
    model->setHeaderData(2, Qt::Horizontal, "Наименование маршрута", Qt::DisplayRole);
    model->setHeaderData(3, Qt::Horizontal, "Аэропорт вылета", Qt::DisplayRole);
    model->setHeaderData(4, Qt::Horizontal, "Аэропорт приземления", Qt::DisplayRole);
    model->select();
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    ui->tableView->setModel(model);
    ui->tableView->setItemDelegateForColumn(1, new QSqlRelationalDelegate(this));
    ui->tableView->setItemDelegateForColumn(3, new QSqlRelationalDelegate(this));
    ui->tableView->setItemDelegateForColumn(4, new QSqlRelationalDelegate(this));
    break;

Подскажите, пожалуйста, что нужно написать для второго случая.

Ответы

▲ 0Принят

Метод QSqlRelationalTableModel::relationModel возвращает QSqlTableModel, которая представляет таблицу, на которую ссылается внешний ключ (или nullptr если для столбца не задана связь). Данную модель и нужно поместить в ваш QComboBox.

За создание editor-ов, выставление значений и передачу результатов в модель отвечают делегаты. Данный код можно подсмотреть в соответствующем делегате. Код создания комбобокса с данными внешнего ключа основанный на QSqlRelationalDelegate::createEditor (qsqlrelationaldelegate.h):

int combo_column = 4;
QComboBox* combo = new QComboBox();
QSqlTableModel *childModel = model->relationModel(combo_column);
//Опущена проверка на childModel != nullptr
combo->setModel(childModel);
const QSqlDriver *const driver = childModel->database().driver();
combo->setModelColumn(fieldIndex(childModel, driver, 
                            model->relation(combo_column).displayColumn()));

//....

static int fieldIndex(const QSqlTableModel *const model,
                  const QSqlDriver *const driver,
                  const QString &fieldName)
{
    const QString stripped = driver->isIdentifierEscaped(fieldName, QSqlDriver::FieldName)
             ? driver->stripDelimiters(fieldName, QSqlDriver::FieldName)
        : fieldName;
    return model->fieldIndex(stripped);
}

Выставить текущее значение комбобокса можно, например, в слоте по сигналу QAbstractItemView::clicked(const QModelIndex &index):

void onClick(const QModelIndex &index)
{
    int comboIndex = combo->findData(index.sibling(index.row(), combo_column).data(), Qt::DisplayRole);
    combo->setCurrentIndex(comboIndex);
}

P.S. Код изменения данных в модели можно посмотреть в QSqlRelationalDelegate::setModelData (qsqlrelationaldelegate.h):

const QSqlDriver *const driver = childModel->database().driver();

int currentItem = combo->currentIndex();

int childEditIndex = fieldIndex(childModel, driver,
                                model->relation(index.column()).indexColumn());

model->setData(index,
        childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole),
        Qt::EditRole);

Поведение модели при методе setData зависит от стратегии редактирования. В случае кэширования данных можно менять и Qt::DisplayRole (см. qsqlrelationaldelegate.h)