41 #include <QTextStream>
43 #include "../vmisc/diagnostic.h"
63 QT_WARNING_DISABLE_GCC("-Weffc++")
82 : QAbstractTableModel(parent)
99 : QAbstractTableModel(parent)
113 if (parent.row() != -1 && parent.column() != -1)
117 return qxt_d().csvData.count();
125 if (parent.row() != -1 && parent.column() != -1)
129 return qxt_d().maxColumn;
137 if (index.parent() != QModelIndex())
141 if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole)
143 if (index.row() < 0 || index.column() < 0 || index.row() >=
rowCount())
147 const QStringList& row =
qxt_d().csvData[index.row()];
148 if (index.column() >= row.length())
152 return row[index.column()];
162 if (section <
qxt_d().header.count() && orientation == Qt::Horizontal && (role == Qt::DisplayRole
163 || role == Qt::EditRole
164 || role == Qt::UserRole))
166 return qxt_d().header[section];
170 return QAbstractTableModel::headerData(section, orientation, role);
182 setSource(&src, withHeader, separator, codec);
197 bool headerSet = !withHeader;
198 if (not file->isOpen())
200 file->open(QIODevice::ReadOnly);
216 QTextStream stream(file);
219 stream.setCodec(codec);
223 stream.setAutoDetectUnicode(
true);
225 while (not stream.atEnd())
227 if (buffer != QChar(0))
236 if (ch ==
'\n' && readCR)
248 if (ch != separator && (ch.category() == QChar::Separator_Line || ch.category() == QChar::Separator_Paragraph
249 || ch.category() == QChar::Other_Control))
253 if (not row.isEmpty())
281 else if (ch == quote)
296 }
while (!stream.atEnd());
298 else if (ch == separator)
308 if (not field.isEmpty())
312 if (not row.isEmpty())
332 emit headerDataChanged(Qt::Horizontal, 0,
data.count());
340 if (orientation != Qt::Horizontal)
345 if (role != Qt::DisplayRole && role != Qt::EditRole)
355 while (section >
qxt_d().header.size())
357 qxt_d().header << QString();
359 qxt_d().header[section] = value.toString();
360 emit headerDataChanged(Qt::Horizontal, section, section);
369 if (index.parent() != QModelIndex())
374 if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole)
376 if (index.row() >=
rowCount() || index.column() >=
columnCount() || index.row() < 0 || index.column() < 0)
380 QStringList& row =
qxt_d().csvData[index.row()];
381 while (row.length() <= index.column())
385 row[index.column()] =
data.toString();
386 emit dataChanged(index, index);
405 if (parent != QModelIndex() || row < 0)
409 emit beginInsertRows(parent, row, row + count);
413 for(
int i = 0; i < count; i++)
415 d_ptr.
csvData << QStringList();
420 for(
int i = 0; i < count; i++)
422 d_ptr.
csvData.insert(row, QStringList());
425 emit endInsertRows();
442 if (parent != QModelIndex() || row < 0)
454 emit beginRemoveRows(parent, row, row + count);
456 for (
int i = 0;i < count;i++)
460 emit endRemoveRows();
477 if (parent != QModelIndex() || col < 0)
481 beginInsertColumns(parent, col, col + count - 1);
483 for (
int i = 0; i <
rowCount(); i++)
485 QStringList& row = d_ptr.
csvData[i];
486 while (col >= row.length())
488 row.append(QString());
490 for (
int j = 0; j < count; j++)
492 row.insert(col, QString());
495 for (
int i = 0; i < count ;i++)
497 d_ptr.
header.insert(col, QString());
517 if (parent != QModelIndex() || col < 0)
529 emit beginRemoveColumns(parent, col, col + count);
531 for (
int i = 0; i <
rowCount(); i++)
533 for (
int j = 0; j < count; j++)
535 d_ptr.
csvData[i].removeAt(col);
538 for (
int i = 0; i < count; i++)
540 d_ptr.
header.removeAt(col);
542 emit endRemoveColumns();
551 if (quoteField && !addDoubleQuotes && !addSingleQuotes)
555 addDoubleQuotes =
true;
559 addSingleQuotes =
true;
566 return '"' + field.replace(
"\\",
"\\\\").replace(
"\"",
"\\\"") +
'"';
570 return '\'' + field.replace(
"\\",
"\\\\").replace(
"'",
"\\'") +
'\'';
577 return '"' + field.replace(
"\"",
"\"\"") +
'"';
581 return '\'' + field.replace(
"'",
"''") +
'\'';
597 int row, col, rows, cols;
601 if (not dest->isOpen())
603 dest->open(QIODevice::WriteOnly | QIODevice::Truncate);
605 QTextStream stream(dest);
608 stream.setCodec(codec);
613 for (col = 0; col < cols; ++col)
621 stream <<
data << Qt::endl;
623 for (row = 0; row < rows; ++row)
625 const QStringList& rowData = d_ptr.
csvData[row];
627 for (col = 0; col < cols; ++col)
633 if (col < rowData.length())
642 stream <<
data << Qt::endl;
656 void QxtCsvModel::toCSV(
const QString &filename,
bool withHeader, QChar separator, QTextCodec* codec)
const
658 QFile dest(filename);
659 toCSV(&dest, withHeader, separator, codec);
667 return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
676 return qxt_d().quoteMode;
688 qxt_d().quoteMode = mode;
699 setData(index(row, column), value);
710 return data(index(row, column)).toString();
730 return headerData(column, Qt::Horizontal).toString();
QxtCsvModel::QuoteMode quoteMode
QList< QStringList > csvData
The QxtCsvModel class provides a QAbstractTableModel for CSV Files.
virtual bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) Q_DECL_OVERRIDE
\reimp
void setText(int row, int column, const QString &value)
Sets the content of the cell at row row and column column to value.
bool insertColumn(int col, const QModelIndex &parent=QModelIndex())
\reimp
void setHeaderText(int column, const QString &value)
Sets the content of the header for column column to value.
QString headerText(int column) const
Fetches the content of the cell at row row and column column.
bool removeColumn(int col, const QModelIndex &parent=QModelIndex())
\reimp
virtual bool insertColumns(int col, int count, const QModelIndex &parent=QModelIndex()) Q_DECL_OVERRIDE
\reimp
virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role=Qt::DisplayRole) Q_DECL_OVERRIDE
\reimp
void setSource(QIODevice *file, bool withHeader=false, QChar separator=',', QTextCodec *codec=nullptr)
Reads in a CSV file from the provided file using codec.
bool removeRow(int row, const QModelIndex &parent=QModelIndex())
\reimp
QuoteMode quoteMode() const
Returns the current quoting mode.
virtual Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE
\reimp
bool insertRow(int row, const QModelIndex &parent=QModelIndex())
\reimp
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const Q_DECL_OVERRIDE
\reimp
void setQuoteMode(QuoteMode mode)
Sets the current quoting mode.
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const Q_DECL_OVERRIDE
\reimp
virtual bool removeColumns(int col, int count, const QModelIndex &parent=QModelIndex()) Q_DECL_OVERRIDE
\reimp
virtual bool setData(const QModelIndex &index, const QVariant &data, int role=Qt::EditRole) Q_DECL_OVERRIDE
\reimp
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const Q_DECL_OVERRIDE
\reimp
QString text(int row, int column) const
Fetches the content of the cell at row row and column column.
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const Q_DECL_OVERRIDE
\reimp
void toCSV(QIODevice *file, bool withHeader=false, QChar separator=',', QTextCodec *codec=nullptr) const
Outputs the content of the model as a CSV file to the device dest using codec.
QxtCsvModel(QObject *parent=nullptr)
Creates an empty QxtCsvModel with parent parent.
virtual bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) Q_DECL_OVERRIDE
\reimp
QxtPrivateInterface< QxtCsvModel, QxtCsvModelPrivate > qxt_d
#define QXT_DECLARE_PUBLIC(PUB)
#define QXT_INIT_PRIVATE(PUB)
static QString qxt_addCsvQuotes(QxtCsvModel::QuoteMode mode, QString field)