File indexing completed on 2024-05-19 15:09:23

0001 /*
0002     SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "columnproxymodel.h"
0008 
0009 ColumnProxyModel::ColumnProxyModel(QObject *parent)
0010     : QAbstractListModel(parent)
0011     , m_column(0)
0012     , m_sourceModel(nullptr)
0013 {
0014 }
0015 
0016 void ColumnProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
0017 {
0018     if (sourceModel == m_sourceModel) {
0019         return;
0020     }
0021 
0022     beginResetModel();
0023     if (m_sourceModel) {
0024         disconnect(m_sourceModel, &QObject::destroyed, this, &ColumnProxyModel::sourceDestroyed);
0025 
0026         disconnect(m_sourceModel, &QAbstractItemModel::dataChanged, this, &ColumnProxyModel::considerDataChanged);
0027         disconnect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &ColumnProxyModel::considerRowsAboutToBeInserted);
0028         disconnect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeMoved, this, &ColumnProxyModel::considerRowsAboutToBeMoved);
0029         disconnect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ColumnProxyModel::considerRowsAboutToBeRemoved);
0030         disconnect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &ColumnProxyModel::considerRowsInserted);
0031         disconnect(m_sourceModel, &QAbstractItemModel::rowsMoved, this, &ColumnProxyModel::considerRowsMoved);
0032         disconnect(m_sourceModel, &QAbstractItemModel::rowsRemoved, this, &ColumnProxyModel::considerRowsRemoved);
0033 
0034         // TODO: QAbstractItemModel::modelAboutToBeReset and QAbstractItemModel::modelReset are private signals
0035         // we can connect to them, but can't emit them
0036         disconnect(m_sourceModel, SIGNAL(modelAboutToBeReset()), this, SIGNAL(modelAboutToBeReset()));
0037         disconnect(m_sourceModel, SIGNAL(modelReset()), this, SIGNAL(modelReset()));
0038 
0039         disconnect(m_sourceModel, &QAbstractItemModel::headerDataChanged, this, &QAbstractItemModel::headerDataChanged);
0040         disconnect(m_sourceModel, &QAbstractItemModel::layoutAboutToBeChanged, this, &QAbstractItemModel::layoutAboutToBeChanged);
0041         disconnect(m_sourceModel, &QAbstractItemModel::layoutChanged, this, &QAbstractItemModel::layoutChanged);
0042     }
0043     m_sourceModel = sourceModel;
0044     if (m_sourceModel) {
0045         connect(m_sourceModel, &QObject::destroyed, this, &ColumnProxyModel::sourceDestroyed);
0046 
0047         connect(m_sourceModel, &QAbstractItemModel::dataChanged, this, &ColumnProxyModel::considerDataChanged);
0048         connect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &ColumnProxyModel::considerRowsAboutToBeInserted);
0049         connect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeMoved, this, &ColumnProxyModel::considerRowsAboutToBeMoved);
0050         connect(m_sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ColumnProxyModel::considerRowsAboutToBeRemoved);
0051         connect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &ColumnProxyModel::considerRowsInserted);
0052         connect(m_sourceModel, &QAbstractItemModel::rowsMoved, this, &ColumnProxyModel::considerRowsMoved);
0053         connect(m_sourceModel, &QAbstractItemModel::rowsRemoved, this, &ColumnProxyModel::considerRowsRemoved);
0054 
0055         // TODO: QAbstractItemModel::modelAboutToBeReset and QAbstractItemModel::modelReset are private signals
0056         // we can connect to them, but can't emit them
0057         connect(m_sourceModel, SIGNAL(modelAboutToBeReset()), this, SIGNAL(modelAboutToBeReset()));
0058         connect(m_sourceModel, SIGNAL(modelReset()), this, SIGNAL(modelReset()));
0059 
0060         connect(m_sourceModel, &QAbstractItemModel::headerDataChanged, this, &QAbstractItemModel::headerDataChanged);
0061         connect(m_sourceModel, &QAbstractItemModel::layoutAboutToBeChanged, this, &QAbstractItemModel::layoutAboutToBeChanged);
0062         connect(m_sourceModel, &QAbstractItemModel::layoutChanged, this, &QAbstractItemModel::layoutChanged);
0063     }
0064     endResetModel();
0065 }
0066 
0067 void ColumnProxyModel::setColumn(int col)
0068 {
0069     beginResetModel();
0070     m_column = col;
0071     endResetModel();
0072 }
0073 
0074 int ColumnProxyModel::column() const
0075 {
0076     return m_column;
0077 }
0078 
0079 QModelIndex ColumnProxyModel::rootIndex() const
0080 {
0081     return m_index;
0082 }
0083 
0084 void ColumnProxyModel::setRootIndex(const QModelIndex &index)
0085 {
0086     if (index == m_index) {
0087         return;
0088     }
0089 
0090     if (index.isValid()) {
0091         setSourceModel(const_cast<QAbstractItemModel *>(index.model()));
0092     }
0093     beginResetModel();
0094     m_index = index;
0095     endResetModel();
0096 
0097     Q_EMIT rootIndexChanged();
0098 }
0099 
0100 QModelIndex ColumnProxyModel::indexFromModel(QAbstractItemModel *model, int row, int column, const QModelIndex &parent)
0101 {
0102     return model ? model->index(row, column, parent) : QModelIndex();
0103 }
0104 
0105 QVariant ColumnProxyModel::data(const QModelIndex &index, int role) const
0106 {
0107     return m_sourceModel ? m_sourceModel->data(sourceIndex(index), role) : QVariant();
0108 }
0109 
0110 QVariant ColumnProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
0111 {
0112     return m_sourceModel ? m_sourceModel->headerData(section, orientation, role) : QVariant();
0113 }
0114 
0115 QModelIndex ColumnProxyModel::sourceIndex(const QModelIndex &proxyIndex) const
0116 {
0117     return m_sourceModel ? m_sourceModel->index(proxyIndex.row(), m_column, m_index) : QModelIndex();
0118 }
0119 
0120 int ColumnProxyModel::rowCount(const QModelIndex &parent) const
0121 {
0122     return (!m_sourceModel || parent.isValid()) ? 0 : m_sourceModel->rowCount(m_index);
0123 }
0124 
0125 QModelIndex ColumnProxyModel::proxyIndex(const QModelIndex &sourceIndex) const
0126 {
0127     if (sourceIndex.parent() == m_index) {
0128         return index(sourceIndex.row(), sourceIndex.column(), QModelIndex());
0129     }
0130 
0131     return QModelIndex();
0132 }
0133 
0134 void ColumnProxyModel::sourceDestroyed(QObject *source)
0135 {
0136     Q_ASSERT(source == m_sourceModel);
0137 
0138     beginResetModel();
0139     m_sourceModel = nullptr;
0140     endResetModel();
0141 }
0142 
0143 QModelIndex ColumnProxyModel::indexAt(int row, const QModelIndex &parent) const
0144 {
0145     return m_sourceModel ? m_sourceModel->index(row, m_column, parent) : QModelIndex();
0146 }
0147 
0148 /////////////////
0149 
0150 void ColumnProxyModel::considerDataChanged(const QModelIndex &idxA, const QModelIndex &idxB)
0151 {
0152     if (idxA.parent() == m_index && idxB.parent() == m_index) {
0153         Q_EMIT dataChanged(proxyIndex(idxA), proxyIndex(idxB));
0154     }
0155 }
0156 
0157 void ColumnProxyModel::considerRowsAboutToBeInserted(const QModelIndex &parent, int rA, int rB)
0158 {
0159     if (parent == m_index) {
0160         beginInsertRows(QModelIndex(), rA, rB);
0161     }
0162 }
0163 
0164 void ColumnProxyModel::considerRowsAboutToBeMoved(const QModelIndex &sourceParent, int rA, int rB, const QModelIndex &destParent, int rD)
0165 {
0166     if (sourceParent == m_index && destParent == m_index) {
0167         beginMoveRows(QModelIndex(), rA, rB, QModelIndex(), rD);
0168     } else if (sourceParent == m_index) {
0169         beginRemoveRows(sourceParent, rA, rB);
0170     } else if (destParent == m_index) {
0171         beginInsertRows(destParent, rD, rD + (rB - rA));
0172     }
0173 }
0174 
0175 void ColumnProxyModel::considerRowsAboutToBeRemoved(const QModelIndex &parent, int rA, int rB)
0176 {
0177     if (parent == m_index) {
0178         beginRemoveRows(QModelIndex(), rA, rB);
0179     }
0180 }
0181 
0182 void ColumnProxyModel::considerRowsInserted(const QModelIndex &parent, int, int)
0183 {
0184     if (parent == m_index) {
0185         endInsertRows();
0186     }
0187 }
0188 
0189 void ColumnProxyModel::considerRowsMoved(const QModelIndex &sourceParent, int, int, const QModelIndex &destParent, int)
0190 {
0191     if (sourceParent == m_index && destParent == m_index) {
0192         endMoveRows();
0193     } else if (sourceParent == m_index) {
0194         endRemoveRows();
0195     } else if (destParent == m_index) {
0196         endInsertRows();
0197     }
0198 }
0199 
0200 void ColumnProxyModel::considerRowsRemoved(const QModelIndex &parent, int, int)
0201 {
0202     if (parent == m_index) {
0203         endInsertRows();
0204     }
0205 }
0206 
0207 QHash<int, QByteArray> ColumnProxyModel::roleNames() const
0208 {
0209     return m_sourceModel ? m_sourceModel->roleNames() : QHash<int, QByteArray>();
0210 }
0211 
0212 bool ColumnProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
0213 {
0214     return m_sourceModel && m_sourceModel->setData(sourceIndex(index), value, role);
0215 }
0216 
0217 #include "moc_columnproxymodel.cpp"