diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index d5ea7b38a7..f588a6c3ff 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -233,7 +233,7 @@ void DrapeEngine::UpdateUserMarks(UserMarksProvider * provider) auto removedIdCollection = make_unique_dp(); df::MarkGroupID lastGroupId = *dirtyGroupIds.begin(); - bool visibilityChanged = provider->IsGroupVisiblityChanged(lastGroupId); + bool visibilityChanged = provider->IsGroupVisibilityChanged(lastGroupId); bool groupIsVisible = provider->IsGroupVisible(lastGroupId); auto const HandleMark = [&]( @@ -248,7 +248,7 @@ void DrapeEngine::UpdateUserMarks(UserMarksProvider * provider) if (groupId != lastGroupId) { lastGroupId = groupId; - visibilityChanged = provider->IsGroupVisiblityChanged(groupId); + visibilityChanged = provider->IsGroupVisibilityChanged(groupId); groupIsVisible = provider->IsGroupVisible(groupId); } if (!visibilityChanged && groupIsVisible) @@ -273,7 +273,7 @@ void DrapeEngine::UpdateUserMarks(UserMarksProvider * provider) for (auto groupId : dirtyGroupIds) { auto & idCollection = *(dirtyMarkIds.emplace(groupId, make_unique_dp()).first->second); - visibilityChanged = provider->IsGroupVisiblityChanged(groupId); + visibilityChanged = provider->IsGroupVisibilityChanged(groupId); groupIsVisible = provider->IsGroupVisible(groupId); if (!groupIsVisible && !visibilityChanged) continue; diff --git a/drape_frontend/user_marks_global.hpp b/drape_frontend/user_marks_global.hpp index 3096c3d828..ca25fa982b 100644 --- a/drape_frontend/user_marks_global.hpp +++ b/drape_frontend/user_marks_global.hpp @@ -7,7 +7,7 @@ namespace df { using MarkID = uint32_t; using LineID = uint32_t; -using MarkGroupID = size_t; +using MarkGroupID = uint32_t; using MarkIDCollection = std::vector; using LineIDCollection = std::vector; using MarkIDSet = std::set; diff --git a/drape_frontend/user_marks_provider.hpp b/drape_frontend/user_marks_provider.hpp index fd35b62cc8..f661c8b2ec 100644 --- a/drape_frontend/user_marks_provider.hpp +++ b/drape_frontend/user_marks_provider.hpp @@ -103,7 +103,7 @@ public: virtual ~UserMarksProvider() {} virtual GroupIDSet const & GetDirtyGroupIds() const = 0; virtual bool IsGroupVisible(MarkGroupID groupID) const = 0; - virtual bool IsGroupVisiblityChanged(MarkGroupID groupID) const = 0; + virtual bool IsGroupVisibilityChanged(MarkGroupID groupID) const = 0; virtual MarkIDSet const & GetGroupPointIds(MarkGroupID groupID) const = 0; virtual LineIDSet const & GetGroupLineIds(MarkGroupID groupID) const = 0; virtual MarkIDSet const & GetCreatedMarkIds() const = 0; diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index a36b7ca9a7..b82c14089a 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -135,6 +135,7 @@ std::string const GenerateValidAndUniqueFilePathForKML(std::string const & fileN BookmarkManager::BookmarkManager(Callbacks && callbacks) : m_callbacks(std::move(callbacks)) + , m_changesTracker(*this) , m_needTeardown(false) , m_nextGroupID(UserMark::BOOKMARK) { @@ -170,10 +171,12 @@ UserMark const * BookmarkManager::GetUserMark(df::MarkID markID) const UserMark * BookmarkManager::GetUserMarkForEdit(df::MarkID markID) { auto it = m_userMarks.find(markID); - if (it == m_userMarks.end()) - return nullptr; - m_updatedMarks.insert(markID); - return it->second.get(); + if (it != m_userMarks.end()) + { + m_changesTracker.OnUpdateMark(markID); + return it->second.get(); + } + return nullptr; } void BookmarkManager::DeleteUserMark(df::MarkID markId) @@ -181,11 +184,7 @@ void BookmarkManager::DeleteUserMark(df::MarkID markId) auto it = m_userMarks.find(markId); auto const groupId = it->second->GetGroupId(); FindContainer(groupId)->DetachUserMark(markId); - auto const mit = m_createdMarks.find(markId); - if (mit != m_createdMarks.end()) - m_createdMarks.erase(mit); - else - m_removedMarks.insert(markId); + m_changesTracker.OnDeleteMark(markId); m_userMarks.erase(it); } @@ -225,11 +224,11 @@ Bookmark * BookmarkManager::GetBookmarkForEdit(df::MarkID markID) auto it = m_bookmarks.find(markID); if (it == m_bookmarks.end()) return nullptr; + auto const groupId = it->second->GetGroupId(); if (groupId) - { - m_updatedMarks.insert(markID); - } + m_changesTracker.OnUpdateMark(markID); + return it->second.get(); } @@ -251,11 +250,7 @@ void BookmarkManager::DeleteBookmark(df::MarkID bmId) auto const groupID = groupIt->second->GetGroupId(); if (groupID) { - auto const it = m_createdMarks.find(bmId); - if (it != m_createdMarks.end()) - m_createdMarks.erase(it); - else - m_removedMarks.insert(bmId); + m_changesTracker.OnDeleteMark(bmId); FindContainer(groupID)->DetachUserMark(bmId); } m_bookmarks.erase(groupIt); @@ -293,34 +288,26 @@ void BookmarkManager::DeleteTrack(df::LineID trackID) m_tracks.erase(it); } -void BookmarkManager::FindDirtyGroups() +void BookmarkManager::CollectDirtyGroups(df::GroupIDSet & dirtyGroups) { - m_dirtyGroups.clear(); for (auto const & group : m_userMarkLayers) { if (!group->IsDirty()) continue; auto const groupId = static_cast(group->GetType()); - m_dirtyGroups.insert(groupId); + dirtyGroups.insert(groupId); } for (auto const & group : m_categories) { if (!group.second->IsDirty()) continue; - m_dirtyGroups.insert(group.first); - } - for (auto const markId : m_updatedMarks) - { - auto const * mark = GetMark(markId); - if (mark->IsDirty()) - m_dirtyGroups.insert(mark->GetGroupId()); + dirtyGroups.insert(group.first); } } + void BookmarkManager::NotifyChanges(df::MarkGroupID) { - FindDirtyGroups(); - - if (m_dirtyGroups.empty()) + if (!m_changesTracker.CheckChanges()) return; df::DrapeEngineLockGuard lock(m_drapeEngine); @@ -329,16 +316,16 @@ void BookmarkManager::NotifyChanges(df::MarkGroupID) bool isBookmarks = false; auto engine = lock.Get(); - for (auto groupId : m_dirtyGroups) + for (auto groupId : m_changesTracker.GetDirtyGroupIds()) { - isBookmarks |= IsBookmark(groupId); + isBookmarks |= IsBookmarkCategory(groupId); auto * group = FindContainer(groupId); engine->ChangeVisibilityUserMarksGroup(groupId, group->IsVisible()); } - engine->UpdateUserMarks(this); + engine->UpdateUserMarks(&m_changesTracker); - for (auto groupId : m_dirtyGroups) + for (auto groupId : m_changesTracker.GetDirtyGroupIds()) { auto * group = FindContainer(groupId); if (group->GetUserMarks().empty() && group->GetUserLines().empty()) @@ -351,13 +338,10 @@ void BookmarkManager::NotifyChanges(df::MarkGroupID) if (isBookmarks) SendBookmarksChanges(); - for (auto const markId : m_updatedMarks) + for (auto const markId : m_changesTracker.GetUpdatedMarkIds()) GetMark(markId)->ResetChanges(); - m_dirtyGroups.clear(); - m_createdMarks.clear(); - m_removedMarks.clear(); - m_updatedMarks.clear(); + m_changesTracker.ResetChanges(); } df::MarkIDSet const & BookmarkManager::GetUserMarkIds(df::MarkGroupID groupID) const @@ -375,12 +359,8 @@ void BookmarkManager::ClearGroup(df::MarkGroupID groupId) auto * group = FindContainer(groupId); for (auto markId : group->GetUserMarks()) { - auto const it = m_createdMarks.find(markId); - if (it == m_createdMarks.end()) - m_removedMarks.insert(markId); - else - m_createdMarks.erase(it); - if (IsBookmark(groupId)) + m_changesTracker.OnDeleteMark(markId); + if (IsBookmarkCategory(groupId)) m_bookmarks.erase(markId); else m_userMarks.erase(markId); @@ -409,10 +389,10 @@ UserMark const * BookmarkManager::FindMarkInRect(df::MarkGroupID groupID, m2::An { auto const * group = FindContainer(groupID); - UserMark const * mark = nullptr; + UserMark const * resMark = nullptr; if (group->IsVisible()) { - FindMarkFunctor f(&mark, d, rect); + FindMarkFunctor f(&resMark, d, rect); for (auto markId : group->GetUserMarks()) { auto const * mark = GetMark(markId); @@ -420,7 +400,7 @@ UserMark const * BookmarkManager::FindMarkInRect(df::MarkGroupID groupID, m2::An f(mark); } } - return mark; + return resMark; } void BookmarkManager::SetIsVisible(df::MarkGroupID groupId, bool visible) @@ -461,7 +441,7 @@ Bookmark * BookmarkManager::AddBookmark(std::unique_ptr && bookmark) auto const markId = bm->GetId(); ASSERT(m_bookmarks.count(markId) == 0, ()); m_bookmarks.emplace(markId, std::move(bookmark)); - m_createdMarks.insert(markId); + m_changesTracker.OnAddMark(markId); return bm; } @@ -690,7 +670,7 @@ void BookmarkManager::UpdateBookmark(df::MarkID bmID, BookmarkData const & bm) SaveState(); } -size_t BookmarkManager::LastEditedBMCategory() +df::MarkGroupID BookmarkManager::LastEditedBMCategory() { for (auto & cat : m_categories) { @@ -721,22 +701,25 @@ void BookmarkManager::SendBookmarksChanges() if (m_callbacks.m_createdBookmarksCallback != nullptr) { std::vector> marksInfo; - GetBookmarksData(m_createdMarks, marksInfo); + GetBookmarksData(m_changesTracker.GetCreatedMarkIds(), marksInfo); m_callbacks.m_createdBookmarksCallback(marksInfo); } if (m_callbacks.m_updatedBookmarksCallback != nullptr) { std::vector> marksInfo; - GetBookmarksData(m_updatedMarks, marksInfo); + GetBookmarksData(m_changesTracker.GetUpdatedMarkIds(), marksInfo); m_callbacks.m_updatedBookmarksCallback(marksInfo); } if (m_callbacks.m_deletedBookmarksCallback != nullptr) { df::MarkIDCollection idCollection; - idCollection.reserve(m_removedMarks.size()); - for (auto markId : m_removedMarks) + auto const & removedIds = m_changesTracker.GetRemovedMarkIds(); + idCollection.reserve(removedIds.size()); + for (auto markId : removedIds) + { if (IsBookmark(markId)) idCollection.push_back(markId); + } m_callbacks.m_deletedBookmarksCallback(idCollection); } } @@ -840,72 +823,18 @@ UserMarkContainer const * BookmarkManager::FindContainer(df::MarkGroupID contain { if (containerId < UserMark::Type::BOOKMARK) return m_userMarkLayers[containerId].get(); - else - { - ASSERT(m_categories.find(containerId) != m_categories.end(), ()); - return m_categories.at(containerId).get(); - } + + ASSERT(m_categories.find(containerId) != m_categories.end(), ()); + return m_categories.at(containerId).get(); } UserMarkContainer * BookmarkManager::FindContainer(df::MarkGroupID containerId) { if (containerId < UserMark::Type::BOOKMARK) return m_userMarkLayers[containerId].get(); - else - { - auto const it = m_categories.find(containerId); - return it != m_categories.end() ? it->second.get() : 0; - } -} -df::GroupIDSet const & BookmarkManager::GetDirtyGroupIds() const -{ - return m_dirtyGroups; -} - -bool BookmarkManager::IsGroupVisible(df::MarkGroupID groupID) const -{ - return IsVisible(groupID); -} - -bool BookmarkManager::IsGroupVisiblityChanged(df::MarkGroupID groupID) const -{ - return FindContainer(groupID)->IsVisibilityChanged(); -} - -df::MarkIDSet const & BookmarkManager::GetGroupPointIds(df::MarkGroupID groupId) const -{ - return GetUserMarkIds(groupId); -} - -df::LineIDSet const & BookmarkManager::GetGroupLineIds(df::MarkGroupID groupId) const -{ - return GetTrackIds(groupId); -} - -df::MarkIDSet const & BookmarkManager::GetCreatedMarkIds() const -{ - return m_createdMarks; -} - -df::MarkIDSet const & BookmarkManager::GetRemovedMarkIds() const -{ - return m_removedMarks; -} - -df::MarkIDSet const & BookmarkManager::GetUpdatedMarkIds() const -{ - return m_updatedMarks; -} - -df::UserPointMark const * BookmarkManager::GetUserPointMark(df::MarkID markID) const -{ - return GetMark(markID); -} - -df::UserLineMark const * BookmarkManager::GetUserLineMark(df::LineID lineID) const -{ - return GetTrack(lineID); + auto const it = m_categories.find(containerId); + return it != m_categories.end() ? it->second.get() : nullptr; } void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection) @@ -958,9 +887,6 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection) NotifyChanges(cat.first); } - - - namespace { char const * kmlHeader = @@ -1215,3 +1141,78 @@ bool BookmarkManager::SaveToKMLFile(df::MarkGroupID groupID) return false; } + +bool BookmarkManager::MarksChangesTracker::IsGroupVisible(df::MarkGroupID groupID) const +{ + return m_bmManager.IsVisible(groupID); +} + +bool BookmarkManager::MarksChangesTracker::IsGroupVisibilityChanged(df::MarkGroupID groupID) const +{ + return m_bmManager.FindContainer(groupID)->IsVisibilityChanged(); +} + +df::MarkIDSet const & BookmarkManager::MarksChangesTracker::GetGroupPointIds(df::MarkGroupID groupId) const +{ + return m_bmManager.GetUserMarkIds(groupId); +} + +df::LineIDSet const & BookmarkManager::MarksChangesTracker::GetGroupLineIds(df::MarkGroupID groupId) const +{ + return m_bmManager.GetTrackIds(groupId); +} + +df::UserPointMark const * BookmarkManager::MarksChangesTracker::GetUserPointMark(df::MarkID markID) const +{ + return m_bmManager.GetMark(markID); +} + +df::UserLineMark const * BookmarkManager::MarksChangesTracker::GetUserLineMark(df::LineID lineID) const +{ + return m_bmManager.GetTrack(lineID); +} + +void BookmarkManager::MarksChangesTracker::OnAddMark(df::MarkID markId) +{ + m_createdMarks.insert(markId); +} + +void BookmarkManager::MarksChangesTracker::OnDeleteMark(df::MarkID markId) +{ + auto const it = m_createdMarks.find(markId); + if (it != m_createdMarks.end()) + { + m_createdMarks.erase(it); + } + else + { + m_updatedMarks.erase(markId); + m_removedMarks.insert(markId); + } +} + +void BookmarkManager::MarksChangesTracker::OnUpdateMark(df::MarkID markId) +{ + if (m_createdMarks.find(markId) == m_createdMarks.end()) + m_updatedMarks.insert(markId); +} + +bool BookmarkManager::MarksChangesTracker::CheckChanges() +{ + m_bmManager.CollectDirtyGroups(m_dirtyGroups); + for (auto const markId : m_updatedMarks) + { + auto const * mark = m_bmManager.GetMark(markId); + if (mark->IsDirty()) + m_dirtyGroups.insert(mark->GetGroupId()); + } + return !m_dirtyGroups.empty(); +} + +void BookmarkManager::MarksChangesTracker::ResetChanges() +{ + m_dirtyGroups.clear(); + m_createdMarks.clear(); + m_removedMarks.clear(); + m_updatedMarks.clear(); +} diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index cecf1df56c..f8145979e7 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -20,7 +20,7 @@ #include -class BookmarkManager final : public df::UserMarksProvider +class BookmarkManager final { using CategoriesCollection = std::map>; using MarksCollection = std::map>; @@ -80,7 +80,7 @@ public: ASSERT(m_userMarks.count(markId) == 0, ()); ASSERT_LESS(groupId, m_userMarkLayers.size(), ()); m_userMarks.emplace(markId, std::move(mark)); - m_createdMarks.insert(markId); + m_changesTracker.OnAddMark(markId); m_userMarkLayers[groupId]->AttachUserMark(markId); return m; } @@ -200,25 +200,46 @@ public: bool IsAsyncLoadingInProgress() const { return m_asyncLoadingInProgress; } - // UserMarksProvider - df::GroupIDSet const & GetDirtyGroupIds() const override; - bool IsGroupVisible(df::MarkGroupID groupID) const override; - bool IsGroupVisiblityChanged(df::MarkGroupID groupID) const override; - df::MarkIDSet const & GetGroupPointIds(df::MarkGroupID groupId) const override; - df::LineIDSet const & GetGroupLineIds(df::MarkGroupID groupId) const override; - df::MarkIDSet const & GetCreatedMarkIds() const override; - df::MarkIDSet const & GetRemovedMarkIds() const override; - df::MarkIDSet const & GetUpdatedMarkIds() const override; - df::UserPointMark const * GetUserPointMark(df::MarkID markID) const override; - df::UserLineMark const * GetUserLineMark(df::LineID lineID) const override; - private: + class MarksChangesTracker : public df::UserMarksProvider + { + public: + MarksChangesTracker(BookmarkManager & bmManager) : m_bmManager(bmManager) {} + + void OnAddMark(df::MarkID markId); + void OnDeleteMark(df::MarkID markId); + void OnUpdateMark(df::MarkID markId); + + bool CheckChanges(); + void ResetChanges(); + + // UserMarksProvider + df::GroupIDSet const & GetDirtyGroupIds() const override { return m_dirtyGroups; } + df::MarkIDSet const & GetCreatedMarkIds() const override { return m_createdMarks; } + df::MarkIDSet const & GetRemovedMarkIds() const override { return m_removedMarks; } + df::MarkIDSet const & GetUpdatedMarkIds() const override { return m_updatedMarks; } + bool IsGroupVisible(df::MarkGroupID groupID) const override; + bool IsGroupVisibilityChanged(df::MarkGroupID groupID) const override; + df::MarkIDSet const & GetGroupPointIds(df::MarkGroupID groupId) const override; + df::LineIDSet const & GetGroupLineIds(df::MarkGroupID groupId) const override; + df::UserPointMark const * GetUserPointMark(df::MarkID markID) const override; + df::UserLineMark const * GetUserLineMark(df::LineID lineID) const override; + + private: + BookmarkManager & m_bmManager; + + df::MarkIDSet m_createdMarks; + df::MarkIDSet m_removedMarks; + df::MarkIDSet m_updatedMarks; + df::GroupIDSet m_dirtyGroups; + }; + using KMLDataCollection = std::vector>; - static bool IsBookmark(df::MarkGroupID groupId) { return groupId >= UserMark::BOOKMARK; } + static bool IsBookmarkCategory(df::MarkGroupID groupId) { return groupId >= UserMark::BOOKMARK; } static bool IsBookmark(df::MarkID markID) { return UserMark::GetMarkType(markID) == UserMark::BOOKMARK; } + UserMark const * GetMark(df::MarkID markID) const; - void FindDirtyGroups(); UserMarkContainer const * FindContainer(df::MarkGroupID containerId) const; UserMarkContainer * FindContainer(df::MarkGroupID containerId); @@ -236,12 +257,14 @@ private: void NotifyAboutFile(bool success, std::string const & filePath, bool isTemporaryFile); void LoadBookmarkRoutine(std::string const & filePath, bool isTemporaryFile); + void CollectDirtyGroups(df::GroupIDSet & dirtyGroups); + void SendBookmarksChanges(); void GetBookmarksData(df::MarkIDSet const & markIds, std::vector> & data) const; Callbacks m_callbacks; - + MarksChangesTracker m_changesTracker; df::DrapeEngineSafePtr m_drapeEngine; AsyncLoadingCallbacks m_asyncLoadingCallbacks; std::atomic m_needTeardown; @@ -252,7 +275,7 @@ private: CategoriesCollection m_categories; df::GroupIDList m_bmGroupsIdList; - df::GroupIDSet m_dirtyGroups; + std::string m_lastCategoryUrl; std::string m_lastType; UserMarkLayers m_userMarkLayers; @@ -260,9 +283,6 @@ private: MarksCollection m_userMarks; BookmarksCollection m_bookmarks; TracksCollection m_tracks; - df::MarkIDSet m_createdMarks; - df::MarkIDSet m_removedMarks; - df::MarkIDSet m_updatedMarks; StaticMarkPoint * m_selectionMark = nullptr; MyPositionMarkPoint * m_myPositionMark = nullptr;