File indexing completed on 2024-05-12 15:54:24

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