File indexing completed on 2024-05-19 04:21:55
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 "TableModel.h" 0010 0011 #include <QtGlobal> 0012 #include <QtDebug> 0013 #include <QFile> 0014 #include <QByteArray> 0015 #include <QString> 0016 0017 TableModel::TableModel( QObject* parent ) 0018 : QAbstractTableModel( parent ), 0019 m_dataHasHorizontalHeaders( true ), 0020 m_dataHasVerticalHeaders( true ), 0021 m_supplyHeaderData( true ) 0022 { 0023 } 0024 0025 TableModel::~TableModel() 0026 { 0027 } 0028 0029 int TableModel::rowCount( const QModelIndex& ) const 0030 { 0031 return m_rows.size(); 0032 } 0033 0034 int TableModel::columnCount( const QModelIndex& ) const 0035 { 0036 return m_rows.isEmpty() ? 0 : m_rows.first().size(); 0037 } 0038 0039 QVariant TableModel::data( const QModelIndex& index, int role ) const 0040 { 0041 // FIXME kchart queries (-1, -1) for empty models 0042 if ( index.row() == -1 || index.column() == -1 ) { 0043 qDebug() << "TableModel::data: row:" 0044 << index.row() << ", column:" << index.column() 0045 << ", rowCount:" << rowCount() << ", columnCount:" 0046 << columnCount() 0047 << "\nTableModel::data: FIXME fix kchart views to not query" 0048 " model data for invalid indices!"; 0049 return QVariant(); 0050 } 0051 0052 /* qDebug () << "TableModel::data: row: "<< index.row() << ", column: " 0053 << index.column() << endl;*/ 0054 Q_ASSERT( index.row() >= 0 && index.row() < rowCount() ); 0055 Q_ASSERT( index.column() >= 0 && index.column() < columnCount() ); 0056 0057 if ( role == Qt::DisplayRole || role == Qt::EditRole ) { 0058 return m_rows[ index.row() ][ index.column() ]; 0059 } else { 0060 return QVariant(); 0061 } 0062 } 0063 0064 QVariant TableModel::headerData( int section, Qt::Orientation orientation, int role ) const 0065 { 0066 QVariant result; 0067 0068 switch ( role ) { 0069 case Qt::DisplayRole: 0070 case Qt::EditRole: 0071 if ( m_supplyHeaderData ) { 0072 if ( orientation == Qt::Horizontal ) { 0073 // column header data 0074 if ( !m_horizontalHeaderData.isEmpty() ) 0075 result = m_horizontalHeaderData[ section ]; 0076 } else { 0077 // row header data: 0078 if ( !m_verticalHeaderData.isEmpty() ) 0079 result = m_verticalHeaderData[ section ]; 0080 } 0081 } 0082 break; 0083 case Qt::TextAlignmentRole: 0084 // result = QVariant ( Qt::AlignHCenter | Qt::AlignHCenter ); 0085 break; 0086 case Qt::DecorationRole: 0087 case Qt::ToolTipRole: 0088 break; 0089 default: 0090 // qDebug () << "TableModel::headerData: unknown role " << role << "." << endl; 0091 break; 0092 } 0093 return result; 0094 } 0095 0096 0097 bool TableModel::setData( const QModelIndex& index, const QVariant& value, int role/* = Qt::EditRole */ ) 0098 { 0099 Q_ASSERT( index.row() >= 0 && index.row() < rowCount() ); 0100 Q_ASSERT( index.column() >= 0 && index.column() < columnCount() ); 0101 0102 if ( role == Qt::EditRole ) { 0103 m_rows[ index.row() ][ index.column() ] = value; 0104 Q_EMIT dataChanged( index, index ); 0105 return true; 0106 } else { 0107 return false; 0108 } 0109 } 0110 0111 static QStringList splitLine( const QString& line ) 0112 { 0113 QStringList sl = line.split( QChar( ',' ) ); 0114 QStringList ret; 0115 for ( int i = 0; i < sl.size(); i++ ) { 0116 // get rid of leading and trailing whitespace and quotes 0117 QString s = sl.at( i ).simplified(); 0118 if ( s.startsWith( '\"') ) { 0119 s.remove( 0, 1 ); 0120 } 0121 if ( s.endsWith( '\"') ) { 0122 s.remove( s.length() - 1, 1 ); 0123 } 0124 ret.append( s ); 0125 } 0126 return ret; 0127 } 0128 0129 bool TableModel::loadFromCSV( const QString& filename ) 0130 { 0131 QFile file( filename ); 0132 if ( !file.exists() || !file.open ( QIODevice::ReadOnly ) ) { 0133 qDebug() << "TableModel::loadFromCSV: file" << filename 0134 << "does not exist or could not be opened"; 0135 return false; 0136 } 0137 0138 QStringList lines; 0139 while ( !file.atEnd() ) { 0140 lines.append( QString::fromUtf8( file.readLine() ) ); 0141 } 0142 0143 setTitleText( QString() ); 0144 m_rows.clear(); 0145 m_rows.resize( qMax( 0, lines.size() - ( m_dataHasHorizontalHeaders ? 1 : 0 ) ) ); 0146 0147 for ( int row = 0; row < lines.size(); ++row ) { 0148 QStringList cells = splitLine( lines.at( row ) ); 0149 0150 QVector<QVariant> values( qMax( 0, cells.size() - ( m_dataHasVerticalHeaders ? 1 : 0 ) ) ); 0151 0152 for ( int column = 0; column < cells.size(); ++column ) { 0153 QString cell = cells.at( column ); 0154 0155 if ( row == 0 && m_dataHasHorizontalHeaders ) { 0156 // interpret the first row as column headers: 0157 // the first one is an exception: interpret that as title 0158 if ( column == 0 && m_dataHasVerticalHeaders ) { 0159 setTitleText( cell ); 0160 } else { 0161 m_horizontalHeaderData.append( cell ); 0162 } 0163 } else { 0164 if ( column == 0 && m_dataHasVerticalHeaders ) { 0165 // interpret first column as row headers: 0166 m_verticalHeaderData.append( cell ); 0167 } else { 0168 // try to interpret cell values as floating point 0169 bool convertedOk = false; 0170 qreal numeric = cell.toDouble( &convertedOk ); 0171 const int destColumn = column - ( m_dataHasVerticalHeaders ? 1 : 0 ); 0172 values[ destColumn ] = convertedOk ? numeric : ( cell.isEmpty() ? QVariant() : cell ); 0173 } 0174 } 0175 } 0176 const int destRow = row - ( m_dataHasHorizontalHeaders ? 1 : 0 ); 0177 if ( destRow >= 0 ) { 0178 m_rows[ destRow ] = values; 0179 } 0180 } 0181 0182 beginResetModel(); 0183 endResetModel(); 0184 0185 if ( m_rows.isEmpty() ) { 0186 qDebug() << "TableModel::loadFromCSV: table loaded, but no " 0187 "model data found."; 0188 } 0189 return true; 0190 } 0191 0192 void TableModel::clear() 0193 { 0194 beginResetModel(); 0195 m_rows.clear(); 0196 endResetModel(); 0197 }