From 05d53409bf742768446e362884c17f6aa3c210f3 Mon Sep 17 00:00:00 2001 From: Konstantin Isakov Date: Fri, 29 May 2009 19:48:50 +0000 Subject: [PATCH] + 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! --- src/article_maker.cc | 13 ++- src/article_maker.hh | 8 +- src/article_netmgr.cc | 21 ++++- src/articleview.cc | 193 ++++++++++++++++++++++++++++++++--------- src/articleview.hh | 38 +++++++- src/bgl.cc | 6 +- src/dictdfiles.cc | 6 +- src/dictionary.hh | 6 +- src/dsl.cc | 6 +- src/hunspell.cc | 8 +- src/lsa.cc | 6 +- src/mainwindow.cc | 18 ++-- src/mainwindow.hh | 6 +- src/mediawiki.cc | 7 +- src/sounddir.cc | 6 +- src/stardict.cc | 6 +- src/transliteration.cc | 3 +- src/transliteration.hh | 3 +- src/website.cc | 27 ++++-- 19 files changed, 300 insertions(+), 87 deletions(-) diff --git a/src/article_maker.cc b/src/article_maker.cc index 59af9fd3..92acc126 100644 --- a/src/article_maker.cc +++ b/src/article_maker.cc @@ -112,7 +112,8 @@ std::string ArticleMaker::makeNotFoundBody( QString const & word, } 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 ) { @@ -191,7 +192,8 @@ sptr< Dictionary::DataRequest > ArticleMaker::makeDefinitionFor( activeGroup && activeGroup->icon.size() ? 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( @@ -226,9 +228,11 @@ sptr< Dictionary::DataRequest > ArticleMaker::makeEmptyPage() const ArticleRequest::ArticleRequest( QString const & word_, QString const & group_, + QMap< QString, QString > const & contexts_, vector< sptr< Dictionary::Class > > const & activeDicts_, string const & header ): - word( word_ ), group( group_ ), activeDicts( activeDicts_ ), + word( word_ ), group( group_ ), contexts( contexts_ ), + activeDicts( activeDicts_ ), altsDone( false ), bodyDone( false ), foundAnyDefinitions( false ), closePrevSpan( false ) { @@ -295,7 +299,8 @@ void ArticleRequest::altSearchFinished() for( unsigned x = 0; x < activeDicts.size(); ++x ) { 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() ), this, SLOT( bodyFinished() ) ); diff --git a/src/article_maker.hh b/src/article_maker.hh index 4cd399d2..a47a47c2 100644 --- a/src/article_maker.hh +++ b/src/article_maker.hh @@ -5,6 +5,7 @@ #define __ARTICLE_MAKER_HH_INCLUDED__ #include +#include #include #include #include "dictionary.hh" @@ -40,7 +41,10 @@ public: /// The result is returned as Dictionary::DataRequest just like dictionaries /// themselves do. The difference is that the result is a complete html page /// 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 /// 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 QString word, group; + QMap< QString, QString > contexts; std::vector< sptr< Dictionary::Class > > const & activeDicts; std::set< gd::wstring > alts; // Accumulated main forms @@ -82,6 +87,7 @@ class ArticleRequest: public Dictionary::DataRequest public: ArticleRequest( QString const & word, QString const & group, + QMap< QString, QString > const & contexts, std::vector< sptr< Dictionary::Class > > const & activeDicts, std::string const & header ); diff --git a/src/article_netmgr.cc b/src/article_netmgr.cc index 95a5571c..ed9673d2 100644 --- a/src/article_netmgr.cc +++ b/src/article_netmgr.cc @@ -63,8 +63,27 @@ sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource( QString word = url.queryItemValue( "word" ); 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 - return articleMaker.makeDefinitionFor( word, group ); + return articleMaker.makeDefinitionFor( word, group, contexts ); } if ( ( url.scheme() == "bres" || url.scheme() == "gdau" ) && diff --git a/src/articleview.cc b/src/articleview.cc index 6583054b..04bda94b 100644 --- a/src/articleview.cc +++ b/src/articleview.cc @@ -122,7 +122,8 @@ ArticleView::~ArticleView() } void ArticleView::showDefinition( QString const & word, unsigned group, - QString const & scrollTo ) + QString const & scrollTo, + Contexts const & contexts ) { QUrl req; @@ -132,7 +133,22 @@ void ArticleView::showDefinition( QString const & word, unsigned group, req.addQueryItem( "group", QString::number( group ) ); 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 @@ -158,22 +174,6 @@ void ArticleView::loadFinished( bool ) { 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 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';" ). 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; } } @@ -210,6 +214,23 @@ void ArticleView::loadFinished( bool ) 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(); //QApplication::restoreOverrideCursor(); emit pageLoaded( this ); @@ -278,11 +299,7 @@ void ArticleView::setCurrentArticle( QString const & id, bool moveToIt ) if ( getArticlesList().contains( id.mid( 7 ) ) ) { if ( moveToIt ) - { - QUrl url( ui.definition->url() ); - url.setFragment( id ); - openLink( url, ui.definition->url() ); - } + ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "document.getElementById('%1').scrollIntoView(true);" ).arg( id ) ); ui.definition->history()->currentItem().setUserData( id ); 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() { 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, - QString const & scrollTo ) + QString const & scrollTo, + Contexts const & contexts ) { 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--" ) ? QUrl::fromPunycode( url.host().toLatin1() ) : url.host() ) + url.path(), - getGroup( ref ), scrollTo ); + getGroup( ref ), scrollTo, contexts ); else if ( url.scheme() == "gdlookup" ) // Plain html links inherit gdlookup scheme { @@ -357,7 +448,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref, } else showDefinition( url.path().mid( 1 ), - getGroup( ref ), scrollTo ); + getGroup( ref ), scrollTo, contexts ); } else if ( url.scheme() == "bres" || url.scheme() == "gdau" ) @@ -511,31 +602,45 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) QWebHitTestResult r = ui.definition->page()->mainFrame()-> hitTestContent( pos ); + updateCurrentArticleFromCurrentFrame( r.frame() ); + QMenu menu( this ); QAction * followLink = 0; + QAction * followLinkExternal = 0; QAction * followLinkNewTab = 0; QAction * lookupSelection = 0; QAction * lookupSelectionGr = 0; QAction * lookupSelectionNewTab = 0; QAction * lookupSelectionNewTabGr = 0; + QUrl targetUrl( r.linkUrl() ); + Contexts contexts; + + tryMangleWebsiteClickedUrl( targetUrl, contexts ); + if ( !r.linkUrl().isEmpty() ) { - followLink = new QAction( tr( "&Open Link" ), &menu ); - menu.addAction( followLink ); - - if ( !popupView ) + if ( !isExternalLink( targetUrl ) ) { - followLinkNewTab = new QAction( tr( "Open Link in New &Tab" ), &menu ); - menu.addAction( followLinkNewTab ); + followLink = new QAction( tr( "&Open Link" ), &menu ); + 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 ( scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "mailto" ) + if ( isExternalLink( r.linkUrl() ) ) + { + followLinkExternal = new QAction( tr( "Open Link in &External Browser" ), &menu ); + menu.addAction( followLinkExternal ); menu.addAction( ui.definition->pageAction( QWebPage::CopyLinkToClipboard ) ); + } } QString selectedText = ui.definition->selectedText(); @@ -628,8 +733,14 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) { QAction * result = menu.exec( ui.definition->mapToGlobal( pos ) ); + if ( !result ) + return; + if ( result == followLink ) - linkClicked( r.linkUrl() ); + openLink( targetUrl, ui.definition->url(), getCurrentArticle(), contexts ); + else + if ( result == followLinkExternal ) + QDesktopServices::openUrl( r.linkUrl() ); else if ( result == lookupSelection ) showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() ); @@ -638,15 +749,15 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) showDefinition( selectedText, groupComboBox->getCurrentGroup(), QString() ); else if ( !popupView && result == followLinkNewTab ) - emit openLinkInNewTab( r.linkUrl(), ui.definition->url(), getCurrentArticle() ); + emit openLinkInNewTab( targetUrl, ui.definition->url(), getCurrentArticle(), contexts ); else if ( !popupView && result == lookupSelectionNewTab ) emit showDefinitionInNewTab( selectedText, getGroup( ui.definition->url() ), - getCurrentArticle() ); + getCurrentArticle(), Contexts() ); else if ( !popupView && result == lookupSelectionNewTabGr && groupComboBox ) emit showDefinitionInNewTab( selectedText, groupComboBox->getCurrentGroup(), - QString() ); + QString(), Contexts() ); else { // Match against table of contents diff --git a/src/articleview.hh b/src/articleview.hh index 85cef3ed..fe5f90bc 100644 --- a/src/articleview.hh +++ b/src/articleview.hh @@ -6,6 +6,7 @@ #include #include +#include #include #include "article_netmgr.hh" #include "instances.hh" @@ -65,11 +66,17 @@ public: ~ArticleView(); + typedef QMap< QString, QString > Contexts; + /// Shows the definition of the given word with the given group. /// scrollTo can be optionally set to a "gdfrom-xxxx" identifier to position /// 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, - QString const & scrollTo = QString() ); + QString const & scrollTo = QString(), + Contexts const & contexts = Contexts() ); /// Clears the view and sets the application-global waiting cursor, /// 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 /// openLinkInNewTab() signal. The link scheme is therefore supposed to be /// 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, - QString const & scrollTo = QString() ); + QString const & scrollTo = QString(), + Contexts const & contexts = Contexts() ); /// Goes back in history void back() @@ -129,10 +140,12 @@ signals: /// Singals that the following link was requested to be opened in new tab 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 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 /// switch focus to word input. @@ -183,6 +196,23 @@ private: /// If moveToIt is true, it moves the focus to it as well. 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. void cleanupTemp(); diff --git a/src/bgl.cc b/src/bgl.cc index c3faacc3..e4db6a93 100644 --- a/src/bgl.cc +++ b/src/bgl.cc @@ -241,7 +241,8 @@ namespace throw( std::exception ); virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ); virtual sptr< Dictionary::DataRequest > getResource( string const & name ) @@ -673,7 +674,8 @@ void BglArticleRequest::run() } sptr< Dictionary::DataRequest > BglDictionary::getArticle( wstring const & word, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ) { return new BglArticleRequest( word, alts, *this ); diff --git a/src/dictdfiles.cc b/src/dictdfiles.cc index fedaaf3c..2f78673f 100644 --- a/src/dictdfiles.cc +++ b/src/dictdfiles.cc @@ -110,7 +110,8 @@ public: { return idxHeader.langTo; } virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ); }; @@ -185,7 +186,8 @@ uint32_t decodeBase64( string const & str ) } sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & word, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ) { try diff --git a/src/dictionary.hh b/src/dictionary.hh index 2a2a71a6..1fd77acc 100644 --- a/src/dictionary.hh +++ b/src/dictionary.hh @@ -319,7 +319,11 @@ public: /// 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 /// 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; /// Loads contents of a resource named 'name' into the 'data' vector. This is diff --git a/src/dsl.cc b/src/dsl.cc index 666cd7c3..08c5e042 100644 --- a/src/dsl.cc +++ b/src/dsl.cc @@ -162,7 +162,8 @@ public: #endif virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ); virtual sptr< Dictionary::DataRequest > getResource( string const & name ) @@ -1056,7 +1057,8 @@ void DslArticleRequest::run() } sptr< Dictionary::DataRequest > DslDictionary::getArticle( wstring const & word, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ) { return new DslArticleRequest( word, alts, *this ); diff --git a/src/hunspell.cc b/src/hunspell.cc index a8267b05..db88fdd6 100644 --- a/src/hunspell.cc +++ b/src/hunspell.cc @@ -65,7 +65,9 @@ public: virtual sptr< WordSearchRequest > findHeadwordsForSynonym( wstring const & ) 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 ); }; @@ -252,7 +254,9 @@ void HunspellArticleRequest::run() 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 ) { return new HunspellArticleRequest( word, hunspellMutex, hunspell ); diff --git a/src/lsa.cc b/src/lsa.cc index cb7ba12c..36794d46 100644 --- a/src/lsa.cc +++ b/src/lsa.cc @@ -173,7 +173,8 @@ public: { return QIcon(":/icons/playsound.png"); } virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ); 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, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ) { vector< WordArticleLink > chain = findArticles( word ); diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 6f95b9a2..62852520 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -530,11 +530,11 @@ ArticleView * MainWindow::createNewTab( bool switchToIt, connect( view, SIGNAL( pageLoaded( ArticleView * ) ), this, SLOT( pageLoaded( ArticleView * ) ) ); - connect( view, SIGNAL( openLinkInNewTab( QUrl const &, QUrl const &, QString const & ) ), - this, SLOT( 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 &, ArticleView::Contexts const & ) ) ); - connect( view, SIGNAL( showDefinitionInNewTab( QString const &, unsigned, QString const & ) ), - this, SLOT( 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 &, ArticleView::Contexts const & ) ) ); connect( view, SIGNAL( typingEvent( QString const & ) ), this, SLOT( typingEvent( QString const & ) ) ); @@ -943,18 +943,20 @@ void MainWindow::wordListSelectionChanged() void MainWindow::openLinkInNewTab( QUrl const & url, QUrl const & referrer, - QString const & fromArticle ) + QString const & fromArticle, + ArticleView::Contexts const & contexts ) { createNewTab( !cfg.preferences.newTabsOpenInBackground, "" )-> - openLink( url, referrer, fromArticle ); + openLink( url, referrer, fromArticle, contexts ); } void MainWindow::showDefinitionInNewTab( QString const & word, unsigned group, - QString const & fromArticle ) + QString const & fromArticle, + ArticleView::Contexts const & contexts ) { createNewTab( !cfg.preferences.newTabsOpenInBackground, word )-> - showDefinition( word, group, fromArticle ); + showDefinition( word, group, fromArticle, contexts ); } void MainWindow::typingEvent( QString const & t ) diff --git a/src/mainwindow.hh b/src/mainwindow.hh index 2f69175e..cbc7d845 100644 --- a/src/mainwindow.hh +++ b/src/mainwindow.hh @@ -177,9 +177,11 @@ private slots: ArticleView * createNewTab( bool switchToIt, 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, - QString const & fromArticle ); + QString const & fromArticle, + ArticleView::Contexts const & contexts ); void typingEvent( QString const & ); void showTranslationFor( QString const & ); diff --git a/src/mediawiki.cc b/src/mediawiki.cc index 98115817..27bdf205 100644 --- a/src/mediawiki.cc +++ b/src/mediawiki.cc @@ -51,7 +51,8 @@ public: virtual sptr< WordSearchRequest > prefixMatch( wstring const &, 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 ); }; @@ -341,7 +342,9 @@ sptr< WordSearchRequest > MediaWikiDictionary::prefixMatch( wstring const & word 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 ) { return new MediaWikiArticleRequest( word, alts, url, netMgr ); diff --git a/src/sounddir.cc b/src/sounddir.cc index 5ec28aac..9f9fbdb8 100644 --- a/src/sounddir.cc +++ b/src/sounddir.cc @@ -89,7 +89,8 @@ public: { return QIcon(":/icons/playsound.png"); } virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ); 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, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ) { vector< WordArticleLink > chain = findArticles( word ); diff --git a/src/stardict.cc b/src/stardict.cc index 8bd08f77..2904cc64 100644 --- a/src/stardict.cc +++ b/src/stardict.cc @@ -153,7 +153,8 @@ public: throw( std::exception ); virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ); private: @@ -732,7 +733,8 @@ void StardictArticleRequest::run() } sptr< Dictionary::DataRequest > StardictDictionary::getArticle( wstring const & word, - vector< wstring > const & alts ) + vector< wstring > const & alts, + wstring const & ) throw( std::exception ) { return new StardictArticleRequest( word, alts, *this ); diff --git a/src/transliteration.cc b/src/transliteration.cc index cbd0a1ea..81446837 100644 --- a/src/transliteration.cc +++ b/src/transliteration.cc @@ -47,7 +47,8 @@ sptr< Dictionary::WordSearchRequest > TransliterationDictionary::prefixMatch( ws { return new Dictionary::WordSearchRequestInstant(); } sptr< Dictionary::DataRequest > TransliterationDictionary::getArticle( wstring const &, - vector< wstring > const & ) + vector< wstring > const &, + wstring const & ) throw( std::exception ) { return new Dictionary::DataRequestInstant( false ); } diff --git a/src/transliteration.hh b/src/transliteration.hh index 833aef7a..44a7f769 100644 --- a/src/transliteration.hh +++ b/src/transliteration.hh @@ -69,7 +69,8 @@ public: unsigned long ) throw( std::exception ); virtual sptr< Dictionary::DataRequest > getArticle( wstring const &, - vector< wstring > const & ) + vector< wstring > const &, + wstring const & ) throw( std::exception ); }; diff --git a/src/website.cc b/src/website.cc index 0730673e..7e4c0d09 100644 --- a/src/website.cc +++ b/src/website.cc @@ -3,6 +3,7 @@ #include "website.hh" #include "wstring_qt.hh" +#include "utf8.hh" #include #include @@ -45,7 +46,9 @@ public: virtual sptr< WordSearchRequest > prefixMatch( wstring const & word, 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 ); }; @@ -59,18 +62,28 @@ sptr< WordSearchRequest > WebSiteDictionary::prefixMatch( wstring const & word, 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 ) { 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() ); - urlString.replace( "%25GD1251%25", QTextCodec::codecForName( "Windows-1251" )->fromUnicode( inputWord ).toPercentEncoding() ); - urlString.replace( "%25GDISO1%25", QTextCodec::codecForName( "ISO 8859-1" )->fromUnicode( inputWord ).toPercentEncoding() ); + QString inputWord = gd::toQString( str ); + + 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 = "
";