opt: add group by metadata

close #612
This commit is contained in:
xiaoyifang 2023-04-29 14:59:19 +08:00
parent 50cf0a948e
commit 94759ffb58
16 changed files with 17593 additions and 13 deletions

View file

@ -161,7 +161,9 @@ target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
${PROJECT_SOURCE_DIR}/src/
${PROJECT_SOURCE_DIR}/src/common
${PROJECT_SOURCE_DIR}/src/dict
${PROJECT_SOURCE_DIR}/src/ui)
${PROJECT_SOURCE_DIR}/src/ui
${PROJECT_SOURCE_DIR}/thirdparty/tomlplusplus
)
if (WITH_FFMPEG_PLAYER)

View file

@ -35,6 +35,7 @@ CONFIG( release, debug|release ) {
INCLUDEPATH += ./src/
INCLUDEPATH += ./src/ui # for compiled .ui files to find headers
INCLUDEPATH += ./src/common
INCLUDEPATH += ./thirdparty/tomlplusplus
QT += core \
gui \
@ -400,6 +401,7 @@ HEADERS += \
src/wordfinder.hh \
src/wordlist.hh \
src/zipfile.hh \
thirdparty/tomlplusplus/toml.hpp
FORMS += $$files(src/ui/*.ui)

View file

@ -632,6 +632,26 @@ between classic and school orthography in cyrillic)</source>
<source>Combine groups by target language to &quot;-&gt;%1&quot;</source>
<translation>&quot;-&gt;%1&quot;</translation>
</message>
<message>
<location filename="../src/ui/groups_widgets.cc" line="785"/>
<source>Auto group by folder failed.</source>
<translation></translation>
</message>
<message>
<location filename="../src/ui/groups_widgets.cc" line="786"/>
<source>The parent directory of %1 can be reached.</source>
<translation> %1 </translation>
</message>
<message>
<location filename="../src/ui/groups_widgets.cc" line="791"/>
<source>Are you sure you want to generate a set of groups based on containing folders?</source>
<translation></translation>
</message>
<message>
<location filename="../src/ui/groups_widgets.cc" line="892"/>
<source>Are you sure you want to generate a set of groups based on metadata.txt?</source>
<translation>metadata.txt生成分组吗</translation>
</message>
<message>
<location filename="../src/ui/groups_widgets.cc" line="886"/>
<source>Make two-side translate group &quot;%1-%2-%1&quot;</source>

View file

@ -145,6 +145,16 @@ wstring applyPunctOnly( wstring const & in )
return out;
}
QString applyPunctOnly( QString const & in )
{
QString out;
for ( auto c : in )
if ( !c.isPunct() )
out.push_back( c );
return out;
}
wstring applyWhitespaceOnly( wstring const & in )
{
wchar const * nextChar = in.data();

View file

@ -46,8 +46,8 @@ wstring applyDiacriticsOnly( wstring const & );
/// Applies only punctuation folding algorithm.
wstring applyPunctOnly( wstring const & );
/// Applies only whitespace folding algorithm.
QString applyPunctOnly( QString const & in );
/// Applies only whitespace folding algorithm.
wstring applyWhitespaceOnly( wstring const & );
/// Applies only whitespace&punctuation folding algorithm.

View file

@ -2,7 +2,6 @@
#include <QDir>
#include <QPalette>
#include <QStyle>
#include <QDesktopServices>
#include <QMessageBox>
QString Utils::Path::combine(const QString& path1, const QString& path2)

View file

@ -170,7 +170,7 @@ vector< wstring > Class::getAlternateWritings( wstring const & )
return vector< wstring >();
}
QString Class::getContainingFolder()
QString Class::getContainingFolder() const
{
if ( !dictionaryFiles.empty() ) {
return QFileInfo( QString::fromStdString( dictionaryFiles[ 0 ] ) ).absolutePath();

View file

@ -313,7 +313,7 @@ public:
{ return dictionaryFiles; }
/// Get the main folder that contains the dictionary, without the ending separator .
QString getContainingFolder();
QString getContainingFolder() const;
/// Returns the dictionary's full name, utf8.
virtual string getName() noexcept=0;

View file

@ -12,7 +12,6 @@
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
#include <QtCore5Compat/QRegExp>
#endif
#include <cctype>
#include <QLocale>
LangCoder langCoder;

View file

@ -55,6 +55,7 @@ Groups::Groups( QWidget * parent,
connect( ui.autoGroups, &QAbstractButton::clicked, this, &Groups::addAutoGroups );
connect( ui.autoGroupsFolders, &QAbstractButton::clicked, this, &Groups::addAutoGroupsByFolders );
connect( ui.groupMetadata, &QAbstractButton::clicked, this, &Groups::groupsByMetadata );
ui.dictionaries->setContextMenuPolicy( Qt::CustomContextMenu );
connect( ui.dictionaries, &QWidget::customContextMenuRequested, this, &Groups::showDictInfo );
@ -131,6 +132,10 @@ void Groups::addAutoGroupsByFolders() {
countChanged();
}
void Groups::groupsByMetadata() {
ui.groups->groupsByMetadata();
countChanged();
}
void Groups::renameCurrent()
{
int current = ui.groups->currentIndex();

View file

@ -7,7 +7,6 @@
#include "ui_groups.h"
#include "config.hh"
#include "dict/dictionary.hh"
#include "groups_widgets.hh"
#include <QToolButton>
#include <QMenu>
@ -54,6 +53,7 @@ private slots:
void addAutoGroups();
/// by Containing Folder
void addAutoGroupsByFolders();
void groupsByMetadata();
void showDictInfo( const QPoint & pos );
void fillGroupsMenu();

View file

@ -200,7 +200,7 @@
<string>Create language-based groups</string>
</property>
<property name="text">
<string>Auto groups by Languages</string>
<string>Group by Languages</string>
</property>
</widget>
</item>
@ -210,7 +210,14 @@
<string>Create folder-based groups.</string>
</property>
<property name="text">
<string>Auto groups by Folders</string>
<string>Group by Folders</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="groupMetadata">
<property name="text">
<string>Group by Metadata</string>
</property>
</widget>
</item>

View file

@ -7,7 +7,7 @@
#include "config.hh"
#include "langcoder.hh"
#include "language.hh"
#include "toml.hpp"
//#include "initializing.hh"
@ -863,6 +863,11 @@ void DictGroupsWidget::addAutoGroupsByFolders()
// create and insert groups
// modifying user's groups begins here
addGroupBasedOnMap( groupToDicts );
}
void DictGroupsWidget::addGroupBasedOnMap( const QMultiMap<QString, sptr<Dictionary::Class>> & groupToDicts )
{
for ( const auto & group : groupToDicts.uniqueKeys() ) {
if ( count() != 0 ) {
setCurrentIndex( count() - 1 );
@ -871,12 +876,62 @@ void DictGroupsWidget::addAutoGroupsByFolders()
addUniqueGroup( group );
DictListModel * model = getCurrentModel();
for ( const auto& dict : groupToDicts.values( group ) ) {
for ( const auto & dict : groupToDicts.values( group ) ) {
model->addRow( QModelIndex(), dict );
}
}
}
void DictGroupsWidget::groupsByMetadata()
{
if ( activeDicts->empty() ) {
return;
}
if ( QMessageBox::information( this,
tr( "Confirmation" ),
tr( "Are you sure you want to generate a set of groups based on metadata.toml?" ),
QMessageBox::Yes,
QMessageBox::Cancel )
!= QMessageBox::Yes ) {
return;
}
// map from GroupName to dicts
QMultiMap< QString, sptr< Dictionary::Class > > groupToDicts;
for ( const auto & dict : *activeDicts ) {
auto baseDir = dict->getContainingFolder();
if ( baseDir.isEmpty() )
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 ) {
auto group = QString::fromStdString( elem.as_string()->value_or( "" ) ).trimmed();
if ( group.isEmpty() )
return;
groupToDicts.insert( group, dict );
} );
}catch( toml::parse_error & e) {
qWarning() << "can not open the metadata.toml" << e.what();
}
}
// create and insert groups
// modifying user's groups begins here
addGroupBasedOnMap( groupToDicts );
}
QString DictGroupsWidget::getCurrentGroupName() const
{

View file

@ -166,6 +166,9 @@ public:
/// auto grouping by containning folder
void addAutoGroupsByFolders();
void addGroupBasedOnMap( const QMultiMap<QString, sptr<Dictionary::Class>> & groupToDicts );
void groupsByMetadata();
/// Returns currently chosen group's name
QString getCurrentGroupName() const;

17414
thirdparty/tomlplusplus/toml.hpp vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,14 @@
Here you can create and edit dictionary groups. To add dictionary into group just drag it into groups window, to remove it drag it back to dictionaries list. Also you can press "Auto groups button" to automatically create groups for all presented in dictionaries list language directions. Via context menu of such automatically created groups you can execute additional dictionaries grouping by source or target language and combine dictionaries in more large groups.
## Group by dictionary language
When group by dictionary language,the language is taken from dictionary's built-in metadata which has been embed when creating dictionary.
If the language is not present in the dictionary, it will try to detect the language from dictionary file name.
Then use the founded language to create dictionary groups.
## Auto groups by folders
Click the "Auto groups by folders" will group your dicts based on folder structure.
@ -51,4 +60,59 @@ More levels of folder nesting are not supported.
│ └─Japanese <- Group
| └─DictB <- Dict Files's container folder
| └─ DictB Files
```
```
## group by metadata.toml
Click the "group by metadata" will group your dicts based on metadata.toml file.
the location of the metadata file is at the same location as the dictionary.
The structure of the metadata file use [toml](https://toml.io) format
```
category = [ "english", "yellow", "green" ]
# the following fields have not supported yet.
[metadata]
name = "New Name"
langfrom = "English"
langto = "Russian"
```
For example,
```
.
English<>Chinese
── Cambridge
├── Cambridge.dict.dz
├── Cambridge.idx
├── Cambridge.info
└── Cambridge.syn
└── metadata.toml (A)
── Collins
├── Collins.dsl
└── res.zip
└── metadata.toml (B)
```
The content of the metadata(A) is
```
category=["en-zh","汉英词典"]
```
The content of the metadata(B) is
```
category=["图片词典","en-zh","汉英词典"]
```
the structure below will be auto grouped into three groups:
* `en-zh` with `Cambridge`, `Collins`
* `图片词典` with `Collins`
* `汉英词典` with `Cambridge`,`Collins`
Note: you can configure only the dictionaries you like .