From 67f322a11837e691ec3a00063a8d866f3192cf85 Mon Sep 17 00:00:00 2001 From: Maxim Pimenov Date: Thu, 6 Jun 2019 13:54:58 +0300 Subject: [PATCH] [qt] Use the ranking from search when displaying downloader search results. --- qt/update_dialog.cpp | 95 +++++++++++++++++++++++++++++--------------- qt/update_dialog.hpp | 15 ++++--- 2 files changed, 71 insertions(+), 39 deletions(-) diff --git a/qt/update_dialog.cpp b/qt/update_dialog.cpp index d4298d298c..881e0a9497 100644 --- a/qt/update_dialog.cpp +++ b/qt/update_dialog.cpp @@ -7,12 +7,11 @@ #include "platform/settings.hpp" #include "base/assert.hpp" -#include "base/stl_helpers.hpp" -#include "base/string_utils.hpp" +#include "base/logging.hpp" #include #include -#include +#include #include #include @@ -30,10 +29,12 @@ using namespace storage; enum { -// KItemIndexFlag = 0, + // KItemIndexFlag = 0, KColumnIndexCountry, KColumnIndexStatus, KColumnIndexSize, + KColumnIndexMatchedBy, + KColumnIndexPositionInRanking, KNumberOfColumns }; @@ -47,6 +48,9 @@ enum namespace { +size_t const kInvalidPos = numeric_limits::max(); +size_t const kIrrelevantPos = numeric_limits::max() - 1; + bool DeleteNotUploadedEditsConfirmation() { QMessageBox msb; @@ -55,11 +59,6 @@ bool DeleteNotUploadedEditsConfirmation() msb.setDefaultButton(QMessageBox::Cancel); return QMessageBox::Yes == msb.exec(); } - -bool Matches(CountryId const & countryId, vector const & filter) -{ - return binary_search(filter.begin(), filter.end(), countryId); -} } // namespace namespace qt @@ -78,8 +77,17 @@ namespace qt m_tree = new QTreeWidget(this); m_tree->setColumnCount(KNumberOfColumns); QStringList columnLabels; - columnLabels << tr("Country") << tr("Status") << tr("Size"); + columnLabels << tr("Country") << tr("Status") << tr("Size") << tr("Matched by") << tr("Rank"); m_tree->setHeaderLabels(columnLabels); + + m_tree->setColumnHidden(KColumnIndexPositionInRanking, true); + + m_tree->header()->setSectionResizeMode(KColumnIndexCountry, QHeaderView::ResizeToContents); + m_tree->header()->setSectionResizeMode(KColumnIndexStatus, QHeaderView::ResizeToContents); + m_tree->header()->setSectionResizeMode(KColumnIndexMatchedBy, QHeaderView::ResizeToContents); + m_tree->header()->setSectionResizeMode(KColumnIndexPositionInRanking, + QHeaderView::ResizeToContents); + connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(OnItemClick(QTreeWidgetItem *, int))); QHBoxLayout * horizontalLayout = new QHBoxLayout(); @@ -111,7 +119,7 @@ namespace qt setLayout(verticalLayout); setWindowTitle(tr("Geographical Regions")); - resize(700, 600); + resize(900, 600); // We want to receive all download progress and result events. using namespace std::placeholders; @@ -258,20 +266,25 @@ namespace qt DownloaderSearchParams params; params.m_query = m_query; params.m_inputLocale = m_locale; + auto const query = m_query; - params.m_onResults = [this, timestamp](DownloaderSearchResults const & results) { - vector filter; - for (auto const & res : results.m_results) - filter.push_back(res.m_countryId); + params.m_onResults = [this, timestamp, query](DownloaderSearchResults const & results) { + Filter filter; + for (size_t i = 0; i < results.m_results.size(); ++i) + { + auto const & res = results.m_results[i]; + auto const added = filter.emplace(res.m_countryId, make_pair(i + 1, res.m_matchedName)); + if (!added.second) + LOG(LWARNING, ("Duplicate CountryId in results for query:", query)); + } - base::SortUnique(filter); FillTree(filter, timestamp); }; m_framework.SearchInDownloader(params); } - void UpdateDialog::FillTree(boost::optional> const & filter, uint64_t timestamp) + void UpdateDialog::FillTree(boost::optional const & filter, uint64_t timestamp) { CHECK_THREAD_CHECKER(m_threadChecker, ()); @@ -288,39 +301,50 @@ namespace qt ASSERT_EQUAL(m_tree->topLevelItemCount(), 1, ()); m_tree->topLevelItem(0)->setExpanded(true); - // Note. Sorting does not correspond to the ranking of search results and - // we do not show the matched name in the qt app. So far it's been - // enough to look at the log output when any of these features were needed. - m_tree->sortByColumn(KColumnIndexCountry, Qt::AscendingOrder); + m_tree->sortItems(KColumnIndexPositionInRanking, Qt::AscendingOrder); m_tree->setSortingEnabled(true); - m_tree->header()->setSectionResizeMode(KColumnIndexCountry, QHeaderView::ResizeToContents); - m_tree->header()->setSectionResizeMode(KColumnIndexStatus, QHeaderView::ResizeToContents); } void UpdateDialog::FillTreeImpl(QTreeWidgetItem * parent, CountryId const & countryId, - boost::optional> const & filter) + boost::optional const & filter) { CountriesVec children; GetStorage().GetChildren(countryId, children); + size_t posInRanking = kInvalidPos; + string matchedBy; + if (filter) + { + auto const it = filter->find(countryId); + if (it != filter->end()) + { + posInRanking = it->second.first; + matchedBy = it->second.second; + } + } + else + { + posInRanking = kIrrelevantPos; + } + if (children.empty()) { - if (filter && !Matches(countryId, *filter)) + if (filter && posInRanking == kInvalidPos) return; - QTreeWidgetItem * item = CreateTreeItem(countryId, parent); + QTreeWidgetItem * item = CreateTreeItem(countryId, posInRanking, matchedBy, parent); UpdateRowWithCountryInfo(item, countryId); return; } - QTreeWidgetItem * item = CreateTreeItem(countryId, parent); + QTreeWidgetItem * item = CreateTreeItem(countryId, posInRanking, matchedBy, parent); UpdateRowWithCountryInfo(item, countryId); - if (filter && Matches(countryId, *filter)) + if (filter && posInRanking != kInvalidPos) { // Filter matches to the group name, do not filter the group. for (auto const & child : children) - FillTreeImpl(item, child, vector()); + FillTreeImpl(item, child, {} /* filter */); return; } @@ -431,8 +455,7 @@ namespace qt uint((size.first + 1023) / 1024)).arg(uint((size.second + 1023) / 1024))); } - // Needed for column sorting. - item->setData(KColumnIndexSize, Qt::UserRole, QVariant(qint64(size.second))); + item->setData(KColumnIndexSize, Qt::UserRole, QVariant(static_cast(size.second))); } // Commented out because it looks terrible on black backgrounds. @@ -448,13 +471,19 @@ namespace qt return attrs.m_nodeLocalName.c_str(); } - QTreeWidgetItem * UpdateDialog::CreateTreeItem(CountryId const & countryId, - QTreeWidgetItem * parent) + QTreeWidgetItem * UpdateDialog::CreateTreeItem(CountryId const & countryId, size_t posInRanking, + string matchedBy, QTreeWidgetItem * parent) { QString const text = GetNodeName(countryId); QTreeWidgetItem * item = new QTreeWidgetItem(parent, QStringList(text)); item->setData(KColumnIndexCountry, Qt::UserRole, QVariant(countryId.c_str())); + auto const pos = QVariant(static_cast(posInRanking)); + item->setData(KColumnIndexPositionInRanking, Qt::DisplayRole, pos); + + auto const matched = QVariant(matchedBy.c_str()); + item->setData(KColumnIndexMatchedBy, Qt::DisplayRole, matched); + if (parent == nullptr) m_tree->addTopLevelItem(item); diff --git a/qt/update_dialog.hpp b/qt/update_dialog.hpp index 25fbf1f7a6..9c8051c3b4 100644 --- a/qt/update_dialog.hpp +++ b/qt/update_dialog.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -47,22 +48,24 @@ namespace qt void OnQueryTextChanged(QString const & text); private: + // CountryId to its ranking position and matched string (assuming no duplicates). + using Filter = std::unordered_map>; + void RefillTree(); void StartSearchInDownloader(); // Adds only those countries present in |filter|. // Calls whose timestamp is not the latest are discarded. - void FillTree(boost::optional> const & filter, - uint64_t timestamp); + void FillTree(boost::optional const & filter, uint64_t timestamp); void FillTreeImpl(QTreeWidgetItem * parent, storage::CountryId const & countryId, - boost::optional> const & filter); + boost::optional const & filter); void UpdateRowWithCountryInfo(storage::CountryId const & countryId); void UpdateRowWithCountryInfo(QTreeWidgetItem * item, storage::CountryId const & countryId); QString GetNodeName(storage::CountryId const & countryId); - QTreeWidgetItem * CreateTreeItem(storage::CountryId const & countryId, - QTreeWidgetItem * parent); + QTreeWidgetItem * CreateTreeItem(storage::CountryId const & countryId, size_t posInRanking, + std::string matchedBy, QTreeWidgetItem * parent); std::vector GetTreeItemsByCountryId(storage::CountryId const & countryId); storage::CountryId GetCountryIdByTreeItem(QTreeWidgetItem *); @@ -81,4 +84,4 @@ namespace qt DECLARE_THREAD_CHECKER(m_threadChecker); }; - } // namespace qt +} // namespace qt