Skip to content

Commit

Permalink
feat: support more formats for custom dictionary icon: svg, gif, webp…
Browse files Browse the repository at this point in the history
…, jpeg (xiaoyifang#2139)
  • Loading branch information
shenlebantongying authored Feb 9, 2025
1 parent d083fe2 commit c1d7564
Show file tree
Hide file tree
Showing 25 changed files with 79 additions and 105 deletions.
1 change: 1 addition & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Checks: >
-performance-enum-size,
-readability-else-after-return,
-readability-function-cognitive-complexity,
-readability-use-anyofallof,
-readability-identifier-length,
-readability-magic-numbers,
CheckOptions:
Expand Down
5 changes: 1 addition & 4 deletions src/dict/aard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,7 @@ void AardDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( QString::fromStdString( getDictionaryFilenames()[ 0 ] ) );

// Remove the extension
fileName.chop( 3 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_aard.png" );
}
Expand Down
4 changes: 1 addition & 3 deletions src/dict/bgl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,8 @@ void BglDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( QString::fromStdString( getDictionaryFilenames()[ 0 ] ) );

// Remove the extension
fileName.chop( 3 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
if ( idxHeader.iconSize ) {

// Try loading icon now
Expand Down
5 changes: 1 addition & 4 deletions src/dict/dictdfiles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,7 @@ void DictdDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( QString::fromStdString( getDictionaryFilenames()[ 0 ] ) );

// Remove the extension
fileName.chop( 5 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_dictd.png" );
}
Expand Down
69 changes: 33 additions & 36 deletions src/dict/dictionary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -248,48 +248,45 @@ int Class::getOptimalIconSize()
return 64 * qGuiApp->devicePixelRatio();
}

bool Class::loadIconFromFile( QString const & _filename, bool isFullName )
{
QFileInfo info;
QString fileName( _filename );

if ( isFullName ) {
info = QFileInfo( fileName );
}
else {
fileName += "bmp";
info = QFileInfo( fileName );
if ( !info.isFile() ) {
fileName.chop( 3 );
fileName += "png";
info = QFileInfo( fileName );
}
if ( !info.isFile() ) {
fileName.chop( 3 );
fileName += "jpg";
info = QFileInfo( fileName );
}
if ( !info.isFile() ) {
fileName.chop( 3 );
fileName += "ico";
info = QFileInfo( fileName );
bool Class::loadIconFromFileName( QString const & mainDictFileName )
{
const QFileInfo info( mainDictFileName );
const QString basename = info.baseName();
QDir dir = info.absoluteDir();

dir.setFilter( QDir::Files );
dir.setNameFilters( QStringList() << basename + ".bmp" //
<< basename + ".png" //
<< basename + ".jpg" //
<< basename + ".ico" // below are GD-ng only
<< basename + ".jpeg" //
<< basename + ".gif" //
<< basename + ".webp" //
<< basename + ".svgz" //
<< basename + ".svg" );

for ( const auto & f : dir.entryInfoList() ) {
if ( loadIconFromFilePath( f.absoluteFilePath() ) ) {
return true;
}
}
return false;
}

if ( info.isFile() ) {
auto iconSize = getOptimalIconSize();
QPixmap img( fileName );

if ( !img.isNull() ) {
// Load successful
bool Class::loadIconFromFilePath( QString const & filename )
{
auto iconSize = getOptimalIconSize();
QImage img( filename );

auto result = img.scaled( { iconSize, iconSize }, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation );
dictionaryIcon = QIcon( result );
if ( img.isNull() ) {
return false;
}
else {
auto result = img.scaled( { iconSize, iconSize }, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation );
dictionaryIcon = QIcon( QPixmap::fromImage( result ) );

return !dictionaryIcon.isNull();
}
return !dictionaryIcon.isNull();
}
return false;
}

bool Class::loadIconFromText( const QString & iconUrl, QString const & text )
Expand Down
8 changes: 5 additions & 3 deletions src/dict/dictionary.hh
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,11 @@ protected:

static int getOptimalIconSize();

// Load icon from filename directly if isFullName == true
// else treat filename as name without extension
bool loadIconFromFile( QString const & filename, bool isFullName = false );
/// Try load icon based on the main dict file name
bool loadIconFromFileName( QString const & mainDictFileName );
/// Load an icon using a full image file path
bool loadIconFromFilePath( QString const & filename );
/// Generate icon based on a text
bool loadIconFromText( const QString & iconUrl, QString const & text );

static QString getAbbrName( QString const & text );
Expand Down
2 changes: 1 addition & 1 deletion src/dict/dictserver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ void DictServerDictionary::loadIcon() noexcept
if ( !icon.isEmpty() ) {
QFileInfo fInfo( QDir( Config::getConfigDir() ), icon );
if ( fInfo.isFile() ) {
loadIconFromFile( fInfo.absoluteFilePath(), true );
loadIconFromFilePath( fInfo.absoluteFilePath() );
}
}
if ( dictionaryIcon.isNull() ) {
Expand Down
2 changes: 1 addition & 1 deletion src/dict/dsl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ void DslDictionary::loadIcon() noexcept
fileName.chop( 3 );
}

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_dsl.png" );
}
Expand Down
6 changes: 3 additions & 3 deletions src/dict/epwing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,11 @@ void EpwingDictionary::loadIcon() noexcept
if ( dictionaryIconLoaded )
return;

QString fileName = QString::fromStdString( getDictionaryFilenames()[ 0 ] ) + QDir::separator()
+ eBook.getCurrentSubBookDirectory() + ".";
QString fileName =
QString::fromStdString( getDictionaryFilenames()[ 0 ] ) + QDir::separator() + eBook.getCurrentSubBookDirectory();

if ( !fileName.isEmpty() )
loadIconFromFile( fileName );
loadIconFromFileName( fileName );

if ( dictionaryIcon.isNull() ) {
// Load failed -- use default icons
Expand Down
10 changes: 1 addition & 9 deletions src/dict/gls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -476,15 +476,7 @@ void GlsDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
if ( fileName.endsWith( ".gls.dz", Qt::CaseInsensitive ) ) {
fileName.chop( 6 );
}
else {
fileName.chop( 3 );
}

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icon
dictionaryIcon = QIcon( ":/icons/icon32_gls.png" );
}
Expand Down
5 changes: 1 addition & 4 deletions src/dict/hunspell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,7 @@ void HunspellDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 3 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_hunspell.png" );
}
Expand Down
5 changes: 1 addition & 4 deletions src/dict/lsa.cc
Original file line number Diff line number Diff line change
Expand Up @@ -488,10 +488,7 @@ void LsaDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 3 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/lsasound.png" );
}
Expand Down
4 changes: 1 addition & 3 deletions src/dict/mdx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -816,11 +816,9 @@ void MdxDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 3 );
QString text = QString::fromStdString( dictionaryName );

if ( !loadIconFromFile( fileName ) && !loadIconFromText( ":/icons/mdict-bg.png", text ) ) {
if ( !loadIconFromFileName( fileName ) && !loadIconFromText( ":/icons/mdict-bg.png", text ) ) {
// Use default icons
dictionaryIcon = QIcon( ":/icons/mdict.png" );
}
Expand Down
2 changes: 1 addition & 1 deletion src/dict/mediawiki.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void MediaWikiDictionary::loadIcon() noexcept
if ( !icon.isEmpty() ) {
QFileInfo fInfo( QDir( Config::getConfigDir() ), icon );
if ( fInfo.isFile() ) {
loadIconFromFile( fInfo.absoluteFilePath(), true );
loadIconFromFilePath( fInfo.absoluteFilePath() );
}
}
if ( dictionaryIcon.isNull() ) {
Expand Down
2 changes: 1 addition & 1 deletion src/dict/programs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void ProgramsDictionary::loadIcon() noexcept
if ( !prg.iconFilename.isEmpty() ) {
QFileInfo fInfo( QDir( Config::getConfigDir() ), prg.iconFilename );
if ( fInfo.isFile() ) {
loadIconFromFile( fInfo.absoluteFilePath(), true );
loadIconFromFilePath( fInfo.absoluteFilePath() );
}
}
if ( dictionaryIcon.isNull() ) {
Expand Down
5 changes: 1 addition & 4 deletions src/dict/sdict.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,7 @@ void SdictDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 3 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_sdict.png" );
}
Expand Down
4 changes: 1 addition & 3 deletions src/dict/slob.cc
Original file line number Diff line number Diff line change
Expand Up @@ -721,10 +721,8 @@ void SlobDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 4 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_slob.png" );
}
Expand Down
2 changes: 1 addition & 1 deletion src/dict/sounddir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ void SoundDirDictionary::loadIcon() noexcept
if ( !iconFilename.isEmpty() ) {
const QFileInfo fInfo( QDir( Config::getConfigDir() ), iconFilename );
if ( fInfo.isFile() ) {
loadIconFromFile( fInfo.absoluteFilePath(), true );
loadIconFromFilePath( fInfo.absoluteFilePath() );
}
}
if ( dictionaryIcon.isNull() ) {
Expand Down
5 changes: 1 addition & 4 deletions src/dict/stardict.cc
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,7 @@ void StardictDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 3 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/icon32_stardict.png" );
}
Expand Down
2 changes: 1 addition & 1 deletion src/dict/voiceengines.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ void VoiceEnginesDictionary::loadIcon() noexcept
if ( !voiceEngine.iconFilename.isEmpty() ) {
QFileInfo fInfo( QDir( Config::getConfigDir() ), voiceEngine.iconFilename );
if ( fInfo.isFile() )
loadIconFromFile( fInfo.absoluteFilePath(), true );
loadIconFromFilePath( fInfo.absoluteFilePath() );
}
if ( dictionaryIcon.isNull() )
dictionaryIcon = QIcon( ":/icons/text2speech.svg" );
Expand Down
2 changes: 1 addition & 1 deletion src/dict/website.cc
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ void WebSiteDictionary::loadIcon() noexcept
if ( !iconFilename.isEmpty() ) {
QFileInfo fInfo( QDir( Config::getConfigDir() ), iconFilename );
if ( fInfo.isFile() ) {
loadIconFromFile( fInfo.absoluteFilePath(), true );
loadIconFromFilePath( fInfo.absoluteFilePath() );
}
}
if ( dictionaryIcon.isNull()
Expand Down
6 changes: 5 additions & 1 deletion src/dict/xdxf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,11 @@ void XdxfDictionary::loadIcon() noexcept
}

if ( info.isFile() ) {
loadIconFromFile( fileName, true );
loadIconFromFilePath( fileName );
}

if ( dictionaryIcon.isNull() ) {
loadIconFromFileName( fileName );
}

if ( dictionaryIcon.isNull() ) {
Expand Down
5 changes: 2 additions & 3 deletions src/dict/zim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,8 @@ void ZimDictionary::loadIcon() noexcept

// Try to load Original GD's user provided icon
QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );
// Remove the extension
fileName.chop( 3 );
if ( loadIconFromFile( fileName ) ) {

if ( loadIconFromFileName( fileName ) ) {
dictionaryIconLoaded = true;
return;
}
Expand Down
5 changes: 1 addition & 4 deletions src/dict/zipsounds.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,7 @@ void ZipSoundsDictionary::loadIcon() noexcept

QString fileName = QDir::fromNativeSeparators( getDictionaryFilenames()[ 0 ].c_str() );

// Remove the extension
fileName.chop( 4 );

if ( !loadIconFromFile( fileName ) ) {
if ( !loadIconFromFileName( fileName ) ) {
// Load failed -- use default icons
dictionaryIcon = QIcon( ":/icons/zipsound.svg" );
}
Expand Down
18 changes: 12 additions & 6 deletions website/docs/dictformats.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,23 @@ GoldenDict-ng does not provide any dictionary modification functionality.

To convert between formats, try tools like [pyglossary](https://github.com/ilius/pyglossary).

### Individual Dictionary Icons
### Custom Dictionary Icon

Every local dictionary can have individual icon. BMP, PNG, JPG or ICO files can be used for this icon.
Every local dictionary can have a custom icon.
Supported formats are PNG, JPEG, GIF, SVG, WebP, ICO and BMP.

For Babylon, StarDict, DictD, ABBYY Lingvo, AardDictionary, SDictionary, Zim, MDict, Lsa, Zips, Slob, Gls dictionaries such graphics file must be named by main dictionary file name and places beside one. That is if main file of your dictionary, for example, named "My_best_dictionary.dsl" therefore icon file must be named "My_best_dictionary.bmp" (.png, .jpg etc.).
For most dictionary formats, a dictionary's icon file should have the same basename as the main dictionary file and be placed beside the main dictionary file. For example:

For XDXF dictionaries, the icon file must be named "icon16.png" (for 16х16 images) or "icon32.png" (for 32х32 images) or "dict.bmp" and placed into the dictionary folder.
```
.
├── My_best_dictionary.mdx <- the main dictionary file
└── My_best_dictionary.svg <- the icon
```

For Epwing dictionaries icon file must be named by name of folder with dictionary data beside "catalogs" file (a few folders can be presented, every folder is separate dictionary) and placed beside "catalogs" file.
For XDXF, GD will prioritize to use `icon16.png`, `icon32.png` or `dict.bmp` in the dictionary folder as icon.

For Epwing, the icon file should be placed beside the `catalogs` file and have the same name as the parent folder that contains `catalogs` file.

If individual icon is not presented the default icon for this type of dictionaries will be used.

### Stardict

Expand Down

0 comments on commit c1d7564

Please sign in to comment.