• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kaddressbook

  • sources
  • kde-4.14
  • kdepim
  • kaddressbook
  • xxport
  • csv
qcsvreader.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "qcsvreader.h"
21 
22 #include <QtCore/QStringList>
23 #include <QtCore/QTextCodec>
24 #include <QtCore/QTextStream>
25 
26 #include <KLocalizedString>
27 
28 QCsvBuilderInterface::~QCsvBuilderInterface()
29 {
30 }
31 
32 class QCsvReader::Private
33 {
34 public:
35  Private( QCsvBuilderInterface *builder )
36  : mBuilder( builder ), mNotTerminated( true )
37  {
38  mTextQuote = QLatin1Char( '"' );
39  mDelimiter = QLatin1Char( ' ' );
40  mStartRow = 0;
41  mCodec = QTextCodec::codecForLocale();
42  }
43 
44  void emitBeginLine( uint row );
45  void emitEndLine( uint row );
46  void emitField( const QString &data, int row, int column );
47 
48  QCsvBuilderInterface *mBuilder;
49  QTextCodec *mCodec;
50  QChar mTextQuote;
51  QChar mDelimiter;
52 
53  uint mStartRow;
54  bool mNotTerminated;
55 };
56 
57 void QCsvReader::Private::emitBeginLine( uint row )
58 {
59  if ( ( row - mStartRow ) > 0 ) {
60  mBuilder->beginLine();
61  }
62 }
63 
64 void QCsvReader::Private::emitEndLine( uint row )
65 {
66  if ( ( row - mStartRow ) > 0 ) {
67  mBuilder->endLine();
68  }
69 }
70 
71 void QCsvReader::Private::emitField( const QString &data, int row, int column )
72 {
73  if ( ( row - mStartRow ) > 0 ) {
74  mBuilder->field( data, row - mStartRow - 1, column - 1 );
75  }
76 }
77 
78 QCsvReader::QCsvReader( QCsvBuilderInterface *builder )
79  : d( new Private( builder ) )
80 {
81  Q_ASSERT( builder );
82 }
83 
84 QCsvReader::~QCsvReader()
85 {
86  delete d;
87 }
88 
89 bool QCsvReader::read( QIODevice *device )
90 {
91  enum State {
92  StartLine,
93  QuotedField,
94  QuotedFieldEnd,
95  NormalField,
96  EmptyField
97  };
98 
99  int row, column;
100 
101  QString field;
102  QChar input;
103  State currentState = StartLine;
104 
105  row = column = 1;
106 
107  d->mBuilder->begin();
108 
109  if ( !device->isOpen() ) {
110  d->emitBeginLine( row );
111  d->mBuilder->error( i18n("Device is not open") );
112  d->emitEndLine( row );
113  d->mBuilder->end();
114  return false;
115  }
116 
117  QTextStream inputStream( device );
118  inputStream.setCodec( d->mCodec );
119 
151  while ( !inputStream.atEnd() && d->mNotTerminated ) {
152  inputStream >> input;
153 
154  switch ( currentState ) {
155  case StartLine:
156  if ( input == QLatin1Char( '\r' ) || input == QLatin1Char( '\n' ) ) {
157  currentState = StartLine;
158  } else if ( input == d->mTextQuote ) {
159  d->emitBeginLine( row );
160  currentState = QuotedField;
161  } else if ( input == d->mDelimiter ) {
162  d->emitBeginLine( row );
163  d->emitField( field, row, column );
164  column++;
165  currentState = EmptyField;
166  } else {
167  d->emitBeginLine( row );
168  field.append( input );
169  currentState = NormalField;
170  }
171  break;
172  case QuotedField:
173  if ( input == QLatin1Char( '\r' ) || input == QLatin1Char( '\n' ) ) {
174  field.append( input );
175  currentState = QuotedField;
176  } else if ( input == d->mTextQuote ) {
177  currentState = QuotedFieldEnd;
178  } else if ( input == d->mDelimiter ) {
179  field.append( input );
180  currentState = QuotedField;
181  } else {
182  field.append( input );
183  currentState = QuotedField;
184  }
185  break;
186  case QuotedFieldEnd:
187  if ( input == QLatin1Char( '\r' ) || input == QLatin1Char( '\n' ) ) {
188  d->emitField( field, row, column );
189  field.clear();
190  d->emitEndLine( row );
191  column = 1;
192  row++;
193  currentState = StartLine;
194  } else if ( input == d->mTextQuote ) {
195  field.append( input );
196  currentState = QuotedField;
197  } else if ( input == d->mDelimiter ) {
198  d->emitField( field, row, column );
199  field.clear();
200  column++;
201  currentState = EmptyField;
202  } else {
203  d->emitField( field, row, column );
204  field.clear();
205  column++;
206  field.append( input );
207  currentState = EmptyField;
208  }
209  break;
210  case NormalField:
211  if ( input == QLatin1Char( '\r' ) || input == QLatin1Char( '\n' ) ) {
212  d->emitField( field, row, column );
213  field.clear();
214  d->emitEndLine( row );
215  row++;
216  column = 1;
217  currentState = StartLine;
218  } else if ( input == d->mTextQuote ) {
219  field.append( input );
220  currentState = NormalField;
221  } else if ( input == d->mDelimiter ) {
222  d->emitField( field, row, column );
223  field.clear();
224  column++;
225  currentState = EmptyField;
226  } else {
227  field.append( input );
228  currentState = NormalField;
229  }
230  break;
231  case EmptyField:
232  if ( input == QLatin1Char( '\r' ) || input == QLatin1Char( '\n' ) ) {
233  d->emitField( QString(), row, column );
234  field.clear();
235  d->emitEndLine( row );
236  column = 1;
237  row++;
238  currentState = StartLine;
239  } else if ( input == d->mTextQuote ) {
240  currentState = QuotedField;
241  } else if ( input == d->mDelimiter ) {
242  d->emitField( QString(), row, column );
243  column++;
244  currentState = EmptyField;
245  } else {
246  field.append( input );
247  currentState = NormalField;
248  }
249  break;
250  }
251  }
252 
253  if ( currentState != StartLine ) {
254  if ( field.length() > 0 ) {
255  d->emitField( field, row, column );
256  ++row;
257  field.clear();
258  }
259  d->emitEndLine( row );
260  }
261 
262  d->mBuilder->end();
263 
264  return true;
265 }
266 
267 void QCsvReader::setTextQuote( const QChar &textQuote )
268 {
269  d->mTextQuote = textQuote;
270 }
271 
272 QChar QCsvReader::textQuote() const
273 {
274  return d->mTextQuote;
275 }
276 
277 void QCsvReader::setDelimiter( const QChar &delimiter )
278 {
279  d->mDelimiter = delimiter;
280 }
281 
282 QChar QCsvReader::delimiter() const
283 {
284  return d->mDelimiter;
285 }
286 
287 void QCsvReader::setStartRow( uint startRow )
288 {
289  d->mStartRow = startRow;
290 }
291 
292 uint QCsvReader::startRow() const
293 {
294  return d->mStartRow;
295 }
296 
297 void QCsvReader::setTextCodec( QTextCodec *textCodec )
298 {
299  d->mCodec = textCodec;
300 }
301 
302 QTextCodec *QCsvReader::textCodec() const
303 {
304  return d->mCodec;
305 }
306 
307 void QCsvReader::terminate()
308 {
309  d->mNotTerminated = false;
310 }
311 
312 class QCsvStandardBuilder::Private
313 {
314 public:
315  Private()
316  {
317  init();
318  }
319 
320  void init();
321 
322  QString mLastErrorString;
323  uint mRowCount;
324  uint mColumnCount;
325  QList<QStringList> mRows;
326 };
327 
328 void QCsvStandardBuilder::Private::init()
329 {
330  mRows.clear();
331  mRowCount = 0;
332  mColumnCount = 0;
333  mLastErrorString.clear();
334 }
335 
336 QCsvStandardBuilder::QCsvStandardBuilder()
337  : d( new Private )
338 {
339 }
340 
341 QCsvStandardBuilder::~QCsvStandardBuilder()
342 {
343  delete d;
344 }
345 
346 QString QCsvStandardBuilder::lastErrorString() const
347 {
348  return d->mLastErrorString;
349 }
350 
351 uint QCsvStandardBuilder::rowCount() const
352 {
353  return d->mRowCount;
354 }
355 
356 uint QCsvStandardBuilder::columnCount() const
357 {
358  return d->mColumnCount;
359 }
360 
361 QString QCsvStandardBuilder::data( uint row, uint column ) const
362 {
363  if ( row > d->mRowCount || column > d->mColumnCount || column >= (uint)d->mRows[ row ].count() ) {
364  return QString();
365  }
366 
367  return d->mRows[ row ][ column ];
368 }
369 
370 void QCsvStandardBuilder::begin()
371 {
372  d->init();
373 }
374 
375 void QCsvStandardBuilder::beginLine()
376 {
377  d->mRows.append( QStringList() );
378  d->mRowCount++;
379 }
380 
381 void QCsvStandardBuilder::field( const QString &data, uint row, uint column )
382 {
383  const uint size = d->mRows[ row ].size();
384  if ( column >= size ) {
385  for ( uint i = column; i < size + 1; ++i ) {
386  d->mRows[ row ].append( QString() );
387  }
388  }
389 
390  d->mRows[ row ][ column ] = data;
391 
392  d->mColumnCount = qMax( d->mColumnCount, column + 1 );
393 }
394 
395 void QCsvStandardBuilder::endLine()
396 {
397 }
398 
399 void QCsvStandardBuilder::end()
400 {
401 }
402 
403 void QCsvStandardBuilder::error( const QString &errorMsg )
404 {
405  d->mLastErrorString = errorMsg;
406 }
407 
QIODevice
QTextStream::setCodec
void setCodec(QTextCodec *codec)
QCsvReader::setTextCodec
void setTextCodec(QTextCodec *textCodec)
Sets the text codec that shall be used for parsing the csv list.
Definition: qcsvreader.cpp:297
QList::clear
void clear()
QString::append
QString & append(QChar ch)
QChar
QCsvStandardBuilder::~QCsvStandardBuilder
~QCsvStandardBuilder()
Destroys the csv standard builder.
Definition: qcsvreader.cpp:341
QCsvStandardBuilder::endLine
void endLine()
This method is called whenever a line ends.
Definition: qcsvreader.cpp:395
QCsvReader::~QCsvReader
~QCsvReader()
Destroys the csv reader.
Definition: qcsvreader.cpp:84
QTextCodec::codecForLocale
QTextCodec * codecForLocale()
QTextStream
QCsvStandardBuilder::data
QString data(uint row, uint column) const
Returns the data of the field at the given row and column.
Definition: qcsvreader.cpp:361
QString::clear
void clear()
QCsvStandardBuilder::beginLine
void beginLine()
This method is called whenever a new line starts.
Definition: qcsvreader.cpp:375
QCsvBuilderInterface::~QCsvBuilderInterface
virtual ~QCsvBuilderInterface()
This method is called on the destruction of the interface.
Definition: qcsvreader.cpp:28
QTextStream::atEnd
bool atEnd() const
QCsvReader::setDelimiter
void setDelimiter(const QChar &delimiter)
Sets the character that is used as delimiter for fields.
Definition: qcsvreader.cpp:277
QCsvReader::setTextQuote
void setTextQuote(const QChar &textQuote)
Sets the character that is used for quoting.
Definition: qcsvreader.cpp:267
QCsvReader::setStartRow
void setStartRow(uint startRow)
Sets the row from where the parsing shall be started.
Definition: qcsvreader.cpp:287
QCsvReader::terminate
void terminate()
Terminates the parsing of the csv data.
Definition: qcsvreader.cpp:307
QIODevice::isOpen
bool isOpen() const
QCsvReader::textQuote
QChar textQuote() const
Returns the character that is used for quoting.
QString
QList< QStringList >
QCsvStandardBuilder::rowCount
uint rowCount() const
Returns the number of rows.
Definition: qcsvreader.cpp:351
QTextCodec
QCsvStandardBuilder::begin
void begin()
Definition: qcsvreader.cpp:370
qcsvreader.h
QStringList
QCsvReader::read
bool read(QIODevice *device)
Parses the csv data from device.
Definition: qcsvreader.cpp:89
QLatin1Char
QCsvStandardBuilder::error
void error(const QString &errorMsg)
This method is called whenever an error occurs during parsing.
Definition: qcsvreader.cpp:403
QCsvReader::delimiter
QChar delimiter() const
Returns the delimiter that is used as delimiter for fields.
QCsvStandardBuilder::end
void end()
This method is called at the end of parsing.
Definition: qcsvreader.cpp:399
QCsvStandardBuilder::field
void field(const QString &data, uint row, uint column)
This method is called for every parsed field.
Definition: qcsvreader.cpp:381
QCsvReader::startRow
uint startRow() const
Returns the start row.
QCsvBuilderInterface
An interface to build data structures from a CSV file.
Definition: qcsvreader.h:36
QCsvStandardBuilder::lastErrorString
QString lastErrorString() const
Returns the error message of the last error.
Definition: qcsvreader.cpp:346
QString::length
int length() const
QCsvStandardBuilder::QCsvStandardBuilder
QCsvStandardBuilder()
Creates a new csv standard builder.
Definition: qcsvreader.cpp:336
QCsvReader::textCodec
QTextCodec * textCodec() const
Returns the text codec that is used for parsing the csv list.
Definition: qcsvreader.cpp:302
QCsvReader::QCsvReader
QCsvReader(QCsvBuilderInterface *builder)
Creates a new csv reader.
Definition: qcsvreader.cpp:78
QCsvStandardBuilder::columnCount
uint columnCount() const
Returns the number of columns.
Definition: qcsvreader.cpp:356
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:32:34 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kaddressbook

Skip menu "kaddressbook"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal