From 3ab1392d6f4883b9eb7ba733743699c53de0ae9d Mon Sep 17 00:00:00 2001 From: Roman Kuznetsov Date: Fri, 11 May 2018 10:53:43 +0300 Subject: [PATCH] Rescue of old-style hotel placemarks --- kml/serdes.cpp | 21 ++++++- kml/types.hpp | 2 + map/bookmark_manager.cpp | 120 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) diff --git a/kml/serdes.cpp b/kml/serdes.cpp index 27f2e645e5..836fd2a1ff 100644 --- a/kml/serdes.cpp +++ b/kml/serdes.cpp @@ -123,6 +123,17 @@ std::string GetStyleForPredefinedColor(PredefinedColor color) return {}; } } + +BookmarkIcon GetIcon(std::string const & iconName) +{ + for (size_t i = 0; i < static_cast(BookmarkIcon::Count); ++i) + { + auto const icon = static_cast(i); + if (iconName == DebugPrint(icon)) + return icon; + } + return BookmarkIcon::None; +} template uint32_t ToRGBA(Channel red, Channel green, Channel blue, Channel alpha) @@ -852,6 +863,13 @@ void KmlParser::CharData(std::string value) { // Bookmark draw style. m_predefinedColor = ExtractPlacemarkPredefinedColor(value); + + // Here we support old-style hotel placemarks. + if (value == "#placemark-hotel") + { + m_predefinedColor = PredefinedColor::Blue; + m_icon = BookmarkIcon::Hotel; + } // Track draw style. if (!GetColorForStyle(value, m_color)) @@ -930,8 +948,7 @@ void KmlParser::CharData(std::string value) } else if (currTag == "mwm:icon") { - //TODO: add new icon types. - //m_icon = ; + m_icon = GetIcon(value); } } else if (prevTag == "TimeStamp") diff --git a/kml/types.hpp b/kml/types.hpp index c74b6c5087..f625250c98 100644 --- a/kml/types.hpp +++ b/kml/types.hpp @@ -66,6 +66,7 @@ inline std::string DebugPrint(AccessRules accessRules) enum class BookmarkIcon : uint16_t { None = 0, + Hotel, Count }; @@ -75,6 +76,7 @@ inline std::string DebugPrint(BookmarkIcon icon) switch (icon) { case BookmarkIcon::None: return "None"; + case BookmarkIcon::Hotel: return "Hotel"; case BookmarkIcon::Count: return {}; } } diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 0b20cb546f..d15e9bf063 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -48,6 +48,7 @@ std::string const kLastEditedBookmarkCategory = "LastBookmarkCategory"; std::string const kLastBookmarkType = "LastBookmarkType"; std::string const kLastEditedBookmarkColor = "LastBookmarkColor"; std::string const kDefaultBookmarksFileName = "Bookmarks"; +std::string const kHotelsBookmarks = "Hotels"; std::string const kKmzExtension = ".kmz"; std::string const kKmlExtension = ".kml"; std::string const kKmbExtension = ".kmb"; @@ -377,6 +378,124 @@ bool MigrateIfNeeded() OnMigrationSuccess(files.size(), convertedCount); return true; } + +// Here we read backup and try to restore old-style #placemark-hotel bookmarks. +void FixUpHotelPlacemarks(BookmarkManager::KMLDataCollectionPtr & collection) +{ + static std::string const kSettingsKey = "HotelPlacemarksExtracted"; + bool isHotelPlacemarksExtracted; + if (settings::Get(kSettingsKey, isHotelPlacemarksExtracted) && isHotelPlacemarksExtracted) + return; + + if (!migration::IsMigrationCompleted()) + { + settings::Set(kSettingsKey, true); + return; + } + + // Find all hotel bookmarks in backup. + Platform::FilesList files; + Platform::GetFilesRecursively(GetBackupFolderName(), files); + std::vector> hotelBookmarks; + hotelBookmarks.reserve(100); + for (auto const & f : files) + { + if (GetFileExt(f) != kKmzExtension) + continue; + + ZipFileReader::FileListT filesInZip; + ZipFileReader::FilesList(f, filesInZip); + if (filesInZip.empty()) + continue; + + auto fileName = filesInZip.front().first; + for (auto const & fileInZip : filesInZip) + { + if (GetFileExt(fileInZip.first) == kKmlExtension) + { + fileName = fileInZip.first; + break; + } + } + std::string const unarchievedPath = my::JoinPath(GetPlatform().TmpDir(), fileName + ".raw"); + MY_SCOPE_GUARD(fileGuard, bind(&FileWriter::DeleteFileX, unarchievedPath)); + ZipFileReader::UnzipFile(f, fileName, unarchievedPath); + if (!GetPlatform().IsFileExistsByFullPath(unarchievedPath)) + continue; + + auto kmlData = LoadKmlFile(unarchievedPath, false /* binary */); + if (kmlData == nullptr) + continue; + + for (auto const & b : kmlData->m_bookmarksData) + { + if (b.m_icon == kml::BookmarkIcon::Hotel) + hotelBookmarks.emplace_back(b, false); + } + } + if (hotelBookmarks.empty()) + { + settings::Set(kSettingsKey, true); + return; + } + + if (!collection) + collection = std::make_shared(); + + if (collection->empty()) + { + auto fileData = std::make_unique(); + kml::SetDefaultStr(fileData->m_categoryData.m_name, kHotelsBookmarks); + fileData->m_bookmarksData.reserve(hotelBookmarks.size()); + for (auto & hb : hotelBookmarks) + fileData->m_bookmarksData.push_back(std::move(hb.first)); + collection->emplace_back("", std::move(fileData)); + settings::Set(kSettingsKey, true); + return; + } + + // Match found hotel bookmarks with existing bookmarks. + double constexpr kEps = 1e-5; + for (auto const & p : *collection) + { + CHECK(p.second, ()); + bool needSave = false; + for (auto & b : p.second->m_bookmarksData) + { + for (auto & hb : hotelBookmarks) + { + if (hb.second) + continue; + + if (b.m_point.EqualDxDy(hb.first.m_point, kEps)) + { + needSave = true; + hb.second = true; + b.m_color = hb.first.m_color; + b.m_icon = hb.first.m_icon; + } + } + } + if (needSave) + { + CHECK(!p.first.empty(), ()); + SaveKmlFile(*p.second, p.first, true /* useBinary */); + } + } + + // Add not-matched hotel bookmarks. + auto fileData = std::make_unique(); + kml::SetDefaultStr(fileData->m_categoryData.m_name, kHotelsBookmarks); + fileData->m_bookmarksData.reserve(hotelBookmarks.size()); + for (auto & hb : hotelBookmarks) + { + if (!hb.second) + fileData->m_bookmarksData.push_back(std::move(hb.first)); + } + if (!fileData->m_bookmarksData.empty()) + collection->emplace_back("", std::move(fileData)); + settings::Set(kSettingsKey, true); +} } // namespace migration using namespace std::placeholders; @@ -862,6 +981,7 @@ void BookmarkManager::LoadBookmarks() std::vector filePaths; auto collection = LoadBookmarks(dir, filesExt, migrated, filePaths); + migration::FixUpHotelPlacemarks(collection); if (m_needTeardown) return;