QT 4: программирование GUI на С++
Шрифт:
Функция headerData имеет простой вид, потому что наша таблица является квадратной матрицей, в которой строки и столбцы имеют идентичные заголовки. Мы просто возвращаем название города, расположенное с заданным смещением в списке строк cities.
Функция setData
Функция createIndex используется для формирования индекса модели. Она нужна для получения индекса модели элемента, который расположен по другую сторону от главной диагонали и который соответствует элементу с установленным значением, поскольку оба элемента должны показывать одинаковые данные. Функция createIndex принимает сначала строку и затем столбец; здесь мы передаем параметры в обратном порядке, чтобы получить индекс модели элемента, расположенного по другую строну диагонали напротив элемента, определенного индексом index.
Мы генерируем сигнал dataChanged с указанием индекса модели элемента, который изменился. Эта функция принимает два индекса модели, поскольку возможна ситуация, когда изменения относятся к некоторой прямоугольной области, охватывающей несколько строк и столбцов, поэтому передаются индекс верхнего левого угла и индекс нижнего правого угла этой области. Генерируем также сигнал dataChanged для индекса противоположного элемента, чтобы представление обновило его отображение на экране. Наконец, мы возвращаем true или false, указывая на успешность или неуспешность редактирования.
Функция flags используется моделью для того, чтобы можно было сообщить о допустимых действиях с элементом (например, допускает ли он редактирование). По умолчанию эта функция для модели QAbstractTableModel
Если задан новый список городов, мы устанавливаем закрытую переменную типа QStringList на новый список, изменяем размеры и очищаем вектор расстояний, а затем вызываем функцию QAbstractItemModel::reset, чтобы уведомить все представления о необходимости обновления всех видимых элементов.
Закрытая функция offsetOf вычисляет индекс заданной пары городов для вектора расстояний distances. Например, предположим, что мы имеем города А, В, С и D, и пользователь обновляет элемент со строкой 3 и столбцом 1, т. е. (B, D). Тогда индекс вектора расстояний будет равен 3 × (3 — 1) / 2 + 1 = 4. Если бы пользователь вместо этого изменил элемент со строкой 1 и столбцом 3, т.е. (D, В), благодаря применению функции qSwap, выполнялись бы точно такие же вычисления и возвращалось бы то же самое значение.
Рис. 10.13. Структуры данных cities и distances и табличная модель.
Последний пример в данном разделе представляет собой модель, которая показывает дерево грамматического разбора заданного регулярного выражения. Регулярное выражение состоит из одного или нескольких термов, разделяемых символами '|'. Так, регулярное выражение «alpha|bravo|charlie» содержит три терма. Каждый терм представляет собой последовательность из одного или нескольких факторов: например, терм «bravo» состоит из пяти факторов (каждая буква является фактором). Факторы могут состоять из атома и необязательного квантификатора (quantifier), например '*', '+' и '?'. Поскольку регулярные выражения могут иметь подвыражения, заключенные в скобки, они могут быть представлены рекурсивными деревьями грамматического разбора.
Регулярное выражение, показанное на рис. 10.14, «ab|(cd)?e» означает, что за 'a' следует 'b' или допускается два варианта: за 'c' идет 'd' и затем 'e' или просто имеется 'e'. Поэтому подойдут строки «ab» и «cde», но не подойдут строки «bc» или «cd».
Рис. 10.14. Приложение Парсер регулярных выражений.
Приложение Парсер регулярных выражений (Regexp Parser) состоит из четырех классов:
• RegExpWindow — окно, которое позволяет пользователю вводить регулярное выражение и показывает соответствующее дерево грамматического разбора;