Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--map/CMakeLists.txt2
-rw-r--r--map/address_finder.cpp2
-rw-r--r--map/framework.cpp377
-rw-r--r--map/framework.hpp80
-rw-r--r--map/map.pro2
-rw-r--r--map/search_api.cpp295
-rw-r--r--map/search_api.hpp127
-rw-r--r--qt/draw_widget.cpp7
-rw-r--r--search/search_quality/assessment_tool/main_model.cpp2
9 files changed, 555 insertions, 339 deletions
diff --git a/map/CMakeLists.txt b/map/CMakeLists.txt
index 180ff71402..204afad342 100644
--- a/map/CMakeLists.txt
+++ b/map/CMakeLists.txt
@@ -58,6 +58,8 @@ set(
routing_manager.hpp
routing_mark.cpp
routing_mark.hpp
+ search_api.cpp
+ search_api.hpp
search_mark.cpp
search_mark.hpp
taxi_delegate.cpp
diff --git a/map/address_finder.cpp b/map/address_finder.cpp
index 825dce4609..49e7f76e1e 100644
--- a/map/address_finder.cpp
+++ b/map/address_finder.cpp
@@ -511,8 +511,6 @@ search::AddressInfo Framework::GetFeatureAddressInfo(FeatureType & ft) const
vector<string> Framework::GetPrintableFeatureTypes(FeatureType const & ft) const
{
- ASSERT(m_searchEngine, ());
-
vector<string> results;
int8_t const locale = CategoriesHolder::MapLocaleToInteger(languages::GetCurrentOrig());
diff --git a/map/framework.cpp b/map/framework.cpp
index 68efffc43d..91a73559e6 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -139,7 +139,6 @@ char const kTranslitMode[] = "TransliterationMode";
char const kICUDataFile[] = "icudt57l.dat";
#endif
-double const kDistEqualQueryMeters = 100.0;
double const kLargeFontsScaleFactor = 1.6;
size_t constexpr kMaxTrafficCacheSizeBytes = 64 /* Mb */ * 1024 * 1024;
@@ -147,30 +146,23 @@ size_t constexpr kMaxTrafficCacheSizeBytes = 64 /* Mb */ * 1024 * 1024;
// To adjust GpsTrackFilter was added secret command "?gpstrackaccuracy:xxx;"
// where xxx is a new value for horizontal accuracy.
// This is temporary solution while we don't have a good filter.
-void ParseSetGpsTrackMinAccuracyCommand(string const & query)
+bool ParseSetGpsTrackMinAccuracyCommand(string const & query)
{
const char kGpsAccuracy[] = "?gpstrackaccuracy:";
- if (strings::StartsWith(query, kGpsAccuracy))
- {
- size_t const end = query.find(';', sizeof(kGpsAccuracy) - 1);
- if (end != string::npos)
- {
- string s(query.begin() + sizeof(kGpsAccuracy) - 1, query.begin() + end);
- double value;
- if (strings::to_double(s, value))
- {
- GpsTrackFilter::StoreMinHorizontalAccuracy(value);
- }
- }
- }
-}
+ if (!strings::StartsWith(query, kGpsAccuracy))
+ return false;
-// Cancels search query by |handle|.
-void CancelQuery(weak_ptr<search::ProcessorHandle> & handle)
-{
- if (auto queryHandle = handle.lock())
- queryHandle->Cancel();
- handle.reset();
+ size_t const end = query.find(';', sizeof(kGpsAccuracy) - 1);
+ if (end == string::npos)
+ return false;
+
+ string s(query.begin() + sizeof(kGpsAccuracy) - 1, query.begin() + end);
+ double value;
+ if (!strings::to_double(s, value))
+ return false;
+
+ GpsTrackFilter::StoreMinHorizontalAccuracy(value);
+ return true;
}
string MakeSearchBookingUrl(booking::Api const & bookingApi, search::CityFinder & cityFinder,
@@ -285,24 +277,7 @@ void Framework::OnViewportChanged(ScreenBase const & screen)
{
m_currentModelView = screen;
- auto const forceSearchInViewport = !m_isViewportInitialized;
-
- if (!m_isViewportInitialized)
- {
- m_isViewportInitialized = true;
- for (size_t i = 0; i < static_cast<size_t>(search::Mode::Count); i++)
- {
- auto & intent = m_searchIntents[i];
- // Viewport search will be triggered below, in PokeSearchInViewport().
- if (!intent.m_isDelayed || static_cast<search::Mode>(i) == search::Mode::Viewport)
- continue;
- SetViewportIfPossible(intent.m_params);
- SetCurrentPositionIfPossible(intent.m_params);
- Search(intent);
- }
- }
-
- PokeSearchInViewport(forceSearchInViewport);
+ GetSearchAPI().OnViewportChanged(GetCurrentViewport());
m_trafficManager.UpdateViewport(m_currentModelView);
m_localAdsManager.UpdateViewport(m_currentModelView);
@@ -355,7 +330,7 @@ void Framework::Migrate(bool keepDownloaded)
OnDestroyGLContext();
}
m_selectedFeature = FeatureID();
- m_searchEngine.reset();
+ m_searchAPI.reset();
m_infoGetter.reset();
m_taxiEngine.reset();
m_cityFinder.reset();
@@ -367,7 +342,7 @@ void Framework::Migrate(bool keepDownloaded)
GetStorage().Migrate(keepDownloaded ? existedCountries : TCountriesVec());
InitCountryInfoGetter();
InitUGC();
- InitSearchEngine();
+ InitSearchAPI();
InitCityFinder();
InitTaxiEngine();
RegisterAllMaps();
@@ -450,8 +425,8 @@ Framework::Framework(FrameworkParams const & params)
InitUGC();
LOG(LDEBUG, ("UGC initialized"));
- InitSearchEngine();
- LOG(LDEBUG, ("Search engine initialized"));
+ InitSearchAPI();
+ LOG(LDEBUG, ("Search API initialized"));
InitCityFinder();
InitTaxiEngine();
@@ -462,7 +437,7 @@ Framework::Framework(FrameworkParams const & params)
LOG(LDEBUG, ("Maps initialized"));
// Need to reload cities boundaries because maps in indexer were updated.
- m_searchEngine->LoadCitiesBoundaries();
+ GetSearchAPI().LoadCitiesBoundaries();
// Init storage with needed callback.
m_storage.Init(
@@ -591,7 +566,7 @@ void Framework::OnCountryFileDownloaded(storage::TCountryId const & countryId, s
m_trafficManager.Invalidate();
m_localAdsManager.OnDownloadCountry(countryId);
InvalidateRect(rect);
- m_searchEngine->ClearCaches();
+ GetSearchAPI().ClearCaches();
}
bool Framework::OnCountryFileDelete(storage::TCountryId const & countryId, storage::TLocalFilePtr const localFile)
@@ -616,7 +591,7 @@ bool Framework::OnCountryFileDelete(storage::TCountryId const & countryId, stora
}
InvalidateRect(rect);
- m_searchEngine->ClearCaches();
+ GetSearchAPI().ClearCaches();
return deferredDelete;
}
@@ -970,9 +945,9 @@ void Framework::FillSearchResultInfo(SearchMarkPoint const & smp, place_page::In
void Framework::FillMyPositionInfo(place_page::Info & info, df::TapInfo const & tapInfo) const
{
- double lat, lon;
- VERIFY(GetCurrentPosition(lat, lon), ());
- info.SetMercator(MercatorBounds::FromLatLon(lat, lon));
+ auto const position = GetCurrentPosition();
+ VERIFY(position, ());
+ info.SetMercator(*position);
info.SetIsMyPosition();
info.SetCustomName(m_stringsBundle.GetString("my_position"));
@@ -1301,7 +1276,7 @@ void Framework::ClearAllCaches()
{
m_model.ClearCaches();
m_infoGetter->ClearCaches();
- m_searchEngine->ClearCaches();
+ GetSearchAPI().ClearCaches();
}
void Framework::OnUpdateCurrentCountry(m2::PointF const & pt, int zoomLevel)
@@ -1330,120 +1305,32 @@ void Framework::SetCurrentCountryChangedListener(TCurrentCountryChanged const &
void Framework::PokeSearchInViewport(bool forceSearch)
{
- if (!m_isViewportInitialized || !IsViewportSearchActive())
- return;
-
- // Copy is intentional here, to skip possible duplicating requests.
- auto params = m_searchIntents[static_cast<size_t>(search::Mode::Viewport)].m_params;
- SetViewportIfPossible(params);
- SetCurrentPositionIfPossible(params);
- Search(params, forceSearch);
+ return GetSearchAPI().PokeSearchInViewport(forceSearch);
}
bool Framework::SearchEverywhere(search::EverywhereSearchParams const & params)
{
- search::SearchParams p;
- p.m_query = params.m_query;
- p.m_inputLocale = params.m_inputLocale;
- p.m_mode = search::Mode::Everywhere;
- SetViewportIfPossible(p); // Search request will be delayed if viewport is not available.
- p.m_maxNumResults = search::SearchParams::kDefaultNumResultsEverywhere;
- p.m_suggestsEnabled = true;
- p.m_needAddress = true;
- p.m_needHighlighting = true;
- p.m_hotelsFilter = params.m_hotelsFilter;
- p.m_cianMode = IsCianMode(params.m_query);
-
- p.m_onResults = search::EverywhereSearchCallback(
- static_cast<search::EverywhereSearchCallback::Delegate &>(*this),
- [params](search::Results const & results, vector<bool> const & isLocalAdsCustomer) {
- if (params.m_onResults)
- GetPlatform().RunOnGuiThread([params, results, isLocalAdsCustomer]() {
- params.m_onResults(results, isLocalAdsCustomer);
- });
- });
- SetCurrentPositionIfPossible(p);
- return Search(p, true /* forceSearch */);
+ return GetSearchAPI().SearchEverywhere(params);
}
bool Framework::SearchInViewport(search::ViewportSearchParams const & params)
{
- // TODO: delete me after Cian project is finished.
- m_cianSearchMode = IsCianMode(params.m_query);
-
- search::SearchParams p;
- p.m_query = params.m_query;
- p.m_inputLocale = params.m_inputLocale;
- SetViewportIfPossible(p); // Search request will be delayed if viewport is not available.
- p.m_maxNumResults = search::SearchParams::kDefaultNumResultsInViewport;
- p.m_mode = search::Mode::Viewport;
- p.m_suggestsEnabled = false;
- p.m_needAddress = false;
- p.m_needHighlighting = false;
- p.m_hotelsFilter = params.m_hotelsFilter;
- p.m_cianMode = m_cianSearchMode;
-
- p.m_onStarted = [params]() {
- if (params.m_onStarted)
- GetPlatform().RunOnGuiThread([params]() { params.m_onStarted(); });
- };
-
- p.m_onResults = search::ViewportSearchCallback(
- static_cast<search::ViewportSearchCallback::Delegate &>(*this),
- [params](search::Results const & results) {
- if (results.IsEndMarker() && params.m_onCompleted)
- GetPlatform().RunOnGuiThread([params, results]() { params.m_onCompleted(results); });
- });
- SetCurrentPositionIfPossible(p);
-
- return Search(p, false /* forceSearch */);
+ return GetSearchAPI().SearchInViewport(params);
}
bool Framework::SearchInDownloader(DownloaderSearchParams const & params)
{
- search::SearchParams p;
- p.m_query = params.m_query;
- p.m_inputLocale = params.m_inputLocale;
- SetViewportIfPossible(p); // Search request will be delayed if viewport is not available.
- p.m_maxNumResults = search::SearchParams::kDefaultNumResultsEverywhere;
- p.m_mode = search::Mode::Downloader;
- p.m_suggestsEnabled = false;
- p.m_needAddress = false;
- p.m_needHighlighting = false;
- p.m_onResults = search::DownloaderSearchCallback(
- static_cast<search::DownloaderSearchCallback::Delegate &>(*this), m_model.GetIndex(),
- GetCountryInfoGetter(), GetStorage(), params);
- return Search(p, true /* forceSearch */);
-}
-
-void Framework::SetViewportIfPossible(search::SearchParams & params)
-{
- if (m_isViewportInitialized)
- params.m_viewport = GetCurrentViewport();
+ return GetSearchAPI().SearchInDownloader(params);
}
void Framework::CancelSearch(search::Mode mode)
{
- ASSERT_NOT_EQUAL(mode, search::Mode::Count, ());
-
- if (mode == search::Mode::Viewport)
- {
- // TODO: delete me after Cian project is finished.
- m_cianSearchMode = false;
-
- ClearSearchResultsMarks();
- SetDisplacementMode(DisplacementModeManager::SLOT_INTERACTIVE_SEARCH, false /* show */);
- }
-
- auto & intent = m_searchIntents[static_cast<size_t>(mode)];
- intent.m_params.Clear();
- CancelQuery(intent.m_handle);
+ return GetSearchAPI().CancelSearch(mode);
}
void Framework::CancelAllSearches()
{
- for (size_t i = 0; i < static_cast<size_t>(search::Mode::Count); ++i)
- CancelSearch(static_cast<search::Mode>(i));
+ return GetSearchAPI().CancelAllSearches();
}
void Framework::MemoryWarning()
@@ -1491,20 +1378,6 @@ void Framework::EnterForeground()
m_routingManager.SetAllowSendingPoints(true);
}
-bool Framework::GetCurrentPosition(double & lat, double & lon) const
-{
- m2::PointD pos;
- MyPositionMarkPoint * myPosMark = UserMarkContainer::UserMarkForMyPostion();
- if (!myPosMark->HasPosition())
- return false;
-
- pos = myPosMark->GetPivot();
-
- lat = MercatorBounds::YToLat(pos.y);
- lon = MercatorBounds::XToLon(pos.x);
- return true;
-}
-
void Framework::InitCountryInfoGetter()
{
ASSERT(!m_infoGetter.get(), ("InitCountryInfoGetter() must be called only once."));
@@ -1520,21 +1393,18 @@ void Framework::InitUGC()
m_ugcApi = make_unique<ugc::Api>(m_model.GetIndex());
}
-void Framework::InitSearchEngine()
+void Framework::InitSearchAPI()
{
- ASSERT(!m_searchEngine.get(), ("InitSearchEngine() must be called only once."));
+ ASSERT(!m_searchAPI.get(), ("InitSearchAPI() must be called only once."));
ASSERT(m_infoGetter.get(), ());
try
{
- search::Engine::Params params;
- params.m_locale = languages::GetCurrentOrig();
- params.m_numThreads = 1;
- m_searchEngine = make_unique<search::Engine>(const_cast<Index &>(m_model.GetIndex()),
- GetDefaultCategories(), *m_infoGetter, params);
+ m_searchAPI = make_unique<SearchAPI>(const_cast<Index &>(m_model.GetIndex()), m_storage,
+ *m_infoGetter, static_cast<SearchAPI::Delegate &>(*this));
}
catch (RootException const & e)
{
- LOG(LCRITICAL, ("Can't load needed resources for search::Engine:", e.Msg()));
+ LOG(LCRITICAL, ("Can't load needed resources for SearchAPI:", e.Msg()));
}
}
@@ -1602,19 +1472,27 @@ Framework::DoAfterUpdate Framework::ToDoAfterUpdate() const
return DoAfterUpdate::AskForUpdateMaps;
}
+SearchAPI & Framework::GetSearchAPI()
+{
+ ASSERT(m_searchAPI != nullptr, ("Search API is not initialized."));
+ return *m_searchAPI;
+}
+
+SearchAPI const & Framework::GetSearchAPI() const
+{
+ ASSERT(m_searchAPI != nullptr, ("Search API is not initialized."));
+ return *m_searchAPI;
+}
+
search::DisplayedCategories const & Framework::GetDisplayedCategories()
{
ASSERT(m_displayedCategories, ());
ASSERT(m_cityFinder, ());
- ms::LatLon latlon;
string city;
- if (GetCurrentPosition(latlon.lat, latlon.lon))
- {
- city = m_cityFinder->GetCityName(MercatorBounds::FromLatLon(latlon),
- StringUtf8Multilang::kEnglishCode);
- }
+ if (auto const position = GetCurrentPosition())
+ city = m_cityFinder->GetCityName(*position, StringUtf8Multilang::kEnglishCode);
CianModifier cianModifier(city);
m_displayedCategories->Modify(cianModifier);
@@ -1622,96 +1500,6 @@ search::DisplayedCategories const & Framework::GetDisplayedCategories()
return *m_displayedCategories;
}
-bool Framework::Search(search::SearchParams const & params, bool forceSearch)
-{
- if (ParseDrapeDebugCommand(params.m_query))
- return false;
-
- auto const mode = params.m_mode;
- auto & intent = m_searchIntents[static_cast<size_t>(mode)];
-
-#ifdef FIXED_LOCATION
- search::SearchParams rParams(params);
- if (params.IsValidPosition())
- {
- m_fixedPos.GetLat(rParams.m_lat);
- m_fixedPos.GetLon(rParams.m_lon);
- }
-#else
- search::SearchParams const & rParams = params;
-#endif
-
- ParseSetGpsTrackMinAccuracyCommand(params.m_query);
- if (ParseEditorDebugCommand(params))
- return true;
-
- if (!forceSearch && QueryMayBeSkipped(intent, rParams))
- return false;
-
- intent.m_params = rParams;
- // Cancels previous search request (if any) and initiates new search request.
- CancelQuery(intent.m_handle);
-
- double const eps = m_searchMarks.GetMaxDimension(m_currentModelView);
- intent.m_params.m_minDistanceOnMapBetweenResults = eps;
-
- Search(intent);
-
- return true;
-}
-
-void Framework::Search(SearchIntent & intent) const
-{
- if (!m_isViewportInitialized)
- {
- intent.m_isDelayed = true;
- return;
- }
-
- intent.m_handle = m_searchEngine->Search(intent.m_params);
- intent.m_isDelayed = false;
-}
-
-void Framework::SetCurrentPositionIfPossible(search::SearchParams & params)
-{
- double lat;
- double lon;
- if (GetCurrentPosition(lat, lon))
- params.m_position = MercatorBounds::FromLatLon(lat, lon);
-}
-
-bool Framework::QueryMayBeSkipped(SearchIntent const & intent,
- search::SearchParams const & params) const
-{
- auto const & lastParams = intent.m_params;
- auto const & lastViewport = lastParams.m_viewport;
-
- auto const & viewport = params.m_viewport;
-
- if (!lastParams.IsEqualCommon(params))
- return false;
- if (!lastViewport.IsValid() ||
- !search::IsEqualMercator(lastViewport, viewport, kDistEqualQueryMeters))
- {
- return false;
- }
-
- if (lastParams.m_position && params.m_position &&
- MercatorBounds::DistanceOnEarth(*lastParams.m_position, *params.m_position) >
- kDistEqualQueryMeters)
- {
- return false;
- }
-
- if (static_cast<bool>(lastParams.m_position) != static_cast<bool>(params.m_position))
- return false;
-
- if (!search::hotels_filter::Rule::IsIdentical(lastParams.m_hotelsFilter, params.m_hotelsFilter))
- return false;
-
- return true;
-}
-
void Framework::SelectSearchResult(search::Result const & result, bool animation)
{
place_page::Info info;
@@ -1850,7 +1638,7 @@ void Framework::FillSearchResultsMarks(search::Results::ConstIter begin,
}
// TODO: delete me after Cian project is finished.
- if (m_cianSearchMode)
+ if (GetSearchAPI().IsCianSearchMode())
{
mark->SetMarkType(SearchMarkType::Cian);
continue;
@@ -2434,13 +2222,17 @@ void Framework::OnTapEvent(TapEvent const & tapEvent)
m_lastTapEvent = make_unique<TapEvent>(tapEvent);
{ // Log statistics event.
- ms::LatLon const ll = info.GetLatLon();
- double myLat, myLon;
+ auto const ll = info.GetLatLon();
double metersToTap = -1;
if (info.IsMyPosition())
+ {
metersToTap = 0;
- else if (GetCurrentPosition(myLat, myLon))
- metersToTap = ms::DistanceOnEarth(myLat, myLon, ll.lat, ll.lon);
+ }
+ else if (auto const position = GetCurrentPosition())
+ {
+ auto const tapPoint = MercatorBounds::FromLatLon(ll);
+ metersToTap = MercatorBounds::DistanceOnEarth(*position, tapPoint);
+ }
alohalytics::TStringMap kv = {{"longTap", tapInfo.m_isLong ? "1" : "0"},
{"title", info.GetTitle()},
@@ -2449,10 +2241,14 @@ void Framework::OnTapEvent(TapEvent const & tapEvent)
if (info.IsFeature())
kv["types"] = DebugPrint(info.GetTypes());
// Older version of statistics used "$GetUserMark" event.
- alohalytics::Stats::Instance().LogEvent("$SelectMapObject", kv, alohalytics::Location::FromLatLon(ll.lat, ll.lon));
+ alohalytics::Stats::Instance().LogEvent("$SelectMapObject", kv,
+ alohalytics::Location::FromLatLon(ll.lat, ll.lon));
if (info.GetSponsoredType() == SponsoredType::Booking)
- GetPlatform().GetMarketingService().SendMarketingEvent(marketing::kPlacepageHotelBook, {{"provider", "booking.com"}});
+ {
+ GetPlatform().GetMarketingService().SendMarketingEvent(marketing::kPlacepageHotelBook,
+ {{"provider", "booking.com"}});
+ }
}
SetPlacePageLocation(info);
@@ -3329,6 +3125,42 @@ ads::Engine const & Framework::GetAdsEngine() const
return *m_adsEngine;
}
+void Framework::RunUITask(function<void()> fn) { GetPlatform().RunOnGuiThread(move(fn)); }
+
+void Framework::SetSearchDisplacementModeEnabled(bool enabled)
+{
+ SetDisplacementMode(DisplacementModeManager::SLOT_INTERACTIVE_SEARCH, enabled /* show */);
+}
+
+void Framework::ShowViewportSearchResults(search::Results const & results)
+{
+ FillSearchResultsMarks(results);
+}
+
+void Framework::ClearViewportSearchResults() { ClearSearchResultsMarks(); }
+
+boost::optional<m2::PointD> Framework::GetCurrentPosition() const
+{
+ m2::PointD position;
+ MyPositionMarkPoint * myPosMark = UserMarkContainer::UserMarkForMyPostion();
+ if (!myPosMark->HasPosition())
+ return {};
+
+ position = myPosMark->GetPivot();
+ return position;
+}
+
+bool Framework::ParseMagicSearchQuery(search::SearchParams const & params)
+{
+ if (ParseDrapeDebugCommand(params.m_query))
+ return true;
+ if (ParseSetGpsTrackMinAccuracyCommand(params.m_query))
+ return true;
+ if (ParseEditorDebugCommand(params))
+ return true;
+ return false;
+}
+
bool Framework::IsLocalAdsCustomer(search::Result const & result) const
{
if (result.IsSuggest())
@@ -3338,6 +3170,11 @@ bool Framework::IsLocalAdsCustomer(search::Result const & result) const
return m_localAdsManager.Contains(result.GetFeatureID());
}
+double Framework::GetMinDistanceBetweenResults() const
+{
+ return m_searchMarks.GetMaxDimension(m_currentModelView);
+}
+
vector<MwmSet::MwmId> Framework::GetMwmsByRect(m2::RectD const & rect, bool rough) const
{
vector<MwmSet::MwmId> result;
diff --git a/map/framework.hpp b/map/framework.hpp
index 5546a1012c..eca64cd6fe 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -10,6 +10,7 @@
#include "map/place_page_info.hpp"
#include "map/routing_manager.hpp"
#include "map/routing_mark.hpp"
+#include "map/search_api.hpp"
#include "map/search_mark.hpp"
#include "map/track.hpp"
#include "map/traffic_manager.hpp"
@@ -33,13 +34,9 @@
#include "search/city_finder.hpp"
#include "search/displayed_categories.hpp"
-#include "search/downloader_search_callback.hpp"
-#include "search/engine.hpp"
-#include "search/everywhere_search_callback.hpp"
#include "search/mode.hpp"
#include "search/query_saver.hpp"
#include "search/result.hpp"
-#include "search/viewport_search_callback.hpp"
#include "storage/downloading_policy.hpp"
#include "storage/storage.hpp"
@@ -75,7 +72,8 @@
#include "std/target_os.hpp"
#include "std/unique_ptr.hpp"
#include "std/vector.hpp"
-#include "std/weak_ptr.hpp"
+
+#include "boost/optional.hpp"
namespace osm
{
@@ -122,10 +120,7 @@ struct FrameworkParams
{}
};
-class Framework : public search::ViewportSearchCallback::Delegate,
- public search::DownloaderSearchCallback::Delegate,
- public search::EverywhereSearchCallback::Delegate,
- public RoutingManager::Delegate
+class Framework : public SearchAPI::Delegate, public RoutingManager::Delegate
{
DISALLOW_COPY(Framework);
@@ -166,7 +161,7 @@ protected:
unique_ptr<ugc::Api> m_ugcApi;
- unique_ptr<search::Engine> m_searchEngine;
+ unique_ptr<SearchAPI> m_searchAPI;
search::QuerySaver m_searchQuerySaver;
@@ -304,8 +299,8 @@ public:
Index const & GetIndex() const { return m_model.GetIndex(); }
- search::Engine & GetSearchEngine() { return *m_searchEngine; }
- search::Engine const & GetSearchEngine() const { return *m_searchEngine; }
+ SearchAPI & GetSearchAPI();
+ SearchAPI const & GetSearchAPI() const;
/// @name Bookmarks, Tracks and other UserMarks
//@{
@@ -346,29 +341,16 @@ public:
ads::Engine const & GetAdsEngine() const;
-protected:
- // search::ViewportSearchCallback::Delegate overrides:
- void RunUITask(function<void()> fn) override { GetPlatform().RunOnGuiThread(move(fn)); }
-
- void SetHotelDisplacementMode() override
- {
- SetDisplacementMode(DisplacementModeManager::SLOT_INTERACTIVE_SEARCH, true /* show */);
- }
-
- bool IsViewportSearchActive() const override
- {
- return !m_searchIntents[static_cast<size_t>(search::Mode::Viewport)].m_params.m_query.empty();
- }
-
- void ShowViewportSearchResults(search::Results const & results) override
- {
- FillSearchResultsMarks(results);
- }
-
- void ClearViewportSearchResults() override { ClearSearchResultsMarks(); }
-
- // EverywhereSearchCallback::Delegate overrides:
+public:
+ // SearchAPI::Delegate overrides:
+ void RunUITask(function<void()> fn) override;
+ void SetSearchDisplacementModeEnabled(bool enabled) override;
+ void ShowViewportSearchResults(search::Results const & results) override;
+ void ClearViewportSearchResults() override;
+ boost::optional<m2::PointD> GetCurrentPosition() const override;
+ bool ParseMagicSearchQuery(search::SearchParams const & params) override;
bool IsLocalAdsCustomer(search::Result const & result) const override;
+ double GetMinDistanceBetweenResults() const override;
private:
void ActivateMapSelection(bool needAnimation,
@@ -515,40 +497,19 @@ public:
void SetDisplacementMode(DisplacementModeManager::Slot slot, bool show);
private:
- struct SearchIntent
- {
- search::SearchParams m_params;
- weak_ptr<search::ProcessorHandle> m_handle;
- bool m_isDelayed = false;
- };
-
void InitCountryInfoGetter();
void InitUGC();
- void InitSearchEngine();
+ void InitSearchAPI();
DisplacementModeManager m_displacementModeManager;
bool m_connectToGpsTrack; // need to connect to tracker when Drape is being constructed
- void SetCurrentPositionIfPossible(search::SearchParams & params);
-
void OnUpdateCurrentCountry(m2::PointF const & pt, int zoomLevel);
storage::TCountryId m_lastReportedCountry;
TCurrentCountryChanged m_currentCountryChanged;
- // Descriptions of last search queries for different modes. May be
- // used for search requests skipping. This field is not guarded
- // because it must be used from the UI thread only.
- SearchIntent m_searchIntents[static_cast<size_t>(search::Mode::Count)];
-
- bool Search(search::SearchParams const & params, bool forceSearch);
- void Search(SearchIntent & intent) const;
-
- // Returns true when |params| is almost the same as the latest
- // search query params in |intent|.
- bool QueryMayBeSkipped(SearchIntent const & intent, search::SearchParams const & params) const;
-
void OnUpdateGpsTrackPointsCallback(vector<pair<size_t, location::GpsTrackInfo>> && toAdd,
pair<size_t, size_t> const & toRemove);
@@ -570,13 +531,9 @@ public:
// Search for maps by countries or cities.
bool SearchInDownloader(storage::DownloaderSearchParams const & params);
- void SetViewportIfPossible(search::SearchParams & params);
-
void CancelSearch(search::Mode mode);
void CancelAllSearches();
- bool GetCurrentPosition(double & lat, double & lon) const;
-
// Moves viewport to the search result and taps on it.
void SelectSearchResult(search::Result const & res, bool animation);
@@ -846,9 +803,6 @@ private:
// taxi::Engine and, therefore, destroyed after taxi::Engine.
unique_ptr<taxi::Engine> m_taxiEngine;
- // TODO: delete me after Cian project is finished.
- bool m_cianSearchMode = false;
-
void InitCityFinder();
void InitTaxiEngine();
diff --git a/map/map.pro b/map/map.pro
index a5c113ac63..f5f06e90e0 100644
--- a/map/map.pro
+++ b/map/map.pro
@@ -34,6 +34,7 @@ HEADERS += \
reachable_by_taxi_checker.hpp \
routing_manager.hpp \
routing_mark.hpp \
+ search_api.hpp \
search_mark.hpp \
taxi_delegate.hpp \
track.hpp \
@@ -69,6 +70,7 @@ SOURCES += \
reachable_by_taxi_checker.cpp \
routing_manager.cpp \
routing_mark.cpp \
+ search_api.cpp \
search_mark.cpp \
taxi_delegate.cpp \
track.cpp \
diff --git a/map/search_api.cpp b/map/search_api.cpp
new file mode 100644
index 0000000000..714607c3e0
--- /dev/null
+++ b/map/search_api.cpp
@@ -0,0 +1,295 @@
+#include "map/search_api.hpp"
+
+#include "search/everywhere_search_params.hpp"
+#include "search/geometry_utils.hpp"
+#include "search/hotels_filter.hpp"
+#include "search/viewport_search_params.hpp"
+
+#include "storage/downloader_search_params.hpp"
+
+#include "platform/preferred_languages.hpp"
+
+#include "geometry/mercator.hpp"
+
+#include "base/string_utils.hpp"
+
+#include <vector>
+
+using namespace search;
+using namespace std;
+
+namespace
+{
+double const kDistEqualQueryMeters = 100.0;
+
+// Cancels search query by |handle|.
+void CancelQuery(weak_ptr<ProcessorHandle> & handle)
+{
+ if (auto queryHandle = handle.lock())
+ queryHandle->Cancel();
+ handle.reset();
+}
+
+bool IsCianMode(string query)
+{
+ strings::Trim(query);
+ strings::AsciiToLower(query);
+ return query == "cian";
+}
+} // namespace
+
+SearchAPI::SearchAPI(Index & index, storage::Storage const & storage,
+ storage::CountryInfoGetter const & infoGetter, Delegate & delegate)
+ : m_index(index)
+ , m_storage(storage)
+ , m_infoGetter(infoGetter)
+ , m_delegate(delegate)
+ , m_engine(m_index, GetDefaultCategories(), m_infoGetter,
+ Engine::Params(languages::GetCurrentOrig() /* locale */, 1 /* params.m_numThreads */))
+{
+}
+
+void SearchAPI::OnViewportChanged(m2::RectD const & viewport)
+{
+ m_viewport = viewport;
+
+ auto const forceSearchInViewport = !m_isViewportInitialized;
+ if (!m_isViewportInitialized)
+ {
+ m_isViewportInitialized = true;
+ for (size_t i = 0; i < static_cast<size_t>(Mode::Count); i++)
+ {
+ auto & intent = m_searchIntents[i];
+ // Viewport search will be triggered below, in PokeSearchInViewport().
+ if (!intent.m_isDelayed || static_cast<Mode>(i) == Mode::Viewport)
+ continue;
+ intent.m_params.m_viewport = m_viewport;
+ intent.m_params.m_position = m_delegate.GetCurrentPosition();
+ Search(intent);
+ }
+ }
+
+ PokeSearchInViewport(forceSearchInViewport);
+}
+
+bool SearchAPI::SearchEverywhere(EverywhereSearchParams const & params)
+{
+ SearchParams p;
+ p.m_query = params.m_query;
+ p.m_inputLocale = params.m_inputLocale;
+ p.m_mode = Mode::Everywhere;
+ p.m_position = m_delegate.GetCurrentPosition();
+ SetViewportIfPossible(p); // Search request will be delayed if viewport is not available.
+ p.m_maxNumResults = SearchParams::kDefaultNumResultsEverywhere;
+ p.m_suggestsEnabled = true;
+ p.m_needAddress = true;
+ p.m_needHighlighting = true;
+ p.m_hotelsFilter = params.m_hotelsFilter;
+ p.m_cianMode = IsCianMode(params.m_query);
+
+ p.m_onResults = EverywhereSearchCallback(
+ static_cast<EverywhereSearchCallback::Delegate &>(*this),
+ [this, params](Results const & results, vector<bool> const & isLocalAdsCustomer) {
+ if (params.m_onResults)
+ RunUITask([params, results, isLocalAdsCustomer]() {
+ params.m_onResults(results, isLocalAdsCustomer);
+ });
+ });
+
+ return Search(p, true /* forceSearch */);
+}
+
+bool SearchAPI::SearchInViewport(ViewportSearchParams const & params)
+{
+ // TODO: delete me after Cian project is finished.
+ m_cianSearchMode = IsCianMode(params.m_query);
+
+ SearchParams p;
+ p.m_query = params.m_query;
+ p.m_inputLocale = params.m_inputLocale;
+ p.m_position = m_delegate.GetCurrentPosition();
+ SetViewportIfPossible(p); // Search request will be delayed if viewport is not available.
+ p.m_maxNumResults = SearchParams::kDefaultNumResultsInViewport;
+ p.m_mode = Mode::Viewport;
+ p.m_suggestsEnabled = false;
+ p.m_needAddress = false;
+ p.m_needHighlighting = false;
+ p.m_hotelsFilter = params.m_hotelsFilter;
+ p.m_cianMode = m_cianSearchMode;
+
+ p.m_onStarted = [this, params]() {
+ if (params.m_onStarted)
+ RunUITask([params]() { params.m_onStarted(); });
+ };
+
+ p.m_onResults = ViewportSearchCallback(
+ static_cast<ViewportSearchCallback::Delegate &>(*this),
+ [this, params](Results const & results) {
+ if (results.IsEndMarker() && params.m_onCompleted)
+ RunUITask([params, results]() { params.m_onCompleted(results); });
+ });
+
+ return Search(p, false /* forceSearch */);
+}
+
+bool SearchAPI::SearchInDownloader(storage::DownloaderSearchParams const & params)
+{
+ SearchParams p;
+ p.m_query = params.m_query;
+ p.m_inputLocale = params.m_inputLocale;
+ p.m_position = m_delegate.GetCurrentPosition();
+ SetViewportIfPossible(p); // Search request will be delayed if viewport is not available.
+ p.m_maxNumResults = SearchParams::kDefaultNumResultsEverywhere;
+ p.m_mode = Mode::Downloader;
+ p.m_suggestsEnabled = false;
+ p.m_needAddress = false;
+ p.m_needHighlighting = false;
+
+ p.m_onResults = DownloaderSearchCallback(static_cast<DownloaderSearchCallback::Delegate &>(*this),
+ m_index, m_infoGetter, m_storage, params);
+
+ return Search(p, true /* forceSearch */);
+}
+
+void SearchAPI::PokeSearchInViewport(bool forceSearch)
+{
+ if (!m_isViewportInitialized || !IsViewportSearchActive())
+ return;
+
+ // Copy is intentional here, to skip possible duplicating requests.
+ auto params = m_searchIntents[static_cast<size_t>(Mode::Viewport)].m_params;
+ SetViewportIfPossible(params);
+ params.m_position = m_delegate.GetCurrentPosition();
+ Search(params, forceSearch);
+}
+
+void SearchAPI::CancelSearch(Mode mode)
+{
+ ASSERT_NOT_EQUAL(mode, Mode::Count, ());
+
+ if (mode == Mode::Viewport)
+ {
+ // TODO: delete me after Cian project is finished.
+ m_cianSearchMode = false;
+
+ m_delegate.ClearViewportSearchResults();
+ m_delegate.SetSearchDisplacementModeEnabled(false /* enabled */);
+ }
+
+ auto & intent = m_searchIntents[static_cast<size_t>(mode)];
+ intent.m_params.Clear();
+ CancelQuery(intent.m_handle);
+}
+
+void SearchAPI::CancelAllSearches()
+{
+ for (size_t i = 0; i < static_cast<size_t>(Mode::Count); ++i)
+ CancelSearch(static_cast<Mode>(i));
+}
+
+void SearchAPI::RunUITask(std::function<void()> fn) { return m_delegate.RunUITask(fn); }
+
+void SearchAPI::SetHotelDisplacementMode()
+{
+ return m_delegate.SetSearchDisplacementModeEnabled(true);
+}
+
+bool SearchAPI::IsViewportSearchActive() const
+{
+ return !m_searchIntents[static_cast<size_t>(Mode::Viewport)].m_params.m_query.empty();
+}
+
+void SearchAPI::ShowViewportSearchResults(Results const & results)
+{
+ return m_delegate.ShowViewportSearchResults(results);
+}
+
+void SearchAPI::ClearViewportSearchResults() { return m_delegate.ClearViewportSearchResults(); }
+
+bool SearchAPI::IsLocalAdsCustomer(Result const & result) const
+{
+ return m_delegate.IsLocalAdsCustomer(result);
+}
+
+bool SearchAPI::Search(SearchParams const & params, bool forceSearch)
+{
+ if (m_delegate.ParseMagicSearchQuery(params))
+ return false;
+
+ auto const mode = params.m_mode;
+ auto & intent = m_searchIntents[static_cast<size_t>(mode)];
+
+#ifdef FIXED_LOCATION
+ SearchParams currParams = params;
+ if (currParams.IsValidPosition())
+ {
+ // TODO (@y): fix this
+ m_fixedPos.GetLat(currParams.m_lat);
+ m_fixedPos.GetLon(rParams.m_lon);
+ }
+#else
+ SearchParams const & currParams = params;
+#endif
+
+ if (!forceSearch && QueryMayBeSkipped(intent.m_params, currParams))
+ return false;
+
+ intent.m_params = currParams;
+ // Cancels previous search request (if any) and initiates new search request.
+ CancelQuery(intent.m_handle);
+
+ intent.m_params.m_minDistanceOnMapBetweenResults = m_delegate.GetMinDistanceBetweenResults();
+
+ Search(intent);
+
+ return true;
+}
+
+void SearchAPI::Search(SearchIntent & intent)
+{
+ if (!m_isViewportInitialized)
+ {
+ intent.m_isDelayed = true;
+ return;
+ }
+
+ intent.m_handle = m_engine.Search(intent.m_params);
+ intent.m_isDelayed = false;
+}
+
+void SearchAPI::SetViewportIfPossible(SearchParams & params)
+{
+ if (m_isViewportInitialized)
+ params.m_viewport = m_viewport;
+}
+
+bool SearchAPI::QueryMayBeSkipped(SearchParams const & prevParams,
+ SearchParams const & currParams) const
+{
+ auto const & prevViewport = prevParams.m_viewport;
+ auto const & currViewport = currParams.m_viewport;
+
+ if (!prevParams.IsEqualCommon(currParams))
+ return false;
+
+ if (!prevViewport.IsValid() ||
+ !IsEqualMercator(prevViewport, currViewport, kDistEqualQueryMeters))
+ {
+ return false;
+ }
+
+ if (prevParams.m_position && currParams.m_position &&
+ MercatorBounds::DistanceOnEarth(*prevParams.m_position, *currParams.m_position) >
+ kDistEqualQueryMeters)
+ {
+ return false;
+ }
+
+ if (static_cast<bool>(prevParams.m_position) != static_cast<bool>(currParams.m_position))
+ return false;
+
+ if (!hotels_filter::Rule::IsIdentical(prevParams.m_hotelsFilter, currParams.m_hotelsFilter))
+ return false;
+
+ return true;
+}
diff --git a/map/search_api.hpp b/map/search_api.hpp
new file mode 100644
index 0000000000..5f438e1bf8
--- /dev/null
+++ b/map/search_api.hpp
@@ -0,0 +1,127 @@
+#pragma once
+
+#include "search/downloader_search_callback.hpp"
+#include "search/engine.hpp"
+#include "search/everywhere_search_callback.hpp"
+#include "search/mode.hpp"
+#include "search/result.hpp"
+#include "search/search_params.hpp"
+#include "search/viewport_search_callback.hpp"
+
+#include "geometry/point2d.hpp"
+#include "geometry/rect2d.hpp"
+
+#include <cstddef>
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <boost/optional.hpp>
+
+namespace search
+{
+struct EverywhereSearchParams;
+struct ViewportSearchParams;
+}
+
+namespace storage
+{
+class CountryInfoGetter;
+class Storage;
+struct DownloaderSearchParams;
+}
+
+class SearchAPI : public search::DownloaderSearchCallback::Delegate,
+ public search::EverywhereSearchCallback::Delegate,
+ public search::ViewportSearchCallback::Delegate
+{
+public:
+ struct Delegate
+ {
+ virtual ~Delegate() = default;
+
+ virtual void RunUITask(std::function<void()> /* fn */) {}
+ virtual void SetSearchDisplacementModeEnabled(bool /* enabled */) {}
+ virtual void ShowViewportSearchResults(search::Results const & /* results */) {}
+ virtual void ClearViewportSearchResults() {}
+
+ virtual boost::optional<m2::PointD> GetCurrentPosition() const { return {}; };
+ virtual bool ParseMagicSearchQuery(search::SearchParams const & /* params */) { return false; };
+ virtual double GetMinDistanceBetweenResults() const { return 0.0; };
+ virtual bool IsLocalAdsCustomer(search::Result const & /* result */) const { return false; }
+ };
+
+ SearchAPI(Index & index, storage::Storage const & storage,
+ storage::CountryInfoGetter const & infoGetter, Delegate & delegate);
+ virtual ~SearchAPI() = default;
+
+ void OnViewportChanged(m2::RectD const & viewport);
+
+ void LoadCitiesBoundaries() { m_engine.LoadCitiesBoundaries(); }
+
+ bool IsCianSearchMode() const { return m_cianSearchMode; }
+
+ // Search everywhere.
+ bool SearchEverywhere(search::EverywhereSearchParams const & params);
+
+ // Search in the viewport.
+ bool SearchInViewport(search::ViewportSearchParams const & params);
+
+ // Search for maps by countries or cities.
+ bool SearchInDownloader(storage::DownloaderSearchParams const & params);
+
+ search::Engine & GetEngine() { return m_engine; }
+ search::Engine const & GetEngine() const { return m_engine; }
+
+ // When search in viewport is active or delayed, restarts search in
+ // viewport. When |forceSearch| is false, request is skipped when it
+ // is similar to the previous request in the current
+ // search-in-viewport session.
+ void PokeSearchInViewport(bool forceSearch = true);
+
+ void CancelSearch(search::Mode mode);
+ void CancelAllSearches();
+ void ClearCaches() { return m_engine.ClearCaches(); }
+
+ // *SearchCallback::Delegate overrides:
+ void RunUITask(std::function<void()> fn) override;
+ void SetHotelDisplacementMode() override;
+ bool IsViewportSearchActive() const override;
+ void ShowViewportSearchResults(search::Results const & results) override;
+ void ClearViewportSearchResults() override;
+ bool IsLocalAdsCustomer(search::Result const & result) const override;
+
+private:
+ struct SearchIntent
+ {
+ search::SearchParams m_params;
+ std::weak_ptr<search::ProcessorHandle> m_handle;
+ bool m_isDelayed = false;
+ };
+
+ bool Search(search::SearchParams const & params, bool forceSearch);
+ void Search(SearchIntent & intent);
+
+ void SetViewportIfPossible(search::SearchParams & params);
+
+ bool QueryMayBeSkipped(search::SearchParams const & prevParams,
+ search::SearchParams const & currParams) const;
+
+ Index & m_index;
+ storage::Storage const & m_storage;
+ storage::CountryInfoGetter const & m_infoGetter;
+ Delegate & m_delegate;
+
+ search::Engine m_engine;
+
+ // Descriptions of last search queries for different modes. May be
+ // used for search requests skipping. This field is not guarded
+ // because it must be used from the UI thread only.
+ SearchIntent m_searchIntents[static_cast<size_t>(search::Mode::Count)];
+
+ m2::RectD m_viewport;
+ bool m_isViewportInitialized = false;
+
+ // TODO (@y, @m): delete me after Cian project is finished.
+ bool m_cianSearchMode = false;
+};
diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp
index b42e848110..5db6bb0329 100644
--- a/qt/draw_widget.cpp
+++ b/qt/draw_widget.cpp
@@ -277,11 +277,12 @@ bool DrawWidget::Search(search::EverywhereSearchParams const & params)
string DrawWidget::GetDistance(search::Result const & res) const
{
string dist;
- double lat, lon;
- if (m_framework.GetCurrentPosition(lat, lon))
+ if (auto const position = m_framework.GetCurrentPosition())
{
+ auto const ll = MercatorBounds::ToLatLon(*position);
double dummy;
- (void) m_framework.GetDistanceAndAzimut(res.GetFeatureCenter(), lat, lon, -1.0, dist, dummy);
+ (void)m_framework.GetDistanceAndAzimut(res.GetFeatureCenter(), ll.lat, ll.lon, -1.0, dist,
+ dummy);
}
return dist;
}
diff --git a/search/search_quality/assessment_tool/main_model.cpp b/search/search_quality/assessment_tool/main_model.cpp
index b9c988841e..a4f3b30aa7 100644
--- a/search/search_quality/assessment_tool/main_model.cpp
+++ b/search/search_quality/assessment_tool/main_model.cpp
@@ -136,7 +136,7 @@ void MainModel::OnSampleSelected(int index)
return;
}
- auto & engine = m_framework.GetSearchEngine();
+ auto & engine = m_framework.GetSearchAPI().GetEngine();
{
search::SearchParams params;
sample.FillSearchParams(params);