01 void SettingsViewer::readSettings()
02 {
03 QSettings settings(organization, application);
04 treeWidget->clear();
05 addChildSettings(settings, 0, "");
06 treeWidget->sortByColurnn(0);
07 treeWidget->setFocus();
08 setWindowTitle(tr("Settings Viewer - %1 by %2")
09 .arg(application).arg(organization));
10 }
Параметры настройки приложения хранятся в виде набора ключей и значений, имеющих иерархическую структуру. Закрытая функция addChildSettings() принимает объект параметров настройки, родительский элемент QTreeWidgetItem и текущую «группу». Группа в QSettings аналогична каталогу файловой системы. Функция addChildSettings() может вызывать себя рекурсивно для прохода по произвольной структуре типа дерева. При первом ее вызове из функции readSettings() передается 0, задавая корень в качестве родительского объекта.
01 void SettingsViewer::addChildSettings(QSettings &settings,
02 QTreeWidgetItem *parent, const QString &group)
03 {
04 QTreeWidgetItem *item;
05 settings.beginGroup(group);
06 foreach (QString key, settings.childKeys()) {
07 if (parent) {
08 item = new QTreeWidgetItem(parent);
09 } else {
10 item = new QTreeWidgetItem(treeWidget);
11 }
12 item->setText(0, key);
13 item->setText(1, settings.value(key).toString());
14 }
15 foreach (QString group, settings.childGroups()) {
16 if (parent) {
17 item = new QTreeWidgetItem(parent);
18 } else {
19 item = new QTreeWidgetItem(treeWidget);
20 }
21 item->setText(0, group);
21 addChildSettings(settings, item, group);
22 }
23 settings.endGroup();
24 }
Функция addChildSettings() используется для создания всех элементов QTreeWidgetItem. Она проходит по всем ключам текущего уровня в иерархии параметров настройки и для каждого ключа создает один объект QTableWidgetItem. Если в качестве родительского элемента задан 0, мы создаем дочерний элемент собственно виджета QTreeWidget (т.е. создается элемент верхнего уровня); в противном случае мы создаем дочерний элемент для объекта parent. В первый столбец записывается имя ключа, а во второй столбец — соответствующее ему значение.
Затем эта функция выполняется для каждой группы текущего уровня. Для каждой группы создается новый объект QTreeWidgetItem, причем в первый столбец записывается имя группы. Затем эта функция рекурсивно вызывает саму себя с указанием группового элемента в качестве родительского для заполнения виджета QTreeWidget дочерними элементами группы.
Показанные в данном разделе виджеты отображения элементов позволяют нам использовать стиль программирования, который очень похож на тот, который применялся в ранних версиях Qt: чтение всего набора данных в виджет отображения элементов с использованием объектов, представляющих отдельные элементы данных, и (если элементы допускают редактирование) их запись обратно в источник данных. В последующих разделах мы выйдем за рамки этого простого подхода и воспользуемся всеми преимуществами, которые дает архитектура Qt модель/представление.
Применение заранее определенных моделей
В Qt заранее определено несколько моделей, предназначенных для использования с классами представлений:
• QStringListModel — хранит список строк;
• QStandardltemModel — хранит данные произвольной иерархической структуры;
• QDirModel — формирует структуру локальной файловой системы;
• QSqlQueryModel — формирует набор результата SQL—запроса;
• QSqlTableModel — формирует SQL—таблицу;
• QSqlRelationalTableModel — формирует SQL—таблицу с внешними ключами (foreign keys);
• QSortFilterProxyModel — сортирует и/или пропускает через фильтр другую модель.
В данном разделе мы рассмотрим способы применения моделей QStringListModel, QDirModel и QSortFilterProxyModel. SQL—модели рассматриваются в главе 13.
Давайте начнем с простого диалогового окна, которое может применяться для добавления, удаления и редактирования списка строк QStringList, где каждая строка представляет лидера команды.
Ниже приводится соответствующий фрагмент конструктора:
01 TeamLeadersDialog::TeamLeadersDialog(const QStringList &leaders,
02 QWidget *parent)