MultiLevelHeaderView.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. #include "MultiLevelHeaderView.h"
  2. #include <QAbstractTableModel>
  3. #include <QMap>
  4. #include <QPainter>
  5. #include <QMouseEvent>
  6. #include <QVariant>
  7. #include <QBrush>
  8. #include <qdrawutil.h>
  9. #include <set>
  10. /**
  11. *
  12. * QTableView tableView;
  13. auto pView = &tableView;
  14. pView->setContextMenuPolicy(Qt::CustomContextMenu);
  15. bool horizontal = false;
  16. pView->setContextMenuPolicy(Qt::CustomContextMenu);
  17. bool horizontal = true;
  18. if (horizontal) {
  19. auto pHeader = new MultiLevelHeaderView(Qt::Horizontal, 3, 8, pView);
  20. pHeader->setCellSpan(0, 0, 1, 4);
  21. pHeader->setCellSpan(0, 4, 1, 4);
  22. pHeader->setCellSpan(1, 0, 1, 2);
  23. pHeader->setCellSpan(1, 2, 1, 2);
  24. pHeader->setCellSpan(1, 4, 1, 2);
  25. pHeader->setCellSpan(1, 6, 1, 2);
  26. for (int i = 0; i < 8; i++) {
  27. pHeader->setCellSpan(2, i, 1, 1);
  28. }
  29. // 一级
  30. pHeader->setCellText(0, 0, QString(u8"横向尺寸"));
  31. pHeader->setCellText(0, 4, QString(u8"纵向尺寸"));
  32. // 二级
  33. pHeader->setCellText(1, 0, QStringLiteral("极耳宽度"));
  34. pHeader->setCellText(1, 2, QStringLiteral("极耳高度"));
  35. pHeader->setCellText(1, 4, QStringLiteral("极片宽度"));
  36. pHeader->setCellText(1, 6, QStringLiteral("极耳间距"));
  37. // 三级
  38. pHeader->setCellText(2, 0, QStringLiteral("CCD测量值"));
  39. pHeader->setCellText(2, 1, QStringLiteral("真值"));
  40. pHeader->setCellText(2, 2, QStringLiteral("CCD测量值"));
  41. pHeader->setCellText(2, 3, QStringLiteral("真值"));
  42. pHeader->setCellText(2, 4, QStringLiteral("CCD测量值"));
  43. pHeader->setCellText(2, 5, QStringLiteral("真值"));
  44. pHeader->setCellText(2, 6, QStringLiteral("CCD测量值"));
  45. pHeader->setCellText(2, 7, QStringLiteral("真值"));
  46. pHeader->setMinimumHeight(90);
  47. for (int i = 0; i < 3; ++i)
  48. pHeader->setRowHeight(i, 30);
  49. // m_pHeader->setMinimumHeight(60);
  50. pHeader->setSectionsClickable(false);
  51. pHeader->setCellBackgroundColor(0, 0, 0xffcfcf);
  52. pHeader->setCellBackgroundColor(0, 4, 0xcfcfcf);
  53. pHeader->setCellBackgroundColor(1, 0, 0xcfcfcf);
  54. pHeader->setCellBackgroundColor(1, 2, 0xcfcfcf);
  55. pHeader->setCellBackgroundColor(1, 4, 0xcfcfcf);
  56. pHeader->setCellBackgroundColor(1, 6, 0xcfcfcf);
  57. for (int i = 0; i < 8; i++) {
  58. pHeader->setCellBackgroundColor(2, i, 0xcfcfcf);
  59. }
  60. int rowCount = 10;
  61. auto m_pDataModel = new QStandardItemModel;
  62. for (int i = 0; i < rowCount; i++) {
  63. QList<QStandardItem *> items;
  64. for (int j = 0; j < 8; j++) {
  65. items.append(new QStandardItem);
  66. }
  67. m_pDataModel->appendRow(items);
  68. }
  69. pView->setModel(m_pDataModel);
  70. pView->setHorizontalHeader(pHeader);
  71. } else {
  72. auto pHeader = new MultiLevelHeaderView(Qt::Vertical, 8, 3, pView);
  73. pHeader->setCellSpan(0, 0, 4, 1);
  74. pHeader->setCellSpan(4, 0, 4, 1);
  75. pHeader->setCellSpan(0, 1, 2, 1);
  76. pHeader->setCellSpan(2, 1, 2, 1);
  77. pHeader->setCellSpan(4, 1, 2, 1);
  78. pHeader->setCellSpan(6, 1, 2, 1);
  79. for (int i = 0; i < 8; i++) {
  80. pHeader->setCellSpan(i, 2, 1, 1);
  81. }
  82. // 一级
  83. pHeader->setCellText(0, 0, QString(u8"横\n向\n尺\n寸"));
  84. pHeader->setCellText(4, 0, QString(u8"纵\n向\n尺\n寸"));
  85. // 二级
  86. pHeader->setCellText(0, 1, QStringLiteral("极耳宽度"));
  87. pHeader->setCellText(2, 1, QStringLiteral("极耳高度"));
  88. pHeader->setCellText(4, 1, QStringLiteral("极片宽度"));
  89. pHeader->setCellText(6, 1, QStringLiteral("极耳间距"));
  90. // 三级
  91. pHeader->setCellText(0, 2, QStringLiteral("CCD测量值"));
  92. pHeader->setCellText(1, 2, QStringLiteral("真值"));
  93. pHeader->setCellText(2, 2, QStringLiteral("CCD测量值"));
  94. pHeader->setCellText(3, 2, QStringLiteral("真值"));
  95. pHeader->setCellText(4, 2, QStringLiteral("CCD测量值"));
  96. pHeader->setCellText(5, 2, QStringLiteral("真值"));
  97. pHeader->setCellText(6, 2, QStringLiteral("CCD测量值"));
  98. pHeader->setCellText(7, 2, QStringLiteral("真值"));
  99. pHeader->setMinimumHeight(90);
  100. pHeader->setMinimumWidth(30);
  101. for (int i = 0; i < 3; ++i)
  102. pHeader->setColumnWidth(i, 30);
  103. for (int i = 0; i < 8; ++i)
  104. pHeader->setRowHeight(i, 30);
  105. // m_pHeader->setMinimumHeight(60);
  106. pHeader->setSectionsClickable(false);
  107. int rowCount = 8;
  108. auto m_pDataModel = new QStandardItemModel;
  109. for (int i = 0; i < rowCount; i++) {
  110. QList<QStandardItem *> items;
  111. for (int j = 0; j < 6; j++) {
  112. items.append(new QStandardItem);
  113. }
  114. m_pDataModel->appendRow(items);
  115. }
  116. pView->setModel(m_pDataModel);
  117. pView->setVerticalHeader(pHeader);
  118. }
  119. */
  120. struct Cell
  121. {
  122. int row = 0;
  123. int column = 0;
  124. bool operator<(const Cell &oth) const
  125. {
  126. if (row < oth.row)
  127. return true;
  128. if (row == oth.row)
  129. return column < oth.column;
  130. return false;
  131. }
  132. };
  133. class MultiLevelHeaderModel : public QAbstractTableModel
  134. {
  135. public:
  136. MultiLevelHeaderModel(Qt::Orientation orientation, int rows, int cols, QObject *parent = 0);
  137. virtual ~MultiLevelHeaderModel();
  138. public:
  139. // override
  140. virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
  141. virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
  142. virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
  143. virtual QVariant data(const QModelIndex &index, int role) const override;
  144. virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
  145. virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
  146. void setRowHeight(int row, int size);
  147. int getRowHeight(int row) const;
  148. void setColumnWidth(int col, int size);
  149. int getColumnWidth(int col) const;
  150. void setRootCell(int row, int column, int rootRow, int rootColumn);
  151. bool getRootCell(int row, int column, int &rootCellRow, int &rootCellColumn) const;
  152. private:
  153. Qt::Orientation m_orientation;
  154. int m_rowCount;
  155. int m_columnCount;
  156. std::vector<int> m_rowSizes;
  157. std::vector<int> m_columnSizes;
  158. QMap<Cell, QMap<int, QVariant>> m_data;
  159. QMap<Cell, Cell> m_rootCellMap;
  160. };
  161. MultiLevelHeaderModel::MultiLevelHeaderModel(Qt::Orientation orientation, int rows, int cols, QObject *parent)
  162. : QAbstractTableModel(parent), m_orientation(orientation), m_rowCount(rows), m_columnCount(cols)
  163. {
  164. m_rowSizes.resize(rows, 0);
  165. m_columnSizes.resize(cols, 0);
  166. }
  167. MultiLevelHeaderModel::~MultiLevelHeaderModel() { }
  168. QModelIndex MultiLevelHeaderModel::index(int row, int column, const QModelIndex &parent) const
  169. {
  170. if (!hasIndex(row, column, parent))
  171. return QModelIndex();
  172. return createIndex(row, column, nullptr);
  173. }
  174. int MultiLevelHeaderModel::rowCount(const QModelIndex &parent) const
  175. {
  176. return m_rowCount;
  177. }
  178. int MultiLevelHeaderModel::columnCount(const QModelIndex &parent) const
  179. {
  180. return m_columnCount;
  181. }
  182. QVariant MultiLevelHeaderModel::data(const QModelIndex &index, int role) const
  183. {
  184. if (!index.isValid())
  185. return QVariant();
  186. if (index.row() >= m_rowCount || index.row() < 0 || index.column() >= m_columnCount || index.column() < 0)
  187. return QVariant();
  188. auto it = m_data.find({ index.row(), index.column() });
  189. if (it != m_data.end()) {
  190. auto it2 = it.value().find(role);
  191. if (it2 != it.value().end())
  192. return it2.value();
  193. }
  194. // default value
  195. if (role == Qt::BackgroundRole)
  196. return QColor(0xcfcfcf);
  197. if (role == Qt::SizeHintRole) {
  198. return QSize(m_columnSizes[index.column()], m_rowSizes[index.row()]);
  199. }
  200. return QVariant();
  201. }
  202. bool MultiLevelHeaderModel::setData(const QModelIndex &index, const QVariant &value, int role)
  203. {
  204. if (index.isValid()) {
  205. QVariant value2;
  206. if (role == COLUMN_SPAN_ROLE) {
  207. int col = index.column();
  208. int span = value.toInt();
  209. if (span > 0) // span size should be more than 1, else nothing to do
  210. {
  211. if (col + span - 1 >= m_columnCount) // span size should be less than whole columns,
  212. span = m_columnCount - col;
  213. value2 = span;
  214. }
  215. } else if (role == ROW_SPAN_ROLE) {
  216. int row = index.row();
  217. int span = value.toInt();
  218. if (span > 0) // span size should be more than 1, else nothing to do
  219. {
  220. if (row + span - 1 >= m_rowCount)
  221. span = m_rowCount - row;
  222. value2 = span;
  223. }
  224. } else {
  225. value2 = value;
  226. }
  227. if (value.isValid()) {
  228. if (role == Qt::SizeHintRole) {
  229. m_columnSizes[index.column()] = value.toSize().width();
  230. m_rowSizes[index.row()] = value.toSize().height();
  231. } else {
  232. auto &map = m_data[{ index.row(), index.column() }];
  233. map.insert(role, value2);
  234. }
  235. }
  236. return true;
  237. }
  238. return false;
  239. }
  240. Qt::ItemFlags MultiLevelHeaderModel::flags(const QModelIndex &index) const
  241. {
  242. return Qt::NoItemFlags | QAbstractTableModel::flags(index);
  243. }
  244. void MultiLevelHeaderModel::setRowHeight(int row, int size)
  245. {
  246. if (row >= 0 && row < m_rowCount) {
  247. m_rowSizes[row] = size;
  248. emit dataChanged(index(row, 0), index(row, m_columnCount - 1), QVector<int>() << Qt::SizeHintRole);
  249. }
  250. }
  251. int MultiLevelHeaderModel::getRowHeight(int row) const
  252. {
  253. if (row >= 0 && row < m_rowCount)
  254. return m_rowSizes[row];
  255. return 0;
  256. }
  257. void MultiLevelHeaderModel::setColumnWidth(int col, int size)
  258. {
  259. if (col >= 0 && col < m_columnCount) {
  260. m_columnSizes[col] = size;
  261. emit dataChanged(index(0, col), index(m_rowCount - 1, col), QVector<int>() << Qt::SizeHintRole);
  262. }
  263. }
  264. int MultiLevelHeaderModel::getColumnWidth(int col) const
  265. {
  266. if (col >= 0 && col < m_columnCount)
  267. return m_columnSizes[col];
  268. return 0;
  269. }
  270. void MultiLevelHeaderModel::setRootCell(int row, int column, int rootRow, int rootColumn)
  271. {
  272. Cell c { row, column };
  273. auto it = m_rootCellMap.find(c);
  274. assert(it == m_rootCellMap.end());
  275. Cell rc { rootRow, rootColumn };
  276. m_rootCellMap.insert(c, rc);
  277. }
  278. bool MultiLevelHeaderModel::getRootCell(int row, int column, int &rootCellRow, int &rootCellColumn) const
  279. {
  280. Cell c { row, column };
  281. auto it = m_rootCellMap.find(c);
  282. if (it == m_rootCellMap.end())
  283. return false;
  284. rootCellRow = it.value().row;
  285. rootCellColumn = it.value().column;
  286. return true;
  287. }
  288. MultiLevelHeaderView::MultiLevelHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget *parent)
  289. : QHeaderView(orientation, parent)
  290. {
  291. // create header model
  292. MultiLevelHeaderModel *m = new MultiLevelHeaderModel(orientation, rows, columns);
  293. // set default size of item
  294. if (orientation == Qt::Horizontal) {
  295. for (int row = 0; row < rows; ++row)
  296. m->setRowHeight(row, 20);
  297. for (int col = 0; col < columns; ++col)
  298. m->setColumnWidth(col, defaultSectionSize());
  299. } else {
  300. for (int row = 0; row < rows; ++row)
  301. m->setRowHeight(row, defaultSectionSize());
  302. for (int col = 0; col < columns; ++col)
  303. m->setColumnWidth(col, defaultSectionSize());
  304. }
  305. setModel(m);
  306. connect(this, SIGNAL(sectionResized(int, int, int)), this, SLOT(onSectionResized(int, int, int)));
  307. }
  308. MultiLevelHeaderView::~MultiLevelHeaderView()
  309. {
  310. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  311. if (m)
  312. delete m;
  313. setModel(nullptr);
  314. }
  315. void MultiLevelHeaderView::setRowHeight(int row, int rowHeight)
  316. {
  317. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  318. m->setRowHeight(row, rowHeight);
  319. if (orientation() == Qt::Vertical)
  320. resizeSection(row, rowHeight);
  321. }
  322. void MultiLevelHeaderView::setColumnWidth(int col, int colWidth)
  323. {
  324. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  325. m->setColumnWidth(col, colWidth);
  326. if (orientation() == Qt::Horizontal)
  327. resizeSection(col, colWidth);
  328. }
  329. void MultiLevelHeaderView::setCellData(int row, int column, int role, const QVariant &value)
  330. {
  331. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  332. m->setData(m->index(row, column), value, role);
  333. }
  334. void MultiLevelHeaderView::setCellSpan(int row, int column, int rowSpanCount, int columnSpanCount)
  335. {
  336. assert(rowSpanCount > 0);
  337. assert(columnSpanCount > 0);
  338. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  339. QModelIndex idx = m->index(row, column);
  340. m->setData(idx, rowSpanCount, ROW_SPAN_ROLE);
  341. m->setData(idx, columnSpanCount, COLUMN_SPAN_ROLE);
  342. int lastRow = row + rowSpanCount;
  343. int lastCol = column + columnSpanCount;
  344. for (int i = row; i < lastRow; ++i) {
  345. for (int j = column; j < lastCol; ++j) {
  346. m->setRootCell(i, j, row, column);
  347. }
  348. }
  349. }
  350. void MultiLevelHeaderView::setCellBackgroundColor(int row, int column, const QColor &color)
  351. {
  352. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  353. m->setData(m->index(row, column), color, Qt::BackgroundRole);
  354. }
  355. void MultiLevelHeaderView::setCellForegroundColor(int row, int column, const QColor &color)
  356. {
  357. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  358. m->setData(m->index(row, column), color, Qt::ForegroundRole);
  359. }
  360. void MultiLevelHeaderView::setCellText(int row, int column, const QString &text)
  361. {
  362. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  363. m->setData(m->index(row, column), text, Qt::DisplayRole);
  364. }
  365. void MultiLevelHeaderView::mousePressEvent(QMouseEvent *event)
  366. {
  367. QHeaderView::mousePressEvent(event);
  368. QPoint pos = event->pos();
  369. QModelIndex index = indexAt(pos);
  370. const int orient = orientation();
  371. if (index.isValid()) {
  372. int beginSection = -1;
  373. int endSection = -1;
  374. int numbers = 0;
  375. numbers = getSectionRange(index, &beginSection, &endSection);
  376. if (numbers > 0) {
  377. emit sectionPressed(beginSection, endSection);
  378. return;
  379. } else {
  380. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
  381. const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
  382. int logicalIdx = (orient == Qt::Horizontal) ? index.column() : index.row();
  383. int curLevel = (orient == Qt::Horizontal) ? index.row() : index.column();
  384. for (int i = 0; i < levelCount; ++i) {
  385. QModelIndex cellIndex = (orient == Qt::Horizontal) ? m->index(i, logicalIdx) : m->index(logicalIdx, i);
  386. numbers = getSectionRange(cellIndex, &beginSection, &endSection);
  387. if (numbers > 0) {
  388. if (beginSection <= logicalIdx && logicalIdx <= endSection) {
  389. int beginLevel = (orient == Qt::Horizontal) ? cellIndex.row() : cellIndex.column();
  390. QVariant levelSpanCnt =
  391. cellIndex.data((orient == Qt::Horizontal) ? ROW_SPAN_ROLE : COLUMN_SPAN_ROLE);
  392. if (!levelSpanCnt.isValid())
  393. continue;
  394. int endLevel = beginLevel + levelSpanCnt.toInt() - 1;
  395. if (beginLevel <= curLevel && curLevel <= endLevel) {
  396. emit sectionPressed(beginSection, endSection);
  397. break;
  398. }
  399. }
  400. }
  401. }
  402. }
  403. }
  404. }
  405. QModelIndex MultiLevelHeaderView::indexAt(const QPoint &pos) const
  406. {
  407. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
  408. const int orient = orientation();
  409. const int ROWS = m->rowCount();
  410. const int COLS = m->columnCount();
  411. int logicalIdx = logicalIndexAt(pos);
  412. if (orient == Qt::Horizontal) {
  413. int dY = 0;
  414. for (int row = 0; row < ROWS; ++row) {
  415. dY += m->getRowHeight(row);
  416. if (pos.y() <= dY) {
  417. QModelIndex cellIndex = m->index(row, logicalIdx);
  418. return cellIndex;
  419. }
  420. }
  421. } else {
  422. int dX = 0;
  423. for (int col = 0; col < COLS; ++col) {
  424. dX += m->getColumnWidth(col);
  425. if (pos.x() <= dX) {
  426. QModelIndex cellIndex = m->index(logicalIdx, col);
  427. return cellIndex;
  428. }
  429. }
  430. }
  431. return QModelIndex();
  432. }
  433. std::set<Cell> getCellsToBeDrawn(const MultiLevelHeaderView *view, const MultiLevelHeaderModel *m, int orient,
  434. int levelCount, int logicalIdx)
  435. {
  436. std::set<Cell> cellsToBeDrawn;
  437. for (int i = 0; i < levelCount; ++i) {
  438. int row = i, column = logicalIdx;
  439. if (orient == Qt::Vertical)
  440. std::swap(row, column);
  441. int rootRow, rootCol;
  442. if (m->getRootCell(row, column, rootRow, rootCol))
  443. cellsToBeDrawn.insert({ rootRow, rootCol });
  444. }
  445. return cellsToBeDrawn;
  446. }
  447. void MultiLevelHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIdx) const
  448. {
  449. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
  450. const int orient = orientation();
  451. const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
  452. std::set<Cell> cellsToBeDrawn = getCellsToBeDrawn(this, m, orient, levelCount, logicalIdx);
  453. for (const auto &cell : cellsToBeDrawn) {
  454. QRect sectionRect = getCellRect(cell.row, cell.column);
  455. // draw section with style
  456. QStyleOptionHeader sectionStyle;
  457. initStyleOption(&sectionStyle);
  458. sectionStyle.textAlignment = Qt::AlignCenter;
  459. sectionStyle.iconAlignment = Qt::AlignVCenter;
  460. // sectionStyle.section = logicalIdx;
  461. QModelIndex cellIndex = m->index(cell.row, cell.column);
  462. sectionStyle.text = cellIndex.data(Qt::DisplayRole).toString();
  463. sectionStyle.rect = sectionRect;
  464. // file background or foreground color of the cell
  465. QVariant bg = cellIndex.data(Qt::BackgroundRole);
  466. QVariant fg = cellIndex.data(Qt::ForegroundRole);
  467. if (bg.canConvert(QVariant::Brush)) {
  468. sectionStyle.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(bg));
  469. sectionStyle.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(bg));
  470. }
  471. if (fg.canConvert(QVariant::Brush)) {
  472. sectionStyle.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(fg));
  473. }
  474. painter->save();
  475. qDrawShadePanel(painter, sectionStyle.rect, sectionStyle.palette, false, 1,
  476. &sectionStyle.palette.brush(QPalette::Button));
  477. style()->drawControl(QStyle::CE_HeaderLabel, &sectionStyle, painter);
  478. painter->restore();
  479. }
  480. }
  481. QSize MultiLevelHeaderView::sectionSizeFromContents(int logicalIdx) const
  482. {
  483. const MultiLevelHeaderModel *m = static_cast<const MultiLevelHeaderModel *>(this->model());
  484. const int orient = orientation();
  485. const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
  486. int w = 0, h = 0;
  487. if (orient == Qt::Horizontal) {
  488. w = m->getColumnWidth(logicalIdx);
  489. for (int i = 0; i < levelCount; ++i) {
  490. h += m->getRowHeight(i);
  491. }
  492. } else {
  493. for (int i = 0; i < levelCount; ++i) {
  494. w += m->getColumnWidth(i);
  495. }
  496. h = m->getRowHeight(logicalIdx);
  497. }
  498. return QSize(w, h);
  499. }
  500. QModelIndex MultiLevelHeaderView::columnSpanIndex(const QModelIndex &currentIdx) const
  501. {
  502. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  503. const int curRow = currentIdx.row();
  504. const int curCol = currentIdx.column();
  505. int i = curCol;
  506. while (i >= 0) {
  507. QModelIndex spanIndex = m->index(curRow, i);
  508. QVariant span = spanIndex.data(COLUMN_SPAN_ROLE);
  509. if (span.isValid() && spanIndex.column() + span.toInt() - 1 >= curCol)
  510. return spanIndex;
  511. i--;
  512. }
  513. return QModelIndex();
  514. }
  515. QModelIndex MultiLevelHeaderView::rowSpanIndex(const QModelIndex &currentIdx) const
  516. {
  517. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  518. const int curRow = currentIdx.row();
  519. const int curCol = currentIdx.column();
  520. int i = curRow;
  521. while (i >= 0) {
  522. QModelIndex spanIndex = m->index(i, curCol);
  523. QVariant span = spanIndex.data(ROW_SPAN_ROLE);
  524. if (span.isValid() && spanIndex.row() + span.toInt() - 1 >= curRow)
  525. return spanIndex;
  526. i--;
  527. }
  528. return QModelIndex();
  529. }
  530. int MultiLevelHeaderView::columnSpanSize(int row, int from, int spanCount) const
  531. {
  532. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  533. int span = 0;
  534. for (int i = from; i < from + spanCount; ++i) {
  535. int colWidth = m->getColumnWidth(i);
  536. span += colWidth;
  537. }
  538. return span;
  539. }
  540. int MultiLevelHeaderView::rowSpanSize(int column, int from, int spanCount) const
  541. {
  542. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  543. int span = 0;
  544. for (int i = from; i < from + spanCount; ++i) {
  545. int rowHeight = m->getRowHeight(i);
  546. span += rowHeight;
  547. }
  548. return span;
  549. }
  550. bool MultiLevelHeaderView::getRootCell(int row, int column, int &rootCellRow, int &rootCellColumn) const
  551. {
  552. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
  553. return m->getRootCell(row, column, rootCellRow, rootCellColumn);
  554. }
  555. QRect MultiLevelHeaderView::getCellRect(int row, int column) const
  556. {
  557. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
  558. const int orient = orientation();
  559. QModelIndex cellIndex = m->index(row, column);
  560. auto colSpanVar = cellIndex.data(COLUMN_SPAN_ROLE);
  561. auto rowSpanVar = cellIndex.data(ROW_SPAN_ROLE);
  562. assert(colSpanVar.isValid() && rowSpanVar.isValid());
  563. int colSpan = colSpanVar.toInt();
  564. int rowSpan = rowSpanVar.toInt();
  565. int w = 0, h = 0, l = 0, t = 0;
  566. w = columnSpanSize(row, column, colSpan);
  567. h = rowSpanSize(column, row, rowSpan);
  568. if (orient == Qt::Horizontal) {
  569. l = sectionViewportPosition(column);
  570. for (int i = 0; i < row; ++i)
  571. t += m->getRowHeight(i);
  572. } else {
  573. for (int i = 0; i < column; ++i)
  574. l += m->getColumnWidth(i);
  575. t = sectionViewportPosition(row);
  576. }
  577. QRect rect(l, t, w, h);
  578. return rect;
  579. }
  580. /**
  581. * @return section numbers
  582. */
  583. int MultiLevelHeaderView::getSectionRange(QModelIndex &index, int *beginSection, int *endSection) const
  584. {
  585. int row = index.row(), column = index.column();
  586. int rootRow, rootCol;
  587. bool success = getRootCell(row, column, rootRow, rootCol);
  588. if (!success)
  589. return 0;
  590. const MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(model());
  591. QModelIndex rootIndex = m->index(rootRow, rootCol);
  592. if (orientation() == Qt::Horizontal) {
  593. int colSpanCnt = rootIndex.data(COLUMN_SPAN_ROLE).toInt();
  594. *beginSection = rootIndex.column();
  595. ;
  596. *endSection = *beginSection + colSpanCnt - 1;
  597. index = rootIndex;
  598. return colSpanCnt;
  599. } else {
  600. int rowSpanCnt = rootIndex.data(ROW_SPAN_ROLE).toInt();
  601. *beginSection = rootIndex.row();
  602. ;
  603. *endSection = *beginSection + rowSpanCnt - 1;
  604. index = rootIndex;
  605. return rowSpanCnt;
  606. }
  607. }
  608. void MultiLevelHeaderView::onSectionResized(int logicalIndex, int oldSize, int newSize)
  609. {
  610. MultiLevelHeaderModel *m = static_cast<MultiLevelHeaderModel *>(this->model());
  611. const int orient = orientation();
  612. const int levelCount = (orient == Qt::Horizontal) ? m->rowCount() : m->columnCount();
  613. if (orient == Qt::Horizontal) {
  614. m->setColumnWidth(logicalIndex, newSize);
  615. } else {
  616. m->setRowHeight(logicalIndex, newSize);
  617. }
  618. std::set<Cell> cellsToBeDrawn = getCellsToBeDrawn(this, m, orient, levelCount, logicalIndex);
  619. for (const auto &cell : cellsToBeDrawn) {
  620. QRect sectionRect = getCellRect(cell.row, cell.column);
  621. if (orient == Qt::Horizontal) {
  622. sectionRect.setWidth(viewport()->width() - sectionRect.left());
  623. } else {
  624. sectionRect.setHeight(viewport()->height() - sectionRect.top());
  625. }
  626. viewport()->update(sectionRect);
  627. }
  628. }