feat(metadata): abstract metadata loader

This commit is contained in:
shenleban tongying 2023-04-30 00:31:49 -04:00 committed by xiaoyifang
parent 77c919f7dd
commit 6bbb4d9971
5 changed files with 66 additions and 27 deletions

View file

@ -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 \

33
src/metadata.cc Normal file
View file

@ -0,0 +1,33 @@
#include "metadata.hh"
#include "toml.hpp"
#include <QDebug>
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;
}

19
src/metadata.hh Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include <QStringView>
#include <optional>
#include <vector>
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

View file

@ -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 <QDir>
#include <QIcon>
#include <QMap>
#include <QMultiMap>
#include <QVector>
#include <QFileInfo>
#include <QFileDialog>
@ -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 );
}
}
}

View file

@ -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: