Класс QgebComplexTreeView

В представленном документе описывается класс QgebComplexTreeView, наследуемый от стандартного класса QTreeView, и обладающий дополнительной функциональностью по сравнению с ним.

Краткое описание дополнений

Класс QgebComplexTreeView обеспечивает следующий набор дополнительных возможностей:

            - построение заголовка сложной иерархической структуры;

            - установку одной или нескольких левых колонок иерархической таблицы не прокручиваемыми;

            - наличие встроенного контекстного меню со следующими опциями:

                        - печать иерархической таблицы;

                        - сохранение в HTML файле;

                        - скрытие/отображение колонок;

            - сохранение/восстановление настроек иерархической таблицы (ширина и видимость колонок).

Подробное описание класса QgebComplexTreeView

В таблице ниже представлены новые или переопределенные открытые методы класса.

Метод

Краткое описание

QgebComplexTableView(QWidget *parent = 0)

конструктор

~QgebComplexTableView()

деструктор

Основные методы

void setHeaderModel(QStandardItemModel *headerModel)

установить модель заголовка

void setModel(QAbstractItemModel *model)

установить модель таблицы

QAbstractItemModel * model()

вернуть модель таблицы

void setFrozenColumn(int frozenCount)

установить заданное количество не прокручиваемых колонок

QTableView * getFrozenTable()

вернуть не прокручиваемую таблицу

Методы сохранения и восстановления параметров колонок таблицы

QString getPathLocation()

получить местоположение файла с параметрами колонок таблицы

int saveStateTable(QString path)

сохранить параметры колонок таблицы

int restoreStateTable(QString path)

восстановить параметры колонок таблицы

QString getErrorMessage()

вернуть описание ошибки

Методы, применяемые при печати таблицы или сохранении ее в HTML файле

void setTitle(QString title)

задать титульный заголовок таблицы

void setPrintHtml(QString textHtml)

установить не стандартное представление таблицы

void setAlignColumn(QVector <int> align)

задать выравнивание  текста по горизонтали для каждой колонки таблицы

void setVAlignColumn(QVector <int> valign)

задать выравнивание  текста по вертикали для

каждой колонки таблицы

void setLevelIndicator(bool levelIndicator=true)

показывать индикатор уровня иерархии

Основные методы

Методы данного раздела обеспечивают базовую функциональность класса, связанную с установкой сложного иерархического заголовка и не прокручиваемых колонок.

void setHeaderModel(QStandardItemModel *headerModel)

Данный метод обеспечивает установку в иерархической таблице сложного иерархического заголовка.

Вход: QStandardItemModel *headerModel – модель иерархического заголовка.

Выход: нет.

Примечание. Правила построения заголовка подробно рассмотрены в примере программы, представленной в конце документа. Принцип построения заголовка, и его реализация взяты отсюда.

void setModel(QAbstractItemModel *model)

Данный метод обеспечивает установку модели в представление иерархической таблицы. Переопределяет QTableView::setModel(QAbstractItemModel *model).

Вход: QAbstractItemModel *model – модель данных иерархической таблицы.

Выход: нет.

QAbstractItemModel * model()

Данный метод возвращает адрес модели иерархической таблицы, установленной посредством метода void setModel(QAbstractItemModel *model).

Вход: нет.

Выход: адрес модели иерархической таблицы.

void setFrozenColumn(int frozenCount)

Данный метод обеспечивает задание количества не прокручиваемых левых колонок иерархической таблицы.

Вход: int frozenCount – количество левых, не прокручиваемых колонок.

Выход: нет.

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

Задание одной или нескольких левых колонок не прокручиваемыми обеспечивает фиксацию их положения при выполнении горизонтальной прокрутки.

Если данный метод не использован, то все колонки иерархической таблицы будут прокручиваться.

QTableView * getFrozenTable()

Данный метод возвращает адрес таблицы, используемой для представления не прокручиваемых колонок.

Вход: нет.

Выход: адрес таблицы, используемой для представления не прокручиваемых колонок.

Примечание. Визуальный эффект создания не прокручиваемых колонок достигается совмещением местоположения и синхронизацией работы двух таблиц. Одна из них представляет прокручиваемую таблицу, именно она наследуется от QTreeView, а вторая не прокручиваемую. В поставке библиотеки Qt есть пример, иллюстрирующий механизм реализации не прокручиваемой колонки.

В классе обеспечена синхронизация обработки большинства возможных сигналов связанных с представлением таблиц. Для тех же случаев, когда реализация методов QTreeView, изменяющих представление таблицы, не выполнена в классе QgebComplexTreeView, она возлагается на пользователя класса. В этом случае пользователь должен:

- выполнить требуемый метод для класса QgebComplexTreeView;

- получить адрес не прокручиваемой таблицы;

- повторно выполнить тот же метод, но уже для не прокручиваемой таблицы.

Методы сохранения и восстановления параметров колонок иерархической таблицы

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

Параметры таблицы хранятся в xml файле. Причем один xml файл хранения можно помещать параметры нескольких таблиц программы, даже расположенных в разных виджетах. Поэтому, для правильной обработки информации требуется таблицам и их родительским виджетам обязательно устанавливать уникальные объектные имена, используя метод QWidget::setObjectName (const QString &) QgebComplexTableView (наличие уникальных объектных имен обеспечивает однозначность определения узлов в XML документе файла хранения).

int saveStateTable(QString path)

Данный метод сохраняет параметры иерархической таблицы. Обычно выполняется при уничтожении ее родительского виджета .

Вход: QString path – полный путь доступа к xml файлу сохранения (включая название xml файла, например, для Windows c:/my_table/table_param.xml или для Linux /usr/my_table/table_param.xml) параметров таблицы.

Выход: код возврата. Возможны следующие коды возврата:

  0 - успешное завершение;

  -1 - не задано объектное имя таблицы;

  -2 - не задано объектное имя родителя;

  -3 - не существует указанного файла сохранения (только для restoreStateTable);

  -4 - ошибка в структуре XML документа;

  -5 - ошибка при открытии XML документа на чтение;

  -6 - файловая ошибка при чтении документа;

  -7 - ошибка при открытии XML документа на запись.

int restoreStateTable(QString path)

Данный метод восстанавливает представление иерархической таблицы в соответствии с параметрами xml файла сохранения.

Вход: QString path – полный путь доступа к xml файлу сохранения (включая название xml файла, например, для Windows c:\my_table\table_param.xml или для Linux /usr/my_table/table_param.xml) параметров таблицы.

Выход: код возврата. Возможны следующие коды возврата:

  0 - успешное завершение;

  -1 - не задано объектное имя таблицы;

  -2 - не задано объектное имя родителя;

  -3 - не существует указанного файла сохранения (только для restoreStateTable);

  -4 - ошибка в структуре XML документа;

  -5 - ошибка при открытии XML документа на чтение;

  -6 - файловая ошибка при чтении документа;

  -7 - ошибка при открытии XML документа на запись.

QString getPathLocation()

Данный метод возвращает полный путь доступа к xml файлу сохранения параметров иерархической таблицы.

Вход: нет.

Выход: полный путь доступа к xml файлу сохранения параметров таблицы.

QString getErrorMessage()

 Данный метод возвращает текстовое описание местоположения ошибки в xml файле сохранения, выданное XML парсером, при выполнении методов saveStateTable и restoreStateTable.

Методы, применяемые при печати иерархической таблицы или сохранении ее в HTML файле

В иерархическую таблицу, создаваемую посредством данного класса, встроено контекстное меню, включающее три опции:

            - печать таблицы;

            - сохранение в HTML файле;

            - скрытие/отображение колонки.

При формировании представления иерархической таблицы на печати и при сохранении в HTML файле (соответственно его отображении в браузере или другой программе просмотра html файлов) по умолчанию устанавливается та же ширина колонок, размер и тип шрифтов заголовка и ячеек тела таблицы, что и на экране. Это позволяет максимально приблизить печатное и html представление таблицы экранному представлению.

Кроме этого, данный класс поддерживает ряд методов, обеспечивающий дополнительный сервис представления таблиц на печати и в HTML файле.

void setTitle(QString title)

Данный метод позволяет задать название (титульный заголовок) иерархической таблицы. Например, если таблица является документом, то название этого документа.

Вход: QString title – строка с названием таблицы.

Выход: нет.

Название таблицы размещается над иерархической таблицей, с выравниванием по центру.

void setPrintHtml(QString textHtml)

Данный метод позволяет установить не стандартное, пользовательское представление иерархической таблицы на печати или в HTML файле.

Вход: QString textHtml – строка с текстом html

Выход: нет.

Если пользователя не устраивает стандартное отображение иерархической таблицы на печати или в HTML файле, то он может сформировать собственный HTML файл представления таблицы и, именно данное, пользовательское представление будет выведено на печать и сохранено в HTML файле.

Методы выравнивания информации ячеек тела иерархической таблицы при выводе на печать и HTML файл

При формировании представления иерархической таблицы на печати и при сохранении в HTML файле информация в ячейках заголовка таблицы автоматически выравниваются также, как в при ее представлении на экране.

Однако информация ячеек тела иерархической таблицы по умолчанию при выводе на печать и сохранении в HTML файле выравнивается по горизонтали «влево», а по вертикали «вверх».

Представленные ниже методы позволяют установить требуемое пользователю выравнивание информация ячеек тела иерархической таблицы при выводе на печать и сохранении в HTML файле.

void setAlignColumn(QVector <int> align)

Данный метод позволяет установить требуемое выравнивание в колонках по горизонтали.

Вход: QVector <int> align – значение выравнивания по горизонтали в колонках.

Выход: нет.

Значение выравнивания должно соответствовать значению перечисления enum Qt::AlignmentFlag. Позиция в векторе определяет номер колонки.

void setVAlignColumn(QVector <int> valign)

Данный метод позволяет установить требуемое выравнивание в колонках по вертикали.

Вход: QVector <int> valign – значение выравнивания по вертикали в колонках.

Выход: нет.

Значение выравнивания должно соответствовать значению перечисления enum Qt::AlignmentFlag. Позиция в векторе определяет номер колонки.

void setLevelIndicator(bool levelIndicator=true)

Данный метод устанавливает индикатор уровня иерархии при печати иерархической таблицы и ее преобразовании в HTML файл.

Вход:  bool levelIndicator - true – показывать индикатор иерархии, false – не показывать.

Выход: нет.

При установке levelIndicator=true, в колонке иерархии перед именем элемента будет проставляться последовательность точек, количество которых соответствует  уровню иерархии.

Примечание. В случае глубокой вложенности может не хватить места для проставления индикатора иерархии, и он будет проставлен над именем элемента.

Скрытие и отображение колонок

Возможности по скрытию и отображению колонок активизируются при выборе опции «скрыть/отобразить колонки» контекстного меню, встроенного в иерархическую таблицу. При этом появляется окно «Скрыть/отобразить колонки таблицы» со списком названий всех колонок таблицы. Слева от названия колонки находится элемент выбора (QCheckBox).  Для скрытия колонки необходимо сделать отметку в ее элементе выбора, т.е. отображаются колонки, у которых нет отметки в элементе выбора. Не прокручиваемые колонки недоступны для скрытия.

Пример с комментариями

Примечание. Проект примера использует кодировку UTF-8.

mainwindow.h

  #ifndef MAINWINDOW_H
  #define MAINWINDOW_H
  #include <QMainWindow>
  #include "qgebcomplextreeview.h"
  #include <QStandardItemModel>
  class MainWindow : public QMainWindow {
      Q_OBJECT
  public:
      MainWindow(QWidget *parent = 0);
      ~MainWindow();
  private:
      void BuildHeaderModel(QStandardItemModel& headerModel);
      void BuildBodyModel();
      void setNextLevel(QStandardItem * parent, QString pLevel);
      QgebComplexTreeView *complexTreeView;
      QStandardItemModel * stm;
      int depth;
      int currentDepth;
      int cols;
  };
  #endif // MAINWINDOW_H
  

Mainwindow.cpp

  #include "mainwindow.h"
  #include "qgebcomplextreeview.h"
  #include <QRect>
  #include <QStandardItemModel>
  #include <QVBoxLayout>
  #include <QHBoxLayout>
  MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent)
  {
      if (objectName().isEmpty())
          setObjectName(QString::fromUtf8("MainWindow"));
      QWidget * centralWidget = new QWidget(this);
      centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
      setCentralWidget(centralWidget);
      QGridLayout * gridLayout = new QGridLayout;
      centralWidget->setLayout(gridLayout);
      //создаем модель заголовка
      QStandardItemModel *headerModel = new QStandardItemModel;
      BuildHeaderModel(*headerModel);
      complexTreeView = new QgebComplexTreeView(this);
      complexTreeView->setVisible(true);

    complexTreeView->setSortingEnabled(true);

    //передаем в класс модель заголовка (должна быть передана до установки не прокручиваемых колонок)     complexTreeView->setHeaderModel(headerModel);     //устанавливаем модель данных    //последовательность из 5 операторов должна быть фиксированной     stm = new QStandardItemModel;     complexTreeView->setModel(stm);     //таблица 9 колонок

    cols = 9;     stm->insertColumns(0,cols,QModelIndex());     complexTreeView->setColumnWidth(0,200);     //вектор для хранения значений горизонтального выравнивания в колонках     QVector <int> alignColumnText;     //вектор для хранения значений вертикального выравнивания в колонках     QVector <int> valignColumnText;     //заполняем вектора со знчениями выравнивания     for (int col=0; col<cols; ++col)     {         //здесь для примера устанавливаем явно, если это не сделать, то умолчанию (left и top)         //устанавливаем горизонтальное и вертикальное выравнивание при представлении в HTML по центру         //(делаем один раз)         alignColumnText.append(Qt::AlignHCenter);         valignColumnText.append(Qt::AlignVCenter);     }     //сформировать иерархию в колонке 0 тела таблицы на основе QStandardItemModel     BuildBodyModel();     //делаем левые две колонки не прокручиваемыми     complexTreeView->setFrozenColumn(2);     //разрешаем в случае необходимости горизонтальный и вертикальный ScrollBar     complexTreeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);     complexTreeView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);     complexTreeView->setObjectName("complexTreeView");  //объектное имя таблицы     //восстанавливаем сохраненные значения     gridLayout->addWidget(complexTreeView, 0, 0);     //!!! пример синхронизации прокручиваемой и не прокручивамой иерархической таблицы     //раскрываем полную иерархию (сначала у прокручиваемой, а затем не прокручивамой иерархической таблицы)     complexTreeView->expandAll();     complexTreeView->getFrozenTable()->expandAll(); } /*   Две функции заполнения иерархической таблицы, вторая рекурсивная */ void MainWindow::BuildBodyModel() {     //заполняем дерево     //уровень 0, три элемента     depth = 3; //глубина дерева примера     currentDepth = 0;     QString sLevel;     QString sCol;     QStandardItem * item;     QStandardItem * item1;     for (int row=0; row<3; ++row)     {         sLevel = tr("Уровень_") + QString::number(row);         item = new QStandardItem;         item->setData(sLevel, Qt::DisplayRole);         item->insertColumns(0,cols);         stm->setItem(row, item);         for (int col=1; col<item->columnCount(); ++col)         {             sCol = tr("Кол_") + QString::number(col) + " " + sLevel;             item1 = new QStandardItem;             item1->setData(sCol, Qt::DisplayRole);             stm->setItem(row, col, item1);         }         currentDepth ++;         setNextLevel(item, sLevel);         currentDepth --;     } } void MainWindow::setNextLevel(QStandardItem * parent, QString pLevel) {     if ( currentDepth == depth )         return;     QString sLevel;     QStandardItem * item;     QString sCol;     QStandardItem * item1;     for (int row=0; row<3; ++row)     {         sLevel = pLevel + "_" + QString::number(row);         item = new QStandardItem;         item->setData(sLevel, Qt::DisplayRole);         item->insertColumns(0,cols);         parent->setChild(row, item);         for (int col=1; col<item->columnCount(); ++col)         {             sCol = tr("Кол_") + QString::number(col) + " " + sLevel;             item1 = new QStandardItem;             item1->setData(sCol, Qt::DisplayRole);             parent->setChild(row, col, item1);         }         currentDepth ++;         setNextLevel(item, sLevel);         currentDepth --;     } } MainWindow::~MainWindow() {     int ret = complexTreeView->saveStateTable("c:/complexTreeView.xml");     if ( ret != 0 )         QMessageBox::critical(this, tr("Error"), tr("Ошибка сохранения параметров таблицы. Код: ") + QString::number(ret), QMessageBox::Ok); } void MainWindow::BuildHeaderModel(QStandardItemModel& headerModel) {     //Заголовки "замороженных" колонок. В них не должно быть иерархии, т.е. они всегда на уровне 1.     QStandardItem* fixedItem = new QStandardItem("Фиксированная\nколонка 1");     QStandardItem* fixedItem1 = new QStandardItem("Фиксированная\nколонка 2");     //Два заголовка уровня 1. Для первого будем формировать иерархию, для второго нет.     QStandardItem* rootItem = new QStandardItem("Уровень 1 с иерархией");     QStandardItem* rootItem1 = new QStandardItem("Уровень 1\nбез иерархии");     //список для элементов заголовков, находящихся под rootItem (уровень 2)     QList<QStandardItem*> list;         //Создаем элемент уровеня 2 под rootItem. Дочерних не имеет. Название устанавливается с поворотом.         QStandardItem* rotatedTextCell=new QStandardItem("Уровень 2\nВращаемый текст");         rotatedTextCell->setData(1, Qt::UserRole);  //Признак поворота: первый параметр равен 1         list.push_back(rotatedTextCell);         rootItem->appendColumn(list);         //Создаем элемент уровня 2 под rootItem. Дочерних не имеет.         list.clear();         list.push_back(new QStandardItem("Уровень 2\nОбычный текст"));         rootItem->appendColumn(list);         //Создаем элемент уровня 2 под rootItem. Имеет дочерние.         list.clear();         QStandardItem* cell=new QStandardItem("Уровень 2\nС дочерними");         list.push_back(cell);         rootItem->appendColumn(list);         //Создаем элемент уровеня 3 под cell.  Дочерних не имеет.         list.clear();         list.push_back(new QStandardItem("Уровень 3\nБез дочерних"));         cell->appendColumn(list);         //Создаем элемент уровеня 3 под cell.  Имеет дочерние.         list.clear();         QStandardItem* cell3=new QStandardItem("Уровень 3\nС дочерними");         list.push_back(cell3);         cell->appendColumn(list);         //Создаем элемент уровеня 4 под cell3.  Дочерних не имеет.         list.clear();         list.push_back(new QStandardItem("Уровень 4\nПервый элемент"));         cell3->appendColumn(list);         //Создаем элемент уровеня 4 под cell3.  Дочерних не имеет.         list.clear();         list.push_back(new QStandardItem("Уровень 4\nВторой элемент"));         cell3->appendColumn(list);         //Создаем элемент уровеня 2 под rootItem. Дочерних не имеет.         list.clear();         list.push_back(new QStandardItem("Уровень 2\nБез дочерних"));         rootItem->appendColumn(list);         //Устанавливаем элементы уровня 1 в модель заголовка         headerModel.setItem(0, 0, fixedItem);         headerModel.setItem(0, 1, fixedItem1);         headerModel.setItem(0, 2, rootItem);         headerModel.setItem(0, 3, rootItem1); }

Запустим программу. На экране построенная иерархическая таблица будет представляться примерно следующим образом:

Уменьшим ширину иерархической таблицы, чтобы появился элемент горизонтальной прокрутки, и прокрутим таблицу вправо на две колонки. Сначала «уйдет» колонка «Уровень2 Вращаемый текст», затем «Уровень 2 Обычный текст». Левые две фиксированные колонки останутся на месте. Таблица на экране будет представляться примерно следующим образом:

Исходный текст примера здесь.

Сайт создан в системе uCoz