File indexing completed on 2025-07-13 03:32:34
0001 /* 0002 File : ImportDatasetWidget.cpp 0003 Project : LabPlot 0004 Description : import online dataset widget 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2019 Kovacs Ferencz <kferike98@gmail.com> 0007 SPDX-FileCopyrightText: 2019-2023 Alexander Semke <alexander.semke@web.de> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "kdefrontend/datasources/ImportDatasetWidget.h" 0012 #include "backend/core/Settings.h" 0013 #include "backend/datasources/DatasetHandler.h" 0014 #include "backend/lib/macros.h" 0015 #include "kdefrontend/DatasetModel.h" 0016 0017 #include <QCompleter> 0018 #include <QDir> 0019 #include <QFile> 0020 #include <QJsonDocument> 0021 #include <QJsonValue> 0022 #include <QMessageBox> 0023 #include <QNetworkAccessManager> 0024 #include <QNetworkReply> 0025 #include <QStandardPaths> 0026 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0027 #include <QNetworkInformation> 0028 #endif 0029 0030 #include <KConfigGroup> 0031 #include <KLocalizedString> 0032 0033 /*! 0034 \class ImportDatasetWidget 0035 \brief Widget for importing data from a dataset. 0036 0037 \ingroup kdefrontend 0038 */ 0039 ImportDatasetWidget::ImportDatasetWidget(QWidget* parent) 0040 : QWidget(parent) 0041 , m_networkManager(new QNetworkAccessManager(this)) { 0042 ui.setupUi(this); 0043 0044 m_jsonDir = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("datasets"), QStandardPaths::LocateDirectory); 0045 loadCategories(); 0046 0047 ui.lwDatasets->setSelectionMode(QAbstractItemView::SingleSelection); 0048 ui.twCategories->setSelectionMode(QAbstractItemView::SingleSelection); 0049 0050 const int size = ui.leSearch->height(); 0051 ui.lSearch->setPixmap(QIcon::fromTheme(QStringLiteral("edit-find")).pixmap(size, size)); 0052 0053 QString info = i18n("Enter the keyword you want to search for"); 0054 ui.lSearch->setToolTip(info); 0055 ui.leSearch->setToolTip(info); 0056 ui.leSearch->setPlaceholderText(i18n("Search...")); 0057 ui.leSearch->setFocus(); 0058 0059 connect(ui.cbCollections, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ImportDatasetWidget::collectionChanged); 0060 connect(ui.twCategories, &QTreeWidget::itemDoubleClicked, this, &ImportDatasetWidget::updateDatasets); 0061 connect(ui.twCategories, &QTreeWidget::itemSelectionChanged, [this] { 0062 if (!m_initializing) 0063 updateDatasets(ui.twCategories->selectedItems().first()); 0064 }); 0065 0066 connect(ui.leSearch, &TimedLineEdit::textChanged, this, &ImportDatasetWidget::updateCategories); 0067 connect(ui.lwDatasets, &QListWidget::itemSelectionChanged, [this]() { 0068 if (!m_initializing) 0069 datasetChanged(); 0070 }); 0071 connect(ui.lwDatasets, &QListWidget::doubleClicked, [this]() { 0072 Q_EMIT datasetDoubleClicked(); 0073 }); 0074 connect(m_networkManager, &QNetworkAccessManager::finished, this, &ImportDatasetWidget::downloadFinished); 0075 0076 // select the last used collection 0077 KConfigGroup conf = Settings::group(QStringLiteral("ImportDatasetWidget")); 0078 const QString& collection = conf.readEntry("Collection", QString()); 0079 if (collection.isEmpty()) 0080 ui.cbCollections->setCurrentIndex(0); 0081 else { 0082 for (int i = 0; i < ui.cbCollections->count(); ++i) { 0083 if (ui.cbCollections->itemData(i).toString() == collection) { 0084 ui.cbCollections->setCurrentIndex(i); 0085 break; 0086 } 0087 } 0088 } 0089 } 0090 0091 ImportDatasetWidget::~ImportDatasetWidget() { 0092 delete m_model; 0093 0094 // save the selected collection 0095 if (ui.cbCollections->currentIndex() != -1) { 0096 KConfigGroup conf = Settings::group(QStringLiteral("ImportDatasetWidget")); 0097 conf.writeEntry("Collection", ui.cbCollections->itemData(ui.cbCollections->currentIndex()).toString()); 0098 } 0099 } 0100 0101 /** 0102 * @brief Processes the json metadata file that contains the list of categories and subcategories and their datasets. 0103 */ 0104 void ImportDatasetWidget::loadCategories() { 0105 m_datasetsMap.clear(); 0106 ui.cbCollections->clear(); 0107 0108 const QString collectionsFileName = m_jsonDir + QStringLiteral("/DatasetCollections.json"); 0109 QFile file(collectionsFileName); 0110 0111 if (file.open(QIODevice::ReadOnly)) { 0112 QJsonDocument document = QJsonDocument::fromJson(file.readAll()); 0113 file.close(); 0114 if (!document.isArray()) { 0115 QDEBUG(QStringLiteral("Invalid definition of ") + collectionsFileName); 0116 return; 0117 } 0118 0119 m_collections = document.array(); 0120 0121 for (const QJsonValueRef col : m_collections) { 0122 const QJsonObject& collection = col.toObject(); 0123 const QString& m_collection = collection[QLatin1String("name")].toString(); 0124 0125 QString path = m_jsonDir + QLatin1Char('/') + m_collection + QStringLiteral(".json"); 0126 QFile collectionFile(path); 0127 if (collectionFile.open(QIODevice::ReadOnly)) { 0128 QJsonDocument collectionDocument = QJsonDocument::fromJson(collectionFile.readAll()); 0129 if (!collectionDocument.isObject()) { 0130 QDEBUG(QStringLiteral("Invalid definition of ") + path); 0131 continue; 0132 } 0133 0134 const QJsonObject& collectionObject = collectionDocument.object(); 0135 const QJsonArray& categoryArray = collectionObject.value(QLatin1String("categories")).toArray(); 0136 0137 // processing categories 0138 for (const auto& cat : categoryArray) { 0139 const QJsonObject& currentCategory = cat.toObject(); 0140 const QString& categoryName = currentCategory.value(QLatin1String("name")).toString(); 0141 const QJsonArray& subcategories = currentCategory.value(QLatin1String("subcategories")).toArray(); 0142 0143 // processing subcategories 0144 for (const auto& sub : subcategories) { 0145 QJsonObject currentSubCategory = sub.toObject(); 0146 QString subcategoryName = currentSubCategory.value(QLatin1String("name")).toString(); 0147 const QJsonArray& datasetArray = currentSubCategory.value(QLatin1String("datasets")).toArray(); 0148 0149 // processing the datasets of the actual subcategory 0150 for (const auto& dataset : datasetArray) 0151 m_datasetsMap[m_collection][categoryName][subcategoryName].push_back( 0152 dataset.toObject().value(QLatin1String("filename")).toString()); 0153 } 0154 } 0155 } 0156 } 0157 0158 if (m_model) 0159 delete m_model; 0160 m_model = new DatasetModel(m_datasetsMap); 0161 0162 // Fill up collections combo box 0163 ui.cbCollections->addItem(i18n("All") + QStringLiteral(" (") + QString::number(m_model->allDatasetsList().toStringList().size()) + QLatin1Char(')')); 0164 for (const QString& collection : m_model->collections()) 0165 ui.cbCollections->addItem(collection + QStringLiteral(" (") + QString::number(m_model->datasetCount(collection)) + QLatin1Char(')'), collection); 0166 0167 collectionChanged(ui.cbCollections->currentIndex()); 0168 } else 0169 QMessageBox::critical(this, 0170 i18n("File not found"), 0171 i18n("Couldn't open the dataset collections file %1. Please check your installation.", collectionsFileName)); 0172 } 0173 0174 /** 0175 * Shows all categories and sub-categories for the currently selected collection 0176 */ 0177 void ImportDatasetWidget::collectionChanged(int index) { 0178 m_allCollections = (index == 0); 0179 0180 if (!m_allCollections) 0181 m_collection = ui.cbCollections->itemData(index).toString(); 0182 else 0183 m_collection = QString(); 0184 0185 // update the info field 0186 m_collectionDescription.clear(); 0187 if (!m_allCollections) { 0188 for (const QJsonValueRef col : m_collections) { 0189 const QJsonObject& collection = col.toObject(); 0190 if (m_collection == collection[QLatin1String("name")].toString()) { 0191 m_collectionDescription = collection[QLatin1String("description")].toString(); 0192 m_collectionDescription += QStringLiteral("<br></hline><br>"); 0193 break; 0194 } 0195 } 0196 } else { 0197 for (const QJsonValueRef col : m_collections) { 0198 const QJsonObject& collection = col.toObject(); 0199 m_collectionDescription = collection[QLatin1String("description")].toString(); 0200 m_collectionDescription += QStringLiteral("<br>"); 0201 } 0202 } 0203 ui.lInfo->setText(m_collectionDescription); 0204 updateCategories(); 0205 0206 // update the completer 0207 if (m_completer) 0208 delete m_completer; 0209 0210 // add all categories, sub-categories and the dataset names for the current collection 0211 QStringList keywords; 0212 for (const auto& category : m_model->categories(m_collection)) { 0213 keywords << category; 0214 for (const auto& subcategory : m_model->subcategories(m_collection, category)) { 0215 keywords << subcategory; 0216 for (const QString& dataset : m_model->datasets(m_collection, category, subcategory)) 0217 keywords << dataset; 0218 } 0219 } 0220 0221 m_completer = new QCompleter(keywords, this); 0222 m_completer->setCompletionMode(QCompleter::PopupCompletion); 0223 m_completer->setCaseSensitivity(Qt::CaseInsensitive); 0224 m_completer->setFilterMode(Qt::MatchContains); 0225 ui.leSearch->setCompleter(m_completer); 0226 } 0227 0228 void ImportDatasetWidget::updateCategories() { 0229 m_initializing = true; 0230 ui.twCategories->clear(); 0231 0232 auto* rootItem = new QTreeWidgetItem(QStringList(i18n("All"))); 0233 ui.twCategories->addTopLevelItem(rootItem); 0234 0235 const QString& filter = ui.leSearch->text(); 0236 0237 // add categories 0238 for (const auto& category : m_model->categories(m_collection)) { 0239 const bool categoryMatch = (filter.isEmpty() || category.startsWith(filter, Qt::CaseInsensitive)); 0240 0241 if (categoryMatch) { 0242 auto* const item = new QTreeWidgetItem(QStringList(category)); 0243 rootItem->addChild(item); 0244 0245 // add all sub-categories 0246 for (const auto& subcategory : m_model->subcategories(m_collection, category)) 0247 item->addChild(new QTreeWidgetItem(QStringList(subcategory))); 0248 } else { 0249 QTreeWidgetItem* item = nullptr; 0250 for (const auto& subcategory : m_model->subcategories(m_collection, category)) { 0251 bool subcategoryMatch = subcategory.startsWith(filter, Qt::CaseInsensitive); 0252 0253 if (subcategoryMatch) { 0254 if (!item) { 0255 item = new QTreeWidgetItem(QStringList(category)); 0256 rootItem->addChild(item); 0257 item->setExpanded(true); 0258 } 0259 item->addChild(new QTreeWidgetItem(QStringList(subcategory))); 0260 } else { 0261 for (const QString& dataset : m_model->datasets(m_collection, category, subcategory)) { 0262 bool datasetMatch = dataset.startsWith(filter, Qt::CaseInsensitive); 0263 if (datasetMatch) { 0264 if (!item) { 0265 item = new QTreeWidgetItem(QStringList(category)); 0266 rootItem->addChild(item); 0267 item->setExpanded(true); 0268 } 0269 item->addChild(new QTreeWidgetItem(QStringList(subcategory))); 0270 break; 0271 } 0272 } 0273 } 0274 } 0275 } 0276 } 0277 0278 // remote the root item "All" if nothing has matched to the filter string 0279 if (rootItem->childCount() == 0) 0280 ui.twCategories->clear(); 0281 0282 // expand the root item and select the first category item 0283 rootItem->setExpanded(true); 0284 if (filter.isEmpty()) { 0285 rootItem->setSelected(true); 0286 updateDatasets(rootItem); 0287 } else { 0288 if (rootItem->child(0) && rootItem->child(0)->child(0)) { 0289 rootItem->child(0)->child(0)->setSelected(true); 0290 updateDatasets(rootItem->child(0)->child(0)); 0291 } else 0292 updateDatasets(nullptr); 0293 } 0294 0295 m_initializing = false; 0296 } 0297 0298 /** 0299 * @brief Populates lwDatasets with the datasets of the selected subcategory or its parent 0300 * @param item the selected subcategory 0301 */ 0302 void ImportDatasetWidget::updateDatasets(QTreeWidgetItem* item) { 0303 m_initializing = true; 0304 ui.lwDatasets->clear(); 0305 0306 if (!item) { 0307 // no category item is selected because nothing matches the search string 0308 m_initializing = false; 0309 datasetChanged(); 0310 return; 0311 } 0312 0313 const QString& filter = ui.leSearch->text(); 0314 0315 if (item->childCount() == 0) { 0316 // sub-category was selected -> show all its datasets 0317 m_category = item->parent()->text(0); 0318 m_subcategory = item->text(0); 0319 0320 addDatasetItems(m_collection, m_category, m_subcategory, filter); 0321 } else { 0322 if (!item->parent()) { 0323 // top-level item "All" was selected -> show datasets for all categories and their sub-categories 0324 m_category = QString(); 0325 m_subcategory = QString(); 0326 0327 for (const auto& category : m_model->categories(m_collection)) { 0328 for (const auto& subcategory : m_model->subcategories(m_collection, category)) 0329 addDatasetItems(m_collection, category, subcategory, filter); 0330 } 0331 } else { 0332 // a category was selected -> show all its datasets 0333 m_category = item->text(0); 0334 m_subcategory = QString(); 0335 0336 for (const auto& subcategory : m_model->subcategories(m_collection, m_category)) 0337 addDatasetItems(m_collection, m_category, subcategory, filter); 0338 } 0339 } 0340 0341 m_initializing = false; 0342 0343 // select the first available dataset 0344 if (ui.lwDatasets->count()) 0345 ui.lwDatasets->setCurrentRow(0); 0346 } 0347 0348 void ImportDatasetWidget::addDatasetItems(const QString& collection, const QString& category, const QString& subcategory, const QString& filter) { 0349 if (!filter.isEmpty() && (category.startsWith(filter, Qt::CaseInsensitive) || subcategory.startsWith(filter, Qt::CaseInsensitive))) { 0350 for (const QString& dataset : m_model->datasets(collection, category, subcategory)) 0351 ui.lwDatasets->addItem(new QListWidgetItem(dataset)); 0352 } else { 0353 for (const QString& dataset : m_model->datasets(collection, category, subcategory)) { 0354 if (filter.isEmpty() || dataset.startsWith(filter, Qt::CaseInsensitive)) 0355 ui.lwDatasets->addItem(new QListWidgetItem(dataset)); 0356 } 0357 } 0358 } 0359 0360 /** 0361 * @brief Returns the name of the selected dataset 0362 */ 0363 QString ImportDatasetWidget::getSelectedDataset() const { 0364 if (!ui.lwDatasets->selectedItems().isEmpty()) 0365 return ui.lwDatasets->selectedItems().at(0)->text(); 0366 return {}; 0367 } 0368 0369 /** 0370 * @brief Initiates the processing of the dataset's metadata file and of the dataset itself. 0371 * @param datasetHandler the DatasetHanlder that downloads processes the dataset 0372 */ 0373 void ImportDatasetWidget::import(DatasetHandler* datasetHandler) { 0374 datasetHandler->processMetadata(m_datasetObject, m_datasetDescription); 0375 } 0376 0377 /** 0378 * @brief Returns the QJsonObject associated with the currently selected dataset. 0379 */ 0380 QJsonObject ImportDatasetWidget::loadDatasetObject() { 0381 for (const QJsonValueRef col : m_collections) { 0382 const QJsonObject& collectionJson = col.toObject(); 0383 const QString& collection = collectionJson[QLatin1String("name")].toString(); 0384 0385 // we have to find the selected collection in the metadata file. 0386 if (m_allCollections || m_collection == collection) { 0387 QFile file(m_jsonDir + QLatin1Char('/') + collection + QStringLiteral(".json")); 0388 0389 // open the metadata file of the current collection 0390 if (file.open(QIODevice::ReadOnly)) { 0391 QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); 0392 file.close(); 0393 if (!doc.isObject()) { 0394 DEBUG("The " << STDSTRING(collection) << ".json file is invalid"); 0395 return {}; 0396 } 0397 0398 QJsonArray categoryArray = doc.object().value(QLatin1String("categories")).toArray(); 0399 0400 // processing categories 0401 for (const QJsonValueRef cat : categoryArray) { 0402 const QJsonObject currentCategory = cat.toObject(); 0403 const QString categoryName = currentCategory.value(QLatin1String("name")).toString(); 0404 if (m_category.isEmpty() || categoryName.compare(m_category) == 0) { 0405 const QJsonArray subcategories = currentCategory.value(QLatin1String("subcategories")).toArray(); 0406 0407 // processing subcategories 0408 for (const auto& sub : subcategories) { 0409 QJsonObject currentSubCategory = sub.toObject(); 0410 QString subcategoryName = currentSubCategory.value(QLatin1String("name")).toString(); 0411 0412 if (m_subcategory.isEmpty() || subcategoryName.compare(m_subcategory) == 0) { 0413 const QJsonArray datasetArray = currentSubCategory.value(QLatin1String("datasets")).toArray(); 0414 0415 // processing the datasets of the actual subcategory 0416 for (const auto& dataset : datasetArray) { 0417 if (getSelectedDataset().compare(dataset.toObject().value(QLatin1String("filename")).toString()) == 0) 0418 return dataset.toObject(); 0419 } 0420 0421 if (!m_subcategory.isEmpty()) 0422 break; 0423 } 0424 } 0425 0426 if (!m_category.isEmpty()) 0427 break; 0428 } 0429 } 0430 } 0431 0432 if (!m_allCollections) 0433 break; 0434 } 0435 } 0436 0437 return {}; 0438 } 0439 0440 /** 0441 * @brief Returns the structure containing the categories, subcategories and datasets. 0442 * @return the structure containing the categories, subcategories and datasets 0443 */ 0444 const DatasetsMap& ImportDatasetWidget::getDatasetsMap() { 0445 return m_datasetsMap; 0446 } 0447 0448 /** 0449 * @brief Sets the currently selected collection 0450 * @param category the name of the collection 0451 */ 0452 void ImportDatasetWidget::setCollection(const QString& collection) { 0453 ui.cbCollections->setCurrentText(collection + QStringLiteral(" (") + QString::number(m_model->datasetCount(collection)) + QLatin1Char(')')); 0454 } 0455 0456 /** 0457 * @brief Sets the currently selected category 0458 * @param category the name of the category 0459 */ 0460 void ImportDatasetWidget::setCategory(const QString& category) { 0461 for (int i = 0; i < ui.twCategories->topLevelItemCount(); i++) { 0462 if (ui.twCategories->topLevelItem(i)->text(0).compare(category) == 0) { 0463 updateDatasets(ui.twCategories->topLevelItem(i)); 0464 break; 0465 } 0466 } 0467 } 0468 0469 /** 0470 * @brief Sets the currently selected subcategory 0471 * @param subcategory the name of the subcategory 0472 */ 0473 void ImportDatasetWidget::setSubcategory(const QString& subcategory) { 0474 for (int i = 0; i < ui.twCategories->topLevelItemCount(); i++) { 0475 if (ui.twCategories->topLevelItem(i)->text(0).compare(m_category) == 0) { 0476 QTreeWidgetItem* categoryItem = ui.twCategories->topLevelItem(i); 0477 for (int j = 0; j < categoryItem->childCount(); j++) { 0478 if (categoryItem->child(j)->text(0).compare(subcategory) == 0) { 0479 updateDatasets(categoryItem->child(j)); 0480 break; 0481 } 0482 } 0483 break; 0484 } 0485 } 0486 } 0487 0488 /** 0489 * @brief Sets the currently selected dataset 0490 * @param the currently selected dataset 0491 */ 0492 void ImportDatasetWidget::setDataset(const QString& datasetName) { 0493 for (int i = 0; i < ui.lwDatasets->count(); i++) { 0494 if (ui.lwDatasets->item(i)->text().compare(datasetName) == 0) { 0495 ui.lwDatasets->item(i)->setSelected(true); 0496 break; 0497 } 0498 } 0499 } 0500 0501 /** 0502 * @brief Updates the details of the currently selected dataset 0503 */ 0504 void ImportDatasetWidget::datasetChanged() { 0505 QString dataset = getSelectedDataset(); 0506 0507 // no need to fetch the same dataset description again if it's already shown 0508 if (m_collection == m_prevCollection && m_category == m_prevCategory && m_subcategory == m_prevSubcategory && dataset == m_prevDataset) 0509 return; 0510 0511 m_prevCollection = m_collection; 0512 m_prevCategory = m_category; 0513 m_prevSubcategory = m_subcategory; 0514 m_prevDataset = dataset; 0515 0516 if (!dataset.isEmpty()) { 0517 m_datasetObject = loadDatasetObject(); 0518 0519 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0520 if (m_datasetObject.contains(QLatin1String("description_url")) 0521 && QNetworkInformation::instance()->reachability() == QNetworkInformation::Reachability::Online) { 0522 #else 0523 if (m_datasetObject.contains(QLatin1String("description_url")) && m_networkManager->networkAccessible() == QNetworkAccessManager::Accessible) { 0524 #endif 0525 WAIT_CURSOR; 0526 m_networkManager->get(QNetworkRequest(QUrl(m_datasetObject[QLatin1String("description_url")].toString()))); 0527 } else { 0528 m_datasetDescription = QStringLiteral("<b>") + i18n("Dataset") + QStringLiteral(":</b><br>"); 0529 m_datasetDescription += m_datasetObject[QLatin1String("name")].toString(); 0530 m_datasetDescription += QStringLiteral("<br><br>"); 0531 m_datasetDescription += QStringLiteral("<b>") + i18n("Description") + QStringLiteral(":</b><br>"); 0532 m_datasetDescription += m_datasetObject[QLatin1String("description")].toString(); 0533 0534 if (!m_allCollections) 0535 ui.lInfo->setText(m_collectionDescription + m_datasetDescription); 0536 else 0537 ui.lInfo->setText(m_datasetDescription); 0538 } 0539 } else 0540 m_datasetObject = QJsonObject(); 0541 0542 Q_EMIT datasetSelected(); 0543 } 0544 0545 void ImportDatasetWidget::downloadFinished(QNetworkReply* reply) { 0546 if (reply->error() == QNetworkReply::NoError) { 0547 QString info = QLatin1String(reply->readAll()); 0548 0549 if (m_collection == QLatin1String("Rdatasets")) { 0550 // detailed descriptions for R is in html format, 0551 // remove the header from the html file since we construct our own header 0552 0553 int headerStart = info.indexOf(QLatin1String("<head>")); 0554 int headerEnd = info.indexOf(QLatin1String("</head>")); 0555 info = info.left(headerStart) + info.right(info.length() - headerEnd - 7); 0556 0557 headerStart = info.indexOf(QLatin1String("<table")); 0558 headerEnd = info.indexOf(QLatin1String("</table>")); 0559 info = info.left(headerStart) + info.right(info.length() - headerEnd - 8); 0560 0561 headerStart = info.indexOf(QLatin1String("<h2>")); 0562 headerEnd = info.indexOf(QLatin1String("</h2>")); 0563 info = info.left(headerStart) + info.right(info.length() - headerEnd - 5); 0564 0565 info = info.replace(QLatin1String("<body>\n\n\n\n\n\n"), QLatin1String("<body>")); 0566 info = info.remove(QLatin1String("\n\n\n")); 0567 } else 0568 info = info.replace(QLatin1Char('\n'), QLatin1String("<br>")); 0569 0570 // do further collection specific replacements to get better formatting 0571 if (m_collection == QLatin1String("JSEDataArchive")) { 0572 info = info.replace(QLatin1String("NAME:"), QLatin1String("<b>NAME:</b>"), Qt::CaseInsensitive); 0573 info = info.replace(QLatin1String("TYPE:"), QLatin1String("<b>TYPE:</b>"), Qt::CaseSensitive); 0574 info = info.replace(QLatin1String("SIZE:"), QLatin1String("<b>SIZE:</b>"), Qt::CaseSensitive); 0575 info = info.replace(QLatin1String("DESCRIPTIVE ABSTRACT:"), QLatin1String("<b>DESCRIPTIVE ABSTRACT:</b>"), Qt::CaseInsensitive); 0576 info = info.replace(QLatin1String("NOTE:"), QLatin1String("<b>NOTE:</b>"), Qt::CaseSensitive); 0577 info = info.replace(QLatin1String("SPECIAL NOTES:"), QLatin1String("<b>SPECIAL NOTES:</b>"), Qt::CaseSensitive); 0578 info = info.replace(QLatin1String("SOURCE:"), QLatin1String("<b>SOURCE:</b>"), Qt::CaseSensitive); 0579 info = info.replace(QLatin1String("SOURCES:"), QLatin1String("<b>SOURCES:</b>"), Qt::CaseInsensitive); 0580 info = info.replace(QLatin1String("DATA <b>SOURCE:</b>"), QLatin1String("<b>DATA SOURCE:</b>"), Qt::CaseSensitive); 0581 info = info.replace(QLatin1String("DATASET LAYOUT:"), QLatin1String("<b>DATASET LAYOUT:</b>"), Qt::CaseSensitive); 0582 info = info.replace(QLatin1String("DATASETS LAYOUT:"), QLatin1String("<b>DATASETS LAYOUT:</b>"), Qt::CaseSensitive); 0583 info = info.replace(QLatin1String("VARIABLE DESCRIPTIONS:"), QLatin1String("<b>VARIABLE DESCRIPTIONS:</b>"), Qt::CaseSensitive); 0584 info = info.replace(QLatin1String("VARIABLES DESCRIPTIONS:"), QLatin1String("<b>VARIABLES DESCRIPTIONS:</b>"), Qt::CaseSensitive); 0585 info = info.replace(QLatin1String("RELATED DATASETS:"), QLatin1String("<b>RELATED DATASETS:</b>"), Qt::CaseSensitive); 0586 info = info.replace(QLatin1String("SPECIAL NOTES:"), QLatin1String("<b>SPECIAL NOTES:</b>"), Qt::CaseSensitive); 0587 info = info.replace(QLatin1String("STORY BEHIND THE DATA:"), QLatin1String("<b>STORY BEHIND THE DATA:</b>"), Qt::CaseSensitive); 0588 info = info.replace(QLatin1String("THE <b>STORY BEHIND THE DATA:</b>"), QLatin1String("<b>THE STORY BEHIND THE DATA:</b>"), Qt::CaseSensitive); 0589 info = info.replace(QLatin1String("PEDAGOGICAL NOTES:"), QLatin1String("<b>PEDAGOGICAL NOTES:</b>"), Qt::CaseSensitive); 0590 info = info.replace(QLatin1String("REFERENCE:"), QLatin1String("<b>REFERENCE:</b>"), Qt::CaseSensitive); 0591 info = info.replace(QLatin1String("REFERENCES:"), QLatin1String("<b>REFERENCES:</b>"), Qt::CaseSensitive); 0592 info = info.replace(QLatin1String("SUBMITTED BY:"), QLatin1String("<b>SUBMITTED BY:</b>"), Qt::CaseSensitive); 0593 } 0594 0595 m_datasetDescription = info; 0596 } else { 0597 DEBUG("Failed to fetch the description."); 0598 m_datasetDescription = m_datasetObject[QLatin1String("description")].toString(); 0599 } 0600 0601 if (!m_allCollections) 0602 ui.lInfo->setText(m_collectionDescription + m_datasetDescription); 0603 else 0604 ui.lInfo->setText(m_datasetDescription); 0605 0606 reply->deleteLater(); 0607 RESET_CURSOR; 0608 }