diff --git a/src/article-style.css b/src/article-style.css index 99228b9f..8feb028d 100644 --- a/src/article-style.css +++ b/src/article-style.css @@ -323,6 +323,14 @@ div.sdct_x margin-top: 1em; } +/************* Websites *****************/ + +.website_padding +{ + height: 1em; + clear:both; +} + /************* MediaWiki articles ***************** The following consist of excerpts from different .css files edited with a .mwiki prepended to each record. diff --git a/src/articleview.cc b/src/articleview.cc index 15a7f98a..b317a907 100644 --- a/src/articleview.cc +++ b/src/articleview.cc @@ -174,6 +174,42 @@ void ArticleView::loadFinished( bool ) setCurrentArticle( url.fragment() ); } + // 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 ); + } + ui.definition->unsetCursor(); //QApplication::restoreOverrideCursor(); emit pageLoaded( this ); @@ -218,14 +254,14 @@ unsigned ArticleView::getGroup( QUrl const & url ) QStringList ArticleView::getArticlesList() { - return ui.definition->page()->currentFrame()-> + return ui.definition->page()->mainFrame()-> evaluateJavaScript( "gdArticleContents;" ).toString(). trimmed().split( ' ', QString::SkipEmptyParts ); } QString ArticleView::getCurrentArticle() { - QVariant v = ui.definition->page()->currentFrame()->evaluateJavaScript( + QVariant v = ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "gdCurrentArticle;" ) ); if ( v.type() == QVariant::String ) @@ -249,7 +285,7 @@ void ArticleView::setCurrentArticle( QString const & id, bool moveToIt ) } ui.definition->history()->currentItem().setUserData( id ); - ui.definition->page()->currentFrame()->evaluateJavaScript( + ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "gdMakeArticleActive( '%1' );" ).arg( id.mid( 7 ) ) ); } } @@ -316,7 +352,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref, { if ( url.hasFragment() ) { - ui.definition->page()->currentFrame()->evaluateJavaScript( + ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "window.location = \"%1\"" ).arg( QString::fromUtf8( url.toEncoded() ) ) ); } else @@ -440,13 +476,13 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref, bool ArticleView::hasSound() { - return ui.definition->page()->currentFrame()-> + return ui.definition->page()->mainFrame()-> evaluateJavaScript( "gdAudioLink;" ).type() == QVariant::String; } void ArticleView::playSound() { - QVariant v = ui.definition->page()->currentFrame()->evaluateJavaScript( + QVariant v = ui.definition->page()->mainFrame()->evaluateJavaScript( QString( "gdAudioLink;" ) ); if ( v.type() == QVariant::String ) @@ -455,12 +491,12 @@ void ArticleView::playSound() QString ArticleView::toHtml() { - return ui.definition->page()->currentFrame()->toHtml(); + return ui.definition->page()->mainFrame()->toHtml(); } QString ArticleView::getTitle() { - return ui.definition->page()->currentFrame()->title(); + return ui.definition->page()->mainFrame()->title(); } void ArticleView::print( QPrinter * printer ) const @@ -472,7 +508,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) { // Is that a link? Is there a selection? - QWebHitTestResult r = ui.definition->page()->currentFrame()-> + QWebHitTestResult r = ui.definition->page()->mainFrame()-> hitTestContent( pos ); QMenu menu( this ); @@ -803,14 +839,23 @@ void ArticleView::openSearch() // Clear any current selection if ( ui.definition->selectedText().size() ) { - ui.definition->triggerPageAction( QWebPage::SelectAll ); - ui.definition->triggerPageAction( QWebPage::SelectStartOfDocument ); + ui.definition->page()->currentFrame()-> + evaluateJavaScript( "window.getSelection().removeAllRanges();" ); } if ( ui.searchText->property( "noResults" ).toBool() ) { ui.searchText->setProperty( "noResults", false ); - qApp->setStyleSheet( qApp->styleSheet() ); + + // Reload stylesheet + for( QWidget * w = parentWidget(); w; w = w->parentWidget() ) + { + if ( w->styleSheet().size() ) + { + w->setStyleSheet( w->styleSheet() ); + break; + } + } } } @@ -849,8 +894,8 @@ void ArticleView::performFindOperation( bool restart, bool backwards ) // For now we resort to this hack: if ( ui.definition->selectedText().size() ) { - ui.definition->triggerPageAction( QWebPage::SelectAll ); - ui.definition->triggerPageAction( QWebPage::SelectStartOfDocument ); + ui.definition->page()->currentFrame()-> + evaluateJavaScript( "window.getSelection().removeAllRanges();" ); } } @@ -867,7 +912,16 @@ void ArticleView::performFindOperation( bool restart, bool backwards ) if ( ui.searchText->property( "noResults" ).toBool() != setMark ) { ui.searchText->setProperty( "noResults", setMark ); - qApp->setStyleSheet( qApp->styleSheet() ); + + // Reload stylesheet + for( QWidget * w = parentWidget(); w; w = w->parentWidget() ) + { + if ( w->styleSheet().size() ) + { + w->setStyleSheet( w->styleSheet() ); + break; + } + } } } diff --git a/src/articleview.ui b/src/articleview.ui index 2d54ecfc..f235bd42 100644 --- a/src/articleview.ui +++ b/src/articleview.ui @@ -13,7 +13,7 @@ Form - + 0 @@ -43,6 +43,12 @@ + + + 0 + 0 + + QFrame::NoFrame diff --git a/src/config.cc b/src/config.cc index 00b3e1db..d6923385 100644 --- a/src/config.cc +++ b/src/config.cc @@ -126,6 +126,18 @@ MediaWikis makeDefaultMediaWikis( bool enable ) return mw; } +WebSites makeDefaultWebSites() +{ + WebSites ws; + + ws.push_back( WebSite( "f376365a0de651fd7505e7e5e683aa45", "Urban Dictionary", "http://www.urbandictionary.com/define.php?term=%GDWORD%", false ) ); + ws.push_back( WebSite( "324ca0306187df7511b26d3847f4b07c", "Multitran (En)", "http://multitran.ru/c/m.exe?CL=1&l1=1&s=%GD1251%", false ) ); + ws.push_back( WebSite( "924db471b105299c82892067c0f10787", "Lingvo (En-Ru)", "http://www.abbyyonline.ru/translate.aspx?LingvoAction=translate&Ln=1&words=%GDWORD%", false ) ); + ws.push_back( WebSite( "087a6d65615fb047f4c80eef0a9465db", "Michaelis (Pt-En)", "http://michaelis.uol.com.br/moderno/ingles/index.php?lingua=portugues-ingles&palavra=%GDISO1%", false ) ); + + return ws; +} + /// Sets option to true of false if node is "1" or "0" respectively, or leaves /// it intact if it's neither "1" nor "0". void applyBoolOption( bool & option, QDomNode const & node ) @@ -225,6 +237,7 @@ Class load() throw( exError ) #endif c.mediawikis = makeDefaultMediaWikis( true ); + c.webSites = makeDefaultWebSites(); // Check if we have a template config file. If we do, load it instead @@ -392,6 +405,32 @@ Class load() throw( exError ) c.mediawikis = makeDefaultMediaWikis( false ); } + QDomNode wss = root.namedItem( "websites" ); + + if ( !wss.isNull() ) + { + QDomNodeList nl = wss.toElement().elementsByTagName( "website" ); + + for( unsigned x = 0; x < nl.length(); ++x ) + { + QDomElement ws = nl.item( x ).toElement(); + + WebSite w; + + w.id = ws.attribute( "id" ); + w.name = ws.attribute( "name" ); + w.url = ws.attribute( "url" ); + w.enabled = ( ws.attribute( "enabled" ) == "1" ); + + c.webSites.push_back( w ); + } + } + else + { + // Upgrading + c.webSites = makeDefaultWebSites(); + } + QDomNode preferences = root.namedItem( "preferences" ); if ( !preferences.isNull() ) @@ -695,6 +734,33 @@ void save( Class const & c ) throw( exError ) } } + { + QDomElement wss = dd.createElement( "websites" ); + root.appendChild( wss ); + + for( WebSites::const_iterator i = c.webSites.begin(); i != c.webSites.end(); ++i ) + { + QDomElement ws = dd.createElement( "website" ); + wss.appendChild( ws ); + + QDomAttr id = dd.createAttribute( "id" ); + id.setValue( i->id ); + ws.setAttributeNode( id ); + + QDomAttr name = dd.createAttribute( "name" ); + name.setValue( i->name ); + ws.setAttributeNode( name ); + + QDomAttr url = dd.createAttribute( "url" ); + url.setValue( i->url ); + ws.setAttributeNode( url ); + + QDomAttr enabled = dd.createAttribute( "enabled" ); + enabled.setValue( i->enabled ? "1" : "0" ); + ws.setAttributeNode( enabled ); + } + } + { QDomElement preferences = dd.createElement( "preferences" ); root.appendChild( preferences ); diff --git a/src/config.hh b/src/config.hh index ef926889..04364c34 100644 --- a/src/config.hh +++ b/src/config.hh @@ -180,6 +180,27 @@ struct MediaWiki enabled == other.enabled; } }; +/// Any website which can be queried though a simple template substitution +struct WebSite +{ + QString id, name, url; + bool enabled; + + WebSite(): enabled( false ) + {} + + WebSite( QString const & id_, QString const & name_, QString const & url_, + bool enabled_ ): + id( id_ ), name( name_ ), url( url_ ), enabled( enabled_ ) {} + + bool operator == ( WebSite const & other ) const + { return id == other.id && name == other.name && url == other.url && + enabled == other.enabled; } +}; + +/// All the WebSites +typedef vector< WebSite > WebSites; + /// Hunspell configuration struct Hunspell { @@ -256,6 +277,7 @@ struct Class Groups groups; Preferences preferences; MediaWikis mediawikis; + WebSites webSites; Hunspell hunspell; Transliteration transliteration; diff --git a/src/editdictionaries.cc b/src/editdictionaries.cc index ee398da7..0e79de0a 100644 --- a/src/editdictionaries.cc +++ b/src/editdictionaries.cc @@ -16,7 +16,7 @@ EditDictionaries::EditDictionaries( QWidget * parent, Config::Class & cfg_, dictNetMgr( dictNetMgr_ ), origCfg( cfg ), sources( this, cfg.paths, cfg.soundDirs, cfg.hunspell, cfg.transliteration, - cfg.mediawikis ), + cfg.mediawikis, cfg.webSites ), groups( new Groups( this, dictionaries, cfg.groups ) ), dictionariesChanged( false ), groupsChanged( false ), @@ -105,7 +105,8 @@ bool EditDictionaries::isSourcesChanged() const sources.getSoundDirs() != cfg.soundDirs || sources.getHunspell() != cfg.hunspell || sources.getTransliteration() != cfg.transliteration || - sources.getMediaWikis() != cfg.mediawikis; + sources.getMediaWikis() != cfg.mediawikis || + sources.getWebSites() != cfg.webSites; } void EditDictionaries::acceptChangedSources( bool rebuildGroups ) @@ -119,7 +120,8 @@ void EditDictionaries::acceptChangedSources( bool rebuildGroups ) cfg.hunspell = sources.getHunspell(); cfg.transliteration = sources.getTransliteration(); cfg.mediawikis = sources.getMediaWikis(); - + cfg.webSites = sources.getWebSites(); + groupInstances.clear(); // Those hold pointers to dictionaries, we need to // free them. diff --git a/src/goldendict.pro b/src/goldendict.pro index acec0289..500e6568 100644 --- a/src/goldendict.pro +++ b/src/goldendict.pro @@ -1,259 +1,261 @@ -# ##################################################################### -# Automatically generated by qmake (2.01a) ?? ????. 2 18:38:07 2008 -# ##################################################################### -TEMPLATE = app -TARGET = goldendict -VERSION = 0.8.0+svn - -# DEPENDPATH += . generators -INCLUDEPATH += . -QT += webkit -QT += xml -QT += network -CONFIG += exceptions \ - rtti \ - stl -OBJECTS_DIR = build -UI_DIR = build -MOC_DIR = build -RCC_DIR = build -LIBS += -lvorbisfile \ - -lvorbis \ - -logg \ - -lz \ - -lhunspell-1.2 -win32 { - LIBS += -liconv \ - -lwsock32 \ - -lwinmm \ - -lpsapi - RC_FILE = goldendict.rc - INCLUDEPATH += winlibs/include - LIBS += -Lwinlibs/lib -} -unix { - LIBS += -lXtst - PREFIX = $$(PREFIX) - isEmpty( PREFIX ):PREFIX = /usr/local - DEFINES += PROGRAM_DATA_DIR=\\\"$$PREFIX/share/apps/goldendict/\\\" - target.path = $$PREFIX/bin/ - locale.path = $$PREFIX/share/apps/goldendict/locale/ - locale.files = locale/*.qm - INSTALLS += target \ - locale - icons.path = /usr/share/pixmaps - icons.files = redist/icons/*.* - INSTALLS += icons - icons2.path = /usr/share/app-install/icons - icons2.files = redist/icons/*.* - INSTALLS += icons2 - desktops.path = /usr/share/applications - desktops.files = redist/*.desktop - INSTALLS += desktops - desktops2.path = /usr/share/app-install/desktop - desktops2.files = redist/*.desktop - INSTALLS += desktops2 -} -DEFINES += PROGRAM_VERSION=\\\"$$VERSION\\\" - -# Input -HEADERS += folding.hh \ - inc_case_folding.hh \ - inc_diacritic_folding.hh \ - mainwindow.hh \ - sptr.hh \ - dictionary.hh \ - ex.hh \ - config.hh \ - sources.hh \ - utf8.hh \ - file.hh \ - bgl_babylon.hh \ - bgl.hh \ - initializing.hh \ - article_netmgr.hh \ - dictzip.h \ - btreeidx.hh \ - stardict.hh \ - chunkedstorage.hh \ - xdxf2html.hh \ - iconv.hh \ - lsa.hh \ - htmlescape.hh \ - dsl.hh \ - dsl_details.hh \ - filetype.hh \ - fsencoding.hh \ - groups.hh \ - groups_widgets.hh \ - instances.hh \ - article_maker.hh \ - scanpopup.hh \ - articleview.hh \ - externalviewer.hh \ - wordfinder.hh \ - groupcombobox.hh \ - keyboardstate.hh \ - mouseover.hh \ - preferences.hh \ - mutex.hh \ - mediawiki.hh \ - sounddir.hh \ - hunspell.hh \ - dictdfiles.hh \ - audiolink.hh \ - wstring.hh \ - wstring_qt.hh \ - processwrapper.hh \ - hotkeywrapper.hh \ - searchpanewidget.hh \ - hotkeyedit.hh \ - langcoder.hh \ - editdictionaries.hh \ - loaddictionaries.hh \ - transliteration.hh \ - romaji.hh \ - russiantranslit.hh \ - german.hh -FORMS += groups.ui \ - dictgroupwidget.ui \ - mainwindow.ui \ - sources.ui \ - initializing.ui \ - groupselectorwidget.ui \ - scanpopup.ui \ - articleview.ui \ - preferences.ui \ - about.ui \ - editdictionaries.ui -SOURCES += folding.cc \ - main.cc \ - dictionary.cc \ - config.cc \ - sources.cc \ - mainwindow.cc \ - utf8.cc \ - file.cc \ - bgl_babylon.cc \ - bgl.cc \ - initializing.cc \ - article_netmgr.cc \ - dictzip.c \ - btreeidx.cc \ - stardict.cc \ - chunkedstorage.cc \ - xdxf2html.cc \ - iconv.cc \ - lsa.cc \ - htmlescape.cc \ - dsl.cc \ - dsl_details.cc \ - filetype.cc \ - fsencoding.cc \ - groups.cc \ - groups_widgets.cc \ - instances.cc \ - article_maker.cc \ - scanpopup.cc \ - articleview.cc \ - externalviewer.cc \ - wordfinder.cc \ - groupcombobox.cc \ - keyboardstate.cc \ - mouseover.cc \ - preferences.cc \ - mutex.cc \ - mediawiki.cc \ - sounddir.cc \ - hunspell.cc \ - dictdfiles.cc \ - audiolink.cc \ - wstring.cc \ - wstring_qt.cc \ - processwrapper.cc \ - hotkeywrapper.cc \ - hotkeyedit.cc \ - langcoder.cc \ - editdictionaries.cc \ - loaddictionaries.cc \ - transliteration.cc \ - romaji.cc \ - russiantranslit.cc \ - german.cc -win32 { - SOURCES += mouseover_win32/ThTypes.c - HEADERS += mouseover_win32/ThTypes.h -} -RESOURCES += resources.qrc \ - flags.qrc -TRANSLATIONS += locale/ru.ts - -# This makes qmake generate translations -isEmpty(QMAKE_LRELEASE):QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease -TS_OUT = $$TRANSLATIONS -TS_OUT ~= s/.ts/.qm -TSQM.name = lrelease \ - ${QMAKE_FILE_IN} -TSQM.input = TRANSLATIONS -TSQM.output = $$TS_OUT -TSQM.commands = $$QMAKE_LRELEASE \ - ${QMAKE_FILE_IN} -TSQM.CONFIG = no_link -QMAKE_EXTRA_COMPILERS += TSQM -PRE_TARGETDEPS += $$TS_OUT - -# LibZip -SOURCES += libzip/mkstemp.c \ - libzip/zip_add.c \ - libzip/zip_add_dir.c \ - libzip/zip_close.c \ - libzip/zip_delete.c \ - libzip/zip_dirent.c \ - libzip/zip_entry_free.c \ - libzip/zip_entry_new.c \ - libzip/zip_error.c \ - libzip/zip_error_clear.c \ - libzip/zip_error_get.c \ - libzip/zip_error_get_sys_type.c \ - libzip/zip_error_strerror.c \ - libzip/zip_error_to_str.c \ - libzip/zip_err_str.c \ - libzip/zip_fclose.c \ - libzip/zip_file_error_clear.c \ - libzip/zip_file_error_get.c \ - libzip/zip_file_get_offset.c \ - libzip/zip_filerange_crc.c \ - libzip/zip_file_strerror.c \ - libzip/zip_fopen.c \ - libzip/zip_fopen_index.c \ - libzip/zip_fread.c \ - libzip/zip_free.c \ - libzip/zip_get_archive_comment.c \ - libzip/zip_get_archive_flag.c \ - libzip/zip_get_file_comment.c \ - libzip/zip_get_name.c \ - libzip/zip_get_num_files.c \ - libzip/zip_memdup.c \ - libzip/zip_name_locate.c \ - libzip/zip_new.c \ - libzip/zip_open.c \ - libzip/zip_rename.c \ - libzip/zip_replace.c \ - libzip/zip_set_archive_comment.c \ - libzip/zip_set_archive_flag.c \ - libzip/zip_set_file_comment.c \ - libzip/zip_set_name.c \ - libzip/zip_source_buffer.c \ - libzip/zip_source_file.c \ - libzip/zip_source_filep.c \ - libzip/zip_source_free.c \ - libzip/zip_source_function.c \ - libzip/zip_source_zip.c \ - libzip/zip_stat.c \ - libzip/zip_stat_index.c \ - libzip/zip_stat_init.c \ - libzip/zip_strerror.c \ - libzip/zip_unchange_all.c \ - libzip/zip_unchange_archive.c \ - libzip/zip_unchange.c \ - libzip/zip_unchange_data.c +# ##################################################################### +# Automatically generated by qmake (2.01a) ?? ????. 2 18:38:07 2008 +# ##################################################################### +TEMPLATE = app +TARGET = goldendict +VERSION = 0.8.0+svn + +# DEPENDPATH += . generators +INCLUDEPATH += . +QT += webkit +QT += xml +QT += network +CONFIG += exceptions \ + rtti \ + stl +OBJECTS_DIR = build +UI_DIR = build +MOC_DIR = build +RCC_DIR = build +LIBS += -lvorbisfile \ + -lvorbis \ + -logg \ + -lz \ + -lhunspell-1.2 +win32 { + LIBS += -liconv \ + -lwsock32 \ + -lwinmm \ + -lpsapi + RC_FILE = goldendict.rc + INCLUDEPATH += winlibs/include + LIBS += -Lwinlibs/lib +} +unix { + LIBS += -lXtst + PREFIX = $$(PREFIX) + isEmpty( PREFIX ):PREFIX = /usr/local + DEFINES += PROGRAM_DATA_DIR=\\\"$$PREFIX/share/apps/goldendict/\\\" + target.path = $$PREFIX/bin/ + locale.path = $$PREFIX/share/apps/goldendict/locale/ + locale.files = locale/*.qm + INSTALLS += target \ + locale + icons.path = /usr/share/pixmaps + icons.files = redist/icons/*.* + INSTALLS += icons + icons2.path = /usr/share/app-install/icons + icons2.files = redist/icons/*.* + INSTALLS += icons2 + desktops.path = /usr/share/applications + desktops.files = redist/*.desktop + INSTALLS += desktops + desktops2.path = /usr/share/app-install/desktop + desktops2.files = redist/*.desktop + INSTALLS += desktops2 +} +DEFINES += PROGRAM_VERSION=\\\"$$VERSION\\\" + +# Input +HEADERS += folding.hh \ + inc_case_folding.hh \ + inc_diacritic_folding.hh \ + mainwindow.hh \ + sptr.hh \ + dictionary.hh \ + ex.hh \ + config.hh \ + sources.hh \ + utf8.hh \ + file.hh \ + bgl_babylon.hh \ + bgl.hh \ + initializing.hh \ + article_netmgr.hh \ + dictzip.h \ + btreeidx.hh \ + stardict.hh \ + chunkedstorage.hh \ + xdxf2html.hh \ + iconv.hh \ + lsa.hh \ + htmlescape.hh \ + dsl.hh \ + dsl_details.hh \ + filetype.hh \ + fsencoding.hh \ + groups.hh \ + groups_widgets.hh \ + instances.hh \ + article_maker.hh \ + scanpopup.hh \ + articleview.hh \ + externalviewer.hh \ + wordfinder.hh \ + groupcombobox.hh \ + keyboardstate.hh \ + mouseover.hh \ + preferences.hh \ + mutex.hh \ + mediawiki.hh \ + sounddir.hh \ + hunspell.hh \ + dictdfiles.hh \ + audiolink.hh \ + wstring.hh \ + wstring_qt.hh \ + processwrapper.hh \ + hotkeywrapper.hh \ + searchpanewidget.hh \ + hotkeyedit.hh \ + langcoder.hh \ + editdictionaries.hh \ + loaddictionaries.hh \ + transliteration.hh \ + romaji.hh \ + russiantranslit.hh \ + german.hh \ + website.hh +FORMS += groups.ui \ + dictgroupwidget.ui \ + mainwindow.ui \ + sources.ui \ + initializing.ui \ + groupselectorwidget.ui \ + scanpopup.ui \ + articleview.ui \ + preferences.ui \ + about.ui \ + editdictionaries.ui +SOURCES += folding.cc \ + main.cc \ + dictionary.cc \ + config.cc \ + sources.cc \ + mainwindow.cc \ + utf8.cc \ + file.cc \ + bgl_babylon.cc \ + bgl.cc \ + initializing.cc \ + article_netmgr.cc \ + dictzip.c \ + btreeidx.cc \ + stardict.cc \ + chunkedstorage.cc \ + xdxf2html.cc \ + iconv.cc \ + lsa.cc \ + htmlescape.cc \ + dsl.cc \ + dsl_details.cc \ + filetype.cc \ + fsencoding.cc \ + groups.cc \ + groups_widgets.cc \ + instances.cc \ + article_maker.cc \ + scanpopup.cc \ + articleview.cc \ + externalviewer.cc \ + wordfinder.cc \ + groupcombobox.cc \ + keyboardstate.cc \ + mouseover.cc \ + preferences.cc \ + mutex.cc \ + mediawiki.cc \ + sounddir.cc \ + hunspell.cc \ + dictdfiles.cc \ + audiolink.cc \ + wstring.cc \ + wstring_qt.cc \ + processwrapper.cc \ + hotkeywrapper.cc \ + hotkeyedit.cc \ + langcoder.cc \ + editdictionaries.cc \ + loaddictionaries.cc \ + transliteration.cc \ + romaji.cc \ + russiantranslit.cc \ + german.cc \ + website.cc +win32 { + SOURCES += mouseover_win32/ThTypes.c + HEADERS += mouseover_win32/ThTypes.h +} +RESOURCES += resources.qrc \ + flags.qrc +TRANSLATIONS += locale/ru.ts + +# This makes qmake generate translations +isEmpty(QMAKE_LRELEASE):QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease +TS_OUT = $$TRANSLATIONS +TS_OUT ~= s/.ts/.qm +TSQM.name = lrelease \ + ${QMAKE_FILE_IN} +TSQM.input = TRANSLATIONS +TSQM.output = $$TS_OUT +TSQM.commands = $$QMAKE_LRELEASE \ + ${QMAKE_FILE_IN} +TSQM.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += TSQM +PRE_TARGETDEPS += $$TS_OUT + +# LibZip +SOURCES += libzip/mkstemp.c \ + libzip/zip_add.c \ + libzip/zip_add_dir.c \ + libzip/zip_close.c \ + libzip/zip_delete.c \ + libzip/zip_dirent.c \ + libzip/zip_entry_free.c \ + libzip/zip_entry_new.c \ + libzip/zip_error.c \ + libzip/zip_error_clear.c \ + libzip/zip_error_get.c \ + libzip/zip_error_get_sys_type.c \ + libzip/zip_error_strerror.c \ + libzip/zip_error_to_str.c \ + libzip/zip_err_str.c \ + libzip/zip_fclose.c \ + libzip/zip_file_error_clear.c \ + libzip/zip_file_error_get.c \ + libzip/zip_file_get_offset.c \ + libzip/zip_filerange_crc.c \ + libzip/zip_file_strerror.c \ + libzip/zip_fopen.c \ + libzip/zip_fopen_index.c \ + libzip/zip_fread.c \ + libzip/zip_free.c \ + libzip/zip_get_archive_comment.c \ + libzip/zip_get_archive_flag.c \ + libzip/zip_get_file_comment.c \ + libzip/zip_get_name.c \ + libzip/zip_get_num_files.c \ + libzip/zip_memdup.c \ + libzip/zip_name_locate.c \ + libzip/zip_new.c \ + libzip/zip_open.c \ + libzip/zip_rename.c \ + libzip/zip_replace.c \ + libzip/zip_set_archive_comment.c \ + libzip/zip_set_archive_flag.c \ + libzip/zip_set_file_comment.c \ + libzip/zip_set_name.c \ + libzip/zip_source_buffer.c \ + libzip/zip_source_file.c \ + libzip/zip_source_filep.c \ + libzip/zip_source_free.c \ + libzip/zip_source_function.c \ + libzip/zip_source_zip.c \ + libzip/zip_stat.c \ + libzip/zip_stat_index.c \ + libzip/zip_stat_init.c \ + libzip/zip_strerror.c \ + libzip/zip_unchange_all.c \ + libzip/zip_unchange_archive.c \ + libzip/zip_unchange.c \ + libzip/zip_unchange_data.c diff --git a/src/icons/internet.png b/src/icons/internet.png new file mode 100644 index 00000000..4ddadd60 Binary files /dev/null and b/src/icons/internet.png differ diff --git a/src/loaddictionaries.cc b/src/loaddictionaries.cc index 0f51a185..99516688 100644 --- a/src/loaddictionaries.cc +++ b/src/loaddictionaries.cc @@ -14,6 +14,7 @@ #include "romaji.hh" #include "russiantranslit.hh" #include "german.hh" +#include "website.hh" #include #include @@ -191,6 +192,14 @@ void loadDictionaries( QWidget * parent, bool showInitially, dictionaries.insert( dictionaries.end(), dicts.begin(), dicts.end() ); } + ///// WebSites are very simple, no need to create them asyncronously + { + vector< sptr< Dictionary::Class > > dicts = + WebSite::makeDictionaries( cfg.webSites ); + + dictionaries.insert( dictionaries.end(), dicts.begin(), dicts.end() ); + } + // Remove any stale index files set< string > ids; diff --git a/src/main.cc b/src/main.cc index 9ebb2f35..68ad3940 100644 --- a/src/main.cc +++ b/src/main.cc @@ -97,9 +97,6 @@ int main( int argc, char ** argv ) translator.load( QString( Config::getProgramDataDir() ) + "/locale/" + localeName ); app.installTranslator( &translator ); - // Apply qt stylesheet - MainWindow::applyQtStyleSheet( cfg.preferences.displayStyle ); - MainWindow m( cfg ); int r = app.exec(); diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 072e70c8..bbdf7574 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -39,6 +39,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ): wordFinder( this ), newReleaseCheckTimer( this ) { + applyQtStyleSheet( cfg.preferences.displayStyle ); + ui.setupUi( this ); // Make the search pane's titlebar @@ -299,7 +301,7 @@ void MainWindow::applyQtStyleSheet( QString const & displayStyle ) if ( cssFile.open( QFile::ReadOnly ) ) css += cssFile.readAll(); - qApp->setStyleSheet( css ); + setStyleSheet( css ); } void MainWindow::updateTrayIcon() @@ -458,6 +460,8 @@ void MainWindow::makeScanPopup() scanPopup = new ScanPopup( 0, cfg, articleNetMgr, dictionaries, groupInstances ); + scanPopup->setStyleSheet( styleSheet() ); + if ( cfg.preferences.enableScanPopup && enableScanPopup->isChecked() ) scanPopup->enableScanning(); } @@ -719,7 +723,7 @@ void MainWindow::translateInputChanged( QString const & newValue ) if ( ui.translateLine->property( "noResults" ).toBool() ) { ui.translateLine->setProperty( "noResults", false ); - qApp->setStyleSheet( qApp->styleSheet() ); + setStyleSheet( styleSheet() ); } return; } @@ -836,7 +840,7 @@ void MainWindow::updateMatchResults( bool finished ) if ( ui.translateLine->property( "noResults" ).toBool() != setMark ) { ui.translateLine->setProperty( "noResults", setMark ); - qApp->setStyleSheet( qApp->styleSheet() ); + setStyleSheet( styleSheet() ); } if ( !wordFinder.getErrorString().isEmpty() ) diff --git a/src/mainwindow.hh b/src/mainwindow.hh index b700895f..2f69175e 100644 --- a/src/mainwindow.hh +++ b/src/mainwindow.hh @@ -33,9 +33,6 @@ public: MainWindow( Config::Class & cfg ); ~MainWindow(); - /// Applies the qt's stylesheet, given the style's name. - static void applyQtStyleSheet( QString const & displayStyle ); - private: QSystemTrayIcon * trayIcon; @@ -77,6 +74,9 @@ private: QPrinter printer; // The printer we use for all printing operations + /// Applies the qt's stylesheet, given the style's name. + void applyQtStyleSheet( QString const & displayStyle ); + /// Creates, destroys or otherwise updates tray icon, according to the /// current configuration and situation. void updateTrayIcon(); diff --git a/src/resources.qrc b/src/resources.qrc index 0163770b..550030ba 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -36,5 +36,6 @@ icons/bookcase.png qt-style-st-lingvo.css article-style-st-lingvo.css + icons/internet.png diff --git a/src/sources.cc b/src/sources.cc index 5a7c8546..391742b6 100644 --- a/src/sources.cc +++ b/src/sources.cc @@ -11,8 +11,11 @@ Sources::Sources( QWidget * parent, Config::Paths const & paths, Config::SoundDirs const & soundDirs, Config::Hunspell const & hunspell, Config::Transliteration const & tr, - Config::MediaWikis const & mediawikis ): QWidget( parent ), - mediawikisModel( this, mediawikis ), pathsModel( this, paths ), + Config::MediaWikis const & mediawikis, + Config::WebSites const & webSites ): QWidget( parent ), + mediawikisModel( this, mediawikis ), + webSitesModel( this, webSites ), + pathsModel( this, paths ), soundDirsModel( this, soundDirs ), hunspellDictsModel( this, hunspell ) { @@ -24,6 +27,12 @@ Sources::Sources( QWidget * parent, Config::Paths const & paths, ui.mediaWikis->resizeColumnToContents( 1 ); ui.mediaWikis->resizeColumnToContents( 2 ); + ui.webSites->setTabKeyNavigation( true ); + ui.webSites->setModel( &webSitesModel ); + ui.webSites->resizeColumnToContents( 0 ); + ui.webSites->resizeColumnToContents( 1 ); + ui.webSites->resizeColumnToContents( 2 ); + ui.paths->setTabKeyNavigation( true ); ui.paths->setModel( &pathsModel ); @@ -159,6 +168,30 @@ void Sources::on_removeMediaWiki_clicked() mediawikisModel.removeWiki( current.row() ); } +void Sources::on_addWebSite_clicked() +{ + webSitesModel.addNewSite(); + + QModelIndex result = + webSitesModel.index( webSitesModel.rowCount( QModelIndex() ) - 1, + 1, QModelIndex() ); + + ui.webSites->scrollTo( result ); + ui.webSites->edit( result ); +} + +void Sources::on_removeWebSite_clicked() +{ + QModelIndex current = ui.webSites->currentIndex(); + + if ( current.isValid() && + QMessageBox::question( this, tr( "Confirm removal" ), + tr( "Remove site %1 from the list?" ).arg( webSitesModel.getCurrentWebSites()[ current.row() ].name ), + QMessageBox::Ok, + QMessageBox::Cancel ) == QMessageBox::Ok ) + webSitesModel.removeSite( current.row() ); +} + Config::Hunspell Sources::getHunspell() const { Config::Hunspell h; @@ -337,6 +370,160 @@ bool MediaWikisModel::setData( QModelIndex const & index, const QVariant & value return false; } + +////////// WebSitesModel + +WebSitesModel::WebSitesModel( QWidget * parent, + Config::WebSites const & webSites_ ): + QAbstractItemModel( parent ), webSites( webSites_ ) +{ +} +void WebSitesModel::removeSite( int index ) +{ + beginRemoveRows( QModelIndex(), index, index ); + webSites.erase( webSites.begin() + index ); + endRemoveRows(); +} + +void WebSitesModel::addNewSite() +{ + Config::WebSite w; + + w.enabled = false; + + // That's quite some rng + w.id = QString( + QCryptographicHash::hash( + QDateTime::currentDateTime().toString( "\"WebSite\"dd.MM.yyyy hh:mm:ss.zzz" ).toUtf8(), + QCryptographicHash::Md5 ).toHex() ); + + w.url = "http://"; + + beginInsertRows( QModelIndex(), webSites.size(), webSites.size() ); + webSites.push_back( w ); + endInsertRows(); +} + +QModelIndex WebSitesModel::index( int row, int column, QModelIndex const & /*parent*/ ) const +{ + return createIndex( row, column, 0 ); +} + +QModelIndex WebSitesModel::parent( QModelIndex const & /*parent*/ ) const +{ + return QModelIndex(); +} + +Qt::ItemFlags WebSitesModel::flags( QModelIndex const & index ) const +{ + Qt::ItemFlags result = QAbstractItemModel::flags( index ); + + if ( index.isValid() ) + { + if ( !index.column() ) + result |= Qt::ItemIsUserCheckable; + else + result |= Qt::ItemIsEditable; + } + + return result; +} + +int WebSitesModel::rowCount( QModelIndex const & parent ) const +{ + if ( parent.isValid() ) + return 0; + else + return webSites.size(); +} + +int WebSitesModel::columnCount( QModelIndex const & parent ) const +{ + if ( parent.isValid() ) + return 0; + else + return 3; +} + +QVariant WebSitesModel::headerData( int section, Qt::Orientation /*orientation*/, int role ) const +{ + if ( role == Qt::DisplayRole ) + switch( section ) + { + case 0: + return tr( "Enabled" ); + case 1: + return tr( "Name" ); + case 2: + return tr( "Address" ); + default: + return QVariant(); + } + + return QVariant(); +} + +QVariant WebSitesModel::data( QModelIndex const & index, int role ) const +{ + if ( (unsigned)index.row() >= webSites.size() ) + return QVariant(); + + if ( role == Qt::DisplayRole || role == Qt::EditRole ) + { + switch( index.column() ) + { + case 1: + return webSites[ index.row() ].name; + case 2: + return webSites[ index.row() ].url; + default: + return QVariant(); + } + } + + if ( role == Qt::CheckStateRole && !index.column() ) + return webSites[ index.row() ].enabled; + + return QVariant(); +} + +bool WebSitesModel::setData( QModelIndex const & index, const QVariant & value, + int role ) +{ + if ( (unsigned)index.row() >= webSites.size() ) + return false; + + if ( role == Qt::CheckStateRole && !index.column() ) + { + //printf( "type = %d\n", (int)value.type() ); + //printf( "value = %d\n", (int)value.toInt() ); + + // XXX it seems to be always passing Int( 2 ) as a value, so we just toggle + webSites[ index.row() ].enabled = !webSites[ index.row() ].enabled; + + dataChanged( index, index ); + return true; + } + + if ( role == Qt::DisplayRole || role == Qt::EditRole ) + switch( index.column() ) + { + case 1: + webSites[ index.row() ].name = value.toString(); + dataChanged( index, index ); + return true; + case 2: + webSites[ index.row() ].url = value.toString(); + dataChanged( index, index ); + return true; + default: + return false; + } + + return false; +} + + ////////// PathsModel PathsModel::PathsModel( QWidget * parent, diff --git a/src/sources.hh b/src/sources.hh index 3b927e93..98e78a76 100644 --- a/src/sources.hh +++ b/src/sources.hh @@ -39,6 +39,36 @@ private: Config::MediaWikis mediawikis; }; +/// A model to be projected into the webSites view, according to Qt's MVC model +class WebSitesModel: public QAbstractItemModel +{ + Q_OBJECT + +public: + + WebSitesModel( QWidget * parent, Config::WebSites const & ); + + void removeSite( int index ); + void addNewSite(); + + /// Returns the sites the model currently has listed + Config::WebSites const & getCurrentWebSites() const + { return webSites; } + + QModelIndex index( int row, int column, QModelIndex const & parent ) const; + QModelIndex parent( QModelIndex const & parent ) const; + Qt::ItemFlags flags( QModelIndex const & index ) const; + int rowCount( QModelIndex const & parent ) const; + int columnCount( QModelIndex const & parent ) const; + QVariant headerData( int section, Qt::Orientation orientation, int role ) const; + QVariant data( QModelIndex const & index, int role ) const; + bool setData( QModelIndex const & index, const QVariant & value, int role ); + +private: + + Config::WebSites webSites; +}; + /// A model to be projected into the paths view, according to Qt's MVC model class PathsModel: public QAbstractItemModel { @@ -139,7 +169,8 @@ public: Config::SoundDirs const &, Config::Hunspell const &, Config::Transliteration const &, - Config::MediaWikis const & ); + Config::MediaWikis const &, + Config::WebSites const & ); Config::Paths const & getPaths() const { return pathsModel.getCurrentPaths(); } @@ -150,6 +181,9 @@ public: Config::MediaWikis const & getMediaWikis() const { return mediawikisModel.getCurrentWikis(); } + Config::WebSites const & getWebSites() const + { return webSitesModel.getCurrentWebSites(); } + Config::Hunspell getHunspell() const; Config::Transliteration getTransliteration() const; @@ -162,6 +196,7 @@ signals: private: Ui::Sources ui; MediaWikisModel mediawikisModel; + WebSitesModel webSitesModel; PathsModel pathsModel; SoundDirsModel soundDirsModel; HunspellDictsModel hunspellDictsModel; @@ -183,6 +218,9 @@ private slots: void on_addMediaWiki_clicked(); void on_removeMediaWiki_clicked(); + void on_addWebSite_clicked(); + void on_removeWebSite_clicked(); + void on_rescan_clicked(); }; diff --git a/src/sources.ui b/src/sources.ui index 6b938304..c2e61d72 100644 --- a/src/sources.ui +++ b/src/sources.ui @@ -1,464 +1,527 @@ - - - Sources - - - - 0 - 0 - 578 - 336 - - - - Sources - - - - - - 0 - - - - 15 - 15 - - - - - - :/icons/filesave.png:/icons/filesave.png - - - Files - - - - - - Paths to search for the dictionary files: - - - - - - - - - - - - - - &Add... - - - - - - - &Remove - - - - - - - Qt::Vertical - - - - 17 - 68 - - - - - - - - Re&scan now - - - - - - - - - - - - - :/icons/fileopen.png:/icons/fileopen.png - - - Sound Dirs - - - - - - Make dictionaries from bunches of audiofiles by adding paths here: - - - - - - - - - - - - - - &Add... - - - - - - - &Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - :/icons/icon32_hunspell.png:/icons/icon32_hunspell.png - - - Morphology - - - - - - Path to a directory with Hunspell/Myspell dictionaries: - - - - - - - - - true - - - - - - - &Change... - - - - - - - - - Available morphology dictionaries: - - - - - - - - - - - - Each morphology dictionary appears as a -separate auxiliary dictionary which -provides stem words for searches and -spelling suggestions for mistyped words. -Add appropriate dictionaries to the bottoms -of the appropriate groups to use them. - - - Qt::PlainText - - - false - - - - - - - - - - - :/icons/icon32_wiki.png:/icons/icon32_wiki.png - - - Wikipedia - - - - - - Wikipedia (MediaWiki) sites: - - - - - - - - - - - - - - &Add... - - - - - - - &Remove - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - - - - - - - - - - Transliteration - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Russian transliteration - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - German transliteration - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Enables to use the Latin alphabet to write the Japanese language - - - Japanese Romaji - - - true - - - true - - - - - - Systems: - - - - - - - The most widely used method of transcription of Japanese, -based on English phonology - - - Hepburn - - - - - - - The most regular system, having a one-to-one relation to the -kana writing systems. Standardized as ISO 3602 - - - Nihon-shiki - - - - - - - Based on Nihon-shiki system, but modified for modern standard Japanese. -Standardized as ISO 3602 - - - Kunrei-shiki - - - - - - - Syllabaries: - - - - - - - Hiragana Japanese syllabary - - - Hiragana - - - - - - - Hiragana Japanese syllabary - - - Katakana - - - - - - - - - - Qt::Vertical - - - - 20 - 80 - - - - - - - - - - - - enableRussianTransliteration - enableGermanTransliteration - enableRomaji - enableHepburn - enableNihonShiki - enableKunreiShiki - enableHiragana - enableKatakana - hunspellPath - changeHunspellPath - hunspellDictionaries - mediaWikis - addMediaWiki - removeMediaWiki - tabWidget - addPath - removePath - rescan - soundDirs - addSoundDir - removeSoundDir - paths - - - - - - + + + Sources + + + + 0 + 0 + 578 + 336 + + + + Sources + + + + + + 0 + + + + 15 + 15 + + + + + + :/icons/filesave.png:/icons/filesave.png + + + Files + + + + + + Paths to search for the dictionary files: + + + + + + + + + + + + + + &Add... + + + + + + + &Remove + + + + + + + Qt::Vertical + + + + 17 + 68 + + + + + + + + Re&scan now + + + + + + + + + + + + + :/icons/fileopen.png:/icons/fileopen.png + + + Sound Dirs + + + + + + Make dictionaries from bunches of audiofiles by adding paths here: + + + + + + + + + + + + + + &Add... + + + + + + + &Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + :/icons/icon32_hunspell.png:/icons/icon32_hunspell.png + + + Morphology + + + + + + Path to a directory with Hunspell/Myspell dictionaries: + + + + + + + + + true + + + + + + + &Change... + + + + + + + + + Available morphology dictionaries: + + + + + + + + + + + + Each morphology dictionary appears as a +separate auxiliary dictionary which +provides stem words for searches and +spelling suggestions for mistyped words. +Add appropriate dictionaries to the bottoms +of the appropriate groups to use them. + + + Qt::PlainText + + + false + + + + + + + + + + + :/icons/icon32_wiki.png:/icons/icon32_wiki.png + + + Wikipedia + + + + + + Wikipedia (MediaWiki) sites: + + + + + + + + + + + + + + &Add... + + + + + + + &Remove + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + + + + + + + :/icons/internet.png:/icons/internet.png + + + Websites + + + + + + Any websites. A string %GDWORD% will be replaced with the query word: + + + + + + + + + + + + + + &Add... + + + + + + + &Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Alternatively, use %GD1251% for CP1251, %GDISO1% for ISO 8859-1. + + + + + + + + Transliteration + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Russian transliteration + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + German transliteration + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Enables to use the Latin alphabet to write the Japanese language + + + Japanese Romaji + + + true + + + true + + + + + + Systems: + + + + + + + The most widely used method of transcription of Japanese, +based on English phonology + + + Hepburn + + + + + + + The most regular system, having a one-to-one relation to the +kana writing systems. Standardized as ISO 3602 + + + Nihon-shiki + + + + + + + Based on Nihon-shiki system, but modified for modern standard Japanese. +Standardized as ISO 3602 + + + Kunrei-shiki + + + + + + + Syllabaries: + + + + + + + Hiragana Japanese syllabary + + + Hiragana + + + + + + + Hiragana Japanese syllabary + + + Katakana + + + + + + + + + + Qt::Vertical + + + + 20 + 80 + + + + + + + + + + + + enableRussianTransliteration + enableGermanTransliteration + enableRomaji + enableHepburn + enableNihonShiki + enableKunreiShiki + enableHiragana + enableKatakana + hunspellPath + changeHunspellPath + hunspellDictionaries + mediaWikis + addMediaWiki + removeMediaWiki + tabWidget + addPath + removePath + rescan + soundDirs + addSoundDir + removeSoundDir + paths + + + + + + diff --git a/src/website.cc b/src/website.cc new file mode 100644 index 00000000..0730673e --- /dev/null +++ b/src/website.cc @@ -0,0 +1,109 @@ +/* This file is (c) 2008-2009 Konstantin Isakov + * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */ + +#include "website.hh" +#include "wstring_qt.hh" +#include +#include + +namespace WebSite { + +using namespace Dictionary; + +namespace { + +class WebSiteDictionary: public Dictionary::Class +{ + string name; + QByteArray urlTemplate; + +public: + + WebSiteDictionary( string const & id, string const & name_, + QString const & urlTemplate_ ): + Dictionary::Class( id, vector< string >() ), + name( name_ ), + urlTemplate( QUrl( urlTemplate_ ).toEncoded() ) + { + } + + virtual string getName() throw() + { return name; } + + virtual map< Property, string > getProperties() throw() + { return map< Property, string >(); } + + virtual unsigned long getArticleCount() throw() + { return 0; } + + virtual unsigned long getWordCount() throw() + { return 0; } + + virtual QIcon getIcon() throw() + { return QIcon(":/icons/internet.png"); } + + virtual sptr< WordSearchRequest > prefixMatch( wstring const & word, + unsigned long ) throw( std::exception ); + + virtual sptr< DataRequest > getArticle( wstring const &, vector< wstring > const & alts ) + throw( std::exception ); +}; + +sptr< WordSearchRequest > WebSiteDictionary::prefixMatch( wstring const & word, + unsigned long ) throw( std::exception ) +{ + sptr< WordSearchRequestInstant > sr = new WordSearchRequestInstant; + + sr->getMatches().push_back( WordMatch( word, 1 ) ); + + return sr; +} + +sptr< DataRequest > WebSiteDictionary::getArticle( wstring const & str, vector< wstring > const & ) + throw( std::exception ) +{ + sptr< DataRequestInstant > dr = new DataRequestInstant( true ); + + QByteArray urlString( urlTemplate ); + + 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 = "
"; + + result += string( ""; + + dr->getData().resize( result.size() ); + + memcpy( &( dr->getData().front() ), result.data(), result.size() ); + + return dr; +} + +} + +vector< sptr< Dictionary::Class > > makeDictionaries( Config::WebSites const & ws ) + throw( std::exception ) +{ + vector< sptr< Dictionary::Class > > result; + + for( unsigned x = 0; x < ws.size(); ++x ) + { + if ( ws[ x ].enabled ) + result.push_back( new WebSiteDictionary( ws[ x ].id.toUtf8().data(), + ws[ x ].name.toUtf8().data(), + ws[ x ].url ) ); + } + + return result; +} + +} diff --git a/src/website.hh b/src/website.hh new file mode 100644 index 00000000..bb0cee24 --- /dev/null +++ b/src/website.hh @@ -0,0 +1,21 @@ +/* This file is (c) 2008-2009 Konstantin Isakov + * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */ + +#ifndef __WEBSITE_HH_INCLUDED__ +#define __WEBSITE_HH_INCLUDED__ + +#include "dictionary.hh" +#include "config.hh" + +/// Support for any web sites via a templated url. +namespace WebSite { + +using std::vector; +using std::string; + +vector< sptr< Dictionary::Class > > makeDictionaries( Config::WebSites const & ) + throw( std::exception ); + +} + +#endif