File indexing completed on 2024-07-21 06:38:21

0001 /*
0002     SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "kcheckableproxymodel.h"
0008 
0009 #include <QItemSelectionModel>
0010 
0011 class KCheckableProxyModelPrivate
0012 {
0013     Q_DECLARE_PUBLIC(KCheckableProxyModel)
0014     KCheckableProxyModel *q_ptr;
0015 
0016     KCheckableProxyModelPrivate(KCheckableProxyModel *checkableModel)
0017         : q_ptr(checkableModel)
0018     {
0019     }
0020 
0021     QItemSelectionModel *m_itemSelectionModel = nullptr;
0022 
0023     void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
0024 };
0025 
0026 KCheckableProxyModel::KCheckableProxyModel(QObject *parent)
0027     : QIdentityProxyModel(parent)
0028     , d_ptr(new KCheckableProxyModelPrivate(this))
0029 {
0030 }
0031 
0032 KCheckableProxyModel::~KCheckableProxyModel() = default;
0033 
0034 void KCheckableProxyModel::setSelectionModel(QItemSelectionModel *itemSelectionModel)
0035 {
0036     Q_D(KCheckableProxyModel);
0037     d->m_itemSelectionModel = itemSelectionModel;
0038     Q_ASSERT(sourceModel() ? d->m_itemSelectionModel->model() == sourceModel() : true);
0039     connect(itemSelectionModel, &QItemSelectionModel::selectionChanged, this, [d](const QItemSelection &selected, const QItemSelection &deselected) {
0040         d->selectionChanged(selected, deselected);
0041     });
0042 }
0043 
0044 QItemSelectionModel *KCheckableProxyModel::selectionModel() const
0045 {
0046     Q_D(const KCheckableProxyModel);
0047     return d->m_itemSelectionModel;
0048 }
0049 
0050 Qt::ItemFlags KCheckableProxyModel::flags(const QModelIndex &index) const
0051 {
0052     if (!index.isValid() || index.column() != 0) {
0053         return QIdentityProxyModel::flags(index);
0054     }
0055     return QIdentityProxyModel::flags(index) | Qt::ItemIsUserCheckable;
0056 }
0057 
0058 QVariant KCheckableProxyModel::data(const QModelIndex &index, int role) const
0059 {
0060     Q_D(const KCheckableProxyModel);
0061 
0062     if (role == Qt::CheckStateRole) {
0063         if (index.column() != 0) {
0064             return QVariant();
0065         }
0066         if (!d->m_itemSelectionModel) {
0067             return Qt::Unchecked;
0068         }
0069 
0070         return d->m_itemSelectionModel->selection().contains(mapToSource(index)) ? Qt::Checked : Qt::Unchecked;
0071     }
0072     return QIdentityProxyModel::data(index, role);
0073 }
0074 
0075 bool KCheckableProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
0076 {
0077     Q_D(KCheckableProxyModel);
0078     if (role == Qt::CheckStateRole) {
0079         if (index.column() != 0) {
0080             return false;
0081         }
0082         if (!d->m_itemSelectionModel) {
0083             return false;
0084         }
0085 
0086         Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
0087         const QModelIndex srcIndex = mapToSource(index);
0088         bool result = select(QItemSelection(srcIndex, srcIndex), state == Qt::Checked ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
0089         Q_EMIT dataChanged(index, index);
0090         return result;
0091     }
0092     return QIdentityProxyModel::setData(index, value, role);
0093 }
0094 
0095 void KCheckableProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
0096 {
0097     QIdentityProxyModel::setSourceModel(sourceModel);
0098     Q_ASSERT(d_ptr->m_itemSelectionModel ? d_ptr->m_itemSelectionModel->model() == sourceModel : true);
0099 }
0100 
0101 void KCheckableProxyModelPrivate::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
0102 {
0103     Q_Q(KCheckableProxyModel);
0104     const auto lstSelected = q->mapSelectionFromSource(selected);
0105     for (const QItemSelectionRange &range : lstSelected) {
0106         Q_EMIT q->dataChanged(range.topLeft(), range.bottomRight());
0107     }
0108     const auto lstDeselected = q->mapSelectionFromSource(deselected);
0109     for (const QItemSelectionRange &range : lstDeselected) {
0110         Q_EMIT q->dataChanged(range.topLeft(), range.bottomRight());
0111     }
0112 }
0113 
0114 bool KCheckableProxyModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
0115 {
0116     Q_D(KCheckableProxyModel);
0117     d->m_itemSelectionModel->select(selection, command);
0118     return true;
0119 }
0120 
0121 QHash<int, QByteArray> KCheckableProxyModel::roleNames() const
0122 {
0123     auto roles = QIdentityProxyModel::roleNames();
0124     roles[Qt::CheckStateRole] = QByteArrayLiteral("checkState");
0125     return roles;
0126 }
0127 
0128 #include "moc_kcheckableproxymodel.cpp"