File indexing completed on 2025-09-14 03:42:58
0001 /* 0002 File : JsonOptionsWidget.cpp 0003 Project : LabPlot 0004 Description : Widget providing options for the import of json data. 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2018 Andrey Cygankov <craftplace.ms@gmail.com> 0007 SPDX-FileCopyrightText: 2018-2023 Alexander Semke <alexander.semke@web.de> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "JsonOptionsWidget.h" 0012 #include "ImportFileWidget.h" 0013 #include "backend/core/Settings.h" 0014 #include "backend/datasources/filters/AbstractFileFilter.h" 0015 #include "backend/datasources/filters/JsonFilter.h" 0016 #include "backend/datasources/filters/QJsonModel.h" 0017 #include "backend/lib/trace.h" 0018 0019 #include <KCompressionDevice> 0020 #include <KConfigGroup> 0021 #include <KLocalizedString> 0022 0023 /*! 0024 \class JsonOptionsWidget 0025 \brief Widget providing options for the import of json data 0026 0027 \ingroup kdefrontend 0028 */ 0029 JsonOptionsWidget::JsonOptionsWidget(QWidget* parent) 0030 : QWidget(parent) 0031 , m_model(new QJsonModel()) { 0032 ui.setupUi(parent); 0033 0034 ui.cbDecimalSeparator->addItem(i18n("Point '.'")); 0035 ui.cbDecimalSeparator->addItem(i18n("Comma ','")); 0036 ui.cbDateTimeFormat->addItems(AbstractColumn::dateTimeFormats()); 0037 0038 connect(m_model, &QJsonModel::error, this, &JsonOptionsWidget::error); 0039 0040 setTooltips(); 0041 } 0042 0043 void JsonOptionsWidget::applyFilterSettings(JsonFilter* filter, const QModelIndex& index) const { 0044 Q_ASSERT(filter); 0045 0046 filter->setModel(m_model); 0047 filter->setModelRows(getIndexRows(index)); 0048 0049 QLocale::Language lang; 0050 if (ui.cbDecimalSeparator->currentIndex() == 0) 0051 lang = QLocale::Language::C; 0052 else 0053 lang = QLocale::Language::German; 0054 filter->setNumberFormat(lang); 0055 0056 filter->setDateTimeFormat(ui.cbDateTimeFormat->currentText()); 0057 filter->setCreateIndexEnabled(ui.chbCreateIndex->isChecked()); 0058 filter->setNaNValueToZero(ui.chbConvertNaNToZero->isChecked()); 0059 filter->setImportObjectNames(ui.chbImportObjectNames->isChecked()); 0060 0061 // TODO: change this after implementation other row types 0062 filter->setDataRowType(QJsonValue::Array); 0063 if (!index.isValid()) 0064 return; 0065 auto* item = static_cast<QJsonTreeItem*>(index.internalPointer()); 0066 if (item->childCount() < 1) 0067 return; 0068 filter->setDataRowType(item->child(0)->type()); 0069 } 0070 0071 void JsonOptionsWidget::clearModel() { 0072 m_model->clear(); 0073 m_filename.clear(); 0074 } 0075 0076 void JsonOptionsWidget::loadSettings() const { 0077 KConfigGroup conf = Settings::group(QStringLiteral("ImportJson")); 0078 0079 const auto decimalSeparator = QLocale().decimalPoint(); 0080 int index = (decimalSeparator == QLatin1Char('.')) ? 0 : 1; 0081 ui.cbDecimalSeparator->setCurrentIndex(conf.readEntry("DecimalSeparator", index)); 0082 0083 ui.cbDateTimeFormat->setCurrentItem(conf.readEntry("DateTimeFormat", "yyyy-MM-dd hh:mm:ss.zzz")); 0084 ui.chbCreateIndex->setChecked(conf.readEntry("CreateIndex", false)); 0085 ui.chbConvertNaNToZero->setChecked(conf.readEntry("ConvertNaNToZero", false)); 0086 ui.chbImportObjectNames->setChecked(conf.readEntry("ParseRowsName", false)); 0087 } 0088 0089 void JsonOptionsWidget::saveSettings() { 0090 KConfigGroup conf = Settings::group(QStringLiteral("ImportJson")); 0091 0092 conf.writeEntry("DecimalSeparator", ui.cbDecimalSeparator->currentIndex()); 0093 conf.writeEntry("DateTimeFormat", ui.cbDateTimeFormat->currentText()); 0094 conf.writeEntry("CreateIndex", ui.chbCreateIndex->isChecked()); 0095 conf.writeEntry("ConvertNaNToZero", ui.chbConvertNaNToZero->isChecked()); 0096 conf.writeEntry("ParseRowsName", ui.chbImportObjectNames->isChecked()); 0097 } 0098 0099 void JsonOptionsWidget::loadDocument(const QString& filename) { 0100 PERFTRACE(QStringLiteral("JsonOptionsWidget::loadDocument")); 0101 if (m_filename == filename) 0102 return; 0103 else 0104 m_filename = filename; 0105 0106 KCompressionDevice device(m_filename); 0107 m_model->clear(); 0108 if (!device.open(QIODevice::ReadOnly) || (device.atEnd() && !device.isSequential()) || // empty file 0109 !m_model->loadJson(device.readAll())) 0110 clearModel(); 0111 } 0112 0113 QAbstractItemModel* JsonOptionsWidget::model() { 0114 return m_model; 0115 } 0116 0117 void JsonOptionsWidget::setTooltips() { 0118 const QString textNumberFormatShort = i18n("This option determines how the imported strings have to be converted to numbers."); 0119 const QString textNumberFormat = textNumberFormatShort + QStringLiteral("<br><br>") 0120 + i18n("For 'C Format', a period is used for the decimal point character and comma is used for the thousands group separator. " 0121 "Valid number representations are:" 0122 "<ul>" 0123 "<li>1234.56</li>" 0124 "<li>1,234.56</li>" 0125 "<li>etc.</li>" 0126 "</ul>" 0127 "When using 'System locale', the system settings will be used. " 0128 "E.g., for the German local the valid number representations are:" 0129 "<ul>" 0130 "<li>1234,56</li>" 0131 "<li>1.234,56</li>" 0132 "<li>etc.</li>" 0133 "</ul>"); 0134 0135 ui.lDecimalSeparator->setToolTip(textNumberFormatShort); 0136 ui.lDecimalSeparator->setWhatsThis(textNumberFormat); 0137 ui.cbDecimalSeparator->setToolTip(textNumberFormatShort); 0138 ui.cbDecimalSeparator->setWhatsThis(textNumberFormat); 0139 0140 const QString textDateTimeFormatShort = i18n( 0141 "This option determines how the imported strings have to be converted to calendar date, i.e. year, month, and day numbers in the Gregorian calendar " 0142 "and to time."); 0143 const QString textDateTimeFormat = textDateTimeFormatShort + QStringLiteral("<br><br>") 0144 + i18n("Expressions that may be used for the date part of format string:" 0145 "<table>" 0146 "<tr><td>d</td><td>the day as number without a leading zero (1 to 31).</td></tr>" 0147 "<tr><td>dd</td><td>the day as number with a leading zero (01 to 31).</td></tr>" 0148 "<tr><td>ddd</td><td>the abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses the system locale to localize the name.</td></tr>" 0149 "<tr><td>dddd</td><td>the long localized day name (e.g. 'Monday' to 'Sunday'). Uses the system locale to localize the name.</td></tr>" 0150 "<tr><td>M</td><td>the month as number without a leading zero (1 to 12).</td></tr>" 0151 "<tr><td>MM</td><td>the month as number with a leading zero (01 to 12).</td></tr>" 0152 "<tr><td>MMM</td><td>the abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses the system locale to localize the name.</td></tr>" 0153 "<tr><td>MMMM</td><td>the long localized month name (e.g. 'January' to 'December'). Uses the system locale to localize the name.</td></tr>" 0154 "<tr><td>yy</td><td>the year as two digit number (00 to 99).</td></tr>" 0155 "<tr><td>yyyy</td><td>the year as four digit number. If the year is negative, a minus sign is prepended in addition.</td></tr>" 0156 "</table><br><br>" 0157 "Expressions that may be used for the time part of the format string:" 0158 "<table>" 0159 "<tr><td>h</td><td>the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)</td></tr>" 0160 "<tr><td>hh</td><td>the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)</td></tr>" 0161 "<tr><td>H</td><td>the hour without a leading zero (0 to 23, even with AM/PM display)</td></tr>" 0162 "<tr><td>HH</td><td>the hour with a leading zero (00 to 23, even with AM/PM display)</td></tr>" 0163 "<tr><td>m</td><td>the minute without a leading zero (0 to 59)</td></tr>" 0164 "<tr><td>mm</td><td>the minute with a leading zero (00 to 59)</td></tr>" 0165 "<tr><td>s</td><td>the second without a leading zero (0 to 59)</td></tr>" 0166 "<tr><td>ss</td><td>the second with a leading zero (00 to 59)</td></tr>" 0167 "<tr><td>z</td><td>the milliseconds without leading zeroes (0 to 999)</td></tr>" 0168 "<tr><td>zzz</td><td>the milliseconds with leading zeroes (000 to 999)</td></tr>" 0169 "<tr><td>AP or A</td><td>interpret as an AM/PM time. AP must be either 'AM' or 'PM'.</td></tr>" 0170 "<tr><td>ap or a</td><td>Interpret as an AM/PM time. ap must be either 'am' or 'pm'.</td></tr>" 0171 "</table><br><br>" 0172 "Examples are:" 0173 "<table>" 0174 "<tr><td>dd.MM.yyyy</td><td>20.07.1969</td></tr>" 0175 "<tr><td>ddd MMMM d yy</td><td>Sun July 20 69</td></tr>" 0176 "<tr><td>'The day is' dddd</td><td>The day is Sunday</td></tr>" 0177 "</table>"); 0178 0179 ui.lDateTimeFormat->setToolTip(textDateTimeFormatShort); 0180 ui.lDateTimeFormat->setWhatsThis(textDateTimeFormat); 0181 ui.cbDateTimeFormat->setToolTip(textDateTimeFormatShort); 0182 ui.cbDateTimeFormat->setWhatsThis(textDateTimeFormat); 0183 } 0184 0185 QVector<int> JsonOptionsWidget::getIndexRows(const QModelIndex& index) const { 0186 QVector<int> rows; 0187 QModelIndex current = index; 0188 while (current.isValid()) { 0189 rows.prepend(current.row()); 0190 current = current.parent(); 0191 } 0192 return rows; 0193 }