mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-30 13:24:05 +00:00
+ 'WebSites' implemented.
*! Don't set a global qt stylesheet - sometimes WebKit crashes with it. *! Fixes for text search feature (works faster, no selection artifacts, frame doesn't grow).
This commit is contained in:
parent
747825a505
commit
93fe5e5301
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1000,0">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
@ -43,6 +43,12 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="searchFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,6 +120,7 @@ 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.
|
||||
|
|
|
@ -114,7 +114,8 @@ HEADERS += folding.hh \
|
|||
transliteration.hh \
|
||||
romaji.hh \
|
||||
russiantranslit.hh \
|
||||
german.hh
|
||||
german.hh \
|
||||
website.hh
|
||||
FORMS += groups.ui \
|
||||
dictgroupwidget.ui \
|
||||
mainwindow.ui \
|
||||
|
@ -179,7 +180,8 @@ SOURCES += folding.cc \
|
|||
transliteration.cc \
|
||||
romaji.cc \
|
||||
russiantranslit.cc \
|
||||
german.cc
|
||||
german.cc \
|
||||
website.cc
|
||||
win32 {
|
||||
SOURCES += mouseover_win32/ThTypes.c
|
||||
HEADERS += mouseover_win32/ThTypes.h
|
||||
|
|
BIN
src/icons/internet.png
Normal file
BIN
src/icons/internet.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -14,6 +14,7 @@
|
|||
#include "romaji.hh"
|
||||
#include "russiantranslit.hh"
|
||||
#include "german.hh"
|
||||
#include "website.hh"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QDir>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() )
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -36,5 +36,6 @@
|
|||
<file>icons/bookcase.png</file>
|
||||
<file>qt-style-st-lingvo.css</file>
|
||||
<file>article-style-st-lingvo.css</file>
|
||||
<file>icons/internet.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
191
src/sources.cc
191
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 <b>%1</b> 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,
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -271,6 +271,69 @@ of the appropriate groups to use them.</string>
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/icons/internet.png</normaloff>:/icons/internet.png</iconset>
|
||||
</attribute>
|
||||
<attribute name="title">
|
||||
<string>Websites</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Any websites. A string %GDWORD% will be replaced with the query word:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QTreeView" name="webSites"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addWebSite">
|
||||
<property name="text">
|
||||
<string>&Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeWebSite">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Alternatively, use %GD1251% for CP1251, %GDISO1% for ISO 8859-1.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Transliteration</string>
|
||||
|
|
109
src/website.cc
Normal file
109
src/website.cc
Normal file
|
@ -0,0 +1,109 @@
|
|||
/* This file is (c) 2008-2009 Konstantin Isakov <ikm@users.berlios.de>
|
||||
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
||||
|
||||
#include "website.hh"
|
||||
#include "wstring_qt.hh"
|
||||
#include <QUrl>
|
||||
#include <QTextCodec>
|
||||
|
||||
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 = "<div class=\"website_padding\"></div>";
|
||||
|
||||
result += string( "<iframe id=\"gdexpandframe-" ) + getId() +
|
||||
"\" src=\"" + urlString.data() +
|
||||
"\" scrolling=\"no\" marginwidth=\"0\" marginheight=\"0\" "
|
||||
"frameborder=\"0\" vspace=\"0\" hspace=\"0\" "
|
||||
"style=\"overflow:visible; width:100%; display:none;\">"
|
||||
"</iframe>";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
21
src/website.hh
Normal file
21
src/website.hh
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* This file is (c) 2008-2009 Konstantin Isakov <ikm@users.berlios.de>
|
||||
* 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
|
Loading…
Reference in a new issue