11 this, SLOT(beforeInsertArtist(QSqlRecord &)));
12 tableView = new QTableView;
13 tableView->setModel(model);
14 tableView->setColumnHidden(Artist_Id, true);
15 tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
16 tableView->resizeColumnsToContents();
17 for (int row = 0; row < model->rowCount(); ++row) {
18 QSqlRecord record = model->record(row);
19 if (record.value(Artist_Name).toString() == name) {
20 tableView->selectRow(row);
21 break;
22 }
23 }
24 …
25 }
Конструктор начинается с создания объекта QSqlTableModel. Мы передаем this в качестве родителя, чтобы владельцем модели стала форма. Нами выбрана сортировка по столбцу 1 (задается константой Artist_Name), который соответствует полю имени. Если бы мы не задали заголовки столбцов, то использовались бы имена полей. Мы предпочитаем их указать, чтобы обеспечить правильный регистр и локализацию.
Затем создается QTableView для визуального отображения модели. Мы не показываем поле id и устанавливаем такую ширину столбцов, которая будет достаточна для размещения в них текста без необходимости вывода многоточия.
Конструктор ArtistForm принимает имя артиста, который будет выбран при выводе на экран диалогового окна. Мы проходим по записям таблицы artist и выбираем этого артиста. Остальная часть программного кода конструктора используется для создания кнопок и подключения к ним слотов, а также для компоновки дочерних виджетов в диалоговом окне.
01 void ArtistForm::addArtist()
02 {
03 int row = model->rowCount();
04 model->insertRow(row);
05 QModelIndex index = model->index(row, Artist_Name);
06 tableView->setCurrentIndex(index);
07 tableView->edit(index);
08 }
Для добавления нового артиста мы вставляем одну пустую строку в конец табличного представления QTableView. Теперь пользователь может вводить имя нового артиста и его страну. Если пользователь подтверждает вставку, нажимая кнопку Enter, генерируется сигнал beforeInsert(), и после этого новая запись вставляется в базу данных.
01 void ArtistForm::beforeInsertArtist(QSqlRecord &record)
02 {
03 record.setValue("id", generateId("artist"));
04 }
В конструкторе мы связываем сигнал модели beforeInsert() с этим слотом. Мы передаем неконстантную ссылку на запись непосредственно перед ее вставкой в базу данных. Здесь мы устанавливаем значение поля id.
Поскольку нам потребуется вызывать функцию generateId() несколько раз, мы определяем ее как inline—функцию в заголовочном файле и включаем ее каждый раз по мере необходимости. Ниже дается простой (и неэффективный) способ ее реализации:
01 inline int generateId(const QString &table)
02 {
03 QSqlQuery query;
04 query.exec("SELECT MAX(id) FROM " + table);
05 int id = 0;
06 if (query.next())
07 id = query.value(0).tolnt() + 1;
08 return id;
09 }
Функция generateId() может гарантированно работать правильно, если она выполняется в рамках контекста одной транзакции соответствующей команды INSERT. Некоторые базы данных поддерживают средство автоматической генерации полей, и обычно значительно лучше использовать предусмотренные в базе данных специальные средства поддержки этой операции.
Удаление — это последняя операция, которую позволяет сделать диалоговое окно ArtistForm. Вместо каскадного удаления (вскоре будет рассмотрено) мы разрешаем удалять артистов только в том случае, если в коллекции нет их компакт-дисков.
01 void ArtistForm::deleteArtist()
02 {
03 tableView->setFocus();
04 QModelIndex index = tableView->currentIndex();
05 if (!index.isValid())