File indexing completed on 2024-04-21 04:00:36

0001 /*
0002     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0003     SPDX-FileCopyrightText: 2023 David Redondo <kde@david-redondo.de>
0004 */
0005 
0006 #include "itembranchindicators.h"
0007 
0008 #include "kquickstyleitem_p.h"
0009 
0010 #include <Kirigami/Platform/PlatformTheme>
0011 
0012 #include <QAbstractItemModel>
0013 #include <QGuiApplication>
0014 #include <QStyle>
0015 #include <QStyleOption>
0016 
0017 ItemBranchIndicators::ItemBranchIndicators(QQuickItem *parent)
0018     : QQuickPaintedItem(parent)
0019 {
0020     if (auto theme = static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true))) {
0021         m_palette = theme->palette();
0022         connect(theme, &Kirigami::Platform::PlatformTheme::paletteChanged, this, [this](const QPalette &palette) {
0023             m_palette = palette;
0024             update();
0025         });
0026     }
0027 }
0028 
0029 void ItemBranchIndicators::updateParentChain()
0030 {
0031     const bool wasPainting = parentChain.size() != 0;
0032     parentChain.clear();
0033 
0034     // If we have children the indicator is drawn in the QML
0035     if (m_index.column() == 0) {
0036         auto index = m_index.model()->hasChildren(m_index) ? m_index.parent() : m_index;
0037         // if the TreeView's root index is set, don't go past it
0038         while (index.isValid() && (!m_rootIndex.isValid() || index != m_rootIndex)) {
0039             parentChain.push_back(index);
0040             index = index.parent();
0041         }
0042     }
0043 
0044     const auto elementWidth = KQuickStyleItem::style()->pixelMetric(QStyle::PM_TreeViewIndentation);
0045     setImplicitWidth(elementWidth * parentChain.size());
0046 
0047     if (wasPainting || !parentChain.empty()) {
0048         update();
0049     }
0050 }
0051 
0052 void ItemBranchIndicators::setRootIndex(const QModelIndex &new_root_index)
0053 {
0054     m_rootIndex = new_root_index;
0055     updateParentChain();
0056     Q_EMIT rootIndexChanged();
0057 }
0058 
0059 void ItemBranchIndicators::setModelIndex(const QModelIndex &new_index)
0060 {
0061     m_index = new_index;
0062     updateParentChain();
0063     Q_EMIT modelIndexChanged();
0064 }
0065 
0066 void ItemBranchIndicators::setSelected(bool selected)
0067 {
0068     if (m_selected == selected) {
0069         return;
0070     }
0071     m_selected = selected;
0072     update();
0073     Q_EMIT selectedChanged();
0074 }
0075 
0076 void ItemBranchIndicators::paint(QPainter *painter)
0077 {
0078     const auto elementWidth = KQuickStyleItem::style()->pixelMetric(QStyle::PM_TreeViewIndentation);
0079     QStyleOption styleOption;
0080     styleOption.state.setFlag(QStyle::State_Selected, m_selected);
0081     styleOption.state.setFlag(QStyle::State_Children, false);
0082     styleOption.rect.setSize(QSize(elementWidth, height()));
0083     styleOption.palette = m_palette;
0084     for (auto it = parentChain.rbegin(); it != parentChain.rend(); ++it) {
0085         styleOption.state.setFlag(QStyle::State_Item, *it == m_index);
0086         styleOption.state.setFlag(QStyle::State_Sibling, it->siblingAtRow(it->row() + 1).isValid());
0087         if (QGuiApplication::layoutDirection() == Qt::LeftToRight) {
0088             styleOption.rect.moveLeft(std::distance(parentChain.rbegin(), it) * elementWidth);
0089         } else {
0090             styleOption.rect.moveLeft((std::distance(it, parentChain.rend()) - 1) * elementWidth);
0091         }
0092         KQuickStyleItem::style()->drawPrimitive(QStyle::PE_IndicatorBranch, &styleOption, painter);
0093     }
0094 }