diff --git a/map/framework.cpp b/map/framework.cpp index 5cb8b2aecd..fd021276f6 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2,6 +2,7 @@ #include "draw_processor.hpp" #include "drawer_yg.hpp" #include "benchmark_provider.hpp" +#include "geourl_process.hpp" #include "../defines.hpp" @@ -861,7 +862,6 @@ void Framework::ScaleDefault(bool enlarge) void Framework::Scale(double scale) { m_navigator.Scale(scale); - //m_tiler.seed(m_navigator.Screen(), m_tileSize); Invalidate(); } @@ -1087,6 +1087,17 @@ string Framework::GetCountryCodeByPosition(double lat, double lon) const bool Framework::SetViewportByURL(string const & url) { - Invalidate(); - return true; + using namespace url_scheme; + + Info info; + ParseURL(url, info); + + if (info.IsValid()) + { + ShowRectFixed(info.GetViewport()); + Invalidate(); + return true; + } + + return false; } diff --git a/map/geourl_process.cpp b/map/geourl_process.cpp new file mode 100644 index 0000000000..f22f490a87 --- /dev/null +++ b/map/geourl_process.cpp @@ -0,0 +1,104 @@ +#include "geourl_process.hpp" + +#include "../indexer/scales.hpp" +#include "../indexer/mercator.hpp" + +#include "../base/string_utils.hpp" + + +namespace url_scheme +{ + void Info::Reset() + { + m_lat = m_lon = EmptyValue(); + m_zoom = scales::GetUpperScale(); + } + + m2::RectD Info::GetViewport() const + { + ASSERT ( IsValid(), () ); + + return scales::GetRectForLevel(m_zoom, + m2::PointD(MercatorBounds::LonToX(m_lon), + MercatorBounds::LatToY(m_lat)), + 1.0); + } + + + class DoParse + { + Info & m_info; + + enum TMode { START, LAT, LON, ZOOM, FINISH }; + TMode m_mode; + + static void ToDouble(string const & token, double & d) + { + double temp; + if (strings::to_double(token, temp)) + d = temp; + } + + bool CheckKeyword(string const & token) + { + if (token == "lat" || token == "point") + m_mode = LAT; + else if (token == "lon") + m_mode = LON; + else if (token == "zoom") + m_mode = ZOOM; + else + return false; + + return true; + } + + public: + DoParse(Info & info) : m_info(info), m_mode(START) + { + } + + void operator()(string const & token) + { + switch (m_mode) + { + case START: + ASSERT(token == "geo" || token == "mapswithme", (token)); + m_mode = LAT; + break; + + case LAT: + if (!CheckKeyword(token)) + { + ToDouble(token, m_info.m_lat); + m_mode = LON; + } + break; + + case LON: + if (!CheckKeyword(token)) + { + ToDouble(token, m_info.m_lon); + m_mode = ZOOM; + } + break; + + case ZOOM: + if (!CheckKeyword(token)) + { + ToDouble(token, m_info.m_zoom); + m_mode = FINISH; + } + break; + + default: + break; + } + } + }; + + void ParseURL(string const & s, Info & info) + { + strings::Tokenize(s, ":/?&=,", DoParse(info)); + } +} diff --git a/map/geourl_process.hpp b/map/geourl_process.hpp new file mode 100644 index 0000000000..edff95acdf --- /dev/null +++ b/map/geourl_process.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "../geometry/rect2d.hpp" + +#include "../std/string.hpp" + + +namespace url_scheme +{ + struct Info + { + double m_lat, m_lon, m_zoom; + + static double EmptyValue() { return -1000.0; } + + bool IsValid() const + { + return (m_lat != EmptyValue() && m_lon != EmptyValue()); + } + + void Reset(); + + Info() + { + Reset(); + } + + m2::RectD GetViewport() const; + }; + + void ParseURL(string const & s, Info & info); +} diff --git a/map/map.pro b/map/map.pro index 3eea9d5ce1..0bd3f335c4 100644 --- a/map/map.pro +++ b/map/map.pro @@ -48,7 +48,8 @@ HEADERS += \ basic_tiling_render_policy.hpp \ render_policy_mt.hpp \ bookmark.hpp \ - tile_set.hpp + tile_set.hpp \ + geourl_process.hpp \ SOURCES += \ feature_vec_model.cpp \ @@ -87,16 +88,11 @@ SOURCES += \ basic_tiling_render_policy.cpp \ render_policy_mt.cpp \ address_finder.cpp \ - tile_set.cpp + tile_set.cpp \ + geourl_process.cpp \ !iphone*:!bada*:!android* { HEADERS += qgl_render_context.hpp SOURCES += qgl_render_context.cpp QT += opengl } - - - - - - diff --git a/map/map_tests/geourl_test.cpp b/map/map_tests/geourl_test.cpp new file mode 100644 index 0000000000..d715e4cc16 --- /dev/null +++ b/map/map_tests/geourl_test.cpp @@ -0,0 +1,31 @@ +#include "../../testing/testing.hpp" + +#include "../geourl_process.hpp" + +using namespace url_scheme; + +UNIT_TEST(ProcessURL_Smoke) +{ + Info info; + ParseURL("geo:53.666,27.666", info); + TEST(info.IsValid(), ()); + TEST_ALMOST_EQUAL(info.m_lat, 53.666, ()); + TEST_ALMOST_EQUAL(info.m_lon, 27.666, ()); + + info.Reset(); + ParseURL("mapswithme:53.666,27.666", info); + TEST(info.IsValid(), ()); + TEST_ALMOST_EQUAL(info.m_lat, 53.666, ()); + TEST_ALMOST_EQUAL(info.m_lon, 27.666, ()); + + info.Reset(); + ParseURL("mapswithme://point/?lon=27.666&lat=53.666&zoom=10", info); + TEST(info.IsValid(), ()); + TEST_ALMOST_EQUAL(info.m_lat, 53.666, ()); + TEST_ALMOST_EQUAL(info.m_lon, 27.666, ()); + TEST_ALMOST_EQUAL(info.m_zoom, 10.0, ()); + + info.Reset(); + ParseURL("geo:53.666", info); + TEST(!info.IsValid(), ()); +} diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index 9f9ec14400..c3ed7dcc1a 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -25,3 +25,4 @@ SOURCES += \ draw_processor_test.cpp \ multithread_map_test.cpp \ bookmarks_test.cpp \ + geourl_test.cpp \