mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-28 12:04:08 +00:00
Merge branch 'staged' into dev
This commit is contained in:
commit
92af70d156
|
@ -56,3 +56,6 @@ QRegularExpression Mdx::srcRe2( "([\\s\"'](?:src|srcset)\\s*=)\\s*(?![\\s\"']|\\
|
||||||
|
|
||||||
QRegularExpression Mdx::links( "url\\(\\s*(['\"]?)([^'\"]*)(['\"]?)\\s*\\)",
|
QRegularExpression Mdx::links( "url\\(\\s*(['\"]?)([^'\"]*)(['\"]?)\\s*\\)",
|
||||||
QRegularExpression::CaseInsensitiveOption );
|
QRegularExpression::CaseInsensitiveOption );
|
||||||
|
|
||||||
|
QRegularExpression Mdx::fontFace( "(?:url\\s*\\(\\s*\\\"(.*?)\\\"\\s*)\\)",
|
||||||
|
QRegularExpression::CaseInsensitiveOption|QRegularExpression::DotMatchesEverythingOption );
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
static QRegularExpression srcRe2;
|
static QRegularExpression srcRe2;
|
||||||
|
|
||||||
static QRegularExpression links;
|
static QRegularExpression links;
|
||||||
|
static QRegularExpression fontFace;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace RX
|
} // namespace RX
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "dictionary.hh"
|
#include "dictionary.hh"
|
||||||
#include "delegate.hh"
|
#include "delegate.hh"
|
||||||
#include "helpwindow.hh"
|
#include "helpwindow.hh"
|
||||||
#include "headwordslistmodel.h"
|
#include "headwordsmodel.h"
|
||||||
|
|
||||||
class DictHeadwords : public QDialog
|
class DictHeadwords : public QDialog
|
||||||
{
|
{
|
||||||
|
|
|
@ -443,7 +443,7 @@ public:
|
||||||
/// Retrieve all dictionary headwords
|
/// Retrieve all dictionary headwords
|
||||||
virtual bool getHeadwords( QStringList & )
|
virtual bool getHeadwords( QStringList & )
|
||||||
{ return false; }
|
{ return false; }
|
||||||
virtual void findHeadWordsWithLenth( int &, QSet< QString > * headwords, uint32_t length ){}
|
virtual void findHeadWordsWithLenth( int &, QSet< QString > * /*headwords*/, uint32_t ){}
|
||||||
|
|
||||||
/// Enable/disable search via synonyms
|
/// Enable/disable search via synonyms
|
||||||
void setSynonymSearchEnabled( bool enabled )
|
void setSynonymSearchEnabled( bool enabled )
|
||||||
|
|
|
@ -268,8 +268,8 @@ HEADERS += folding.hh \
|
||||||
articlewebpage.h \
|
articlewebpage.h \
|
||||||
base/globalregex.hh \
|
base/globalregex.hh \
|
||||||
globalbroadcaster.h \
|
globalbroadcaster.h \
|
||||||
|
headwordsmodel.h \
|
||||||
iframeschemehandler.h \
|
iframeschemehandler.h \
|
||||||
headwordslistmodel.h \
|
|
||||||
inc_case_folding.hh \
|
inc_case_folding.hh \
|
||||||
inc_diacritic_folding.hh \
|
inc_diacritic_folding.hh \
|
||||||
mainwindow.hh \
|
mainwindow.hh \
|
||||||
|
@ -412,8 +412,8 @@ SOURCES += folding.cc \
|
||||||
articlewebpage.cpp \
|
articlewebpage.cpp \
|
||||||
base/globalregex.cc \
|
base/globalregex.cc \
|
||||||
globalbroadcaster.cpp \
|
globalbroadcaster.cpp \
|
||||||
|
headwordsmodel.cpp \
|
||||||
iframeschemehandler.cpp \
|
iframeschemehandler.cpp \
|
||||||
headwordslistmodel.cpp \
|
|
||||||
main.cc \
|
main.cc \
|
||||||
dictionary.cc \
|
dictionary.cc \
|
||||||
config.cc \
|
config.cc \
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
#include "headwordslistmodel.h"
|
|
||||||
#include "wstring_qt.hh"
|
|
||||||
|
|
||||||
HeadwordListModel::HeadwordListModel(QObject *parent)
|
|
||||||
: QAbstractListModel(parent), index(0),ptr(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
int HeadwordListModel::rowCount(const QModelIndex &parent) const
|
|
||||||
{
|
|
||||||
return parent.isValid() ? 0 : words.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int HeadwordListModel::totalCount() const{
|
|
||||||
return totalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeadwordListModel::isFinish() const{
|
|
||||||
return words.size() >=totalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//export headword
|
|
||||||
QString HeadwordListModel::getRow(int row)
|
|
||||||
{
|
|
||||||
if(fileSortedList.empty()){
|
|
||||||
fileSortedList<<words;
|
|
||||||
fileSortedList.sort();
|
|
||||||
}
|
|
||||||
return fileSortedList.at(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeadwordListModel::setFilter(QRegularExpression reg){
|
|
||||||
if(reg.pattern().isEmpty())
|
|
||||||
return;
|
|
||||||
filterWords.clear();
|
|
||||||
auto sr = _dict->prefixMatch(gd::toWString(reg.pattern()),30);
|
|
||||||
connect( sr.get(), SIGNAL( finished() ),
|
|
||||||
this, SLOT( requestFinished() ), Qt::QueuedConnection );
|
|
||||||
queuedRequests.push_back( sr );
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeadwordListModel::requestFinished()
|
|
||||||
{
|
|
||||||
// See how many new requests have finished, and if we have any new results
|
|
||||||
for( std::list< sptr< Dictionary::WordSearchRequest > >::iterator i =
|
|
||||||
queuedRequests.begin(); i != queuedRequests.end(); )
|
|
||||||
{
|
|
||||||
if ( (*i)->isFinished() )
|
|
||||||
{
|
|
||||||
if ( !(*i)->getErrorString().isEmpty() )
|
|
||||||
{
|
|
||||||
qDebug()<<"error:"<<(*i)->getErrorString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (*i)->matchesCount() )
|
|
||||||
{
|
|
||||||
auto allmatches = (*i)->getAllMatches();
|
|
||||||
for(auto& match:allmatches)
|
|
||||||
filterWords.append(gd::toQString(match.word));
|
|
||||||
}
|
|
||||||
queuedRequests.erase( i++ );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(queuedRequests.empty()){
|
|
||||||
QStringList filtered;
|
|
||||||
for(auto& w:filterWords){
|
|
||||||
if(!words.contains(w)){
|
|
||||||
filtered<<w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beginInsertRows(QModelIndex(), words.size(), words.size() + filtered.count() - 1);
|
|
||||||
|
|
||||||
for(const auto & word:filtered)
|
|
||||||
words.append(word);
|
|
||||||
|
|
||||||
endInsertRows();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int HeadwordListModel::wordCount() const{
|
|
||||||
return words.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant HeadwordListModel::data(const QModelIndex &index, int role) const
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
if (index.row() >= totalSize || index.row() < 0 || index.row()>=words.size())
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
|
||||||
return words.at(index.row());
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeadwordListModel::canFetchMore(const QModelIndex &parent) const
|
|
||||||
{
|
|
||||||
if (parent.isValid())
|
|
||||||
return false;
|
|
||||||
return (words.size() < totalSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeadwordListModel::fetchMore(const QModelIndex &parent)
|
|
||||||
{
|
|
||||||
if (parent.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QSet<QString> headword;
|
|
||||||
Mutex::Lock _(lock);
|
|
||||||
_dict->findHeadWordsWithLenth(index,&headword,10000);
|
|
||||||
if(headword.isEmpty()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> filtered;
|
|
||||||
for(const auto & word:qAsConst(headword))
|
|
||||||
{
|
|
||||||
if(!words.contains(word))
|
|
||||||
filtered.insert(word);
|
|
||||||
}
|
|
||||||
|
|
||||||
beginInsertRows(QModelIndex(), words.size(), words.size() + filtered.count() - 1);
|
|
||||||
for(const auto & word:filtered)
|
|
||||||
{
|
|
||||||
words.append(word);
|
|
||||||
}
|
|
||||||
endInsertRows();
|
|
||||||
|
|
||||||
emit numberPopulated(words.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
int HeadwordListModel::getCurrentIndex()
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> HeadwordListModel::getRemainRows(int & nodeIndex)
|
|
||||||
{
|
|
||||||
QSet<QString> headword;
|
|
||||||
Mutex::Lock _(lock);
|
|
||||||
_dict->findHeadWordsWithLenth(nodeIndex, &headword,10000);
|
|
||||||
|
|
||||||
QSet<QString> filtered;
|
|
||||||
for(const auto & word:headword)
|
|
||||||
{
|
|
||||||
if(!words.contains(word))
|
|
||||||
filtered.insert(word);
|
|
||||||
}
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeadwordListModel::setDict(Dictionary::Class * dict){
|
|
||||||
_dict = dict;
|
|
||||||
totalSize = _dict->getWordCount();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
#ifndef HEADWORDSLISTMODEL_H
|
|
||||||
#define HEADWORDSLISTMODEL_H
|
|
||||||
|
|
||||||
#include "dictionary.hh"
|
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
class HeadwordListModel : public QAbstractListModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
HeadwordListModel(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
|
||||||
int totalCount() const;
|
|
||||||
int wordCount() const;
|
|
||||||
bool isFinish() const;
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
||||||
QString getRow(int row);
|
|
||||||
void setFilter(QRegularExpression);
|
|
||||||
int getCurrentIndex();
|
|
||||||
QSet<QString> getRemainRows(int & nodeIndex);
|
|
||||||
signals:
|
|
||||||
void numberPopulated(int number);
|
|
||||||
void finished(int number);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setDict(Dictionary::Class * dict);
|
|
||||||
void requestFinished();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool canFetchMore(const QModelIndex &parent) const override;
|
|
||||||
void fetchMore(const QModelIndex &parent) override;
|
|
||||||
private:
|
|
||||||
QStringList words;
|
|
||||||
QStringList filterWords;
|
|
||||||
QStringList fileSortedList;
|
|
||||||
long totalSize;
|
|
||||||
Dictionary::Class * _dict;
|
|
||||||
int index;
|
|
||||||
char* ptr;
|
|
||||||
Mutex lock;
|
|
||||||
std::list< sptr< Dictionary::WordSearchRequest > > queuedRequests;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // HEADWORDSLISTMODEL_H
|
|
176
headwordsmodel.cpp
Normal file
176
headwordsmodel.cpp
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
#include "headwordsmodel.h"
|
||||||
|
#include "wstring_qt.hh"
|
||||||
|
|
||||||
|
HeadwordListModel::HeadwordListModel( QObject * parent ) :
|
||||||
|
QAbstractListModel( parent ), filtering( false ), index( 0 ), ptr( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int HeadwordListModel::rowCount( const QModelIndex & parent ) const
|
||||||
|
{
|
||||||
|
return parent.isValid() ? 0 : words.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int HeadwordListModel::totalCount() const
|
||||||
|
{
|
||||||
|
return totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeadwordListModel::isFinish() const
|
||||||
|
{
|
||||||
|
return words.size() >= totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// export headword
|
||||||
|
QString HeadwordListModel::getRow( int row )
|
||||||
|
{
|
||||||
|
if( fileSortedList.empty() )
|
||||||
|
{
|
||||||
|
fileSortedList << words;
|
||||||
|
fileSortedList.sort();
|
||||||
|
}
|
||||||
|
return fileSortedList.at( row );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadwordListModel::setFilter( QRegularExpression reg )
|
||||||
|
{
|
||||||
|
if( reg.pattern().isEmpty() )
|
||||||
|
{
|
||||||
|
filtering = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filtering = true;
|
||||||
|
filterWords.clear();
|
||||||
|
auto sr = _dict->prefixMatch( gd::toWString( reg.pattern() ), 30 );
|
||||||
|
connect( sr.get(), SIGNAL( finished() ), this, SLOT( requestFinished() ), Qt::QueuedConnection );
|
||||||
|
queuedRequests.push_back( sr );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadwordListModel::requestFinished()
|
||||||
|
{
|
||||||
|
// See how many new requests have finished, and if we have any new results
|
||||||
|
for( std::list< sptr< Dictionary::WordSearchRequest > >::iterator i = queuedRequests.begin();
|
||||||
|
i != queuedRequests.end(); )
|
||||||
|
{
|
||||||
|
if( ( *i )->isFinished() )
|
||||||
|
{
|
||||||
|
if( !( *i )->getErrorString().isEmpty() )
|
||||||
|
{
|
||||||
|
qDebug() << "error:" << ( *i )->getErrorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( *i )->matchesCount() )
|
||||||
|
{
|
||||||
|
auto allmatches = ( *i )->getAllMatches();
|
||||||
|
for( auto & match : allmatches )
|
||||||
|
filterWords.append( gd::toQString( match.word ) );
|
||||||
|
}
|
||||||
|
queuedRequests.erase( i++ );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( queuedRequests.empty() )
|
||||||
|
{
|
||||||
|
QStringList filtered;
|
||||||
|
for( auto & w : filterWords )
|
||||||
|
{
|
||||||
|
if( !words.contains( w ) )
|
||||||
|
{
|
||||||
|
filtered << w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows( QModelIndex(), words.size(), words.size() + filtered.count() - 1 );
|
||||||
|
|
||||||
|
for( const auto & word : filtered )
|
||||||
|
words.append( word );
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HeadwordListModel::wordCount() const
|
||||||
|
{
|
||||||
|
return words.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant HeadwordListModel::data( const QModelIndex & index, int role ) const
|
||||||
|
{
|
||||||
|
if( !index.isValid() )
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if( index.row() >= totalSize || index.row() < 0 || index.row() >= words.size() )
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if( role == Qt::DisplayRole )
|
||||||
|
{
|
||||||
|
return words.at( index.row() );
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeadwordListModel::canFetchMore( const QModelIndex & parent ) const
|
||||||
|
{
|
||||||
|
if( parent.isValid() || filtering )
|
||||||
|
return false;
|
||||||
|
return ( words.size() < totalSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadwordListModel::fetchMore( const QModelIndex & parent )
|
||||||
|
{
|
||||||
|
if( parent.isValid() || filtering )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QSet< QString > headword;
|
||||||
|
Mutex::Lock _( lock );
|
||||||
|
|
||||||
|
_dict->findHeadWordsWithLenth( index, &headword, 1000 );
|
||||||
|
if( headword.isEmpty() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet< QString > filtered;
|
||||||
|
for( const auto & word : qAsConst( headword ) )
|
||||||
|
{
|
||||||
|
if( !words.contains( word ) )
|
||||||
|
filtered.insert( word );
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows( QModelIndex(), words.size(), words.size() + filtered.count() - 1 );
|
||||||
|
for( const auto & word : filtered )
|
||||||
|
{
|
||||||
|
words.append( word );
|
||||||
|
}
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
emit numberPopulated( words.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int HeadwordListModel::getCurrentIndex()
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet< QString > HeadwordListModel::getRemainRows( int & nodeIndex )
|
||||||
|
{
|
||||||
|
QSet< QString > headword;
|
||||||
|
Mutex::Lock _( lock );
|
||||||
|
_dict->findHeadWordsWithLenth( nodeIndex, &headword, 10000 );
|
||||||
|
|
||||||
|
QSet< QString > filtered;
|
||||||
|
for( const auto & word : headword )
|
||||||
|
{
|
||||||
|
if( !words.contains( word ) )
|
||||||
|
filtered.insert( word );
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeadwordListModel::setDict( Dictionary::Class * dict )
|
||||||
|
{
|
||||||
|
_dict = dict;
|
||||||
|
totalSize = _dict->getWordCount();
|
||||||
|
}
|
50
headwordsmodel.h
Normal file
50
headwordsmodel.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef HEADWORDSMODEL_H
|
||||||
|
#define HEADWORDSMODEL_H
|
||||||
|
|
||||||
|
#include "dictionary.hh"
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class HeadwordListModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
HeadwordListModel( QObject * parent = nullptr );
|
||||||
|
|
||||||
|
int rowCount( const QModelIndex & parent = QModelIndex() ) const override;
|
||||||
|
int totalCount() const;
|
||||||
|
int wordCount() const;
|
||||||
|
bool isFinish() const;
|
||||||
|
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
|
||||||
|
QString getRow( int row );
|
||||||
|
void setFilter( QRegularExpression );
|
||||||
|
int getCurrentIndex();
|
||||||
|
QSet< QString > getRemainRows( int & nodeIndex );
|
||||||
|
signals:
|
||||||
|
void numberPopulated( int number );
|
||||||
|
void finished( int number );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setDict( Dictionary::Class * dict );
|
||||||
|
void requestFinished();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool canFetchMore( const QModelIndex & parent ) const override;
|
||||||
|
void fetchMore( const QModelIndex & parent ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringList words;
|
||||||
|
QStringList filterWords;
|
||||||
|
bool filtering;
|
||||||
|
QStringList fileSortedList;
|
||||||
|
long totalSize;
|
||||||
|
Dictionary::Class * _dict;
|
||||||
|
int index;
|
||||||
|
char * ptr;
|
||||||
|
Mutex lock;
|
||||||
|
std::list< sptr< Dictionary::WordSearchRequest > > queuedRequests;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HEADWORDSMODEL_H
|
104
mdx.cc
104
mdx.cc
|
@ -301,6 +301,10 @@ private:
|
||||||
/// Process resource links (images, audios, etc)
|
/// Process resource links (images, audios, etc)
|
||||||
QString & filterResource( QString const & articleId, QString & article );
|
QString & filterResource( QString const & articleId, QString & article );
|
||||||
|
|
||||||
|
void replaceLinks( QString & id, const QString & articleId, QString & article );
|
||||||
|
//@font-face
|
||||||
|
void replaceFontLinks( QString & id, QString & article );
|
||||||
|
|
||||||
void removeDirectory( QString const & directory );
|
void removeDirectory( QString const & directory );
|
||||||
|
|
||||||
friend class MdxHeadwordsRequest;
|
friend class MdxHeadwordsRequest;
|
||||||
|
@ -954,12 +958,19 @@ void MdxDictionary::loadArticle( uint32_t offset, string & articleText, bool noF
|
||||||
QString & MdxDictionary::filterResource( QString const & articleId, QString & article )
|
QString & MdxDictionary::filterResource( QString const & articleId, QString & article )
|
||||||
{
|
{
|
||||||
QString id = QString::fromStdString( getId() );
|
QString id = QString::fromStdString( getId() );
|
||||||
|
replaceLinks( id, articleId, article );
|
||||||
|
replaceFontLinks( id, article);
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MdxDictionary::replaceLinks( QString & id, const QString & articleId, QString & article )
|
||||||
|
{
|
||||||
QString uniquePrefix = QString::fromLatin1( "g" ) + id + "_" + articleId + "_";
|
QString uniquePrefix = QString::fromLatin1( "g" ) + id + "_" + articleId + "_";
|
||||||
|
|
||||||
QString articleNewText;
|
QString articleNewText;
|
||||||
int linkPos = 0;
|
int linkPos = 0;
|
||||||
QRegularExpressionMatchIterator it = RX::Mdx::allLinksRe.globalMatch( article );
|
QRegularExpressionMatchIterator it = RX::Mdx::allLinksRe.globalMatch( article );
|
||||||
QMap<QString,QString> idMap;
|
QMap< QString, QString > idMap;
|
||||||
while( it.hasNext() )
|
while( it.hasNext() )
|
||||||
{
|
{
|
||||||
QRegularExpressionMatch allLinksMatch = it.next();
|
QRegularExpressionMatch allLinksMatch = it.next();
|
||||||
|
@ -970,7 +981,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
||||||
articleNewText += article.mid( linkPos, allLinksMatch.capturedStart() - linkPos );
|
articleNewText += article.mid( linkPos, allLinksMatch.capturedStart() - linkPos );
|
||||||
linkPos = allLinksMatch.capturedEnd();
|
linkPos = allLinksMatch.capturedEnd();
|
||||||
|
|
||||||
QString linkTxt = allLinksMatch.captured();
|
QString linkTxt = allLinksMatch.captured();
|
||||||
QString linkType = allLinksMatch.captured( 1 ).toLower();
|
QString linkType = allLinksMatch.captured( 1 ).toLower();
|
||||||
QString newLink;
|
QString newLink;
|
||||||
|
|
||||||
|
@ -985,7 +996,7 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
||||||
idMap.insert( wordMatch.captured( 3 ), uniquePrefix + wordMatch.captured( 3 ) );
|
idMap.insert( wordMatch.captured( 3 ), uniquePrefix + wordMatch.captured( 3 ) );
|
||||||
}
|
}
|
||||||
QString newText = match.captured( 1 ) + match.captured( 2 ) + uniquePrefix;
|
QString newText = match.captured( 1 ) + match.captured( 2 ) + uniquePrefix;
|
||||||
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
newLink = linkTxt.replace( RX::Mdx::anchorIdRe2, "\\1\"" + uniquePrefix + "\\2\"" );
|
newLink = linkTxt.replace( RX::Mdx::anchorIdRe2, "\\1\"" + uniquePrefix + "\\2\"" );
|
||||||
|
@ -996,19 +1007,18 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
||||||
if( match.hasMatch() )
|
if( match.hasMatch() )
|
||||||
{
|
{
|
||||||
// sounds and audio link script
|
// sounds and audio link script
|
||||||
QString newTxt = match.captured( 1 ) + match.captured( 2 )
|
QString newTxt =
|
||||||
+ "gdau://" + id + "/"
|
match.captured( 1 ) + match.captured( 2 ) + "gdau://" + id + "/" + match.captured( 3 ) + match.captured( 2 );
|
||||||
+ match.captured( 3 ) + match.captured( 2 );
|
newLink =
|
||||||
newLink = QString::fromUtf8( addAudioLink( "\"gdau://" + getId() + "/" + match.captured( 3 ).toUtf8().data() + "\"", getId() ).c_str() )
|
QString::fromUtf8(
|
||||||
+ newLink.replace( match.capturedStart(), match.capturedLength(), newTxt );
|
addAudioLink( "\"gdau://" + getId() + "/" + match.captured( 3 ).toUtf8().data() + "\"", getId() ).c_str() )
|
||||||
|
+ newLink.replace( match.capturedStart(), match.capturedLength(), newTxt );
|
||||||
}
|
}
|
||||||
|
|
||||||
match = RX::Mdx::wordCrossLink.match( newLink );
|
match = RX::Mdx::wordCrossLink.match( newLink );
|
||||||
if( match.hasMatch() )
|
if( match.hasMatch() )
|
||||||
{
|
{
|
||||||
QString newTxt = match.captured( 1 ) + match.captured( 2 )
|
QString newTxt = match.captured( 1 ) + match.captured( 2 ) + "gdlookup://localhost/" + match.captured( 3 );
|
||||||
+ "gdlookup://localhost/"
|
|
||||||
+ match.captured( 3 );
|
|
||||||
|
|
||||||
if( match.lastCapturedIndex() >= 4 && !match.captured( 4 ).isEmpty() )
|
if( match.lastCapturedIndex() >= 4 && !match.captured( 4 ).isEmpty() )
|
||||||
newTxt += QString( "?gdanchor=" ) + uniquePrefix + match.captured( 4 ).mid( 1 );
|
newTxt += QString( "?gdanchor=" ) + uniquePrefix + match.captured( 4 ).mid( 1 );
|
||||||
|
@ -1017,25 +1027,20 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
||||||
newLink.replace( match.capturedStart(), match.capturedLength(), newTxt );
|
newLink.replace( match.capturedStart(), match.capturedLength(), newTxt );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if( linkType.compare( "link" ) == 0 )
|
||||||
if( linkType.compare( "link" ) == 0 )
|
|
||||||
{
|
{
|
||||||
// stylesheets
|
// stylesheets
|
||||||
QRegularExpressionMatch match = RX::Mdx::stylesRe.match( linkTxt );
|
QRegularExpressionMatch match = RX::Mdx::stylesRe.match( linkTxt );
|
||||||
if( match.hasMatch() )
|
if( match.hasMatch() )
|
||||||
{
|
{
|
||||||
QString newText = match.captured( 1 ) + match.captured( 2 )
|
QString newText =
|
||||||
+ "bres://" + id + "/"
|
match.captured( 1 ) + match.captured( 2 ) + "bres://" + id + "/" + match.captured( 3 ) + match.captured( 2 );
|
||||||
+ match.captured( 3 ) + match.captured( 2 );
|
|
||||||
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
newLink = linkTxt.replace( RX::Mdx::stylesRe2,
|
newLink = linkTxt.replace( RX::Mdx::stylesRe2, "\\1\"bres://" + id + "/\\2\"" );
|
||||||
"\\1\"bres://" + id + "/\\2\"" );
|
|
||||||
}
|
}
|
||||||
else
|
else if( linkType.compare( "script" ) == 0 || linkType.compare( "img" ) == 0 || linkType.compare( "source" ) == 0 )
|
||||||
if( linkType.compare( "script" ) == 0 || linkType.compare( "img" ) == 0
|
|
||||||
|| linkType.compare( "source" ) == 0 )
|
|
||||||
{
|
{
|
||||||
// javascripts and images
|
// javascripts and images
|
||||||
QRegularExpressionMatch match = RX::Mdx::inlineScriptRe.match( linkTxt );
|
QRegularExpressionMatch match = RX::Mdx::inlineScriptRe.match( linkTxt );
|
||||||
|
@ -1061,22 +1066,19 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
||||||
if( linkType.at( 1 ) == 'o' ) // "source" tag
|
if( linkType.at( 1 ) == 'o' ) // "source" tag
|
||||||
{
|
{
|
||||||
QString filename = match.captured( 3 );
|
QString filename = match.captured( 3 );
|
||||||
QString newName = getCachedFileName( filename );
|
QString newName = getCachedFileName( filename );
|
||||||
newName.replace( '\\', '/' );
|
newName.replace( '\\', '/' );
|
||||||
newText = match.captured( 1 ) + match.captured( 2 )
|
newText = match.captured( 1 ) + match.captured( 2 ) + "file:///" + newName + match.captured( 2 );
|
||||||
+ "file:///" + newName + match.captured( 2 );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newText = match.captured( 1 ) + match.captured( 2 )
|
newText = match.captured( 1 ) + match.captured( 2 ) + "bres://" + id + "/" + match.captured( 3 )
|
||||||
+ "bres://" + id + "/"
|
+ match.captured( 2 );
|
||||||
+ match.captured( 3 ) + match.captured( 2 );
|
|
||||||
}
|
}
|
||||||
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
newLink = linkTxt.replace( match.capturedStart(), match.capturedLength(), newText );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
newLink = linkTxt.replace( RX::Mdx::srcRe2,
|
newLink = linkTxt.replace( RX::Mdx::srcRe2, "\\1\"bres://" + id + "/\\2\"" );
|
||||||
"\\1\"bres://" + id + "/\\2\"" );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( !newLink.isEmpty() )
|
if( !newLink.isEmpty() )
|
||||||
|
@ -1092,14 +1094,46 @@ QString & MdxDictionary::filterResource( QString const & articleId, QString & ar
|
||||||
article = articleNewText;
|
article = articleNewText;
|
||||||
}
|
}
|
||||||
|
|
||||||
//some built-in javascript may reference this id. replace "idxxx" with "unique_idxxx"
|
// some built-in javascript may reference this id. replace "idxxx" with "unique_idxxx"
|
||||||
foreach ( const auto& key, idMap.keys() )
|
foreach( const auto & key, idMap.keys() )
|
||||||
{
|
{
|
||||||
const auto& value = idMap[ key ];
|
const auto & value = idMap[ key ];
|
||||||
article.replace("\""+key+"\"","\""+value+"\"");
|
article.replace( "\"" + key + "\"", "\"" + value + "\"" );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return article;
|
void MdxDictionary::replaceFontLinks( QString & id, QString & article )
|
||||||
|
{
|
||||||
|
//article = article.replace( RX::Mdx::fontFace, "src:url(\"bres://" + id + "/" + "\\1\")" );
|
||||||
|
QString articleNewText;
|
||||||
|
int linkPos = 0;
|
||||||
|
QRegularExpressionMatchIterator it = RX::Mdx::fontFace.globalMatch( article );
|
||||||
|
while( it.hasNext() )
|
||||||
|
{
|
||||||
|
QRegularExpressionMatch allLinksMatch = it.next();
|
||||||
|
|
||||||
|
if( allLinksMatch.capturedEnd() < linkPos )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
articleNewText += article.mid( linkPos, allLinksMatch.capturedStart() - linkPos );
|
||||||
|
linkPos = allLinksMatch.capturedEnd();
|
||||||
|
|
||||||
|
QString linkTxt = allLinksMatch.captured();
|
||||||
|
QString linkType = allLinksMatch.captured( 1 );
|
||||||
|
QString newLink = linkTxt;
|
||||||
|
|
||||||
|
//skip remote url
|
||||||
|
if( !linkType.contains( ":" ) )
|
||||||
|
{
|
||||||
|
newLink = QString( "url(\"bres://%1/%2\")" ).arg( id, linkType );
|
||||||
|
}
|
||||||
|
articleNewText += newLink;
|
||||||
|
}
|
||||||
|
if( linkPos )
|
||||||
|
{
|
||||||
|
articleNewText += article.mid( linkPos );
|
||||||
|
article = articleNewText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
14
scanpopup.cc
14
scanpopup.cc
|
@ -1136,11 +1136,15 @@ void ScanPopup::altModePoll()
|
||||||
|
|
||||||
void ScanPopup::pageLoaded( ArticleView * )
|
void ScanPopup::pageLoaded( ArticleView * )
|
||||||
{
|
{
|
||||||
|
if( !isVisible() )
|
||||||
|
return;
|
||||||
definition->hasSound([this](bool has){
|
auto pronounceBtn = ui.pronounceButton;
|
||||||
ui.pronounceButton->setVisible( has );
|
definition->hasSound(
|
||||||
});
|
[ pronounceBtn ]( bool has )
|
||||||
|
{
|
||||||
|
if( pronounceBtn )
|
||||||
|
pronounceBtn->setVisible( has );
|
||||||
|
} );
|
||||||
|
|
||||||
updateBackForwardButtons();
|
updateBackForwardButtons();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue