File indexing completed on 2024-05-12 15:54:13
0001 /* 0002 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KD Chart 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 "KChartAbstractProxyModel.h" 0021 0022 #include "KChartMath_p.h" 0023 0024 #include <QDebug> 0025 0026 #ifdef __GNUC__ 0027 #if __GNUC__ > 3 0028 #define MAY_ALIAS __attribute__((__may_alias__)) 0029 #endif 0030 #else 0031 #define MAY_ALIAS 0032 #endif 0033 0034 namespace KChart { 0035 0036 AbstractProxyModel::AbstractProxyModel(QObject* parent) 0037 : QAbstractProxyModel(parent) {} 0038 0039 // Allows access to QModelIndex's private data via type punning and a compatible data layout. 0040 // Due to inlining in Qt and no d-pointer, it is safe to assume that the layout won't change except 0041 // between major Qt versions. As it happens, the layout is the same in Qt4 and Qt5. 0042 // The only change is void * -> quintptr. 0043 struct MAY_ALIAS KDPrivateModelIndex 0044 { 0045 int r, c; 0046 void *p; 0047 const QAbstractItemModel *m; 0048 }; 0049 0050 QModelIndex AbstractProxyModel::mapFromSource( const QModelIndex & sourceIndex ) const 0051 { 0052 if ( !sourceIndex.isValid() ) 0053 return QModelIndex(); 0054 //qDebug() << "sourceIndex.model()="<<sourceIndex.model(); 0055 //qDebug() << "model()="<<sourceModel(); 0056 Q_ASSERT( sourceIndex.model() == sourceModel() ); 0057 0058 // Create an index that preserves the internal pointer from the source; 0059 // this way AbstractProxyModel preserves the structure of the source model 0060 return createIndex( sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer() ); 0061 } 0062 0063 QModelIndex AbstractProxyModel::mapToSource( const QModelIndex &proxyIndex ) const 0064 { 0065 if ( !proxyIndex.isValid() ) 0066 return QModelIndex(); 0067 if ( proxyIndex.model() != this ) 0068 qDebug() << proxyIndex.model() << this; 0069 Q_ASSERT( proxyIndex.model() == this ); 0070 // So here we need to create a source index which holds that internal pointer. 0071 // No way to pass it to sourceModel()->index... so we have to do the ugly way: 0072 QModelIndex sourceIndex; 0073 KDPrivateModelIndex* hack = reinterpret_cast<KDPrivateModelIndex*>(&sourceIndex); 0074 hack->r = proxyIndex.row(); 0075 hack->c = proxyIndex.column(); 0076 hack->p = proxyIndex.internalPointer(); 0077 hack->m = sourceModel(); 0078 Q_ASSERT( sourceIndex.isValid() ); 0079 return sourceIndex; 0080 } 0081 0082 QModelIndex AbstractProxyModel::index( int row, int col, const QModelIndex& index ) const 0083 { 0084 Q_ASSERT(sourceModel()); 0085 return mapFromSource(sourceModel()->index( row, col, mapToSource(index) )); 0086 } 0087 0088 QModelIndex AbstractProxyModel::parent( const QModelIndex& index ) const 0089 { 0090 Q_ASSERT(sourceModel()); 0091 return mapFromSource(sourceModel()->parent( mapToSource(index) )); 0092 } 0093 0094 }