File indexing completed on 2025-07-13 03:32:33

0001 /*
0002     File                 : DatasetMetadataManagerWidget.cpp
0003     Project              : LabPlot
0004     Description          : widget for managing a metadata file of a dataset
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2019 Ferencz Kovacs <kferike98@gmail.com>
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "kdefrontend/datasources/DatasetMetadataManagerWidget.h"
0011 #include "backend/core/Settings.h"
0012 #include "backend/datasources/filters/AsciiFilter.h"
0013 #include "backend/lib/macros.h"
0014 #include "kdefrontend/DatasetModel.h"
0015 #include "kdefrontend/GuiTools.h"
0016 
0017 #include <KConfigGroup>
0018 
0019 #include <QDir>
0020 #include <QFile>
0021 #include <QHBoxLayout>
0022 #include <QJsonArray>
0023 #include <QJsonDocument>
0024 #include <QJsonObject>
0025 #include <QJsonValue>
0026 #include <QMap>
0027 #include <QMapIterator>
0028 #include <QRegularExpression>
0029 #include <QStringList>
0030 #include <QTcpSocket>
0031 #include <QUrl>
0032 
0033 /*!
0034     \class DatasetMetadataManagerWidget
0035     \brief Widget for adding a new dataset to LabPlot's current collection.
0036 
0037     \ingroup kdefrontend
0038  */
0039 DatasetMetadataManagerWidget::DatasetMetadataManagerWidget(QWidget* parent, const QMap<QString, QMap<QString, QMap<QString, QVector<QString>>>>& datasetMap)
0040     : QWidget(parent) {
0041     ui.setupUi(this);
0042     m_datasetModel = new DatasetModel(datasetMap);
0043 
0044     m_baseColor = GuiTools::isDarkMode() ? QStringLiteral("#5f5f5f") : QStringLiteral("#ffffff");
0045     m_textColor = GuiTools::isDarkMode() ? QStringLiteral("#ffffff") : QStringLiteral("#000000");
0046 
0047     ui.cbCollection->addItems(m_datasetModel->collections());
0048     ui.cbCategory->addItems(m_datasetModel->categories(ui.cbCollection->currentText()));
0049     ui.cbSubcategory->addItems(m_datasetModel->subcategories(ui.cbCollection->currentText(), ui.cbCategory->currentText()));
0050 
0051     ui.cbSeparatingCharacter->addItems(AsciiFilter::separatorCharacters());
0052     ui.cbCommentCharacter->addItems(AsciiFilter::commentCharacters());
0053     ui.cbNumberFormat->addItems(AbstractFileFilter::numberFormats());
0054     ui.cbDateTimeFormat->addItems(AbstractColumn::dateTimeFormats());
0055 
0056     connect(ui.leDatasetName, &QLineEdit::textChanged, [this] {
0057         Q_EMIT checkOk();
0058     });
0059     connect(ui.leDownloadURL, &QLineEdit::textChanged, [this] {
0060         Q_EMIT checkOk();
0061     });
0062     connect(ui.teDescription, &QTextEdit::textChanged, [this] {
0063         Q_EMIT checkOk();
0064     });
0065     connect(ui.leFileName, &QLineEdit::textChanged, [this] {
0066         Q_EMIT checkOk();
0067     });
0068 
0069     connect(ui.cbSubcategory, &QComboBox::currentTextChanged, [this] {
0070         Q_EMIT checkOk();
0071     });
0072 
0073     connect(ui.cbCollection, &QComboBox::currentTextChanged, this, &DatasetMetadataManagerWidget::updateCategories);
0074     connect(ui.cbCategory, &QComboBox::currentTextChanged, this, &DatasetMetadataManagerWidget::updateSubcategories);
0075     connect(ui.bNewColumn, &QPushButton::clicked, this, &DatasetMetadataManagerWidget::addColumnDescription);
0076     connect(ui.bDelete, &QPushButton::clicked, this, &DatasetMetadataManagerWidget::removeColumnDescription);
0077 
0078     loadSettings();
0079 }
0080 
0081 DatasetMetadataManagerWidget::~DatasetMetadataManagerWidget() {
0082     KConfigGroup conf = Settings::group(QStringLiteral("DatasetMetadataManagerWidget"));
0083 
0084     // filter settings
0085     conf.writeEntry("separator", ui.cbSeparatingCharacter->currentText());
0086     conf.writeEntry("commentChar", ui.cbCommentCharacter->currentText());
0087     conf.writeEntry("numberFormat", ui.cbNumberFormat->currentIndex());
0088     conf.writeEntry("dateTimeFormat", ui.cbDateTimeFormat->currentText());
0089     conf.writeEntry("createIndexColumn", ui.chbCreateIndex->isChecked());
0090     conf.writeEntry("skipEmptyParts", ui.chbSkipEmptyParts->isChecked());
0091     conf.writeEntry("simplifyWhitespaces", ui.chbSimplifyWhitespaces->isChecked());
0092     conf.writeEntry("removeQuotes", ui.chbRemoveQuotes->isChecked());
0093     conf.writeEntry("useFirstRowForVectorName", ui.chbHeader->isChecked());
0094     conf.writeEntry("collection", ui.cbCollection->currentText());
0095     conf.writeEntry("category", ui.cbCategory->currentText());
0096     conf.writeEntry("subcategory", ui.cbSubcategory->currentText());
0097 }
0098 
0099 /**
0100  * @brief Loads the settings of the widget.
0101  */
0102 void DatasetMetadataManagerWidget::loadSettings() {
0103     KConfigGroup conf = Settings::group(QStringLiteral("DatasetMetadataManagerWidget"));
0104     ui.cbCommentCharacter->setCurrentItem(conf.readEntry("commentChar", "#"));
0105     ui.cbSeparatingCharacter->setCurrentItem(conf.readEntry("separator", "auto"));
0106     // TODO: use general setting for decimal separator?
0107     ui.cbNumberFormat->setCurrentIndex(conf.readEntry("numberFormat", static_cast<int>(QLocale::AnyLanguage)));
0108     ui.cbDateTimeFormat->setCurrentItem(conf.readEntry("dateTimeFormat", "yyyy-MM-dd hh:mm:ss.zzz"));
0109     ui.chbCreateIndex->setChecked(conf.readEntry("createIndexColumn", false));
0110     ui.chbSimplifyWhitespaces->setChecked(conf.readEntry("simplifyWhitespaces", true));
0111     ui.chbRemoveQuotes->setChecked(conf.readEntry("removeQuotes", false));
0112     ui.chbSkipEmptyParts->setChecked(conf.readEntry("skipEmptyParts", false));
0113     ui.chbHeader->setChecked(conf.readEntry("useFirstRowForVectorName", true));
0114 
0115     QString lastCollection = conf.readEntry("collection", "");
0116     if (m_datasetModel->collections().contains(lastCollection))
0117         ui.cbCollection->setCurrentText(lastCollection);
0118 
0119     QString lastCategory = conf.readEntry("category", "");
0120     if (m_datasetModel->categories(ui.cbCollection->currentText()).contains(lastCategory))
0121         ui.cbCategory->setCurrentText(lastCategory);
0122 
0123     QString lastSubcategory = conf.readEntry("subcategory", "");
0124     if (m_datasetModel->subcategories(ui.cbCollection->currentText(), ui.cbCategory->currentText()).contains(lastSubcategory))
0125         ui.cbSubcategory->setCurrentText(lastSubcategory);
0126 }
0127 
0128 /**
0129  * @brief Checks whether leFileName contains a valid file name.
0130  */
0131 bool DatasetMetadataManagerWidget::checkFileName() {
0132     const QString fileName = ui.leFileName->text();
0133 
0134     // check whether it contains only digits, letters, -, _ or not
0135     const QRegularExpression re(QLatin1String("^[\\w\\d-]+$"));
0136     const QRegularExpressionMatch match = re.match(fileName);
0137     bool hasMatch = match.hasMatch();
0138 
0139     if (!hasMatch || fileName.isEmpty()) {
0140         DEBUG("File name invalid");
0141         QPalette palette;
0142         palette.setColor(QPalette::Base, Qt::red);
0143         palette.setColor(QPalette::Text, Qt::black);
0144         ui.leFileName->setPalette(palette);
0145         ui.leFileName->setToolTip(QStringLiteral("Invalid name for a file (it can contain:digits, letters, -, _)"));
0146     } else {
0147         QPalette palette;
0148         palette.setColor(QPalette::Base, m_baseColor);
0149         palette.setColor(QPalette::Text, m_textColor);
0150         ui.leFileName->setPalette(palette);
0151         ui.leFileName->setToolTip(QString());
0152     }
0153 
0154     // check whether there already is a file named like this or not.
0155     bool found = false;
0156 
0157     if (m_datasetModel->allDatasetsList().toStringList().contains(fileName)) {
0158         DEBUG("There already is a metadata file with this name");
0159         QPalette palette;
0160         palette.setColor(QPalette::Base, Qt::red);
0161         palette.setColor(QPalette::Text, Qt::black);
0162         ui.leFileName->setPalette(palette);
0163         ui.leFileName->setToolTip(QStringLiteral("There already is a dataset metadata file with this name!"));
0164         found = true;
0165     } else {
0166         if (hasMatch) {
0167             QPalette palette;
0168             palette.setColor(QPalette::Base, m_baseColor);
0169             palette.setColor(QPalette::Text, m_textColor);
0170             ui.leFileName->setPalette(palette);
0171             ui.leFileName->setToolTip(QString());
0172         }
0173     }
0174 
0175     return hasMatch && !found;
0176 }
0177 
0178 /**
0179  * @brief Checks whether leDownloadURL contains a valid URL.
0180  */
0181 bool DatasetMetadataManagerWidget::urlExists() {
0182     // Check whether the given url is acceptable syntactically
0183     const QRegularExpression re(QLatin1String(R"(^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$)"));
0184     const QRegularExpressionMatch match = re.match(ui.leDownloadURL->text());
0185     bool hasMatch = match.hasMatch();
0186     const bool urlExists = hasMatch && !ui.leDownloadURL->text().isEmpty();
0187 
0188     if (!urlExists) {
0189         QPalette palette;
0190         palette.setColor(QPalette::Base, Qt::red);
0191         palette.setColor(QPalette::Text, Qt::black);
0192         ui.leDownloadURL->setPalette(palette);
0193         ui.leDownloadURL->setToolTip(QStringLiteral("The URL is invalid!"));
0194     } else {
0195         QPalette palette;
0196         palette.setColor(QPalette::Base, m_baseColor);
0197         palette.setColor(QPalette::Text, m_textColor);
0198         ui.leDownloadURL->setPalette(palette);
0199         ui.leDownloadURL->setToolTip(QString());
0200     }
0201     return urlExists;
0202 }
0203 
0204 /**
0205  * @brief Checks whether leDatasetName is empty or not.
0206  */
0207 bool DatasetMetadataManagerWidget::checkDatasetName() {
0208     const bool longNameOk = !ui.leDatasetName->text().isEmpty();
0209     if (!longNameOk) {
0210         QPalette palette;
0211         palette.setColor(QPalette::Base, Qt::red);
0212         palette.setColor(QPalette::Text, Qt::black);
0213         ui.leDatasetName->setPalette(palette);
0214         ui.leDatasetName->setToolTip(QStringLiteral("Please fill this out!"));
0215     } else {
0216         QPalette palette;
0217         palette.setColor(QPalette::Base, m_baseColor);
0218         palette.setColor(QPalette::Text, m_textColor);
0219         ui.leDatasetName->setPalette(palette);
0220         ui.leDatasetName->setToolTip(QString());
0221     }
0222 
0223     return longNameOk;
0224 }
0225 
0226 /**
0227  * @brief Checks whether teDescription is empty or not.
0228  */
0229 bool DatasetMetadataManagerWidget::checkDescription() {
0230     const bool descriptionOk = !ui.teDescription->toPlainText().isEmpty();
0231     if (!descriptionOk) {
0232         QPalette palette;
0233         palette.setColor(QPalette::Base, Qt::red);
0234         palette.setColor(QPalette::Text, Qt::black);
0235         ui.teDescription->setPalette(palette);
0236         ui.teDescription->setToolTip(QStringLiteral("Please fill this out!"));
0237     } else {
0238         QPalette palette;
0239         palette.setColor(QPalette::Base, m_baseColor);
0240         palette.setColor(QPalette::Text, m_textColor);
0241         ui.teDescription->setPalette(palette);
0242         ui.teDescription->setToolTip(QString());
0243     }
0244 
0245     return descriptionOk;
0246 }
0247 
0248 /**
0249  * @brief Checks whether the given QComboBox's current text is empty or not.
0250  */
0251 bool DatasetMetadataManagerWidget::checkCategories(QComboBox* comboBox) {
0252     // Check whether it is a word or not (might contain digits)
0253     const QString fileName = comboBox->currentText();
0254     const QRegularExpression re(QLatin1String("^[\\w\\d]+$"));
0255     const QRegularExpressionMatch match = re.match(fileName);
0256     const bool hasMatch = match.hasMatch();
0257 
0258     if (!hasMatch || fileName.isEmpty()) {
0259         DEBUG("category/subcategory name invalid");
0260         QPalette palette;
0261         palette.setColor(QPalette::Base, Qt::red);
0262         palette.setColor(QPalette::Text, Qt::black);
0263         comboBox->setPalette(palette);
0264         comboBox->setToolTip(QStringLiteral("Invalid or empty name for a category/subcategory (only digits and letters)"));
0265     } else {
0266         QPalette palette;
0267         palette.setColor(QPalette::Base, m_baseColor);
0268         palette.setColor(QPalette::Text, m_textColor);
0269         comboBox->setPalette(palette);
0270         comboBox->setToolTip(QString());
0271     }
0272 
0273     return hasMatch;
0274 }
0275 
0276 /**
0277  * @brief Enables/disables the widget's components meant to configure the metadata file of the new dataset.
0278  */
0279 void DatasetMetadataManagerWidget::enableDatasetSettings(bool enable) {
0280     ui.leFileName->setEnabled(enable);
0281     ui.leFileName->setReadOnly(!enable);
0282     ui.leDatasetName->setEnabled(enable);
0283     ui.leDatasetName->setReadOnly(!enable);
0284     ui.leDownloadURL->setEnabled(enable);
0285     ui.leDownloadURL->setReadOnly(!enable);
0286     ui.teDescription->setEnabled(enable);
0287     ui.teDescription->setReadOnly(!enable);
0288     ui.gbColumnDescriptions->setEnabled(enable);
0289     ui.gbFilter->setEnabled(enable);
0290 }
0291 
0292 /**
0293  * @brief Checks whether the introduced data is valid or not. Used by DatasetMetadataManagerDialog.
0294  */
0295 bool DatasetMetadataManagerWidget::checkDataValidity() {
0296     const bool fileNameOK = checkFileName();
0297     const bool urlOk = urlExists();
0298     const bool longNameOk = checkDatasetName();
0299     const bool descriptionOk = checkDescription();
0300     const bool categoryOk = checkCategories(ui.cbCategory);
0301     const bool subcategoryOk = checkCategories(ui.cbSubcategory);
0302     const bool collectionOk = checkCategories(ui.cbCollection);
0303 
0304     enableDatasetSettings(categoryOk && subcategoryOk && collectionOk);
0305 
0306     return fileNameOK && urlOk && longNameOk && descriptionOk && subcategoryOk && categoryOk && collectionOk;
0307 }
0308 
0309 /**
0310  * @brief Updates content of cbCategory based on current collection.
0311  */
0312 void DatasetMetadataManagerWidget::updateCategories(const QString& collection) {
0313     ui.cbCategory->clear();
0314     if (m_datasetModel->collections().contains(collection))
0315         ui.cbCategory->addItems(m_datasetModel->categories(collection));
0316 
0317     Q_EMIT checkOk();
0318 }
0319 
0320 /**
0321  * @brief Updates content of cbSubcategory based on current category.
0322  */
0323 void DatasetMetadataManagerWidget::updateSubcategories(const QString& category) {
0324     ui.cbSubcategory->clear();
0325     const QString collection = ui.cbCollection->currentText();
0326     if (m_datasetModel->categories(collection).contains(category))
0327         ui.cbSubcategory->addItems(m_datasetModel->subcategories(collection, category));
0328 
0329     Q_EMIT checkOk();
0330 }
0331 
0332 /**
0333  * @brief Updates the metadata file containing the categories, subcategories and datasets.
0334  * @param fileName the name of the metadata file (path)
0335  */
0336 void DatasetMetadataManagerWidget::updateDocument(const QString& dirPath) {
0337     if (checkDataValidity()) {
0338         // Check whether the current collection already exists, if yes update it
0339         if (m_datasetModel->collections().contains(ui.cbCollection->currentText())) {
0340             QString fileName = dirPath + ui.cbCollection->currentText() + QStringLiteral(".json");
0341             qDebug() << "Updating: " << fileName;
0342             QFile file(fileName);
0343             if (file.open(QIODevice::ReadWrite)) {
0344                 QJsonDocument document = QJsonDocument::fromJson(file.readAll());
0345                 QJsonObject rootObject = document.object();
0346                 QJsonValueRef categoryArrayRef = rootObject.find(QStringLiteral("categories")).value();
0347                 QJsonArray categoryArray = categoryArrayRef.toArray();
0348 
0349                 // Check whether the current category already exists
0350                 bool foundCategory = false;
0351                 for (int i = 0; i < categoryArray.size(); ++i) {
0352                     QJsonValueRef categoryRef = categoryArray[i];
0353                     QJsonObject currentCategory = categoryRef.toObject();
0354                     QString categoryName = currentCategory.value(QStringLiteral("category_name")).toString();
0355 
0356                     // If we find the category we have to update that QJsonObject
0357                     if (categoryName.compare(ui.cbCategory->currentText()) == 0) {
0358                         foundCategory = true;
0359                         QJsonValueRef subcategoryArrayRef = currentCategory.find(QStringLiteral("subcategories")).value();
0360                         QJsonArray subcategoryArray = subcategoryArrayRef.toArray();
0361 
0362                         // Check whether the current subcategory already exists
0363                         bool subcategoryFound = false;
0364                         for (int j = 0; j < subcategoryArray.size(); ++j) {
0365                             QJsonValueRef subcategoryRef = subcategoryArray[j];
0366                             QJsonObject currentSubcategory = subcategoryRef.toObject();
0367                             QString subcategoryName = currentSubcategory.value(QStringLiteral("subcategory_name")).toString();
0368 
0369                             // If we find the subcategory we have to update that QJsonObject
0370                             if (subcategoryName.compare(ui.cbSubcategory->currentText()) == 0) {
0371                                 subcategoryFound = true;
0372                                 QJsonValueRef datasetsRef = currentSubcategory.find(QStringLiteral("datasets")).value();
0373                                 QJsonArray datasets = datasetsRef.toArray();
0374 
0375                                 datasets.append(createDatasetObject());
0376                                 datasetsRef = datasets;
0377 
0378                                 subcategoryRef = currentSubcategory;
0379                                 subcategoryArrayRef = subcategoryArray;
0380                                 categoryRef = currentCategory;
0381                                 categoryArrayRef = categoryArray;
0382                                 document.setObject(rootObject);
0383                                 break;
0384                             }
0385                         }
0386 
0387                         // If we didn't find the subcategory, we have to create it
0388                         if (!subcategoryFound) {
0389                             qDebug() << "Subcategory not found";
0390                             QJsonObject newSubcategory;
0391                             newSubcategory.insert(QStringLiteral("subcategory_name"), ui.cbSubcategory->currentText());
0392 
0393                             QJsonArray datasets;
0394                             datasets.append(createDatasetObject());
0395 
0396                             newSubcategory.insert(QStringLiteral("datasets"), datasets);
0397                             subcategoryArray.append(newSubcategory);
0398 
0399                             subcategoryArrayRef = subcategoryArray;
0400                             categoryRef = currentCategory;
0401                             categoryArrayRef = categoryArray;
0402                             document.setObject(rootObject);
0403                         }
0404                         break;
0405                     }
0406                 }
0407 
0408                 // If we didn't find the category, we have to create it
0409                 if (!foundCategory) {
0410                     qDebug() << "Category not found";
0411                     QJsonObject newCategory;
0412                     newCategory.insert(QStringLiteral("category_name"), ui.cbCategory->currentText());
0413 
0414                     QJsonArray subcategoryArray;
0415 
0416                     QJsonObject newSubcategory;
0417                     newSubcategory.insert(QStringLiteral("subcategory_name"), ui.cbSubcategory->currentText());
0418 
0419                     QJsonArray datasets;
0420                     datasets.append(createDatasetObject());
0421                     newSubcategory.insert(QStringLiteral("datasets"), datasets);
0422 
0423                     subcategoryArray.append(newSubcategory);
0424                     newCategory.insert(QStringLiteral("subcategories"), subcategoryArray);
0425 
0426                     categoryArray.append(newCategory);
0427                     categoryArrayRef = categoryArray;
0428                     document.setObject(rootObject);
0429                 }
0430                 file.close();
0431                 bool rc = file.open(QIODevice::ReadWrite | QIODevice::Truncate);
0432                 if (rc) {
0433                     file.write(document.toJson());
0434                     file.close();
0435                 } else
0436                     qDebug() << "Couldn't write file, because " << file.errorString();
0437             } else
0438                 qDebug() << "Couldn't open dataset category file, because " << file.errorString();
0439         }
0440         // If the collection doesn't exist we have to create a new json file for it.
0441         else {
0442             QString fileName = dirPath + QStringLiteral("DatasetCollections.json");
0443             qDebug() << "creating: " << fileName;
0444             QFile file(fileName);
0445             if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
0446                 QJsonArray collectionArray;
0447 
0448                 for (QString collection : m_datasetModel->collections())
0449                     collectionArray.append(collection);
0450 
0451                 collectionArray.append(ui.cbCollection->currentText());
0452 
0453                 QJsonDocument newDocument;
0454                 newDocument.setArray(collectionArray);
0455                 file.write(newDocument.toJson());
0456                 file.close();
0457             }
0458 
0459             QJsonObject rootObject;
0460 
0461             rootObject.insert(QStringLiteral("collection_name"), ui.cbCollection->currentText());
0462 
0463             QJsonArray categoryArray;
0464             QJsonObject newCategory;
0465             newCategory.insert(QStringLiteral("category_name"), ui.cbCategory->currentText());
0466 
0467             QJsonArray subcategoryArray;
0468 
0469             QJsonObject newSubcategory;
0470             newSubcategory.insert(QStringLiteral("subcategory_name"), ui.cbSubcategory->currentText());
0471 
0472             QJsonArray datasets;
0473             datasets.append(createDatasetObject());
0474             newSubcategory.insert(QStringLiteral("datasets"), datasets);
0475 
0476             subcategoryArray.append(newSubcategory);
0477             newCategory.insert(QStringLiteral("subcategories"), subcategoryArray);
0478             categoryArray.append(newCategory);
0479             rootObject.insert(QStringLiteral("categories"), categoryArray);
0480 
0481             QJsonDocument document;
0482             document.setObject(rootObject);
0483 
0484             QFile collectionFile(dirPath + ui.cbCollection->currentText() + QStringLiteral(".json"));
0485             if (collectionFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
0486                 collectionFile.write(document.toJson());
0487                 collectionFile.close();
0488             }
0489         }
0490     }
0491 }
0492 
0493 /**
0494  * @brief Creates and returns a QJsonObject based on the given settings of the widget, this will be part of the collection's metadata file
0495  */
0496 QJsonObject DatasetMetadataManagerWidget::createDatasetObject() {
0497     QJsonObject rootObject;
0498     rootObject.insert(QStringLiteral("filename"), ui.leFileName->text());
0499     rootObject.insert(QStringLiteral("name"), ui.leDatasetName->text());
0500     rootObject.insert(QStringLiteral("download"), ui.leDownloadURL->text());
0501     rootObject.insert(QStringLiteral("description"), ui.teDescription->toPlainText());
0502     rootObject.insert(QStringLiteral("separator"), ui.cbSeparatingCharacter->currentText());
0503     rootObject.insert(QStringLiteral("comment_character"), ui.cbCommentCharacter->currentText());
0504     rootObject.insert(QStringLiteral("DateTime_format"), ui.cbDateTimeFormat->currentText());
0505     rootObject.insert(QStringLiteral("number_format"), ui.cbNumberFormat->currentIndex());
0506     rootObject.insert(QStringLiteral("create_index_column"), ui.chbCreateIndex->isChecked());
0507     rootObject.insert(QStringLiteral("skip_empty_parts"), ui.chbSkipEmptyParts->isChecked());
0508     rootObject.insert(QStringLiteral("simplify_whitespaces"), ui.chbSimplifyWhitespaces->isChecked());
0509     rootObject.insert(QStringLiteral("remove_quotes"), ui.chbRemoveQuotes->isChecked());
0510     rootObject.insert(QStringLiteral("use_first_row_for_vectorname"), ui.chbHeader->isChecked());
0511 
0512     for (int i = 0; i < m_columnDescriptions.size(); ++i)
0513         rootObject.insert(i18n("column_description_%1", i), m_columnDescriptions[i]);
0514 
0515     return rootObject;
0516 }
0517 
0518 /**
0519  * @brief Adds a new QLineEdit so the user can set a new column description.
0520  */
0521 void DatasetMetadataManagerWidget::addColumnDescription() {
0522     auto* label = new QLabel();
0523     label->setText(i18n("Description for column %1", m_columnDescriptions.size() + 1));
0524     auto* lineEdit = new QLineEdit();
0525 
0526     int layoutIndex = m_columnDescriptions.size() + 1;
0527     ui.columnLayout->addWidget(label, layoutIndex, 0);
0528     ui.columnLayout->addWidget(lineEdit, layoutIndex, 1, 1, -1);
0529 
0530     connect(lineEdit, &QLineEdit::textChanged, [this, layoutIndex](const QString& text) {
0531         m_columnDescriptions[layoutIndex - 1] = text;
0532     });
0533 
0534     m_columnDescriptions.append(QString());
0535 }
0536 
0537 /**
0538  * @brief Removes the lastly added QLineEdit (used to set a column description).
0539  */
0540 void DatasetMetadataManagerWidget::removeColumnDescription() {
0541     const int index = ui.columnLayout->count() - 1;
0542 
0543     QLayoutItem* item;
0544     if ((item = ui.columnLayout->takeAt(index)) != nullptr) {
0545         delete item->widget();
0546         delete item;
0547     }
0548 
0549     if ((item = ui.columnLayout->takeAt(index - 1)) != nullptr) {
0550         delete item->widget();
0551         delete item;
0552     }
0553 
0554     m_columnDescriptions.removeLast();
0555 }
0556 
0557 /**
0558  * @brief returns the path to the new metadata file of the new dataset.
0559  */
0560 QString DatasetMetadataManagerWidget::getMetadataFilePath() const {
0561     return m_metadataFilePath;
0562 }
0563 
0564 /**
0565  * @brief Sets the collection name.
0566  */
0567 void DatasetMetadataManagerWidget::setCollection(const QString& collection) {
0568     ui.cbCollection->setCurrentText(collection);
0569 }
0570 
0571 /**
0572  * @brief Sets the category name.
0573  */
0574 void DatasetMetadataManagerWidget::setCategory(const QString& category) {
0575     ui.cbCategory->setCurrentText(category);
0576 }
0577 
0578 /**
0579  * @brief Sets the subcategory name.
0580  */
0581 void DatasetMetadataManagerWidget::setSubcategory(const QString& subcategory) {
0582     ui.cbSubcategory->setCurrentText(subcategory);
0583 }
0584 
0585 /**
0586  * @brief Sets the short name of the dataset.
0587  */
0588 void DatasetMetadataManagerWidget::setShortName(const QString& name) {
0589     ui.leFileName->setText(name);
0590 }
0591 
0592 /**
0593  * @brief Sets the full name of the dataset.
0594  */
0595 void DatasetMetadataManagerWidget::setFullName(const QString& name) {
0596     ui.leDatasetName->setText(name);
0597 }
0598 
0599 /**
0600  * @brief Sets the text of the description.
0601  */
0602 void DatasetMetadataManagerWidget::setDescription(const QString& description) {
0603     ui.teDescription->setText(description);
0604 }
0605 
0606 /**
0607  * @brief Sets the download url.
0608  */
0609 void DatasetMetadataManagerWidget::setURL(const QString& url) {
0610     ui.leDownloadURL->setText(url);
0611 }