Класс QgebComplexTableView

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

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

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

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

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

            - наличие встроенного контекстного меню (активизируемого по щелчку правой кнопкой мышки на заголовке таблице) со следующими опциями:

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

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

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

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

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

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

 

Метод

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

QgebComplexTableView(QWidget *parent = 0)

конструктор

~QgebComplexTableView()

деструктор

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

void setHeaderModel(QStandardItemModel *headerModel)

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

void setModel(QAbstractItemModel *model)

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

QAbstractItemModel * model()

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

void setFrozenColumn(int frozenCount)

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

QTableView * getFrozenTable()

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

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

int saveStateTable(QString path)

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

int restoreStateTable(QString path)

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

QString getPathLocation()

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

QString getErrorMessage()

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

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

void setTitle(QString title)

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

void setPrintHtml(QString textHtml)

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

void setAlignColumn(QVector <int> align)

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

void setVAlignColumn(QVector <int> valign)

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

 

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

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

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()

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

Вход: нет.

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

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

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

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

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

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

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

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

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

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. Позиция в векторе определяет номер колонки.

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

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

 

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

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

mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H  

#include <QMainWindow>

#include "qgebcomplextableview.h"

#include <QStandardItemModel>

 

class MainWindow : public QMainWindow {

    Q_OBJECT

public:

    MainWindow(QWidget *parent = 0);

    ~MainWindow();  

private:

    void BuildHeaderModel(QStandardItemModel& headerModel);

    QgebComplexTableView *complexTableView;

};

#endif // MAINWINDOW_H

 

Mainwindow.cpp

#include "mainwindow.h"

#include <QVBoxLayout>

#include <QHBoxLayout>

 

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent)

{

    if (objectName().isEmpty())

        setObjectName(tr("MainWindow"));

    //формируем представление главного окна

    QWidget * centralWidget = new QWidget(this);

    centralWidget->setObjectName(tr("centralWidget"));

    setCentralWidget(centralWidget);  

    QGridLayout * gridLayout = new QGridLayout;

    centralWidget->setLayout(gridLayout);  

    //создаем модель заголовка

    QStandardItemModel *headerModel = new QStandardItemModel;

    //вызываем функцию формирования заголовка

    BuildHeaderModel(*headerModel);  

    //создаем таблицу

    complexTableView = new QgebComplexTableView(this);

    complexTableView->setObjectName("ComplexTableView");  //объектное имя таблицы

    complexTableView->setVisible(true);

    complexTableView->setSortingEnabled(true);  

    //передаем в класс модель заголовка (должна быть передана до установки непрокручиваемых колонок)

    complexTableView->setHeaderModel(headerModel);

    //устанавливаем модель данных

    QStandardItemModel * stm = new QStandardItemModel;

    complexTableView->setModel(stm);  

    //строим для примера таблицу в 9 колонок и 15 рядов

    complexTableView->model()->insertColumns(0,9, QModelIndex());

    complexTableView->model()->insertRows(0,15, QModelIndex());

    //задаем вектора для размещения признаков выравнивания для представления таблицы

    //на печати и в HTML файле

    //вектор для хранения значений горизонтального выравнивания в колонках

    QVector <int> alignColumnText;

    //вектор для хранения значений вертикального выравнивания в колонках

    QVector <int> valignColumnText;

    //заполняем таблицу

    for (int row=0; row<complexTableView->model()->rowCount(QModelIndex()); ++row)

    {

        for (int col=0; col<complexTableView->model()->columnCount(QModelIndex()); ++col)

        {

            if ( row == 0 )

            {

                //здесь для примера устанавливаем явно, если это не сделать, то умолчанию (left и top)

                //устанавливаем для всех колонок значение горизонтального и вертикального 

                //выравнивания

                //при представлении таблицы на печати и в HTML файле

                //(делаем один раз)

                alignColumnText.append(Qt::AlignHCenter);

                valignColumnText.append(Qt::AlignVCenter);

            }

            QModelIndex index = complexTableView->model()->index(row, col, QModelIndex());

            //в строке 2 колонка 1 вводим более сложную информацию из 4-х строк, чтобы показать

            //возможности выравнивания

            if ( (row==2) && (col==1) )

            {

                QString ss = QString::number(row)+"_"+QString::number(col);

                ss = ss + "\n" + ss + "\n" + ss + "\n" + ss;

                complexTableView->model()->setData(index, QVariant(ss));

            }

            else

                //стандартная информация, помещаемая в ячейку тела таблицы

                complexTableView->model()->setData(index, QVariant(QString::number(row)+"_"+QString::number(col)));

        }

    }  

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

    //в HTML файле

    complexTableView->setAlignColumn(alignColumnText);

    complexTableView->setVAlignColumn(valignColumnText);  

    //делаем левые две колонки не прокручиваемыми

    complexTableView->setFrozenColumn(2);  

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

    //устанавливаем для вертикального заголовка изменение высоты в зависимости от данных

    complexTableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);

    //получаем не прокручиваемую ячейку и устанавливаем для ее вертикального заголовка

    //изменение высоты в зависимости от данных

    complexTableView->getFrozenTable()->verticalHeader()->  

                                                                            setResizeMode(QHeaderView::ResizeToContents);  

    //разрешаем в случае необходимости горизонтальную и вертикальную прокрутку

    complexTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    complexTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);  

    //восстанавливаем сохраненные значения

    complexTableView->restoreStateTable("c:/complexTableView.xml");  

    //размещаем таблицу

    gridLayout->addWidget(complexTableView, 0, 0);

}

 

MainWindow::~MainWindow()

{

    int ret = complexTableView->saveStateTable("c:/complexTableView.xml");

    //проверяем, успешно ли сохранились параметры таблицы

    if ( ret != 0 )

        QMessageBox::critical(this, tr("Error"), tr("Ошибка сохранения параметров таблицы. Код: ")  

                                                                             + QString::number(ret), QMessageBox::Ok);

    //уничтожаем таблицу

    delete complexTableView;

}

 

/*

  Построение заголовка таблицы

*/

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