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