From 9338907ae8f945fcdea04ce9d4dd958c2e7f7345 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Wed, 20 Jan 2016 12:58:43 +0300 Subject: [PATCH] Don not save feature if it wasn't edited. --- coding/multilang_utf8_string.hpp | 5 +++ indexer/feature.hpp | 2 + indexer/feature_data.cpp | 11 ++++++ indexer/feature_data.hpp | 5 +++ indexer/feature_meta.hpp | 10 +++++ indexer/osm_editor.cpp | 67 ++++++++++++++++++++++++++++---- indexer/osm_editor.hpp | 3 ++ 7 files changed, 96 insertions(+), 7 deletions(-) diff --git a/coding/multilang_utf8_string.hpp b/coding/multilang_utf8_string.hpp index 7fe6f8ff3e..fa8c1216d9 100644 --- a/coding/multilang_utf8_string.hpp +++ b/coding/multilang_utf8_string.hpp @@ -52,6 +52,11 @@ public: return (m_s == rhs.m_s); } + inline bool operator!= (StringUtf8Multilang const & rhs) const + { + return !(*this == rhs); + } + inline void Clear() { m_s.clear(); } inline bool IsEmpty() const { return m_s.empty(); } diff --git a/indexer/feature.hpp b/indexer/feature.hpp index be53c9e7ac..0a4486b779 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -81,6 +81,8 @@ public: }; */ + inline StringUtf8Multilang const & GetNames() const { return m_params.name; } + template inline bool ForEachName(T && fn) const { diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp index f3c9e025b9..bdf3e7a329 100644 --- a/indexer/feature_data.cpp +++ b/indexer/feature_data.cpp @@ -7,6 +7,7 @@ #include "base/stl_add.hpp" #include "std/bind.hpp" +#include "std/set.hpp" using namespace feature; @@ -39,6 +40,16 @@ void TypesHolder::Remove(uint32_t t) (void) RemoveIf(EqualFunctor(t)); } +bool feature::operator==(TypesHolder const & a, TypesHolder const & b) +{ + return set(a.begin(), a.end()) == set(b.begin(), b.end()); +} + +bool feature::operator!=(TypesHolder const & a, TypesHolder const & b) +{ + return !(a == b); +} + namespace { diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index 3f2588b9ae..5db6a58c7a 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -102,18 +102,23 @@ namespace feature } return false; } + void Remove(uint32_t t); string DebugPrint() const; /// Sort types by it's specification (more detailed type goes first). void SortBySpec(); + + friend bool operator==(TypesHolder const & a, TypesHolder const & b); + friend bool operator!=(TypesHolder const & a, TypesHolder const & b); }; inline string DebugPrint(TypesHolder const & t) { return t.DebugPrint(); } + uint8_t CalculateHeader(uint32_t const typesCount, uint8_t const headerGeomType, FeatureParamsBase const & params); } diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp index b626a435ca..b0e2581fd4 100644 --- a/indexer/feature_meta.hpp +++ b/indexer/feature_meta.hpp @@ -77,6 +77,16 @@ public: } } + inline friend bool operator==(MetadataBase const & a, MetadataBase const & b) + { + return a.m_metadata == b.m_metadata; + } + + inline friend bool operator!=(MetadataBase const & a, MetadataBase const & b) + { + return !(a == b); + } + protected: map m_metadata; }; diff --git a/indexer/osm_editor.cpp b/indexer/osm_editor.cpp index 647a4331e9..c2b8c812a4 100644 --- a/indexer/osm_editor.cpp +++ b/indexer/osm_editor.cpp @@ -18,6 +18,7 @@ #include "base/logging.hpp" #include "base/string_utils.hpp" +#include "std/algorithm.hpp" #include "std/chrono.hpp" #include "std/future.hpp" #include "std/tuple.hpp" @@ -206,6 +207,25 @@ uint32_t MigrateFeatureIndex(XMLFeature const & /*xml*/) return 0; } +bool AreFeaturesEqualButStreat(FeatureType const & a, FeatureType const & b) +{ + feature::TypesHolder const aTypes(a); + feature::TypesHolder const bTypes(b); + + if (aTypes != bTypes) + return false; + + if (a.GetHouseNumber() != b.GetHouseNumber()) + return false; + + if (a.GetMetadata() != b.GetMetadata()) + return false; + + if (a.GetNames() != b.GetNames()) + return false; + + return true; +} } // namespace namespace osm @@ -313,9 +333,11 @@ void Editor::LoadMapEdits() void Editor::Save(string const & fullFilePath) const { - // Should we delete edits file if user has canceled all changes? if (m_features.empty()) + { + my::DeleteFileX(GetEditorFilePath()); return; + } xml_document doc; xml_node root = doc.append_child(kXmlRootNode); @@ -395,8 +417,7 @@ void Editor::DeleteFeature(FeatureType const & feature) // TODO(AlexZ): Synchronize Save call/make it on a separate thread. Save(GetEditorFilePath()); - if (m_invalidateFn) - m_invalidateFn(); + Invalidate(); } //namespace @@ -412,9 +433,10 @@ void Editor::DeleteFeature(FeatureType const & feature) void Editor::EditFeature(FeatureType const & editedFeature, string const & editedStreet, string const & editedHouseNumber) { - // TODO(AlexZ): Check if feature has not changed and reset status. FeatureID const fid = editedFeature.GetID(); + auto const originalFeaturePtr = m_featureLoaderFn(fid); FeatureTypeInfo & fti = m_features[fid.m_mwmId][fid.m_index]; + fti.m_status = FeatureStatus::Modified; fti.m_feature = editedFeature; // TODO: What if local client time is absolutely wrong? @@ -425,11 +447,23 @@ void Editor::EditFeature(FeatureType const & editedFeature, string const & edite fti.m_feature.SetHouseNumber(editedHouseNumber); // TODO(AlexZ): Store edited house number as house name if feature::IsHouseNumber() returned false. + if (AreFeaturesEqualButStreat(fti.m_feature, *originalFeaturePtr) + // TODO(mgsergio): Handle street as well. + ) + { + // We always have a feature with fid.m_mwmId, fid.m_index at the point. + // Either it was set previously or just now on quering m_features. See code above. + RemoveFeatureFromStorage(fid.m_mwmId, fid.m_index); + // TODO(AlexZ): Synchronize Save call/make it on a separate thread. + Save(GetEditorFilePath()); + Invalidate(); + + return; + } + // TODO(AlexZ): Synchronize Save call/make it on a separate thread. Save(GetEditorFilePath()); - - if (m_invalidateFn) - m_invalidateFn(); + Invalidate(); } void Editor::ForEachFeatureInMwmRectAndScale(MwmSet::MwmId const & id, @@ -636,4 +670,23 @@ void Editor::UploadChanges(string const & key, string const & secret, TChangeset future = async(launch::async, lambda, key, secret, tags); } +void Editor::RemoveFeatureFromStorage(MwmSet::MwmId const & mwmId, uint32_t index) +{ + auto mwmMatched = m_features.find(mwmId); + if (mwmMatched == m_features.end()) + return; + + auto matchedIndex = mwmMatched->second.find(index); + if (matchedIndex != mwmMatched->second.end()) + mwmMatched->second.erase(matchedIndex); + + if (mwmMatched->second.empty()) + m_features.erase(mwmMatched); +} + +void Editor::Invalidate() +{ + if (m_invalidateFn) + m_invalidateFn(); +} } // namespace osm diff --git a/indexer/osm_editor.hpp b/indexer/osm_editor.hpp index a0f22c4041..b83f6c0dd5 100644 --- a/indexer/osm_editor.hpp +++ b/indexer/osm_editor.hpp @@ -91,6 +91,9 @@ public: private: // TODO(AlexZ): Synchronize Save call/make it on a separate thread. void Save(string const & fullFilePath) const; + void RemoveFeatureFromStorage(MwmSet::MwmId const & mwmId, uint32_t index); + /// Notify framework that something has changed and should be redisplayed. + void Invalidate(); struct FeatureTypeInfo {