123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700 |
- #include "MultiLevelHeaderView.h"
- #include <QAbstractTableModel>
- #include <QMap>
- #include <QPainter>
- #include <QMouseEvent>
- #include <QVariant>
- #include <QBrush>
- #include <qdrawutil.h>
- #include <set>
- /**
- *
- * QTableView tableView;
- auto pView = &tableView;
- pView->setContextMenuPolicy(Qt::CustomContextMenu);
- bool horizontal = false;
- pView->setContextMenuPolicy(Qt::CustomContextMenu);
- bool horizontal = true;
- if (horizontal) {
- auto pHeader = new MultiLevelHeaderView(Qt::Horizontal, 3, 8, pView);
- pHeader->setCellSpan(0, 0, 1, 4);
- pHeader->setCellSpan(0, 4, 1, 4);
- pHeader->setCellSpan(1, 0, 1, 2);
- pHeader->setCellSpan(1, 2, 1, 2);
- pHeader->setCellSpan(1, 4, 1, 2);
- pHeader->setCellSpan(1, 6, 1, 2);
- for (int i = 0; i < 8; i++) {
- pHeader->setCellSpan(2, i, 1, 1);
- }
- // 一级
- pHeader->setCellText(0, 0, QString(u8"横向尺寸"));
- pHeader->setCellText(0, 4, QString(u8"纵向尺寸"));
- // 二级
- pHeader->setCellText(1, 0, QStringLiteral("极耳宽度"));
- pHeader->setCellText(1, 2, QStringLiteral("极耳高度"));
- pHeader->setCellText(1, 4, QStringLiteral("极片宽度"));
- pHeader->setCellText(1, 6, QStringLiteral("极耳间距"));
- // 三级
- pHeader->setCellText(2, 0, QStringLiteral("CCD测量值"));
- pHeader->setCellText(2, 1, QStringLiteral("真值"));
- pHeader->setCellText(2, 2, QStringLiteral("CCD测量值"));
- pHeader->setCellText(2, 3, QStringLiteral("真值"));
- pHeader->setCellText(2, 4, QStringLiteral("CCD测量值"));
- pHeader->setCellText(2, 5, QStringLiteral("真值"));
- pHeader->setCellText(2, 6, QStringLiteral("CCD测量值"));
- pHeader->setCellText(2, 7, QStringLiteral("真值"));
- pHeader->setMinimumHeight(90);
- for (int i = 0; i < 3; ++i)
- pHeader->setRowHeight(i, 30);
- // m_pHeader->setMinimumHeight(60);
- pHeader->setSectionsClickable(false);
- pHeader->setCellBackgroundColor(0, 0, 0xffcfcf);
- pHeader->setCellBackgroundColor(0, 4, 0xcfcfcf);
- pHeader->setCellBackgroundColor(1, 0, 0xcfcfcf);
- pHeader->setCellBackgroundColor(1, 2, 0xcfcfcf);
- pHeader->setCellBackgroundColor(1, 4, 0xcfcfcf);
- pHeader->setCellBackgroundColor(1, 6, 0xcfcfcf);
- for (int i = 0; i < 8; i++) {
- pHeader->setCellBackgroundColor(2, i, 0xcfcfcf);
- }
- int rowCount = 10;
- auto m_pDataModel = new QStandardItemModel;
- for (int i = 0; i < rowCount; i++) {
- QList<QStandardItem *> items;
- for (int j = 0; j < 8; j++) {
- items.append(new QStandardItem);
- }
- m_pDataModel->appendRow(items);
- }
- pView->setModel(m_pDataModel);
- pView->setHorizontalHeader(pHeader);
- } else {
- auto pHeader = new MultiLevelHeaderView(Qt::Vertical, 8, 3, pView);
- pHeader->setCellSpan(0, 0, 4, 1);
- pHeader->setCellSpan(4, 0, 4, 1);
- pHeader->setCellSpan(0, 1, 2, 1);
- pHeader->setCellSpan(2, 1, 2, 1);
- pHeader->setCellSpan(4, 1, 2, 1);
- pHeader->setCellSpan(6, 1, 2, 1);
- for (int i = 0; i < 8; i++) {
- pHeader->setCellSpan(i, 2, 1, 1);
- }
- // 一级
- pHeader->setCellText(0, 0, QString(u8"横\n向\n尺\n寸"));
- pHeader->setCellText(4, 0, QString(u8"纵\n向\n尺\n寸"));
- // 二级
- pHeader->setCellText(0, 1, QStringLiteral("极耳宽度"));
- pHeader->setCellText(2, 1, QStringLiteral("极耳高度"));
- pHeader->setCellText(4, 1, QStringLiteral("极片宽度"));
- pHeader->setCellText(6, 1, QStringLiteral("极耳间距"));
- // 三级
- pHeader->setCellText(0, 2, QStringLiteral("CCD测量值"));
- pHeader->setCellText(1, 2, QStringLiteral("真值"));
- pHeader->setCellText(2, 2, QStringLiteral("CCD测量值"));
- pHeader->setCellText(3, 2, QStringLiteral("真值"));
- pHeader->setCellText(4, 2, QStringLiteral("CCD测量值"));
- pHeader->setCellText(5, 2, QStringLiteral("真值"));
- pHeader->setCellText(6, 2, QStringLiteral("CCD测量值"));
- pHeader->setCellText(7, 2, QStringLiteral("真值"));
- pHeader->setMinimumHeight(90);
- pHeader->setMinimumWidth(30);
- for (int i = 0; i < 3; ++i)
- pHeader->setColumnWidth(i, 30);
- for (int i = 0; i < 8; ++i)
- pHeader->setRowHeight(i, 30);
- // m_pHeader->setMinimumHeight(60);
- pHeader->setSectionsClickable(false);
- int rowCount = 8;
- auto m_pDataModel = new QStandardItemModel;
- for (int i = 0; i < rowCount; i++) {
- QList<QStandardItem *> items;
- for (int j = 0; j < 6; j++) {
- items.append(new QStandardItem);
- }
- m_pDataModel->appendRow(items);
- }
- pView->setModel(m_pDataModel);
- pView->setVerticalHeader(pHeader);
- }
- */
- struct Cell
- {
- int row = 0;
- int column = 0;
- bool operator<(const Cell &oth) const
- {
- if (row < oth.row)
- return true;
- if (row == oth.row)
- return column < oth.column;
- return false;
- }
- };
- class MultiLevelHeaderModel : public QAbstractTableModel
- {
- public:
- MultiLevelHeaderModel(Qt::Orientation orientation, int rows, int cols, QObject *parent = 0);
- virtual ~MultiLevelHeaderModel();
- public:
- // override
- virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
- virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- virtual QVariant data(const QModelIndex &index, int role) const override;
- virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
- void setRowHeight(int row, int size);
- int getRowHeight(int row) const;
- void setColumnWidth(int col, int size);
- int getColumnWidth(int col) const;
- void setRootCell(int row, int column, int rootRow, int rootColumn);
- bool getRootCell(int row, int column, int &rootCellRow, int &rootCellColumn) const;
- private:
- Qt::Orientation m_orientation;
- int m_rowCount;
- int m_columnCount;
- std::vector<int> m_rowSizes;
- std::vector<int> m_columnSizes;
- QMap<Cell, QMap<int, QVariant>> m_data;
- QMap<Cell, Cell> m_rootCellMap;
- };
- MultiLevelHeaderModel::MultiLevelHeaderModel(Qt::Orientation orientation, int rows, int cols, QObject *parent)
- : QAbstractTableModel(parent), m_orientation(orientation), m_rowCount(rows), m_columnCount(cols)
- {
- m_rowSizes.resize(rows, 0);
- m_columnSizes.resize(cols, 0);
- }
- MultiLevelHeaderModel::~MultiLevelHeaderModel() { }
- QModelIndex MultiLevelHeaderModel::index(int row, int column, const QModelIndex &parent) const
- {
- if (!hasIndex(row, column, parent))
- return QModelIndex();
- return createIndex(row, column, nullptr);
- }
- int MultiLevelHeaderModel::rowCount(const QModelIndex &parent) const
- {
- return m_rowCount;
- }
- int MultiLevelHeaderModel::columnCount(const QModelIndex &parent) const
- {
- return m_columnCount;
- }
- QVariant MultiLevelHeaderModel::data(const QModelIndex &index, int role) const
- {
- if (!index.isValid())
- return QVariant();
- if (index.row() >= m_rowCount || index.row() < 0 || index.column() >= m_columnCount || index.column() < 0)
- return QVariant();
- auto it = m_data.find({ index.row(), index.column() });
- if (it != m_data.end()) {
- auto it2 = it.value().find(role);
- if (it2 != it.value().end())
- return it2.value();
- }
- // default value
- if (role == Qt::BackgroundRole)
- return QColor(0xcfcfcf);
- if (role == Qt::SizeHintRole) {
- return QSize(m_columnSizes[index.column()], m_rowSizes[index.row()]);
- }
- return QVariant();
- }
- bool MultiLevelHeaderModel::setData(const QModelIndex &index, const QVariant &value, int role)
- {
- if (index.isValid()) {
- QVariant value2;
- if (role == COLUMN_SPAN_ROLE) {
- int col = index.column();
- int span = value.toInt();
- if (span > 0) // span size should be more than 1, else nothing to do
- {
- if (col + span - 1 >= m_columnCount) // span size should be less than whole columns,
- span = m_columnCount - col;
- value2 = span;
- }
- } else if (role == ROW_SPAN_ROLE) {
- int row = index.row();
- int span = value.toInt();
- if (span > 0) // span size should be more than 1, else nothing to do
- {
- if (row + span - 1 >= m_rowCount)
- span = m_rowCount - row;
- value2 = span;
- }
- } else {
- value2 = value;
- }
- if (value.isValid()) {
- if (role == Qt::SizeHintRole) {
- m_columnSizes[index.column()] = value.toSize().width();
- m_rowSizes[index.row()] = value.toSize().height();
- } else {
- auto &map = m_data[{ index.row(), index.column() }];
- map.insert(role, value2);
- }
- }
- return true;
- }
- return false;
- }
- Qt::ItemFlags MultiLevelHeaderModel::flags(const QModelIndex &index) const
- {
- return Qt::NoItemFlags | QAbstractTableModel::flags(index);
- }
- void MultiLevelHeaderModel::setRowHeight(int row, int size)
- {
- if (row >= 0 && row < m_rowCount) {
- m_rowSizes[row] = size;
- emit dataChanged(index(row, 0), index(row, m_columnCount - 1), QVector<int>() << Qt::SizeHintRole);
- }
- }
- int MultiLevelHeaderModel::getRowHeight(int row) const
- {
- if (row >= 0 && row < m_rowCount)
- return m_rowSizes[row];
- return 0;
- }
- void MultiLevelHeaderModel::setColumnWidth(int col, int size)
- {
- if (col >= 0 && col < m_columnCount) {
- m_columnSizes[col] = size;
- emit dataChanged(index(0, col), index(m_rowCount - 1, col), QVector<int>() << Qt::SizeHintRole);
- }
- }
- int MultiLevelHeaderModel::getColumnWidth(int col) const
- {
- if (col >= 0 && col < m_columnCount)
- return m_columnSizes[col];
- return 0;
- }
- void MultiLevelHeaderModel::setRootCell(int row, int column, int rootRow, int rootColumn)
- {
- Cell c { row, column };
- auto it = m_rootCellMap.find(c);
- assert(it == m_rootCellMap.end());
- Cell rc { rootRow, rootColumn };
- m_rootCellMap.insert(c, rc);
- }
- bool MultiLevelHeaderModel::getRootCell(int row, int column, int &rootCellRow, int &rootCellColumn) const
- {
- Cell c { row, column };
- auto it = m_rootCellMap.find(c);
- if (it == m_rootCellMap.end())
- return false;
- rootCellRow = it.value().row;
- rootCellColumn = it.value().column;
- return true;
- }
- MultiLevelHeaderView::MultiLevelHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget *parent)
- : QHeaderView(orientation, parent)
- {
- // create header model
- MultiLevelHeaderModel *m = new MultiLevelHeaderModel(orientation, rows, columns);
- // set default size of item
- if (orientation == Qt::Horizontal) {
- for (int row = 0; row < rows; ++row)
- m->setRowHeight(row, 20);
- for (int col = 0; col < columns; ++col)
- m->setColumnWidth(col, defaultSectionSize());
- } else {
- for (int row = 0; row < rows; ++row)
- m->setRowHeight(row, defaultSectionSize());
- for (int col = 0; col < columns; ++col)
- m->setColumnWidth(col, defaultSectionSize());
- }
- setModel(m);
- connect(this, SIGNAL(sectionResized(int, int, int)), this, SLOT(onSectionResized(int, int, int)));
- }
- MultiLevelHeaderView::~MultiLevelHeaderView()
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- if (m)
- delete m;
- setModel(nullptr);
- }
- void MultiLevelHeaderView::setRowHeight(int row, int rowHeight)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- m->setRowHeight(row, rowHeight);
- if (orientation() == Qt::Vertical)
- resizeSection(row, rowHeight);
- }
- void MultiLevelHeaderView::setColumnWidth(int col, int colWidth)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- m->setColumnWidth(col, colWidth);
- if (orientation() == Qt::Horizontal)
- resizeSection(col, colWidth);
- }
- void MultiLevelHeaderView::setCellData(int row, int column, int role, const QVariant &value)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- m->setData(m->index(row, column), value, role);
- }
- void MultiLevelHeaderView::setCellSpan(int row, int column, int rowSpanCount, int columnSpanCount)
- {
- assert(rowSpanCount > 0);
- assert(columnSpanCount > 0);
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- QModelIndex idx = m->index(row, column);
- m->setData(idx, rowSpanCount, ROW_SPAN_ROLE);
- m->setData(idx, columnSpanCount, COLUMN_SPAN_ROLE);
- int lastRow = row + rowSpanCount;
- int lastCol = column + columnSpanCount;
- for (int i = row; i < lastRow; ++i) {
- for (int j = column; j < lastCol; ++j) {
- m->setRootCell(i, j, row, column);
- }
- }
- }
- void MultiLevelHeaderView::setCellBackgroundColor(int row, int column, const QColor &color)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- m->setData(m->index(row, column), color, Qt::BackgroundRole);
- }
- void MultiLevelHeaderView::setCellForegroundColor(int row, int column, const QColor &color)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- m->setData(m->index(row, column), color, Qt::ForegroundRole);
- }
- void MultiLevelHeaderView::setCellText(int row, int column, const QString &text)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- m->setData(m->index(row, column), text, Qt::DisplayRole);
- }
- void MultiLevelHeaderView::mousePressEvent(QMouseEvent *event)
- {
- QHeaderView::mousePressEvent(event);
- QPoint pos = event->pos();
- QModelIndex index = indexAt(pos);
- const int orient = orientation();
- if (index.isValid()) {
- int beginSection = -1;
- int endSection = -1;
- int numbers = 0;
- numbers = getSectionRange(index, &beginSection, &endSection);
- if (numbers > 0) {
- emit sectionPressed(beginSection, endSection);
- return;
- } else {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
- const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
- int logicalIdx = (orient == Qt::Horizontal) ? index.column() : index.row();
- int curLevel = (orient == Qt::Horizontal) ? index.row() : index.column();
- for (int i = 0; i < levelCount; ++i) {
- QModelIndex cellIndex = (orient == Qt::Horizontal) ? m->index(i, logicalIdx) : m->index(logicalIdx, i);
- numbers = getSectionRange(cellIndex, &beginSection, &endSection);
- if (numbers > 0) {
- if (beginSection <= logicalIdx && logicalIdx <= endSection) {
- int beginLevel = (orient == Qt::Horizontal) ? cellIndex.row() : cellIndex.column();
- QVariant levelSpanCnt =
- cellIndex.data((orient == Qt::Horizontal) ? ROW_SPAN_ROLE : COLUMN_SPAN_ROLE);
- if (!levelSpanCnt.isValid())
- continue;
- int endLevel = beginLevel + levelSpanCnt.toInt() - 1;
- if (beginLevel <= curLevel && curLevel <= endLevel) {
- emit sectionPressed(beginSection, endSection);
- break;
- }
- }
- }
- }
- }
- }
- }
- QModelIndex MultiLevelHeaderView::indexAt(const QPoint &pos) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
- const int orient = orientation();
- const int ROWS = m->rowCount();
- const int COLS = m->columnCount();
- int logicalIdx = logicalIndexAt(pos);
- if (orient == Qt::Horizontal) {
- int dY = 0;
- for (int row = 0; row < ROWS; ++row) {
- dY += m->getRowHeight(row);
- if (pos.y() <= dY) {
- QModelIndex cellIndex = m->index(row, logicalIdx);
- return cellIndex;
- }
- }
- } else {
- int dX = 0;
- for (int col = 0; col < COLS; ++col) {
- dX += m->getColumnWidth(col);
- if (pos.x() <= dX) {
- QModelIndex cellIndex = m->index(logicalIdx, col);
- return cellIndex;
- }
- }
- }
- return QModelIndex();
- }
- std::set<Cell> getCellsToBeDrawn(const MultiLevelHeaderView *view, const MultiLevelHeaderModel *m, int orient,
- int levelCount, int logicalIdx)
- {
- std::set<Cell> cellsToBeDrawn;
- for (int i = 0; i < levelCount; ++i) {
- int row = i, column = logicalIdx;
- if (orient == Qt::Vertical)
- std::swap(row, column);
- int rootRow, rootCol;
- if (m->getRootCell(row, column, rootRow, rootCol))
- cellsToBeDrawn.insert({ rootRow, rootCol });
- }
- return cellsToBeDrawn;
- }
- void MultiLevelHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIdx) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
- const int orient = orientation();
- const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
- std::set<Cell> cellsToBeDrawn = getCellsToBeDrawn(this, m, orient, levelCount, logicalIdx);
- for (const auto &cell : cellsToBeDrawn) {
- QRect sectionRect = getCellRect(cell.row, cell.column);
- // draw section with style
- QStyleOptionHeader sectionStyle;
- initStyleOption(§ionStyle);
- sectionStyle.textAlignment = Qt::AlignCenter;
- sectionStyle.iconAlignment = Qt::AlignVCenter;
- // sectionStyle.section = logicalIdx;
- QModelIndex cellIndex = m->index(cell.row, cell.column);
- sectionStyle.text = cellIndex.data(Qt::DisplayRole).toString();
- sectionStyle.rect = sectionRect;
- // file background or foreground color of the cell
- QVariant bg = cellIndex.data(Qt::BackgroundRole);
- QVariant fg = cellIndex.data(Qt::ForegroundRole);
- if (bg.canConvert(QVariant::Brush)) {
- sectionStyle.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(bg));
- sectionStyle.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(bg));
- }
- if (fg.canConvert(QVariant::Brush)) {
- sectionStyle.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(fg));
- }
- painter->save();
- qDrawShadePanel(painter, sectionStyle.rect, sectionStyle.palette, false, 1,
- §ionStyle.palette.brush(QPalette::Button));
- style()->drawControl(QStyle::CE_HeaderLabel, §ionStyle, painter);
- painter->restore();
- }
- }
- QSize MultiLevelHeaderView::sectionSizeFromContents(int logicalIdx) const
- {
- const MultiLevelHeaderModel *m = static_cast<const MultiLevelHeaderModel *>(this->model());
- const int orient = orientation();
- const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
- int w = 0, h = 0;
- if (orient == Qt::Horizontal) {
- w = m->getColumnWidth(logicalIdx);
- for (int i = 0; i < levelCount; ++i) {
- h += m->getRowHeight(i);
- }
- } else {
- for (int i = 0; i < levelCount; ++i) {
- w += m->getColumnWidth(i);
- }
- h = m->getRowHeight(logicalIdx);
- }
- return QSize(w, h);
- }
- QModelIndex MultiLevelHeaderView::columnSpanIndex(const QModelIndex ¤tIdx) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- const int curRow = currentIdx.row();
- const int curCol = currentIdx.column();
- int i = curCol;
- while (i >= 0) {
- QModelIndex spanIndex = m->index(curRow, i);
- QVariant span = spanIndex.data(COLUMN_SPAN_ROLE);
- if (span.isValid() && spanIndex.column() + span.toInt() - 1 >= curCol)
- return spanIndex;
- i--;
- }
- return QModelIndex();
- }
- QModelIndex MultiLevelHeaderView::rowSpanIndex(const QModelIndex ¤tIdx) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- const int curRow = currentIdx.row();
- const int curCol = currentIdx.column();
- int i = curRow;
- while (i >= 0) {
- QModelIndex spanIndex = m->index(i, curCol);
- QVariant span = spanIndex.data(ROW_SPAN_ROLE);
- if (span.isValid() && spanIndex.row() + span.toInt() - 1 >= curRow)
- return spanIndex;
- i--;
- }
- return QModelIndex();
- }
- int MultiLevelHeaderView::columnSpanSize(int row, int from, int spanCount) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- int span = 0;
- for (int i = from; i < from + spanCount; ++i) {
- int colWidth = m->getColumnWidth(i);
- span += colWidth;
- }
- return span;
- }
- int MultiLevelHeaderView::rowSpanSize(int column, int from, int spanCount) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- int span = 0;
- for (int i = from; i < from + spanCount; ++i) {
- int rowHeight = m->getRowHeight(i);
- span += rowHeight;
- }
- return span;
- }
- bool MultiLevelHeaderView::getRootCell(int row, int column, int &rootCellRow, int &rootCellColumn) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
- return m->getRootCell(row, column, rootCellRow, rootCellColumn);
- }
- QRect MultiLevelHeaderView::getCellRect(int row, int column) const
- {
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
- const int orient = orientation();
- QModelIndex cellIndex = m->index(row, column);
- auto colSpanVar = cellIndex.data(COLUMN_SPAN_ROLE);
- auto rowSpanVar = cellIndex.data(ROW_SPAN_ROLE);
- assert(colSpanVar.isValid() && rowSpanVar.isValid());
- int colSpan = colSpanVar.toInt();
- int rowSpan = rowSpanVar.toInt();
- int w = 0, h = 0, l = 0, t = 0;
- w = columnSpanSize(row, column, colSpan);
- h = rowSpanSize(column, row, rowSpan);
- if (orient == Qt::Horizontal) {
- l = sectionViewportPosition(column);
- for (int i = 0; i < row; ++i)
- t += m->getRowHeight(i);
- } else {
- for (int i = 0; i < column; ++i)
- l += m->getColumnWidth(i);
- t = sectionViewportPosition(row);
- }
- QRect rect(l, t, w, h);
- return rect;
- }
- /**
- * @return section numbers
- */
- int MultiLevelHeaderView::getSectionRange(QModelIndex &index, int *beginSection, int *endSection) const
- {
- int row = index.row(), column = index.column();
- int rootRow, rootCol;
- bool success = getRootCell(row, column, rootRow, rootCol);
- if (!success)
- return 0;
- const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
- QModelIndex rootIndex = m->index(rootRow, rootCol);
- if (orientation() == Qt::Horizontal) {
- int colSpanCnt = rootIndex.data(COLUMN_SPAN_ROLE).toInt();
- *beginSection = rootIndex.column();
- ;
- *endSection = *beginSection + colSpanCnt - 1;
- index = rootIndex;
- return colSpanCnt;
- } else {
- int rowSpanCnt = rootIndex.data(ROW_SPAN_ROLE).toInt();
- *beginSection = rootIndex.row();
- ;
- *endSection = *beginSection + rowSpanCnt - 1;
- index = rootIndex;
- return rowSpanCnt;
- }
- }
- void MultiLevelHeaderView::onSectionResized(int logicalIndex, int oldSize, int newSize)
- {
- MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
- const int orient = orientation();
- const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
- if (orient == Qt::Horizontal) {
- m->setColumnWidth(logicalIndex, newSize);
- } else {
- m->setRowHeight(logicalIndex, newSize);
- }
- std::set<Cell> cellsToBeDrawn = getCellsToBeDrawn(this, m, orient, levelCount, logicalIndex);
- for (const auto &cell : cellsToBeDrawn) {
- QRect sectionRect = getCellRect(cell.row, cell.column);
- if (orient == Qt::Horizontal) {
- sectionRect.setWidth(viewport()->width() - sectionRect.left());
- } else {
- sectionRect.setHeight(viewport()->height() - sectionRect.top());
- }
- viewport()->update(sectionRect);
- }
- }
|