[bookmarks] Export to kmz with custom user symbols.

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
Viktor Govako 2023-10-09 15:20:17 -03:00
parent 906a98ef7b
commit 454338996c
6 changed files with 62 additions and 79 deletions

View file

@ -15,7 +15,7 @@ namespace
{
void CreateAndTestZip(std::string const & filePath, std::string const & zipPath)
{
TEST(CreateZipFromPathDeflatedAndDefaultCompression(filePath, zipPath), ());
TEST(CreateZipFromFiles({filePath}, zipPath, CompressionLevel::DefaultCompression), ());
ZipFileReader::FileList files;
ZipFileReader::FilesList(zipPath, files);

View file

@ -67,61 +67,11 @@ int GetCompressionLevel(CompressionLevel compression)
}
} // namespace
bool CreateZipFromPathDeflatedAndDefaultCompression(std::string const & filePath,
std::string const & zipFilePath)
{
// Open zip file for writing.
SCOPE_GUARD(outFileGuard, [&zipFilePath]() { base::DeleteFileX(zipFilePath); });
ZipHandle zip(zipFilePath);
if (!zip.Handle())
return false;
zip::FileInfo zipInfo = {};
CreateTMZip(zipInfo.tmz_date);
std::string fileName = base::FileNameFromFullPath(filePath);
if (!strings::IsASCIIString(fileName))
fileName = "OrganicMaps.kml";
if (zip::Code::Ok != zip::OpenNewFileInZip(zip.Handle(), fileName, zipInfo, "ZIP from OMaps",
Z_DEFLATED, Z_DEFAULT_COMPRESSION))
{
return false;
}
// Write source file into zip file.
try
{
base::FileData file(filePath, base::FileData::OP_READ);
uint64_t const fileSize = file.Size();
uint64_t currSize = 0;
std::array<char, zip::kFileBufferSize> buffer;
while (currSize < fileSize)
{
auto const toRead = std::min(buffer.size(), static_cast<size_t>(fileSize - currSize));
file.Read(currSize, buffer.data(), toRead);
if (zip::Code::Ok != zip::WriteInFileInZip(zip.Handle(), buffer, toRead))
return false;
currSize += toRead;
}
}
catch (Reader::Exception const & ex)
{
LOG(LERROR, ("Error reading file:", filePath, ex.Msg()));
return false;
}
outFileGuard.release();
return true;
}
bool CreateZipFromFiles(std::vector<std::string> const & files, std::string const & zipFilePath,
CompressionLevel compression)
bool CreateZipFromFiles(std::vector<std::string> const & filePaths, std::string const & zipFilePath,
CompressionLevel compression /* = CompressionLevel::DefaultCompression */,
std::vector<std::string> const * fileNames /* = nullptr */)
{
ASSERT(!fileNames || filePaths.size() == fileNames->size(), ());
SCOPE_GUARD(outFileGuard, [&zipFilePath]() { base::DeleteFileX(zipFilePath); });
ZipHandle zip(zipFilePath);
@ -129,19 +79,21 @@ bool CreateZipFromFiles(std::vector<std::string> const & files, std::string cons
return false;
auto const compressionLevel = GetCompressionLevel(compression);
zip::FileInfo const fileInfo = {};
zip::FileInfo zipInfo = {};
CreateTMZip(zipInfo.tmz_date);
try
{
for (auto const & filePath : files)
for (size_t i = 0; i < filePaths.size(); ++i)
{
if (zip::Code::Ok != zip::OpenNewFileInZip(zip.Handle(), filePath, fileInfo, "",
Z_DEFLATED, compressionLevel))
if (zip::Code::Ok != zip::OpenNewFileInZip(zip.Handle(), fileNames ? fileNames->at(i) : filePaths[i],
zipInfo, "ZIP from Organic Maps", Z_DEFLATED, compressionLevel))
{
return false;
}
base::FileData file(filePath, base::FileData::OP_READ);
base::FileData file(filePaths[i], base::FileData::OP_READ);
uint64_t const fileSize = file.Size();
uint64_t writtenSize = 0;
zip::Buffer buffer;

View file

@ -12,8 +12,8 @@ enum class CompressionLevel
Count
};
bool CreateZipFromPathDeflatedAndDefaultCompression(std::string const & filePath,
std::string const & zipFilePath);
bool CreateZipFromFiles(std::vector<std::string> const & files, std::string const & zipFilePath,
CompressionLevel compression = CompressionLevel::DefaultCompression);
/// @param[in] filePaths Full paths on disk to archive.
/// @param[in] fileNames Correspondent (for filePaths) file names in archive.
bool CreateZipFromFiles(std::vector<std::string> const & filePaths, std::string const & zipFilePath,
CompressionLevel compression = CompressionLevel::DefaultCompression,
std::vector<std::string> const * fileNames = nullptr);

View file

@ -81,19 +81,41 @@ BookmarkManager::SharingResult GetFileForSharing(BookmarkManager::KMLDataCollect
if (fileName.empty())
fileName = base::GetNameFromFullPathWithoutExt(kmlToShare.first);
auto const filePath = base::JoinPath(GetPlatform().TmpDir(), fileName + std::string{kKmlExtension});
SCOPE_GUARD(fileGuard, std::bind(&base::DeleteFileX, filePath));
/// @todo Really needed for zip?
if (!strings::IsASCIIString(fileName))
fileName = kDefaultBookmarksFileName;
fileName.append(kKmlExtension);
auto const & tmpDir = GetPlatform().TmpDir();
std::vector<std::string> filePaths, fileNames;
fileNames.push_back(fileName);
filePaths.push_back(base::JoinPath(tmpDir, fileNames.back()));
SCOPE_GUARD(fileGuard, std::bind(&base::DeleteFileX, filePaths.back()));
auto const categoryId = kmlToShare.second->m_categoryData.m_id;
if (!SaveKmlFileSafe(*kmlToShare.second, filePath, KmlFileType::Text))
if (!SaveKmlFileSafe(*kmlToShare.second, filePaths.back(), KmlFileType::Text))
return {categoryId, BookmarkManager::SharingResult::Code::FileError, "Bookmarks file does not exist."};
auto const tmpFilePath = base::JoinPath(GetPlatform().TmpDir(), fileName + std::string{kKmzExtension});
if (!CreateZipFromPathDeflatedAndDefaultCompression(filePath, tmpFilePath))
auto const bookmarksDir = GetBookmarksDirectory();
for (auto const & bmData : kmlToShare.second->m_bookmarksData)
{
if (!bmData.m_iconPath.empty())
{
auto const path = base::JoinPath(bookmarksDir, bmData.m_iconPath);
if (Platform::IsFileExistsByFullPath(path))
{
fileNames.push_back(bmData.m_iconPath);
filePaths.push_back(std::move(path));
}
}
}
auto const kmzFilePath = base::JoinPath(tmpDir, fileName);
if (!CreateZipFromFiles(filePaths, kmzFilePath, CompressionLevel::DefaultCompression, &fileNames))
return {categoryId, BookmarkManager::SharingResult::Code::ArchiveError, "Could not create archive."};
return {categoryId, tmpFilePath};
return {categoryId, kmzFilePath};
}
std::string ToString(BookmarkManager::SortingType type)
@ -2196,7 +2218,7 @@ kml::MarkGroupId BookmarkManager::CreateBookmarkCategory(kml::CategoryData && da
return groupId;
}
kml::MarkGroupId BookmarkManager::CreateBookmarkCategory(std::string const & name, bool autoSave)
kml::MarkGroupId BookmarkManager::CreateBookmarkCategory(std::string const & name, bool autoSave /* = true */)
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
auto const groupId = UserMarkIdStorage::Instance().GetNextCategoryId();
@ -2557,6 +2579,7 @@ std::unique_ptr<kml::FileData> BookmarkManager::CollectBmGroupKMLData(BookmarkCa
return kmlData;
}
/*
bool BookmarkManager::SaveBookmarkCategory(kml::MarkGroupId groupId)
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
@ -2576,6 +2599,7 @@ bool BookmarkManager::SaveBookmarkCategory(kml::MarkGroupId groupId, Writer & wr
auto kmlData = CollectBmGroupKMLData(group);
return SaveKmlData(*kmlData, writer, fileType);
}
*/
BookmarkManager::KMLDataCollectionPtr BookmarkManager::PrepareToSaveBookmarks(
kml::GroupIdCollection const & groupIdCollection)

View file

@ -360,9 +360,11 @@ public:
void FilterInvalidBookmarks(kml::MarkIdCollection & bookmarks) const;
void FilterInvalidTracks(kml::TrackIdCollection & tracks) const;
/// @todo Avoid dualism with sync/async tasks. Leave async only.
void EnableTestMode(bool enable);
bool SaveBookmarkCategory(kml::MarkGroupId groupId);
bool SaveBookmarkCategory(kml::MarkGroupId groupId, Writer & writer, KmlFileType fileType) const;
// bool SaveBookmarkCategory(kml::MarkGroupId groupId);
// bool SaveBookmarkCategory(kml::MarkGroupId groupId, Writer & writer, KmlFileType fileType) const;
static void UpdateLastModifiedTime(KMLDataCollection & collection);
// Used for LoadBookmarks() and unit tests only. Does *not* update last modified time.

View file

@ -211,6 +211,7 @@ UNIT_CLASS_TEST(Runner, Bookmarks_ImportKML)
TEST_EQUAL(bmManager.IsVisible(groupId), false, ());
}
/*
UNIT_CLASS_TEST(Runner, Bookmarks_ExportKML)
{
string const dir = GetBookmarksDirectory();
@ -268,7 +269,7 @@ UNIT_CLASS_TEST(Runner, Bookmarks_ExportKML)
kmlDataCollection3.emplace_back(fileName, LoadKmlFile(fileName, GetActiveKmlFileType()));
TEST(kmlDataCollection3.back().second, ());
bmManager.CreateCategories(std::move(kmlDataCollection3), true /* autoSave */);
bmManager.CreateCategories(std::move(kmlDataCollection3), true);
TEST_EQUAL(bmManager.GetBmGroupsIdList().size(), 1, ());
auto const groupId3 = bmManager.GetBmGroupsIdList().front();
@ -279,6 +280,7 @@ UNIT_CLASS_TEST(Runner, Bookmarks_ExportKML)
uint64_t dummy;
TEST(base::GetFileSize(fileName, dummy), ());
}
*/
namespace
{
@ -967,12 +969,13 @@ UNIT_CLASS_TEST(Runner, Bookmarks_InnerFolder)
TEST_EQUAL(bmManager.GetUserMarkIds(groupIds.front()).size(), 1, ());
}
/*
UNIT_CLASS_TEST(Runner, BookmarkCategory_EmptyName)
{
BookmarkManager bmManager(BM_CALLBACKS);
bmManager.EnableTestMode(true);
auto const catId = bmManager.CreateBookmarkCategory("", false /* autoSave */);
auto const catId = bmManager.CreateBookmarkCategory("", false);
kml::BookmarkData bm;
bm.m_point = m2::PointD(0, 0);
bmManager.GetEditSession().CreateBookmark(std::move(bm), catId);
@ -986,6 +989,7 @@ UNIT_CLASS_TEST(Runner, BookmarkCategory_EmptyName)
vector<string> const arrFiles = {"Bookmarks", "xxx"};
DeleteCategoryFiles(arrFiles);
}
*/
namespace
{
@ -1046,6 +1050,7 @@ UNIT_CLASS_TEST(Runner, Bookmarks_SpecialXMLNames)
expectedName = "test";
bmManager.GetEditSession().SetCategoryName(catId, expectedName);
/*
TEST(bmManager.SaveBookmarkCategory(catId), ());
auto const fileName = bmManager.GetCategoryFileName(catId);
@ -1055,12 +1060,11 @@ UNIT_CLASS_TEST(Runner, Bookmarks_SpecialXMLNames)
bmManager.GetEditSession().DeleteBmCategory(catId);
BookmarkManager::KMLDataCollection kmlDataCollection2;
kmlDataCollection2.emplace_back("" /* filePath */, LoadKmlFile(fileNameTmp, GetActiveKmlFileType()));
kmlDataCollection2.emplace_back("", LoadKmlFile(fileNameTmp, GetActiveKmlFileType()));
bmManager.CreateCategories(std::move(kmlDataCollection2));
BookmarkManager::KMLDataCollection kmlDataCollection3;
kmlDataCollection3.emplace_back("" /* filePath */,
LoadKmlData(MemReader(kmlString3, strlen(kmlString3)), KmlFileType::Text));
kmlDataCollection3.emplace_back("", LoadKmlData(MemReader(kmlString3, strlen(kmlString3)), KmlFileType::Text));
bmManager.UpdateLastModifiedTime(kmlDataCollection3);
bmManager.CreateCategories(std::move(kmlDataCollection3));
@ -1081,6 +1085,7 @@ UNIT_CLASS_TEST(Runner, Bookmarks_SpecialXMLNames)
TEST_EQUAL(kml::GetDefaultStr(bm1->GetName()), "![X1]{X2}(X3)", ());
TEST(base::DeleteFileX(fileNameTmp), ());
*/
}
UNIT_CLASS_TEST(Runner, TrackParsingTest_1)