Merge branch 'staged' into dev

This commit is contained in:
YiFang Xiao 2023-08-30 19:14:52 +08:00
commit 2525885b92
20 changed files with 214 additions and 59 deletions

View file

@ -215,7 +215,8 @@ jobs:
Windows users can use either `****-installer.exe` (for installer) or `****.zip` (unzip and run).
The `goldendict.exe` can be dropped into previous installation's folder (if dependencies aren't changed).
Linux users can use AppImages.
Linux users can use AppImages or Flatpak.
https://flathub.org/zh-Hans/apps/io.github.xiaoyifang.goldendict_ng
macOS users can use `.dmg` installer.

View file

@ -76,10 +76,8 @@ jobs:
brew install create-dmg
brew install xapian
brew install libzim
# brew reinstall icu4c
brew install dylibbundler
find /opt -name libicudata.72.dylib
find /usr/local -name libicudata.72.dylib
find /opt -name libzstd.1.dylib
find /usr/local -name libzstd.1.dylib
brew install dylibbundler
@ -232,7 +230,8 @@ jobs:
Windows users can use either `****-installer.exe` (for installer) or `****.zip` (unzip and run).
The `goldendict.exe` can be dropped into previous installation's folder (if dependencies aren't changed).
Linux users can use AppImages.
Linux users can use AppImages or Flatpak.
https://flathub.org/zh-Hans/apps/io.github.xiaoyifang.goldendict_ng
macOS users can use `.dmg` installer.

View file

@ -190,7 +190,8 @@ jobs:
Windows users can use either `****-installer.exe` (for installer) or `****.zip` (unzip and run).
The `goldendict.exe` can be dropped into previous installation's folder (if dependencies aren't changed).
Linux users can use AppImages.
Linux users can use AppImages or Flatpak.
https://flathub.org/zh-Hans/apps/io.github.xiaoyifang.goldendict_ng
macOS users can use `.dmg` installer.

View file

@ -177,7 +177,8 @@ jobs:
Windows users can use either `****-installer.exe` (for installer) or `****.zip` (unzip and run).
The `goldendict.exe` can be dropped into previous installation's folder (if dependencies aren't changed).
Linux users can use AppImages.
Linux users can use AppImages or Flatpak.
https://flathub.org/zh-Hans/apps/io.github.xiaoyifang.goldendict_ng
macOS users can use `.dmg` installer.

View file

@ -249,7 +249,8 @@ jobs:
Windows users can use either `****-installer.exe` (for installer) or `****.zip` (unzip and run).
The `goldendict.exe` can be dropped into previous installation's folder (if dependencies aren't changed).
Linux users can use AppImages.
Linux users can use AppImages or Flatpak.
https://flathub.org/zh-Hans/apps/io.github.xiaoyifang.goldendict_ng
macOS users can use `.dmg` installer.

View file

@ -226,7 +226,8 @@ jobs:
Windows users can use either `****-installer.exe` (for installer) or `****.zip` (unzip and run).
The `goldendict.exe` can be dropped into previous installation's folder (if dependencies aren't changed).
Linux users can use AppImages.
Linux users can use AppImages or Flatpak.
https://flathub.org/zh-Hans/apps/io.github.xiaoyifang.goldendict_ng
macOS users can use `.dmg` installer.

View file

@ -5,7 +5,7 @@
<name>About</name>
<message>
<source>About</source>
<translation>Über</translation>
<translation>Info</translation>
</message>
<message>
<source>GoldenDict-ng dictionary lookup program, version </source>
@ -13,7 +13,7 @@
</message>
<message>
<source>Licensed under GNU GPLv3 or later</source>
<translation>Lizensiert unter der GNU GPLv3 oder neuer</translation>
<translation>Lizenziert unter der GNU GPLv3 oder neuer</translation>
</message>
<message>
<source>Copy version info</source>
@ -21,7 +21,7 @@
</message>
<message>
<source>Copy dictionaries list</source>
<translation>Wörterbücher kopieren</translation>
<translation>Wörterbuchliste kopieren</translation>
</message>
<message>
<source>Credits:</source>
@ -36,7 +36,7 @@
<name>AnkiConnector</name>
<message>
<source>anki: can&apos;t create a card without a word</source>
<translation>anki: kann&apos;t eine Karte ohne Wort erstellen</translation>
<translation>Anki: eine Karte ohne Wort kann nicht erstellt werden</translation>
</message>
<message>
<source>Anki search: AnkiConnect is not enabled.</source>
@ -49,7 +49,7 @@
</message>
<message>
<source>anki: post to anki success</source>
<translation>anki: Beitrag zu anki Erfolg</translation>
<translation>Anki: Beitrag zu Anki erfolgreich</translation>
</message>
</context>
<context>

View file

@ -1220,16 +1220,26 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f
ChunkedStorage::Writer chunks( idx );
Epwing::Book::EpwingHeadword head;
dict.getFirstHeadword( head );
int wordCount = 0;
int articleCount = 0;
for ( ;; ) {
addWordToChunks( head, chunks, indexedWords, wordCount, articleCount );
if ( !dict.getNextHeadword( head ) )
break;
if ( dict.getFirstHeadword( head ) ) {
for ( ;; ) {
addWordToChunks( head, chunks, indexedWords, wordCount, articleCount );
if ( !dict.getNextHeadword( head ) )
break;
}
}
else {
//the book does not contain text,use menu instead if any.
if ( dict.getMenu( head ) ) {
auto candidateItems = dict.candidate( head.page, head.offset );
for ( Epwing::Book::EpwingHeadword word : candidateItems ) {
addWordToChunks( word, chunks, indexedWords, wordCount, articleCount );
}
}
else {
throw exEbLibrary( dict.errorString().toUtf8().data() );
}
}
dict.clearBuffers();

View file

@ -61,6 +61,7 @@ HookFunc( hook_mpeg );
HookFunc( hook_narrow_font );
HookFunc( hook_wide_font );
HookFunc( hook_reference );
HookFunc( hook_candidate );
const EB_Hook hooks[] = { { EB_HOOK_NEWLINE, hook_newline },
{ EB_HOOK_ISO8859_1, hook_iso8859_1 },
@ -89,6 +90,7 @@ const EB_Hook hooks[] = { { EB_HOOK_NEWLINE, hook_newline },
{ EB_HOOK_WIDE_FONT, hook_wide_font },
{ EB_HOOK_BEGIN_REFERENCE, hook_reference },
{ EB_HOOK_END_REFERENCE, hook_reference },
{ EB_HOOK_END_CANDIDATE_GROUP, hook_candidate },
{ EB_HOOK_NULL, NULL } };
const EB_Hook refHooks[] = {
@ -377,6 +379,21 @@ hook_reference( EB_Book * book, EB_Appendix *, void * container, EB_Hook_Code co
return EB_SUCCESS;
}
EB_Error_Code
hook_candidate( EB_Book * book, EB_Appendix *, void * container, EB_Hook_Code code, int, const unsigned int * argv )
{
EContainer * cn = static_cast< EContainer * >( container );
if ( cn->textOnly )
return EB_SUCCESS;
QByteArray str = cn->book->handleCandidate( code, argv );
if ( !str.isEmpty() )
eb_write_text( book, str.data(), str.size() );
return EB_SUCCESS;
}
// EpwingBook class
EpwingBook::EpwingBook():
@ -564,7 +581,7 @@ QString EpwingBook::createCacheDir( QString const & dirName )
if ( !info.exists() || !info.isDir() ) {
if ( !dir.mkdir( mainCacheDir ) ) {
gdWarning( "Epwing: can't create cache directory \"%s\"", mainCacheDir.toUtf8().data() );
return QString();
return {};
}
}
@ -573,7 +590,7 @@ QString EpwingBook::createCacheDir( QString const & dirName )
if ( !info.exists() || !info.isDir() ) {
if ( !dir.mkdir( cacheDir ) ) {
gdWarning( "Epwing: can't create cache directory \"%s\"", cacheDir.toUtf8().data() );
return QString();
return {};
}
}
return cacheDir;
@ -649,7 +666,7 @@ QString EpwingBook::title()
if ( codec_Euc )
return codec_Euc->toUnicode( buf );
return QString();
return {};
}
QString EpwingBook::copyright()
@ -657,7 +674,7 @@ QString EpwingBook::copyright()
error_string.clear();
if ( !eb_have_copyright( &book ) )
return QString();
return {};
EB_Position position;
EB_Error_Code ret = eb_copyright( &book, &position );
@ -671,9 +688,18 @@ QString EpwingBook::copyright()
return getText( position.page, position.offset, true );
}
QList< EpwingHeadword > EpwingBook::candidate( int page, int offset )
{
//clear candidateItems in getText;
candidateItems.clear();
getText( page, offset, false );
return candidateItems;
}
QString EpwingBook::getText( int page, int offset, bool text_only )
{
error_string.clear();
candidateItems.clear();
seekBookThrow( page, offset );
@ -701,7 +727,7 @@ QString EpwingBook::getText( int page, int offset, bool text_only )
if ( buf.length() > TextSizeLimit ) {
error_string = "Data too large";
currentPosition.page = 0;
return QString();
return {};
}
}
@ -822,7 +848,6 @@ QString EpwingBook::getPreviousTextWithLength( int page, int offset, int total,
return text;
}
void EpwingBook::getReferencesFromText( int page, int offset )
{
error_string.clear();
@ -872,15 +897,14 @@ EB_Error_Code EpwingBook::forwardText( EB_Position & startPos )
}
ret = eb_forward_text( &book, &appendix );
while ( ret == EB_ERR_END_OF_CONTENT ) {
ret = eb_tell_text( &book, &startPos );
if ( ret != EB_SUCCESS )
break;
while ( ret != EB_SUCCESS ) {
if ( startPos.page >= book.subbook_current->text.end_page )
return EB_ERR_END_OF_CONTENT;
startPos.offset += 2;
const auto offset = startPos.offset + 2;
startPos.offset = offset % EB_SIZE_PAGE;
startPos.page += offset / EB_SIZE_PAGE;
currentPosition = startPos;
ret = eb_seek_text( &book, &startPos );
@ -891,7 +915,7 @@ EB_Error_Code EpwingBook::forwardText( EB_Position & startPos )
return ret;
}
void EpwingBook::getFirstHeadword( EpwingHeadword & head )
bool EpwingBook::getFirstHeadword( EpwingHeadword & head )
{
error_string.clear();
@ -900,13 +924,15 @@ void EpwingBook::getFirstHeadword( EpwingHeadword & head )
EB_Error_Code ret = eb_text( &book, &pos );
if ( ret != EB_SUCCESS ) {
setErrorString( "eb_text", ret );
throw exEbLibrary( error_string.toUtf8().data() );
qWarning() << error_string;
return false;
}
ret = forwardText( pos );
if ( ret != EB_SUCCESS ) {
setErrorString( "forwardText", ret );
throw exEbLibrary( error_string.toUtf8().data() );
setErrorString( "getFirstHeadword", ret );
qWarning() << error_string;
return false;
}
eb_backward_text( &book, &appendix );
@ -914,7 +940,49 @@ void EpwingBook::getFirstHeadword( EpwingHeadword & head )
ret = eb_tell_text( &book, &pos );
if ( ret != EB_SUCCESS ) {
setErrorString( "eb_tell_text", ret );
throw exEbLibrary( error_string.toUtf8().data() );
qWarning() << error_string;
return false;
}
currentPosition = pos;
indexHeadwordsPosition = pos;
head.page = pos.page;
head.offset = pos.offset;
if ( !readHeadword( pos, head.headword, true ) ) {
qWarning() << error_string;
return false;
}
fixHeadword( head.headword );
allHeadwordPositions[ ( (uint64_t)pos.page ) << 32 | ( pos.offset ) ] = true;
return true;
}
bool EpwingBook::haveMenu()
{
error_string.clear();
int ret = eb_have_menu( &book );
return ret == 1;
}
bool EpwingBook::getMenu( EpwingHeadword & head )
{
error_string.clear();
if ( !haveMenu() ) {
return false;
}
EB_Position pos;
EB_Error_Code ret = eb_menu( &book, &pos );
if ( ret != EB_SUCCESS ) {
setErrorString( "getMenu", ret );
return false;
}
currentPosition = pos;
@ -924,19 +992,18 @@ void EpwingBook::getFirstHeadword( EpwingHeadword & head )
head.offset = pos.offset;
if ( !readHeadword( pos, head.headword, true ) )
throw exEbLibrary( error_string.toUtf8().data() );
return false;
fixHeadword( head.headword );
EWPos epos( pos.page, pos.offset );
allHeadwordPositions[ ( (uint64_t)pos.page ) << 32 | ( pos.offset ) ] = true;
return true;
}
bool EpwingBook::getNextHeadword( EpwingHeadword & head )
{
EB_Position pos;
// No queued positions - forward to next article
error_string.clear();
@ -965,8 +1032,10 @@ bool EpwingBook::getNextHeadword( EpwingHeadword & head )
head.page = pos.page;
head.offset = pos.offset;
if ( !readHeadword( pos, head.headword, true ) )
throw exEbLibrary( error_string.toUtf8().data() );
if ( !readHeadword( pos, head.headword, true ) ) {
qDebug() << "Epwing: ignore the following error=> " << error_string;
continue;
}
if ( head.headword.isEmpty() )
continue;
@ -1766,6 +1835,27 @@ QByteArray EpwingBook::handleReference( EB_Hook_Code code, const unsigned int *
return str.toUtf8();
}
QByteArray EpwingBook::handleCandidate( EB_Hook_Code code, const unsigned int * argv )
{
EpwingHeadword w_headword;
w_headword.headword = currentCandidate();
w_headword.page = argv[ 1 ];
w_headword.offset = argv[ 2 ];
candidateItems << w_headword;
return QByteArray{};
}
QString EpwingBook::currentCandidate()
{
const char * s = eb_current_candidate( &book );
if ( book.character_code == EB_CHARCODE_ISO8859_1 )
return QString::fromLatin1( s );
if ( codec_Euc )
return codec_Euc->toUnicode( s );
return QString{};
}
bool EpwingBook::getMatches( QString word, QVector< QString > & matches )
{
QByteArray bword, bword2;

View file

@ -85,6 +85,7 @@ class EpwingBook
QVector< EWPos > LinksQueue;
int refOpenCount, refCloseCount;
static QMutex libMutex;
QList< EpwingHeadword > candidateItems;
QString createCacheDir( QString const & dir );
@ -184,6 +185,8 @@ public:
// Make name for resource
QString makeFName( QString const & ext, int page, int offset ) const;
QByteArray handleCandidate( EB_Hook_Code code, const unsigned * argv );
QString currentCandidate();
// Store all files in Epwing folder
static void collectFilenames( QString const & directory, vector< string > & files );
@ -199,10 +202,13 @@ public:
QString getCurrentSubBookDirectory();
QString copyright();
QList< EpwingHeadword > candidate( int page, int offset );
QString title();
// Seek to first article
void getFirstHeadword( EpwingHeadword & head );
bool getFirstHeadword( EpwingHeadword & head );
bool haveMenu();
bool getMenu( EpwingHeadword & head );
// Find next headword and article position
bool getNextHeadword( EpwingHeadword & head );

2
thirdparty/eb vendored

@ -1 +1 @@
Subproject commit d5bd52b581fb036ac075bac257ab76a0f8c1de19
Subproject commit 6863251e0712c4e00f5b129fd84995cce606c831

View file

@ -194,22 +194,12 @@ qmake "CONFIG+=use_breakpad"
### Build with VS2019
Install `QT tool for VS` from VS extension
VS2019 support CMake project, open the source directory directly then you go.
#### steps:
- configure qt path
toolbar Extensions=>Qt VS Tools=>Options=>versions.
add qt installation folder
- Open pro project file directly throughttoolbar Extensions=>Qt VS Tools=>Open Qt Project file(.pro)
ref:
[1](https://blog.csdn.net/qq_43493715/article/details/109839046)
#### build
after successfully build,in the target folder(where goldendict.exe resides) ,run windeployqt which copy all the necessary files to this folder.
and copy other missing dlls to this folder. you can click the exe to verify the application can run .
After successful build, run windeployqt.exe(bundled with Qt installation) in the target folder (where GoldenDict.exe is located), which will copy all necessary files to this folder.
You can click on the exe to verify that the application can be run.
after alll this ,you can debug the application normally.
After all this, you can debug the application normally.

View file

@ -0,0 +1,53 @@
# How to debug dictionary javascript
- [How to debug dictionary javascript](#how-to-debug-dictionary-javascript)
- [background](#background)
- [goldendict-ng inspector](#goldendict-ng-inspector)
- [How to navigate to the specified element](#how-to-navigate-to-the-specified-element)
- [Modify the css style](#modify-the-css-style)
- [check javascript events](#check-javascript-events)
- [reproduce the issue in the goldendit](#reproduce-the-issue-in-the-goldendit)
## background
When some js functions do not work as expected, this article tries to give a debug solution to pinpoint the problem.
## goldendict-ng inspector
Goldendict-ng has embedded an inspector, you can trigger it manually using `F12`.
Screenshot:
![Inspector](../img/inspector.png)
## How to navigate to the specified element
Click the find element and move mouse to the specified element, click the element will navigate the source panel to the very place.
![steps](../img/inspector-steps.png)
## Modify the css style
you can play around with the css to modify the appearance of the html and check the results.
![style](../img/inspector-style.png)
## check javascript events
- navigate to the specified element
- check eventlisterner panel
- pay attention to the click events
- in the following screenshot ,there are two registered event listeners, one from the goldendict `gd-custom.js` and one from the html itself.
- click the above event listener location will locate to the right place in the javascript.
![event](../img/inspector-event.png)
If some desired event does not triggered , it can first check does the event listeners has been successfully registered. then set a breakpoint in the right place to check whether the event has been triggered and if it can executed successfully.
![breakpoint](../img/inspector-breakpoint.png)
## reproduce the issue in the goldendit
following your normal operations and debugging the javascript code and pay attention to the console output. Whether any errors happened.
![Alt text](../img/inspector-console.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

View file

@ -55,3 +55,5 @@ nav:
- Breadpad crash analysis: howto/how to use breadpad crash analysis.md
- Build ffmpeg on Windows: howto/how to build ffmpeg for visual studio.md
- How to update the crowdin.ts file: howto/how to update crowdin.ts file.md
- How to debug dictionary js: howto/how to debug dictionary js.md