mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-12-04 16:14:05 +00:00
merge conflict
This commit is contained in:
commit
299bc876b1
|
@ -49,6 +49,7 @@ jobs:
|
|||
|
||||
- name: install deps on macos
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=TRUE
|
||||
brew install cmake ninja
|
||||
brew install automake
|
||||
brew install autoconf
|
||||
|
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [macos-13]
|
||||
qt_ver: [ 6.5.2,6.6.0 ]
|
||||
qt_ver: [ 6.6.0 ]
|
||||
qt_arch: [clang_64]
|
||||
env:
|
||||
targetName: GoldenDict
|
||||
|
|
23
.github/workflows/macos-homebrew.yml
vendored
23
.github/workflows/macos-homebrew.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [macos-12,macos-13]
|
||||
qt_ver: [ 6.5.2,6.6.0 ]
|
||||
qt_ver: [ 6.6.0,6.6.1 ]
|
||||
qt_arch: [clang_64]
|
||||
env:
|
||||
targetName: GoldenDict
|
||||
|
@ -42,6 +42,7 @@ jobs:
|
|||
|
||||
- name: install deps on macos
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=TRUE
|
||||
brew install cmake ninja
|
||||
brew install automake
|
||||
brew install autoconf
|
||||
|
@ -101,22 +102,16 @@ jobs:
|
|||
macdeployqt ${targetName}.app -qmldir=. -verbose=1
|
||||
otool -L GoldenDict.app/Contents/MacOS/GoldenDict
|
||||
ls -al GoldenDict.app/Contents/Frameworks
|
||||
otool -L GoldenDict.app/Contents/Frameworks/libzim.8.dylib
|
||||
# otool -L GoldenDict.app/Contents/Frameworks/libav*
|
||||
# otool -L GoldenDict.app/Contents/Frameworks/libjxl.0.8.dylib
|
||||
# cp -r /usr/local/Cellar/icu4c/7*/lib/libicu*.dylib GoldenDict.app/Contents/Frameworks
|
||||
# cp -r /usr/local/Cellar/zstd/1.5.5/lib/libzstd.1.dylib GoldenDict.app/Contents/Frameworks
|
||||
dylibbundler -of -b -x GoldenDict.app/Contents/Frameworks/libzim.8.dylib -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/
|
||||
# dylibbundler -of -b -x GoldenDict.app/Contents/Frameworks/libicu* -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/
|
||||
find /usr/local/Cellar -name "libicudata.73.dylib" -exec cp {} GoldenDict.app/Contents/Frameworks/ \;
|
||||
|
||||
find GoldenDict.app/Contents/Frameworks/ -maxdepth 1 -type f -name "libicu*" -exec dylibbundler -of -b -x {} -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/ \;
|
||||
# dylibbundler -of -x GoldenDict.app/Contents/Frameworks/libavformat.60.dylib -x GoldenDict.app/Contents/Frameworks/libavcodec.60.dylib -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/
|
||||
# dylibbundler -of -b -x GoldenDict.app/Contents/Frameworks/libjxl.0.8.dylib -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/
|
||||
find GoldenDict.app/Contents/Frameworks/ -maxdepth 1 -name "libicu*" -exec ls -al {} \;
|
||||
find GoldenDict.app/Contents/Frameworks/ -maxdepth 1 -type f -name "libicu*" -exec ls -al {} \;
|
||||
|
||||
find GoldenDict.app/Contents/Frameworks/ -maxdepth 1 -type f -name "libzim*" -exec dylibbundler -of -b -x {} -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/ \;
|
||||
find GoldenDict.app/Contents/Frameworks/ -maxdepth 1 -name "libicu*" -exec dylibbundler -of -b -x {} -d GoldenDict.app/Contents/Frameworks/ -p @executable_path/../Frameworks -s /usr/local/ -s /opt/ \;
|
||||
|
||||
otool -L GoldenDict.app/Contents/Frameworks/libicu*
|
||||
otool -L GoldenDict.app/Contents/Frameworks/libzim.8.dylib
|
||||
otool -L GoldenDict.app/Contents/Frameworks/libxapian.30.dylib
|
||||
otool -L GoldenDict.app/Contents/Frameworks/liblzma.5.dylib
|
||||
otool -L GoldenDict.app/Contents/Frameworks/libzim*
|
||||
|
||||
codesign --force --deep -s - GoldenDict.app
|
||||
|
||||
|
|
2
.github/workflows/ubuntu-6.2.yml
vendored
2
.github/workflows/ubuntu-6.2.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
qt_ver: [ 6.5.2,6.6.0 ]
|
||||
qt_ver: [ 6.6.0 ]
|
||||
qt_arch: [gcc_64]
|
||||
env:
|
||||
version: 23.11.08
|
||||
|
|
2
.github/workflows/windows-6.x.yml
vendored
2
.github/workflows/windows-6.x.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [windows-2019]
|
||||
qt_ver: [6.5.2,6.6.0 ]
|
||||
qt_ver: [ 6.6.0,6.6.1 ]
|
||||
qt_arch: [win64_msvc2019_64]
|
||||
env:
|
||||
targetName: GoldenDict.exe
|
||||
|
|
|
@ -41,9 +41,4 @@
|
|||
<provides>
|
||||
<id>org.goldendict_ng.desktop</id>
|
||||
</provides>
|
||||
<releases>
|
||||
<release version="23.09.08" date="2023-09-08"/>
|
||||
<release version="23.07.23" date="2023-07-23"/>
|
||||
<release version="23.06.01" date="2023-06-01"/>
|
||||
</releases>
|
||||
</component>
|
||||
|
|
|
@ -141,6 +141,7 @@ std::string ArticleMaker::makeHtmlHeader( QString const & word, QString const &
|
|||
.toStdString();
|
||||
|
||||
result += R"(<script src="qrc:///scripts/gd-builtin.js"></script>)";
|
||||
result += R"(<script src="qrc:///scripts/mark.min.js"></script>)";
|
||||
|
||||
if ( GlobalBroadcaster::instance()->getPreference()->darkReaderMode ) {
|
||||
//only enable this darkmode on modern style.
|
||||
|
@ -674,8 +675,8 @@ void ArticleRequest::bodyFinished()
|
|||
fmt::format_to( std::back_inserter( head ),
|
||||
FMT_COMPILE(
|
||||
R"( <div class="gdarticle {0} {1}" id="{2}"
|
||||
onClick="gdMakeArticleActive( '{3}', false );"
|
||||
onContextMenu="gdMakeArticleActive( '{3}', false );">)" ),
|
||||
onClick="if(typeof gdMakeArticleActive !='undefined') gdMakeArticleActive( '{3}', false );"
|
||||
onContextMenu="if(typeof gdMakeArticleActive !='undefined') gdMakeArticleActive( '{3}', false );">)" ),
|
||||
closePrevSpan ? "" : " gdactivearticle",
|
||||
collapse ? " gdcollapsedarticle" : "",
|
||||
gdFrom,
|
||||
|
|
|
@ -35,6 +35,20 @@ bool endsWithIgnoreCase( const string & str1, string str2 )
|
|||
return ( str1.size() >= (unsigned)str2.size() )
|
||||
&& ( strcasecmp( str1.c_str() + ( str1.size() - str2.size() ), str2.data() ) == 0 );
|
||||
}
|
||||
|
||||
QString escapeAmps( QString const & str )
|
||||
{
|
||||
QString result( str );
|
||||
result.replace( "&", "&&" );
|
||||
return result;
|
||||
}
|
||||
|
||||
QString unescapeAmps( QString const & str )
|
||||
{
|
||||
QString result( str );
|
||||
result.replace( "&&", "&" );
|
||||
return result;
|
||||
}
|
||||
} // namespace Utils
|
||||
|
||||
QString Utils::Path::combine( const QString & path1, const QString & path2 )
|
||||
|
|
|
@ -341,6 +341,10 @@ void removeDirectory( QString const & directory );
|
|||
void removeDirectory( string const & directory );
|
||||
} // namespace Fs
|
||||
|
||||
QString escapeAmps( QString const & str );
|
||||
|
||||
QString unescapeAmps( QString const & str );
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
#endif // UTILS_HH
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <exception>
|
||||
#include <stdio.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <QtEndian>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Dsl {
|
||||
|
@ -832,7 +832,33 @@ DslScanner::DslScanner( string const & fileName ):
|
|||
bool needExactEncoding = false;
|
||||
|
||||
QByteArray ba = QByteArray::fromRawData( (const char *)firstBytes, 50 );
|
||||
codec = QTextCodec::codecForUtfText( ba, QTextCodec::codecForName( "UTF-8" ) );
|
||||
codec = QTextCodec::codecForUtfText( ba, nullptr );
|
||||
if ( !codec ) {
|
||||
// the encoding has no bom.
|
||||
// check the first char # (0x23).
|
||||
auto hashTag = 0x0023;
|
||||
|
||||
auto uci = qFromUnaligned< uint32_t >( firstBytes );
|
||||
if ( uci == qToBigEndian( hashTag ) ) {
|
||||
codec = QTextCodec::codecForMib( 1018 ); // utf-32 be
|
||||
}
|
||||
else if ( uci == qToLittleEndian( hashTag ) ) {
|
||||
codec = QTextCodec::codecForMib( 1019 ); // utf-32 le
|
||||
}
|
||||
else {
|
||||
auto uc = qFromUnaligned< uint16_t >( firstBytes );
|
||||
if ( uc == qToBigEndian( uint16_t( hashTag ) ) ) {
|
||||
codec = QTextCodec::codecForMib( 1013 ); // utf16 be
|
||||
}
|
||||
else if ( uc == qToLittleEndian( uint16_t( hashTag ) ) ) {
|
||||
codec = QTextCodec::codecForMib( 1014 ); // utf16 le
|
||||
}
|
||||
else {
|
||||
//default encoding
|
||||
codec = QTextCodec::codecForName( "UTF-8" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
encoding = Utf8::getEncodingForName( codec->name() );
|
||||
qDebug() << codec->name();
|
||||
|
|
|
@ -320,7 +320,7 @@ bool MdictParser::readHeader( QDataStream & in )
|
|||
|
||||
if ( headerText.contains( "StyleSheet" ) ) {
|
||||
// a workaround to bypass https://bugreports.qt.io/browse/QTBUG-102612
|
||||
QRegularExpression rx( "StyleSheet=\"([^\"]*?)\"", QRegularExpression::CaseInsensitiveOption );
|
||||
QRegularExpression const rx( "StyleSheet=\"([^\"]*?)\"", QRegularExpression::CaseInsensitiveOption );
|
||||
|
||||
auto match = rx.match( headerText );
|
||||
|
||||
|
@ -334,6 +334,9 @@ bool MdictParser::readHeader( QDataStream & in )
|
|||
|
||||
QDomNamedNodeMap headerAttributes = parseHeaderAttributes( headerText );
|
||||
|
||||
if ( headerAttributes.isEmpty() )
|
||||
return false;
|
||||
|
||||
encoding_ = headerAttributes.namedItem( "Encoding" ).toAttr().value();
|
||||
if ( encoding_ == "GBK" || encoding_ == "GB2312" ) {
|
||||
encoding_ = "GB18030";
|
||||
|
|
|
@ -31,10 +31,8 @@ bool ftsIndexIsOldOrBad( BtreeIndexing::BtreeDictionary * dict )
|
|||
auto document = db.get_document( docid );
|
||||
|
||||
string const lastDoc = document.get_data();
|
||||
bool const notFinished = lastDoc != finish_mark;
|
||||
qDebug() << dict->ftsIndexName().c_str() << document.get_data().c_str() << notFinished;
|
||||
return lastDoc != finish_mark;
|
||||
//use a special document to mark the end of the index.
|
||||
return notFinished;
|
||||
}
|
||||
catch ( Xapian::Error & e ) {
|
||||
qWarning() << e.get_description().c_str();
|
||||
|
@ -118,8 +116,9 @@ void makeFTSIndex( BtreeIndexing::BtreeDictionary * dict, QAtomicInt & isCancell
|
|||
for ( auto const & address : offsets ) {
|
||||
indexedDoc++;
|
||||
|
||||
if ( address > lastAddress && skip ) {
|
||||
if ( address == lastAddress && skip ) {
|
||||
skip = false;
|
||||
continue;
|
||||
}
|
||||
//skip until to the lastAddress;
|
||||
if ( skip ) {
|
||||
|
@ -138,12 +137,8 @@ void makeFTSIndex( BtreeIndexing::BtreeDictionary * dict, QAtomicInt & isCancell
|
|||
|
||||
indexer.set_document( doc );
|
||||
|
||||
if ( GlobalBroadcaster::instance()->getPreference()->fts.enablePosition ) {
|
||||
indexer.index_text( articleStr.toStdString() );
|
||||
}
|
||||
else {
|
||||
indexer.index_text_without_positions( articleStr.toStdString() );
|
||||
}
|
||||
indexer.index_text( articleStr.toStdString() );
|
||||
|
||||
|
||||
doc.set_data( std::to_string( address ) );
|
||||
// Add the document to the database.
|
||||
|
@ -199,10 +194,14 @@ void FTSResultsRequest::run()
|
|||
// Parse the query string to produce a Xapian::Query object.
|
||||
Xapian::QueryParser qp;
|
||||
qp.set_database( db );
|
||||
Xapian::QueryParser::feature_flag flag = Xapian::QueryParser::FLAG_DEFAULT;
|
||||
if ( searchMode == FTS::Wildcards )
|
||||
flag = Xapian::QueryParser::FLAG_WILDCARD;
|
||||
Xapian::Query query = qp.parse_query( query_string, flag | Xapian::QueryParser::FLAG_CJK_NGRAM );
|
||||
qp.set_default_op( Xapian::Query::op::OP_AND );
|
||||
int flag =
|
||||
Xapian::QueryParser::FLAG_DEFAULT | Xapian::QueryParser::FLAG_PURE_NOT | Xapian::QueryParser::FLAG_CJK_NGRAM;
|
||||
if ( searchMode == FTS::Wildcards ) {
|
||||
flag = flag | Xapian::QueryParser::FLAG_WILDCARD;
|
||||
qp.set_max_expansion( 1 );
|
||||
}
|
||||
Xapian::Query query = qp.parse_query( query_string, flag );
|
||||
qDebug() << "Parsed query is: " << query.get_description().c_str();
|
||||
|
||||
// Find the top 100 results for the query.
|
||||
|
|
|
@ -60,7 +60,7 @@ void IframeSchemeHandler::requestStarted( QWebEngineUrlRequestJob * requestJob )
|
|||
|
||||
QString root = reply->url().scheme() + "://" + reply->url().host();
|
||||
|
||||
if ( reply->url().port() != 80 && reply->url().port() != 443 ) {
|
||||
if ( reply->url().port() != 80 && reply->url().port() != 443 && reply->url().port() != -1 ) {
|
||||
root = root + ":" + QString::number( reply->url().port() );
|
||||
}
|
||||
QString base = root + reply->url().path();
|
||||
|
|
|
@ -307,7 +307,7 @@ void processCommandLine( QCoreApplication * app, GDOptions * result )
|
|||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
#if defined( Q_OS_UNIX ) && !defined( Q_OS_MACOS )
|
||||
// GoldenDict use lots of X11 functions and it currently cannot work
|
||||
// natively on Wayland. This workaround will force GoldenDict to use
|
||||
// XWayland.
|
||||
|
|
1241
src/scripts/mark.js
Normal file
1241
src/scripts/mark.js
Normal file
File diff suppressed because it is too large
Load diff
13
src/scripts/mark.min.js
vendored
Normal file
13
src/scripts/mark.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -9,5 +9,6 @@
|
|||
<file>jquery-3.6.0.slim.min.js</file>
|
||||
<file>popper.min.js</file>
|
||||
<file>tippy.min.js</file>
|
||||
<file>mark.min.js</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <QWebEngineSettings>
|
||||
#include <map>
|
||||
#include <QApplication>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#if ( QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) && QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
#include <QWebEngineContextMenuData>
|
||||
|
@ -477,8 +478,9 @@ void ArticleView::loadFinished( bool result )
|
|||
if ( result ) {
|
||||
emit pageLoaded( this );
|
||||
}
|
||||
if ( Utils::Url::hasQueryItem( webview->url(), "regexp" ) )
|
||||
if ( Utils::Url::hasQueryItem( webview->url(), "regexp" ) ) {
|
||||
highlightFTSResults();
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleView::handleTitleChanged( QString const & title )
|
||||
|
@ -555,10 +557,11 @@ bool ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
|
|||
QString dictId = id.mid( 7 );
|
||||
if ( dictId.isEmpty() )
|
||||
return false;
|
||||
QString script = QString(
|
||||
"var elem=document.getElementById('%1'); "
|
||||
"if(elem!=undefined){elem.scrollIntoView(true);} gdMakeArticleActive('%2',true);" )
|
||||
.arg( id, dictId );
|
||||
QString script =
|
||||
QString(
|
||||
"var elem=document.getElementById('%1'); "
|
||||
"if(elem!=undefined){elem.scrollIntoView(true);} if(typeof gdMakeArticleActive !='undefined') gdMakeArticleActive('%2',true);" )
|
||||
.arg( id, dictId );
|
||||
onJsActiveArticleChanged( id );
|
||||
webview->page()->runJavaScript( script );
|
||||
setActiveArticleId( dictId );
|
||||
|
@ -1491,6 +1494,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
QAction * addHeaderToHistoryAction = nullptr;
|
||||
QAction * sendWordToInputLineAction = nullptr;
|
||||
QAction * saveImageAction = nullptr;
|
||||
QAction * openImageAction = nullptr;
|
||||
QAction * saveSoundAction = nullptr;
|
||||
QAction * saveBookmark = nullptr;
|
||||
|
||||
|
@ -1534,6 +1538,9 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
menu.addAction( webview->pageAction( QWebEnginePage::CopyImageToClipboard ) );
|
||||
saveImageAction = new QAction( tr( "Save &image..." ), &menu );
|
||||
menu.addAction( saveImageAction );
|
||||
|
||||
openImageAction = new QAction( tr( "Open image in system viewer..." ), &menu );
|
||||
menu.addAction( openImageAction );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1746,6 +1753,36 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
|
|||
saveResource( url, webview->url(), fileName );
|
||||
}
|
||||
}
|
||||
else if ( result == openImageAction ) {
|
||||
QUrl url = imageUrl;
|
||||
QString fileName;
|
||||
|
||||
|
||||
QString name = Utils::Url::path( url ).section( '/', -1 );
|
||||
// Image data
|
||||
|
||||
// Check for babylon image name
|
||||
if ( name[ 0 ] == '\x1E' )
|
||||
name.remove( 0, 1 );
|
||||
if ( name.length() && name[ name.length() - 1 ] == '\x1F' )
|
||||
name.chop( 1 );
|
||||
|
||||
fileName = QDir::temp().filePath( QString::number( QRandomGenerator::global()->generate() ) + name );
|
||||
|
||||
if ( !fileName.isEmpty() ) {
|
||||
QFileInfo fileInfo( fileName );
|
||||
auto handler = saveResource( url, webview->url(), fileName );
|
||||
|
||||
if ( !handler->isEmpty() ) {
|
||||
connect( handler, &ResourceToSaveHandler::done, this, [ fileName ]() {
|
||||
QDesktopServices::openUrl( fileName );
|
||||
} );
|
||||
}
|
||||
else {
|
||||
QDesktopServices::openUrl( fileName );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( !popupView && result == maxDictionaryRefsAction )
|
||||
emit showDictsPane();
|
||||
|
@ -2136,54 +2173,21 @@ void ArticleView::highlightFTSResults()
|
|||
if ( regString.isEmpty() )
|
||||
return;
|
||||
|
||||
//<div><i>watch</i>out</div> to plainText will return "watchout".
|
||||
//if application goes here,that means the article text must contains the search text.
|
||||
//whole word match regString will contain \b . can not match the above senario.
|
||||
//workaround ,remove \b from the regstring="(\bwatch\b)"
|
||||
regString.remove( QRegularExpression( R"(\b)" ) );
|
||||
|
||||
//make it simple ,and do not support too much complex cases. such as wildcard etc.
|
||||
firstAvailableText = regString;
|
||||
//replace any unicode Number ,Symbol ,Punctuation ,Mark character to whitespace
|
||||
regString.replace( QRegularExpression( R"([\p{N}\p{S}\p{P}\p{M}])", QRegularExpression::UseUnicodePropertiesOption ),
|
||||
" " );
|
||||
|
||||
if ( firstAvailableText.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove possible wildcard character.
|
||||
auto cleaned =
|
||||
firstAvailableText.split( QRegularExpression( "\\p{P}", QRegularExpression::UseUnicodePropertiesOption ) );
|
||||
|
||||
if ( cleaned.empty() )
|
||||
if ( regString.trimmed().isEmpty() )
|
||||
return;
|
||||
|
||||
firstAvailableText = cleaned.at( 0 );
|
||||
#if ( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
|
||||
webview->findText( firstAvailableText,
|
||||
QWebEnginePage::FindBackward,
|
||||
[ & ]( const QWebEngineFindTextResult & result ) {
|
||||
qInfo() << result.activeMatch() << "of" << result.numberOfMatches() << "matches";
|
||||
QString script = QString(
|
||||
"var context = document.querySelector(\"body\");\n"
|
||||
"var instance = new Mark(context);\n"
|
||||
"instance.mark(\"%1\",{\"accuracy\": \"exactly\"});" )
|
||||
.arg( regString );
|
||||
|
||||
if ( result.numberOfMatches() == 0 ) {
|
||||
ftsSearchPanel->statusLabel->setText( searchStatusMessageNoMatches() );
|
||||
}
|
||||
else {
|
||||
ftsSearchPanel->statusLabel->setText(
|
||||
searchStatusMessage( result.activeMatch(), result.numberOfMatches() ) );
|
||||
}
|
||||
|
||||
ftsSearchPanel->show();
|
||||
ftsSearchPanel->previous->setEnabled( result.numberOfMatches() > 1 );
|
||||
ftsSearchPanel->next->setEnabled( result.numberOfMatches() > 1 );
|
||||
|
||||
ftsSearchIsOpened = true;
|
||||
} );
|
||||
#else
|
||||
webview->findText( firstAvailableText, QWebEnginePage::FindBackward, [ this ]( bool res ) {
|
||||
ftsSearchPanel->previous->setEnabled( res );
|
||||
if ( !ftsSearchPanel->next->isEnabled() )
|
||||
ftsSearchPanel->next->setEnabled( res );
|
||||
} );
|
||||
#endif
|
||||
webview->page()->runJavaScript( script );
|
||||
}
|
||||
|
||||
void ArticleView::setActiveDictIds( const ActiveDictIds & ad )
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "langcoder.hh"
|
||||
#include "language.hh"
|
||||
#include "metadata.hh"
|
||||
#include "utils.hh"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
|
@ -517,23 +518,6 @@ DictGroupsWidget::DictGroupsWidget( QWidget * parent ):
|
|||
setUsesScrollButtons( true );
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
QString escapeAmps( QString const & str )
|
||||
{
|
||||
QString result( str );
|
||||
result.replace( "&", "&&" );
|
||||
return result;
|
||||
}
|
||||
|
||||
QString unescapeAmps( QString const & str )
|
||||
{
|
||||
QString result( str );
|
||||
result.replace( "&&", "&" );
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void DictGroupsWidget::populate( Config::Groups const & groups,
|
||||
vector< sptr< Dictionary::Class > > const & allDicts_,
|
||||
|
@ -546,7 +530,7 @@ void DictGroupsWidget::populate( Config::Groups const & groups,
|
|||
|
||||
for ( int x = 0; x < groups.size(); ++x ) {
|
||||
const auto gr = new DictGroupWidget( this, *allDicts, groups[ x ] );
|
||||
addTab( gr, escapeAmps( groups[ x ].name ) );
|
||||
addTab( gr, Utils::escapeAmps( groups[ x ].name ) );
|
||||
connect( gr, &DictGroupWidget::showDictionaryInfo, this, &DictGroupsWidget::showDictionaryInfo );
|
||||
connect( gr->getModel(), &DictListModel::contentChanged, this, &DictGroupsWidget::tabDataChanged );
|
||||
|
||||
|
@ -569,7 +553,7 @@ Config::Groups DictGroupsWidget::makeGroups() const
|
|||
|
||||
for ( int x = 0; x < count(); ++x ) {
|
||||
result.push_back( dynamic_cast< DictGroupWidget & >( *widget( x ) ).makeGroup() );
|
||||
result.back().name = unescapeAmps( tabText( x ) );
|
||||
result.back().name = Utils::unescapeAmps( tabText( x ) );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -638,7 +622,7 @@ int DictGroupsWidget::addNewGroup( QString const & name )
|
|||
newGroup.id = nextId++;
|
||||
|
||||
const auto gr = new DictGroupWidget( this, *allDicts, newGroup );
|
||||
const int idx = insertTab( currentIndex() + 1, gr, escapeAmps( name ) );
|
||||
const int idx = insertTab( currentIndex() + 1, gr, Utils::escapeAmps( name ) );
|
||||
connect( gr, &DictGroupWidget::showDictionaryInfo, this, &DictGroupsWidget::showDictionaryInfo );
|
||||
|
||||
connect( gr->getModel(), &DictListModel::contentChanged, this, &DictGroupsWidget::tabDataChanged );
|
||||
|
@ -897,7 +881,7 @@ QString DictGroupsWidget::getCurrentGroupName() const
|
|||
const int current = currentIndex();
|
||||
|
||||
if ( current >= 0 )
|
||||
return unescapeAmps( tabText( current ) );
|
||||
return Utils::unescapeAmps( tabText( current ) );
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
@ -907,7 +891,7 @@ void DictGroupsWidget::renameCurrentGroup( QString const & name )
|
|||
const int current = currentIndex();
|
||||
|
||||
if ( current >= 0 )
|
||||
setTabText( current, escapeAmps( name ) );
|
||||
setTabText( current, Utils::escapeAmps( name ) );
|
||||
}
|
||||
|
||||
void DictGroupsWidget::removeCurrentGroup()
|
||||
|
|
|
@ -1814,8 +1814,7 @@ ArticleView * MainWindow::createNewTab( bool switchToIt, QString const & name )
|
|||
|
||||
int index = cfg.preferences.newTabsOpenAfterCurrentOne ? ui.tabWidget->currentIndex() + 1 : ui.tabWidget->count();
|
||||
|
||||
QString escaped = name;
|
||||
escaped.replace( "&", "&&" );
|
||||
QString escaped = Utils::escapeAmps( name );
|
||||
|
||||
ui.tabWidget->insertTab( index, view, escaped );
|
||||
mruList.append( dynamic_cast< QWidget * >( view ) );
|
||||
|
@ -1943,7 +1942,7 @@ void MainWindow::titleChanged( ArticleView * view, QString const & title )
|
|||
else {
|
||||
escaped = title;
|
||||
}
|
||||
escaped.replace( "&", "&&" );
|
||||
escaped = Utils::escapeAmps( escaped );
|
||||
|
||||
int index = ui.tabWidget->indexOf( view );
|
||||
if ( !escaped.isEmpty() )
|
||||
|
@ -2856,7 +2855,7 @@ void MainWindow::toggleMainWindow( bool onlyShow )
|
|||
|
||||
void MainWindow::installHotKeys()
|
||||
{
|
||||
#if defined( Q_OS_LINUX )
|
||||
#if defined( Q_OS_UNIX ) && !defined( Q_OS_MACOS )
|
||||
if ( !qEnvironmentVariableIsEmpty( "GOLDENDICT_FORCE_WAYLAND" ) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -4218,7 +4217,7 @@ void MainWindow::showFullTextSearchDialog()
|
|||
{
|
||||
if ( !ftsDlg ) {
|
||||
ftsDlg = new FTS::FullTextSearchDialog( this, cfg, dictionaries, groupInstances, ftsIndexing );
|
||||
ftsDlg->setSearchText( translateLine->text() );
|
||||
// ftsDlg->setSearchText( translateLine->text() );
|
||||
|
||||
addGlobalActionsToDialog( ftsDlg );
|
||||
addGroupComboBoxActionsToDialog( ftsDlg, groupList );
|
||||
|
@ -4264,11 +4263,7 @@ void MainWindow::showFTSIndexingName( QString const & name )
|
|||
QString MainWindow::unescapeTabHeader( QString const & header )
|
||||
{
|
||||
// Reset table header to original headword
|
||||
|
||||
QString escaped = header;
|
||||
escaped.replace( "&&", "&" );
|
||||
|
||||
return escaped;
|
||||
return Utils::unescapeAmps( header );
|
||||
}
|
||||
|
||||
void MainWindow::addCurrentTabToFavorites()
|
||||
|
|
|
@ -376,6 +376,7 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
|
|||
ui.allowGls->setChecked( !p.fts.disabledTypes.contains( "GLS", Qt::CaseInsensitive ) );
|
||||
|
||||
ui.enablePosition->setChecked( p.fts.enablePosition );
|
||||
ui.enablePosition->hide();
|
||||
#ifndef MAKE_ZIM_SUPPORT
|
||||
ui.allowZim->hide();
|
||||
#endif
|
||||
|
|
|
@ -44,7 +44,7 @@ nav:
|
|||
- Custom transliteration: topic_transliteration.md
|
||||
- Customize Dictionary: custom_dictionary.md
|
||||
- OCR Integration: howto/ocr.md
|
||||
- Wayland/Linux: topic_wayland.md
|
||||
- Wayland: topic_wayland.md
|
||||
- Report Bugs & Feedbacks: feedbacks.md
|
||||
- Contributor Guides:
|
||||
- Developer: developer.md
|
||||
|
|
Loading…
Reference in a new issue