File indexing completed on 2024-05-19 05:44:23

0001 /*
0002     SPDX-FileCopyrightText: 2020 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "costheaderview.h"
0008 
0009 #include <QDebug>
0010 #include <QEvent>
0011 #include <QMenu>
0012 #include <QPainter>
0013 #include <QScopedValueRollback>
0014 
0015 #include <cmath>
0016 
0017 CostHeaderView::CostHeaderView(QWidget* parent)
0018     : QHeaderView(Qt::Horizontal, parent)
0019 {
0020 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
0021     setSectionsMovable(true);
0022     setFirstSectionMovable(false);
0023 #endif
0024     setDefaultSectionSize(100);
0025     setStretchLastSection(false);
0026     connect(this, &QHeaderView::sectionCountChanged, this, [this]() { resizeColumns(false); });
0027     connect(this, &QHeaderView::sectionResized, this, [this](int index, int oldSize, int newSize) {
0028         if (m_isResizing)
0029             return;
0030         QScopedValueRollback<bool> guard(m_isResizing, true);
0031         if (index != 0) {
0032             // give/take space from first column
0033             resizeSection(0, sectionSize(0) - (newSize - oldSize));
0034         } else {
0035             // distribute space across all columns
0036             // use actual width as oldSize/newSize isn't reliable here
0037             const auto numSections = count();
0038             int usedWidth = 0;
0039             for (int i = 0; i < numSections; ++i)
0040                 usedWidth += sectionSize(i);
0041             const auto diff = usedWidth - width();
0042             const auto numVisibleSections = numSections - hiddenSectionCount();
0043             if (numVisibleSections == 0)
0044                 return;
0045 
0046             const auto diffPerSection = diff / numVisibleSections;
0047             const auto extraDiff = diff % numVisibleSections;
0048             for (int i = 1; i < numSections; ++i) {
0049                 if (isSectionHidden(i)) {
0050                     continue;
0051                 }
0052                 auto newSize = sectionSize(i) - diffPerSection;
0053                 if (i == numSections - 1)
0054                     newSize -= extraDiff;
0055                 resizeSection(i, newSize);
0056             }
0057         }
0058     });
0059 
0060     setContextMenuPolicy(Qt::CustomContextMenu);
0061     connect(this, &QHeaderView::customContextMenuRequested, this, [this](const QPoint& pos) {
0062         const auto numSections = count();
0063 
0064         QMenu menu;
0065         auto resetSizes = menu.addAction(tr("Reset Column Sizes"));
0066         connect(resetSizes, &QAction::triggered, this, [this]() { resizeColumns(true); });
0067 
0068         if (numSections > 1) {
0069             auto* subMenu = menu.addMenu(tr("Visible Columns"));
0070             for (int i = 1; i < numSections; ++i) {
0071                 auto* action = subMenu->addAction(model()->headerData(i, Qt::Horizontal).toString());
0072                 action->setCheckable(true);
0073                 action->setChecked(!isSectionHidden(i));
0074                 connect(action, &QAction::toggled, this, [this, i](bool visible) { setSectionHidden(i, !visible); });
0075             }
0076         }
0077 
0078         menu.exec(mapToGlobal(pos));
0079     });
0080 }
0081 
0082 CostHeaderView::~CostHeaderView() = default;
0083 
0084 void CostHeaderView::resizeEvent(QResizeEvent* event)
0085 {
0086     QHeaderView::resizeEvent(event);
0087     resizeColumns(false);
0088 }
0089 
0090 void CostHeaderView::resizeColumns(bool reset)
0091 {
0092     const auto numColumns = count();
0093     if (!numColumns) {
0094         return;
0095     }
0096 
0097     QScopedValueRollback<bool> guard(m_isResizing, true);
0098     auto availableWidth = width();
0099     const auto defaultSize = defaultSectionSize();
0100 
0101     for (int i = numColumns - 1; i >= 0; --i) {
0102         if (i == 0) {
0103             resizeSection(i, std::max(availableWidth, defaultSize));
0104         } else if (reset) {
0105             resizeSection(i, defaultSize);
0106         }
0107         if (!isSectionHidden(i)) {
0108             availableWidth -= sectionSize(i);
0109         }
0110     }
0111 }
0112 
0113 #include "moc_costheaderview.cpp"