+ '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:
Konstantin Isakov 2009-05-16 18:04:21 +00:00
parent 747825a505
commit 93fe5e5301
18 changed files with 1343 additions and 754 deletions

View file

@ -323,6 +323,14 @@ div.sdct_x
margin-top: 1em; margin-top: 1em;
} }
/************* Websites *****************/
.website_padding
{
height: 1em;
clear:both;
}
/************* MediaWiki articles ***************** /************* MediaWiki articles *****************
The following consist of excerpts from different .css files edited The following consist of excerpts from different .css files edited
with a .mwiki prepended to each record. with a .mwiki prepended to each record.

View file

@ -174,6 +174,42 @@ void ArticleView::loadFinished( bool )
setCurrentArticle( url.fragment() ); 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(); ui.definition->unsetCursor();
//QApplication::restoreOverrideCursor(); //QApplication::restoreOverrideCursor();
emit pageLoaded( this ); emit pageLoaded( this );
@ -218,14 +254,14 @@ unsigned ArticleView::getGroup( QUrl const & url )
QStringList ArticleView::getArticlesList() QStringList ArticleView::getArticlesList()
{ {
return ui.definition->page()->currentFrame()-> return ui.definition->page()->mainFrame()->
evaluateJavaScript( "gdArticleContents;" ).toString(). evaluateJavaScript( "gdArticleContents;" ).toString().
trimmed().split( ' ', QString::SkipEmptyParts ); trimmed().split( ' ', QString::SkipEmptyParts );
} }
QString ArticleView::getCurrentArticle() QString ArticleView::getCurrentArticle()
{ {
QVariant v = ui.definition->page()->currentFrame()->evaluateJavaScript( QVariant v = ui.definition->page()->mainFrame()->evaluateJavaScript(
QString( "gdCurrentArticle;" ) ); QString( "gdCurrentArticle;" ) );
if ( v.type() == QVariant::String ) 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->history()->currentItem().setUserData( id );
ui.definition->page()->currentFrame()->evaluateJavaScript( ui.definition->page()->mainFrame()->evaluateJavaScript(
QString( "gdMakeArticleActive( '%1' );" ).arg( id.mid( 7 ) ) ); QString( "gdMakeArticleActive( '%1' );" ).arg( id.mid( 7 ) ) );
} }
} }
@ -316,7 +352,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
{ {
if ( url.hasFragment() ) if ( url.hasFragment() )
{ {
ui.definition->page()->currentFrame()->evaluateJavaScript( ui.definition->page()->mainFrame()->evaluateJavaScript(
QString( "window.location = \"%1\"" ).arg( QString::fromUtf8( url.toEncoded() ) ) ); QString( "window.location = \"%1\"" ).arg( QString::fromUtf8( url.toEncoded() ) ) );
} }
else else
@ -440,13 +476,13 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
bool ArticleView::hasSound() bool ArticleView::hasSound()
{ {
return ui.definition->page()->currentFrame()-> return ui.definition->page()->mainFrame()->
evaluateJavaScript( "gdAudioLink;" ).type() == QVariant::String; evaluateJavaScript( "gdAudioLink;" ).type() == QVariant::String;
} }
void ArticleView::playSound() void ArticleView::playSound()
{ {
QVariant v = ui.definition->page()->currentFrame()->evaluateJavaScript( QVariant v = ui.definition->page()->mainFrame()->evaluateJavaScript(
QString( "gdAudioLink;" ) ); QString( "gdAudioLink;" ) );
if ( v.type() == QVariant::String ) if ( v.type() == QVariant::String )
@ -455,12 +491,12 @@ void ArticleView::playSound()
QString ArticleView::toHtml() QString ArticleView::toHtml()
{ {
return ui.definition->page()->currentFrame()->toHtml(); return ui.definition->page()->mainFrame()->toHtml();
} }
QString ArticleView::getTitle() QString ArticleView::getTitle()
{ {
return ui.definition->page()->currentFrame()->title(); return ui.definition->page()->mainFrame()->title();
} }
void ArticleView::print( QPrinter * printer ) const void ArticleView::print( QPrinter * printer ) const
@ -472,7 +508,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos )
{ {
// Is that a link? Is there a selection? // Is that a link? Is there a selection?
QWebHitTestResult r = ui.definition->page()->currentFrame()-> QWebHitTestResult r = ui.definition->page()->mainFrame()->
hitTestContent( pos ); hitTestContent( pos );
QMenu menu( this ); QMenu menu( this );
@ -803,14 +839,23 @@ void ArticleView::openSearch()
// Clear any current selection // Clear any current selection
if ( ui.definition->selectedText().size() ) if ( ui.definition->selectedText().size() )
{ {
ui.definition->triggerPageAction( QWebPage::SelectAll ); ui.definition->page()->currentFrame()->
ui.definition->triggerPageAction( QWebPage::SelectStartOfDocument ); evaluateJavaScript( "window.getSelection().removeAllRanges();" );
} }
if ( ui.searchText->property( "noResults" ).toBool() ) if ( ui.searchText->property( "noResults" ).toBool() )
{ {
ui.searchText->setProperty( "noResults", false ); 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: // For now we resort to this hack:
if ( ui.definition->selectedText().size() ) if ( ui.definition->selectedText().size() )
{ {
ui.definition->triggerPageAction( QWebPage::SelectAll ); ui.definition->page()->currentFrame()->
ui.definition->triggerPageAction( QWebPage::SelectStartOfDocument ); evaluateJavaScript( "window.getSelection().removeAllRanges();" );
} }
} }
@ -867,7 +912,16 @@ void ArticleView::performFindOperation( bool restart, bool backwards )
if ( ui.searchText->property( "noResults" ).toBool() != setMark ) if ( ui.searchText->property( "noResults" ).toBool() != setMark )
{ {
ui.searchText->setProperty( "noResults", 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;
}
}
} }
} }

View file

@ -13,7 +13,7 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="1000,0">
<property name="margin"> <property name="margin">
<number>0</number> <number>0</number>
</property> </property>
@ -43,6 +43,12 @@
</item> </item>
<item> <item>
<widget class="QFrame" name="searchFrame"> <widget class="QFrame" name="searchFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>

View file

@ -126,6 +126,18 @@ MediaWikis makeDefaultMediaWikis( bool enable )
return mw; 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 /// Sets option to true of false if node is "1" or "0" respectively, or leaves
/// it intact if it's neither "1" nor "0". /// it intact if it's neither "1" nor "0".
void applyBoolOption( bool & option, QDomNode const & node ) void applyBoolOption( bool & option, QDomNode const & node )
@ -225,6 +237,7 @@ Class load() throw( exError )
#endif #endif
c.mediawikis = makeDefaultMediaWikis( true ); c.mediawikis = makeDefaultMediaWikis( true );
c.webSites = makeDefaultWebSites();
// Check if we have a template config file. If we do, load it instead // 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 ); 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" ); QDomNode preferences = root.namedItem( "preferences" );
if ( !preferences.isNull() ) 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" ); QDomElement preferences = dd.createElement( "preferences" );
root.appendChild( preferences ); root.appendChild( preferences );

View file

@ -180,6 +180,27 @@ struct MediaWiki
enabled == other.enabled; } 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 /// Hunspell configuration
struct Hunspell struct Hunspell
{ {
@ -256,6 +277,7 @@ struct Class
Groups groups; Groups groups;
Preferences preferences; Preferences preferences;
MediaWikis mediawikis; MediaWikis mediawikis;
WebSites webSites;
Hunspell hunspell; Hunspell hunspell;
Transliteration transliteration; Transliteration transliteration;

View file

@ -16,7 +16,7 @@ EditDictionaries::EditDictionaries( QWidget * parent, Config::Class & cfg_,
dictNetMgr( dictNetMgr_ ), dictNetMgr( dictNetMgr_ ),
origCfg( cfg ), origCfg( cfg ),
sources( this, cfg.paths, cfg.soundDirs, cfg.hunspell, cfg.transliteration, sources( this, cfg.paths, cfg.soundDirs, cfg.hunspell, cfg.transliteration,
cfg.mediawikis ), cfg.mediawikis, cfg.webSites ),
groups( new Groups( this, dictionaries, cfg.groups ) ), groups( new Groups( this, dictionaries, cfg.groups ) ),
dictionariesChanged( false ), dictionariesChanged( false ),
groupsChanged( false ), groupsChanged( false ),
@ -105,7 +105,8 @@ bool EditDictionaries::isSourcesChanged() const
sources.getSoundDirs() != cfg.soundDirs || sources.getSoundDirs() != cfg.soundDirs ||
sources.getHunspell() != cfg.hunspell || sources.getHunspell() != cfg.hunspell ||
sources.getTransliteration() != cfg.transliteration || sources.getTransliteration() != cfg.transliteration ||
sources.getMediaWikis() != cfg.mediawikis; sources.getMediaWikis() != cfg.mediawikis ||
sources.getWebSites() != cfg.webSites;
} }
void EditDictionaries::acceptChangedSources( bool rebuildGroups ) void EditDictionaries::acceptChangedSources( bool rebuildGroups )
@ -119,6 +120,7 @@ void EditDictionaries::acceptChangedSources( bool rebuildGroups )
cfg.hunspell = sources.getHunspell(); cfg.hunspell = sources.getHunspell();
cfg.transliteration = sources.getTransliteration(); cfg.transliteration = sources.getTransliteration();
cfg.mediawikis = sources.getMediaWikis(); cfg.mediawikis = sources.getMediaWikis();
cfg.webSites = sources.getWebSites();
groupInstances.clear(); // Those hold pointers to dictionaries, we need to groupInstances.clear(); // Those hold pointers to dictionaries, we need to
// free them. // free them.

View file

@ -114,7 +114,8 @@ HEADERS += folding.hh \
transliteration.hh \ transliteration.hh \
romaji.hh \ romaji.hh \
russiantranslit.hh \ russiantranslit.hh \
german.hh german.hh \
website.hh
FORMS += groups.ui \ FORMS += groups.ui \
dictgroupwidget.ui \ dictgroupwidget.ui \
mainwindow.ui \ mainwindow.ui \
@ -179,7 +180,8 @@ SOURCES += folding.cc \
transliteration.cc \ transliteration.cc \
romaji.cc \ romaji.cc \
russiantranslit.cc \ russiantranslit.cc \
german.cc german.cc \
website.cc
win32 { win32 {
SOURCES += mouseover_win32/ThTypes.c SOURCES += mouseover_win32/ThTypes.c
HEADERS += mouseover_win32/ThTypes.h HEADERS += mouseover_win32/ThTypes.h

BIN
src/icons/internet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -14,6 +14,7 @@
#include "romaji.hh" #include "romaji.hh"
#include "russiantranslit.hh" #include "russiantranslit.hh"
#include "german.hh" #include "german.hh"
#include "website.hh"
#include <QMessageBox> #include <QMessageBox>
#include <QDir> #include <QDir>
@ -191,6 +192,14 @@ void loadDictionaries( QWidget * parent, bool showInitially,
dictionaries.insert( dictionaries.end(), dicts.begin(), dicts.end() ); 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 // Remove any stale index files
set< string > ids; set< string > ids;

View file

@ -97,9 +97,6 @@ int main( int argc, char ** argv )
translator.load( QString( Config::getProgramDataDir() ) + "/locale/" + localeName ); translator.load( QString( Config::getProgramDataDir() ) + "/locale/" + localeName );
app.installTranslator( &translator ); app.installTranslator( &translator );
// Apply qt stylesheet
MainWindow::applyQtStyleSheet( cfg.preferences.displayStyle );
MainWindow m( cfg ); MainWindow m( cfg );
int r = app.exec(); int r = app.exec();

View file

@ -39,6 +39,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
wordFinder( this ), wordFinder( this ),
newReleaseCheckTimer( this ) newReleaseCheckTimer( this )
{ {
applyQtStyleSheet( cfg.preferences.displayStyle );
ui.setupUi( this ); ui.setupUi( this );
// Make the search pane's titlebar // Make the search pane's titlebar
@ -299,7 +301,7 @@ void MainWindow::applyQtStyleSheet( QString const & displayStyle )
if ( cssFile.open( QFile::ReadOnly ) ) if ( cssFile.open( QFile::ReadOnly ) )
css += cssFile.readAll(); css += cssFile.readAll();
qApp->setStyleSheet( css ); setStyleSheet( css );
} }
void MainWindow::updateTrayIcon() void MainWindow::updateTrayIcon()
@ -458,6 +460,8 @@ void MainWindow::makeScanPopup()
scanPopup = new ScanPopup( 0, cfg, articleNetMgr, dictionaries, groupInstances ); scanPopup = new ScanPopup( 0, cfg, articleNetMgr, dictionaries, groupInstances );
scanPopup->setStyleSheet( styleSheet() );
if ( cfg.preferences.enableScanPopup && enableScanPopup->isChecked() ) if ( cfg.preferences.enableScanPopup && enableScanPopup->isChecked() )
scanPopup->enableScanning(); scanPopup->enableScanning();
} }
@ -719,7 +723,7 @@ void MainWindow::translateInputChanged( QString const & newValue )
if ( ui.translateLine->property( "noResults" ).toBool() ) if ( ui.translateLine->property( "noResults" ).toBool() )
{ {
ui.translateLine->setProperty( "noResults", false ); ui.translateLine->setProperty( "noResults", false );
qApp->setStyleSheet( qApp->styleSheet() ); setStyleSheet( styleSheet() );
} }
return; return;
} }
@ -836,7 +840,7 @@ void MainWindow::updateMatchResults( bool finished )
if ( ui.translateLine->property( "noResults" ).toBool() != setMark ) if ( ui.translateLine->property( "noResults" ).toBool() != setMark )
{ {
ui.translateLine->setProperty( "noResults", setMark ); ui.translateLine->setProperty( "noResults", setMark );
qApp->setStyleSheet( qApp->styleSheet() ); setStyleSheet( styleSheet() );
} }
if ( !wordFinder.getErrorString().isEmpty() ) if ( !wordFinder.getErrorString().isEmpty() )

View file

@ -33,9 +33,6 @@ public:
MainWindow( Config::Class & cfg ); MainWindow( Config::Class & cfg );
~MainWindow(); ~MainWindow();
/// Applies the qt's stylesheet, given the style's name.
static void applyQtStyleSheet( QString const & displayStyle );
private: private:
QSystemTrayIcon * trayIcon; QSystemTrayIcon * trayIcon;
@ -77,6 +74,9 @@ private:
QPrinter printer; // The printer we use for all printing operations 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 /// Creates, destroys or otherwise updates tray icon, according to the
/// current configuration and situation. /// current configuration and situation.
void updateTrayIcon(); void updateTrayIcon();

View file

@ -36,5 +36,6 @@
<file>icons/bookcase.png</file> <file>icons/bookcase.png</file>
<file>qt-style-st-lingvo.css</file> <file>qt-style-st-lingvo.css</file>
<file>article-style-st-lingvo.css</file> <file>article-style-st-lingvo.css</file>
<file>icons/internet.png</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -11,8 +11,11 @@ Sources::Sources( QWidget * parent, Config::Paths const & paths,
Config::SoundDirs const & soundDirs, Config::SoundDirs const & soundDirs,
Config::Hunspell const & hunspell, Config::Hunspell const & hunspell,
Config::Transliteration const & tr, Config::Transliteration const & tr,
Config::MediaWikis const & mediawikis ): QWidget( parent ), Config::MediaWikis const & mediawikis,
mediawikisModel( this, mediawikis ), pathsModel( this, paths ), Config::WebSites const & webSites ): QWidget( parent ),
mediawikisModel( this, mediawikis ),
webSitesModel( this, webSites ),
pathsModel( this, paths ),
soundDirsModel( this, soundDirs ), soundDirsModel( this, soundDirs ),
hunspellDictsModel( this, hunspell ) hunspellDictsModel( this, hunspell )
{ {
@ -24,6 +27,12 @@ Sources::Sources( QWidget * parent, Config::Paths const & paths,
ui.mediaWikis->resizeColumnToContents( 1 ); ui.mediaWikis->resizeColumnToContents( 1 );
ui.mediaWikis->resizeColumnToContents( 2 ); 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->setTabKeyNavigation( true );
ui.paths->setModel( &pathsModel ); ui.paths->setModel( &pathsModel );
@ -159,6 +168,30 @@ void Sources::on_removeMediaWiki_clicked()
mediawikisModel.removeWiki( current.row() ); 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 Sources::getHunspell() const
{ {
Config::Hunspell h; Config::Hunspell h;
@ -337,6 +370,160 @@ bool MediaWikisModel::setData( QModelIndex const & index, const QVariant & value
return false; 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::PathsModel( QWidget * parent, PathsModel::PathsModel( QWidget * parent,

View file

@ -39,6 +39,36 @@ private:
Config::MediaWikis mediawikis; 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 /// A model to be projected into the paths view, according to Qt's MVC model
class PathsModel: public QAbstractItemModel class PathsModel: public QAbstractItemModel
{ {
@ -139,7 +169,8 @@ public:
Config::SoundDirs const &, Config::SoundDirs const &,
Config::Hunspell const &, Config::Hunspell const &,
Config::Transliteration const &, Config::Transliteration const &,
Config::MediaWikis const & ); Config::MediaWikis const &,
Config::WebSites const & );
Config::Paths const & getPaths() const Config::Paths const & getPaths() const
{ return pathsModel.getCurrentPaths(); } { return pathsModel.getCurrentPaths(); }
@ -150,6 +181,9 @@ public:
Config::MediaWikis const & getMediaWikis() const Config::MediaWikis const & getMediaWikis() const
{ return mediawikisModel.getCurrentWikis(); } { return mediawikisModel.getCurrentWikis(); }
Config::WebSites const & getWebSites() const
{ return webSitesModel.getCurrentWebSites(); }
Config::Hunspell getHunspell() const; Config::Hunspell getHunspell() const;
Config::Transliteration getTransliteration() const; Config::Transliteration getTransliteration() const;
@ -162,6 +196,7 @@ signals:
private: private:
Ui::Sources ui; Ui::Sources ui;
MediaWikisModel mediawikisModel; MediaWikisModel mediawikisModel;
WebSitesModel webSitesModel;
PathsModel pathsModel; PathsModel pathsModel;
SoundDirsModel soundDirsModel; SoundDirsModel soundDirsModel;
HunspellDictsModel hunspellDictsModel; HunspellDictsModel hunspellDictsModel;
@ -183,6 +218,9 @@ private slots:
void on_addMediaWiki_clicked(); void on_addMediaWiki_clicked();
void on_removeMediaWiki_clicked(); void on_removeMediaWiki_clicked();
void on_addWebSite_clicked();
void on_removeWebSite_clicked();
void on_rescan_clicked(); void on_rescan_clicked();
}; };

View file

@ -271,6 +271,69 @@ of the appropriate groups to use them.</string>
</item> </item>
</layout> </layout>
</widget> </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>&amp;Add...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeWebSite">
<property name="text">
<string>&amp;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"> <widget class="QWidget" name="tab_3">
<attribute name="title"> <attribute name="title">
<string>Transliteration</string> <string>Transliteration</string>

109
src/website.cc Normal file
View 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
View 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