File indexing completed on 2024-05-12 15:27:46

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