From 85a41c0e84e371f8f71947e798950c08caad2444 Mon Sep 17 00:00:00 2001 From: Anatoliy Tomilov Date: Wed, 14 Oct 2020 20:29:00 +0500 Subject: [PATCH] [bookmarks] Track visibility of bookmarks, that belong to any number of compilations MAPSME-14915 --- .../maps/bookmarks/data/BookmarkManager.cpp | 9 ++ .../maps/bookmarks/data/BookmarkManager.java | 15 +++ map/bookmark.cpp | 6 + map/bookmark.hpp | 11 +- map/bookmark_manager.cpp | 113 ++++++++++++++++-- map/bookmark_manager.hpp | 6 +- 6 files changed, 150 insertions(+), 10 deletions(-) diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp index e767cb497d..45469f0122 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp @@ -1013,6 +1013,15 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeSetAllCategoriesVi frm()->GetBookmarkManager().SetAllCategoriesVisibility(filter, static_cast(visible)); } +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeSetChildCategoriesVisibility( + JNIEnv * env, jobject thiz, jlong categoryId, jint compilationType, jboolean visible) +{ + frm()->GetBookmarkManager().SetChildCategoriesVisibility(categoryId, + static_cast(compilationType), + static_cast(visible)); +} + JNIEXPORT jint JNICALL Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetKmlFilesCountForConversion( JNIEnv * env, jobject thiz) diff --git a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java index 3fa2ce0294..328cd0d03a 100644 --- a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java +++ b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java @@ -64,6 +64,14 @@ public enum BookmarkManager public static final int SORT_BY_DISTANCE = 1; public static final int SORT_BY_TIME = 2; + @Retention(RetentionPolicy.SOURCE) + @IntDef({ CATEGORY, COLLECTION, DAY }) + public @interface CompilationType {} + + public static final int CATEGORY = 0; + public static final int COLLECTION = 1; + public static final int DAY = 2; + public static final List ICONS = new ArrayList<>(); @NonNull @@ -700,6 +708,11 @@ public enum BookmarkManager nativeSetAllCategoriesVisibility(visible, type.ordinal()); } + public void setChildCategoriesVisibility(long catId, @BookmarkManager.CompilationType int compilationType, boolean visible) + { + nativeSetChildCategoriesVisibility(catId, compilationType, visible); + } + public int getKmlFilesCountForConversion() { return nativeGetKmlFilesCountForConversion(); @@ -1110,6 +1123,8 @@ public enum BookmarkManager private static native boolean nativeAreAllCategoriesInvisible(int type); private static native void nativeSetAllCategoriesVisibility(boolean visible, int type); + + private static native void nativeSetChildCategoriesVisibility(long catId, int compilationType, boolean visible); private static native int nativeGetKmlFilesCountForConversion(); diff --git a/map/bookmark.cpp b/map/bookmark.cpp index 218b781a0d..ec8cc31f23 100644 --- a/map/bookmark.cpp +++ b/map/bookmark.cpp @@ -93,6 +93,12 @@ void Bookmark::SetAddress(search::ReverseGeocoder::RegionAddress const & address m_address = address; } +void Bookmark::SetIsVisible(bool isVisible) +{ + SetDirty(); + m_isVisible = isVisible; +} + dp::Anchor Bookmark::GetAnchor() const { return dp::Bottom; diff --git a/map/bookmark.hpp b/map/bookmark.hpp index fc2b88c194..eaf4e87ac7 100644 --- a/map/bookmark.hpp +++ b/map/bookmark.hpp @@ -25,6 +25,9 @@ public: search::ReverseGeocoder::RegionAddress const & GetAddress() const; void SetAddress(search::ReverseGeocoder::RegionAddress const & address); + bool IsVisible() const override { return m_isVisible; } + void SetIsVisible(bool isVisible); + bool HasCreationAnimation() const override; std::string GetPreferredName() const; @@ -64,12 +67,15 @@ public: void AttachCompilation(kml::MarkGroupId groupId); void Detach(); + kml::GroupIdCollection const & GetCompilations() const { return m_compilationIds; } + private: drape_ptr GetCustomSymbolNames() const; kml::BookmarkData m_data; kml::MarkGroupId m_groupId; kml::GroupIdCollection m_compilationIds; + bool m_isVisible = true; search::ReverseGeocoder::RegionAddress m_address; }; @@ -84,6 +90,8 @@ public: static kml::PredefinedColor GetDefaultColor(); kml::MarkGroupId GetID() const { return m_data.m_id; } + kml::MarkGroupId GetParentID() const { return m_parentId; } + void SetParentId(kml::MarkGroupId parentId) { m_parentId = parentId; } void SetIsVisible(bool isVisible) override; void SetName(std::string const & name); @@ -110,12 +118,13 @@ public: void SetTags(std::vector const & tags); void SetCustomProperty(std::string const & key, std::string const & value); -private: void SetDirty() override; +private: // Stores file name from which bookmarks were loaded. std::string m_file; bool m_autoSave = true; kml::CategoryData m_data; std::string m_serverId; + kml::MarkGroupId m_parentId = kml::kInvalidMarkGroupId; }; diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 9dda23187d..ba5e098be2 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -674,6 +674,13 @@ Bookmark * BookmarkManager::GetBookmarkForEdit(kml::MarkId markId) return it->second.get(); } +Bookmark * BookmarkManager::GetBookmarkForVisibilityChange(kml::MarkId markId) +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + auto it = m_bookmarks.find(markId); + return (it != m_bookmarks.end()) ? it->second.get() : nullptr; +} + void BookmarkManager::AttachBookmark(kml::MarkId bmId, kml::MarkGroupId catId) { CHECK_THREAD_CHECKER(m_threadChecker, ()); @@ -1386,8 +1393,10 @@ kml::GroupIdCollection BookmarkManager::GetCompilationOfType(kml::MarkGroupId pa std::copy_if(compilations.cbegin(), compilations.cend(), std::back_inserter(result), [this, type](auto const groupId) { - auto const & child = m_compilations.at(groupId); - return child->GetCategoryData().m_type == type; + auto const compilation = m_compilations.find(groupId); + ASSERT(compilation != m_compilations.end(), ()); + auto const & child = *compilation->second; + return child.GetCategoryData().m_type == type; }); return result; @@ -1962,6 +1971,12 @@ void BookmarkManager::SetIsVisible(kml::MarkGroupId groupId, bool visible) { CHECK_THREAD_CHECKER(m_threadChecker, ()); GetGroup(groupId)->SetIsVisible(visible); + if (visible) + { + auto const compilation = m_compilations.find(groupId); + if (compilation != m_compilations.end()) + GetGroup(compilation->second->GetParentID())->SetIsVisible(true); + } UpdateTrackMarksVisibility(groupId); } @@ -2977,6 +2992,12 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection, bool group->SetFileName(fileName); group->SetServerId(fileData.m_serverId); + for (auto const & [compilationId, compilation] : compilations) + { + UNUSED_VALUE(compilationId); + compilation->SetParentId(groupId); + } + // Restore sensitive info from the cache. auto const cacheIt = m_restoringCache.find(fileName); if (cacheIt != m_restoringCache.end() && @@ -3323,7 +3344,7 @@ bool BookmarkManager::AreAllCategoriesInvisible(CategoryFilterType const filter) return CheckVisibility(filter, false /* isVisible */); } -bool BookmarkManager::CheckVisibility(BookmarkManager::CategoryFilterType const filter, +bool BookmarkManager::CheckVisibility(CategoryFilterType const filter, bool isVisible) const { CHECK_THREAD_CHECKER(m_threadChecker, ()); @@ -3352,6 +3373,30 @@ void BookmarkManager::SetAllCategoriesVisibility(CategoryFilterType const filter } } +void BookmarkManager::SetChildCategoriesVisibility(kml::MarkGroupId categoryId, kml::CompilationType compilationType, + bool visible) +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + auto session = GetEditSession(); + auto const categoryIt = m_categories.find(categoryId); + CHECK(categoryIt != m_categories.end(), ()); + auto & category = *categoryIt->second; + kml::GroupIdCollection const & compilationIds = category.GetCategoryData().m_compilationIds; + for (kml::MarkGroupId const compilationId : compilationIds) + { + auto const compilationIt = m_compilations.find(compilationId); + CHECK(compilationIt != m_compilations.cend(), ()); + auto & compilation = *compilationIt->second; + if (compilation.GetCategoryData().m_type != compilationType) + continue; + if (visible) + category.SetIsVisible(true); + else if (compilation.IsVisible()) + category.SetDirty(); + compilation.SetIsVisible(visible); + } +} + bool BookmarkManager::CanConvert() const { // The conversion available only after successful migration. @@ -4038,6 +4083,55 @@ bool BookmarkManager::MarksChangesTracker::HasBookmarkCategories( return false; } +void BookmarkManager::MarksChangesTracker::InferBookmarksVisibility(BookmarkCategory * const group, + kml::MarkIdSet & dirtyMarks) +{ + kml::CategoryData const & categoryData = group->GetCategoryData(); + if (categoryData.m_compilationIds.empty()) + return; + std::unordered_set visibility; + visibility.reserve(categoryData.m_compilationIds.size()); + for (kml::MarkGroupId const compilationId : categoryData.m_compilationIds) + { + auto const compilation = m_bmManager->m_compilations.find(compilationId); + CHECK(compilation != m_bmManager->m_compilations.end(), ()); + if (compilation->second.get()->IsVisible()) + visibility.emplace(compilationId); + } + auto const groupId = group->GetID(); + bool hasUserMarksOrDanglingBookmarks = false; + for (kml::MarkId const userMark : m_bmManager->GetUserMarkIds(groupId)) + { + if (!m_bmManager->IsBookmark(userMark)) + { + hasUserMarksOrDanglingBookmarks = true; + continue; + } + Bookmark * const bookmark = m_bmManager->GetBookmarkForVisibilityChange(userMark); + if (bookmark->GetCompilations().empty()) + hasUserMarksOrDanglingBookmarks = true; + bool isVisible = false; + for (kml::MarkGroupId const compilationId : bookmark->GetCompilations()) + { + if (visibility.count(compilationId) != 0) + { + isVisible = true; + break; + } + } + if (isVisible != bookmark->IsVisible()) + { + dirtyMarks.insert(userMark); + bookmark->SetIsVisible(isVisible); + } + } + if (visibility.empty() && m_bmManager->GetTrackIds(groupId).empty() && + !hasUserMarksOrDanglingBookmarks) + { + group->SetIsVisible(false); + } +} + void BookmarkManager::MarksChangesTracker::OnAttachBookmark(kml::MarkId markId, kml::MarkGroupId catId) { @@ -4107,22 +4201,25 @@ void BookmarkManager::MarksChangesTracker::OnBecomeInvisibleGroup(kml::MarkGroup void BookmarkManager::MarksChangesTracker::AcceptDirtyItems() { + kml::MarkIdSet dirtyMarks; + CHECK(m_updatedGroups.empty(), ()); m_bmManager->GetDirtyGroups(m_updatedGroups); for (auto groupId : m_updatedGroups) { - auto group = m_bmManager->GetGroup(groupId); - if (group->IsVisibilityChanged()) + auto userMarkLayer = m_bmManager->GetGroup(groupId); + if (auto const group = dynamic_cast(userMarkLayer)) + InferBookmarksVisibility(group, dirtyMarks); + if (userMarkLayer->IsVisibilityChanged()) { - if (group->IsVisible()) + if (userMarkLayer->IsVisible()) m_becameVisibleGroups.insert(groupId); else m_becameInvisibleGroups.insert(groupId); } - group->ResetChanges(); + userMarkLayer->ResetChanges(); } - kml::MarkIdSet dirtyMarks; for (auto const markId : m_updatedMarks) { auto const mark = m_bmManager->GetMark(markId); diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index a383164495..d7aa29ab03 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -49,7 +49,6 @@ class BookmarkManager final { using UserMarkLayers = std::vector>; using CategoriesCollection = std::map>; - using MarksCollection = std::map>; using BookmarksCollection = std::map>; using TracksCollection = std::map>; @@ -372,6 +371,8 @@ public: bool AreAllCategoriesVisible(CategoryFilterType const filter) const; bool AreAllCategoriesInvisible(CategoryFilterType const filter) const; void SetAllCategoriesVisibility(CategoryFilterType const filter, bool visible); + void SetChildCategoriesVisibility(kml::MarkGroupId categoryId, kml::CompilationType compilationType, + bool visible); // Return number of files for the conversion to the binary format. size_t GetKmlFilesCountForConversion() const; @@ -573,6 +574,8 @@ private: GroupMarkIdSet & setToInsert, GroupMarkIdSet & setToErase); bool HasBookmarkCategories(kml::GroupIdSet const & groupIds) const; + void InferBookmarksVisibility(BookmarkCategory * const group, kml::MarkIdSet & dirtyMarks); + BookmarkManager * m_bmManager; kml::MarkIdSet m_createdMarks; @@ -641,6 +644,7 @@ private: Bookmark * CreateBookmark(kml::BookmarkData && bmData, kml::MarkGroupId groupId); Bookmark * GetBookmarkForEdit(kml::MarkId markId); + Bookmark * GetBookmarkForVisibilityChange(kml::MarkId markId); void AttachBookmark(kml::MarkId bmId, kml::MarkGroupId groupId); void DetachBookmark(kml::MarkId bmId, kml::MarkGroupId groupId); void DeleteBookmark(kml::MarkId bmId);