From fd82f5316c42c17f1d8d77c4e84d682aedeef832 Mon Sep 17 00:00:00 2001 From: peri4 Date: Sun, 18 Dec 2022 20:40:49 +0300 Subject: [PATCH] add pip_vtt util --- CMakeLists.txt | 1 + utils/value_tree_translator/CMakeLists.txt | 16 ++ utils/value_tree_translator/main.cpp | 241 +++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 utils/value_tree_translator/CMakeLists.txt create mode 100644 utils/value_tree_translator/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e32a26f..3bbe6733 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -569,6 +569,7 @@ if(NOT PIP_FREERTOS) add_subdirectory("utils/code_model_generator") add_subdirectory("utils/resources_compiler") add_subdirectory("utils/deploy_tool") + add_subdirectory("utils/value_tree_translator") if(PIP_UTILS AND (NOT CROSSTOOLS)) add_subdirectory("utils/system_test") add_subdirectory("utils/udp_file_transfer") diff --git a/utils/value_tree_translator/CMakeLists.txt b/utils/value_tree_translator/CMakeLists.txt new file mode 100644 index 00000000..22139e2f --- /dev/null +++ b/utils/value_tree_translator/CMakeLists.txt @@ -0,0 +1,16 @@ +list(APPEND PIP_UTILS_LIST "pip_vtt") +set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) +import_version(pip_vtt PIP) +set_deploy_property(pip_vtt + LABEL "PIP ValueTree translator" + FULLNAME "${PIP_DOMAIN}.pip_vtt" + COMPANY "${PIP_COMPANY}" + INFO "Platform-Independent Primitives") +make_rc(pip_vtt _RC) +add_executable(pip_vtt "main.cpp" ${_RC}) +target_link_libraries(pip_vtt pip) +if (DEFINED LIB) + install(TARGETS pip_vtt DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +else() + install(TARGETS pip_vtt DESTINATION bin) +endif() diff --git a/utils/value_tree_translator/main.cpp b/utils/value_tree_translator/main.cpp new file mode 100644 index 00000000..5ee75a1d --- /dev/null +++ b/utils/value_tree_translator/main.cpp @@ -0,0 +1,241 @@ +/* + PIP - Platform Independent Primitives + ValueTree translator + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "picli.h" +#include "pidir.h" +#include "pifile.h" +#include "piiostream.h" +#include "pijson.h" +#include "pivaluetree.h" +#include "pivaluetree_conversions.h" + +#include + +using namespace PICoutManipulators; +using Attribute = PIValueTree::Attribute; + +const char help_string[] = "Read input files or entire directories as PIValueTree\n" + "according to extension, and create QtLinguist translation\n" + "file (*.ts). Extensions:\n" + " * conf - PIValueTreeConversions::fromText\n" + " * json - PIValueTreeConversions::fromJSON\n" + " * bin - binary deserialization\n" + "Output file can be translated by QtLinguist and used\n" + "by QAD PIValueTreeEdit widget to translate strings.\n" + ""; + +void header() { + piCout << Bold << "PIP ValueTree translator"; + piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; + piCout << Green << Bold << "Usage:" << Default + << "\"pip_vtt [-hHq] -l -o [] [] [...]\"" << NewLine; +} + +void usage() { + header(); + piCout << Green << Bold << "Details:"; + piCout << Bold << "Debug control"; + piCout << "-h " << Green << "- display this message and exit"; + piCout << "-H " << Green << "- display details help"; + piCout << "-q " << Green << "- quiet, no debug output to console"; + piCout << ""; + piCout << Bold << "Output control"; + piCout << "-l " << Green << "- translation language (e.g. en_US, ru_RU)"; + piCout << "-o " << Green << "- output file for translation (QtLinguist *.ts file)"; + piCout << ""; + piCout << Bold << "Input control"; + piCout << " " << Green << "- add file or dir translation"; +} + +void help() { + header(); + piCout << help_string; +} + +void printError(const PIString & msg) { + std::cerr << msg.data() << std::endl; +} + + +PISet strings; + +void gatherStrings(const PIValueTree & vt) { + const static PIStringList attrs({Attribute::prefix, Attribute::suffix}); + for (const auto & c: vt.children()) { + if (c.isArray()) return; + if (c.name().isNotEmpty()) strings << c.name(); + if (c.comment().isNotEmpty()) strings << c.comment(); + for (const auto & a: attrs) { + if (c.attributes().contains(a)) { + PIString sa = c.attributes().value(a).toString(); + if (sa.isNotEmpty()) strings << sa; + } + } + gatherStrings(c); + } +} + +const PIString context = "QAD::PIValueTreeEdit"; + +struct TSMessage { + PIString source; + PIString translation; + PIString type; +}; + +PIMap readTS(const PIString & path) { + PIMap ret; + PIFile f(path, PIIODevice::ReadOnly); + if (!f.isOpened()) return ret; + PIIOTextStream ts(&f); + TSMessage msg; + int phase = 0; + while (!ts.isEnd()) { + auto line = ts.readLine().trim(); + switch (phase) { + case 0: + if (line == "") phase = 1; + break; + case 1: + if (line.startsWith("")) { + line.cutLeft(6).cutRight(7); + if (line == context) phase = 2; + } + break; + case 2: + if (line == "") { + msg = {}; + phase = 3; + } + break; + case 3: + if (line == "") { + ret[msg.source] = msg; + phase = 2; + } else if (line.startsWith("")) { + line.cutLeft(8).cutRight(9); + msg.source = line; + } else if (line.startsWith("'); + while (trs.isNotEmpty()) { + PIString t = trs.takeCWord(); + trs.cutLeft(1); + PIString v = trs.takeRange('\"', '\"'); + if (t == "type") msg.type = v; + } + line.cutRight(14); + msg.translation = line; + } + break; + } + if (line == "") phase = 0; + } + return ret; +} + + +int main(int argc, char * argv[]) { + PICLI cli(argc, argv); + // piCout << cli.rawArguments(); + cli.setOptionalArgumentsCount(-1); + cli.addArgument("output", true); + cli.addArgument("language", true); + cli.addArgument("help"); + cli.addArgument("Help"); + cli.addArgument("quiet"); + if (cli.hasArgument("Help")) { + help(); + return 0; + } + if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.argumentValue("language").isEmpty() || + cli.optionalArguments().isEmpty()) { + usage(); + return 0; + } + piDebug = !cli.hasArgument("quiet"); + PIString out_path = cli.argumentValue("output"); + + PIStringList files; + const static PIStringList ext({"conf", "json", "bin"}); + for (const PIString & a: cli.optionalArguments()) { + if (PIDir::isExists(a)) { + auto dl = PIDir(a).allEntries(); + for (const auto & i: dl) { + if (!i.isFile()) continue; + if (ext.contains(i.extension().toLowerCase().trim())) files << i.path; + } + } else { + if (PIFile::isExists(a)) files << a; + } + } + + + piCout << Cyan << Bold << "Read" << files.size_s() << "files ..."; + for (const auto & p: files) { + PIString ext = PIFile::FileInfo(p).extension().toLowerCase().trim(); + PIFile f(p, PIIODevice::ReadOnly); + if (ext == "conf") gatherStrings(PIValueTreeConversions::fromText(PIString::fromUTF8(f.readAll()))); + if (ext == "json") gatherStrings(PIValueTreeConversions::fromJSON(PIJSON::fromJSON(PIString::fromUTF8(f.readAll())))); + if (ext == "bin") gatherStrings(piDeserialize(f.readAll())); + } + piCout << Cyan << Bold << "Reading done"; + + + piCout << Cyan << Bold << "Reading ts file ..."; + + auto old = readTS(out_path); + + piCout << Cyan << Bold << "Reading done"; + + + piCout << Cyan << Bold << "Writing ts file ..."; + + PIFile outf(out_path, PIIODevice::ReadWrite); + if (!outf.isOpened()) { + printError("Can`t open \"" + outf.path() + "\"!"); + return 1; + } + outf.clear(); + PIIOTextStream ts(&outf); + ts << "\n"; + ts << "\n"; + ts << "\n"; + ts << "\n"; + ts << " " << context << "\n"; + for (const auto & s: strings) { + ts << " \n"; + ts << " " << s.first << "\n"; + ts << " " << m.translation << "\n"; + ts << " \n"; + } + ts << "\n"; + ts << "\n"; + + piCout << Cyan << Bold << "Writing done"; + + + return 0; +}