+ Support for folloing websites' links in-place. The actual link is followed for

the website, while the query word is set to the link's text as used for all
  other dictionaries in the group.
* Some associated cleanup (better scrolling to articles, better external link
  handling).
The changes might cause problems - test!
This commit is contained in:
Konstantin Isakov 2009-05-29 19:48:50 +00:00
parent 2b2de01e95
commit 05d53409bf
19 changed files with 300 additions and 87 deletions

View file

@ -112,7 +112,8 @@ std::string ArticleMaker::makeNotFoundBody( QString const & word,
} }
sptr< Dictionary::DataRequest > ArticleMaker::makeDefinitionFor( sptr< Dictionary::DataRequest > ArticleMaker::makeDefinitionFor(
QString const & inWord, unsigned groupId ) const QString const & inWord, unsigned groupId,
QMap< QString, QString > const & contexts ) const
{ {
if ( groupId == UINT_MAX ) if ( groupId == UINT_MAX )
{ {
@ -191,7 +192,8 @@ sptr< Dictionary::DataRequest > ArticleMaker::makeDefinitionFor(
activeGroup && activeGroup->icon.size() ? activeGroup && activeGroup->icon.size() ?
activeGroup->icon : QString() ); activeGroup->icon : QString() );
return new ArticleRequest( inWord.trimmed(), activeGroup ? activeGroup->name : "", activeDicts, header ); return new ArticleRequest( inWord.trimmed(), activeGroup ? activeGroup->name : "",
contexts, activeDicts, header );
} }
sptr< Dictionary::DataRequest > ArticleMaker::makeNotFoundTextFor( sptr< Dictionary::DataRequest > ArticleMaker::makeNotFoundTextFor(
@ -226,9 +228,11 @@ sptr< Dictionary::DataRequest > ArticleMaker::makeEmptyPage() const
ArticleRequest::ArticleRequest( ArticleRequest::ArticleRequest(
QString const & word_, QString const & group_, QString const & word_, QString const & group_,
QMap< QString, QString > const & contexts_,
vector< sptr< Dictionary::Class > > const & activeDicts_, vector< sptr< Dictionary::Class > > const & activeDicts_,
string const & header ): string const & header ):
word( word_ ), group( group_ ), activeDicts( activeDicts_ ), word( word_ ), group( group_ ), contexts( contexts_ ),
activeDicts( activeDicts_ ),
altsDone( false ), bodyDone( false ), foundAnyDefinitions( false ), altsDone( false ), bodyDone( false ), foundAnyDefinitions( false ),
closePrevSpan( false ) closePrevSpan( false )
{ {
@ -295,7 +299,8 @@ void ArticleRequest::altSearchFinished()
for( unsigned x = 0; x < activeDicts.size(); ++x ) for( unsigned x = 0; x < activeDicts.size(); ++x )
{ {
sptr< Dictionary::DataRequest > r = sptr< Dictionary::DataRequest > r =
activeDicts[ x ]->getArticle( wordStd, altsVector ); activeDicts[ x ]->getArticle( wordStd, altsVector,
gd::toWString( contexts.value( QString::fromStdString( activeDicts[ x ]->getId() ) ) ) );
connect( r.get(), SIGNAL( finished() ), connect( r.get(), SIGNAL( finished() ),
this, SLOT( bodyFinished() ) ); this, SLOT( bodyFinished() ) );

View file

@ -5,6 +5,7 @@
#define __ARTICLE_MAKER_HH_INCLUDED__ #define __ARTICLE_MAKER_HH_INCLUDED__
#include <QObject> #include <QObject>
#include <QMap>
#include <set> #include <set>
#include <list> #include <list>
#include "dictionary.hh" #include "dictionary.hh"
@ -40,7 +41,10 @@ public:
/// The result is returned as Dictionary::DataRequest just like dictionaries /// The result is returned as Dictionary::DataRequest just like dictionaries
/// themselves do. The difference is that the result is a complete html page /// themselves do. The difference is that the result is a complete html page
/// with all definitions from all the relevant dictionaries. /// with all definitions from all the relevant dictionaries.
sptr< Dictionary::DataRequest > makeDefinitionFor( QString const & word, unsigned groupId ) const; /// Contexts is a map of context values to be passed to each dictionary, where
/// the keys are dictionary ids.
sptr< Dictionary::DataRequest > makeDefinitionFor( QString const & word, unsigned groupId,
QMap< QString, QString > const & contexts ) const;
/// Makes up a text which states that no translation for the given word /// Makes up a text which states that no translation for the given word
/// was found. Sometimes it's better to call this directly when it's already /// was found. Sometimes it's better to call this directly when it's already
@ -68,6 +72,7 @@ class ArticleRequest: public Dictionary::DataRequest
Q_OBJECT Q_OBJECT
QString word, group; QString word, group;
QMap< QString, QString > contexts;
std::vector< sptr< Dictionary::Class > > const & activeDicts; std::vector< sptr< Dictionary::Class > > const & activeDicts;
std::set< gd::wstring > alts; // Accumulated main forms std::set< gd::wstring > alts; // Accumulated main forms
@ -82,6 +87,7 @@ class ArticleRequest: public Dictionary::DataRequest
public: public:
ArticleRequest( QString const & word, QString const & group, ArticleRequest( QString const & word, QString const & group,
QMap< QString, QString > const & contexts,
std::vector< sptr< Dictionary::Class > > const & activeDicts, std::vector< sptr< Dictionary::Class > > const & activeDicts,
std::string const & header ); std::string const & header );

View file

@ -63,8 +63,27 @@ sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource(
QString word = url.queryItemValue( "word" ); QString word = url.queryItemValue( "word" );
unsigned group = url.queryItemValue( "group" ).toUInt( &groupIsValid ); unsigned group = url.queryItemValue( "group" ).toUInt( &groupIsValid );
// Unpack contexts
QMap< QString, QString > contexts;
QString contextsEncoded = url.queryItemValue( "contexts" );
if ( contextsEncoded.size() )
{
QByteArray ba = QByteArray::fromBase64( contextsEncoded.toAscii() );
QBuffer buf( & ba );
buf.open( QBuffer::ReadOnly );
QDataStream stream( &buf );
stream >> contexts;
}
if ( groupIsValid && word.size() ) // Require group and word to be passed if ( groupIsValid && word.size() ) // Require group and word to be passed
return articleMaker.makeDefinitionFor( word, group ); return articleMaker.makeDefinitionFor( word, group, contexts );
} }
if ( ( url.scheme() == "bres" || url.scheme() == "gdau" ) && if ( ( url.scheme() == "bres" || url.scheme() == "gdau" ) &&

View file

@ -122,7 +122,8 @@ ArticleView::~ArticleView()
} }
void ArticleView::showDefinition( QString const & word, unsigned group, void ArticleView::showDefinition( QString const & word, unsigned group,
QString const & scrollTo ) QString const & scrollTo,
Contexts const & contexts )
{ {
QUrl req; QUrl req;
@ -132,7 +133,22 @@ void ArticleView::showDefinition( QString const & word, unsigned group,
req.addQueryItem( "group", QString::number( group ) ); req.addQueryItem( "group", QString::number( group ) );
if ( scrollTo.size() ) if ( scrollTo.size() )
req.setFragment( scrollTo ); req.addQueryItem( "scrollto", scrollTo );
if ( contexts.size() )
{
QBuffer buf;
buf.open( QIODevice::WriteOnly );
QDataStream stream( &buf );
stream << contexts;
buf.close();
req.addQueryItem( "contexts", QString::fromAscii( buf.buffer().toBase64() ) );
}
// Save current article, if any // Save current article, if any
@ -158,22 +174,6 @@ void ArticleView::loadFinished( bool )
{ {
QUrl url = ui.definition->url(); 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() );
}
// See if we have any iframes in need of expansion // See if we have any iframes in need of expansion
QList< QWebFrame * > frames = ui.definition->page()->mainFrame()->childFrames(); QList< QWebFrame * > frames = ui.definition->page()->mainFrame()->childFrames();
@ -197,6 +197,10 @@ void ArticleView::loadFinished( bool )
ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "document.getElementById('%1').style.display = 'block';" ). ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "document.getElementById('%1').style.display = 'block';" ).
arg( (*i)->frameName() ) ); arg( (*i)->frameName() ) );
(*i)->evaluateJavaScript( "var gdLastUrlText;" );
(*i)->evaluateJavaScript( "document.addEventListener( 'click', function() { gdLastUrlText = window.event.srcElement.text; }, true );" );
(*i)->evaluateJavaScript( "document.addEventListener( 'contextmenu', function() { gdLastUrlText = window.event.srcElement.text; }, true );" );
wereFrames = true; wereFrames = true;
} }
} }
@ -210,6 +214,23 @@ void ArticleView::loadFinished( bool )
qApp->sendEvent( ui.definition, &ev ); qApp->sendEvent( ui.definition, &ev );
} }
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.queryItemValue( "scrollto" ).startsWith( "gdfrom-" ) )
{
// There is no active article saved in history, but we have it as a parameter.
// setCurrentArticle will save it and scroll there.
setCurrentArticle( url.queryItemValue( "scrollto" ), true );
}
ui.definition->unsetCursor(); ui.definition->unsetCursor();
//QApplication::restoreOverrideCursor(); //QApplication::restoreOverrideCursor();
emit pageLoaded( this ); emit pageLoaded( this );
@ -278,11 +299,7 @@ void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
if ( getArticlesList().contains( id.mid( 7 ) ) ) if ( getArticlesList().contains( id.mid( 7 ) ) )
{ {
if ( moveToIt ) if ( moveToIt )
{ ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "document.getElementById('%1').scrollIntoView(true);" ).arg( id ) );
QUrl url( ui.definition->url() );
url.setFragment( id );
openLink( url, ui.definition->url() );
}
ui.definition->history()->currentItem().setUserData( id ); ui.definition->history()->currentItem().setUserData( id );
ui.definition->page()->mainFrame()->evaluateJavaScript( ui.definition->page()->mainFrame()->evaluateJavaScript(
@ -290,6 +307,72 @@ void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
} }
} }
bool ArticleView::isFramedArticle( QString const & ca )
{
if ( ca.isEmpty() )
return false;
return ui.definition->page()->mainFrame()->
evaluateJavaScript( QString( "!!document.getElementById('gdexpandframe-%1');" ).arg( ca.mid( 7 ) ) ).toBool();
}
bool ArticleView::isExternalLink( QUrl const & url )
{
return url.scheme() == "http" || url.scheme() == "https" ||
url.scheme() == "ftp" || url.scheme() == "mailto";
}
void ArticleView::tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts )
{
if( url.scheme() == "http" || url.scheme() == "https" )
{
// Maybe a link inside a website was clicked?
QString ca = getCurrentArticle();
if ( isFramedArticle( ca ) )
{
QVariant result = ui.definition->page()->currentFrame()->evaluateJavaScript( "gdLastUrlText;" );
if ( result.type() == QVariant::String )
{
// Looks this way
contexts[ ca.mid( 7 ) ] = QString::fromAscii( url.toEncoded() );
QUrl target;
target.setScheme( "gdlookup" );
target.setHost( "localhost" );
target.setPath( "/" + result.toString() );
url = target;
}
}
}
}
void ArticleView::updateCurrentArticleFromCurrentFrame( QWebFrame * frame )
{
if ( !frame )
frame = ui.definition->page()->currentFrame();
for( ; frame; frame = frame->parentFrame() )
{
QString frameName = frame->frameName();
if ( frameName.startsWith( "gdexpandframe-" ) )
{
QString newCurrent = "gdfrom-" + frameName.mid( 14 );
if ( getCurrentArticle() != newCurrent )
setCurrentArticle( newCurrent, false );
break;
}
}
}
void ArticleView::cleanupTemp() void ArticleView::cleanupTemp()
{ {
if ( desktopOpenedTempFile.size() ) if ( desktopOpenedTempFile.size() )
@ -332,13 +415,21 @@ bool ArticleView::eventFilter( QObject * obj, QEvent * ev )
} }
void ArticleView::linkClicked( QUrl const & url ) void ArticleView::linkClicked( QUrl const & url_ )
{ {
openLink( url, ui.definition->url(), getCurrentArticle() ); updateCurrentArticleFromCurrentFrame();
QUrl url( url_ );
Contexts contexts;
tryMangleWebsiteClickedUrl( url, contexts );
openLink( url, ui.definition->url(), getCurrentArticle(), contexts );
} }
void ArticleView::openLink( QUrl const & url, QUrl const & ref, void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QString const & scrollTo ) QString const & scrollTo,
Contexts const & contexts )
{ {
printf( "clicked %s\n", url.toString().toLocal8Bit().data() ); printf( "clicked %s\n", url.toString().toLocal8Bit().data() );
@ -346,7 +437,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
showDefinition( ( url.host().startsWith( "xn--" ) ? showDefinition( ( url.host().startsWith( "xn--" ) ?
QUrl::fromPunycode( url.host().toLatin1() ) : QUrl::fromPunycode( url.host().toLatin1() ) :
url.host() ) + url.path(), url.host() ) + url.path(),
getGroup( ref ), scrollTo ); getGroup( ref ), scrollTo, contexts );
else else
if ( url.scheme() == "gdlookup" ) // Plain html links inherit gdlookup scheme if ( url.scheme() == "gdlookup" ) // Plain html links inherit gdlookup scheme
{ {
@ -357,7 +448,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
} }
else else
showDefinition( url.path().mid( 1 ), showDefinition( url.path().mid( 1 ),
getGroup( ref ), scrollTo ); getGroup( ref ), scrollTo, contexts );
} }
else else
if ( url.scheme() == "bres" || url.scheme() == "gdau" ) if ( url.scheme() == "bres" || url.scheme() == "gdau" )
@ -511,31 +602,45 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
QWebHitTestResult r = ui.definition->page()->mainFrame()-> QWebHitTestResult r = ui.definition->page()->mainFrame()->
hitTestContent( pos ); hitTestContent( pos );
updateCurrentArticleFromCurrentFrame( r.frame() );
QMenu menu( this ); QMenu menu( this );
QAction * followLink = 0; QAction * followLink = 0;
QAction * followLinkExternal = 0;
QAction * followLinkNewTab = 0; QAction * followLinkNewTab = 0;
QAction * lookupSelection = 0; QAction * lookupSelection = 0;
QAction * lookupSelectionGr = 0; QAction * lookupSelectionGr = 0;
QAction * lookupSelectionNewTab = 0; QAction * lookupSelectionNewTab = 0;
QAction * lookupSelectionNewTabGr = 0; QAction * lookupSelectionNewTabGr = 0;
QUrl targetUrl( r.linkUrl() );
Contexts contexts;
tryMangleWebsiteClickedUrl( targetUrl, contexts );
if ( !r.linkUrl().isEmpty() ) if ( !r.linkUrl().isEmpty() )
{ {
followLink = new QAction( tr( "&Open Link" ), &menu ); if ( !isExternalLink( targetUrl ) )
menu.addAction( followLink );
if ( !popupView )
{ {
followLinkNewTab = new QAction( tr( "Open Link in New &Tab" ), &menu ); followLink = new QAction( tr( "&Open Link" ), &menu );
menu.addAction( followLinkNewTab ); menu.addAction( followLink );
if ( !popupView )
{
followLinkNewTab = new QAction( QIcon( ":/icons/addtab.png" ),
tr( "Open Link in New &Tab" ), &menu );
menu.addAction( followLinkNewTab );
}
} }
QString scheme = r.linkUrl().scheme(); if ( isExternalLink( r.linkUrl() ) )
{
if ( scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "mailto" ) followLinkExternal = new QAction( tr( "Open Link in &External Browser" ), &menu );
menu.addAction( followLinkExternal );
menu.addAction( ui.definition->pageAction( QWebPage::CopyLinkToClipboard ) ); menu.addAction( ui.definition->pageAction( QWebPage::CopyLinkToClipboard ) );
}
} }
QString selectedText = ui.definition->selectedText(); QString selectedText = ui.definition->selectedText();
@ -628,8 +733,14 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
{ {
QAction * result = menu.exec( ui.definition->mapToGlobal( pos ) ); QAction * result = menu.exec( ui.definition->mapToGlobal( pos ) );
if ( !result )
return;
if ( result == followLink ) if ( result == followLink )
linkClicked( r.linkUrl() ); openLink( targetUrl, ui.definition->url(), getCurrentArticle(), contexts );
else
if ( result == followLinkExternal )
QDesktopServices::openUrl( r.linkUrl() );
else else
if ( result == lookupSelection ) if ( result == lookupSelection )
showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() ); showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() );
@ -638,15 +749,15 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
showDefinition( selectedText, groupComboBox->getCurrentGroup(), QString() ); showDefinition( selectedText, groupComboBox->getCurrentGroup(), QString() );
else else
if ( !popupView && result == followLinkNewTab ) if ( !popupView && result == followLinkNewTab )
emit openLinkInNewTab( r.linkUrl(), ui.definition->url(), getCurrentArticle() ); emit openLinkInNewTab( targetUrl, ui.definition->url(), getCurrentArticle(), contexts );
else else
if ( !popupView && result == lookupSelectionNewTab ) if ( !popupView && result == lookupSelectionNewTab )
emit showDefinitionInNewTab( selectedText, getGroup( ui.definition->url() ), emit showDefinitionInNewTab( selectedText, getGroup( ui.definition->url() ),
getCurrentArticle() ); getCurrentArticle(), Contexts() );
else else
if ( !popupView && result == lookupSelectionNewTabGr && groupComboBox ) if ( !popupView && result == lookupSelectionNewTabGr && groupComboBox )
emit showDefinitionInNewTab( selectedText, groupComboBox->getCurrentGroup(), emit showDefinitionInNewTab( selectedText, groupComboBox->getCurrentGroup(),
QString() ); QString(), Contexts() );
else else
{ {
// Match against table of contents // Match against table of contents

View file

@ -6,6 +6,7 @@
#include <QWebView> #include <QWebView>
#include <QUrl> #include <QUrl>
#include <QMap>
#include <list> #include <list>
#include "article_netmgr.hh" #include "article_netmgr.hh"
#include "instances.hh" #include "instances.hh"
@ -65,11 +66,17 @@ public:
~ArticleView(); ~ArticleView();
typedef QMap< QString, QString > Contexts;
/// Shows the definition of the given word with the given group. /// Shows the definition of the given word with the given group.
/// scrollTo can be optionally set to a "gdfrom-xxxx" identifier to position /// scrollTo can be optionally set to a "gdfrom-xxxx" identifier to position
/// the page to that article on load. /// the page to that article on load.
/// contexts is an optional map of context values to be passed for dictionaries.
/// The only values to pass here are ones obtained from showDefinitionInNewTab()
/// signal or none at all.
void showDefinition( QString const & word, unsigned group, void showDefinition( QString const & word, unsigned group,
QString const & scrollTo = QString() ); QString const & scrollTo = QString(),
Contexts const & contexts = Contexts() );
/// Clears the view and sets the application-global waiting cursor, /// Clears the view and sets the application-global waiting cursor,
/// which will be restored when some article loads eventually. /// which will be restored when some article loads eventually.
@ -78,8 +85,12 @@ public:
/// Opens the given link. Supposed to be used in response to /// Opens the given link. Supposed to be used in response to
/// openLinkInNewTab() signal. The link scheme is therefore supposed to be /// openLinkInNewTab() signal. The link scheme is therefore supposed to be
/// one of the internal ones. /// one of the internal ones.
/// contexts is an optional map of context values to be passed for dictionaries.
/// The only values to pass here are ones obtained from showDefinitionInNewTab()
/// signal or none at all.
void openLink( QUrl const & url, QUrl const & referrer, void openLink( QUrl const & url, QUrl const & referrer,
QString const & scrollTo = QString() ); QString const & scrollTo = QString(),
Contexts const & contexts = Contexts() );
/// Goes back in history /// Goes back in history
void back() void back()
@ -129,10 +140,12 @@ signals:
/// Singals that the following link was requested to be opened in new tab /// Singals that the following link was requested to be opened in new tab
void openLinkInNewTab( QUrl const &, QUrl const & referrer, void openLinkInNewTab( QUrl const &, QUrl const & referrer,
QString const & fromArticle ); QString const & fromArticle,
ArticleView::Contexts const & contexts );
/// Singals that the following definition was requested to be showed in new tab /// Singals that the following definition was requested to be showed in new tab
void showDefinitionInNewTab( QString const & word, unsigned group, void showDefinitionInNewTab( QString const & word, unsigned group,
QString const & fromArticle ); QString const & fromArticle,
ArticleView::Contexts const & contexts );
/// Emitted when user types a text key. This should typically be used to /// Emitted when user types a text key. This should typically be used to
/// switch focus to word input. /// switch focus to word input.
@ -183,6 +196,23 @@ private:
/// If moveToIt is true, it moves the focus to it as well. /// If moveToIt is true, it moves the focus to it as well.
void setCurrentArticle( QString const &, bool moveToIt = false ); void setCurrentArticle( QString const &, bool moveToIt = false );
/// Checks if the given article in form of "gdfrom-xxx" is inside a "website"
/// frame.
bool isFramedArticle( QString const & );
/// Checks if the given link is to be opened externally, as opposed to opening
/// it in-place.
bool isExternalLink( QUrl const & url );
/// Sees if the last clicked link is from a website frame. If so, changes url
/// to point to url text translation instead, and saves the original
/// url to the appropriate "contexts" entry.
void tryMangleWebsiteClickedUrl( QUrl & url, Contexts & contexts );
/// Use the known information about the current frame to update the current
/// article's value.
void updateCurrentArticleFromCurrentFrame( QWebFrame * frame = 0 );
/// Attempts removing last temporary file created. /// Attempts removing last temporary file created.
void cleanupTemp(); void cleanupTemp();

View file

@ -241,7 +241,8 @@ namespace
throw( std::exception ); throw( std::exception );
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
virtual sptr< Dictionary::DataRequest > getResource( string const & name ) virtual sptr< Dictionary::DataRequest > getResource( string const & name )
@ -673,7 +674,8 @@ void BglArticleRequest::run()
} }
sptr< Dictionary::DataRequest > BglDictionary::getArticle( wstring const & word, sptr< Dictionary::DataRequest > BglDictionary::getArticle( wstring const & word,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
return new BglArticleRequest( word, alts, *this ); return new BglArticleRequest( word, alts, *this );

View file

@ -110,7 +110,8 @@ public:
{ return idxHeader.langTo; } { return idxHeader.langTo; }
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
}; };
@ -185,7 +186,8 @@ uint32_t decodeBase64( string const & str )
} }
sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & word, sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & word,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
try try

View file

@ -319,7 +319,11 @@ public:
/// The 'alts' vector could contain a list of words the definitions of which /// The 'alts' vector could contain a list of words the definitions of which
/// should be included in the output as well, being treated as additional /// should be included in the output as well, being treated as additional
/// synonyms for the main word. /// synonyms for the main word.
virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts ) /// context is a dictionary-specific data, currently only used for the
/// 'Websites' feature.
virtual sptr< DataRequest > getArticle( wstring const &,
vector< wstring > const & alts,
wstring const & context = wstring() )
throw( std::exception )=0; throw( std::exception )=0;
/// Loads contents of a resource named 'name' into the 'data' vector. This is /// Loads contents of a resource named 'name' into the 'data' vector. This is

View file

@ -162,7 +162,8 @@ public:
#endif #endif
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
virtual sptr< Dictionary::DataRequest > getResource( string const & name ) virtual sptr< Dictionary::DataRequest > getResource( string const & name )
@ -1056,7 +1057,8 @@ void DslArticleRequest::run()
} }
sptr< Dictionary::DataRequest > DslDictionary::getArticle( wstring const & word, sptr< Dictionary::DataRequest > DslDictionary::getArticle( wstring const & word,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
return new DslArticleRequest( word, alts, *this ); return new DslArticleRequest( word, alts, *this );

View file

@ -65,7 +65,9 @@ public:
virtual sptr< WordSearchRequest > findHeadwordsForSynonym( wstring const & ) virtual sptr< WordSearchRequest > findHeadwordsForSynonym( wstring const & )
throw( std::exception ); throw( std::exception );
virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts ) virtual sptr< DataRequest > getArticle( wstring const &,
vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
}; };
@ -252,7 +254,9 @@ void HunspellArticleRequest::run()
finish(); finish();
} }
sptr< DataRequest > HunspellDictionary::getArticle( wstring const & word, vector< wstring > const & ) sptr< DataRequest > HunspellDictionary::getArticle( wstring const & word,
vector< wstring > const &,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
return new HunspellArticleRequest( word, hunspellMutex, hunspell ); return new HunspellArticleRequest( word, hunspellMutex, hunspell );

View file

@ -173,7 +173,8 @@ public:
{ return QIcon(":/icons/playsound.png"); } { return QIcon(":/icons/playsound.png"); }
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
virtual sptr< Dictionary::DataRequest > getResource( string const & name ) virtual sptr< Dictionary::DataRequest > getResource( string const & name )
@ -205,7 +206,8 @@ LsaDictionary::LsaDictionary( string const & id,
} }
sptr< Dictionary::DataRequest > LsaDictionary::getArticle( wstring const & word, sptr< Dictionary::DataRequest > LsaDictionary::getArticle( wstring const & word,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
vector< WordArticleLink > chain = findArticles( word ); vector< WordArticleLink > chain = findArticles( word );

View file

@ -530,11 +530,11 @@ ArticleView * MainWindow::createNewTab( bool switchToIt,
connect( view, SIGNAL( pageLoaded( ArticleView * ) ), connect( view, SIGNAL( pageLoaded( ArticleView * ) ),
this, SLOT( pageLoaded( ArticleView * ) ) ); this, SLOT( pageLoaded( ArticleView * ) ) );
connect( view, SIGNAL( openLinkInNewTab( QUrl const &, QUrl const &, QString const & ) ), connect( view, SIGNAL( openLinkInNewTab( QUrl const &, QUrl const &, QString const &, ArticleView::Contexts const & ) ),
this, SLOT( openLinkInNewTab( QUrl const &, QUrl const &, QString const & ) ) ); this, SLOT( openLinkInNewTab( QUrl const &, QUrl const &, QString const &, ArticleView::Contexts const & ) ) );
connect( view, SIGNAL( showDefinitionInNewTab( QString const &, unsigned, QString const & ) ), connect( view, SIGNAL( showDefinitionInNewTab( QString const &, unsigned, QString const &, ArticleView::Contexts const & ) ),
this, SLOT( showDefinitionInNewTab( QString const &, unsigned, QString const & ) ) ); this, SLOT( showDefinitionInNewTab( QString const &, unsigned, QString const &, ArticleView::Contexts const & ) ) );
connect( view, SIGNAL( typingEvent( QString const & ) ), connect( view, SIGNAL( typingEvent( QString const & ) ),
this, SLOT( typingEvent( QString const & ) ) ); this, SLOT( typingEvent( QString const & ) ) );
@ -943,18 +943,20 @@ void MainWindow::wordListSelectionChanged()
void MainWindow::openLinkInNewTab( QUrl const & url, void MainWindow::openLinkInNewTab( QUrl const & url,
QUrl const & referrer, QUrl const & referrer,
QString const & fromArticle ) QString const & fromArticle,
ArticleView::Contexts const & contexts )
{ {
createNewTab( !cfg.preferences.newTabsOpenInBackground, "" )-> createNewTab( !cfg.preferences.newTabsOpenInBackground, "" )->
openLink( url, referrer, fromArticle ); openLink( url, referrer, fromArticle, contexts );
} }
void MainWindow::showDefinitionInNewTab( QString const & word, void MainWindow::showDefinitionInNewTab( QString const & word,
unsigned group, unsigned group,
QString const & fromArticle ) QString const & fromArticle,
ArticleView::Contexts const & contexts )
{ {
createNewTab( !cfg.preferences.newTabsOpenInBackground, word )-> createNewTab( !cfg.preferences.newTabsOpenInBackground, word )->
showDefinition( word, group, fromArticle ); showDefinition( word, group, fromArticle, contexts );
} }
void MainWindow::typingEvent( QString const & t ) void MainWindow::typingEvent( QString const & t )

View file

@ -177,9 +177,11 @@ private slots:
ArticleView * createNewTab( bool switchToIt, ArticleView * createNewTab( bool switchToIt,
QString const & name ); QString const & name );
void openLinkInNewTab( QUrl const &, QUrl const &, QString const & ); void openLinkInNewTab( QUrl const &, QUrl const &, QString const &,
ArticleView::Contexts const & contexts );
void showDefinitionInNewTab( QString const & word, unsigned group, void showDefinitionInNewTab( QString const & word, unsigned group,
QString const & fromArticle ); QString const & fromArticle,
ArticleView::Contexts const & contexts );
void typingEvent( QString const & ); void typingEvent( QString const & );
void showTranslationFor( QString const & ); void showTranslationFor( QString const & );

View file

@ -51,7 +51,8 @@ public:
virtual sptr< WordSearchRequest > prefixMatch( wstring const &, virtual sptr< WordSearchRequest > prefixMatch( wstring const &,
unsigned long maxResults ) throw( std::exception ); unsigned long maxResults ) throw( std::exception );
virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts ) virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
}; };
@ -341,7 +342,9 @@ sptr< WordSearchRequest > MediaWikiDictionary::prefixMatch( wstring const & word
return new MediaWikiWordSearchRequest( word, url, netMgr ); return new MediaWikiWordSearchRequest( word, url, netMgr );
} }
sptr< DataRequest > MediaWikiDictionary::getArticle( wstring const & word, vector< wstring > const & alts ) sptr< DataRequest > MediaWikiDictionary::getArticle( wstring const & word,
vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
return new MediaWikiArticleRequest( word, alts, url, netMgr ); return new MediaWikiArticleRequest( word, alts, url, netMgr );

View file

@ -89,7 +89,8 @@ public:
{ return QIcon(":/icons/playsound.png"); } { return QIcon(":/icons/playsound.png"); }
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
virtual sptr< Dictionary::DataRequest > getResource( string const & name ) virtual sptr< Dictionary::DataRequest > getResource( string const & name )
@ -114,7 +115,8 @@ SoundDirDictionary::SoundDirDictionary( string const & id,
} }
sptr< Dictionary::DataRequest > SoundDirDictionary::getArticle( wstring const & word, sptr< Dictionary::DataRequest > SoundDirDictionary::getArticle( wstring const & word,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
vector< WordArticleLink > chain = findArticles( word ); vector< WordArticleLink > chain = findArticles( word );

View file

@ -153,7 +153,8 @@ public:
throw( std::exception ); throw( std::exception );
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ); throw( std::exception );
private: private:
@ -732,7 +733,8 @@ void StardictArticleRequest::run()
} }
sptr< Dictionary::DataRequest > StardictDictionary::getArticle( wstring const & word, sptr< Dictionary::DataRequest > StardictDictionary::getArticle( wstring const & word,
vector< wstring > const & alts ) vector< wstring > const & alts,
wstring const & )
throw( std::exception ) throw( std::exception )
{ {
return new StardictArticleRequest( word, alts, *this ); return new StardictArticleRequest( word, alts, *this );

View file

@ -47,7 +47,8 @@ sptr< Dictionary::WordSearchRequest > TransliterationDictionary::prefixMatch( ws
{ return new Dictionary::WordSearchRequestInstant(); } { return new Dictionary::WordSearchRequestInstant(); }
sptr< Dictionary::DataRequest > TransliterationDictionary::getArticle( wstring const &, sptr< Dictionary::DataRequest > TransliterationDictionary::getArticle( wstring const &,
vector< wstring > const & ) vector< wstring > const &,
wstring const & )
throw( std::exception ) throw( std::exception )
{ return new Dictionary::DataRequestInstant( false ); } { return new Dictionary::DataRequestInstant( false ); }

View file

@ -69,7 +69,8 @@ public:
unsigned long ) throw( std::exception ); unsigned long ) throw( std::exception );
virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
vector< wstring > const & ) vector< wstring > const &,
wstring const & )
throw( std::exception ); throw( std::exception );
}; };

View file

@ -3,6 +3,7 @@
#include "website.hh" #include "website.hh"
#include "wstring_qt.hh" #include "wstring_qt.hh"
#include "utf8.hh"
#include <QUrl> #include <QUrl>
#include <QTextCodec> #include <QTextCodec>
@ -45,7 +46,9 @@ public:
virtual sptr< WordSearchRequest > prefixMatch( wstring const & word, virtual sptr< WordSearchRequest > prefixMatch( wstring const & word,
unsigned long ) throw( std::exception ); unsigned long ) throw( std::exception );
virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts ) virtual sptr< DataRequest > getArticle( wstring const &,
vector< wstring > const & alts,
wstring const & context )
throw( std::exception ); throw( std::exception );
}; };
@ -59,18 +62,28 @@ sptr< WordSearchRequest > WebSiteDictionary::prefixMatch( wstring const & word,
return sr; return sr;
} }
sptr< DataRequest > WebSiteDictionary::getArticle( wstring const & str, vector< wstring > const & ) sptr< DataRequest > WebSiteDictionary::getArticle( wstring const & str,
vector< wstring > const &,
wstring const & context )
throw( std::exception ) throw( std::exception )
{ {
sptr< DataRequestInstant > dr = new DataRequestInstant( true ); sptr< DataRequestInstant > dr = new DataRequestInstant( true );
QByteArray urlString( urlTemplate ); QByteArray urlString;
QString inputWord = gd::toQString( str ); // Context contains the right url to go to
if ( context.size() )
urlString = Utf8::encode( context ).c_str();
else
{
urlString = urlTemplate;
urlString.replace( "%25GDWORD%25", inputWord.toUtf8().toPercentEncoding() ); QString inputWord = gd::toQString( str );
urlString.replace( "%25GD1251%25", QTextCodec::codecForName( "Windows-1251" )->fromUnicode( inputWord ).toPercentEncoding() );
urlString.replace( "%25GDISO1%25", QTextCodec::codecForName( "ISO 8859-1" )->fromUnicode( inputWord ).toPercentEncoding() ); urlString.replace( "%25GDWORD%25", inputWord.toUtf8().toPercentEncoding() );
urlString.replace( "%25GD1251%25", QTextCodec::codecForName( "Windows-1251" )->fromUnicode( inputWord ).toPercentEncoding() );
urlString.replace( "%25GDISO1%25", QTextCodec::codecForName( "ISO 8859-1" )->fromUnicode( inputWord ).toPercentEncoding() );
}
string result = "<div class=\"website_padding\"></div>"; string result = "<div class=\"website_padding\"></div>";