diff --git a/src/backend/datasources/DatasetHandler.cpp b/src/backend/datasources/DatasetHandler.cpp index d0a248b98..330a6df18 100644 --- a/src/backend/datasources/DatasetHandler.cpp +++ b/src/backend/datasources/DatasetHandler.cpp @@ -1,318 +1,317 @@ /*************************************************************************** File : DatasetHandler.cpp Project : LabPlot Description : Processes a dataset's metadata file -------------------------------------------------------------------- Copyright : (C) 2019 Kovacs Ferencz (kferike98@gmail.com) Copyright : (C) 2019 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "backend/datasources/filters/AsciiFilter.h" #include "backend/datasources/DatasetHandler.h" -#include #include #include #include -// #include #include -// #include #include #include #include #include +#include + /*! \class DatasetHandler \brief Provides functionality to process a metadata file of a dataset, configure a spreadsheet and filter based on it, download the dataset and load it into the spreadsheet. \ingroup datasources */ DatasetHandler::DatasetHandler(Spreadsheet* spreadsheet) : m_spreadsheet(spreadsheet), m_filter(new AsciiFilter), m_downloadManager(new QNetworkAccessManager) { connect(m_downloadManager, &QNetworkAccessManager::finished, this, &DatasetHandler::downloadFinished); connect(this, &DatasetHandler::downloadCompleted, this, &DatasetHandler::processDataset); } DatasetHandler::~DatasetHandler() { delete m_downloadManager; delete m_filter; } /** * @brief Initiates processing the metadata file,, located at the given path, belonging to a dataset. * @param path the path to the metadata file */ void DatasetHandler::processMetadata(const QJsonObject& object) { m_object = new QJsonObject(object); DEBUG("Start processing dataset..."); if(!m_object->isEmpty()) { configureFilter(); configureSpreadsheet(); prepareForDataset(); } } /** * @brief Marks the metadata file being invalid by setting the value of a flag, also pops up a messagebox. */ void DatasetHandler::markMetadataAsInvalid() { m_invalidMetadataFile = true; QMessageBox::critical(0, i18n("Invalid metadata file"), i18n("The metadata file for the selected dataset is invalid.")); } /** * @brief Configures the filter, that will be used later, based on the metadata file. */ void DatasetHandler::configureFilter() { //set some default values common to many datasets m_filter->setNumberFormat(QLocale::C); m_filter->setSkipEmptyParts(true); m_filter->setHeaderEnabled(false); //read properties specified in the dataset description if(!m_object->isEmpty()) { if(m_object->contains("separator")) m_filter->setSeparatingCharacter(m_object->value("separator").toString()); if(m_object->contains("comment_character")) m_filter->setCommentCharacter(m_object->value("comment_character").toString()); if(m_object->contains("create_index_column")) m_filter->setCreateIndexEnabled(m_object->value("create_index_column").toBool()); if(m_object->contains("skip_empty_parts")) m_filter->setSkipEmptyParts(m_object->value("skip_empty_parts").toBool()); if(m_object->contains("simplify_whitespaces")) m_filter->setSimplifyWhitespacesEnabled(m_object->value("simplify_whitespaces").toBool()); if(m_object->contains("remove_quotes")) m_filter->setRemoveQuotesEnabled(m_object->value("remove_quotes").toBool()); if(m_object->contains("use_first_row_for_vectorname")) m_filter->setHeaderEnabled(m_object->value("use_first_row_for_vectorname").toBool()); if(m_object->contains("number_format")) m_filter->setNumberFormat(QLocale::Language(m_object->value("number_format").toInt())); if(m_object->contains("DateTime_format")) m_filter->setDateTimeFormat(m_object->value("DateTime_format").toString()); if(m_object->contains("columns")) { const QJsonArray& columnsArray = m_object->value("columns").toArray(); QStringList columnNames; for (int i = 0; i < columnsArray.size(); ++i) columnNames << columnsArray[i].toString(); m_filter->setVectorNames(columnNames); } } else { DEBUG("Empty object"); markMetadataAsInvalid(); } } /** * @brief Configures the spreadsheet based on the metadata file. */ void DatasetHandler::configureSpreadsheet() { DEBUG("Start preparing spreadsheet"); if(!m_object->isEmpty()) { if(m_object->contains("name")) m_spreadsheet->setName( m_object->value("name").toString()); else markMetadataAsInvalid(); if (m_object->contains("description_url")) { QNetworkAccessManager* manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, [this] (QNetworkReply* reply) { if (reply->error() == QNetworkReply::NoError) { QByteArray ba = reply->readAll(); QString info(ba); m_spreadsheet->setComment(info); } else { DEBUG("Failed to fetch the description."); if(m_object->contains("description")) m_spreadsheet->setComment(m_object->value("description").toString()); } reply->deleteLater(); } ); manager->get(QNetworkRequest(QUrl(m_object->value("description_url").toString()))); } else if(m_object->contains("description")) m_spreadsheet->setComment(m_object->value("description").toString()); } else { markMetadataAsInvalid(); } } /** * @brief Extracts the download URL of the dataset and initiates the process of download. */ void DatasetHandler::prepareForDataset() { DEBUG("Start downloading dataset"); if(!m_object->isEmpty()) { if(m_object->contains("url")) { const QString& url = m_object->value("url").toString(); const QUrl downloadUrl = QUrl::fromEncoded(url.toLocal8Bit()); doDownload(url); } else { QMessageBox::critical(0, i18n("Invalid metadata file"), i18n("There is no download URL present in the metadata file!")); } } else { markMetadataAsInvalid(); } } /** * @brief Starts the download of the dataset. * @param url the download URL of the dataset */ void DatasetHandler::doDownload(const QUrl& url) { DEBUG("Download request"); QNetworkRequest request(url); m_currentDownload = m_downloadManager->get(request); connect(m_currentDownload, &QNetworkReply::downloadProgress, [this] (qint64 bytesReceived, qint64 bytesTotal) { double progress; if (bytesTotal == -1) progress = 0; else progress = 100 * (static_cast(bytesReceived) / static_cast(bytesTotal)); qDebug() << "Progress: " << progress; emit downloadProgress(progress); }); } /** * @brief Called when the download of the dataset is finished. */ void DatasetHandler::downloadFinished(QNetworkReply* reply) { DEBUG("Download finished"); const QUrl& url = reply->url(); if (reply->error()) { qDebug("Download of %s failed: %s\n", url.toEncoded().constData(), qPrintable(reply->errorString())); } else { if (isHttpRedirect(reply)) { qDebug("Request was redirected.\n"); } else { QString filename = saveFileName(url); if (saveToDisk(filename, reply)) { qDebug("Download of %s succeeded (saved to %s)\n", url.toEncoded().constData(), qPrintable(filename)); m_fileName = filename; emit downloadCompleted(); } } } m_currentDownload = nullptr; reply->deleteLater(); } /** * @brief Checks whether the GET request was redirected or not. */ bool DatasetHandler::isHttpRedirect(QNetworkReply* reply) { const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); // TODO enum/defines for status codes ? return statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 305 || statusCode == 307 || statusCode == 308; } /** * @brief Returns the name and path of the file that will contain the content of the reply (based on the URL). * @param url */ QString DatasetHandler::saveFileName(const QUrl& url) { const QString path = url.path(); //get the extension of the downloaded file const QString downloadFileName = QFileInfo(path).fileName(); int lastIndex = downloadFileName.lastIndexOf("."); const QString fileExtension = lastIndex >= 0 ? downloadFileName.right(downloadFileName.length() - lastIndex) : ""; QString basename = m_object->value("filename").toString() + fileExtension; if (basename.isEmpty()) basename = "url"; QDir downloadDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1String("/datasets_local/")); if (!downloadDir.exists()) downloadDir.mkdir(downloadDir.path()); QString fileName = downloadDir.path() + QLatin1Char('/') + basename; QFileInfo fileInfo (fileName); if (QFile::exists(fileName)) { if(fileInfo.lastModified().addDays(1) < QDateTime::currentDateTime()){ QFile removeFile (fileName); removeFile.remove(); } else { qDebug() << "Dataset file already exists, no need to download it again"; } } return fileName; } /** * @brief Saves the content of the network reply to the given path under the given name. */ bool DatasetHandler::saveToDisk(const QString& filename, QIODevice* data) { QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { qDebug("Could not open %s for writing: %s\n", qPrintable(filename), qPrintable(file.errorString())); return false; } file.write(data->readAll()); file.close(); return true; } /** * @brief Processes the downloaded dataset with the help of the already configured filter. */ void DatasetHandler::processDataset() { m_filter->readDataFromFile(m_fileName, m_spreadsheet); //set column comments/descriptions, if available //TODO: // if(!m_object->isEmpty()) { // int index = 0; // const int columnsCount = m_spreadsheet->columnCount(); // while(m_object->contains(i18n("column_description_%1", index)) && (index < columnsCount)) { // m_spreadsheet->column(index)->setComment(m_object->value(i18n("column_description_%1", index)).toString()); // ++index; // } // } } diff --git a/src/kdefrontend/datasources/ImportDatasetWidget.cpp b/src/kdefrontend/datasources/ImportDatasetWidget.cpp index 1c59dd13c..3187bac77 100644 --- a/src/kdefrontend/datasources/ImportDatasetWidget.cpp +++ b/src/kdefrontend/datasources/ImportDatasetWidget.cpp @@ -1,577 +1,586 @@ /*************************************************************************** File : ImportDatasetWidget.cpp Project : LabPlot Description : import online dataset widget -------------------------------------------------------------------- Copyright : (C) 2019 Kovacs Ferencz (kferike98@gmail.com) Copyright : (C) 2019 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "backend/datasources/DatasetHandler.h" #include "kdefrontend/datasources/ImportDatasetWidget.h" #include "kdefrontend/DatasetModel.h" #include #include #include #include #include #include #include #include #include #include /*! \class ImportDatasetWidget \brief Widget for importing data from a dataset. \ingroup kdefrontend */ ImportDatasetWidget::ImportDatasetWidget(QWidget* parent) : QWidget(parent), m_networkManager(new QNetworkAccessManager(this)) { ui.setupUi(this); m_jsonDir = QStandardPaths::locate(QStandardPaths::AppDataLocation, QLatin1String("datasets"), QStandardPaths::LocateDirectory); loadCategories(); ui.lwDatasets->setSelectionMode(QAbstractItemView::SingleSelection); ui.twCategories->setSelectionMode(QAbstractItemView::SingleSelection); const int size = ui.leSearch->height(); ui.lSearch->setPixmap( QIcon::fromTheme(QLatin1String("edit-find")).pixmap(size, size) ); QString info = i18n("Enter the keyword you want to search for"); ui.lSearch->setToolTip(info); ui.leSearch->setToolTip(info); ui.leSearch->setPlaceholderText(i18n("Search...")); connect(ui.cbCollections, static_cast(&QComboBox::currentIndexChanged), this, &ImportDatasetWidget::collectionChanged); connect(ui.twCategories, &QTreeWidget::itemDoubleClicked, this, &ImportDatasetWidget::updateDatasets); connect(ui.twCategories, &QTreeWidget::itemSelectionChanged, [this] { if(!m_initializing) updateDatasets(ui.twCategories->selectedItems().first()); }); connect(ui.leSearch, &QLineEdit::textChanged, this, &ImportDatasetWidget::updateCategories); connect(ui.lwDatasets, &QListWidget::itemSelectionChanged, [this]() { if (!m_initializing) datasetChanged(); }); connect(ui.lwDatasets, &QListWidget::doubleClicked, [this]() {emit datasetDoubleClicked(); }); connect(m_networkManager, &QNetworkAccessManager::finished, this, &ImportDatasetWidget::downloadFinished); } ImportDatasetWidget::~ImportDatasetWidget() { delete m_model; } /** * @brief Processes the json metadata file that contains the list of categories and subcategories and their datasets. */ void ImportDatasetWidget::loadCategories() { m_datasetsMap.clear(); ui.cbCollections->clear(); const QString collectionsFileName = m_jsonDir + QLatin1String("/DatasetCollections.json"); QFile file(collectionsFileName); if (file.open(QIODevice::ReadOnly)) { QJsonDocument document = QJsonDocument::fromJson(file.readAll()); file.close(); if (!document.isArray()) { QDEBUG("Invalid definition of " + collectionsFileName); return; } m_collections = document.array(); for (int col = 0; col < m_collections.size(); col++) { const QJsonObject& collection = m_collections[col].toObject(); const QString& m_collection = collection[QLatin1String("name")].toString(); QString path = m_jsonDir + QLatin1Char('/') + m_collection + ".json"; QFile collectionFile(path); if (collectionFile.open(QIODevice::ReadOnly)) { QJsonDocument collectionDocument = QJsonDocument::fromJson(collectionFile.readAll()); if (!collectionDocument.isObject()) { QDEBUG("Invalid definition of " + path); continue; } const QJsonObject& collectionObject = collectionDocument.object(); const QJsonArray& categoryArray = collectionObject.value(QLatin1String("categories")).toArray(); //processing categories for(int i = 0 ; i < categoryArray.size(); ++i) { const QJsonObject& currentCategory = categoryArray[i].toObject(); const QString& categoryName = currentCategory.value(QLatin1String("name")).toString(); const QJsonArray& subcategories = currentCategory.value(QLatin1String("subcategories")).toArray(); //processing subcategories for(int j = 0; j < subcategories.size(); ++j) { QJsonObject currentSubCategory = subcategories[j].toObject(); QString subcategoryName = currentSubCategory.value(QLatin1String("name")).toString(); const QJsonArray& datasetArray = currentSubCategory.value(QLatin1String("datasets")).toArray(); //processing the datasets of the actual subcategory for (const auto& dataset : datasetArray) m_datasetsMap[m_collection][categoryName][subcategoryName].push_back(dataset.toObject().value(QLatin1String("filename")).toString()); } } } } if(m_model) delete m_model; m_model = new DatasetModel(m_datasetsMap); //Fill up collections combo box ui.cbCollections->addItem(i18n("All") + QString(" (" + QString::number(m_model->allDatasetsList().toStringList().size()) + ")")); for (QString collection : m_model->collections()) ui.cbCollections->addItem(collection + " (" + QString::number(m_model->datasetCount(collection)) + ")", collection); collectionChanged(ui.cbCollections->currentIndex()); } else QMessageBox::critical(this, i18n("File not found"), i18n("Couldn't open the dataset collections file %1. Please check your installation.", collectionsFileName)); } /** * Shows all categories and sub-categories for the currently selected collection */ void ImportDatasetWidget::collectionChanged(int index) { m_allCollections = (index == 0); if (!m_allCollections) m_collection = ui.cbCollections->itemData(index).toString(); else m_collection = ""; //update the info field QString info; if (!m_allCollections) { for (int i = 0; i < m_collections.size(); ++i) { const QJsonObject& collection = m_collections[i].toObject(); if ( m_collection == collection[QLatin1String("name")].toString() ) { info += collection[QLatin1String("description")].toString(); info += QLatin1String("



"); break; } } } else { for (int i = 0; i < m_collections.size(); ++i) { const QJsonObject& collection = m_collections[i].toObject(); info += collection[QLatin1String("description")].toString(); info += QLatin1String("

"); } } ui.lInfo->setText(info); updateCategories(); //update the completer if(m_completer) delete m_completer; //add all categories, sub-categories and the dataset names for the current collection QStringList keywords; for(auto category : m_model->categories(m_collection)) { keywords << category; for(auto subcategory : m_model->subcategories(m_collection, category)) { keywords << subcategory; for (QString dataset : m_model->datasets(m_collection, category, subcategory)) keywords << dataset; } } m_completer = new QCompleter(keywords, this); m_completer->setCompletionMode(QCompleter::PopupCompletion); m_completer->setCaseSensitivity(Qt::CaseSensitive); ui.leSearch->setCompleter(m_completer); } void ImportDatasetWidget::updateCategories() { m_initializing = true; ui.twCategories->clear(); QTreeWidgetItem* rootItem = new QTreeWidgetItem(QStringList(i18n("All"))); ui.twCategories->addTopLevelItem(rootItem); const QString& filter = ui.leSearch->text(); bool categoryMatch = false; bool subcategoryMatch = false; bool datasetMatch = false; //add categories for(auto category : m_model->categories(m_collection)) { categoryMatch = (filter.isEmpty() || category.startsWith(filter, Qt::CaseInsensitive)); if (categoryMatch) { QTreeWidgetItem* const item = new QTreeWidgetItem(QStringList(category)); rootItem->addChild(item); //add all sub-categories for(auto subcategory : m_model->subcategories(m_collection, category)) item->addChild(new QTreeWidgetItem(QStringList(subcategory))); } else { QTreeWidgetItem* item = nullptr; for(auto subcategory : m_model->subcategories(m_collection, category)) { subcategoryMatch = subcategory.startsWith(filter, Qt::CaseInsensitive); if (subcategoryMatch) { if (!item) { item = new QTreeWidgetItem(QStringList(category)); rootItem->addChild(item); item->setExpanded(true); } item->addChild(new QTreeWidgetItem(QStringList(subcategory))); } else { for (QString dataset : m_model->datasets(m_collection, category, subcategory)) { datasetMatch = dataset.startsWith(filter, Qt::CaseInsensitive); if (datasetMatch) { if (!item) { item = new QTreeWidgetItem(QStringList(category)); rootItem->addChild(item); item->setExpanded(true); } item->addChild(new QTreeWidgetItem(QStringList(subcategory))); break; } } } } } } //remote the root item "All" if nothing has matched to the filter string if (rootItem->childCount() == 0) ui.twCategories->clear(); //expand the root item and select the first category item rootItem->setExpanded(true); if (filter.isEmpty()) { rootItem->setSelected(true); updateDatasets(rootItem); } else { if (rootItem->child(0) && rootItem->child(0)->child(0)) { rootItem->child(0)->child(0)->setSelected(true); updateDatasets(rootItem->child(0)->child(0)); - } + } else + updateDatasets(nullptr); } m_initializing = false; } /** * @brief Populates lwDatasets with the datasets of the selected subcategory or its parent * @param item the selected subcategory */ void ImportDatasetWidget::updateDatasets(QTreeWidgetItem* item) { m_initializing = true; ui.lwDatasets->clear(); + if (!item) { + //no category item is selected because nothing matches the search string + m_initializing = false; + datasetChanged(); + return; + } + const QString& filter = ui.leSearch->text(); if(item->childCount() == 0) { //sub-category was selected -> show all its datasets m_category = item->parent()->text(0); m_subcategory = item->text(0); addDatasetItems(m_collection, m_category, m_subcategory, filter); } else { if (!item->parent()) { //top-level item "All" was selected -> show datasets for all categories and their sub-categories m_category = ""; m_subcategory = ""; for (auto category : m_model->categories(m_collection)) { for (auto subcategory : m_model->subcategories(m_collection, category)) addDatasetItems(m_collection, category, subcategory, filter); } } else { //a category was selected -> show all its datasets m_category = item->text(0); m_subcategory = ""; for (auto subcategory : m_model->subcategories(m_collection, m_category)) addDatasetItems(m_collection, m_category, subcategory, filter); } } m_initializing = false; //select the first available dataset - ui.lwDatasets->setCurrentRow(0); + if (ui.lwDatasets->count()) + ui.lwDatasets->setCurrentRow(0); } void ImportDatasetWidget::addDatasetItems(const QString& collection, const QString& category, const QString& subcategory, const QString& filter) { if (!filter.isEmpty() && (category.startsWith(filter, Qt::CaseInsensitive) || subcategory.startsWith(filter, Qt::CaseInsensitive))) { for (QString dataset : m_model->datasets(collection, category, subcategory)) ui.lwDatasets->addItem(new QListWidgetItem(dataset)); } else { for (QString dataset : m_model->datasets(collection, category, subcategory)) { if (filter.isEmpty() || dataset.startsWith(filter, Qt::CaseInsensitive)) ui.lwDatasets->addItem(new QListWidgetItem(dataset)); } } } /** * @brief Returns the name of the selected dataset */ QString ImportDatasetWidget::getSelectedDataset() const { if (!ui.lwDatasets->selectedItems().isEmpty()) return ui.lwDatasets->selectedItems().at(0)->text(); else return QString(); } /** * @brief Initiates the processing of the dataset's metadata file and of the dataset itself. * @param datasetHandler the DatasetHanlder that downloads processes the dataset */ void ImportDatasetWidget::import(DatasetHandler* datasetHandler) { datasetHandler->processMetadata(m_datasetObject); } /** * @brief Returns the QJsonObject associated with the currently selected dataset. */ QJsonObject ImportDatasetWidget::loadDatasetObject() { for (int i = 0; i < m_collections.size(); ++i) { const QJsonObject& collectionJson = m_collections[i].toObject(); const QString& collection = collectionJson[QLatin1String("name")].toString(); //we have to find the selected collection in the metadata file. if(m_allCollections || m_collection == collection) { QFile file(m_jsonDir + QLatin1Char('/') + collection + QLatin1String(".json")); //open the metadata file of the current collection if (file.open(QIODevice::ReadOnly)) { QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); file.close(); if(!doc.isObject()) { DEBUG("The " + collection.toStdString() + ".json file is invalid"); return QJsonObject(); } QJsonArray categoryArray = doc.object().value(QLatin1String("categories")).toArray(); //processing categories for(int i = 0 ; i < categoryArray.size(); ++i) { const QJsonObject currentCategory = categoryArray[i].toObject(); const QString categoryName = currentCategory.value(QLatin1String("name")).toString(); if(m_category.isEmpty() || categoryName.compare(m_category) == 0) { const QJsonArray subcategories = currentCategory.value(QLatin1String("subcategories")).toArray(); //processing subcategories for(int j = 0; j < subcategories.size(); ++j) { QJsonObject currentSubCategory = subcategories[j].toObject(); QString subcategoryName = currentSubCategory.value(QLatin1String("name")).toString(); if(m_subcategory.isEmpty() || subcategoryName.compare(m_subcategory) == 0) { const QJsonArray datasetArray = currentSubCategory.value(QLatin1String("datasets")).toArray(); //processing the datasets of the actual subcategory for (const auto& dataset : datasetArray) { if(getSelectedDataset().compare(dataset.toObject().value(QLatin1String("filename")).toString()) == 0) return dataset.toObject(); } if (!m_subcategory.isEmpty()) break; } } if (!m_category.isEmpty()) break; } } } if (!m_allCollections) break; } } return QJsonObject(); } /** * @brief Returns the structure containing the categories, subcategories and datasets. * @return the structure containing the categories, subcategories and datasets */ const DatasetsMap& ImportDatasetWidget::getDatasetsMap() { return m_datasetsMap; } /** * @brief Sets the currently selected collection * @param category the name of the collection */ void ImportDatasetWidget::setCollection(const QString& collection) { ui.cbCollections->setCurrentText(collection + QLatin1String(" (") + QString(m_model->datasetCount(collection)) + QLatin1Char(')')); } /** * @brief Sets the currently selected category * @param category the name of the category */ void ImportDatasetWidget::setCategory(const QString &category) { for(int i = 0; i < ui.twCategories->topLevelItemCount(); i++) { if (ui.twCategories->topLevelItem(i)->text(0).compare(category) == 0) { updateDatasets(ui.twCategories->topLevelItem(i)); break; } } } /** * @brief Sets the currently selected subcategory * @param subcategory the name of the subcategory */ void ImportDatasetWidget::setSubcategory(const QString &subcategory) { for(int i = 0; i < ui.twCategories->topLevelItemCount(); i++) { if (ui.twCategories->topLevelItem(i)->text(0).compare(m_category) == 0) { QTreeWidgetItem* categoryItem = ui.twCategories->topLevelItem(i); for(int j = 0; j childCount(); j++) { if(categoryItem->child(j)->text(0).compare(subcategory) == 0) { updateDatasets(categoryItem->child(j)); break; } } break; } } } /** * @brief Sets the currently selected dataset * @param the currently selected dataset */ void ImportDatasetWidget::setDataset(const QString &datasetName) { for(int i = 0; i < ui.lwDatasets->count() ; i++) { if(ui.lwDatasets->item(i)->text().compare(datasetName) == 0) { ui.lwDatasets->item(i)->setSelected(true); break; } } } /** * @brief Updates the details of the currently selected dataset */ void ImportDatasetWidget::datasetChanged() { QString dataset = getSelectedDataset(); //no need to fetch the same dataset description again if it's already shown if (m_collection == m_prevCollection && m_category == m_prevCategory && m_subcategory == m_prevSubcategory && dataset == m_prevDataset) return; m_prevCollection = m_collection; m_prevCategory = m_category; m_prevSubcategory = m_subcategory; m_prevDataset = dataset; QString info; if (ui.cbCollections->currentIndex() != 0) { const QString& m_collection = ui.cbCollections->itemData(ui.cbCollections->currentIndex()).toString(); for (int i = 0; i < m_collections.size(); ++i) { const QJsonObject& collection = m_collections[i].toObject(); if ( m_collection.startsWith(collection[QLatin1String("name")].toString()) ) { info += collection[QLatin1String("description")].toString(); info += QLatin1String("

"); break; } } } if(!dataset.isEmpty()) { m_datasetObject = loadDatasetObject(); info += QLatin1String("") + i18n("Dataset") + QLatin1String(":
"); info += m_datasetObject[QLatin1String("name")].toString(); info += QLatin1String("

"); if (m_datasetObject.contains(QLatin1String("description_url"))) { WAIT_CURSOR; if (m_networkManager->networkAccessible() == QNetworkAccessManager::Accessible) m_networkManager->get(QNetworkRequest(QUrl(m_datasetObject[QLatin1String("description_url")].toString()))); else info += m_datasetObject[QLatin1String("description")].toString(); } else { info += QLatin1String("") + i18n("Description") + QLatin1String(":
"); info += m_datasetObject[QLatin1String("description")].toString(); } } else m_datasetObject = QJsonObject(); ui.lInfo->setText(info); emit datasetSelected(); } void ImportDatasetWidget::downloadFinished(QNetworkReply* reply) { if (reply->error() == QNetworkReply::NoError) { QByteArray ba = reply->readAll(); QString info(ba); info = info.replace(QLatin1Char('\n'), QLatin1String("
")); //do further collection specific replacements to get better formatting if (m_collection == QLatin1String("JSEDataArchive")) { info = info.replace(QLatin1String("NAME:"), QLatin1String("NAME:"), Qt::CaseSensitive); info = info.replace(QLatin1String("TYPE:"), QLatin1String("TYPE:"), Qt::CaseSensitive); info = info.replace(QLatin1String("SIZE:"), QLatin1String("SIZE:"), Qt::CaseSensitive); info = info.replace(QLatin1String("DESCRIPTIVE ABSTRACT:"), QLatin1String("DESCRIPTIVE ABSTRACT:"), Qt::CaseSensitive); info = info.replace(QLatin1String("NOTE:"), QLatin1String("NOTE:"), Qt::CaseSensitive); info = info.replace(QLatin1String("SPECIAL NOTES:"), QLatin1String("SPECIAL NOTES:"), Qt::CaseSensitive); info = info.replace(QLatin1String("SOURCE:"), QLatin1String("SOURCE:"), Qt::CaseSensitive); info = info.replace(QLatin1String("SOURCES:"), QLatin1String("SOURCES:"), Qt::CaseSensitive); info = info.replace(QLatin1String("DATA SOURCE:"), QLatin1String("DATA SOURCE:"), Qt::CaseSensitive); info = info.replace(QLatin1String("DATASETS LAYOUT:"), QLatin1String("DATASETS LAYOUT:"), Qt::CaseSensitive); info = info.replace(QLatin1String("VARIABLE DESCRIPTIONS:"), QLatin1String("VARIABLE DESCRIPTIONS:"), Qt::CaseSensitive); info = info.replace(QLatin1String("VARIABLES DESCRIPTIONS:"), QLatin1String("VARIABLES DESCRIPTIONS:"), Qt::CaseSensitive); info = info.replace(QLatin1String("RELATED DATASETS:"), QLatin1String("RELATED DATASETS:"), Qt::CaseSensitive); info = info.replace(QLatin1String("SPECIAL NOTES:"), QLatin1String("SPECIAL NOTES:"), Qt::CaseSensitive); info = info.replace(QLatin1String("STORY BEHIND THE DATA:"), QLatin1String("STORY BEHIND THE DATA:"), Qt::CaseSensitive); info = info.replace(QLatin1String("THE STORY BEHIND THE DATA:"), QLatin1String("THE STORY BEHIND THE DATA:"), Qt::CaseSensitive); info = info.replace(QLatin1String("PEDAGOGICAL NOTES:"), QLatin1String("PEDAGOGICAL NOTES:"), Qt::CaseSensitive); info = info.replace(QLatin1String("REFERENCE:"), QLatin1String("REFERENCE:"), Qt::CaseSensitive); info = info.replace(QLatin1String("REFERENCES:"), QLatin1String("REFERENCES:"), Qt::CaseSensitive); info = info.replace(QLatin1String("SUBMITTED BY:"), QLatin1String("SUBMITTED BY:"), Qt::CaseSensitive); } ui.lInfo->setText(ui.lInfo->text() + info); } else { DEBUG("Failed to fetch the description."); ui.lInfo->setText(ui.lInfo->text() + m_datasetObject[QLatin1String("description")].toString()); } reply->deleteLater(); RESET_CURSOR; }