Читаем QT 4: программирование GUI на С++ полностью

RegExpWindow — окно, которое позволяет пользователю вводить регулярное выражение и показывает соответствующее дерево грамматического разбора;

RegExpParser формирует дерево грамматического разбора для заданного регулярного выражения;

RegExpModel — модель дерева, используемая деревом грамматического разбора;

Node (вершина) представляет один элемент в дереве грамматического разбора.

Давайте начнем с класса Node:

01 class Node {

02 public:

03 enum Type { RegExp, Expression, Term, Factor, Atom, Terminal };

04 Node(Type type, const QString &str = "");

05 ~Node;

06 Type type;

07 QString str;

08 Node *parent;

09 QList children;

10 };

Каждая вершина имеет тип, строку (которая может быть пустой), ссылку на родительский элемент (которая может быть нулевой) и список дочерних вершин (который может быть пустым).

01 Node::Node(Type type, const QString &str)

02 {

03 this->type = type;

04 this->str = str;

05 parent = 0;

06 }

Конструктор просто инициализирует тип и строку вершины. Поскольку все данные открыты, в программном коде, использующим Node, можно непосредственно манипулировать типом, строкой, родительским элементом и дочерними элементами.

01 Node::~Node

02 {

03 qDeleteAll(children);

04 }

Функция qDeleteAll проходит no всем указателям контейнера и вызывает оператор delete для каждого из них. Она не устанавливает указатели в 0, поэтому, если она используется вне деструктора, обычно за ней следует вызов функции clear для контейнера, содержащего указатели.

Теперь, когда мы определили элементы наших данных (представленные вершиной Node), мы готовы создать модель:

01 class RegExpModel : public QAbstractItemModel

02 {

03 public:

04 RegExpModel(QObject *parent = 0);

05 ~RegExpModel;

06 void setRootNode(Node *node);

07 QModelIndex index(int row, int column,

08 const QModelIndex &parent) const;

09 QModelIndex parent(const QModelIndex &child) const;

10 int rowCount(const QModelIndex &parent) const;

11 int columnCount(const QModelIndex &parent) const;

12 QVariant data(const QModelIndex &index, int role) const;

13 QVariant headerData(int section,

14 Qt::Orientation Orientation, int role) const;

15 private:

16 Node *nodeFromIndex(const QModelIndex &index) const;

17 Node *rootNode;

18 };

На этот раз мы построили подкласс на основе класса QAbstractItemModel, а не на основе его удобного подкласса QAbstractTableModel, потому что мы хотим создать иерархическую модель. Нам необходимо переопределить те же самые функции и, кроме того, требуется реализовать функции index и parent. Для установки данных модели предусмотрена функция setRootNode, при вызове которой должна задаваться корневая вершина дерева грамматического разбора.

01 RegExpModel::RegExpModel(QObject *parent)

02 : QAbstractItemModel(parent)

03 {

04 rootNode = 0;

05 }

В конструкторе модели нам надо просто задать корневой вершине безопасное нулевое значение и передать указатель parent базовому классу.

01 RegExpModel::~RegExpModel

02 {

03 delete rootNode;

04 }

В деструкторе мы удаляем корневую вершину. Если корневая вершина имеет дочерние вершины, то каждая из них удаляется и эта процедура повторяется рекурсивно деструктором Node.

01 void RegExpModel::setRootNode(Node *node)

02 {

03 delete rootNode;

04 rootNode = node;

05 reset;

06 }

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже