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