Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

Настройка представления таблицы cd выполняется аналогично тому, что мы уже делали. Единственным существенным отличием является применение QSqlRelationalDelegate вместо делегата по умолчанию. Именно этот делегат обеспечивает работу с внешними ключами.

19 trackModel = new QSqlTableModel(this);

20 trackModel->setTable("track");

21 trackModel->setHeaderData(Track_Title, Qt::Horizontal, tr("Title"));

22 trackModel->setHeaderData(Track_Duration, Qt::Horizontal,

23 tr("Duration"));

24 trackTableView = new QTableView;

25 trackTableView->setModel(trackModel);

26 trackTableView->setItemDelegate(

27 new TrackDelegate(Track_Duration, this));

28 trackTableView->setSelectionMode(QAbstractItemView::SingleSelection);

29 trackTableView->setSelectionBehavior(QAbstractItemView::SelectRows);

Для

дорожек мы собираемся выводить на экран только названия песен и их длительности, поэтому достаточно использовать модель QSqlTableModel. (Поля id и cdid, используемые в рассмотренном ниже слоте currentCdChanged, не выводятся на экран.) Единственно, на что следует обратить внимание в этой части программного кода, — это использование разработанного в главе 10 класса TrackDelegate, показывающего времена дорожек в виде «минуты:секунды» и позволяющего их редактировать с помощью удобного класса QTimeEdit.

Создание представлений и кнопок, их компоновка и соединения сигнал—слот не содержат ничего особенного, поэтому из оставшейся части конструктора мы покажем только несколько не совсем очевидных соединений.

30 …

31 connect(cdTableView->selectionModel,

32 SIGNAL(currentRowChanged(const QModelIndex &,

33 const QModelIndex &)),

34 this, SLOT(currentCdChanged(const QModelIndex &)));

35 connect(cdModel, SIGNAL(beforeInsert(QSqlRecord &)),

36 this, SLOT(beforeInsertCd(QSqlRecord &)));

37 connect(trackModel, SIGNAL(beforeInsert(QSqlRecord &)),

38 this, SLOT(beforeInsertTrack(QSqlRecord &)));

39 connect(trackModel, SIGNAL(rowsInserted(

40 const QModelIndex &, int, int)),

41 this, SLOT(refreshTrackViewHeader));

42 …

43 }

Первое соединение необычно, поскольку вместо связывания виджета мы связываем модель выборки. Класс QItemSelectionModel используется для отслеживания выборок в представлениях. Связанный с моделью выборки представления таблицы, наш слот currentCdChanged будет вызываться при всяком перемещении пользователя от одной записи к другой.

01 void MainForm::currentCdChanged(const QModelIndex &index)

02 {

03 if (index.isValid) {

04 QSqlRecord record = cdModel->record(index.row);

05 int id = record.value("id").toInt;

06 trackModel->setFilter(QString("cdid = %1").arg(id));

07 } else {

08 trackModel->setFilter("cdid = -1");

09 }

10 trackModel->select;

11 refreshTrackViewHeader;

12 }

Этот

слот вызывается при каждой смене текущего компакт-диска. Это происходит при переходе пользователя к другому компакт-диску (щелкая мышкой по соответствующей строке или используя клавиши Up и Down). Если компакт-диск недействителен (например, если вообще нет компакт-дисков или был вставлен новый компакт-диск, или текущий компакт-диск был только что удален), мы устанавливаем идентификатор cdid таблицы дорожек track в значение —1 (недействительный идентификатор, которому не соответствует никакая запись).

Затем, установив фильтр, мы выбираем ему соответствующие записи дорожек. Функция refreshTrackViewHeader будет рассмотрена вскоре.

01 void MainForm::addCd

02 {

03 int row = 0;

04 if (cdTableView->currentIndex.isValid)

05 row = cdTableView->currentIndex.row;

06 cdModel->insertRow(row);

07 cdModel->setData(cdModel->index(row, Cd_Year),

08 QDate::currentDate.year);

09 QModelIndex index = cdModel->index(row, Cd_Title);

10 cdTableView->setCurrentIndex(index);

11 cdTableView->edit(index);

12 }

Когда пользователь нажимает клавишу Add CD (добавить компакт-диск), в таблицу cdTableView вставляется новая пустая строка и мы переходим в режим редактирования. Мы также устанавливаем значение по умолчанию для поля year. В этот момент пользователь может редактировать запись, заполняя пустые поля и выбирая артиста из выпадающего списка, который автоматически выдается моделью QSqlRelationalTableModel благодаря вызову setRelation, a также изменяя год, если не подходит значение по умолчанию. Если пользователь подтверждает вставку нажатием клавиши Enter, запись вставляется. Пользователь может отменить вставку, нажав клавишу Esc.

01 void MainForm::beforeInsertCd(QSqlRecord &record)

02 {

03 record.setValue("id", generateId("cd"));

04 }

Этот слот вызывается, когда cdModel генерирует свой сигнал beforeInsert. Мы используем его для заполнения поля id, как это делалось при вставке нового артиста, и здесь применимо то же самое предостережение: данная операция должна выполняться в рамках транзакции, а в идеальном случае должно использоваться зависимое от базы данных средство создания идентификаторов (например, автоматическая генерация идентификаторов).

01 void MainForm::deleteCd

02 {

03 QModelIndex index = cdTableView->currentIndex;

04 if (!index.isValid)

05 return;

06 QSqlDatabase db = QSqlDatabase::database;

07 db.transaction;

08 QSqlRecord record = cdModel->record(index.row);

09 int id = record.value(Cd_Id).toInt;

10 int tracks = 0;

Поделиться с друзьями: