forked from organicmaps/organicmaps
Merge pull request #2882 from mgsergio/street-multilang-name
Street multilang name
This commit is contained in:
commit
0abe598452
5 changed files with 112 additions and 54 deletions
|
@ -322,15 +322,11 @@ Editor::FeatureStatus Editor::GetFeatureStatus(MwmSet::MwmId const & mwmId, uint
|
|||
if (m_features.empty())
|
||||
return FeatureStatus::Untouched;
|
||||
|
||||
auto const matchedMwm = m_features.find(mwmId);
|
||||
if (matchedMwm == m_features.end())
|
||||
auto const * featureInfo = GetFeatureTypeInfo(mwmId, index);
|
||||
if (featureInfo == nullptr)
|
||||
return FeatureStatus::Untouched;
|
||||
|
||||
auto const matchedIndex = matchedMwm->second.find(index);
|
||||
if (matchedIndex == matchedMwm->second.end())
|
||||
return FeatureStatus::Untouched;
|
||||
|
||||
return matchedIndex->second.m_status;
|
||||
return featureInfo->m_status;
|
||||
}
|
||||
|
||||
void Editor::DeleteFeature(FeatureType const & feature)
|
||||
|
@ -503,32 +499,21 @@ void Editor::ForEachFeatureInMwmRectAndScale(MwmSet::MwmId const & id,
|
|||
bool Editor::GetEditedFeature(MwmSet::MwmId const & mwmId, uint32_t index,
|
||||
FeatureType & outFeature) const
|
||||
{
|
||||
auto const matchedMwm = m_features.find(mwmId);
|
||||
if (matchedMwm == m_features.end())
|
||||
auto const * featureInfo = GetFeatureTypeInfo(mwmId, index);
|
||||
if (featureInfo == nullptr)
|
||||
return false;
|
||||
|
||||
auto const matchedIndex = matchedMwm->second.find(index);
|
||||
if (matchedIndex == matchedMwm->second.end())
|
||||
return false;
|
||||
|
||||
// TODO(AlexZ): Should we process deleted/created features as well?
|
||||
outFeature = matchedIndex->second.m_feature;
|
||||
outFeature = featureInfo->m_feature;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Editor::GetEditedFeatureStreet(FeatureID const & fid, string & outFeatureStreet) const
|
||||
{
|
||||
// TODO(AlexZ): Reuse common code or better make better getters/setters for edited features.
|
||||
auto const matchedMwm = m_features.find(fid.m_mwmId);
|
||||
if (matchedMwm == m_features.end())
|
||||
auto const * featureInfo = GetFeatureTypeInfo(fid.m_mwmId, fid.m_index);
|
||||
if (featureInfo == nullptr)
|
||||
return false;
|
||||
|
||||
auto const matchedIndex = matchedMwm->second.find(fid.m_index);
|
||||
if (matchedIndex == matchedMwm->second.end())
|
||||
return false;
|
||||
|
||||
// TODO(AlexZ): Should we process deleted/created features as well?
|
||||
outFeatureStreet = matchedIndex->second.m_street;
|
||||
outFeatureStreet = featureInfo->m_street;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -806,6 +791,36 @@ void Editor::SaveUploadedInformation(FeatureTypeInfo const & fromUploader)
|
|||
Save(GetEditorFilePath());
|
||||
}
|
||||
|
||||
// Macros is used to avoid code duplication.
|
||||
#define GET_FEATURE_TYPE_INFO_BODY \
|
||||
do \
|
||||
{ \
|
||||
/* TODO(mgsergio): machedMwm should be synchronized. */ \
|
||||
auto const matchedMwm = m_features.find(mwmId); \
|
||||
if (matchedMwm == m_features.end()) \
|
||||
return nullptr; \
|
||||
\
|
||||
auto const matchedIndex = matchedMwm->second.find(index); \
|
||||
if (matchedIndex == matchedMwm->second.end()) \
|
||||
return nullptr; \
|
||||
\
|
||||
/* TODO(AlexZ): Should we process deleted/created features as well?*/ \
|
||||
return &matchedIndex->second; \
|
||||
} while (false)
|
||||
|
||||
Editor::FeatureTypeInfo const * Editor::GetFeatureTypeInfo(MwmSet::MwmId const & mwmId,
|
||||
uint32_t index) const
|
||||
{
|
||||
GET_FEATURE_TYPE_INFO_BODY;
|
||||
}
|
||||
|
||||
Editor::FeatureTypeInfo * Editor::GetFeatureTypeInfo(MwmSet::MwmId const & mwmId, uint32_t index)
|
||||
{
|
||||
GET_FEATURE_TYPE_INFO_BODY;
|
||||
}
|
||||
|
||||
#undef GET_FEATURE_TYPE_INFO_BODY
|
||||
|
||||
void Editor::RemoveFeatureFromStorageIfExists(MwmSet::MwmId const & mwmId, uint32_t index)
|
||||
{
|
||||
auto matchedMwm = m_features.find(mwmId);
|
||||
|
|
|
@ -154,6 +154,9 @@ private:
|
|||
string m_uploadStatus;
|
||||
string m_uploadError;
|
||||
};
|
||||
/// @returns pointer to m_features[id][index] if exists, nullptr otherwise.
|
||||
FeatureTypeInfo const * GetFeatureTypeInfo(MwmSet::MwmId const & mwmId, uint32_t index) const;
|
||||
FeatureTypeInfo * GetFeatureTypeInfo(MwmSet::MwmId const & mwmId, uint32_t index);
|
||||
void SaveUploadedInformation(FeatureTypeInfo const & fromUploader);
|
||||
|
||||
// TODO(AlexZ): Synchronize multithread access.
|
||||
|
|
|
@ -2452,26 +2452,38 @@ bool Framework::ParseEditorDebugCommand(search::SearchParams const & params)
|
|||
|
||||
namespace
|
||||
{
|
||||
vector<osm::LocalizedStreet> FilterNearbyStreets(vector<search::ReverseGeocoder::Street> const & streets,
|
||||
string const & exactFeatureStreet = "")
|
||||
osm::LocalizedStreet LocalizeStreet(Index const & index, FeatureID const & fid)
|
||||
{
|
||||
osm::LocalizedStreet result;
|
||||
Index::FeaturesLoaderGuard g(index, fid.m_mwmId);
|
||||
FeatureType ft;
|
||||
g.GetFeatureByIndex(fid.m_index, ft);
|
||||
ft.GetPreferredNames(result.m_defaultName, result.m_localizedName);
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<osm::LocalizedStreet> TakeSomeStreetsAndLocalize(
|
||||
vector<search::ReverseGeocoder::Street> const & streets, Index const & index)
|
||||
|
||||
{
|
||||
vector<osm::LocalizedStreet> results;
|
||||
// Exact feature street always goes first in Editor UI street list.
|
||||
|
||||
// TODO: Push into result LocalizedStreet object with default and localized street name.
|
||||
if (!exactFeatureStreet.empty())
|
||||
results.push_back({exactFeatureStreet, ""});
|
||||
// Reasonable number of different nearby street names to display in UI.
|
||||
constexpr size_t kMaxNumberOfNearbyStreetsToDisplay = 8;
|
||||
for (auto const & street : streets)
|
||||
{
|
||||
osm::LocalizedStreet const st{street.m_name, ""};
|
||||
if (find(results.begin(), results.end(), st) == results.end())
|
||||
{
|
||||
results.push_back(st);
|
||||
if (results.size() >= kMaxNumberOfNearbyStreetsToDisplay)
|
||||
break;
|
||||
}
|
||||
auto const isDuplicate = find_if(begin(results), end(results),
|
||||
[&street](osm::LocalizedStreet const & s)
|
||||
{
|
||||
return s.m_defaultName == street.m_name;
|
||||
}) != results.end();
|
||||
if (isDuplicate)
|
||||
continue;
|
||||
|
||||
results.push_back(LocalizeStreet(index, street.m_id));
|
||||
if (results.size() >= kMaxNumberOfNearbyStreetsToDisplay)
|
||||
break;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -2488,8 +2500,9 @@ bool Framework::CreateMapObject(m2::PointD const & mercator, uint32_t const feat
|
|||
|
||||
search::ReverseGeocoder const coder(m_model.GetIndex());
|
||||
vector<search::ReverseGeocoder::Street> streets;
|
||||
|
||||
coder.GetNearbyStreets(mwmId, mercator, streets);
|
||||
emo.SetNearbyStreets(FilterNearbyStreets(streets));
|
||||
emo.SetNearbyStreets(TakeSomeStreetsAndLocalize(streets, m_model.GetIndex()));
|
||||
return osm::Editor::Instance().CreatePoint(featureType, mercator, mwmId, emo);
|
||||
}
|
||||
|
||||
|
@ -2505,31 +2518,56 @@ bool Framework::GetEditableMapObject(FeatureID const & fid, osm::EditableMapObje
|
|||
osm::Editor & editor = osm::Editor::Instance();
|
||||
emo.SetEditableProperties(editor.GetEditableProperties(ft));
|
||||
|
||||
// Get exact feature's street address (if any) from mwm,
|
||||
// together with all nearby streets.
|
||||
search::ReverseGeocoder const coder(m_model.GetIndex());
|
||||
auto const streets = coder.GetNearbyFeatureStreets(ft);
|
||||
auto const & streetsPool = streets.first;
|
||||
auto const & featureStreetIndex = streets.second;
|
||||
|
||||
string street;
|
||||
if (editor.GetEditedFeatureStreet(fid, street))
|
||||
bool const featureIsInEditor = editor.GetEditedFeatureStreet(fid, street);
|
||||
bool const featureHasStreetInMwm = featureStreetIndex < streetsPool.size();
|
||||
if (!featureIsInEditor && featureHasStreetInMwm)
|
||||
street = streetsPool[featureStreetIndex].m_name;
|
||||
|
||||
auto localizedStreets = TakeSomeStreetsAndLocalize(streetsPool, m_model.GetIndex());
|
||||
|
||||
if (!street.empty())
|
||||
{
|
||||
// Exact feature's street is taken directy from the Editor.
|
||||
// Fill only nearby streets.
|
||||
search::ReverseGeocoder const coder(m_model.GetIndex());
|
||||
vector<search::ReverseGeocoder::Street> streets;
|
||||
coder.GetNearbyStreets(fid.m_mwmId, feature::GetCenter(*feature), streets);
|
||||
emo.SetNearbyStreets(FilterNearbyStreets(streets, street));
|
||||
auto it = find_if(begin(streetsPool), end(streetsPool),
|
||||
[&street](search::ReverseGeocoder::Street const & s)
|
||||
{
|
||||
return s.m_name == street;
|
||||
});
|
||||
|
||||
if (it != end(streetsPool))
|
||||
{
|
||||
auto const localizedStreet = LocalizeStreet(m_model.GetIndex(), it->m_id);
|
||||
emo.SetStreet(localizedStreet);
|
||||
|
||||
// A street that a feature belongs to should alwas be in the first place in the list.
|
||||
auto localizedIt = find(begin(localizedStreets), end(localizedStreets), localizedStreet);
|
||||
if (localizedIt != end(localizedStreets))
|
||||
iter_swap(localizedIt, begin(localizedStreets));
|
||||
else
|
||||
localizedStreets.insert(begin(localizedStreets), localizedStreet);
|
||||
}
|
||||
else
|
||||
{
|
||||
emo.SetStreet({street, ""});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get exact feature's street address (if any) from mwm, together with all nearby streets.
|
||||
search::ReverseGeocoder const coder(m_model.GetIndex());
|
||||
auto const streets = coder.GetNearbyFeatureStreets(ft);
|
||||
if (streets.second < streets.first.size())
|
||||
street = streets.first[streets.second].m_name;
|
||||
emo.SetNearbyStreets(FilterNearbyStreets(streets.first, street));
|
||||
emo.SetStreet({});
|
||||
}
|
||||
//TODO: We have to set default and localized name if last one exists.
|
||||
emo.SetStreet({street, ""});
|
||||
|
||||
emo.SetNearbyStreets(move(localizedStreets));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
osm::Editor::SaveResult Framework::SaveEditedMapObject(osm::EditableMapObject const & emo)
|
||||
{
|
||||
if (!m_lastTapEvent)
|
||||
|
|
|
@ -87,6 +87,7 @@ EditorDialog::EditorDialog(QWidget * parent, osm::EditableMapObject & emo)
|
|||
nearbyStreets.insert(nearbyStreets.begin(), {});
|
||||
grid->addWidget(new QLabel(kStreetObjectName), row, 0);
|
||||
QComboBox * cmb = new QComboBox();
|
||||
cmb->setEditable(true);
|
||||
for (int i = 0; i < nearbyStreets.size(); ++i)
|
||||
{
|
||||
string street = nearbyStreets[i].m_defaultName;
|
||||
|
|
|
@ -82,7 +82,8 @@ public:
|
|||
void GetNearbyStreets(FeatureType & ft, vector<Street> & streets) const;
|
||||
//@}
|
||||
|
||||
/// @returns [a lot of] nearby feature's streets and feature's street index, if valid ( < vector.size()).
|
||||
/// @returns [a lot of] nearby feature's streets and an index of a feature's street.
|
||||
/// Returns a value greater than vector size when there are no Street the feature belongs to.
|
||||
/// @note returned vector can contain duplicated street segments.
|
||||
pair<vector<Street>, uint32_t> GetNearbyFeatureStreets(FeatureType & ft) const;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue