diff --git a/.github/workflows/linux-check.yaml b/.github/workflows/linux-check.yaml index 18cc9584ec..bc47cd7b39 100644 --- a/.github/workflows/linux-check.yaml +++ b/.github/workflows/linux-check.yaml @@ -54,10 +54,8 @@ jobs: sudo apt update -y sudo apt install -y \ ninja-build \ - libgl1-mesa-dev \ - libglvnd-dev \ - qt6-base-dev \ - libqt6svg6-dev + qtbase5-dev \ + libqt5svg5-dev - name: Configure shell: bash @@ -107,10 +105,8 @@ jobs: g++-12 \ gcc-12 \ ninja-build \ - libgl1-mesa-dev \ - libglvnd-dev \ - qt6-base-dev \ - libqt6svg6-dev + qtbase5-dev \ + libqt5svg5-dev - name: Configure shell: bash diff --git a/.github/workflows/macos-check.yaml b/.github/workflows/macos-check.yaml index 9fb137b210..cdc158389b 100644 --- a/.github/workflows/macos-check.yaml +++ b/.github/workflows/macos-check.yaml @@ -49,7 +49,7 @@ jobs: - name: Install build tools and dependencies shell: bash run: | - brew install ninja qt@6 + brew install ninja qt@5 - name: Configure shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 67608fc50c..34978954ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,10 +238,18 @@ if (NOT PLATFORM_IPHONE AND NOT PLATFORM_ANDROID) list(APPEND qt_components Widgets) endif() if (NOT SKIP_DESKTOP) - list(APPEND qt_components Gui Xml Svg OpenGL OpenGLWidgets) + list(APPEND qt_components Gui Xml Svg) + endif() + if (DEFINED ENV{HOMEBREW_PREFIX}) + set(HOMEBREW_PREFIX $ENV{HOMEBREW_PREFIX}) + else() + set(HOMEBREW_PREFIX /opt/homebrew) + endif() + # PATHS are hard-coded hints where to look for qt5 in addition to other places. + find_package(Qt5 COMPONENTS REQUIRED ${qt_components} PATHS $ENV{QT_PATH} ${HOMEBREW_PREFIX}/opt/qt@5 /usr/local/opt/qt@5 /usr/lib/x86_64-linux-gnu/qt5) + if (Qt5_VERSION VERSION_LESS 5.5.0) + message(FATAL_ERROR "Minimum supported Qt5 version is 5.5") endif() - # PATHS are hard-coded hints where to look for qt6 in addition to other places. - find_package(Qt6 COMPONENTS REQUIRED ${qt_components} PATHS $ENV{QT_PATH} /opt/homebrew/opt/qt@6 /usr/local/opt/qt@6 /usr/lib/x86_64-linux-gnu/qt6) endif() find_library(LIBZ NAMES z) diff --git a/android/src/app/organicmaps/intent/Factory.java b/android/src/app/organicmaps/intent/Factory.java index 5da9d96b59..824ee36198 100644 --- a/android/src/app/organicmaps/intent/Factory.java +++ b/android/src/app/organicmaps/intent/Factory.java @@ -202,13 +202,6 @@ public class Factory { final ParsingResult result = Framework.nativeParseAndSetApiUrl(getUrl()); - // TODO: Kernel recognizes "mapsme://", "mwm://" and "mapswithme://" schemas only!!! - if (result.getUrlType() == ParsingResult.TYPE_INCORRECT) - return Map.showMapForUrl(getUrl()); - - if (!result.isSuccess()) - return false; - final Uri uri = Uri.parse(getUrl()); final String backUrl = uri.getQueryParameter("backurl"); if (!TextUtils.isEmpty(backUrl)) @@ -218,6 +211,13 @@ public class Factory intent.putExtra(MwmActivity.EXTRA_BACK_URL, backUrl); } + // Kernel recognizes "om://", "mapsme://", "mwm://" and "mapswithme://" schemes only!!! + if (result.getUrlType() == ParsingResult.TYPE_INCORRECT) + return Map.showMapForUrl(getUrl()); + + if (!result.isSuccess()) + return false; + switch (result.getUrlType()) { case ParsingResult.TYPE_INCORRECT: diff --git a/cmake/OmimHelpers.cmake b/cmake/OmimHelpers.cmake index bc2f535c69..91af2e6f6b 100644 --- a/cmake/OmimHelpers.cmake +++ b/cmake/OmimHelpers.cmake @@ -114,7 +114,7 @@ endfunction() function(omim_add_test_with_qt_event_loop executable) omim_add_test_impl(NO ${executable} ${ARGN}) target_compile_definitions(${executable} PRIVATE OMIM_UNIT_TEST_WITH_QT_EVENT_LOOP) - target_link_libraries(${executable} Qt6::Widgets) + target_link_libraries(${executable} Qt5::Widgets) endfunction() function(omim_add_test_no_platform_init executable) diff --git a/docs/DEBUG_COMMANDS.md b/docs/DEBUG_COMMANDS.md index ae8d261505..d37d4ee060 100644 --- a/docs/DEBUG_COMMANDS.md +++ b/docs/DEBUG_COMMANDS.md @@ -27,13 +27,6 @@ For more information, please see the source code at [`Framework::ParseSearchQuer - `?isolines`: Enable the isolines layer. - `?no-isolines`: Disable the isolines layer. -### 3D mode (for the Qt desktop app only) -- `?3d`: Enable 3D (perspective) mode. -- `?b3d`: Enable 3D buildings. -- `?2d`: Disable 3D mode and buildings. - -The source code is at [`SearchPanel::Try3dModeCmd`](../qt/search_panel.cpp). - ### Information - `?debug-info`: Show renderer version, zoom scale and FPS counter in the top left corner of the map. diff --git a/docs/INSTALL.md b/docs/INSTALL.md index ff8b4f3e53..a2c5612cc4 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -85,7 +85,7 @@ You need a Linux or a Mac machine to build a desktop version of Organic Maps. [W Ensure that you have at least 20GB of free space. -Install Cmake (**3.22.1** minimum), Boost, Qt 6 and other dependencies. +Install Cmake (**3.22.1** minimum), Boost, Qt 5 and other dependencies. Installing *ccache* can speed up active development. @@ -97,13 +97,12 @@ sudo apt update && sudo apt install -y \ clang \ ninja-build \ python3 \ - qt6-base-dev \ + qtbase5-dev \ libc++-dev \ libfreetype-dev \ - libglvnd-dev \ - libgl1-mesa-dev \ + libglu1-mesa-dev \ libicu-dev \ - libqt6svg6-dev \ + libqt5svg5-dev \ libsqlite3-dev \ zlib1g-dev ``` @@ -130,17 +129,15 @@ sudo dnf install -y \ freetype-devel \ libicu-devel \ libstdc++-devel \ - mesa-libGL-devel \ - libglvnd-devel \ - qt6-qtbase-devel \ - qt6-qtsvg-devel \ + qt5-qtbase-devel \ + qt5-qtsvg-devel \ sqlite-devel ``` _macOS:_ ```bash -brew install cmake ninja qt@6 +brew install cmake ninja qt@5 ``` ### Windows @@ -148,7 +145,7 @@ brew install cmake ninja qt@6 We haven't compiled Organic Maps on Windows *natively* in a long time, though it is possible. Some files should be updated. There is a work in progress on [windows](https://github.com/organicmaps/organicmaps/tree/windows) branch. Please contribute if you have time. -You'll need to have python3, cmake, ninja, and QT6 in the PATH, and Visual Studio 2022 or Visual Studio 2022 Build Tools installed. Use [Visual Studio Developer Command Prompt](https://learn.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022) or generate Visual Studio project files with CMake to build the project. +You'll need to have python3, cmake, ninja, and QT5 in the PATH, and Visual Studio 2022 or Visual Studio 2022 Build Tools installed. Use [Visual Studio Developer Command Prompt](https://learn.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022) or generate Visual Studio project files with CMake to build the project. However, it is possible to use the WSL (Windows Subsystem for Linux) to run GUI applications. @@ -268,7 +265,7 @@ To switch themes you can enter this commands: - `?vlight` - Day theme for vehicle navigation - `?vdark` - Night theme for vehicle navigation -There are also other commands for turning on/off isolines, antialiasing, etc. Check [DEBUG_COMMANDS.md](DEBUG_COMMANDS.md) to learn about them. +There are also other commands for turning on/off isolines, antialiasing, etc. Check [the code](https://github.com/organicmaps/organicmaps/blob/6ae19b40c2b7a515338eb128547df05da13bdb78/map/framework.cpp#L2570-L2671) to learn about them. ### More options diff --git a/drape/drape_tests/CMakeLists.txt b/drape/drape_tests/CMakeLists.txt index 377426e8cd..d93f200b32 100644 --- a/drape/drape_tests/CMakeLists.txt +++ b/drape/drape_tests/CMakeLists.txt @@ -40,4 +40,6 @@ target_link_libraries(${PROJECT_NAME} indexer # For StyleReader in static_texture_tests drape gmock + gtest + Qt5::Core ) diff --git a/drape_frontend/area_shape.cpp b/drape_frontend/area_shape.cpp index ff702c0a72..46c94e5cc1 100644 --- a/drape_frontend/area_shape.cpp +++ b/drape_frontend/area_shape.cpp @@ -41,10 +41,7 @@ void AreaShape::Draw(ref_ptr context, ref_ptr } if (m_params.m_is3D) - { - if (m_vertexes.size() < 10000) - DrawArea3D(context, batcher, colorUv, outlineUv, region.GetTexture()); - } + DrawArea3D(context, batcher, colorUv, outlineUv, region.GetTexture()); else if (m_params.m_hatching) DrawHatchingArea(context, batcher, colorUv, region.GetTexture(), textures->GetHatchingTexture()); else diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 6f127ce92b..43216af1a9 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -695,9 +695,7 @@ void BackendRenderer::RenderFrame() void BackendRenderer::InitContextDependentResources() { - // Increase this value for big features. uint32_t constexpr kBatchSize = 5000; - m_batchersPool = make_unique_dp>(kReadingThreadsCount, std::bind(&BackendRenderer::FlushGeometry, this, _1, _2, _3), kBatchSize, kBatchSize); diff --git a/indexer/caching_rank_table_loader.cpp b/indexer/caching_rank_table_loader.cpp index e540c7a797..dbaa3627ba 100644 --- a/indexer/caching_rank_table_loader.cpp +++ b/indexer/caching_rank_table_loader.cpp @@ -3,7 +3,14 @@ #include "search/dummy_rank_table.hpp" #include "indexer/data_source.hpp" +#include "indexer/feature.hpp" +#include "defines.hpp" + +namespace +{ +uint8_t const kNoRank = 0; +} // namespace CachingRankTableLoader::CachingRankTableLoader(DataSource const & dataSource, std::string const & sectionName) @@ -16,7 +23,7 @@ uint8_t CachingRankTableLoader::Get(FeatureID const & featureId) const auto const handle = m_dataSource.GetMwmHandleById(featureId.m_mwmId); if (!handle.IsAlive()) - return search::RankTable::kNoRank; + return kNoRank; auto it = m_deserializers.find(featureId.m_mwmId); diff --git a/indexer/caching_rank_table_loader.hpp b/indexer/caching_rank_table_loader.hpp index c8dc5d5b40..2e80429ae7 100644 --- a/indexer/caching_rank_table_loader.hpp +++ b/indexer/caching_rank_table_loader.hpp @@ -6,6 +6,7 @@ #include "base/macros.hpp" +#include #include #include #include @@ -19,14 +20,13 @@ class CachingRankTableLoader public: CachingRankTableLoader(DataSource const & dataSource, std::string const & sectionName); - /// @return 0 if there is no rank for feature. uint8_t Get(FeatureID const & featureId) const; void OnMwmDeregistered(platform::LocalCountryFile const & localFile); private: DataSource const & m_dataSource; std::string const m_sectionName; - mutable std::map> m_deserializers; + mutable std::map const> m_deserializers; DISALLOW_COPY(CachingRankTableLoader); }; diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index ecf1926bb2..8c065b6990 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -346,16 +346,16 @@ IsWayChecker::IsWayChecker() {"primary", Regular}, {"primary_link", Regular}, {"residential", Residential}, - {"road", Minors}, + {"road", Outdoor}, {"secondary", Regular}, {"secondary_link",Regular}, - {"service", Minors}, + {"service", Residential}, {"tertiary", Regular}, {"tertiary_link", Regular}, {"track", Outdoor}, {"trunk", Motorway}, {"trunk_link", Motorway}, - {"unclassified", Minors}, + {"unclassified", Outdoor}, }; m_ranks.Reserve(std::size(types)); diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index c4611a541b..65eb507c9f 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -222,7 +222,6 @@ public: Pedestrian, Cycleway, Outdoor, - Minors, Residential, Regular, Motorway, diff --git a/indexer/indexer_tests/rank_table_test.cpp b/indexer/indexer_tests/rank_table_test.cpp index 07a4287011..879c33dc86 100644 --- a/indexer/indexer_tests/rank_table_test.cpp +++ b/indexer/indexer_tests/rank_table_test.cpp @@ -85,7 +85,8 @@ UNIT_TEST(RankTableBuilder_EndToEnd) base::CopyFileX(originalMapPath, mapPath); SCOPE_GUARD(cleanup, bind(&FileWriter::DeleteFileX, mapPath)); - auto const localFile = platform::LocalCountryFile::MakeForTesting("minsk-pass-copy"); + platform::LocalCountryFile localFile = + platform::LocalCountryFile::MakeForTesting("minsk-pass-copy"); TEST(localFile.OnDisk(MapFileType::Map), ()); vector ranks; @@ -105,3 +106,57 @@ UNIT_TEST(RankTableBuilder_EndToEnd) TestTable(ranks, mapPath); } + +UNIT_TEST(RankTableBuilder_WrongEndianness) +{ + char const kTestFile[] = "test.mwm"; + SCOPE_GUARD(cleanup, bind(&FileWriter::DeleteFileX, kTestFile)); + + vector ranks = {0, 1, 2, 3, 4}; + { + FilesContainerW wcont(kTestFile); + search::RankTableBuilder::Create(ranks, wcont, SEARCH_RANKS_FILE_TAG); + } + + // Load rank table in host endianness. + unique_ptr table; + { + FilesContainerR rcont(kTestFile); + table = search::RankTable::Load(rcont, SEARCH_RANKS_FILE_TAG); + TEST(table.get(), ()); + TestTable(ranks, *table); + } + + // Serialize rank table in opposite endianness. + { + vector data; + { + MemWriter writer(data); + table->Serialize(writer, false /* preserveHostEndianness */); + } + + FilesContainerW wcont(kTestFile); + wcont.Write(data, SEARCH_RANKS_FILE_TAG); + } + + // Try to load rank table from opposite endianness. + { + FilesContainerR rcont(kTestFile); + auto table = search::RankTable::Load(rcont, SEARCH_RANKS_FILE_TAG); + TEST(table.get(), ()); + TestTable(ranks, *table); + } + + // It's impossible to map rank table from opposite endianness. + { + FilesMappingContainer mcont(kTestFile); + auto table = search::RankTable::Load(mcont, SEARCH_RANKS_FILE_TAG); + TEST(!table.get(), ()); + } + + // Try to re-create rank table in test file. + TEST(search::SearchRankTableBuilder::CreateIfNotExists(kTestFile), ()); + + // Try to load and map rank table - both methods should work now. + TestTable(ranks, kTestFile); +} diff --git a/indexer/rank_table.cpp b/indexer/rank_table.cpp index 348e05d00a..d7511fbf6e 100644 --- a/indexer/rank_table.cpp +++ b/indexer/rank_table.cpp @@ -1,10 +1,17 @@ #include "indexer/rank_table.hpp" +#include "indexer/classificator.hpp" #include "indexer/data_header.hpp" +#include "indexer/feature_algo.hpp" #include "indexer/feature_impl.hpp" +#include "indexer/feature_utils.hpp" #include "indexer/features_vector.hpp" #include "indexer/ftypes_matcher.hpp" +#include "platform/local_country_file.hpp" +#include "platform/local_country_file_utils.hpp" + +#include "coding/endianness.hpp" #include "coding/files_container.hpp" #include "coding/file_writer.hpp" #include "coding/memory_region.hpp" @@ -13,30 +20,54 @@ #include "coding/succinct_mapper.hpp" #include "coding/writer.hpp" -#include "base/exception.hpp" +#include "base/assert.hpp" #include "base/logging.hpp" +#include "base/macros.hpp" +#include "base/math.hpp" #include +#include #include +#include #include "defines.hpp" +using namespace std; namespace search { -using namespace std; - namespace { -size_t constexpr kVersionOffset = 0; -size_t constexpr kHeaderSize = 8; +uint64_t const kVersionOffset = 0; +uint64_t const kFlagsOffset = 1; +uint64_t const kHeaderSize = 8; + +enum class CheckResult +{ + CorruptedHeader, + EndiannessMismatch, + EndiannessMatch +}; + +template +CheckResult CheckEndianness(TReader && reader) +{ + if (reader.Size() < kHeaderSize) + return CheckResult::CorruptedHeader; + uint8_t flags; + reader.Read(kFlagsOffset, &flags, sizeof(flags)); + bool const isHostBigEndian = IsBigEndianMacroBased(); + bool const isDataBigEndian = flags & 1; + if (isHostBigEndian != isDataBigEndian) + return CheckResult::EndiannessMismatch; + return CheckResult::EndiannessMatch; +} unique_ptr GetMemoryRegionForTag(FilesContainerR const & rcont, FilesContainerBase::Tag const & tag) { if (!rcont.IsExist(tag)) - return {}; - + return unique_ptr(); FilesContainerR::TReader reader = rcont.GetReader(tag); vector buffer(static_cast(reader.Size())); reader.Read(0, buffer.data(), buffer.size()); @@ -47,13 +78,13 @@ unique_ptr GetMemoryRegionForTag(FilesMappingContainer const FilesContainerBase::Tag const & tag) { if (!mcont.IsExist(tag)) - return {}; - + return unique_ptr(); FilesMappingContainer::Handle handle = mcont.Map(tag); return make_unique(std::move(handle)); } -// RankTable version 0, uses simple dense coding to store and access array of ranks. +// RankTable version 1, uses simple dense coding to store and access +// array of ranks. class RankTableV0 : public RankTable { public: @@ -68,7 +99,7 @@ public: // May be there is a better way to inject this code. Without this check search engine crashes here. //ASSERT_LESS(i, Size(), ()); if (i >= Size()) - return kNoRank; + return 0; return m_coding.Get(i); } @@ -76,23 +107,60 @@ public: RankTable::Version GetVersion() const override { return V0; } void Serialize(Writer & writer, bool preserveHostEndianness) override { + static uint64_t const padding = 0; + uint8_t const version = GetVersion(); - size_t constexpr kVersionSize = sizeof(version); - writer.Write(&version, kVersionSize); - - uint64_t const padding = 0; - static_assert(kHeaderSize % 8 == 0); // next succinct vector should be aligned - writer.Write(&padding, kHeaderSize - kVersionSize); - - Freeze(m_coding, writer, "SimpleDenseCoding"); + uint8_t const flags = preserveHostEndianness ? IsBigEndianMacroBased() : !IsBigEndianMacroBased(); + writer.Write(&version, sizeof(version)); + writer.Write(&flags, sizeof(flags)); + writer.Write(&padding, 6); + if (preserveHostEndianness) + Freeze(m_coding, writer, "SimpleDenseCoding"); + else + ReverseFreeze(m_coding, writer, "SimpleDenseCoding"); } // Loads RankTableV0 from a raw memory region. - template static unique_ptr Load(unique_ptr && region) + static unique_ptr Load(unique_ptr && region) { + if (!region.get()) + return unique_ptr(); + + auto const result = + CheckEndianness(MemReader(region->ImmutableData(), static_cast(region->Size()))); + if (result != CheckResult::EndiannessMatch) + return unique_ptr(); + auto table = make_unique(); + coding::Map(table->m_coding, region->ImmutableData() + kHeaderSize, "SimpleDenseCoding"); table->m_region = std::move(region); - coding::Map(table->m_coding, table->m_region->ImmutableData() + kHeaderSize, "SimpleDenseCoding"); + return table; + } + + // Loads RankTableV0 from a raw memory region. Modifies region in + // the case of endianness mismatch. + static unique_ptr Load(unique_ptr && region) + { + if (!region.get()) + return unique_ptr(); + + unique_ptr table; + switch ( + CheckEndianness(MemReader(region->ImmutableData(), static_cast(region->Size())))) + { + case CheckResult::CorruptedHeader: + break; + case CheckResult::EndiannessMismatch: + table.reset(new RankTableV0()); + coding::ReverseMap(table->m_coding, region->MutableData() + kHeaderSize, "SimpleDenseCoding"); + table->m_region = std::move(region); + break; + case CheckResult::EndiannessMatch: + table.reset(new RankTableV0()); + coding::Map(table->m_coding, region->ImmutableData() + kHeaderSize, "SimpleDenseCoding"); + table->m_region = std::move(region); + break; + } return table; } @@ -108,6 +176,7 @@ void SerializeRankTable(RankTable & table, FilesContainerW & wcont, string const { if (wcont.IsExist(sectionName)) wcont.DeleteSection(sectionName); + ASSERT(!wcont.IsExist(sectionName), ()); vector buffer; { @@ -148,22 +217,77 @@ unique_ptr LoadRankTable(unique_ptr && region) return {}; } +uint8_t CalcEventRank(FeatureType & /*ft*/) +{ + //TODO: add custom event processing, i.e. fc2018. + return 0; +} + +uint8_t CalcTransportRank(FeatureType & ft) +{ + uint8_t const kTransportRank = 2; + if (ftypes::IsRailwayStationChecker::Instance()(ft) || + ftypes::IsSubwayStationChecker::Instance()(ft) || ftypes::IsAirportChecker::Instance()(ft)) + { + return kTransportRank; + } + + return 0; +} + // Calculates search rank for a feature. uint8_t CalcSearchRank(FeatureType & ft) { - return feature::PopulationToRank(ftypes::GetPopulation(ft)); + auto const eventRank = CalcEventRank(ft); + auto const transportRank = CalcTransportRank(ft); + auto const populationRank = feature::PopulationToRank(ftypes::GetPopulation(ft)); + + return base::Clamp(eventRank + transportRank + populationRank, 0, + static_cast(numeric_limits::max())); } // Creates rank table if it does not exists in |rcont| or has wrong -// endianness. Otherwise (table exists and has correct format) returns null. +// endianness. Otherwise (table exists and has correct format) returns +// null. unique_ptr CreateSearchRankTableIfNotExists(FilesContainerR & rcont) { - if (rcont.IsExist(SEARCH_RANKS_FILE_TAG)) - return {}; + unique_ptr table; - vector ranks; - SearchRankTableBuilder::CalcSearchRanks(rcont, ranks); - return make_unique(ranks); + if (rcont.IsExist(SEARCH_RANKS_FILE_TAG)) + { + switch (CheckEndianness(rcont.GetReader(SEARCH_RANKS_FILE_TAG))) + { + case CheckResult::CorruptedHeader: + { + // Worst case - we need to create rank table from scratch. + break; + } + case CheckResult::EndiannessMismatch: + { + // Try to copy whole serialized data and instantiate table via + // reverse mapping. + auto region = GetMemoryRegionForTag(rcont, SEARCH_RANKS_FILE_TAG); + table = LoadRankTable(std::move(region)); + break; + } + case CheckResult::EndiannessMatch: + { + // Table exists and has proper format. Nothing to do here. + return unique_ptr(); + } + } + } + + // Table doesn't exist or has wrong format. It's better to create it + // from scratch. + if (!table) + { + vector ranks; + SearchRankTableBuilder::CalcSearchRanks(rcont, ranks); + table = make_unique(ranks); + } + + return table; } } // namespace @@ -189,6 +313,37 @@ void SearchRankTableBuilder::CalcSearchRanks(FilesContainerR & rcont, vector table; + { + ModelReaderPtr reader = platform::GetCountryReader(localFile, MapFileType::Map); + if (!reader.GetPtr()) + return false; + + mapPath = reader.GetName(); + + FilesContainerR rcont(reader); + table = CreateSearchRankTableIfNotExists(rcont); + } + + if (table) + SerializeRankTable(*table, mapPath, SEARCH_RANKS_FILE_TAG); + + return true; + } + catch (exception & e) + { + LOG(LWARNING, ("Can' create rank table for:", localFile, ":", e.what())); + return false; + } +} + // static bool SearchRankTableBuilder::CreateIfNotExists(string const & mapPath) noexcept { @@ -205,7 +360,7 @@ bool SearchRankTableBuilder::CreateIfNotExists(string const & mapPath) noexcept return true; } - catch (RootException const & e) + catch (exception & e) { LOG(LWARNING, ("Can' create rank table for:", mapPath, ":", e.what())); return false; diff --git a/indexer/rank_table.hpp b/indexer/rank_table.hpp index 7a26a2fa86..6f2a19886c 100644 --- a/indexer/rank_table.hpp +++ b/indexer/rank_table.hpp @@ -48,8 +48,7 @@ public: virtual ~RankTable() = default; - static uint8_t constexpr kNoRank = 0; - /// @return rank of the i-th feature, or kNoRank if there is no rank. + // Returns rank of the i-th feature. virtual uint8_t Get(uint64_t i) const = 0; // Returns total number of ranks (or features, as there is a 1-1 correspondence). @@ -113,6 +112,7 @@ public: // // Return true if rank table was successfully generated and written // or already exists and has correct format. + static bool CreateIfNotExists(platform::LocalCountryFile const & localFile) noexcept; static bool CreateIfNotExists(std::string const & mapPath) noexcept; }; } // namespace search diff --git a/indexer/search_string_utils.cpp b/indexer/search_string_utils.cpp index 6f32e2a950..7ded9149e9 100644 --- a/indexer/search_string_utils.cpp +++ b/indexer/search_string_utils.cpp @@ -30,9 +30,6 @@ std::vector const kAllowedMisprints = { MakeUniString("ао"), MakeUniString("еиэ"), MakeUniString("шщ"), - // Spanish - MakeUniString("jh"), // "Jose" <-> "Hose" - MakeUniString("fh"), // "Hernández" <-> "Fernández" }; std::pair const kPreprocessReplacements[] = { diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h index bac5c47163..a5da3f0f29 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h @@ -23,7 +23,8 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly, nullable) NSString *cuisine; @property(nonatomic, readonly, nullable) NSString *ppOperator; @property(nonatomic, readonly, nullable) NSString *address; -@property(nonatomic, readonly, nullable) NSArray *coordFormats; +@property(nonatomic, readonly, nullable) NSString *rawCoordinates; +@property(nonatomic, readonly, nullable) NSString *formattedCoordinates; @property(nonatomic, readonly, nullable) NSString *wifiAvailable; @property(nonatomic, readonly, nullable) NSString *level; diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm index 2d4d6adcf0..22690d7f60 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm @@ -71,12 +71,8 @@ using namespace osm; }); _address = rawData.GetAddress().empty() ? nil : @(rawData.GetAddress().c_str()); - _coordFormats = @[@(rawData.GetFormattedCoordinate(place_page::CoordinatesFormat::LatLonDMS).c_str()), - @(rawData.GetFormattedCoordinate(place_page::CoordinatesFormat::LatLonDecimal).c_str()), - @(rawData.GetFormattedCoordinate(place_page::CoordinatesFormat::OLCFull).c_str()), - @(rawData.GetFormattedCoordinate(place_page::CoordinatesFormat::OSMLink).c_str()), - @(rawData.GetFormattedCoordinate(place_page::CoordinatesFormat::UTM).c_str()), - @(rawData.GetFormattedCoordinate(place_page::CoordinatesFormat::MGRS).c_str())]; + _rawCoordinates = @(rawData.GetFormattedCoordinate(true).c_str()); + _formattedCoordinates = @(rawData.GetFormattedCoordinate(false).c_str()); } return self; } diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm index 6e12561cb0..bce287318d 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm @@ -91,7 +91,7 @@ static PlacePageDataHotelType convertHotelType(std::optional 0; diff --git a/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift b/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift index 36f3153d16..0120536276 100644 --- a/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift +++ b/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift @@ -64,7 +64,7 @@ protocol PlacePageInfoViewControllerDelegate: AnyObject { class PlacePageInfoViewController: UIViewController { private struct Const { - static let coordFormatIdKey = "PlacePageInfoViewController_coordFormatIdKey" + static let coordinatesKey = "PlacePageInfoViewController_coordinatesKey" } private typealias TapHandler = InfoItemViewController.TapHandler private typealias Style = InfoItemViewController.Style @@ -95,15 +95,15 @@ class PlacePageInfoViewController: UIViewController { var placePageInfoData: PlacePageInfoData! weak var delegate: PlacePageInfoViewControllerDelegate? - var coordinatesFormatId: Int { + var showFormattedCoordinates: Bool { get { - UserDefaults.standard.integer(forKey: Const.coordFormatIdKey) + UserDefaults.standard.bool(forKey: Const.coordinatesKey) } set { - UserDefaults.standard.set(newValue, forKey: Const.coordFormatIdKey) + UserDefaults.standard.set(newValue, forKey: Const.coordinatesKey) } } - + override func viewDidLoad() { super.viewDidLoad() @@ -202,24 +202,24 @@ class PlacePageInfoViewController: UIViewController { addressView?.canShowMenu = true } - var formatId = self.coordinatesFormatId - if let coordFormats = self.placePageInfoData.coordFormats as? Array { - if formatId >= coordFormats.count { - formatId = 0 - } - - coordinatesView = createInfoItem(coordFormats[formatId], icon: UIImage(named: "ic_placepage_coordinate")) { + if let formattedCoordinates = placePageInfoData.formattedCoordinates, + let rawCoordinates = placePageInfoData.rawCoordinates { + let coordinates = showFormattedCoordinates ? formattedCoordinates : rawCoordinates + coordinatesView = createInfoItem(coordinates, icon: UIImage(named: "ic_placepage_coordinate")) { [unowned self] in - let formatId = (self.coordinatesFormatId + 1) % coordFormats.count - self.coordinatesFormatId = formatId - let coordinates:String = coordFormats[formatId] + self.showFormattedCoordinates = !self.showFormattedCoordinates + let coordinates = self.showFormattedCoordinates ? formattedCoordinates : rawCoordinates self.coordinatesView?.infoLabel.text = coordinates } - - coordinatesView?.accessoryImage.image = UIImage(named: "ic_placepage_change") - coordinatesView?.accessoryImage.isHidden = false - coordinatesView?.canShowMenu = true + } else if let formattedCoordinates = placePageInfoData.formattedCoordinates { + coordinatesView = createInfoItem(formattedCoordinates, icon: UIImage(named: "ic_placepage_coordinate")) + } else if let rawCoordinates = placePageInfoData.rawCoordinates { + coordinatesView = createInfoItem(rawCoordinates, icon: UIImage(named: "ic_placepage_coordinate")) } + + coordinatesView?.accessoryImage.image = UIImage(named: "ic_placepage_change") + coordinatesView?.accessoryImage.isHidden = false + coordinatesView?.canShowMenu = true } // MARK: private diff --git a/map/place_page_info.cpp b/map/place_page_info.cpp index d185e914ce..4491bb550a 100644 --- a/map/place_page_info.cpp +++ b/map/place_page_info.cpp @@ -11,14 +11,12 @@ #include "indexer/feature_utils.hpp" #include "indexer/road_shields_parser.hpp" -#include "platform/localization.hpp" #include "platform/measurement_utils.hpp" #include "platform/preferred_languages.hpp" +#include "platform/localization.hpp" #include "base/assert.hpp" -#include "3party/open-location-code/openlocationcode.h" - #include namespace place_page @@ -286,39 +284,11 @@ std::string Info::FormatStars() const return stars; } -std::string Info::GetFormattedCoordinate(CoordinatesFormat coordsFormat) const +std::string Info::GetFormattedCoordinate(bool isDMS) const { auto const & ll = GetLatLon(); - auto const lat = ll.m_lat; - auto const lon = ll.m_lon; - switch (coordsFormat) - { - default: - case CoordinatesFormat::LatLonDMS: // DMS, comma separated - return measurement_utils::FormatLatLonAsDMS(lat, lon, false /*withComma*/, 2); - case CoordinatesFormat::LatLonDecimal: // Decimal, comma separated - return measurement_utils::FormatLatLon(lat, lon, true /* withComma */); - case CoordinatesFormat::OLCFull: // Open location code, long format - return openlocationcode::Encode({lat, lon}); - case CoordinatesFormat::OSMLink: // Link to osm.org - return measurement_utils::FormatOsmLink(lat, lon, 14); - case CoordinatesFormat::UTM: // Universal Transverse Mercator - { - std::string utmCoords = utm_mgrs_utils::FormatUTM(lat, lon); - if (utmCoords.empty()) - return "UTM: N/A"; - else - return "UTM: " + utmCoords; - } - case CoordinatesFormat::MGRS: // Military Grid Reference System - { - std::string mgrsCoords = utm_mgrs_utils::FormatMGRS(lat, lon, 5); - if (mgrsCoords.empty()) - return "MGRS: N/A"; - else - return "MGRS: " + mgrsCoords; - } - } + return isDMS ? measurement_utils::FormatLatLon(ll.m_lat, ll.m_lon, true) + : measurement_utils::FormatLatLonAsDMS(ll.m_lat, ll.m_lon, false, 2); } void Info::SetRoadType(RoadWarningMarkType type, std::string const & localizedType, std::string const & distance) diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp index 232cad2061..576ea588fe 100644 --- a/map/place_page_info.hpp +++ b/map/place_page_info.hpp @@ -16,8 +16,6 @@ #include "geometry/point2d.hpp" -#include "platform/utm_mgrs_utils.hpp" - #include #include #include @@ -34,16 +32,6 @@ enum class OpeningMode Full }; -enum class CoordinatesFormat -{ - LatLonDMS = 0, // DMS, comma separated - LatLonDecimal, // Decimal, comma separated - OLCFull, // Open location code, long format - OSMLink, // Link to osm.org - UTM, // Universal Transverse Mercator - MGRS // Military Grid Reference System -}; - struct BuildInfo { enum class Source : uint8_t @@ -141,7 +129,7 @@ public: std::string const & GetAddress() const { return m_uiAddress; } std::string const & GetDescription() const { return m_description; } /// @returns coordinate in DMS format if isDMS is true - std::string GetFormattedCoordinate(CoordinatesFormat format) const; + std::string GetFormattedCoordinate(bool isDMS) const; /// UI setters void SetCustomName(std::string const & name); diff --git a/openlr/openlr_match_quality/openlr_assessment_tool/traffic_mode.cpp b/openlr/openlr_match_quality/openlr_assessment_tool/traffic_mode.cpp index 0cec12a32a..9020535baa 100644 --- a/openlr/openlr_match_quality/openlr_assessment_tool/traffic_mode.cpp +++ b/openlr/openlr_match_quality/openlr_assessment_tool/traffic_mode.cpp @@ -273,8 +273,8 @@ QVariant TrafficMode::headerData(int section, Qt::Orientation orientation, void TrafficMode::OnItemSelected(QItemSelection const & selected, QItemSelection const &) { - ASSERT(!selected.empty(), ()); - ASSERT(!m_segments.empty(), ()); + CHECK(!selected.empty(), ("The selection should not be empty. RTFM for qt5.")); + CHECK(!m_segments.empty(), ("No segments are loaded, can't select.")); auto const row = selected.front().top(); diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 06cc41ecb3..20284baec6 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -170,8 +170,8 @@ endif() target_link_libraries(${PROJECT_NAME} geometry # mercator::YToLat coding - $<$:Qt6::Core> - $<$:Qt6::Network> + $<$:Qt5::Core> + $<$:Qt5::Network> $<$:-framework\ Foundation -framework\ SystemConfiguration -framework\ CoreLocation -framework\ CFNetwork> ) diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index d9a44d1f6c..194371f976 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -1,6 +1,6 @@ project(desktop) -QT6_ADD_RESOURCES(RES_SOURCES res/resources.qrc) +QT5_ADD_RESOURCES(RES_SOURCES res/resources.qrc) set(SRC about.cpp diff --git a/qt/build_style/build_common.cpp b/qt/build_style/build_common.cpp index 8ef0ad88a5..4dd5db1a72 100644 --- a/qt/build_style/build_common.cpp +++ b/qt/build_style/build_common.cpp @@ -2,17 +2,15 @@ #include "platform/platform.hpp" -#include "base/file_name_utils.hpp" - #include #include #include #include #include +#include #include #include // std::quoted -#include #include QString ExecProcess(QString const & program, std::initializer_list args, QProcessEnvironment const * env) @@ -25,7 +23,7 @@ QString ExecProcess(QString const & program, std::initializer_list args QProcess p; if (nullptr != env) p.setProcessEnvironment(*env); - + p.start(program, qargs, QIODevice::ReadOnly); p.waitForFinished(-1); @@ -113,12 +111,11 @@ QString GetExternalPath(QString const & name, QString const & primaryPath, // Special case for looking for in application folder. if (!QFileInfo::exists(path) && secondaryPath.isEmpty()) { - std::string const appPath = QCoreApplication::applicationDirPath().toStdString(); - - std::regex re("(/[^/]*\\.app)"); - std::smatch m; - if (std::regex_search(appPath, m, re) && m.size() > 0) - path.fromStdString(base::JoinPath(m[0], name.toStdString())); + QString const appPath = QCoreApplication::applicationDirPath(); + QRegExp rx("(/[^/]*\\.app)", Qt::CaseInsensitive); + int i = rx.indexIn(appPath); + if (i >= 0) + path = JoinPathQt({appPath.left(i), name}); } return path; } diff --git a/qt/build_style/build_common.h b/qt/build_style/build_common.h index a73beef8e3..474d3c3df2 100644 --- a/qt/build_style/build_common.h +++ b/qt/build_style/build_common.h @@ -6,6 +6,7 @@ #include #include +class QStringList; class QProcessEnvironment; // Returns stdout output of the program, throws std::runtime_error in case of non-zero exit code. diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 42c16e44ea..d3d245368d 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index e651a857ea..f93ffbcdd2 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -35,6 +35,7 @@ #endif // BUILD_DESIGNER #include +#include #include #include #include @@ -207,7 +208,7 @@ MainWindow::MainWindow(Framework & framework, #endif // NO_DOWNLOADER m_pDrawWidget->UpdateAfterSettingsChanged(); - + RoutingSettings::LoadSession(m_pDrawWidget->GetFramework()); } diff --git a/qt/popup_menu_holder.hpp b/qt/popup_menu_holder.hpp index 7ef29b7e5d..f9155f1429 100644 --- a/qt/popup_menu_holder.hpp +++ b/qt/popup_menu_holder.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/qt/qt_common/CMakeLists.txt b/qt/qt_common/CMakeLists.txt index ba4d9f199a..5af5189912 100644 --- a/qt/qt_common/CMakeLists.txt +++ b/qt/qt_common/CMakeLists.txt @@ -1,6 +1,6 @@ project(qt_common) -QT6_ADD_RESOURCES(RESOURCES res/resources_common.qrc) +QT5_ADD_RESOURCES(RESOURCES res/resources_common.qrc) set_property(SOURCE qrc_resources_common.cpp PROPERTY SKIP_AUTOGEN ON) @@ -33,8 +33,6 @@ target_compile_options(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} map - Qt6::Gui - Qt6::Widgets - Qt6::OpenGL - Qt6::OpenGLWidgets + Qt5::Gui + Qt5::Widgets ) diff --git a/qt/qt_common/map_widget.cpp b/qt/qt_common/map_widget.cpp index bbe4b97136..bebba3c812 100644 --- a/qt/qt_common/map_widget.cpp +++ b/qt/qt_common/map_widget.cpp @@ -15,15 +15,15 @@ #include #include -#include -#include -#include - #include #include -#include +#include +#include #include +#include +#include + namespace qt { namespace common @@ -506,12 +506,7 @@ void MapWidget::wheelEvent(QWheelEvent * e) return; QOpenGLWidget::wheelEvent(e); - - QPointF const pos = e->position(); - - // https://doc-snapshots.qt.io/qt6-dev/qwheelevent.html#angleDelta, angleDelta() returns in eighths of a degree. - /// @todo Here you can tune the speed of zooming. - m_framework.Scale(exp(e->angleDelta().y() / 3.0 / 360.0), m2::PointD(L2D(pos.x()), L2D(pos.y())), false); + m_framework.Scale(exp(e->delta() / 360.0), m2::PointD(L2D(e->x()), L2D(e->y())), false); } search::ReverseGeocoder::Address GetFeatureAddressInfo(Framework const & framework, diff --git a/qt/qt_common/map_widget.hpp b/qt/qt_common/map_widget.hpp index c2ffd32c33..537c71dfbd 100644 --- a/qt/qt_common/map_widget.hpp +++ b/qt/qt_common/map_widget.hpp @@ -10,9 +10,8 @@ #include "indexer/feature.hpp" -#include - #include +#include #include diff --git a/qt/qt_common/qtoglcontext.hpp b/qt/qt_common/qtoglcontext.hpp index 4186dc252b..c0deeb9ac5 100644 --- a/qt/qt_common/qtoglcontext.hpp +++ b/qt/qt_common/qtoglcontext.hpp @@ -2,9 +2,8 @@ #include "drape/oglcontext.hpp" -#include - #include +#include #include #include diff --git a/qt/qt_common/qtoglcontextfactory.hpp b/qt/qt_common/qtoglcontextfactory.hpp index d672f09561..7c82095689 100644 --- a/qt/qt_common/qtoglcontextfactory.hpp +++ b/qt/qt_common/qtoglcontextfactory.hpp @@ -4,6 +4,7 @@ #include "qt/qt_common/qtoglcontext.hpp" #include +#include #include diff --git a/qt/screenshoter.hpp b/qt/screenshoter.hpp index d61a23058c..4a9201ac76 100644 --- a/qt/screenshoter.hpp +++ b/qt/screenshoter.hpp @@ -6,7 +6,7 @@ #include "geometry/rect2d.hpp" -#include +#include #include #include diff --git a/qt/search_panel.cpp b/qt/search_panel.cpp index 0675766b29..0bbb898003 100644 --- a/qt/search_panel.cpp +++ b/qt/search_panel.cpp @@ -141,14 +141,14 @@ void SearchPanel::OnEverywhereSearchResults(uint64_t timestamp, search::Results for (size_t r = 0; r < res.GetHighlightRangesCount(); ++r) { std::pair const & range = res.GetHighlightRange(r); - strHigh.append(name.mid(pos, range.first - pos)); + strHigh.append(name.midRef(pos, range.first - pos)); strHigh.append(""); - strHigh.append(name.mid(range.first, range.second)); + strHigh.append(name.midRef(range.first, range.second)); strHigh.append(""); pos = range.first + range.second; } - strHigh.append(name.mid(pos)); + strHigh.append(name.midRef(pos)); int const rowCount = m_pTable->rowCount(); m_pTable->insertRow(rowCount); diff --git a/qt_tstfrm/CMakeLists.txt b/qt_tstfrm/CMakeLists.txt index 3992c6c4d4..8a773abe65 100644 --- a/qt_tstfrm/CMakeLists.txt +++ b/qt_tstfrm/CMakeLists.txt @@ -14,6 +14,6 @@ target_compile_options(${PROJECT_NAME} ) target_link_libraries(${PROJECT_NAME} - Qt6::Core - Qt6::Widgets + Qt5::Core + Qt5::Widgets ) diff --git a/routing/routing_integration_tests/turn_test.cpp b/routing/routing_integration_tests/turn_test.cpp index a8dc973243..e154b210ae 100644 --- a/routing/routing_integration_tests/turn_test.cpp +++ b/routing/routing_integration_tests/turn_test.cpp @@ -1296,20 +1296,6 @@ UNIT_TEST(Cyprus_A1_A5_TurnTestNextRoad) TEST_EQUAL(ri.m_destination_ref, "A5", ()); } -UNIT_TEST(Zurich_UseMainTurn) -{ - TRouteResult const routeResult = - integration::CalculateRoute(integration::GetVehicleComponents(VehicleType::Car), - mercator::FromLatLon(47.364832, 8.5656975), {0., 0.}, - mercator::FromLatLon(47.3640678, 8.56567312)); - - Route const & route = *routeResult.first; - RouterResultCode const result = routeResult.second; - TEST_EQUAL(result, RouterResultCode::NoError, ()); - integration::TestTurnCount(route, 1); - integration::TestRouteLength(route, 135.573); -} - namespace { template void TestNoTurns(ContT const & cont) diff --git a/routing_common/car_model_coefs.hpp b/routing_common/car_model_coefs.hpp index 04b85014e6..6f4f3c1e1e 100644 --- a/routing_common/car_model_coefs.hpp +++ b/routing_common/car_model_coefs.hpp @@ -35,8 +35,8 @@ HighwayBasedFactors const kHighwayBasedFactors = { // By VNG: Changed 0.3 -> 0.95 for Road and 0.3 -> 1.0 for Track. // They are already have very small speeds (10, 5 respectively). // There are no (99%) traffic lights or pedestrian crossings on this kind of roads. - {HighwayType::HighwayService, InOutCityFactor(0.70)}, - {HighwayType::HighwayRoad, InOutCityFactor(0.90)}, + {HighwayType::HighwayService, InOutCityFactor(0.80)}, + {HighwayType::HighwayRoad, InOutCityFactor(0.95)}, {HighwayType::HighwayTrack, InOutCityFactor(1.0)}, {HighwayType::ManMadePier, InOutCityFactor(0.90)}, diff --git a/search/dummy_rank_table.cpp b/search/dummy_rank_table.cpp index ec357ac588..9d54b9f220 100644 --- a/search/dummy_rank_table.cpp +++ b/search/dummy_rank_table.cpp @@ -2,14 +2,16 @@ #include "base/macros.hpp" +#include + namespace search { -uint8_t DummyRankTable::Get(uint64_t /* i */) const { return kNoRank; } +uint8_t DummyRankTable::Get(uint64_t /* i */) const { return 0; } uint64_t DummyRankTable::Size() const { NOTIMPLEMENTED(); - return 0; + return std::numeric_limits::max(); } RankTable::Version DummyRankTable::GetVersion() const diff --git a/search/geocoder.cpp b/search/geocoder.cpp index be3f17b5ac..cbd55fb746 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -1436,8 +1436,8 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con } } - // Following code creates a fake TYPE_BUILDING layer and intersects it with the streets layer. - // Controversial: we can emit streets like buildings here. Filtered in IsFakeBuildingButStreet(). + // Following code creates a fake layer with buildings and + // intersects it with the streets layer. layers.emplace_back(); SCOPE_GUARD(cleanupGuard, [&]{ layers.pop_back(); }); @@ -1445,8 +1445,7 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con InitLayer(Model::TYPE_BUILDING, m_postcodes.m_tokenRange, layer); vector features; - m_postcodes.m_countryFeatures.ForEach([&features](uint64_t bit) - { + m_postcodes.m_countryFeatures.ForEach([&features](uint64_t bit) { features.push_back(base::asserted_cast(bit)); }); layer.m_sortedFeatures = &features; @@ -1684,12 +1683,8 @@ void Geocoder::FindPaths(BaseContext & ctx) return true; }; - m_finder.ForEachReachableVertex(*m_matcher, sortedLayers, [&](IntersectionResult const & result) - { + m_finder.ForEachReachableVertex(*m_matcher, sortedLayers, [&](IntersectionResult const & result) { ASSERT(result.IsValid(), ()); - if (result.IsFakeBuildingButStreet()) - return; - EmitResult(ctx, m_context->GetId(), result.InnermostResult(), innermostLayer.m_type, innermostLayer.m_tokenRange, &result, ctx.AllTokensUsed(), isExactMatch(ctx, result)); diff --git a/search/intersection_result.hpp b/search/intersection_result.hpp index 509c15e035..926ca297a1 100644 --- a/search/intersection_result.hpp +++ b/search/intersection_result.hpp @@ -16,19 +16,13 @@ struct IntersectionResult void Set(Model::Type type, uint32_t id); - // Returns the first valid feature among the [SUBPOI, COMPLEX_POI, BUILDING, STREET]. + // Returns the first valid feature among the [SUBPOI, COMPLEX_POI, BUILDING, + // STREET]. uint32_t InnermostResult() const; // Returns true when at least one valid feature exists. inline bool IsValid() const { return InnermostResult() != kInvalidId; } - // Building == Streets means that we have actual street result, but got here - // via _fake_ TYPE_BUILDING layer (see MatchPOIsAndBuildings). - inline bool IsFakeBuildingButStreet() const - { - return m_building != kInvalidId && m_building == m_street; - } - // Clears all fields to an invalid state. void Clear(); diff --git a/search/model.cpp b/search/model.cpp index c2d60b0cf2..8ed1f6ca4a 100644 --- a/search/model.cpp +++ b/search/model.cpp @@ -111,13 +111,7 @@ public: bool operator()(FeatureType & ft) const { - if (!ft.GetHouseNumber().empty()) - return true; - - if (ft.GetGeomType() == feature::GeomType::Line) - return IsAddressInterpolChecker::Instance()(ft); - else - return IsBuildingChecker::Instance()(ft); + return !ft.GetHouseNumber().empty() || IsBuildingChecker::Instance()(ft); } }; } // namespace diff --git a/search/ranker.cpp b/search/ranker.cpp index 628d0505a8..f823b9f9d1 100644 --- a/search/ranker.cpp +++ b/search/ranker.cpp @@ -143,17 +143,8 @@ NameScores GetNameScores(FeatureType & ft, Geocoder::Params const & params, } if (type == Model::TYPE_BUILDING) - { - if (ft.GetGeomType() == feature::GeomType::Line) - { - // Separate case for addr:interpolation (Building + Line). - ASSERT(!ft.GetRef().empty(), ()); - // Just assign SUBSTRING with no errors (was checked in HouseNumbersMatch). - bestScores.UpdateIfBetter(NameScores(NameScore::SUBSTRING, ErrorsMade(0), false, 4)); - } - else - UpdateNameScores(ft.GetHouseNumber(), StringUtf8Multilang::kDefaultCode, sliceNoCategories, bestScores); - } + UpdateNameScores(ft.GetHouseNumber(), StringUtf8Multilang::kDefaultCode, sliceNoCategories, + bestScores); if (ftypes::IsAirportChecker::Instance()(ft)) { @@ -383,8 +374,8 @@ public: }, Delimiters()); // Factor is a number of the rest, not common matched tokens in Feature' name. Bigger is worse. - // Example when count == 0: UTH airport has empty name, but "ut" is a _common_ token. - info.m_commonTokensFactor = min(3, std::max(0, count - int(info.m_tokenRanges[info.m_type].Size()))); + info.m_commonTokensFactor = min(3, count - int(info.m_tokenRanges[info.m_type].Size())); + ASSERT_GREATER_OR_EQUAL(info.m_commonTokensFactor, 0, ()); } res.SetRankingInfo(info); diff --git a/search/ranking_info.cpp b/search/ranking_info.cpp index 34e1ec175d..35fd65edfc 100644 --- a/search/ranking_info.cpp +++ b/search/ranking_info.cpp @@ -84,7 +84,6 @@ double constexpr kStreetType[] = { 0, // Pedestrian 0, // Cycleway 0, // Outdoor - 0.004, // Minors 0.004, // Residential 0.005, // Regular 0.006, // Motorway @@ -405,7 +404,6 @@ std::string DebugPrint(StreetType type) case StreetType::Pedestrian: return "Pedestrian"; case StreetType::Cycleway: return "Cycleway"; case StreetType::Outdoor: return "Outdoor"; - case StreetType::Minors: return "Minors"; case StreetType::Residential: return "Residential"; case StreetType::Regular: return "Regular"; case StreetType::Motorway: return "Motorway"; diff --git a/search/ranking_utils.cpp b/search/ranking_utils.cpp index 203406319e..31da4e0b5f 100644 --- a/search/ranking_utils.cpp +++ b/search/ranking_utils.cpp @@ -112,7 +112,7 @@ bool IsStopWord(UniString const & s) // Don't want to put _full_ stopwords list, not to break current ranking. // Only 2-letters and the most common. char const * arr[] = { - "a", "s", "the", // English + "a", "s", // English "am", "im", "an", // German "d", "de", "di", "da", "la", "le", // French, Spanish, Italian "и", "я" // Cyrillic diff --git a/search/search_integration_tests/processor_test.cpp b/search/search_integration_tests/processor_test.cpp index 885622a04b..8bf5998de9 100644 --- a/search/search_integration_tests/processor_test.cpp +++ b/search/search_integration_tests/processor_test.cpp @@ -559,7 +559,7 @@ UNIT_CLASS_TEST(ProcessorTest, TestRankingInfo_PureCategory) } } -UNIT_CLASS_TEST(ProcessorTest, RankingInfo_ErrorsMade_1) +UNIT_CLASS_TEST(ProcessorTest, TestRankingInfo_ErrorsMade) { TestCity chekhov({0, 0}, "Чеховъ Антонъ Павловичъ", "ru", 100 /* rank */); @@ -605,7 +605,6 @@ UNIT_CLASS_TEST(ProcessorTest, RankingInfo_ErrorsMade_1) checkErrors("Cafe Yesenina", ErrorsMade(0)); checkErrors("Cafe Jesenina", ErrorsMade(1)); - /// @see search_string_utils.cpp, kAllowedMisprints // We allow only Y->{E, J, I, U} misprints for the first letter. checkErrors("Cafe Esenina", ErrorsMade(2)); @@ -635,33 +634,6 @@ UNIT_CLASS_TEST(ProcessorTest, RankingInfo_ErrorsMade_1) checkErrors("лермонтов чеховъ антон павлович", ErrorsMade(2)); } -// https://github.com/organicmaps/organicmaps/issues/5296 -UNIT_CLASS_TEST(ProcessorTest, RankingInfo_ErrorsMade_2) -{ - TestStreet hernandes({{-0.5, -0.5}, {0, 0}, {0.5, 0.5}}, "José Hernández", "es"); - - auto wonderlandId = BuildCountry("Wonderland", [&](TestMwmBuilder & builder) - { - builder.Add(hernandes); - }); - - SetViewport(m2::RectD(-1, -1, 1, 1)); - - auto checkErrors = [&](string const & query, ErrorsMade const & errorsMade) - { - auto request = MakeRequest(query, "es"); - auto const & results = request->Results(); - - Rules rules{ExactMatch(wonderlandId, hernandes)}; - TEST(ResultsMatch(results, rules), (query)); - TEST_EQUAL(results.size(), 1, (query)); - TEST_EQUAL(results[0].GetRankingInfo().m_errorsMade, errorsMade, (query)); - }; - - checkErrors("Hose", ErrorsMade(1)); - checkErrors("Fernández", ErrorsMade(1)); -} - UNIT_CLASS_TEST(ProcessorTest, TestHouseNumbers) { TestCity greenCity({0, 0}, "Зеленоград", "ru", 100 /* rank */); diff --git a/search/search_quality/assessment_tool/feature_info_dialog.cpp b/search/search_quality/assessment_tool/feature_info_dialog.cpp index 579580fddf..b7f5f501cd 100644 --- a/search/search_quality/assessment_tool/feature_info_dialog.cpp +++ b/search/search_quality/assessment_tool/feature_info_dialog.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/search/search_quality/assessment_tool/main_view.cpp b/search/search_quality/assessment_tool/main_view.cpp index e7de4c0d52..6f399246c4 100644 --- a/search/search_quality/assessment_tool/main_view.cpp +++ b/search/search_quality/assessment_tool/main_view.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/search/search_quality/assessment_tool/samples_view.cpp b/search/search_quality/assessment_tool/samples_view.cpp index 9194475794..8f4f3865d1 100644 --- a/search/search_quality/assessment_tool/samples_view.cpp +++ b/search/search_quality/assessment_tool/samples_view.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/search/search_quality/search_quality_tests/real_mwm_tests.cpp b/search/search_quality/search_quality_tests/real_mwm_tests.cpp index bac545317a..b4985d1cdd 100644 --- a/search/search_quality/search_quality_tests/real_mwm_tests.cpp +++ b/search/search_quality/search_quality_tests/real_mwm_tests.cpp @@ -474,9 +474,9 @@ UNIT_CLASS_TEST(MwmTestsFixture, Street_BusStop) auto const & results = request->Results(); TEST_GREATER(results.size(), kTopPoiResultsCount, ()); - // Top results are Hotel and Street (sometimes bus stop). - Range const range(results); - EqualClassifType(range, GetClassifTypes({{"tourism", "hotel"}, {"highway", "bus_stop"}, {"highway", "residential"}})); + // Top results are Hotel and Street. + Range const range(results, 0, 3); + EqualClassifType(range, GetClassifTypes({{"tourism", "hotel"}, {"shop", "supermarket"}, {"highway"}})); } { @@ -500,17 +500,6 @@ UNIT_CLASS_TEST(MwmTestsFixture, Street_BusStop) EqualClassifType(range, GetClassifTypes({{"highway", "bus_stop"}})); TEST_LESS(SortedByDistance(range, center), 5000.0, ()); } - - { - auto request = MakeRequest("Juncal train", "en"); - auto const & results = request->Results(); - TEST_GREATER(results.size(), kTopPoiResultsCount, ()); - - // First result is a train station in other MWM, >200km away. - TEST(EqualClassifType(results[0].GetFeatureType(), classif().GetTypeByPath({"railway", "station"})), ()); - double const dist = ms::DistanceOnEarth(center, mercator::ToLatLon(results[0].GetFeatureCenter())); - TEST_GREATER(dist, 2.0E5, ()); - } } UNIT_CLASS_TEST(MwmTestsFixture, Generic_Buildings_Rank) @@ -533,6 +522,7 @@ UNIT_CLASS_TEST(MwmTestsFixture, Generic_Buildings_Rank) { auto request = MakeRequest("dia ", "en"); auto const & results = request->Results(); + LOG(LINFO, (results)); TEST_GREATER(results.size(), kTopPoiResultsCount, ()); Range const range(results); @@ -540,84 +530,4 @@ UNIT_CLASS_TEST(MwmTestsFixture, Generic_Buildings_Rank) TEST_LESS(SortedByDistance(range, center), 1000.0, ()); } } - -UNIT_CLASS_TEST(MwmTestsFixture, UTH_Airport) -{ - auto const aeroportType = classif().GetTypeByPath({"aeroway", "aerodrome", "international"}); - - // Under UTH airport. - ms::LatLon const center(17.3867863, 102.7775625); - SetViewportAndLoadMaps(center); - - // "ut" query is _common_ - auto request = MakeRequest("ut", "en"); - auto const & results = request->Results(); - - bool found = false; - // The first 5 will be cities suggestions. - for (size_t i = 0; i < 10; ++i) - { - auto const & r = results[i]; - if (r.GetResultType() == search::Result::Type::Feature && - EqualClassifType(r.GetFeatureType(), aeroportType)) - { - found = true; - break; - } - } - - TEST(found, (results)); -} - -// https://github.com/organicmaps/organicmaps/issues/5186 -UNIT_CLASS_TEST(MwmTestsFixture, Milan_Streets) -{ - // Milan - ms::LatLon const center(45.46411, 9.19045); - SetViewportAndLoadMaps(center); - - auto request = MakeRequest("Via Domenichino", "it"); - auto const & results = request->Results(); - - size_t constexpr kResultsCount = 2; - TEST_GREATER(results.size(), kResultsCount, ()); - - Range const range(results, 0, kResultsCount); - TEST_LESS(SortedByDistance(range, center), 20000.0, ()); -} - -// https://github.com/organicmaps/organicmaps/issues/5150 -UNIT_CLASS_TEST(MwmTestsFixture, London_RedLion) -{ - // Milan - ms::LatLon const center(51.49263, -0.12877); - SetViewportAndLoadMaps(center); - - auto request = MakeRequest("Red Lion", "en"); - auto const & results = request->Results(); - - TEST_GREATER(results.size(), kPopularPoiResultsCount, ()); - - // Top first results "The Red Lion" in 5 km. - Range const range(results); - TEST_LESS(SortedByDistance(range, center), 5000.0, ()); -} - -UNIT_CLASS_TEST(MwmTestsFixture, AddrInterpolation_Rank) -{ - // Buenos Aires (Palermo) - ms::LatLon const center(-34.57852, -58.42567); - SetViewportAndLoadMaps(center); - - auto request = MakeRequest("Sante Fe 1176", "en"); - auto const & results = request->Results(); - - TEST_GREATER(results.size(), kPopularPoiResultsCount, ()); - - // Top first address results in 50 km. - Range const range(results); - EqualClassifType(range, GetClassifTypes({{"addr:interpolation"}})); - TEST_LESS(SortedByDistance(range, center), 50000.0, ()); -} - } // namespace real_mwm_tests diff --git a/skin_generator/CMakeLists.txt b/skin_generator/CMakeLists.txt index adab22765d..2b04dde9e2 100644 --- a/skin_generator/CMakeLists.txt +++ b/skin_generator/CMakeLists.txt @@ -11,7 +11,7 @@ omim_add_executable(${PROJECT_NAME} ${SRC}) target_link_libraries(${PROJECT_NAME} geometry gflags::gflags - Qt6::Xml - Qt6::Svg - Qt6::Widgets + Qt5::Xml + Qt5::Svg + Qt5::Widgets ) diff --git a/skin_generator/generator.cpp b/skin_generator/generator.cpp index b1bb25278c..dd65107aeb 100644 --- a/skin_generator/generator.cpp +++ b/skin_generator/generator.cpp @@ -241,8 +241,8 @@ bool SkinGenerator::WriteToFileNewStyle(std::string const &skinName) if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) return false; QTextStream ts(&file); - ts.setEncoding(QStringConverter::Utf8); + ts.setCodec("UTF-8"); ts << doc.toString(); return true; } -} // namespace tools +} diff --git a/skin_generator/generator.hpp b/skin_generator/generator.hpp index 8bcd370f93..c8c328c79c 100644 --- a/skin_generator/generator.hpp +++ b/skin_generator/generator.hpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include diff --git a/skin_generator/main.cpp b/skin_generator/main.cpp index 89f0c1e2dc..4e0b7d6361 100644 --- a/skin_generator/main.cpp +++ b/skin_generator/main.cpp @@ -8,6 +8,9 @@ #include #include +#include +#include + #include DEFINE_string(fontFileName, "../../data/01_dejavusans.ttf", "path to TrueType font file");