From 6bbb4d997102169747b7bc80827b4978c3ddf764 Mon Sep 17 00:00:00 2001 From: shenleban tongying Date: Sun, 30 Apr 2023 00:31:49 -0400 Subject: [PATCH] feat(metadata): abstract metadata loader --- goldendict.pro | 2 ++ src/metadata.cc | 33 +++++++++++++++++++++++++++++++++ src/metadata.hh | 19 +++++++++++++++++++ src/ui/groups_widgets.cc | 33 +++++++++------------------------ website/docs/manage_groups.md | 6 +++--- 5 files changed, 66 insertions(+), 27 deletions(-) create mode 100644 src/metadata.cc create mode 100644 src/metadata.hh diff --git a/goldendict.pro b/goldendict.pro index 8f91b9f3..65d9c010 100644 --- a/goldendict.pro +++ b/goldendict.pro @@ -363,6 +363,7 @@ HEADERS += \ src/keyboardstate.hh \ src/langcoder.hh \ src/language.hh \ + src/metadata.hh \ src/multimediaaudioplayer.hh \ src/parsecmdline.hh \ src/resourceschemehandler.hh \ @@ -485,6 +486,7 @@ SOURCES += \ src/langcoder.cc \ src/language.cc \ src/main.cc \ + src/metadata.cc \ src/multimediaaudioplayer.cc \ src/parsecmdline.cc \ src/resourceschemehandler.cc \ diff --git a/src/metadata.cc b/src/metadata.cc new file mode 100644 index 00000000..c9060c81 --- /dev/null +++ b/src/metadata.cc @@ -0,0 +1,33 @@ +#include "metadata.hh" +#include "toml.hpp" +#include + +std::optional< Metadata::result > Metadata::load( std::string_view filepath ) +{ + // by default, the optional will be initialized as std::nullopt + Metadata::result result{}; + toml::table tbl; + + try { + tbl = toml::parse_file( filepath ); + } + catch ( toml::parse_error & e ) { + qWarning()<< "Failed to load metadata: " << QString::fromUtf8(filepath.data(),filepath.size()) + << "Reason:" << e.what(); + + return std::nullopt; + } + + if ( toml::array * categories = tbl.get_as< toml::array >( "categories" ) ) { + // result.categories is an optional, it exists, but the vector does not, so we have to create one here + result.categories.emplace(); + for ( auto & el : *categories ) { + if ( el.is_string() ) { + result.categories.value().emplace_back( std::move( *el.value_exact< std::string >() ) ); + } + } + } + + result.name = tbl[ "metadata" ][ "name" ].value_exact< std::string >(); + return result; +} diff --git a/src/metadata.hh b/src/metadata.hh new file mode 100644 index 00000000..5605dfe9 --- /dev/null +++ b/src/metadata.hh @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include + +namespace Metadata { + +/** + * Represent the metadata.toml beside the dictionary files + */ +struct result +{ + std::optional< std::vector< std::string > > categories; + std::optional< std::string > name; +}; + +[[nodiscard]] std::optional< Metadata::result > load( std::string_view filepath ); + +} // namespace Metadata diff --git a/src/ui/groups_widgets.cc b/src/ui/groups_widgets.cc index f71f2af5..c6b03fcc 100644 --- a/src/ui/groups_widgets.cc +++ b/src/ui/groups_widgets.cc @@ -7,7 +7,7 @@ #include "config.hh" #include "langcoder.hh" #include "language.hh" -#include "toml.hpp" +#include "metadata.hh" //#include "initializing.hh" @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -904,30 +903,16 @@ void DictGroupsWidget::groupsByMetadata() continue; auto filePath = Utils::Path::combine( baseDir, "metadata.toml" ); - if ( !QFile::exists( filePath ) ) { - qDebug() << "the dictionary folder:" << baseDir << " contain no metadata.toml"; - continue; - } - try { - auto config = toml::parse_file( filePath.toStdString() ); - toml::array * categories = config.get_as< toml::array >( "category" ); - if ( !categories ) { - continue; - } - categories->for_each( [ &groupToDicts, &dict ]( auto && elem ) { - if ( elem.is_string() ) { - auto group = QString::fromStdString( elem.as_string()->get() ).trimmed(); - - if ( group.isEmpty() ) - return; - - groupToDicts.insert( group, dict ); + auto dictMetaData = Metadata::load( filePath.toStdString() ); + if ( dictMetaData && dictMetaData->categories ) { + for ( const auto & category : dictMetaData->categories.value() ) { + auto group = QString::fromStdString( category ).trimmed(); + if ( group.isEmpty() ) { + continue; } - } ); - } - catch ( toml::parse_error & e ) { - qWarning() << "can not open the metadata.toml" << e.what(); + groupToDicts.insert( group, dict ); + } } } diff --git a/website/docs/manage_groups.md b/website/docs/manage_groups.md index c7d538a4..28e6614c 100644 --- a/website/docs/manage_groups.md +++ b/website/docs/manage_groups.md @@ -80,7 +80,7 @@ The `metadata.toml` should be placed beside dictionary files. One `metadata.toml The metadata file uses [TOML](https://toml.io) format. ```toml -category = [ "English", "Russian", "Chinese" ] +categories = [ "English", "Russian", "Chinese" ] # the following fields have not supported yet. [metadata] @@ -108,12 +108,12 @@ For example, The content of the metadata `(A)` is ```toml -category = ["en-zh", "汉英词典"] +categories = ["en-zh", "汉英词典"] ``` The content of the metadata `(B)` is ```toml -category = ["图片词典", "en-zh", "汉英词典"] +categories = ["图片词典", "en-zh", "汉英词典"] ``` The structure above will be auto grouped into three groups: