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