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