fix conflict

This commit is contained in:
xiaoyifang 2022-01-08 22:07:33 +08:00
commit 0c55c85339
34 changed files with 292 additions and 160 deletions

View file

@ -44,7 +44,7 @@ About::About( QWidget * parent ): QDialog( parent )
{
QStringList creditsList =
QString::fromUtf8(
creditsFile.readAll() ).split( '\n', QString::SkipEmptyParts );
creditsFile.readAll() ).split( '\n', Qt::SkipEmptyParts );
QString html = "<html><body style='color: black; background: #f4f4f4;'>";

View file

@ -14,6 +14,7 @@
#include "langcoder.hh"
#include "gddebug.hh"
#include "utils.hh"
#include "globalbroadcaster.h"
using std::vector;
using std::string;
@ -55,6 +56,10 @@ std::string ArticleMaker::makeHtmlHeader( QString const & word,
{
result += "<script type=\"text/javascript\" "
"src=\"qrc:///resources/jquery-3.6.0.slim.min.js\"></script>";
//custom javascript
result += "<script type=\"text/javascript\" "
"src=\"qrc:///resources/gd_custom.js\"></script>";
}
// add qwebchannel
@ -630,6 +635,7 @@ void ArticleRequest::bodyFinished()
bool wasUpdated = false;
QStringList dictIds;
while ( bodyRequests.size() )
{
// Since requests should go in order, check the first one first
@ -649,7 +655,7 @@ void ArticleRequest::bodyFinished()
activeDicts[ activeDicts.size() - bodyRequests.size() ];
string dictId = activeDict->getId();
dictIds << QString::fromStdString(dictId);
string head;
string gdFrom = "gdfrom-" + Html::escape( dictId );
@ -702,14 +708,6 @@ void ArticleRequest::bodyFinished()
}
string jsVal = Html::escapeForJavaScript( dictId );
head += "<script type=\"text/javascript\">var gdArticleContents; "
"if ( !gdArticleContents ) gdArticleContents = \"" + jsVal +" \"; "
"else gdArticleContents += \"" + jsVal + " \";"
"function playSound(sound){"
" var a=new Audio(sound);"
" a.play();"
"}"
"</script>";
head += string( "<div class=\"gdarticle" ) +
( closePrevSpan ? "" : " gdactivearticle" ) +
@ -787,6 +785,7 @@ void ArticleRequest::bodyFinished()
}
}
if ( bodyRequests.empty() )
{
// No requests left, end the article
@ -834,12 +833,16 @@ void ArticleRequest::bodyFinished()
if ( stemmedWordFinder.get() )
update();
else
else {
finish();
}
else
if ( wasUpdated )
qDebug() << "send dicts:" << dictIds;
emit GlobalBroadcaster::instance()->emitDictIds(ActiveDictIds{word, dictIds});
}
} else if (wasUpdated) {
update();
qDebug() << "send dicts(updated):" << dictIds;
emit GlobalBroadcaster::instance()->emitDictIds(ActiveDictIds{word, dictIds});
}
}
void ArticleRequest::stemmedSearchFinished()

View file

@ -207,10 +207,10 @@ QNetworkReply * ArticleNetworkAccessManager::createRequest( Operation op,
return QNetworkAccessManager::createRequest( op, newReq, outgoingData );
}
QString contentType;
QUrl url=req.url();
QMimeType mineType=db.mimeTypeForUrl (url);
QString contentType=mineType.name();
if(req.url().scheme()=="gdlookup"){
QString path=url.path();
if(!path.isEmpty()){
@ -379,7 +379,6 @@ sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource(
{
if( url.scheme() == "gico" )
{
contentType="image/png";
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
@ -485,8 +484,6 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize )
if ( maxSize == 0 )
return 0;
GD_DPRINTF( "====reading %d bytes\n", (int)maxSize );
bool finished = req->isFinished();
qint64 avail = req->dataSize();
@ -497,6 +494,7 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize )
qint64 left = avail - alreadyRead;
qint64 toRead = maxSize < left ? maxSize : left;
GD_DPRINTF( "====reading %d bytes\n", (int)toRead );
try
{
@ -517,13 +515,15 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize )
void ArticleResourceReply::readyReadSlot()
{
readyRead();
emit readyRead();
}
void ArticleResourceReply::finishedSlot()
{
if ( req->dataSize() < 0 )
error( ContentNotFoundError );
if (req->dataSize() < 0) {
emit error(ContentNotFoundError);
setError(ContentNotFoundError, "content not found");
}
emit finished();
}

View file

@ -99,6 +99,7 @@ class ArticleNetworkAccessManager: public QNetworkAccessManager
ArticleMaker const & articleMaker;
bool const & disallowContentFromOtherSites;
bool const & hideGoldenDictHeader;
QMimeDatabase db;
public:

View file

@ -28,7 +28,7 @@
#include <QWebEngineSettings>
#include <assert.h>
#include <map>
#include <QWebEngineContextMenuData>
#ifdef Q_OS_WIN32
#include <windows.h>
#include <QPainter>
@ -40,6 +40,7 @@
#include "speechclient.hh"
#endif
#include "globalbroadcaster.h"
using std::map;
using std::list;
@ -180,7 +181,7 @@ QString ArticleView::runJavaScriptSync(QWebEnginePage* frame, const QString& var
QString result;
QSharedPointer<QEventLoop> loop = QSharedPointer<QEventLoop>(new QEventLoop());
QTimer::singleShot(1000, loop.data(), &QEventLoop::quit);
frame->runJavaScript(variable, [loop,&result](const QVariant &v)
frame->runJavaScript(variable, [=,&result](const QVariant &v)
{
if(loop->isRunning()){
if(v.isValid())
@ -275,8 +276,6 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm,
connect(ui.definition, SIGNAL(loadFinished(bool)), this,
SLOT(loadFinished(bool)));
attachToJavaScript();
connect( ui.definition->page(), SIGNAL( titleChanged( QString const & ) ),
this, SLOT( handleTitleChanged( QString const & ) ) );
@ -340,6 +339,7 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm,
QWebEngineSettings * settings = ui.definition->page()->settings();
settings->defaultSettings()->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessFileUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::WebAttribute::ErrorPageEnabled, false);
// Load the default blank page instantly, so there would be no flicker.
QString contentType;
@ -359,6 +359,12 @@ ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm,
// Variable name for store current selection range
rangeVarName = QString( "sr_%1" ).arg( QString::number( (quint64)this, 16 ) );
connect(GlobalBroadcaster::instance(), SIGNAL( emitDictIds(ActiveDictIds)), this,
SLOT(setActiveDictIds(ActiveDictIds)));
channel = new QWebChannel(ui.definition->page());
attachToJavaScript();
}
// explicitly report the minimum size, to avoid
@ -377,7 +383,7 @@ ArticleView::~ArticleView()
{
cleanupTemp();
audioPlayer->stop();
channel->deregisterObject(this);
ui.definition->ungrabGesture( Gestures::GDPinchGestureType );
ui.definition->ungrabGesture( Gestures::GDSwipeGestureType );
}
@ -386,6 +392,8 @@ void ArticleView::showDefinition( Config::InputPhrase const & phrase, unsigned g
QString const & scrollTo,
Contexts const & contexts_ )
{
currentWord = phrase.phrase;
currentActiveDictIds.clear();
// first, let's stop the player
audioPlayer->stop();
@ -508,15 +516,14 @@ void ArticleView::showAnticipation()
void ArticleView::loadFinished( bool )
{
QUrl url = ui.definition->url();
QObject* obj=sender();
qDebug()<<"article view loaded url:"<<url;
setZoomFactor(cfg.preferences.zoomFactor);
QUrl url = ui.definition->url();
qDebug() << "article view loaded url:" << url;
QVariant userDataVariant = ui.definition->property("currentArticle");
if ( userDataVariant.isValid() )
{
QString currentArticle = userDataVariant.toString();
if ( !currentArticle.isEmpty() )
@ -645,8 +652,7 @@ unsigned ArticleView::getGroup( QUrl const & url )
QStringList ArticleView::getArticlesList()
{
return runJavaScriptSync( ui.definition->page(), "gdArticleContents" )
.trimmed().split( ' ', Qt::SkipEmptyParts );
return currentActiveDictIds;
}
QString ArticleView::getActiveArticleId()
@ -758,7 +764,7 @@ void ArticleView::tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts )
void ArticleView::updateCurrentArticleFromCurrentFrame( QWebEnginePage * frame ,QPoint * point)
{
qDebug("updateCurrentArticleFromCurrentFrame");
}
void ArticleView::saveHistoryUserData()
@ -916,7 +922,8 @@ bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
keyEvent->key() == Qt::Key_Tab ||
keyEvent->key() == Qt::Key_Backtab ||
keyEvent->key() == Qt::Key_Return ||
keyEvent->key() == Qt::Key_Enter )
keyEvent->key() == Qt::Key_Enter ||
keyEvent->key() == Qt::Key_Escape)
return false; // Those key have other uses than to start typing
QString text = keyEvent->text();
@ -972,41 +979,36 @@ QString ArticleView::getMutedForGroup( unsigned group )
return QString();
}
QStringList ArticleView::getMutedDictionaries(unsigned group)
{
if (dictionaryBarToggled && dictionaryBarToggled->isChecked())
{
// Dictionary bar is active -- mute the muted dictionaries
Instances::Group const* groupInstance = groups.findGroup(group);
QStringList ArticleView::getMutedDictionaries(unsigned group) {
if (dictionaryBarToggled && dictionaryBarToggled->isChecked()) {
// Dictionary bar is active -- mute the muted dictionaries
Instances::Group const *groupInstance = groups.findGroup(group);
// Find muted dictionaries for current group
Config::Group const* grp = cfg.getGroup(group);
Config::MutedDictionaries const* mutedDictionaries;
if (group == Instances::Group::AllGroupId)
mutedDictionaries = popupView ? &cfg.popupMutedDictionaries : &cfg.mutedDictionaries;
else
mutedDictionaries = grp ? (popupView ? &grp->popupMutedDictionaries : &grp->mutedDictionaries) : 0;
if (!mutedDictionaries)
return QStringList();
// Find muted dictionaries for current group
Config::Group const *grp = cfg.getGroup(group);
Config::MutedDictionaries const *mutedDictionaries;
if (group == Instances::Group::AllGroupId)
mutedDictionaries = popupView ? &cfg.popupMutedDictionaries : &cfg.mutedDictionaries;
else
mutedDictionaries = grp ? (popupView ? &grp->popupMutedDictionaries : &grp->mutedDictionaries) : 0;
if (!mutedDictionaries)
return QStringList();
QStringList mutedDicts;
QStringList mutedDicts;
if (groupInstance)
{
for (unsigned x = 0; x < groupInstance->dictionaries.size(); ++x)
{
QString id = QString::fromStdString(
groupInstance->dictionaries[x]->getId());
if (groupInstance) {
for (unsigned x = 0; x < groupInstance->dictionaries.size(); ++x) {
QString id = QString::fromStdString(groupInstance->dictionaries[x]->getId());
if (mutedDictionaries->contains(id))
mutedDicts.append(id);
}
}
if (mutedDictionaries->contains(id))
mutedDicts.append(id);
}
}
return mutedDicts;
}
return mutedDicts;
}
return QStringList();
return QStringList();
}
void ArticleView::linkHovered ( const QString & link )
@ -1084,7 +1086,7 @@ void ArticleView::linkHovered ( const QString & link )
}
void ArticleView::attachToJavaScript() {
QWebChannel *channel = new QWebChannel(ui.definition->page());
// set the web channel to be used by the page
// see http://doc.qt.io/qt-5/qwebenginepage.html#setWebChannel
@ -1124,7 +1126,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QString const & scrollTo,
Contexts const & contexts_ )
{
qDebug() << "clicked" << url;
qDebug() << "open link url:" << url;
Contexts contexts( contexts_ );
@ -1716,13 +1718,14 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
QAction * saveImageAction = 0;
QAction * saveSoundAction = 0;
//todo url() or lastclickurl ?
QUrl targetUrl( r->url() );
QWebEngineContextMenuData menuData=r->contextMenuData();
QUrl targetUrl(menuData.linkUrl());
qDebug() << "menu:" << menuData.linkText()<<":"<<menuData.mediaUrl();
Contexts contexts;
tryMangleWebsiteClickedUrl( targetUrl, contexts );
if ( !r->url().isEmpty() )
if ( !targetUrl.isEmpty() )
{
if ( !isExternalLink( targetUrl ) )
{
@ -1737,7 +1740,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
}
}
if ( isExternalLink( r->url() ) )
if ( isExternalLink( targetUrl ) )
{
followLinkExternal = new QAction( tr( "Open Link in &External Browser" ), &menu );
menu.addAction( followLinkExternal );
@ -1745,6 +1748,25 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
}
}
QUrl imageUrl;
if( !popupView && menuData.mediaType ()==QWebEngineContextMenuData::MediaTypeImage)
{
imageUrl = menuData.mediaUrl ();
if( !imageUrl.isEmpty() )
{
menu.addAction( ui.definition->pageAction( QWebEnginePage::CopyImageToClipboard ) );
saveImageAction = new QAction( tr( "Save &image..." ), &menu );
menu.addAction( saveImageAction );
}
}
if( !popupView && ( targetUrl.scheme() == "gdau"
|| Dictionary::WebMultimediaDownload::isAudioUrl( targetUrl ) ) )
{
saveSoundAction = new QAction( tr( "Save s&ound..." ), &menu );
menu.addAction( saveSoundAction );
}
QString selectedText = ui.definition->selectedText();
QString text = selectedText.trimmed();
@ -1896,7 +1918,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
openLink( targetUrl, ui.definition->url(), getCurrentArticle(), contexts );
else
if ( result == followLinkExternal )
QDesktopServices::openUrl( r->url() );
QDesktopServices::openUrl( targetUrl );
else
if ( result == lookupSelection )
showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() );
@ -1988,7 +2010,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
}
}
qDebug( "url = %s\n", r->url().toString().toLocal8Bit().data() );
qDebug( "url = %s\n", targetUrl.toString().toLocal8Bit().data() );
qDebug( "title = %s\n", r->title().toLocal8Bit().data() );
}
@ -2526,6 +2548,16 @@ QString ArticleView::getWebPageTextSync(QWebEnginePage * page){
return planText;
}
void ArticleView::setActiveDictIds(ActiveDictIds ad) {
// ignore all other signals.
if (ad.word == currentWord) {
currentActiveDictIds << ad.dictIds;
currentActiveDictIds.removeDuplicates();
qDebug() << "current word:"<<currentWord<<"receivedd:"<<ad.word<<":" << ad.dictIds<<this;
}
}
//todo ,futher refinement?
void ArticleView::performFtsFindOperation( bool backwards )
{

View file

@ -14,6 +14,7 @@
#include "instances.hh"
#include "groupcombobox.hh"
#include "ui_articleview.h"
#include "globalbroadcaster.h"
class ResourceToSaveHandler;
@ -29,7 +30,7 @@ class ArticleView: public QFrame
Instances::Groups const & groups;
bool popupView;
Config::Class const & cfg;
QWebChannel *channel;
Ui::ArticleView ui;
QAction pasteAction, articleUpAction, articleDownAction,
@ -55,7 +56,13 @@ class ArticleView: public QFrame
QSet< QString > desktopOpenedTempFiles;
QAction * dictionaryBarToggled;
GroupComboBox const * groupComboBox;
GroupComboBox const *groupComboBox;
/// current searching word.
QString currentWord;
/// current active dict id list;
QStringList currentActiveDictIds;
/// Search in results of full-text search
QStringList allMatches;
@ -276,14 +283,14 @@ public slots:
/// Selects an entire text of the current article
void selectCurrentArticle();
void linkClicked( QUrl const & );
private slots:
void loadFinished( bool ok );
void handleTitleChanged( QString const & title );
void handleUrlChanged( QUrl const & url );
void attachToJavaScript();
void linkClicked( QUrl const & );
void linkHovered( const QString & link);
void contextMenuRequested( QPoint const & );
@ -322,13 +329,14 @@ private slots:
/// Inspect element
void inspect();
void setActiveDictIds(ActiveDictIds);
private:
/// Deduces group from the url. If there doesn't seem to be any group,
/// returns 0.
unsigned getGroup( QUrl const & );
/// Returns current article in the view, in the form of "gdfrom-xxx" id.
QString getCurrentArticle();
@ -374,6 +382,7 @@ private:
QStringList getMutedDictionaries(unsigned group);
protected:
// We need this to hide the search bar when we're showed
void showEvent( QShowEvent * );

View file

@ -64,7 +64,7 @@ bool ArticleWebView::eventFilter(QObject *obj, QEvent *ev)
mouseReleaseEvent(pe);
if (firstClicked) {
QTimer::singleShot(QApplication::doubleClickInterval(),this,[=](){
singleClickAction(pe);
singleClickAction(obj,pe);
});
} else {
doubleClickAction(pe);
@ -73,12 +73,10 @@ bool ArticleWebView::eventFilter(QObject *obj, QEvent *ev)
if (ev->type() == QEvent::Wheel) {
QWheelEvent *pe = static_cast<QWheelEvent *>(ev);
wheelEvent(pe);
//return true;
}
if (ev->type() == QEvent::FocusIn) {
QFocusEvent *pe = static_cast<QFocusEvent *>(ev);
focusInEvent(pe);
//return true;
}
return QWebEngineView::eventFilter(obj, ev);
@ -92,36 +90,31 @@ void ArticleWebView::mousePressEvent(QMouseEvent *event)
//QWebEngineView::mousePressEvent(event);
}
void ArticleWebView::singleClickAction( QMouseEvent * event )
void ArticleWebView::singleClickAction(QObject* obj, QMouseEvent * event )
{
if(!firstClicked)
return;
if (selectionBySingleClick) {
// findText(""); // clear the selection first, if any
page()->runJavaScript(QString(
" var s = window.getSelection(); "
" if(s.rangeCount>0){ "
" var range = s.getRangeAt(0); "
" var node = s.anchorNode; "
" while (range.toString().indexOf(' ') != 0) { "
" range.setStart(node, (range.startOffset - 1)); "
" } "
" range.setStart(node, range.startOffset + 1); "
" do { "
" range.setEnd(node, range.endOffset+1); "
" } "
" while (range.toString().indexOf(' ') == -1 && range.toString().trim() != ''); "
" range.setEnd(node,range.endOffset-1);"
" var str = range.toString().trim(); "
" console.log(str);"
" }"));
findText(""); // clear the selection first, if any
//send dbl click event twice? send one time seems not work .weird really. need further investigate.
sendCustomMouseEvent(obj, QEvent::MouseButtonDblClick);
sendCustomMouseEvent(obj, QEvent::MouseButtonDblClick);
}
}
void ArticleWebView::sendCustomMouseEvent(QObject *obj, QEvent::Type type) {
QPoint pt = mapFromGlobal(QCursor::pos());
QMouseEvent ev(type, pt, pt, QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier,
Qt::MouseEventSynthesizedByApplication);
void ArticleWebView::mouseReleaseEvent( QMouseEvent * event )
{
QObjectList list = this->children();
for (int i = 0; i < list.size(); i++) {
QApplication::sendEvent(list[i], &ev);
}
}
void ArticleWebView::mouseReleaseEvent(QMouseEvent *event) {
bool noMidButton = !( event->buttons() & Qt::MiddleButton );
//QWebEngineView::mouseReleaseEvent( event );
@ -130,18 +123,13 @@ void ArticleWebView::mouseReleaseEvent( QMouseEvent * event )
midButtonPressed = false;
}
void ArticleWebView::doubleClickAction( QMouseEvent * event )
{
//QWebEngineView::mouseDoubleClickEvent( event );
void ArticleWebView::doubleClickAction(QMouseEvent *event) {
// QWebEngineView::mouseDoubleClickEvent( event );
int scrollBarWidth = 0;
int scrollBarHeight = 0;
// emit the signal only if we are not double-clicking on scrollbars
if ((event->x() < width() - scrollBarWidth) && (event->y() < height() - scrollBarHeight)) {
emit doubleClicked(event->pos());
// emit the signal only if we are not double-clicking on scrollbars
if (Qt::MouseEventSynthesizedByApplication != event->source()) {
emit doubleClicked(event->pos());
}
}
void ArticleWebView::focusInEvent( QFocusEvent * event )

View file

@ -51,7 +51,8 @@ public:
protected:
bool event( QEvent * event );
void singleClickAction( QMouseEvent * event );
void singleClickAction(QObject *obj, QMouseEvent *event);
void sendCustomMouseEvent(QObject *obj, QEvent::Type type);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent( QMouseEvent * event );
void doubleClickAction( QMouseEvent * event );

View file

@ -200,11 +200,11 @@ public:
if( pos < 0 )
url = "dict://" + url;
databases = database_.split( QRegExp( "[ ,;]" ), QString::SkipEmptyParts );
databases = database_.split( QRegExp( "[ ,;]" ), Qt::SkipEmptyParts );
if( databases.isEmpty() )
databases.append( "*" );
strategies = strategies_.split( QRegExp( "[ ,;]" ), QString::SkipEmptyParts );
strategies = strategies_.split( QRegExp( "[ ,;]" ), Qt::SkipEmptyParts );
if( strategies.isEmpty() )
strategies.append( "prefix" );
}

View file

@ -555,7 +555,7 @@ bool EpwingBook::setSubBook( int book_nom )
QString line = ts.readLine();
while( !line.isEmpty() )
{
QStringList list = line.remove( '\n' ).split( ' ', QString::SkipEmptyParts );
QStringList list = line.remove( '\n' ).split( ' ', Qt::SkipEmptyParts );
if( list.count() == 2 )
customFontsMap[ list[ 0 ] ] = list[ 1 ];
line = ts.readLine();

View file

@ -976,7 +976,7 @@ bool FavoritesModel::addNewHeadword( const QString & path, const QString & headw
// Find or create target folder
QStringList folders = path.split( "/", QString::SkipEmptyParts );
QStringList folders = path.split( "/", Qt::SkipEmptyParts );
QStringList::const_iterator it = folders.begin();
for( ; it != folders.end(); ++it )
parentIdx = forceFolder( *it, parentIdx );
@ -992,7 +992,7 @@ bool FavoritesModel::removeHeadword( const QString & path, const QString & headw
// Find target folder
QStringList folders = path.split( "/", QString::SkipEmptyParts );
QStringList folders = path.split( "/", Qt::SkipEmptyParts );
QStringList::const_iterator it = folders.begin();
for( ; it != folders.end(); ++it )
{
@ -1022,7 +1022,7 @@ bool FavoritesModel::isHeadwordPresent( const QString & path, const QString & he
// Find target folder
QStringList folders = path.split( "/", QString::SkipEmptyParts );
QStringList folders = path.split( "/", Qt::SkipEmptyParts );
QStringList::const_iterator it = folders.begin();
for( ; it != folders.end(); ++it )
{

View file

@ -353,7 +353,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
if ( forvo.enable )
{
QStringList codes = forvo.languageCodes.split( ',', QString::SkipEmptyParts );
QStringList codes = forvo.languageCodes.split( ',', Qt::SkipEmptyParts );
QSet< QString > usedCodes;

View file

@ -91,17 +91,17 @@ bool parseSearchString( QString const & str, QStringList & indexWords,
// Make words list for search in article text
searchWords = str.normalized( QString::NormalizationForm_C )
.split( spacesRegExp, QString::SkipEmptyParts );
.split( spacesRegExp, Qt::SkipEmptyParts );
// Make words list for index search
QStringList list = str.normalized( QString::NormalizationForm_C )
.toLower().split( spacesRegExp, QString::SkipEmptyParts );
.toLower().split( spacesRegExp, Qt::SkipEmptyParts );
indexWords = list.filter( wordRegExp );
indexWords.removeDuplicates();
// Make regexp for results hilite
QStringList allWords = str.split( spacesRegExp, QString::SkipEmptyParts );
QStringList allWords = str.split( spacesRegExp, Qt::SkipEmptyParts );
QString searchString = makeHiliteRegExpString( allWords, searchMode, distanceBetweenWords );
searchRegExp = QRegExp( searchString, matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive,
@ -124,7 +124,7 @@ bool parseSearchString( QString const & str, QStringList & indexWords,
tmp.replace( setsRegExp, " " );
QStringList list = tmp.normalized( QString::NormalizationForm_C )
.toLower().split( spacesRegExp, QString::SkipEmptyParts );
.toLower().split( spacesRegExp, Qt::SkipEmptyParts );
if( hasCJK )
{
@ -189,7 +189,7 @@ void parseArticleForFts( uint32_t articleAddress, QString & articleText,
QStringList articleWords = articleText.normalized( QString::NormalizationForm_C )
.split( QRegularExpression( handleRoundBrackets ? "[^\\w\\(\\)\\p{M}]+" : "[^\\w\\p{M}]+",
QRegularExpression::UseUnicodePropertiesOption ),
QString::SkipEmptyParts );
Qt::SkipEmptyParts );
QSet< QString > setOfWords;
@ -233,7 +233,7 @@ void parseArticleForFts( uint32_t articleAddress, QString & articleText,
// Special handle for words with round brackets - DSL feature
QStringList list;
QStringList oldVariant = word.split( regSplit, QString::SkipEmptyParts );
QStringList oldVariant = word.split( regSplit, Qt::SkipEmptyParts );
for( QStringList::iterator it = oldVariant.begin(); it != oldVariant.end(); ++it )
if( it->size() >= FTS::MinimumWordSize && !list.contains( *it ) )
list.append( *it );
@ -509,7 +509,7 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets,
articleText = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( articleText ) ) );
QStringList articleWords = articleText.split( needHandleBrackets ? splitWithBrackets : splitWithoutBrackets,
QString::SkipEmptyParts );
Qt::SkipEmptyParts );
int wordsNum = articleWords.length();
while ( pos < wordsNum )
@ -540,7 +540,7 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets,
parsedWords.append( word );
}
else
parsedWords = s.split( regSplit, QString::SkipEmptyParts );
parsedWords = s.split( regSplit, Qt::SkipEmptyParts );
}
else
parsedWords.append( s );

View file

@ -10,10 +10,17 @@ void GicoSchemeHandler::requestStarted(QWebEngineUrlRequestJob *requestJob)
QNetworkRequest request;
request.setUrl( url );
QNetworkReply* reply=this->mManager.createRequest(QNetworkAccessManager::GetOperation,request,NULL);
QNetworkReply *reply = this->mManager.createRequest(QNetworkAccessManager::GetOperation, request, NULL);
QMimeType mineType=db.mimeTypeForUrl (url);
QString contentType=mineType.name ();
// Reply segment
requestJob->reply(contentType.toLatin1(), reply);
connect(reply, &QNetworkReply::finished, requestJob, [=]() {
if (reply->error() == QNetworkReply::ContentNotFoundError) {
requestJob->fail(QWebEngineUrlRequestJob::UrlNotFound);
return;
}
QMimeType mineType = db.mimeTypeForUrl(url);
QString contentType = mineType.name();
// Reply segment
requestJob->reply(contentType.toLatin1(), reply);
});
}

14
globalbroadcaster.cpp Normal file
View file

@ -0,0 +1,14 @@
#include "globalbroadcaster.h"
#include <QGlobalStatic>
Q_GLOBAL_STATIC(GlobalBroadcaster, bdcaster)
GlobalBroadcaster::GlobalBroadcaster(QObject *parent) : QObject(parent)
{
}
GlobalBroadcaster* GlobalBroadcaster::instance() { return bdcaster; }
// namespace global

24
globalbroadcaster.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef GLOBAL_GLOBALBROADCASTER_H
#define GLOBAL_GLOBALBROADCASTER_H
#include <QObject>
struct ActiveDictIds {
QString word;
QStringList dictIds;
}
;
class GlobalBroadcaster : public QObject
{
Q_OBJECT
public:
GlobalBroadcaster(QObject *parent = nullptr);
static GlobalBroadcaster *instance();
signals:
void emitDictIds(ActiveDictIds ad);
};
#endif // GLOBAL_GLOBALBROADCASTER_H

View file

@ -250,6 +250,7 @@ DEFINES += PROGRAM_VERSION=\\\"$$VERSION\\\"
# Input
HEADERS += folding.hh \
gico_schemahandler.h \
globalbroadcaster.h \
inc_case_folding.hh \
inc_diacritic_folding.hh \
mainwindow.hh \
@ -390,6 +391,7 @@ FORMS += groups.ui \
SOURCES += folding.cc \
gico_schemahandler.cpp \
globalbroadcaster.cpp \
main.cc \
dictionary.cc \
config.cc \

View file

@ -263,8 +263,7 @@ int main( int argc, char ** argv )
#endif
QStringList localSchemes={"gdlookup","gdau","gico","qrcx","bres","bword"};
QStringList localSchemes={"gdlookup","gdau","gico","qrcx","bres","bword","gdprg","gdvideo","gdpicture","gdtts"};
for (int i = 0; i < localSchemes.size(); ++i)
{
@ -272,11 +271,11 @@ int main( int argc, char ** argv )
QWebEngineUrlScheme webUiScheme(localScheme.toLatin1());
webUiScheme.setFlags(QWebEngineUrlScheme::SecureScheme |
QWebEngineUrlScheme::LocalScheme |
QWebEngineUrlScheme::LocalAccessAllowed);
QWebEngineUrlScheme::LocalAccessAllowed|
QWebEngineUrlScheme::CorsEnabled);
QWebEngineUrlScheme::registerScheme(webUiScheme);
}
QHotkeyApplication app( "GoldenDict", argc, argv );
LogFilePtrGuard logFilePtrGuard;

View file

@ -150,7 +150,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler("gdlookup", handler);
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler("bword", handler);
QStringList localSchemes={"gdau","gico","qrcx","bres"};
QStringList localSchemes={"gdau","gico","qrcx","bres","gdprg","gdvideo","gdpicture","gdtts"};
GicoSchemeHandler *h=new GicoSchemeHandler(articleNetMgr);
for(int i=0;i<localSchemes.size();i++){
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler(localSchemes.at(i).toLatin1(), h);
@ -1219,12 +1219,21 @@ void MainWindow::closeEvent( QCloseEvent * ev )
{
if ( cfg.preferences.enableTrayIcon && cfg.preferences.closeToTray )
{
ev->ignore();
if( !cfg.preferences.searchInDock )
translateBox->setPopupEnabled( false );
#ifdef HAVE_X11
// Don't ignore the close event, because doing so cancels session logout if
// the main window is visible when the user attempts to log out.
// The main window will be only hidden, because QApplication::quitOnLastWindowClosed
// property is false and Qt::WA_DeleteOnClose widget attribute is not set.
Q_ASSERT(!QApplication::quitOnLastWindowClosed());
Q_ASSERT(!testAttribute(Qt::WA_DeleteOnClose));
#else
// Ignore the close event because closing the main window breaks global hotkeys on Windows.
ev->ignore();
hide();
#endif
}
else
{
@ -1293,11 +1302,12 @@ void MainWindow::applyProxySettings()
void MainWindow::applyWebSettings()
{
QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings();
QWebEngineSettings *defaultSettings = QWebEngineSettings::defaultSettings();
defaultSettings->setAttribute(QWebEngineSettings::PluginsEnabled, cfg.preferences.enableWebPlugins);
defaultSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, false);
defaultSettings->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true );
defaultSettings->setAttribute( QWebEngineSettings::WebAttribute::LocalContentCanAccessFileUrls, true );
defaultSettings->setAttribute( QWebEngineSettings::WebAttribute::ErrorPageEnabled, false);
}
void MainWindow::setupNetworkCache( int maxSize )
@ -1672,7 +1682,12 @@ ArticleView * MainWindow::createNewTab( bool switchToIt,
connect( view, SIGNAL( zoomIn()), this, SLOT( zoomin() ) );
connect( view, SIGNAL( zoomOut()), this, SLOT( zoomout() ) );
connect (wuri,SIGNAL(linkClicked(QUrl)),view,SLOT(linkClicked(QUrl)));
connect(wuri, &WebUrlRequestInterceptor::linkClicked, view, [=](QUrl url) {
ArticleView *active = getCurrentArticleView();
if (active == view) {
view->linkClicked(url);
}
});
view->setSelectionBySingleClick( cfg.preferences.selectWordBySingleClick );
@ -2619,7 +2634,8 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
if ( keyEvent->key() == Qt::Key_Space ||
keyEvent->key() == Qt::Key_Backspace ||
keyEvent->key() == Qt::Key_Tab ||
keyEvent->key() == Qt::Key_Backtab )
keyEvent->key() == Qt::Key_Backtab ||
keyEvent->key() == Qt::Key_Escape)
return false; // Those key have other uses than to start typing
// or don't make sense
@ -2648,7 +2664,8 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
if ( keyEvent->key() == Qt::Key_Space ||
keyEvent->key() == Qt::Key_Backspace ||
keyEvent->key() == Qt::Key_Tab ||
keyEvent->key() == Qt::Key_Backtab )
keyEvent->key() == Qt::Key_Backtab ||
keyEvent->key() == Qt::Key_Escape)
return false; // Those key have other uses than to start typing
// or don't make sense

View file

@ -353,7 +353,7 @@ void ProgramWordSearchRequest::instanceFinished( QByteArray output, QString erro
// Handle any Windows artifacts
output.replace( "\r\n", "\n" );
QStringList result =
QString::fromUtf8( output ).split( "\n", QString::SkipEmptyParts );
QString::fromUtf8( output ).split( "\n", Qt::SkipEmptyParts );
for( int x = 0; x < result.size(); ++x )
matches.push_back( Dictionary::WordMatch( gd::toWString( result[ x ] ) ) );

View file

@ -85,5 +85,6 @@
<file>icons/folder.png</file>
<file>icons/ontop.png</file>
<file>resources/jquery-3.6.0.slim.min.js</file>
<file>resources/gd_custom.js</file>
</qresource>
</RCC>

27
resources/gd_custom.js Normal file
View file

@ -0,0 +1,27 @@
//document ready ,
$(function() {
$("a").click(function(event) {
var link = $(this).attr("href");
if(link.indexOf(":")>=0){
return;
}
var newLink;
if (link.startsWith("#")) {
newLink = window.location.href + link;
} else {
var href = window.location.href;
var index = href.indexOf("?");
newLink = href.substring(0, index) + "?word=" + link;
}
$(this).attr("href", newLink);
});
}
);
function playSound(sound) {
var a = new Audio(sound);
a.play();
}

View file

@ -635,7 +635,7 @@ void StardictDictionary::pangoToHtml( QString & text )
{
// Parse font description
QStringList list = styleRegex.cap( 2 ).split( " ", QString::SkipEmptyParts );
QStringList list = styleRegex.cap( 2 ).split( " ", Qt::SkipEmptyParts );
int n;
QString sizeStr, stylesStr, familiesStr;
for( n = list.size() - 1; n >= 0; n-- )

View file

@ -26,6 +26,13 @@ inline QString rstrip(const QString& str) {
return "";
}
inline bool isExternalLink( QUrl const & url )
{
return url.scheme() == "http" || url.scheme() == "https" ||
url.scheme() == "ftp" || url.scheme() == "mailto" ||
url.scheme() == "file";
}
inline QString escape( QString const & plain )
{
return plain.toHtmlEscaped();

View file

@ -1,13 +1,16 @@
#include "weburlrequestinterceptor.h"
#include <QDebug>
#include "utils.hh"
WebUrlRequestInterceptor::WebUrlRequestInterceptor(QObject *p)
:QWebEngineUrlRequestInterceptor(p)
{
}
void WebUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) {
if(QWebEngineUrlRequestInfo::NavigationTypeLink==info.navigationType ()&&info.resourceType ()==QWebEngineUrlRequestInfo::ResourceTypeMainFrame)
emit linkClicked(info.requestUrl ());
void WebUrlRequestInterceptor::interceptRequest( QWebEngineUrlRequestInfo &info) {
if (QWebEngineUrlRequestInfo::NavigationTypeLink == info.navigationType() && info.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) {
emit linkClicked(info.requestUrl());
info.block(true);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

19
zim.cc
View file

@ -1188,7 +1188,7 @@ public:
~ZimArticleRequest()
{
isCancelled.ref();
hasExited.acquire();
//hasExited.acquire();
}
};
@ -1353,7 +1353,7 @@ public:
~ZimResourceRequestRunnable()
{
hasExited.release();
//hasExited.release();
}
virtual void run();
@ -1371,14 +1371,11 @@ class ZimResourceRequest: public Dictionary::DataRequest
QSemaphore hasExited;
public:
ZimResourceRequest( ZimDictionary & dict_,
string const & resourceName_ ):
dict( dict_ ),
resourceName( resourceName_ )
{
QThreadPool::globalInstance()->start(
new ZimResourceRequestRunnable( *this, hasExited ) );
ZimResourceRequest(ZimDictionary &dict_, string const &resourceName_)
: dict(dict_), resourceName(resourceName_) {
//(new ZimResourceRequestRunnable(*this, hasExited))->run();
QThreadPool::globalInstance()->start(
new ZimResourceRequestRunnable( *this, hasExited ) );
}
void run(); // Run from another thread by ZimResourceRequestRunnable
@ -1391,7 +1388,7 @@ public:
~ZimResourceRequest()
{
isCancelled.ref();
hasExited.acquire();
//hasExited.acquire();
}
};