2009-02-05 14:21:47 +00:00
|
|
|
/* This file is (c) 2008-2009 Konstantin Isakov <ikm@users.berlios.de>
|
2009-01-28 20:55:45 +00:00
|
|
|
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
|
|
|
|
|
|
#include "articleview.hh"
|
|
|
|
#include "externalviewer.hh"
|
2009-04-12 16:22:42 +00:00
|
|
|
#include <map>
|
2009-01-28 20:55:45 +00:00
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QWebHitTestResult>
|
|
|
|
#include <QMenu>
|
2009-02-01 00:08:08 +00:00
|
|
|
#include <QDesktopServices>
|
2009-05-11 22:25:22 +00:00
|
|
|
#include <QWebHistory>
|
2009-05-12 10:52:11 +00:00
|
|
|
#include <QClipboard>
|
2009-05-12 13:25:18 +00:00
|
|
|
#include <QKeyEvent>
|
2009-05-12 10:52:11 +00:00
|
|
|
#include "folding.hh"
|
|
|
|
#include "wstring_qt.hh"
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-02-06 15:37:37 +00:00
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#include <mmsystem.h> // For PlaySound
|
|
|
|
#endif
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-04-12 16:22:42 +00:00
|
|
|
using std::map;
|
2009-03-26 19:00:08 +00:00
|
|
|
using std::list;
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
ArticleView::ArticleView( QWidget * parent, ArticleNetworkAccessManager & nm,
|
2009-04-12 16:22:42 +00:00
|
|
|
std::vector< sptr< Dictionary::Class > > const & allDictionaries_,
|
2009-04-10 21:07:03 +00:00
|
|
|
Instances::Groups const & groups_, bool popupView_,
|
2009-05-14 19:27:19 +00:00
|
|
|
Config::Class const & cfg_,
|
|
|
|
GroupComboBox const * groupComboBox_ ):
|
2009-01-28 20:55:45 +00:00
|
|
|
QFrame( parent ),
|
|
|
|
articleNetMgr( nm ),
|
2009-04-12 16:22:42 +00:00
|
|
|
allDictionaries( allDictionaries_ ),
|
2009-01-28 20:55:45 +00:00
|
|
|
groups( groups_ ),
|
2009-04-10 21:07:03 +00:00
|
|
|
popupView( popupView_ ),
|
2009-05-12 10:52:11 +00:00
|
|
|
cfg( cfg_ ),
|
2009-05-14 19:27:19 +00:00
|
|
|
pasteAction( this ),
|
2009-05-15 14:11:54 +00:00
|
|
|
articleUpAction( this ),
|
|
|
|
articleDownAction( this ),
|
2009-05-16 11:14:43 +00:00
|
|
|
openSearchAction( this ),
|
|
|
|
searchIsOpened( false ),
|
2009-05-14 19:27:19 +00:00
|
|
|
groupComboBox( groupComboBox_ )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
ui.setupUi( this );
|
|
|
|
|
2009-05-15 14:24:37 +00:00
|
|
|
ui.definition->pageAction( QWebPage::Back )->setShortcut( QKeySequence( "Alt+Left" ) );
|
|
|
|
ui.definition->addAction( ui.definition->pageAction( QWebPage::Back ) );
|
|
|
|
|
|
|
|
ui.definition->pageAction( QWebPage::Forward )->setShortcut( QKeySequence( "Alt+Right" ) );
|
|
|
|
ui.definition->addAction( ui.definition->pageAction( QWebPage::Forward ) );
|
|
|
|
|
2009-04-03 21:57:23 +00:00
|
|
|
ui.definition->pageAction( QWebPage::Copy )->setShortcut( QKeySequence::Copy );
|
|
|
|
ui.definition->addAction( ui.definition->pageAction( QWebPage::Copy ) );
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
ui.definition->setContextMenuPolicy( Qt::CustomContextMenu );
|
|
|
|
|
|
|
|
ui.definition->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
|
|
|
|
|
|
|
|
ui.definition->page()->setNetworkAccessManager( &articleNetMgr );
|
|
|
|
|
2009-02-08 16:50:18 +00:00
|
|
|
connect( ui.definition, SIGNAL( loadFinished( bool ) ),
|
|
|
|
this, SLOT( loadFinished( bool ) ) );
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
connect( ui.definition, SIGNAL( titleChanged( QString const & ) ),
|
|
|
|
this, SLOT( handleTitleChanged( QString const & ) ) );
|
|
|
|
|
|
|
|
connect( ui.definition, SIGNAL( urlChanged( QUrl const & ) ),
|
|
|
|
this, SLOT( handleUrlChanged( QUrl const & ) ) );
|
|
|
|
|
|
|
|
connect( ui.definition, SIGNAL( customContextMenuRequested( QPoint const & ) ),
|
|
|
|
this, SLOT( contextMenuRequested( QPoint const & ) ) );
|
|
|
|
|
|
|
|
connect( ui.definition, SIGNAL( linkClicked( QUrl const & ) ),
|
|
|
|
this, SLOT( linkClicked( QUrl const & ) ) );
|
2009-05-11 15:33:57 +00:00
|
|
|
|
2009-05-12 10:52:11 +00:00
|
|
|
pasteAction.setShortcut( QKeySequence::Paste );
|
|
|
|
ui.definition->addAction( &pasteAction );
|
|
|
|
connect( &pasteAction, SIGNAL( triggered() ), this, SLOT( pasteTriggered() ) );
|
|
|
|
|
2009-05-15 14:11:54 +00:00
|
|
|
articleUpAction.setShortcut( QKeySequence( "Alt+Up" ) );
|
|
|
|
ui.definition->addAction( &articleUpAction );
|
|
|
|
connect( &articleUpAction, SIGNAL( triggered() ), this, SLOT( moveOneArticleUp() ) );
|
|
|
|
|
|
|
|
articleDownAction.setShortcut( QKeySequence( "Alt+Down" ) );
|
|
|
|
ui.definition->addAction( &articleDownAction );
|
|
|
|
connect( &articleDownAction, SIGNAL( triggered() ), this, SLOT( moveOneArticleDown() ) );
|
|
|
|
|
2009-05-16 11:14:43 +00:00
|
|
|
openSearchAction.setShortcut( QKeySequence( "Ctrl+F" ) );
|
|
|
|
ui.definition->addAction( &openSearchAction );
|
|
|
|
connect( &openSearchAction, SIGNAL( triggered() ), this, SLOT( openSearch() ) );
|
|
|
|
|
2009-05-12 13:25:18 +00:00
|
|
|
ui.definition->installEventFilter( this );
|
|
|
|
|
2009-05-11 15:33:57 +00:00
|
|
|
// Load the default blank page instantly, so there would be no flicker.
|
|
|
|
|
|
|
|
QString contentType;
|
|
|
|
QUrl blankPage( "gdlookup://localhost?blank=1" );
|
|
|
|
|
|
|
|
sptr< Dictionary::DataRequest > r = articleNetMgr.getResource( blankPage,
|
|
|
|
contentType );
|
|
|
|
|
|
|
|
ui.definition->setHtml( QByteArray( &( r->getFullData().front() ),
|
|
|
|
r->getFullData().size() ), blankPage );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2009-05-14 19:27:19 +00:00
|
|
|
void ArticleView::setGroupComboBox( GroupComboBox const * g )
|
|
|
|
{
|
|
|
|
groupComboBox = g;
|
|
|
|
}
|
|
|
|
|
2009-02-06 15:37:37 +00:00
|
|
|
ArticleView::~ArticleView()
|
|
|
|
{
|
2009-02-08 21:54:19 +00:00
|
|
|
cleanupTemp();
|
|
|
|
|
2009-02-06 15:37:37 +00:00
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if ( winWavData.size() )
|
|
|
|
{
|
|
|
|
// If we were playing some sound some time ago, make sure it stopped
|
|
|
|
// playing before freeing the waveform memory.
|
|
|
|
PlaySoundA( 0, 0, 0 );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:14:28 +00:00
|
|
|
void ArticleView::showDefinition( QString const & word, unsigned group,
|
|
|
|
QString const & scrollTo )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
QUrl req;
|
|
|
|
|
|
|
|
req.setScheme( "gdlookup" );
|
|
|
|
req.setHost( "localhost" );
|
|
|
|
req.addQueryItem( "word", word );
|
2009-04-10 12:48:40 +00:00
|
|
|
req.addQueryItem( "group", QString::number( group ) );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-05-11 19:14:28 +00:00
|
|
|
if ( scrollTo.size() )
|
|
|
|
req.setFragment( scrollTo );
|
|
|
|
|
2009-05-11 22:25:22 +00:00
|
|
|
// Save current article, if any
|
|
|
|
|
|
|
|
QString currentArticle = getCurrentArticle();
|
|
|
|
|
|
|
|
if ( currentArticle.size() )
|
|
|
|
ui.definition->history()->currentItem().setUserData( currentArticle );
|
|
|
|
|
2009-04-11 20:37:11 +00:00
|
|
|
ui.definition->load( req );
|
2009-05-11 22:25:22 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
//QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
|
|
ui.definition->setCursor( Qt::WaitCursor );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2009-02-08 16:50:18 +00:00
|
|
|
void ArticleView::showAnticipation()
|
|
|
|
{
|
|
|
|
ui.definition->setHtml( "" );
|
2009-03-26 19:00:08 +00:00
|
|
|
ui.definition->setCursor( Qt::WaitCursor );
|
|
|
|
//QApplication::setOverrideCursor( Qt::WaitCursor );
|
2009-02-08 16:50:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::loadFinished( bool )
|
|
|
|
{
|
2009-05-11 22:25:22 +00:00
|
|
|
QUrl url = ui.definition->url();
|
|
|
|
|
|
|
|
QVariant userData = ui.definition->history()->currentItem().userData();
|
|
|
|
|
|
|
|
if ( userData.type() == QVariant::String && userData.toString().startsWith( "gdfrom-" ) )
|
|
|
|
{
|
|
|
|
printf( "has user data\n" );
|
|
|
|
// There's an active article saved, so set it to be active.
|
|
|
|
setCurrentArticle( userData.toString() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( url.hasFragment() && url.fragment().startsWith( "gdfrom-" ) )
|
|
|
|
{
|
|
|
|
// There is no active article saved in history, but we have it in fragment.
|
|
|
|
// setCurrentArticle will save it.
|
|
|
|
setCurrentArticle( url.fragment() );
|
|
|
|
}
|
|
|
|
|
2009-05-16 18:04:21 +00:00
|
|
|
// See if we have any iframes in need of expansion
|
|
|
|
|
|
|
|
QList< QWebFrame * > frames = ui.definition->page()->mainFrame()->childFrames();
|
|
|
|
|
|
|
|
bool wereFrames = false;
|
|
|
|
|
|
|
|
for( QList< QWebFrame * >::iterator i = frames.begin(); i != frames.end(); ++i )
|
|
|
|
{
|
|
|
|
if ( (*i)->frameName().startsWith( "gdexpandframe-" ) )
|
|
|
|
{
|
|
|
|
//printf( "Name: %s\n", (*i)->frameName().toUtf8().data() );
|
|
|
|
//printf( "Size: %d\n", (*i)->contentsSize().height() );
|
|
|
|
//printf( ">>>>>>>>Height = %s\n", (*i)->evaluateJavaScript( "document.body.offsetHeight;" ).toString().toUtf8().data() );
|
|
|
|
|
|
|
|
// Set the height
|
|
|
|
ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "document.getElementById('%1').height = %2;" ).
|
|
|
|
arg( (*i)->frameName() ).
|
|
|
|
arg( (*i)->contentsSize().height() ) );
|
|
|
|
|
|
|
|
// Show it
|
|
|
|
ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "document.getElementById('%1').style.display = 'block';" ).
|
|
|
|
arg( (*i)->frameName() ) );
|
|
|
|
|
|
|
|
wereFrames = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wereFrames )
|
|
|
|
{
|
|
|
|
// There's some sort of glitch -- sometimes you need to move a mouse
|
|
|
|
|
|
|
|
QMouseEvent ev( QEvent::MouseMove, QPoint(), Qt::MouseButton(), 0, 0 );
|
|
|
|
|
|
|
|
qApp->sendEvent( ui.definition, &ev );
|
|
|
|
}
|
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
ui.definition->unsetCursor();
|
|
|
|
//QApplication::restoreOverrideCursor();
|
2009-05-14 19:27:19 +00:00
|
|
|
emit pageLoaded( this );
|
2009-02-08 16:50:18 +00:00
|
|
|
}
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
void ArticleView::handleTitleChanged( QString const & title )
|
|
|
|
{
|
|
|
|
emit titleChanged( this, title );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::handleUrlChanged( QUrl const & url )
|
|
|
|
{
|
|
|
|
QIcon icon;
|
|
|
|
|
2009-04-10 12:48:40 +00:00
|
|
|
unsigned group = getGroup( url );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-04-10 12:48:40 +00:00
|
|
|
if ( group )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
// Find the group's instance corresponding to the fragment value
|
|
|
|
for( unsigned x = 0; x < groups.size(); ++x )
|
2009-04-10 12:48:40 +00:00
|
|
|
if ( groups[ x ].id == group )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
// Found it
|
|
|
|
|
|
|
|
if ( groups[ x ].icon.size() )
|
|
|
|
icon = QIcon( ":/flags/" + groups[ x ].icon );
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit iconChanged( this, icon );
|
|
|
|
}
|
|
|
|
|
2009-04-10 12:48:40 +00:00
|
|
|
unsigned ArticleView::getGroup( QUrl const & url )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
if ( url.scheme() == "gdlookup" && url.hasQueryItem( "group" ) )
|
2009-04-10 12:48:40 +00:00
|
|
|
return url.queryItemValue( "group" ).toUInt();
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-04-10 12:48:40 +00:00
|
|
|
return 0;
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2009-05-11 22:25:22 +00:00
|
|
|
QStringList ArticleView::getArticlesList()
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
return ui.definition->page()->mainFrame()->
|
2009-05-11 22:25:22 +00:00
|
|
|
evaluateJavaScript( "gdArticleContents;" ).toString().
|
|
|
|
trimmed().split( ' ', QString::SkipEmptyParts );
|
|
|
|
}
|
|
|
|
|
2009-05-11 19:14:28 +00:00
|
|
|
QString ArticleView::getCurrentArticle()
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
QVariant v = ui.definition->page()->mainFrame()->evaluateJavaScript(
|
2009-05-11 19:14:28 +00:00
|
|
|
QString( "gdCurrentArticle;" ) );
|
|
|
|
|
|
|
|
if ( v.type() == QVariant::String )
|
|
|
|
return v.toString();
|
|
|
|
else
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:11:54 +00:00
|
|
|
void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
|
2009-05-11 22:25:22 +00:00
|
|
|
{
|
|
|
|
if ( !id.startsWith( "gdfrom-" ) )
|
|
|
|
return; // Incorrect id
|
|
|
|
|
|
|
|
if ( getArticlesList().contains( id.mid( 7 ) ) )
|
|
|
|
{
|
2009-05-15 14:11:54 +00:00
|
|
|
if ( moveToIt )
|
|
|
|
{
|
|
|
|
QUrl url( ui.definition->url() );
|
|
|
|
url.setFragment( id );
|
|
|
|
openLink( url, ui.definition->url() );
|
|
|
|
}
|
|
|
|
|
2009-05-11 22:25:22 +00:00
|
|
|
ui.definition->history()->currentItem().setUserData( id );
|
2009-05-16 18:04:21 +00:00
|
|
|
ui.definition->page()->mainFrame()->evaluateJavaScript(
|
2009-05-14 20:38:17 +00:00
|
|
|
QString( "gdMakeArticleActive( '%1' );" ).arg( id.mid( 7 ) ) );
|
2009-05-11 22:25:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-08 21:54:19 +00:00
|
|
|
void ArticleView::cleanupTemp()
|
|
|
|
{
|
|
|
|
if ( desktopOpenedTempFile.size() )
|
|
|
|
{
|
|
|
|
QFile( desktopOpenedTempFile ).remove();
|
|
|
|
desktopOpenedTempFile.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-12 13:25:18 +00:00
|
|
|
bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
|
|
|
|
{
|
|
|
|
if ( obj == ui.definition )
|
|
|
|
{
|
|
|
|
if ( ev->type() == QEvent::KeyPress )
|
|
|
|
{
|
|
|
|
QKeyEvent * keyEvent = static_cast< QKeyEvent * >( ev );
|
|
|
|
|
2009-05-14 20:43:32 +00:00
|
|
|
if ( keyEvent->modifiers() &
|
|
|
|
( Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier ) )
|
|
|
|
return false; // A non-typing modifier is pressed
|
|
|
|
|
2009-05-12 15:54:37 +00:00
|
|
|
if ( keyEvent->key() == Qt::Key_Space ||
|
2009-05-12 17:57:53 +00:00
|
|
|
keyEvent->key() == Qt::Key_Backspace ||
|
|
|
|
keyEvent->key() == Qt::Key_Tab )
|
2009-05-12 15:54:37 +00:00
|
|
|
return false; // Those key have other uses than to start typing
|
|
|
|
|
2009-05-12 13:25:18 +00:00
|
|
|
QString text = keyEvent->text();
|
|
|
|
|
|
|
|
if ( text.size() )
|
|
|
|
{
|
|
|
|
emit typingEvent( text );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return QFrame::eventFilter( obj, ev );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
|
|
|
|
void ArticleView::linkClicked( QUrl const & url )
|
2009-02-08 15:49:17 +00:00
|
|
|
{
|
2009-05-11 19:14:28 +00:00
|
|
|
openLink( url, ui.definition->url(), getCurrentArticle() );
|
2009-02-08 15:49:17 +00:00
|
|
|
}
|
|
|
|
|
2009-05-11 19:14:28 +00:00
|
|
|
void ArticleView::openLink( QUrl const & url, QUrl const & ref,
|
|
|
|
QString const & scrollTo )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
printf( "clicked %s\n", url.toString().toLocal8Bit().data() );
|
|
|
|
|
|
|
|
if ( url.scheme() == "bword" )
|
2009-05-08 17:19:10 +00:00
|
|
|
showDefinition( ( url.host().startsWith( "xn--" ) ?
|
2009-01-28 20:55:45 +00:00
|
|
|
QUrl::fromPunycode( url.host().toLatin1() ) :
|
2009-05-08 17:19:10 +00:00
|
|
|
url.host() ) + url.path(),
|
2009-05-11 19:14:28 +00:00
|
|
|
getGroup( ref ), scrollTo );
|
2009-01-28 20:55:45 +00:00
|
|
|
else
|
|
|
|
if ( url.scheme() == "gdlookup" ) // Plain html links inherit gdlookup scheme
|
2009-03-26 19:00:08 +00:00
|
|
|
{
|
|
|
|
if ( url.hasFragment() )
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
ui.definition->page()->mainFrame()->evaluateJavaScript(
|
2009-03-26 19:00:08 +00:00
|
|
|
QString( "window.location = \"%1\"" ).arg( QString::fromUtf8( url.toEncoded() ) ) );
|
|
|
|
}
|
|
|
|
else
|
2009-01-28 20:55:45 +00:00
|
|
|
showDefinition( url.path().mid( 1 ),
|
2009-05-11 19:14:28 +00:00
|
|
|
getGroup( ref ), scrollTo );
|
2009-03-26 19:00:08 +00:00
|
|
|
}
|
2009-01-28 20:55:45 +00:00
|
|
|
else
|
|
|
|
if ( url.scheme() == "bres" || url.scheme() == "gdau" )
|
|
|
|
{
|
2009-02-06 16:19:05 +00:00
|
|
|
// Download it
|
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
// Clear any pending ones
|
|
|
|
|
|
|
|
resourceDownloadRequests.clear();
|
2009-02-06 16:19:05 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
resourceDownloadUrl = url;
|
2009-02-06 16:19:05 +00:00
|
|
|
|
2009-04-25 21:04:49 +00:00
|
|
|
if ( url.scheme() == "gdau" && url.host() == "search" )
|
2009-02-06 16:19:05 +00:00
|
|
|
{
|
|
|
|
// Since searches should be limited to current group, we just do them
|
|
|
|
// here ourselves since otherwise we'd need to pass group id to netmgr
|
|
|
|
// and it should've been having knowledge of the current groups, too.
|
|
|
|
|
2009-04-10 12:48:40 +00:00
|
|
|
unsigned currentGroup = getGroup( ref );
|
2009-02-06 16:19:05 +00:00
|
|
|
|
2009-04-25 21:04:49 +00:00
|
|
|
std::vector< sptr< Dictionary::Class > > const * activeDicts = 0;
|
|
|
|
|
|
|
|
if ( groups.size() )
|
|
|
|
{
|
|
|
|
for( unsigned x = 0; x < groups.size(); ++x )
|
|
|
|
if ( groups[ x ].id == currentGroup )
|
|
|
|
{
|
|
|
|
activeDicts = &( groups[ x ].dictionaries );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
activeDicts = &allDictionaries;
|
|
|
|
|
|
|
|
if ( activeDicts )
|
|
|
|
for( unsigned x = 0; x < activeDicts->size(); ++x )
|
2009-02-06 16:19:05 +00:00
|
|
|
{
|
2009-04-25 21:04:49 +00:00
|
|
|
sptr< Dictionary::DataRequest > req =
|
|
|
|
(*activeDicts)[ x ]->getResource(
|
|
|
|
url.path().mid( 1 ).toUtf8().data() );
|
|
|
|
|
|
|
|
if ( req->isFinished() && req->dataSize() >= 0 )
|
2009-02-06 16:19:05 +00:00
|
|
|
{
|
2009-04-25 21:04:49 +00:00
|
|
|
// A request was instantly finished with success.
|
|
|
|
// If we've managed to spawn some lingering requests already,
|
|
|
|
// erase them.
|
|
|
|
resourceDownloadRequests.clear();
|
|
|
|
|
|
|
|
// Handle the result
|
|
|
|
resourceDownloadRequests.push_back( req );
|
|
|
|
resourceDownloadFinished();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( !req->isFinished() )
|
|
|
|
{
|
|
|
|
resourceDownloadRequests.push_back( req );
|
|
|
|
|
|
|
|
connect( req.get(), SIGNAL( finished() ),
|
|
|
|
this, SLOT( resourceDownloadFinished() ) );
|
2009-02-06 16:19:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-03-26 19:00:08 +00:00
|
|
|
else
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2009-03-26 19:00:08 +00:00
|
|
|
// Normal resource download
|
|
|
|
QString contentType;
|
2009-02-08 14:40:26 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
sptr< Dictionary::DataRequest > req =
|
|
|
|
articleNetMgr.getResource( url, contentType );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-04-25 21:04:49 +00:00
|
|
|
if ( !req.get() )
|
|
|
|
{
|
|
|
|
// Request failed, fail
|
|
|
|
}
|
|
|
|
else
|
2009-03-26 19:00:08 +00:00
|
|
|
if ( req->isFinished() && req->dataSize() >= 0 )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2009-03-26 19:00:08 +00:00
|
|
|
// Have data ready, handle it
|
|
|
|
resourceDownloadRequests.push_back( req );
|
|
|
|
resourceDownloadFinished();
|
2009-02-08 14:40:26 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
return;
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
2009-03-26 19:00:08 +00:00
|
|
|
else
|
|
|
|
if ( !req->isFinished() )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2009-03-26 19:00:08 +00:00
|
|
|
// Queue to be handled when done
|
2009-02-08 14:40:26 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
resourceDownloadRequests.push_back( req );
|
|
|
|
|
|
|
|
connect( req.get(), SIGNAL( finished() ),
|
|
|
|
this, SLOT( resourceDownloadFinished() ) );
|
|
|
|
}
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
2009-02-08 14:40:26 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
QString contentType;
|
2009-02-08 14:40:26 +00:00
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
if ( resourceDownloadRequests.empty() ) // No requests were queued
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2009-03-26 19:00:08 +00:00
|
|
|
QMessageBox::critical( this, tr( "GoldenDict" ), tr( "The referenced resource doesn't exist." ) );
|
|
|
|
return;
|
2009-02-08 21:54:19 +00:00
|
|
|
}
|
2009-04-25 21:04:49 +00:00
|
|
|
else
|
|
|
|
resourceDownloadFinished(); // Check any requests finished already
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
2009-02-01 00:08:08 +00:00
|
|
|
else
|
|
|
|
if ( url.scheme() == "http" || url.scheme() == "https" ||
|
|
|
|
url.scheme() == "ftp" || url.scheme() == "mailto" )
|
|
|
|
{
|
|
|
|
// Use the system handler for the conventional internet links
|
|
|
|
QDesktopServices::openUrl( url );
|
|
|
|
}
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2009-04-10 21:07:03 +00:00
|
|
|
bool ArticleView::hasSound()
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
return ui.definition->page()->mainFrame()->
|
2009-04-10 21:07:03 +00:00
|
|
|
evaluateJavaScript( "gdAudioLink;" ).type() == QVariant::String;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::playSound()
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
QVariant v = ui.definition->page()->mainFrame()->evaluateJavaScript(
|
2009-04-10 21:07:03 +00:00
|
|
|
QString( "gdAudioLink;" ) );
|
|
|
|
|
|
|
|
if ( v.type() == QVariant::String )
|
2009-04-12 23:07:45 +00:00
|
|
|
openLink( QUrl::fromEncoded( v.toString().toUtf8() ), ui.definition->url() );
|
2009-04-10 21:07:03 +00:00
|
|
|
}
|
|
|
|
|
2009-05-01 11:17:29 +00:00
|
|
|
QString ArticleView::toHtml()
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
return ui.definition->page()->mainFrame()->toHtml();
|
2009-05-01 11:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QString ArticleView::getTitle()
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
return ui.definition->page()->mainFrame()->title();
|
2009-05-01 11:17:29 +00:00
|
|
|
}
|
|
|
|
|
2009-05-01 12:20:33 +00:00
|
|
|
void ArticleView::print( QPrinter * printer ) const
|
|
|
|
{
|
|
|
|
ui.definition->print( printer );
|
|
|
|
}
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
void ArticleView::contextMenuRequested( QPoint const & pos )
|
|
|
|
{
|
|
|
|
// Is that a link? Is there a selection?
|
|
|
|
|
2009-05-16 18:04:21 +00:00
|
|
|
QWebHitTestResult r = ui.definition->page()->mainFrame()->
|
2009-01-28 20:55:45 +00:00
|
|
|
hitTestContent( pos );
|
|
|
|
|
|
|
|
QMenu menu( this );
|
|
|
|
|
|
|
|
|
|
|
|
QAction * followLink = 0;
|
2009-02-08 15:49:17 +00:00
|
|
|
QAction * followLinkNewTab = 0;
|
2009-01-28 20:55:45 +00:00
|
|
|
QAction * lookupSelection = 0;
|
2009-05-14 19:27:19 +00:00
|
|
|
QAction * lookupSelectionGr = 0;
|
2009-02-08 15:49:17 +00:00
|
|
|
QAction * lookupSelectionNewTab = 0;
|
2009-05-14 19:27:19 +00:00
|
|
|
QAction * lookupSelectionNewTabGr = 0;
|
2009-01-28 20:55:45 +00:00
|
|
|
|
|
|
|
if ( !r.linkUrl().isEmpty() )
|
|
|
|
{
|
2009-02-08 15:49:17 +00:00
|
|
|
followLink = new QAction( tr( "&Open Link" ), &menu );
|
2009-01-28 20:55:45 +00:00
|
|
|
menu.addAction( followLink );
|
2009-02-08 15:49:17 +00:00
|
|
|
|
|
|
|
if ( !popupView )
|
|
|
|
{
|
|
|
|
followLinkNewTab = new QAction( tr( "Open Link in New &Tab" ), &menu );
|
|
|
|
menu.addAction( followLinkNewTab );
|
|
|
|
}
|
2009-04-03 21:57:23 +00:00
|
|
|
|
|
|
|
QString scheme = r.linkUrl().scheme();
|
|
|
|
|
|
|
|
if ( scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "mailto" )
|
2009-04-29 23:18:26 +00:00
|
|
|
menu.addAction( ui.definition->pageAction( QWebPage::CopyLinkToClipboard ) );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QString selectedText = ui.definition->selectedText();
|
2009-02-08 15:49:17 +00:00
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
if ( selectedText.size() )
|
|
|
|
{
|
2009-05-14 19:27:19 +00:00
|
|
|
lookupSelection = new QAction( tr( "&Look up \"%1\"" ).
|
|
|
|
arg( ui.definition->selectedText() ),
|
|
|
|
&menu );
|
2009-01-28 20:55:45 +00:00
|
|
|
menu.addAction( lookupSelection );
|
2009-02-08 15:49:17 +00:00
|
|
|
|
|
|
|
if ( !popupView )
|
|
|
|
{
|
2009-05-14 19:27:19 +00:00
|
|
|
lookupSelectionNewTab = new QAction( QIcon( ":/icons/addtab.png" ),
|
|
|
|
tr( "Look up \"%1\" in &New Tab" ).
|
|
|
|
arg( ui.definition->selectedText() ),
|
|
|
|
&menu );
|
2009-02-08 15:49:17 +00:00
|
|
|
menu.addAction( lookupSelectionNewTab );
|
|
|
|
}
|
2009-04-03 21:57:23 +00:00
|
|
|
|
2009-05-14 19:27:19 +00:00
|
|
|
Instances::Group const * altGroup =
|
|
|
|
( groupComboBox && groupComboBox->getCurrentGroup() != getGroup( ui.definition->url() ) ) ?
|
|
|
|
groups.findGroup( groupComboBox->getCurrentGroup() ) : 0;
|
|
|
|
|
|
|
|
if ( altGroup )
|
|
|
|
{
|
|
|
|
QIcon icon = altGroup->icon.size() ? QIcon( ":/flags/" + altGroup->icon ) :
|
|
|
|
QIcon();
|
|
|
|
|
|
|
|
lookupSelectionGr = new QAction( icon, tr( "&Look up \"%1\" in %2" ).
|
|
|
|
arg( ui.definition->selectedText() ).
|
|
|
|
arg( altGroup->name ), &menu );
|
|
|
|
menu.addAction( lookupSelectionGr );
|
|
|
|
|
|
|
|
if ( !popupView )
|
|
|
|
{
|
|
|
|
lookupSelectionNewTabGr = new QAction( QIcon( ":/icons/addtab.png" ),
|
|
|
|
tr( "Look up \"%1\" in %2 in &New Tab" ).
|
|
|
|
arg( ui.definition->selectedText() ).
|
|
|
|
arg( altGroup->name ), &menu );
|
|
|
|
menu.addAction( lookupSelectionNewTabGr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-29 23:18:26 +00:00
|
|
|
menu.addAction( ui.definition->pageAction( QWebPage::Copy ) );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2009-04-12 16:22:42 +00:00
|
|
|
map< QAction *, QString > tableOfContents;
|
|
|
|
|
|
|
|
// Add table of contents
|
2009-05-11 22:25:22 +00:00
|
|
|
QStringList ids = getArticlesList();
|
2009-04-12 16:22:42 +00:00
|
|
|
|
|
|
|
if ( !menu.isEmpty() && ids.size() )
|
|
|
|
menu.addSeparator();
|
2009-04-14 18:35:27 +00:00
|
|
|
|
|
|
|
unsigned refsAdded = 0;
|
|
|
|
|
2009-04-12 16:22:42 +00:00
|
|
|
for( QStringList::const_iterator i = ids.constBegin(); i != ids.constEnd();
|
2009-04-14 18:35:27 +00:00
|
|
|
++i, ++refsAdded )
|
2009-04-12 16:22:42 +00:00
|
|
|
{
|
2009-04-14 18:35:27 +00:00
|
|
|
if ( refsAdded == 20 )
|
|
|
|
{
|
|
|
|
// Enough! Or the menu would become too large.
|
|
|
|
menu.addAction( new QAction( ".........", &menu ) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-04-12 16:22:42 +00:00
|
|
|
// Find this dictionary
|
|
|
|
|
|
|
|
for( unsigned x = allDictionaries.size(); x--; )
|
|
|
|
{
|
|
|
|
if ( allDictionaries[ x ]->getId() == i->toUtf8().data() )
|
|
|
|
{
|
|
|
|
QAction * action =
|
|
|
|
new QAction(
|
2009-04-23 16:29:54 +00:00
|
|
|
allDictionaries[ x ]->getIcon(),
|
2009-04-12 16:22:42 +00:00
|
|
|
QString::fromUtf8( allDictionaries[ x ]->getName().c_str() ),
|
|
|
|
&menu );
|
|
|
|
|
|
|
|
menu.addAction( action );
|
|
|
|
|
|
|
|
tableOfContents[ action ] = *i;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
if ( !menu.isEmpty() )
|
|
|
|
{
|
|
|
|
QAction * result = menu.exec( ui.definition->mapToGlobal( pos ) );
|
|
|
|
|
|
|
|
if ( result == followLink )
|
|
|
|
linkClicked( r.linkUrl() );
|
|
|
|
else
|
|
|
|
if ( result == lookupSelection )
|
2009-05-11 19:14:28 +00:00
|
|
|
showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() );
|
2009-02-08 15:49:17 +00:00
|
|
|
else
|
2009-05-14 19:27:19 +00:00
|
|
|
if ( result == lookupSelectionGr && groupComboBox )
|
|
|
|
showDefinition( selectedText, groupComboBox->getCurrentGroup(), QString() );
|
|
|
|
else
|
2009-04-12 16:22:42 +00:00
|
|
|
if ( !popupView && result == followLinkNewTab )
|
2009-05-11 19:14:28 +00:00
|
|
|
emit openLinkInNewTab( r.linkUrl(), ui.definition->url(), getCurrentArticle() );
|
2009-04-12 16:22:42 +00:00
|
|
|
else
|
|
|
|
if ( !popupView && result == lookupSelectionNewTab )
|
2009-05-11 19:14:28 +00:00
|
|
|
emit showDefinitionInNewTab( selectedText, getGroup( ui.definition->url() ),
|
|
|
|
getCurrentArticle() );
|
2009-04-12 16:22:42 +00:00
|
|
|
else
|
2009-05-14 19:27:19 +00:00
|
|
|
if ( !popupView && result == lookupSelectionNewTabGr && groupComboBox )
|
|
|
|
emit showDefinitionInNewTab( selectedText, groupComboBox->getCurrentGroup(),
|
|
|
|
QString() );
|
|
|
|
else
|
2009-02-08 15:49:17 +00:00
|
|
|
{
|
2009-04-12 16:22:42 +00:00
|
|
|
// Match against table of contents
|
|
|
|
QString id = tableOfContents[ result ];
|
|
|
|
|
|
|
|
if ( id.size() )
|
2009-05-15 14:11:54 +00:00
|
|
|
setCurrentArticle( "gdfrom-" + id, true );
|
2009-02-08 15:49:17 +00:00
|
|
|
}
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
printf( "%s\n", r.linkUrl().isEmpty() ? "null" : "not null" );
|
|
|
|
|
|
|
|
printf( "url = %s\n", r.linkUrl().toString().toLocal8Bit().data() );
|
|
|
|
printf( "title = %s\n", r.title().toLocal8Bit().data() );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
void ArticleView::resourceDownloadFinished()
|
|
|
|
{
|
|
|
|
if ( resourceDownloadRequests.empty() )
|
|
|
|
return; // Stray signal
|
|
|
|
|
|
|
|
// Find any finished resources
|
|
|
|
for( list< sptr< Dictionary::DataRequest > >::iterator i =
|
|
|
|
resourceDownloadRequests.begin(); i != resourceDownloadRequests.end(); )
|
|
|
|
{
|
|
|
|
if ( (*i)->isFinished() )
|
|
|
|
{
|
|
|
|
if ( (*i)->dataSize() >= 0 )
|
|
|
|
{
|
|
|
|
// Ok, got one finished, all others are irrelevant now
|
|
|
|
|
|
|
|
vector< char > const & data = (*i)->getFullData();
|
|
|
|
|
|
|
|
if ( resourceDownloadUrl.scheme() == "gdau" )
|
|
|
|
{
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
// Windows-only: use system PlaySound function
|
|
|
|
|
|
|
|
if ( winWavData.size() )
|
|
|
|
PlaySoundA( 0, 0, 0 ); // Stop any currently playing sound to make sure
|
|
|
|
// previous data isn't used anymore
|
|
|
|
//
|
|
|
|
winWavData = data;
|
|
|
|
|
|
|
|
PlaySoundA( &winWavData.front(), 0,
|
|
|
|
SND_ASYNC | SND_MEMORY | SND_NODEFAULT | SND_NOWAIT );
|
|
|
|
#else
|
|
|
|
|
|
|
|
// Use external viewer to play the file
|
|
|
|
try
|
|
|
|
{
|
2009-04-10 21:07:03 +00:00
|
|
|
ExternalViewer * viewer = new ExternalViewer( this, data, "wav", cfg.preferences.audioPlaybackProgram );
|
2009-03-26 19:00:08 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
viewer->start();
|
|
|
|
|
|
|
|
// Once started, it will erase itself
|
|
|
|
}
|
|
|
|
catch( ... )
|
|
|
|
{
|
|
|
|
delete viewer;
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch( ExternalViewer::Ex & e )
|
|
|
|
{
|
|
|
|
QMessageBox::critical( this, tr( "GoldenDict" ), tr( "Failed to run a player to play sound file: %1" ).arg( e.what() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Create a temporary file
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the one previously used, if any
|
|
|
|
cleanupTemp();
|
|
|
|
|
|
|
|
{
|
|
|
|
QTemporaryFile tmp(
|
|
|
|
QDir::temp().filePath( "XXXXXX-" + resourceDownloadUrl.path().section( '/', -1 ) ), this );
|
|
|
|
|
|
|
|
if ( !tmp.open() || tmp.write( &data.front(), data.size() ) != data.size() )
|
|
|
|
{
|
|
|
|
QMessageBox::critical( this, tr( "GoldenDict" ), tr( "Failed to create temporary file." ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp.setAutoRemove( false );
|
|
|
|
|
|
|
|
desktopOpenedTempFile = tmp.fileName();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !QDesktopServices::openUrl( QUrl::fromLocalFile( desktopOpenedTempFile ) ) )
|
|
|
|
QMessageBox::critical( this, tr( "GoldenDict" ), tr( "Failed to auto-open resource file, try opening manually: %1." ).arg( desktopOpenedTempFile ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ok, whatever it was, it's finished. Remove this and any other
|
|
|
|
// requests and finish.
|
|
|
|
|
|
|
|
resourceDownloadRequests.clear();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// This one had no data. Erase it.
|
|
|
|
resourceDownloadRequests.erase( i++ );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // Unfinished, try the next one.
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( resourceDownloadRequests.empty() )
|
|
|
|
{
|
|
|
|
// No requests suceeded.
|
|
|
|
QMessageBox::critical( this, tr( "GoldenDict" ), tr( "The referenced resource failed to download." ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-12 10:52:11 +00:00
|
|
|
void ArticleView::pasteTriggered()
|
|
|
|
{
|
|
|
|
QString text =
|
|
|
|
gd::toQString(
|
|
|
|
Folding::trimWhitespaceOrPunct(
|
|
|
|
gd::toWString(
|
|
|
|
QApplication::clipboard()->text() ) ) );
|
|
|
|
|
|
|
|
if ( text.size() )
|
|
|
|
showDefinition( text, getGroup( ui.definition->url() ), getCurrentArticle() );
|
|
|
|
}
|
|
|
|
|
2009-05-15 14:11:54 +00:00
|
|
|
void ArticleView::moveOneArticleUp()
|
|
|
|
{
|
|
|
|
QString current = getCurrentArticle();
|
|
|
|
|
|
|
|
if ( current.size() )
|
|
|
|
{
|
|
|
|
QStringList lst = getArticlesList();
|
|
|
|
|
|
|
|
int idx = lst.indexOf( current.mid( 7 ) );
|
|
|
|
|
|
|
|
if ( idx != -1 )
|
|
|
|
{
|
|
|
|
--idx;
|
|
|
|
|
|
|
|
if ( idx < 0 )
|
|
|
|
idx = lst.size() - 1;
|
|
|
|
|
|
|
|
setCurrentArticle( "gdfrom-" + lst[ idx ], true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::moveOneArticleDown()
|
|
|
|
{
|
|
|
|
QString current = getCurrentArticle();
|
|
|
|
|
|
|
|
if ( current.size() )
|
|
|
|
{
|
|
|
|
QStringList lst = getArticlesList();
|
|
|
|
|
|
|
|
int idx = lst.indexOf( current.mid( 7 ) );
|
|
|
|
|
|
|
|
if ( idx != -1 )
|
|
|
|
{
|
|
|
|
idx = ( idx + 1 ) % lst.size();
|
|
|
|
|
|
|
|
setCurrentArticle( "gdfrom-" + lst[ idx ], true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-16 11:14:43 +00:00
|
|
|
void ArticleView::openSearch()
|
|
|
|
{
|
|
|
|
if ( !searchIsOpened )
|
|
|
|
{
|
|
|
|
ui.searchFrame->show();
|
|
|
|
ui.searchText->setText( getTitle() );
|
|
|
|
searchIsOpened = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ui.searchText->setFocus();
|
|
|
|
ui.searchText->selectAll();
|
|
|
|
|
|
|
|
// Clear any current selection
|
|
|
|
if ( ui.definition->selectedText().size() )
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
ui.definition->page()->currentFrame()->
|
|
|
|
evaluateJavaScript( "window.getSelection().removeAllRanges();" );
|
2009-05-16 11:14:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( ui.searchText->property( "noResults" ).toBool() )
|
|
|
|
{
|
|
|
|
ui.searchText->setProperty( "noResults", false );
|
2009-05-16 18:04:21 +00:00
|
|
|
|
|
|
|
// Reload stylesheet
|
|
|
|
for( QWidget * w = parentWidget(); w; w = w->parentWidget() )
|
|
|
|
{
|
|
|
|
if ( w->styleSheet().size() )
|
|
|
|
{
|
|
|
|
w->setStyleSheet( w->styleSheet() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-05-16 11:14:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::on_searchPrevious_clicked()
|
|
|
|
{
|
|
|
|
performFindOperation( false, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::on_searchNext_clicked()
|
|
|
|
{
|
|
|
|
performFindOperation( false, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::on_searchText_textEdited()
|
|
|
|
{
|
|
|
|
performFindOperation( true, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::on_searchText_returnPressed()
|
|
|
|
{
|
|
|
|
on_searchNext_clicked();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::on_searchCloseButton_clicked()
|
|
|
|
{
|
|
|
|
closeSearch();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArticleView::performFindOperation( bool restart, bool backwards )
|
|
|
|
{
|
|
|
|
QString text = ui.searchText->text();
|
|
|
|
|
|
|
|
if ( restart )
|
|
|
|
{
|
|
|
|
// Anyone knows how we reset the search position?
|
|
|
|
// For now we resort to this hack:
|
|
|
|
if ( ui.definition->selectedText().size() )
|
|
|
|
{
|
2009-05-16 18:04:21 +00:00
|
|
|
ui.definition->page()->currentFrame()->
|
|
|
|
evaluateJavaScript( "window.getSelection().removeAllRanges();" );
|
2009-05-16 11:14:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QWebPage::FindFlags f( 0 );
|
|
|
|
|
|
|
|
if ( ui.searchCaseSensitive->isChecked() )
|
|
|
|
f |= QWebPage::FindCaseSensitively;
|
|
|
|
|
|
|
|
if ( backwards )
|
|
|
|
f |= QWebPage::FindBackward;
|
|
|
|
|
|
|
|
bool setMark = text.size() && !ui.definition->findText( text, f );
|
|
|
|
|
|
|
|
if ( ui.searchText->property( "noResults" ).toBool() != setMark )
|
|
|
|
{
|
|
|
|
ui.searchText->setProperty( "noResults", setMark );
|
2009-05-16 18:04:21 +00:00
|
|
|
|
|
|
|
// Reload stylesheet
|
|
|
|
for( QWidget * w = parentWidget(); w; w = w->parentWidget() )
|
|
|
|
{
|
|
|
|
if ( w->styleSheet().size() )
|
|
|
|
{
|
|
|
|
w->setStyleSheet( w->styleSheet() );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-05-16 11:14:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ArticleView::closeSearch()
|
|
|
|
{
|
|
|
|
if ( searchIsOpened )
|
|
|
|
{
|
|
|
|
ui.searchFrame->hide();
|
|
|
|
ui.definition->setFocus();
|
|
|
|
searchIsOpened = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
void ArticleView::showEvent( QShowEvent * ev )
|
|
|
|
{
|
|
|
|
QFrame::showEvent( ev );
|
|
|
|
|
2009-05-16 11:14:43 +00:00
|
|
|
if ( !searchIsOpened )
|
|
|
|
ui.searchFrame->hide();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|