mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-24 21:04:09 +00:00
Merge branch 'staged' into dev
This commit is contained in:
commit
bba4b8ef23
15
README.md
15
README.md
|
@ -35,10 +35,6 @@ sudo dnf install git pkg-config libzstd-devel opencc-devel xz-devel xz-lzma-comp
|
||||||
libao-devel ffmpeg-devel libtiff-devel eb-devel qt5-qtx11extras-devel libXtst-devel \
|
libao-devel ffmpeg-devel libtiff-devel eb-devel qt5-qtx11extras-devel libXtst-devel \
|
||||||
libxkbcommon-devel qt5-qtbase qt5-qttools qt5-qtsvg-devl qt5-qtwebengine-devel qt5-qtmultimedia-devl
|
libxkbcommon-devel qt5-qtbase qt5-qttools qt5-qtsvg-devl qt5-qtwebengine-devel qt5-qtmultimedia-devl
|
||||||
|
|
||||||
qmake-qt5 CONFIG+=release CONFIG+=no_extra_tiff_handler CONFIG+=no_epwing_support
|
|
||||||
make
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## How to build
|
## How to build
|
||||||
|
@ -48,11 +44,20 @@ First, clone this repository, e.g.:
|
||||||
git clone https://github.com/xiaoyifang/goldendict.git
|
git clone https://github.com/xiaoyifang/goldendict.git
|
||||||
|
|
||||||
|
|
||||||
### Linux
|
### Linux (fedora)
|
||||||
And then invoke `qmake-qt5` and `make`:
|
And then invoke `qmake-qt5` and `make`:
|
||||||
|
|
||||||
cd goldendict && qmake-qt5 && make
|
cd goldendict && qmake-qt5 && make
|
||||||
|
|
||||||
|
### ArchLinux
|
||||||
|
|
||||||
|
on archlinux based os, you can use `yay` to install the community goldendict-webengine-git .
|
||||||
|
|
||||||
|
#(Manjaro distribution)
|
||||||
|
pacman -S --needed git base-devel yay
|
||||||
|
|
||||||
|
yay -S goldendict-webengine-git
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
```
|
```
|
||||||
brew install qt # or use official offline installer
|
brew install qt # or use official offline installer
|
||||||
|
|
11
btreeidx.cc
11
btreeidx.cc
|
@ -1353,9 +1353,16 @@ QSet<uint32_t> BtreeIndex::findNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
char const * leaf = &rootNode.front();
|
char const * leaf = &rootNode.front();
|
||||||
|
|
||||||
vector< char > extLeaf;
|
|
||||||
QSet<uint32_t> leafOffset;
|
QSet<uint32_t> leafOffset;
|
||||||
|
|
||||||
|
uint32_t leafEntries;
|
||||||
|
leafEntries = *(uint32_t *)leaf;
|
||||||
|
if ( leafEntries != 0xffffFFFF )
|
||||||
|
{
|
||||||
|
leafOffset.insert(rootOffset);
|
||||||
|
return leafOffset;
|
||||||
|
}
|
||||||
|
|
||||||
// the current the btree's implementation has the height = 2.
|
// the current the btree's implementation has the height = 2.
|
||||||
|
|
||||||
// A node offset
|
// A node offset
|
||||||
|
|
|
@ -184,7 +184,7 @@ InputPhrase Preferences::sanitizeInputPhrase( QString const & inputPhrase ) cons
|
||||||
|
|
||||||
if( limitInputPhraseLength && inputPhrase.size() > inputPhraseLengthLimit )
|
if( limitInputPhraseLength && inputPhrase.size() > inputPhraseLengthLimit )
|
||||||
{
|
{
|
||||||
gdWarning( "Ignoring an input phrase %d symbols long. The configured maximum input phrase length is %d symbols.",
|
gdDebug( "Ignoring an input phrase %d symbols long. The configured maximum input phrase length is %d symbols.",
|
||||||
inputPhrase.size(), inputPhraseLengthLimit );
|
inputPhrase.size(), inputPhraseLengthLimit );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Dsl {
|
namespace Dsl {
|
||||||
|
@ -164,12 +165,37 @@ wstring ArticleDom::Node::renderAsText( bool stripTrsTag ) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if src == 'm' and dest is 'mX', where X is a digit
|
namespace {
|
||||||
static inline bool checkM( wstring const & dest, wstring const & src )
|
|
||||||
|
/// @return true if @p tagName equals "mN" where N is a digit
|
||||||
|
bool is_mN( wstring const & tagName )
|
||||||
{
|
{
|
||||||
return ( src == U"m" && dest.size() == 2 && dest[ 0 ] == L'm' && iswdigit( dest[ 1 ] ) );
|
return tagName.size() == 2 && tagName[ 0 ] == U'm' && iswdigit( tagName[ 1 ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isAnyM( wstring const & tagName )
|
||||||
|
{
|
||||||
|
return tagName == U"m" || is_mN( tagName );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkM( wstring const & dest, wstring const & src )
|
||||||
|
{
|
||||||
|
return src == U"m" && is_mN( dest );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Closing the [mN] tags is optional. Quote from https://documentation.help/ABBYY-Lingvo8/paragraph_form.htm:
|
||||||
|
/// Any paragraph from this tag until the end of card or until system meets an «[/m]» (margin shift toggle off) tag
|
||||||
|
struct MustTagBeClosed
|
||||||
|
{
|
||||||
|
bool operator()( ArticleDom::Node const * tag ) const
|
||||||
|
{
|
||||||
|
Q_ASSERT( tag->isTag );
|
||||||
|
return !isAnyM( tag->tagName );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
ArticleDom::ArticleDom( wstring const & str, string const & dictName,
|
ArticleDom::ArticleDom( wstring const & str, string const & dictName,
|
||||||
wstring const & headword_):
|
wstring const & headword_):
|
||||||
root( Node::Tag(), wstring(), wstring() ), stringPos( str.c_str() ),
|
root( Node::Tag(), wstring(), wstring() ), stringPos( str.c_str() ),
|
||||||
|
@ -375,7 +401,7 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
|
||||||
|
|
||||||
if ( !isClosing )
|
if ( !isClosing )
|
||||||
{
|
{
|
||||||
if( name == U"m" || ( name.size() == 2 && name[ 0 ] == L'm' && iswdigit( name[ 1 ] ) ) )
|
if( isAnyM( name ) )
|
||||||
{
|
{
|
||||||
// Opening an 'mX' or 'm' tag closes any previous 'm' tag
|
// Opening an 'mX' or 'm' tag closes any previous 'm' tag
|
||||||
closeTag( U"m" , stack, false );
|
closeTag( U"m" , stack, false );
|
||||||
|
@ -630,7 +656,24 @@ ArticleDom::ArticleDom( wstring const & str, string const & dictName,
|
||||||
|
|
||||||
if ( stack.size() )
|
if ( stack.size() )
|
||||||
{
|
{
|
||||||
GD_FDPRINTF( stderr, "Warning: %u tags were unclosed.\n", (unsigned) stack.size() );
|
list< Node * >::iterator it = std::find_if( stack.begin(), stack.end(), MustTagBeClosed() );
|
||||||
|
if( it == stack.end() )
|
||||||
|
return; // no unclosed tags that must be closed => nothing to warn about
|
||||||
|
QByteArray const firstTagName = gd::toQString( ( *it )->tagName ).toUtf8();
|
||||||
|
++it;
|
||||||
|
unsigned const unclosedTagCount = 1 + std::count_if( it, stack.end(), MustTagBeClosed() );
|
||||||
|
|
||||||
|
if( dictName.empty() )
|
||||||
|
{
|
||||||
|
gdWarning( "Warning: %u tag(s) were unclosed, first tag name \"%s\".\n",
|
||||||
|
unclosedTagCount, firstTagName.constData() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gdWarning( "Warning: %u tag(s) were unclosed in \"%s\", article \"%s\", first tag name \"%s\".\n",
|
||||||
|
unclosedTagCount, dictName.c_str(), gd::toQString( headword ).toUtf8().constData(),
|
||||||
|
firstTagName.constData() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,7 +683,7 @@ void ArticleDom::openTag( wstring const & name,
|
||||||
{
|
{
|
||||||
list< Node > nodesToReopen;
|
list< Node > nodesToReopen;
|
||||||
|
|
||||||
if( name == U"m" || checkM( name, U"m" ) )
|
if( isAnyM( name ) )
|
||||||
{
|
{
|
||||||
// All tags above [m] tag will be closed and reopened after
|
// All tags above [m] tag will be closed and reopened after
|
||||||
// to avoid break this tag by closing some other tag.
|
// to avoid break this tag by closing some other tag.
|
||||||
|
|
|
@ -208,12 +208,12 @@ void FavoritesPaneWidget::onSelectionChanged( QItemSelection const & selection )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
itemSelectionChanged = true;
|
itemSelectionChanged = true;
|
||||||
emitFavoritesItemRequested( selection.indexes().front() );
|
// emitFavoritesItemRequested( selection.indexes().front() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void FavoritesPaneWidget::onItemClicked( QModelIndex const & idx )
|
void FavoritesPaneWidget::onItemClicked( QModelIndex const & idx )
|
||||||
{
|
{
|
||||||
if ( !itemSelectionChanged && m_favoritesTree->selectionModel()->selectedIndexes().size() == 1 )
|
// if ( !itemSelectionChanged && m_favoritesTree->selectionModel()->selectedIndexes().size() == 1 )
|
||||||
{
|
{
|
||||||
emitFavoritesItemRequested( idx );
|
emitFavoritesItemRequested( idx );
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@ void FavoritesModel::readData()
|
||||||
QFile favoritesFile( m_favoritesFilename );
|
QFile favoritesFile( m_favoritesFilename );
|
||||||
if( !favoritesFile.open( QFile::ReadOnly ) )
|
if( !favoritesFile.open( QFile::ReadOnly ) )
|
||||||
{
|
{
|
||||||
gdWarning( "No favorities file found" );
|
gdDebug( "No favorites file found" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ bool DecoderContext::openCodec( QString & errorString )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_log( NULL, AV_LOG_INFO, "Codec open: %s: channels: %d, rate: %d, format: %s\n", codec_->long_name,
|
gdDebug( "Codec open: %s: channels: %d, rate: %d, format: %s\n", codec_->long_name,
|
||||||
codecContext_->channels, codecContext_->sample_rate, av_get_sample_fmt_name( codecContext_->sample_fmt ) );
|
codecContext_->channels, codecContext_->sample_rate, av_get_sample_fmt_name( codecContext_->sample_fmt ) );
|
||||||
|
|
||||||
if ( codecContext_->sample_fmt == AV_SAMPLE_FMT_S32 ||
|
if ( codecContext_->sample_fmt == AV_SAMPLE_FMT_S32 ||
|
||||||
|
@ -341,7 +341,7 @@ bool DecoderContext::openOutputDevice( QString & errorString )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_log( NULL, AV_LOG_INFO, "ao_open_live(): %s: channels: %d, rate: %d, bits: %d\n",
|
gdDebug( "ao_open_live(): %s: channels: %d, rate: %d, bits: %d\n",
|
||||||
aoDrvInfo->name, aoSampleFormat.channels, aoSampleFormat.rate, aoSampleFormat.bits );
|
aoDrvInfo->name, aoSampleFormat.channels, aoSampleFormat.rate, aoSampleFormat.bits );
|
||||||
|
|
||||||
aoDevice_ = ao_open_live( aoDriverId, &aoSampleFormat, NULL );
|
aoDevice_ = ao_open_live( aoDriverId, &aoSampleFormat, NULL );
|
||||||
|
|
|
@ -666,9 +666,10 @@ TS_OUT = $$TRANSLATIONS
|
||||||
TS_OUT ~= s/.ts/.qm/g
|
TS_OUT ~= s/.ts/.qm/g
|
||||||
PRE_TARGETDEPS += $$TS_OUT
|
PRE_TARGETDEPS += $$TS_OUT
|
||||||
|
|
||||||
equals(QT_VERSION,6.4.0){
|
equals(QT_VERSION,6.4.0)
|
||||||
|
{
|
||||||
#QTBUG-105984
|
#QTBUG-105984
|
||||||
multimedia.files = $$[QT_INSTALL_PLUGINS]/multimedia/*
|
multimedia.files = $$[QT_PLUGIN_PATH]/multimedia/*
|
||||||
multimedia.path = plugins/multimedia
|
multimedia.path = plugins/multimedia
|
||||||
#multimedia.CONFIG += no_check_exist
|
#multimedia.CONFIG += no_check_exist
|
||||||
message("copy qt6.4.0 multimedia")
|
message("copy qt6.4.0 multimedia")
|
||||||
|
|
|
@ -202,14 +202,14 @@ void HistoryPaneWidget::onSelectionChanged( QItemSelection const & selection )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
itemSelectionChanged = true;
|
itemSelectionChanged = true;
|
||||||
emitHistoryItemRequested( selection.front().topLeft() );
|
// emitHistoryItemRequested( selection.front().topLeft() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryPaneWidget::onItemClicked( QModelIndex const & idx )
|
void HistoryPaneWidget::onItemClicked( QModelIndex const & idx )
|
||||||
{
|
{
|
||||||
// qDebug() << "clicked";
|
// qDebug() << "clicked";
|
||||||
|
|
||||||
if ( !itemSelectionChanged )
|
// if ( !itemSelectionChanged )
|
||||||
{
|
{
|
||||||
emitHistoryItemRequested( idx );
|
emitHistoryItemRequested( idx );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue