Нас самом деле делать наследника от QSqlRecord нет никакой необходимости.
Но тем не менее на начальном этапе мы попробовали это сделать и потом убедились, что это лишнее.
QSqlRecord это самостоятельный класс, без родителя. По сути это удобная обертка над полями одной строки.
Заполнение информации в QSqlRecord происходит в классе модели данных QSqlQueryModel, а именно в функции record.
Получив QSqlRecord по номеру строки из модели данных его можно копировать, сравнивать с другим QSqlRecord, присваивать, то есть удобно манипулировать данными строки..
То есть это все про удобство манипулирования строками.
После того как у нас произошло развитие класса модели данных QSqlTableModel в PblSqlRelationalTabelModel показалось, что возникла необходимость форкнуть и класс QSqlRecord, чтобы исполЬзовать преимущества нового развития. Но это не так.
Дело в том, что QSqlRecord самодостаточен. Он содержит все поля строки, которые формирует selectStatement функция. А selectStatement принадлежит модели данных.
Примечание: как оказалось впоследствие на самом деле делать наследника от QSqlRecord нет никакой необходимости, смотрите последнюю версию sql форк.
Но тем не менее представляем наследника QSqlRecord: PblSqlRecord.
В PblSqlRecord нам надо содержать информацию о полях с внешней связью. Точнее какое дополнительное поле является id внешней связи для заданного номера поля (если конечно такое есть).
По сути PblSqlRecord добавляет карту QHash соответствия оригинальных relation полей и полей, где лежат их id связей.
Может показаться, что добавлять служебную информацию надо как-то в конструкторах класса наследника PblSqlRecord. Но тогда в конструкторах нам нужен доступ к классу модели данных, то есть ссылку/указатель на него надо передавать в конструктор как параметр.
QSqlRecord();
QSqlRecord(const QSqlRecord& other);
QSqlRecord& operator=(const QSqlRecord& other);
Выше представлен стандартный набор конструкторов:правило 3.
Но на самом деле добавить карту соответствия полей можно в методе record модели данных, в котором единственно и происходит создание об'екта QSqlRecord.
Вот функция record класса QSqlQueryModel.
QSqlRecord QSqlQueryModel::record(int row) const
{
Q_D(const QSqlQueryModel);
if (row < 0)
return d->rec;
QSqlRecord rec = d->rec; // вызывается конструктор копирования, d->rec пустой (это только набор полей)
for (int i = 0; i < rec.count(); i)
rec.setValue(i, data(createIndex(row, i), Qt::EditRole));
return rec;
}
Вопрос: как лучше поступить?
Можно полностью переопределить функцию record в нашем классе наследнике (PblSqlRelationalTableModel). И в PblSqlRelationalTableModel будет своя record, а QSqlQueryModel будет своя функция record .
Можно попытаться оставить QSqlQueryModel::record и как-то выкрутится через каст.Например подойдет вариант reinterpretet_cast:
PblSqlRecord pblRec = reinterpret_cast(QSqlQueryModel::record(row));
Далее надо после reinterpret_cast все данные экземпляра PblSqlRecord не забыть проинициализировать.
И еще есть третий вариант, как нам кажется более логичный и правильный, но строчек кода будет побольше. Во первый надо переопределить конструктор копирования с не тривиальным передаваемым параметром (ссылка на объект копирования предка). А именно речь об этом
PblSqlRecord(const QSqlRecord& other);
class Q_SQL_EXPORT PblSqlRecord: public QSqlRecord
{
public:
PblSqlRecord();
PblSqlRecord(const PblSqlRecord& other); // конструктор копирования стандартный
PblSqlRecord(const QSqlRecord& other); // конструктор копирования не стандартный (для функции record)
PblSqlRecord& operator=(const PblSqlRecord& other);
Именно в этом случае мы сможет выполнить строку кода:
PblSqlRecord pblRec(QSqlQueryModel::record(row));
И все будет работать ОК. То есть получается, что мы передаем параметром в конструктор копирования ссылку на объект родителя, что нам и нужно.(см.конструкторы, деструкторы)
Как можно еще решить данную проблему - думаю уже достаточно вариантов и не будем до поры до времени об этом беспокоится.
Вообще-то напрашивается вариант конструктора перемещения, но это стандарт С11, в Qt 4.8.1 вроде бы ещё не используемый. Надо будет попробовать.