From d18ff9ec8d9261b3bec3b272d20bbc5c71da48f6 Mon Sep 17 00:00:00 2001 From: leha-bot Date: Mon, 28 Jan 2019 02:02:58 +0300 Subject: [PATCH] history_location_manager: Introduce new classes for getting location tiles info This commit adds the helper interface ILocationMapTileHelper for getting info about current location (e.g. location URL or map tile image URL). This commit adds the following classes: 1. The interface ILocationMapTileHelper; 2. YandexMapsLocationTileHelper - uses Yandex.Maps Static API as backend for getting tile info; 3. GoogleMapsLocationTileHelper - uses Google Maps Statis API as backend; Please note that these classes aren't used yet, it will be used in next commit. Also please note that all virtual functions has been extracted from classes definitions to avoid the -WWeak-tables warning. (See Clang manual about this warning). --- .../history/history_location_manager.cpp | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/Telegram/SourceFiles/history/history_location_manager.cpp b/Telegram/SourceFiles/history/history_location_manager.cpp index f355f18e4..aeadd701c 100644 --- a/Telegram/SourceFiles/history/history_location_manager.cpp +++ b/Telegram/SourceFiles/history/history_location_manager.cpp @@ -38,6 +38,92 @@ constexpr auto kMaxHttpRedirects = 5; } // namespace +/// @brief Helper interface for getting location map tile and URL. +/// Used instead of hardcoded URLs. +class ILocationMapTileHelper { +public: + virtual QString locationUrl(const LocationCoords &loc) = 0; + /// @brief Returns image tile URL for requested location loc. + /// @param width Tile width, in px. + /// @param height Tile height, in px. + /// @param zoom The world map zoom. Usually varies from 1 to 16. + /// @param scale The map objects' scale for adopting map objects and + /// labels for HiDPI / Retina displays. + virtual QString locationTileImageUrl(const LocationCoords &loc, int width, int height, int zoom, int scale) = 0; + virtual ~ILocationMapTileHelper(); +}; + +// Note: this dtor has been extracted to avoid the inlining and triggering a +// warning related to Weak vtables. If this dtor will be inside the class +// definition, then compiler will have to place multiple copies of vtables +// which could increase binary size and could make ABI clashes. +ILocationMapTileHelper::~ILocationMapTileHelper() = default; + +/// @brief Yandex.Maps tile helper. Allows to use the Yandex.Maps as backend +/// for tile images and location URLs. +class YandexMapsLocationTileHelper : public ILocationMapTileHelper { +public: + QString locationUrl(const LocationCoords &loc) override; + + /// @param zoom World map zoom (from 0 to 17) + /// @see https://tech.yandex.ru/maps/doc/staticapi/1.x/dg/concepts/map_scale_docpage/ + QString locationTileImageUrl(const LocationCoords &loc, int width, int height, int zoom, int scale) override; +}; + +QString YandexMapsLocationTileHelper::locationUrl(const LocationCoords &loc) { + // Yandex.Maps accepts ll string in "longitude,latitude" format + auto latlon = loc.lonAsString() + "%2C" + loc.latAsString(); + return qsl("https://maps.yandex.ru/?ll=") + latlon + qsl("&z=16"); +} + +QString YandexMapsLocationTileHelper::locationTileImageUrl(const LocationCoords &loc, int width, int height, int zoom, + int scale) { + // Map marker and API endpoint constants. + // See https://tech.yandex.ru/maps/doc/staticapi/1.x/dg/concepts/input_params-docpage/ + // for API parameters reference. + const char *mapsApiUrl = "https://static-maps.yandex.ru/1.x/?ll="; + const char *mapsMarkerParams = ",pm2rdl"; // red large marker looking like "9" + // Tile image parameters format string + QString mapsApiParams = "&z=%1&size=%2,%3&l=map&scale=%4&pt="; + + // Yandex.Maps accepts ll string in "longitude,latitude" format + auto coords = loc.lonAsString() + ',' + loc.latAsString(); + + QString url = + mapsApiUrl + coords + mapsApiParams.arg(zoom).arg(width).arg(height).arg(scale) + coords + mapsMarkerParams; + + return url; +} + +/// @brief Uses Google Maps Static API. Adopted from old upstream code. +class GoogleMapsLocationTileHelper : public ILocationMapTileHelper { +public: + QString locationUrl(const LocationCoords &loc) override; + QString locationTileImageUrl(const LocationCoords &loc, int width, int height, int zoom, int scale) override; +}; + +QString GoogleMapsLocationTileHelper::locationUrl(const LocationCoords &loc) { + auto latlon = loc.latAsString() + ',' + loc.lonAsString(); + return qsl("https://maps.google.com/maps?q=") + latlon + qsl("&ll=") + latlon + qsl("&z=16"); +} + +QString GoogleMapsLocationTileHelper::locationTileImageUrl(const LocationCoords &loc, int width, int height, int zoom, + int scale) { + // Map marker, API options and endpoint constants. + const char *mapsApiUrl = "https://maps.googleapis.com/maps/api/staticmap?center="; + // additional marker params + const char *mapsMarkerParams = "&sensor=false"; + // API format string with basic marker params (red and big) + QString mapsApiParams = "&zoom=%1&size=%2,%3&maptype=roadmap&scale=%4&markers=color:red|size:big|"; + + // Google uses lat,lon in query URLs + auto coords = loc.latAsString() + ',' + loc.lonAsString(); + + QString url = + mapsApiUrl + coords + mapsApiParams.arg(zoom).arg(width).arg(height).arg(scale) + coords + mapsMarkerParams; + return url; +} + QString LocationClickHandler::copyToClipboardContextItemText() const { return lang(lng_context_copy_link); }