labplot  2.8.2
About: LabPlot is an application for plotting and analysis of 2D and 3D functions and data. It is a complete rewrite of LabPlot1 and lacks in the first release a lot of features available in the predecessor. On the other hand, the GUI and the usability is more superior.
  Fossies Dox: labplot-2.8.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

JsonFilter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : JsonFilter.cpp
3  Project : LabPlot
4  Description : JSON I/O-filter.
5  --------------------------------------------------------------------
6  --------------------------------------------------------------------
7  Copyright : (C) 2018 Andrey Cygankov (craftplace.ms@gmail.com)
8  Copyright : (C) 2018-2020 Alexander Semke (alexander.semke@web.de)
9  Copyright : (C) 2018-2020 Stefan Gerlach (stefan.gerlach@uni.kn)
10 
11  ***************************************************************************/
12 
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  * This program is distributed in the hope that it will be useful, *
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23  * GNU General Public License for more details. *
24  * *
25  * You should have received a copy of the GNU General Public License *
26  * along with this program; if not, write to the Free Software *
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
28  * Boston, MA 02110-1301 USA *
29  * *
30  ***************************************************************************/
31 
37 #include "backend/lib/trace.h"
38 
39 #include <QJsonDocument>
40 #include <QJsonObject>
41 #include <QJsonArray>
42 #include <QDataStream>
43 #include <QDateTime>
44 
45 #include <KLocalizedString>
46 #include <KFilterDev>
47 
48 /*!
49 \class JsonFilter
50 \brief Manages the import/export of data from/to a file formatted using JSON.
51 
52 \ingroup datasources
53 */
55 
56 JsonFilter::~JsonFilter() = default;
57 
58 /*!
59 reads the content of the device \c device.
60 */
61 void JsonFilter::readDataFromDevice(QIODevice& device, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode, int lines) {
62  d->readDataFromDevice(device, dataSource, importMode, lines);
63 }
64 
65 /*!
66 reads the content of the file \c fileName.
67 */
68 void JsonFilter::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) {
69  d->readDataFromFile(fileName, dataSource, importMode);
70 }
71 
72 QVector<QStringList> JsonFilter::preview(const QString& fileName, int lines) {
73  return d->preview(fileName, lines);
74 }
75 
76 QVector<QStringList> JsonFilter::preview(QIODevice& device, int lines) {
77  return d->preview(device, lines);
78 }
79 
80 // QVector<QStringList> JsonFilter::preview(const QJsonDocument& doc) {
81 // return d->preview(doc);
82 // }
83 
84 /*!
85 writes the content of the data source \c dataSource to the file \c fileName.
86 */
87 void JsonFilter::write(const QString& fileName, AbstractDataSource* dataSource) {
88  d->write(fileName, dataSource);
89 }
90 
91 ///////////////////////////////////////////////////////////////////////
92 /*!
93 loads the predefined filter settings for \c filterName
94 */
95 void JsonFilter::loadFilterSettings(const QString& filterName) {
96  Q_UNUSED(filterName);
97 }
98 
99 /*!
100 saves the current settings as a new filter with the name \c filterName
101 */
102 void JsonFilter::saveFilterSettings(const QString& filterName) const {
103  Q_UNUSED(filterName);
104 }
105 
106 /*!
107 returns the list of all predefined data types.
108 */
109 QStringList JsonFilter::dataTypes() {
110  const QMetaObject& mo = AbstractColumn::staticMetaObject;
111  const QMetaEnum& me = mo.enumerator(mo.indexOfEnumerator("ColumnMode"));
112  QStringList list;
113  for (int i = 0; i <= 100; ++i) // me.keyCount() does not work because we have holes in enum
114  if (me.valueToKey(i))
115  list << me.valueToKey(i);
116  return list;
117 }
118 
119 /*!
120 returns the list of all predefined data row types.
121 */
123  return (QStringList() << "Array" << "Object");
124 }
125 
126 void JsonFilter::setDataRowType(QJsonValue::Type type) {
127  d->rowType = type;
128 }
129 QJsonValue::Type JsonFilter::dataRowType() const {
130  return d->rowType;
131 }
132 
134  d->model = model;
135 }
136 
138  d->modelRows = rows;
139 }
140 
142  return d->modelRows;
143 }
144 
145 void JsonFilter::setDateTimeFormat(const QString &f) {
146  d->dateTimeFormat = f;
147 }
148 QString JsonFilter::dateTimeFormat() const {
149  return d->dateTimeFormat;
150 }
151 
152 void JsonFilter::setNumberFormat(QLocale::Language lang) {
153  d->numberFormat = lang;
154 }
155 QLocale::Language JsonFilter::numberFormat() const {
156  return d->numberFormat;
157 }
158 
160  if (b)
161  d->nanValue = 0;
162  else
163  d->nanValue = NAN;
164 }
166  if (d->nanValue == 0)
167  return true;
168  return false;
169 }
170 
172  d->createIndexEnabled = b;
173 }
174 
176  d->importObjectNames = b;
177 }
178 
179 QStringList JsonFilter::vectorNames() const {
180  return d->vectorNames;
181 }
182 
184  return d->columnModes;
185 }
186 
187 void JsonFilter::setStartRow(const int r) {
188  d->startRow = r;
189 }
190 int JsonFilter::startRow() const {
191  return d->startRow;
192 }
193 
194 void JsonFilter::setEndRow(const int r) {
195  d->endRow = r;
196 }
197 int JsonFilter::endRow() const {
198  return d->endRow;
199 }
200 
201 void JsonFilter::setStartColumn(const int c) {
202  d->startColumn = c;
203 }
205  return d->startColumn;
206 }
207 
208 void JsonFilter::setEndColumn(const int c) {
209  d->endColumn = c;
210 }
212  return d->endColumn;
213 }
214 
215 QString JsonFilter::fileInfoString(const QString& fileName) {
216  DEBUG("JsonFilter::fileInfoString()");
217 
218  KFilterDev device(fileName);
219 
220  if (!device.open(QIODevice::ReadOnly))
221  return i18n("Open device failed");
222 
223  if (device.atEnd() && !device.isSequential())
224  return i18n("Empty file");
225 
226  QJsonParseError err;
227  QJsonDocument doc = QJsonDocument::fromJson(device.readAll(), &err);
228 
229  if (err.error != QJsonParseError::NoError || doc.isEmpty())
230  return i18n("Parse error: %1 at offset %2", err.errorString(), err.offset);
231 
232  QString info;
233  info += i18n("Valid JSON document");
234 
235  //TODO: get number of object, etc.
236  //if (prepareDocumentToRead(doc) != 0)
237  // return info;
238 
239  // reset to start of file
240  if (!device.isSequential())
241  device.seek(0);
242 
243  return info;
244 }
245 
246 //#####################################################################
247 //################### Private implementation ##########################
248 //#####################################################################
250 
251 }
252 
253 /*!
254 returns 1 if row is invalid and 0 otherwise.
255 */
256 int JsonFilterPrivate::checkRow(QJsonValueRef value, int& countCols) {
257  switch (rowType) {
258  //TODO: implement other value types
259  case QJsonValue::Array: {
260  QJsonArray row = value.toArray();
261  if (row.isEmpty())
262  return 1;
263  countCols = (countCols == -1 || countCols > row.count()) ? row.count() : countCols;
264  break;
265  }
266  case QJsonValue::Object: {
267  QJsonObject row = value.toObject();
268  if (row.isEmpty())
269  return 1;
270  countCols = (countCols == -1 || countCols > row.count()) ? row.count() : countCols;
271  break;
272  }
273  case QJsonValue::Double:
274  case QJsonValue::String:
275  case QJsonValue::Bool:
276  case QJsonValue::Null:
277  case QJsonValue::Undefined:
278  return 1;
279  }
280  return 0;
281 }
282 
283 /*!
284 returns -1 if a parse error has occurred, 1 if the current row type not supported and 0 otherwise.
285 */
286 int JsonFilterPrivate::parseColumnModes(const QJsonValue& row, const QString& rowName) {
287  columnModes.clear();
288  vectorNames.clear();
289 
290  //add index column if required
291  if (createIndexEnabled) {
293  vectorNames << i18n("index");
294  }
295 
296  //add column for object names if required
297  if (importObjectNames) {
299  columnModes << mode;
301  vectorNames << i18n("timestamp");
303  vectorNames << i18n("month");
305  vectorNames << i18n("day");
306  else
307  vectorNames << i18n("name");
308  }
309 
310  //determine the column modes and names
311  for (int i = startColumn - 1; i < endColumn; ++i) {
312  QJsonValue columnValue;
313  switch (rowType) {
314  case QJsonValue::Array: {
315  columnValue = *(row.toArray().begin() + i);
316  vectorNames << i18n("Column %1", QString::number(i + 1));
317  break;
318  }
319  case QJsonValue::Object: {
320  QString key = row.toObject().keys().at(i);
321  vectorNames << key;
322  columnValue = row.toObject().value(key);
323  break;
324  }
325  //TODO: implement other value types
326  case QJsonValue::Double:
327  case QJsonValue::String:
328  case QJsonValue::Bool:
329  case QJsonValue::Null:
330  case QJsonValue::Undefined:
331  return 1;
332  }
333 
334  switch (columnValue.type()) {
335  case QJsonValue::Double:
337  break;
338  case QJsonValue::String:
340  break;
341  case QJsonValue::Array:
342  case QJsonValue::Object:
343  case QJsonValue::Bool:
344  case QJsonValue::Null:
345  case QJsonValue::Undefined:
346  return -1;
347  }
348  }
349 
350  return 0;
351 }
352 
353 void JsonFilterPrivate::setEmptyValue(int column, int row) {
354  switch (columnModes[column]) {
356  static_cast<QVector<double>*>(m_dataContainer[column])->operator[](row) = nanValue;
357  break;
359  static_cast<QVector<int>*>(m_dataContainer[column])->operator[](row) = 0;
360  break;
362  static_cast<QVector<qint64>*>(m_dataContainer[column])->operator[](row) = 0;
363  break;
365  static_cast<QVector<QDateTime>*>(m_dataContainer[column])->operator[](row) = QDateTime();
366  break;
368  static_cast<QVector<QString>*>(m_dataContainer[column])->operator[](row) = QString();
369  break;
372  break;
373  }
374 }
375 
376 void JsonFilterPrivate::setValueFromString(int column, int row, const QString& valueString) {
377  QLocale locale(numberFormat);
378  switch (columnModes[column]) {
380  bool isNumber;
381  const double value = locale.toDouble(valueString, &isNumber);
382  static_cast<QVector<double>*>(m_dataContainer[column])->operator[](row) = isNumber ? value : nanValue;
383  break;
384  }
386  bool isNumber;
387  const int value = locale.toInt(valueString, &isNumber);
388  static_cast<QVector<int>*>(m_dataContainer[column])->operator[](row) = isNumber ? value : 0;
389  break;
390  }
392  bool isNumber;
393  const qint64 value = locale.toLongLong(valueString, &isNumber);
394  static_cast<QVector<qint64>*>(m_dataContainer[column])->operator[](row) = isNumber ? value : 0;
395  break;
396  }
398  const QDateTime valueDateTime = QDateTime::fromString(valueString, dateTimeFormat);
399  static_cast<QVector<QDateTime>*>(m_dataContainer[column])->operator[](row) =
400  valueDateTime.isValid() ? valueDateTime : QDateTime();
401  break;
402  }
404  static_cast<QVector<QString>*>(m_dataContainer[column])->operator[](row) = valueString;
405  break;
408  break;
409  }
410 }
411 
412 /*!
413 returns -1 if the device couldn't be opened, 1 if the current read position in the device is at the end
414 */
416  DEBUG("device is sequential = " << device.isSequential());
417 
418  if (!device.open(QIODevice::ReadOnly))
419  return -1;
420 
421  if (device.atEnd() && !device.isSequential()) // empty file
422  return 1;
423 
424  QJsonParseError err;
425  m_doc = QJsonDocument::fromJson(device.readAll(), &err);
426 
427  if (err.error != QJsonParseError::NoError || m_doc.isEmpty())
428  return 1;
429 
430  // reset to start of file
431  if (!device.isSequential())
432  device.seek(0);
433 
434  return 0;
435 }
436 
437 /*!
438  determines the relevant part of the full JSON document to be read and its structure.
439  returns \c true if successful, \c false otherwise.
440 */
442  PERFTRACE("Prepare the JSON document to read");
443 
444  if (modelRows.isEmpty())
446  else {
447  if (modelRows.size() == 1)
448  m_preparedDoc = m_doc; //root element selected, use the full document
449  else {
450  //when running tests there is no ImportFileWidget and JsonOptionsWidget available
451  //where the model is created and also passed to JsonFilter. So, we need to create
452  //a model here for in this case.
453  if (!model) {
454  model = new QJsonModel();
455  model->loadJson(m_doc);
456  }
457 
458  QModelIndex index;
459  for (auto& it : modelRows)
460  index = model->index(it, 0, index);
461 
463  }
464  }
465 
466  if (!m_preparedDoc.isEmpty()) {
467  if (m_preparedDoc.isArray())
469  else if (m_preparedDoc.isObject())
471  else
472  return false;
473  } else
474  return false;
475 
476  int countRows = 0;
477  int countCols = -1;
478  QJsonValue firstRow;
479  QString firstRowName;
480  importObjectNames = (importObjectNames && (rowType == QJsonValue::Object));
481 
482  switch (containerType) {
484  QJsonArray arr = m_preparedDoc.array();
485  int count = arr.count();
486 
487  if (count < startRow)
488  return false;
489 
490  int endRowOffset = (endRow == -1 || endRow > count) ? count : endRow;
491  firstRow = *(arr.begin() + (startRow - 1));
492  for (QJsonArray::iterator it = arr.begin() + (startRow - 1); it != arr.begin() + endRowOffset; ++it) {
493  if (checkRow(*it, countCols) != 0)
494  return false;
495  countRows++;
496  }
497  break;
498  }
500  QJsonObject obj = m_preparedDoc.object();
501 
502  if (obj.count() < startRow)
503  return false;
504 
505  int startRowOffset = startRow - 1;
506  int endRowOffset = (endRow == -1 || endRow > obj.count()) ? obj.count() : endRow;
507  firstRow = *(obj.begin() + startRowOffset);
508  firstRowName = (obj.begin() + startRowOffset).key();
509  for (QJsonObject::iterator it = obj.begin() + startRowOffset; it != obj.begin() + endRowOffset; ++it) {
510  if (checkRow(*it, countCols) != 0)
511  return false;
512  countRows++;
513  }
514  break;
515  }
516  }
517 
518  if (endColumn == -1 || endColumn > countCols)
519  endColumn = countCols;
520 
521  m_actualRows = countRows;
523 
524  if (parseColumnModes(firstRow, firstRowName) != 0)
525  return false;
526 
527  DEBUG("start/end column: = " << startColumn << ' ' << endColumn);
528  DEBUG("start/end rows = " << startRow << ' ' << endRow);
529  DEBUG("actual cols/rows = " << m_actualCols << ' ' << m_actualRows);
530 
531  return true;
532 }
533 
534 /*!
535 reads the content of the file \c fileName to the data source \c dataSource. Uses the settings defined in the data source.
536 */
537 void JsonFilterPrivate::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) {
538  KFilterDev device(fileName);
539  readDataFromDevice(device, dataSource, importMode);
540 }
541 
542 /*!
543 reads the content of device \c device to the data source \c dataSource. Uses the settings defined in the data source.
544 */
545 void JsonFilterPrivate::readDataFromDevice(QIODevice& device, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode, int lines) {
546  if (!m_prepared) {
547  const int deviceError = prepareDeviceToRead(device);
548  if (deviceError != 0) {
549  DEBUG("Device error = " << deviceError);
550  return;
551  }
552  //TODO: support other modes and vector names
553  m_prepared = true;
554  }
555 
556  if (prepareDocumentToRead())
557  importData(dataSource, importMode, lines);
558 }
559 
560 /*!
561 import the content of document \c m_preparedDoc to the data source \c dataSource. Uses the settings defined in the data source.
562 */
564  Q_UNUSED(lines)
565 
567  int rowOffset = startRow - 1;
568  int colOffset = (int)createIndexEnabled + (int)importObjectNames;
569  DEBUG("reading " << m_actualRows << " lines");
570  DEBUG("reading " << m_actualCols << " columns");
571 
572  int progressIndex = 0;
573  const float progressInterval = 0.01*lines; //update on every 1% only
574 
575  const auto& array = m_preparedDoc.array();
576  const auto& arrayIterator = array.begin();
577  const auto& object = m_preparedDoc.object();
578  const auto& objectIterator = object.begin();
579 
580  for (int i = 0; i < m_actualRows; ++i) {
581  if (createIndexEnabled)
582  static_cast<QVector<int>*>(m_dataContainer[0])->operator[](i) = i + 1;
583 
584  QJsonValue row;
585  switch (containerType) {
587  row = *(arrayIterator + rowOffset + i);
588  break;
590  if (importObjectNames) {
591  const QString& rowName = (objectIterator + rowOffset + i).key();
592  setValueFromString((int)createIndexEnabled, i, rowName);
593  }
594  row = *(objectIterator + rowOffset + i);
595  break;
596  }
597 
598  for (int n = 0; n < m_actualCols - colOffset; ++n) {
599  QJsonValue value;
600  switch (rowType) {
601  case QJsonValue::Array:
602  value = *(row.toArray().begin() + n + startColumn -1);
603  break;
604  case QJsonValue::Object:
605  value = *(row.toObject().begin() + n + startColumn - 1);
606  break;
607  //TODO: implement other value types
608  case QJsonValue::Double:
609  case QJsonValue::String:
610  case QJsonValue::Bool:
611  case QJsonValue::Null:
612  case QJsonValue::Undefined:
613  break;
614  }
615 
616  switch (value.type()) {
617  case QJsonValue::Double:
618  if (columnModes[colOffset + n] == AbstractColumn::ColumnMode::Numeric)
619  static_cast<QVector<double>*>(m_dataContainer[colOffset + n])->operator[](i) = value.toDouble();
620  else
621  setEmptyValue(colOffset + n, i + startRow - 1);
622  break;
623  case QJsonValue::String:
624  setValueFromString(colOffset + n, i, value.toString());
625  break;
626  case QJsonValue::Array:
627  case QJsonValue::Object:
628  case QJsonValue::Bool:
629  case QJsonValue::Null:
630  case QJsonValue::Undefined:
631  setEmptyValue(colOffset + n, i + startRow - 1);
632  break;
633  }
634  }
635 
636  //ask to update the progress bar only if we have more than 1000 lines
637  //only in 1% steps
638  progressIndex++;
639  if (m_actualRows > 1000 && progressIndex > progressInterval) {
640  emit q->completed(100 * i/m_actualRows);
641  progressIndex = 0;
642  QApplication::processEvents(QEventLoop::AllEvents, 0);
643  }
644  }
645 
646  //set the plot designation to 'X' for index and name columns, if available
647  Spreadsheet* spreadsheet = dynamic_cast<Spreadsheet*>(dataSource);
648  if (spreadsheet) {
649  if (createIndexEnabled)
651  if (importObjectNames)
652  spreadsheet->column(m_columnOffset + (int)createIndexEnabled)->setPlotDesignation(AbstractColumn::PlotDesignation::X);
653  }
654 
656 }
657 
658 /*!
659 generates the preview for the file \c fileName.
660 */
661 QVector<QStringList> JsonFilterPrivate::preview(const QString& fileName, int lines) {
662  if (!m_prepared) {
663  KFilterDev device(fileName);
664  return preview(device, lines);
665  } else
666  return preview(lines);
667 }
668 
669 /*!
670 generates the preview for device \c device.
671 */
672 QVector<QStringList> JsonFilterPrivate::preview(QIODevice& device, int lines) {
673  if (!m_prepared) {
674  const int deviceError = prepareDeviceToRead(device);
675  if (deviceError != 0) {
676  DEBUG("Device error = " << deviceError);
677  return QVector<QStringList>();
678  }
679  }
680 
681  if (prepareDocumentToRead())
682  return preview(lines);
683  else
684  return QVector<QStringList>();
685 }
686 
687 /*!
688 generates the preview for document \c m_preparedDoc.
689 */
691  QVector<QStringList> dataStrings;
692  const int rowOffset = startRow - 1;
693  DEBUG(" Generating preview for " << qMin(lines, m_actualRows) << " lines");
694 
695  const auto& array = m_preparedDoc.array();
696  const auto& arrayIterator = array.begin();
697  const auto& object = m_preparedDoc.object();
698  const auto& objectIterator = object.begin();
699 
700  for (int i = 0; i < qMin(lines, m_actualRows); ++i) {
701  QString rowName;
702  QJsonValue row;
703  switch (containerType) {
705  rowName = (objectIterator + rowOffset + i).key();
706  row = *(objectIterator + rowOffset + i);
707  break;
709  row = *(arrayIterator + rowOffset + i);
710  break;
711  }
712 
713  QStringList lineString;
714  if (createIndexEnabled)
715  lineString += QString::number(i + 1);
716  if (importObjectNames)
717  lineString += rowName;
718 
719  for (int n = startColumn - 1; n < endColumn; ++n) {
720  QJsonValue value;
721  switch (rowType) {
722  case QJsonValue::Object:
723  value = *(row.toObject().begin() + n);
724  break;
725  case QJsonValue::Array:
726  value = *(row.toArray().begin() + n);
727  break;
728  //TODO: implement other value types
729  case QJsonValue::Double:
730  case QJsonValue::String:
731  case QJsonValue::Bool:
732  case QJsonValue::Null:
733  case QJsonValue::Undefined:
734  break;
735  }
736 
737  switch (value.type()) {
738  case QJsonValue::Double:
739  lineString += QString::number(value.toDouble(), 'g', 16);
740  break;
741  case QJsonValue::String:
742  lineString += value.toString();
743  break;
744  case QJsonValue::Array:
745  case QJsonValue::Object:
746  case QJsonValue::Bool:
747  case QJsonValue::Null:
748  case QJsonValue::Undefined:
749  lineString += QString();
750  break;
751  }
752  }
753  dataStrings << lineString;
754  }
755  return dataStrings;
756 }
757 
758 /*!
759 writes the content of \c dataSource to the file \c fileName.
760 */
761 void JsonFilterPrivate::write(const QString& fileName, AbstractDataSource* dataSource) {
762  Q_UNUSED(fileName);
763  Q_UNUSED(dataSource);
764 
765  //TODO: saving data to json file not supported yet
766 }
767 
768 //##############################################################################
769 //################## Serialization/Deserialization ###########################
770 //##############################################################################
771 /*!
772 Saves as XML.
773 */
774 void JsonFilter::save(QXmlStreamWriter* writer) const {
775  writer->writeStartElement("jsonFilter");
776  writer->writeAttribute("rowType", QString::number(d->rowType));
777  writer->writeAttribute("dateTimeFormat", d->dateTimeFormat);
778  writer->writeAttribute("numberFormat", QString::number(d->numberFormat));
779  writer->writeAttribute("createIndex", QString::number(d->createIndexEnabled));
780  writer->writeAttribute("importObjectNames", QString::number(d->importObjectNames));
781  writer->writeAttribute("nanValue", QString::number(d->nanValue));
782  writer->writeAttribute("startRow", QString::number(d->startRow));
783  writer->writeAttribute("endRow", QString::number(d->endRow));
784  writer->writeAttribute("startColumn", QString::number(d->startColumn));
785  writer->writeAttribute("endColumn", QString::number(d->endColumn));
786 
787  QStringList list;
788  for (auto& it : modelRows())
789  list.append(QString::number(it));
790 
791  writer->writeAttribute("modelRows", list.join(';'));
792 
793  writer->writeEndElement();
794  DEBUG("JsonFilter save params");
795 }
796 
797 /*!
798 Loads from XML.
799 */
801  KLocalizedString attributeWarning = ki18n("Attribute '%1' missing or empty, default value is used");
802  QXmlStreamAttributes attribs = reader->attributes();
803  QString str;
804 
805  READ_INT_VALUE("rowType", rowType, QJsonValue::Type);
806  READ_STRING_VALUE("dateTimeFormat", dateTimeFormat);
807  READ_INT_VALUE("numberFormat", numberFormat, QLocale::Language);
808  READ_INT_VALUE("createIndex", createIndexEnabled, bool);
809  READ_INT_VALUE("importObjectNames", importObjectNames, bool);
810  READ_DOUBLE_VALUE("nanValue", nanValue);
811  READ_INT_VALUE("startRow", startRow, int);
812  READ_INT_VALUE("endRow", endRow, int);
813  READ_INT_VALUE("startColumn", startColumn, int);
814  READ_INT_VALUE("endColumn", endColumn, int);
815 
816  QStringList list = attribs.value("modelRows").toString().split(';');
817  if (list.isEmpty())
818  reader->raiseWarning(attributeWarning.subs("'modelRows'").toString());
819  else {
820  d->modelRows = QVector<int>();
821  for (auto& it : list)
822  d->modelRows.append(it.toInt());
823  }
824 
825  DEBUG("JsonFilter load params");
826  return true;
827 }
Interface for the data sources.
virtual int prepareImport(std::vector< void * > &dataContainer, AbstractFileFilter::ImportMode, int actualRows, int actualCols, QStringList colNameList=QStringList(), QVector< AbstractColumn::ColumnMode >=QVector< AbstractColumn::ColumnMode >())=0
virtual void finalizeImport(int columnOffset=0, int startColumn=0, int endColumn=0, const QString &dateTimeFormat=QString(), AbstractFileFilter::ImportMode importMode=AbstractFileFilter::ImportMode::Replace)=0
Interface for the input/output file filters.
FileType type() const
static AbstractColumn::ColumnMode columnMode(const QString &valueString, const QString &dateTimeFormat, QLocale::Language)
void completed(int) const
int ranging from 0 to 100 notifies about the status of a read/write process
void setPlotDesignation(AbstractColumn::PlotDesignation) override
Set the column plot designation.
Definition: Column.cpp:403
JsonFilterPrivate(JsonFilter *owner)
Definition: JsonFilter.cpp:249
QVector< AbstractColumn::ColumnMode > columnModes
void setValueFromString(int column, int row, const QString &value)
Definition: JsonFilter.cpp:376
const JsonFilter * q
bool prepareDocumentToRead()
Definition: JsonFilter.cpp:441
QVector< QStringList > preview(const QString &fileName, int lines)
Definition: JsonFilter.cpp:661
QJsonDocument m_preparedDoc
void importData(AbstractDataSource *=nullptr, AbstractFileFilter::ImportMode=AbstractFileFilter::ImportMode::Replace, int lines=-1)
Definition: JsonFilter.cpp:563
int parseColumnModes(const QJsonValue &row, const QString &rowName=QString())
Definition: JsonFilter.cpp:286
void setEmptyValue(int column, int row)
Definition: JsonFilter.cpp:353
void readDataFromDevice(QIODevice &, AbstractDataSource *=nullptr, AbstractFileFilter::ImportMode=AbstractFileFilter::ImportMode::Replace, int lines=-1)
Definition: JsonFilter.cpp:545
QLocale::Language numberFormat
QVector< int > modelRows
int checkRow(QJsonValueRef value, int &countCols)
Definition: JsonFilter.cpp:256
void write(const QString &fileName, AbstractDataSource *)
Definition: JsonFilter.cpp:761
QJsonValue::Type rowType
QStringList vectorNames
QJsonDocument m_doc
JsonFilter::DataContainerType containerType
void readDataFromFile(const QString &fileName, AbstractDataSource *=nullptr, AbstractFileFilter::ImportMode=AbstractFileFilter::ImportMode::Replace)
Definition: JsonFilter.cpp:537
int prepareDeviceToRead(QIODevice &)
Definition: JsonFilter.cpp:415
std::vector< void * > m_dataContainer
Manages the import/export of data from/to a file formatted using JSON.
Definition: JsonFilter.h:45
QVector< QStringList > preview(const QString &fileName, int lines)
Definition: JsonFilter.cpp:72
void setDataRowType(const QJsonValue::Type)
Definition: JsonFilter.cpp:126
bool NaNValueToZeroEnabled() const
Definition: JsonFilter.cpp:165
static QStringList dataTypes()
Definition: JsonFilter.cpp:109
void setEndRow(const int)
Definition: JsonFilter.cpp:194
void setStartColumn(const int)
Definition: JsonFilter.cpp:201
void loadFilterSettings(const QString &) override
Definition: JsonFilter.cpp:95
QLocale::Language numberFormat() const
Definition: JsonFilter.cpp:155
QString dateTimeFormat() const
Definition: JsonFilter.cpp:148
void setNumberFormat(QLocale::Language)
Definition: JsonFilter.cpp:152
void readDataFromFile(const QString &fileName, AbstractDataSource *=nullptr, AbstractFileFilter::ImportMode=AbstractFileFilter::ImportMode::Replace) override
Definition: JsonFilter.cpp:68
std::unique_ptr< JsonFilterPrivate > const d
Definition: JsonFilter.h:102
void setImportObjectNames(const bool)
Definition: JsonFilter.cpp:175
void setModel(QJsonModel *)
Definition: JsonFilter.cpp:133
void setModelRows(const QVector< int > &)
Definition: JsonFilter.cpp:137
void setStartRow(const int)
Definition: JsonFilter.cpp:187
bool load(XmlStreamReader *) override
Definition: JsonFilter.cpp:800
static QString fileInfoString(const QString &)
Definition: JsonFilter.cpp:215
void readDataFromDevice(QIODevice &device, AbstractDataSource *, AbstractFileFilter::ImportMode=AbstractFileFilter::ImportMode::Replace, int lines=-1)
Definition: JsonFilter.cpp:61
void setDateTimeFormat(const QString &)
Definition: JsonFilter.cpp:145
static QStringList dataRowTypes()
Definition: JsonFilter.cpp:122
QJsonValue::Type dataRowType() const
Definition: JsonFilter.cpp:129
QStringList vectorNames() const
Definition: JsonFilter.cpp:179
void saveFilterSettings(const QString &) const override
Definition: JsonFilter.cpp:102
void setCreateIndexEnabled(const bool)
Definition: JsonFilter.cpp:171
void setNaNValueToZero(const bool)
Definition: JsonFilter.cpp:159
int endColumn() const
Definition: JsonFilter.cpp:211
int startColumn() const
Definition: JsonFilter.cpp:204
int endRow() const
Definition: JsonFilter.cpp:197
QVector< AbstractColumn::ColumnMode > columnModes()
Definition: JsonFilter.cpp:183
~JsonFilter() override
void save(QXmlStreamWriter *) const override
Definition: JsonFilter.cpp:774
void write(const QString &fileName, AbstractDataSource *) override
Definition: JsonFilter.cpp:87
QVector< int > modelRows() const
Definition: JsonFilter.cpp:141
int startRow() const
Definition: JsonFilter.cpp:190
void setEndColumn(const int)
Definition: JsonFilter.cpp:208
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: QJsonModel.cpp:308
QJsonDocument genJsonByIndex(const QModelIndex &) const
Definition: QJsonModel.cpp:402
bool loadJson(const QByteArray &)
Definition: QJsonModel.cpp:209
Aspect providing a spreadsheet table with column logic.
Definition: Spreadsheet.h:40
Column * column(int index) const
XML stream parser that supports errors as well as warnings. This class also adds line and column numb...
void raiseWarning(const QString &)
#define READ_DOUBLE_VALUE(name, var)
Definition: macros.h:475
#define DEBUG(x)
Definition: macros.h:50
#define READ_INT_VALUE(name, var, type)
Definition: macros.h:468
#define READ_STRING_VALUE(name, var)
Definition: macros.h:482
@ NoError
Definition: qxtnamespace.h:64
std::string String(char *&buffer)
Get TString.
Definition: ROOTFilter.cpp:603
#define i18n(m)
Definition: nsl_common.h:38
#define PERFTRACE(msg)
Definition: trace.h:57