mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-24 00:14:06 +00:00
Win-specific: Scan popup now work in GoldenDict article tabs
This commit is contained in:
parent
3abb74ad51
commit
3de1e09663
174
articleview.cc
174
articleview.cc
|
@ -21,7 +21,11 @@
|
|||
#ifdef Q_OS_WIN32
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> // For PlaySound
|
||||
|
||||
#include <QWebElement>
|
||||
#include <QPainter>
|
||||
#endif
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
// Phonon headers are a mess. How to include them properly? Send patches if you
|
||||
|
@ -1568,3 +1572,173 @@ void ArticleView::switchExpandOptionalParts()
|
|||
emit setExpandMode( expandOptionalParts );
|
||||
reload();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
void ArticleView::readTag( const QString & from, QString & to, int & count )
|
||||
{
|
||||
QChar ch, prev_ch;
|
||||
bool inQuote = false, inDoublequote = false;
|
||||
|
||||
to.append( ch = prev_ch = from[ count++ ] );
|
||||
while( count < from.size() )
|
||||
{
|
||||
ch = from[ count ];
|
||||
if( ch == '>' && !( inQuote || inDoublequote ) )
|
||||
{
|
||||
to.append( ch );
|
||||
break;
|
||||
}
|
||||
if( ch == '\'' )
|
||||
inQuote = !inQuote;
|
||||
if( ch == '\"' )
|
||||
inDoublequote = !inDoublequote;
|
||||
to.append( prev_ch = ch );
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
QString ArticleView::insertSpans( QString const & html )
|
||||
{
|
||||
QChar ch;
|
||||
QString newContent;
|
||||
bool inSpan = false, escaped = false;
|
||||
|
||||
/// Enclose every word in string (exclude tags) with <span></span>
|
||||
|
||||
for( int i = 0; i < html.size(); i++ )
|
||||
{
|
||||
ch = html[ i ];
|
||||
if( ch == '&' )
|
||||
{
|
||||
escaped = true;
|
||||
if( inSpan )
|
||||
{
|
||||
newContent.append( "</span>" );
|
||||
inSpan = false;
|
||||
}
|
||||
newContent.append( ch );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ch == '<' ) // Skip tag
|
||||
{
|
||||
escaped = false;
|
||||
if( inSpan )
|
||||
{
|
||||
newContent.append( "</span>" );
|
||||
inSpan = false;
|
||||
}
|
||||
readTag( html, newContent, i );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( escaped )
|
||||
{
|
||||
if( ch == ';' )
|
||||
escaped = false;
|
||||
newContent.append( ch );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !inSpan && ( ch.isLetterOrNumber() || ch.isLowSurrogate() ) )
|
||||
{
|
||||
newContent.append( "<span>");
|
||||
inSpan = true;
|
||||
}
|
||||
|
||||
if( inSpan && !( ch.isLetterOrNumber() || ch.isLowSurrogate() ) )
|
||||
{
|
||||
newContent.append( "</span>");
|
||||
inSpan = false;
|
||||
}
|
||||
|
||||
if( ch.isLowSurrogate() )
|
||||
{
|
||||
newContent.append( ch );
|
||||
ch = html[ ++i ];
|
||||
}
|
||||
|
||||
newContent.append( ch );
|
||||
}
|
||||
if( inSpan )
|
||||
newContent.append( "</span>" );
|
||||
return newContent;
|
||||
}
|
||||
|
||||
QString ArticleView::checkElement( QWebElement & elem, QPoint const & pt )
|
||||
{
|
||||
/// Search for lower-level matching element
|
||||
|
||||
QWebElement parentElem = elem;
|
||||
QWebElement childElem = elem.firstChild();
|
||||
while( !childElem.isNull() )
|
||||
{
|
||||
if( childElem.geometry().contains( pt ) )
|
||||
{
|
||||
parentElem = childElem;
|
||||
childElem = parentElem.firstChild();
|
||||
continue;
|
||||
}
|
||||
childElem = childElem.nextSibling();
|
||||
}
|
||||
|
||||
return parentElem.toPlainText();
|
||||
}
|
||||
|
||||
QString ArticleView::wordAtPoint( int x, int y )
|
||||
{
|
||||
QString word;
|
||||
|
||||
if( popupView )
|
||||
return word;
|
||||
|
||||
QPoint pos = mapFromGlobal( QPoint( x, y ) );
|
||||
QWebFrame *frame = ui.definition->page()->frameAt( pos );
|
||||
if( !frame )
|
||||
return word;
|
||||
|
||||
QPoint posWithScroll = pos + frame->scrollPosition();
|
||||
|
||||
/// Find target HTML element
|
||||
|
||||
QWebHitTestResult result = frame->hitTestContent( pos );
|
||||
QWebElement baseElem = result.enclosingBlockElement();
|
||||
|
||||
if( baseElem.tagName().compare( "BODY" ) == 0 || /// Assume empty field position
|
||||
baseElem.tagName().compare( "HTML" ) == 0 ||
|
||||
baseElem.tagName().compare( "HEAD" ) == 0 )
|
||||
return word;
|
||||
|
||||
/// Enclose every word be <span> </span>
|
||||
|
||||
QString content = baseElem.toInnerXml();
|
||||
QString newContent = insertSpans( content );
|
||||
|
||||
/// Set new code and re-render it to fill geometry
|
||||
|
||||
QImage img( baseElem.geometry().width(), baseElem.geometry().height(), QImage::Format_Mono );
|
||||
img.fill( 0 );
|
||||
QPainter painter( & img );
|
||||
|
||||
baseElem.setInnerXml( newContent );
|
||||
baseElem.render( &painter );
|
||||
|
||||
/// Search in all child elements and check it
|
||||
|
||||
QWebElementCollection elemCollection = baseElem.findAll( "*" );
|
||||
foreach ( QWebElement elem, elemCollection )
|
||||
{
|
||||
if( elem.geometry().contains( posWithScroll ) )
|
||||
word = checkElement( elem, posWithScroll );
|
||||
if( !word.isEmpty() )
|
||||
break;
|
||||
}
|
||||
|
||||
/// Restore old content
|
||||
baseElem.setInnerXml( content );
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -298,6 +298,19 @@ protected:
|
|||
|
||||
// We need this to hide the search bar when we're showed
|
||||
void showEvent( QShowEvent * );
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
/// Search inside web page for word under cursor
|
||||
|
||||
private:
|
||||
QString insertSpans( QString const & html );
|
||||
void readTag( QString const & from, QString & to, int & count );
|
||||
QString checkElement( QWebElement & elem, const QPoint & pt );
|
||||
public:
|
||||
QString wordAtPoint( int x, int y );
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
#include "lionsupport.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#include <windows.h>
|
||||
#include "mouseover_win32/GDDataTranfer.h"
|
||||
#endif
|
||||
|
||||
using std::set;
|
||||
using std::wstring;
|
||||
using std::map;
|
||||
|
@ -527,6 +532,9 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
|||
#ifdef Q_OS_MAC
|
||||
LionSupport::addFullscreen(this);
|
||||
#endif
|
||||
#ifdef Q_OS_WIN32
|
||||
gdAskMessage = RegisterWindowMessage( GD_MESSAGE_NAME );
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::ctrlTabPressed()
|
||||
|
@ -1021,6 +1029,9 @@ ArticleView * MainWindow::createNewTab( bool switchToIt,
|
|||
|
||||
view->setZoomFactor( cfg.preferences.zoomFactor );
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
view->installEventFilter( this );
|
||||
#endif
|
||||
return view;
|
||||
}
|
||||
|
||||
|
@ -2950,3 +2961,28 @@ void MainWindow::switchExpandOptionalPartsMode()
|
|||
if( view )
|
||||
view->switchExpandOptionalParts();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
bool MainWindow::winEvent( MSG * message, long * result )
|
||||
{
|
||||
if( message->message != gdAskMessage )
|
||||
return false;
|
||||
*result = 0;
|
||||
ArticleView * view = getCurrentArticleView();
|
||||
if( !view )
|
||||
return true;
|
||||
|
||||
LPGDDataStruct lpdata = ( LPGDDataStruct ) message->lParam;
|
||||
|
||||
QString str = view->wordAtPoint( lpdata->Pt.x, lpdata->Pt.y );
|
||||
|
||||
str.truncate( lpdata->dwMaxLength - 1 );
|
||||
memset( lpdata->cwData, 0, lpdata->dwMaxLength * sizeof( WCHAR ) );
|
||||
str.toWCharArray( lpdata->cwData );
|
||||
|
||||
*result = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -341,6 +341,13 @@ private slots:
|
|||
signals:
|
||||
/// Set optional parts expand mode for all tabs
|
||||
void setExpandOptionalParts( bool expand );
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
/// For receiving message from scan libraries
|
||||
protected:
|
||||
unsigned gdAskMessage;
|
||||
bool winEvent( MSG * message, long * result );
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue