File indexing completed on 2024-05-12 04:20:41

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KGantt library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "kganttforwardingproxymodel.h"
0010 
0011 #include <cassert>
0012 #include <QStringList>
0013 
0014 using namespace KGantt;
0015 
0016 typedef QAbstractProxyModel BASE;
0017 
0018 
0019 ForwardingProxyModel::ForwardingProxyModel( QObject* parent )
0020     : BASE( parent )
0021 {
0022 }
0023 
0024 ForwardingProxyModel::~ForwardingProxyModel()
0025 {
0026 }
0027 
0028 
0029 QModelIndex ForwardingProxyModel::mapFromSource( const QModelIndex & sourceIndex ) const
0030 {
0031     if ( !sourceIndex.isValid() )
0032         return QModelIndex();
0033     assert( sourceIndex.model() == sourceModel() );
0034 
0035     // Create an index that preserves the internal pointer from the source;
0036     // this way KDDataConverterProxyModel preserves the structure of the source model
0037     return createIndex( sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer() );
0038 }
0039 #ifdef __GNUC__
0040 #if __GNUC__ > 3
0041 #define ATTRIBUTE __attribute__((__may_alias__))
0042 #endif
0043 #else
0044 #define ATTRIBUTE
0045 #endif
0046 namespace {
0047     // Think this is ugly? Well, it's not from me, it comes from QProxyModel
0048     struct ATTRIBUTE KDPrivateModelIndex {
0049         int r, c;
0050         void *p;
0051         const QAbstractItemModel *m;
0052     };
0053 }
0054 
0055 
0056 QModelIndex ForwardingProxyModel::mapToSource( const QModelIndex & proxyIndex ) const
0057 {
0058     if ( !proxyIndex.isValid() )
0059         return QModelIndex();
0060     assert( proxyIndex.model() == this );
0061     // So here we need to create a source index which holds that internal pointer.
0062     // No way to pass it to sourceModel()->index... so we have to do the ugly way:
0063     QModelIndex sourceIndex;
0064     KDPrivateModelIndex* hack = reinterpret_cast<KDPrivateModelIndex*>(&sourceIndex);
0065     hack->r = proxyIndex.row();
0066     hack->c = proxyIndex.column();
0067     hack->p = proxyIndex.internalPointer();
0068     hack->m = sourceModel();
0069     assert( sourceIndex.isValid() );
0070     return sourceIndex;
0071 }
0072 
0073 
0074 void ForwardingProxyModel::setSourceModel( QAbstractItemModel* model )
0075 {
0076     if ( sourceModel() ) sourceModel()->disconnect( this );
0077     BASE::setSourceModel( model );
0078 
0079     if (!model) return;
0080 
0081     connect( model, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
0082     connect( model, SIGNAL(modelReset()), this, SLOT(sourceModelReset()) );
0083     connect( model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged()) );
0084     connect( model, SIGNAL(layoutChanged()), this, SLOT(sourceLayoutChanged()) );
0085 
0086     connect( model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
0087              this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)) );
0088 
0089 
0090     connect( model,  SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
0091              this, SLOT(sourceColumnsAboutToBeInserted(QModelIndex,int,int)) );
0092     connect( model,  SIGNAL(columnsInserted(QModelIndex,int,int)),
0093              this, SLOT(sourceColumnsInserted(QModelIndex,int,int)) );
0094     connect( model,  SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
0095              this, SLOT(sourceColumnsAboutToBeRemoved(QModelIndex,int,int)) );
0096     connect( model,  SIGNAL(columnsRemoved(QModelIndex,int,int)),
0097              this, SLOT(sourceColumnsRemoved(QModelIndex,int,int)) );
0098 
0099     connect( model,  SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
0100              this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)) );
0101     connect( model,  SIGNAL(rowsInserted(QModelIndex,int,int)),
0102              this, SLOT(sourceRowsInserted(QModelIndex,int,int)) );
0103     connect( model,  SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
0104              this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)) );
0105     connect( model,  SIGNAL(rowsRemoved(QModelIndex,int,int)),
0106              this, SLOT(sourceRowsRemoved(QModelIndex,int,int)) );
0107 }
0108 
0109 
0110 void ForwardingProxyModel::sourceModelAboutToBeReset()
0111 {
0112     // The matching signal is emitted be reset()
0113 }
0114 
0115 
0116 void ForwardingProxyModel::sourceModelReset()
0117 {
0118   //qDebug() << "ForwardingProxyModel::sourceModelReset()";
0119     beginResetModel();
0120     endResetModel();
0121 }
0122 
0123 
0124 
0125 void ForwardingProxyModel::sourceLayoutAboutToBeChanged()
0126 {
0127   //qDebug() << "ForwardingProxyModel::sourceLayoutAboutToBeChanged()";
0128     Q_EMIT layoutAboutToBeChanged();
0129 }
0130 
0131 
0132 void ForwardingProxyModel::sourceLayoutChanged()
0133 {
0134   //qDebug() << "ForwardingProxyModel::sourceLayoutChanged()";
0135     beginResetModel();
0136     endResetModel();
0137 }
0138 
0139 
0140 void ForwardingProxyModel::sourceDataChanged( const QModelIndex& from, const QModelIndex& to )
0141 {
0142   //qDebug() << "ForwardingProxyModel::sourceDataChanged("<<from<<to<<")";
0143     Q_EMIT dataChanged( mapFromSource( from ), mapFromSource( to ) );
0144 }
0145 
0146 
0147 void ForwardingProxyModel::sourceColumnsAboutToBeInserted( const QModelIndex& parentIdx,
0148                                                                     int start,
0149                                                                     int end )
0150 {
0151     beginInsertColumns( mapFromSource( parentIdx ), start, end );
0152 }
0153 
0154 
0155 void ForwardingProxyModel::sourceColumnsInserted( const QModelIndex& parentIdx, int start, int end )
0156 {
0157     Q_UNUSED( parentIdx );
0158     Q_UNUSED( start );
0159     Q_UNUSED( end );
0160     endInsertColumns();
0161 }
0162 
0163 
0164 void ForwardingProxyModel::sourceColumnsAboutToBeRemoved( const QModelIndex& parentIdx,
0165                                                                     int start,
0166                                                                     int end )
0167 {
0168     beginRemoveColumns( mapFromSource( parentIdx ), start, end );
0169 }
0170 
0171 
0172 void ForwardingProxyModel::sourceColumnsRemoved( const QModelIndex& parentIdx, int start, int end )
0173 {
0174     Q_UNUSED( parentIdx );
0175     Q_UNUSED( start );
0176     Q_UNUSED( end );
0177     endRemoveColumns();
0178 }
0179 
0180 
0181 void ForwardingProxyModel::sourceRowsAboutToBeInserted( const QModelIndex & parentIdx, int start, int end )
0182 {
0183     beginInsertRows( mapFromSource( parentIdx ), start, end );
0184 }
0185 
0186 
0187 void ForwardingProxyModel::sourceRowsInserted( const QModelIndex& parentIdx, int start, int end )
0188 {
0189     Q_UNUSED( parentIdx );
0190     Q_UNUSED( start );
0191     Q_UNUSED( end );
0192     endInsertRows();
0193 }
0194 
0195 
0196 void ForwardingProxyModel::sourceRowsAboutToBeRemoved( const QModelIndex & parentIdx, int start, int end )
0197 {
0198     beginRemoveRows( mapFromSource( parentIdx ), start, end );
0199 }
0200 
0201 
0202 void ForwardingProxyModel::sourceRowsRemoved( const QModelIndex& parentIdx, int start, int end )
0203 {
0204     Q_UNUSED( parentIdx );
0205     Q_UNUSED( start );
0206     Q_UNUSED( end );
0207     endRemoveRows();
0208 }
0209 
0210 
0211 int ForwardingProxyModel::rowCount( const QModelIndex& idx ) const
0212 {
0213     return sourceModel()->rowCount( mapToSource( idx ) );
0214 }
0215 
0216 
0217 int ForwardingProxyModel::columnCount( const QModelIndex& idx ) const
0218 {
0219     return sourceModel()->columnCount( mapToSource( idx ) );
0220 }
0221 
0222 
0223 QModelIndex ForwardingProxyModel::index( int row, int column, const QModelIndex& parent ) const
0224 {
0225     return mapFromSource( sourceModel()->index( row, column, mapToSource( parent ) ) );
0226 }
0227 
0228 
0229 QModelIndex ForwardingProxyModel::parent( const QModelIndex& idx ) const
0230 {
0231     return mapFromSource( sourceModel()->parent( mapToSource( idx ) ) );
0232 }
0233 
0234 
0235 bool ForwardingProxyModel::setData( const QModelIndex& index, const QVariant& value, int role )
0236 {
0237   //qDebug() << "ForwardingProxyModel::setData( " << index<<value<< role<<")";
0238     return sourceModel()->setData( mapToSource( index ), value, role );
0239 }
0240 
0241 QMimeData *ForwardingProxyModel::mimeData(const QModelIndexList &indexes) const
0242 {
0243     QModelIndexList source_indexes;
0244     for (int i = 0; i < indexes.count(); ++i)
0245         source_indexes << mapToSource(indexes.at(i));
0246     return sourceModel()->mimeData(source_indexes);
0247 }
0248 
0249 bool ForwardingProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
0250 {
0251     if ((row == -1) && (column == -1))
0252         return sourceModel()->dropMimeData(data, action, -1, -1, mapToSource(parent));
0253     int source_destination_row = -1;
0254     int source_destination_column = -1;
0255     QModelIndex source_parent;
0256     if (row == rowCount(parent)) {
0257         source_parent = mapToSource(parent);
0258         source_destination_row = sourceModel()->rowCount(source_parent);
0259     } else {
0260         QModelIndex proxy_index = index(row, column, parent);
0261         QModelIndex source_index = mapToSource(proxy_index);
0262         source_destination_row = source_index.row();
0263         source_destination_column = source_index.column();
0264         source_parent = source_index.parent();
0265     }
0266     return sourceModel()->dropMimeData(data, action, source_destination_row, source_destination_column, source_parent);
0267 }
0268 
0269 QStringList ForwardingProxyModel::mimeTypes() const
0270 {
0271     return sourceModel()->mimeTypes();
0272 }
0273 
0274 Qt::DropActions ForwardingProxyModel::supportedDropActions() const
0275 {
0276     return sourceModel()->supportedDropActions();
0277 }
0278         
0279 #include "moc_kganttforwardingproxymodel.cpp"
0280