mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-24 00:14:06 +00:00
Set up network disk cache for articleNetMgr
When a Wikipedia article is already cached, this change reduces the amount of sent and received network data almost tenfold. Setting up a network disk cache in the same way for dictNetMgr does not noticeably impact the amount of network traffic. Either this network access manager sends and receives very little data or the data is never the same. So dictNetMgr does not need a disk cache. Use QNetworkDiskCache's default maximum size of 50 MiB as the default network cache size. This size is large enough to accommodate tens of huge MediaWiki articles. It is also small enough that the user is unlikely to run out of disk space because of the cache. Clear network cache on exit by default because most users probably don't load the same online articles after restarting GoldenDict. Plus storing the network cache on disk indefinitely by default would be a new and unexpected to the users privacy risk. Nikita Moor came up with the idea and wrote an initial network disk cache implementation in #1310.
This commit is contained in:
parent
8364b04dc0
commit
193aa4e31d
46
config.cc
46
config.cc
|
@ -22,14 +22,25 @@
|
||||||
#include "atomic_rename.hh"
|
#include "atomic_rename.hh"
|
||||||
#include "qt4x5.hh"
|
#include "qt4x5.hh"
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#else
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Config {
|
namespace Config {
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
QString portableHomeDirPath()
|
||||||
|
{
|
||||||
|
return QCoreApplication::applicationDirPath() + "/portable";
|
||||||
|
}
|
||||||
|
|
||||||
QDir getHomeDir()
|
QDir getHomeDir()
|
||||||
{
|
{
|
||||||
if ( isPortableVersion() )
|
if ( isPortableVersion() )
|
||||||
return QDir( QCoreApplication::applicationDirPath() + "/portable" );
|
return QDir( portableHomeDirPath() );
|
||||||
|
|
||||||
QDir result;
|
QDir result;
|
||||||
|
|
||||||
|
@ -199,6 +210,8 @@ Preferences::Preferences():
|
||||||
disallowContentFromOtherSites( false ),
|
disallowContentFromOtherSites( false ),
|
||||||
enableWebPlugins( false ),
|
enableWebPlugins( false ),
|
||||||
hideGoldenDictHeader( false ),
|
hideGoldenDictHeader( false ),
|
||||||
|
maxNetworkCacheSize( 50 ),
|
||||||
|
clearNetworkCacheOnExit( true ),
|
||||||
zoomFactor( 1 ),
|
zoomFactor( 1 ),
|
||||||
helpZoomFactor( 1 ),
|
helpZoomFactor( 1 ),
|
||||||
wordsZoomLevel( 0 ),
|
wordsZoomLevel( 0 ),
|
||||||
|
@ -897,6 +910,12 @@ Class load() THROW_SPEC( exError )
|
||||||
if ( !preferences.namedItem( "hideGoldenDictHeader" ).isNull() )
|
if ( !preferences.namedItem( "hideGoldenDictHeader" ).isNull() )
|
||||||
c.preferences.hideGoldenDictHeader = ( preferences.namedItem( "hideGoldenDictHeader" ).toElement().text() == "1" );
|
c.preferences.hideGoldenDictHeader = ( preferences.namedItem( "hideGoldenDictHeader" ).toElement().text() == "1" );
|
||||||
|
|
||||||
|
if ( !preferences.namedItem( "maxNetworkCacheSize" ).isNull() )
|
||||||
|
c.preferences.maxNetworkCacheSize = preferences.namedItem( "maxNetworkCacheSize" ).toElement().text().toInt();
|
||||||
|
|
||||||
|
if ( !preferences.namedItem( "clearNetworkCacheOnExit" ).isNull() )
|
||||||
|
c.preferences.clearNetworkCacheOnExit = ( preferences.namedItem( "clearNetworkCacheOnExit" ).toElement().text() == "1" );
|
||||||
|
|
||||||
if ( !preferences.namedItem( "maxStringsInHistory" ).isNull() )
|
if ( !preferences.namedItem( "maxStringsInHistory" ).isNull() )
|
||||||
c.preferences.maxStringsInHistory = preferences.namedItem( "maxStringsInHistory" ).toElement().text().toUInt() ;
|
c.preferences.maxStringsInHistory = preferences.namedItem( "maxStringsInHistory" ).toElement().text().toUInt() ;
|
||||||
|
|
||||||
|
@ -1859,6 +1878,14 @@ void save( Class const & c ) THROW_SPEC( exError )
|
||||||
opt.appendChild( dd.createTextNode( c.preferences.hideGoldenDictHeader ? "1" : "0" ) );
|
opt.appendChild( dd.createTextNode( c.preferences.hideGoldenDictHeader ? "1" : "0" ) );
|
||||||
preferences.appendChild( opt );
|
preferences.appendChild( opt );
|
||||||
|
|
||||||
|
opt = dd.createElement( "maxNetworkCacheSize" );
|
||||||
|
opt.appendChild( dd.createTextNode( QString::number( c.preferences.maxNetworkCacheSize ) ) );
|
||||||
|
preferences.appendChild( opt );
|
||||||
|
|
||||||
|
opt = dd.createElement( "clearNetworkCacheOnExit" );
|
||||||
|
opt.appendChild( dd.createTextNode( c.preferences.clearNetworkCacheOnExit ? "1" : "0" ) );
|
||||||
|
preferences.appendChild( opt );
|
||||||
|
|
||||||
opt = dd.createElement( "maxStringsInHistory" );
|
opt = dd.createElement( "maxStringsInHistory" );
|
||||||
opt.appendChild( dd.createTextNode( QString::number( c.preferences.maxStringsInHistory ) ) );
|
opt.appendChild( dd.createTextNode( QString::number( c.preferences.maxStringsInHistory ) ) );
|
||||||
preferences.appendChild( opt );
|
preferences.appendChild( opt );
|
||||||
|
@ -2246,7 +2273,7 @@ bool isPortableVersion() throw()
|
||||||
{
|
{
|
||||||
bool isPortable;
|
bool isPortable;
|
||||||
|
|
||||||
IsPortable(): isPortable( QFileInfo( QCoreApplication::applicationDirPath() + "/portable" ).isDir() )
|
IsPortable(): isPortable( QFileInfo( portableHomeDirPath() ).isDir() )
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2283,4 +2310,19 @@ QString getStylesDir() throw()
|
||||||
return result.path() + QDir::separator();
|
return result.path() + QDir::separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString getCacheDir() throw()
|
||||||
|
{
|
||||||
|
return isPortableVersion() ? portableHomeDirPath() + "/cache"
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
|
||||||
|
: QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
|
||||||
|
#else
|
||||||
|
: QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getNetworkCacheDir() throw()
|
||||||
|
{
|
||||||
|
return getCacheDir() + "/network";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,6 +302,8 @@ struct Preferences
|
||||||
bool disallowContentFromOtherSites;
|
bool disallowContentFromOtherSites;
|
||||||
bool enableWebPlugins;
|
bool enableWebPlugins;
|
||||||
bool hideGoldenDictHeader;
|
bool hideGoldenDictHeader;
|
||||||
|
int maxNetworkCacheSize;
|
||||||
|
bool clearNetworkCacheOnExit;
|
||||||
|
|
||||||
qreal zoomFactor;
|
qreal zoomFactor;
|
||||||
qreal helpZoomFactor;
|
qreal helpZoomFactor;
|
||||||
|
@ -792,6 +794,12 @@ QString getPortableVersionMorphoDir() throw();
|
||||||
/// Returns the add-on styles directory.
|
/// Returns the add-on styles directory.
|
||||||
QString getStylesDir() throw();
|
QString getStylesDir() throw();
|
||||||
|
|
||||||
|
/// Returns the directory where user-specific non-essential (cached) data should be written.
|
||||||
|
QString getCacheDir() throw();
|
||||||
|
|
||||||
|
/// Returns the article network disk cache directory.
|
||||||
|
QString getNetworkCacheDir() throw();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -763,6 +763,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||||
connect( &articleNetMgr, SIGNAL( proxyAuthenticationRequired( QNetworkProxy, QAuthenticator * ) ),
|
connect( &articleNetMgr, SIGNAL( proxyAuthenticationRequired( QNetworkProxy, QAuthenticator * ) ),
|
||||||
this, SLOT( proxyAuthentication( QNetworkProxy, QAuthenticator * ) ) );
|
this, SLOT( proxyAuthentication( QNetworkProxy, QAuthenticator * ) ) );
|
||||||
|
|
||||||
|
setupNetworkCache( cfg.preferences.maxNetworkCacheSize );
|
||||||
|
|
||||||
makeDictionaries();
|
makeDictionaries();
|
||||||
|
|
||||||
// After we have dictionaries and groups, we can populate history
|
// After we have dictionaries and groups, we can populate history
|
||||||
|
@ -1068,6 +1070,10 @@ void MainWindow::commitData( QSessionManager & )
|
||||||
|
|
||||||
void MainWindow::commitData()
|
void MainWindow::commitData()
|
||||||
{
|
{
|
||||||
|
if( cfg.preferences.clearNetworkCacheOnExit )
|
||||||
|
if( QAbstractNetworkCache * cache = articleNetMgr.cache() )
|
||||||
|
cache->clear();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Save MainWindow state and geometry
|
// Save MainWindow state and geometry
|
||||||
|
@ -1287,6 +1293,33 @@ void MainWindow::applyWebSettings()
|
||||||
defaultSettings->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
|
defaultSettings->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::setupNetworkCache( int maxSize )
|
||||||
|
{
|
||||||
|
// x << 20 == x * 2^20 converts mebibytes to bytes.
|
||||||
|
qint64 const maxCacheSizeInBytes = maxSize <= 0 ? qint64( 0 ) : static_cast< qint64 >( maxSize ) << 20;
|
||||||
|
|
||||||
|
if( QAbstractNetworkCache * abstractCache = articleNetMgr.cache() )
|
||||||
|
{
|
||||||
|
QNetworkDiskCache * const diskCache = qobject_cast< QNetworkDiskCache * >( abstractCache );
|
||||||
|
Q_ASSERT_X( diskCache, Q_FUNC_INFO, "Unexpected network cache type." );
|
||||||
|
diskCache->setMaximumCacheSize( maxCacheSizeInBytes );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( maxCacheSizeInBytes == 0 )
|
||||||
|
return; // There is currently no cache and it is not needed.
|
||||||
|
|
||||||
|
QString const cacheDirectory = Config::getNetworkCacheDir();
|
||||||
|
if( !QDir().mkpath( cacheDirectory ) )
|
||||||
|
{
|
||||||
|
gdWarning( "Cannot create a cache directory %s. Disabling network cache.", cacheDirectory.toUtf8().constData() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QNetworkDiskCache * const diskCache = new QNetworkDiskCache( this );
|
||||||
|
diskCache->setMaximumCacheSize( maxCacheSizeInBytes );
|
||||||
|
diskCache->setCacheDirectory( cacheDirectory );
|
||||||
|
articleNetMgr.setCache( diskCache );
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::makeDictionaries()
|
void MainWindow::makeDictionaries()
|
||||||
{
|
{
|
||||||
Q_ASSERT( !scanPopup && "Scan popup must not exist while dictionaries are initialized. "
|
Q_ASSERT( !scanPopup && "Scan popup must not exist while dictionaries are initialized. "
|
||||||
|
@ -2139,6 +2172,8 @@ void MainWindow::editPreferences()
|
||||||
if( cfg.preferences.favoritesStoreInterval != p.favoritesStoreInterval )
|
if( cfg.preferences.favoritesStoreInterval != p.favoritesStoreInterval )
|
||||||
ui.favoritesPaneWidget->setSaveInterval( p.favoritesStoreInterval );
|
ui.favoritesPaneWidget->setSaveInterval( p.favoritesStoreInterval );
|
||||||
|
|
||||||
|
if( cfg.preferences.maxNetworkCacheSize != p.maxNetworkCacheSize )
|
||||||
|
setupNetworkCache( p.maxNetworkCacheSize );
|
||||||
cfg.preferences = p;
|
cfg.preferences = p;
|
||||||
|
|
||||||
audioPlayerFactory.setPreferences( cfg.preferences );
|
audioPlayerFactory.setPreferences( cfg.preferences );
|
||||||
|
|
|
@ -201,6 +201,7 @@ private:
|
||||||
|
|
||||||
void applyProxySettings();
|
void applyProxySettings();
|
||||||
void applyWebSettings();
|
void applyWebSettings();
|
||||||
|
void setupNetworkCache( int maxSize );
|
||||||
void makeDictionaries();
|
void makeDictionaries();
|
||||||
void updateStatusLine();
|
void updateStatusLine();
|
||||||
void updateGroupList();
|
void updateGroupList();
|
||||||
|
|
|
@ -153,6 +153,12 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
// 1 MB stands for 2^20 bytes on Windows. "MiB" is never used by this OS.
|
||||||
|
ui.maxNetworkCacheSize->setSuffix( tr( " MB" ) );
|
||||||
|
#endif
|
||||||
|
ui.maxNetworkCacheSize->setToolTip( ui.maxNetworkCacheSize->toolTip().arg( Config::getNetworkCacheDir() ) );
|
||||||
|
|
||||||
ui.newTabsOpenAfterCurrentOne->setChecked( p.newTabsOpenAfterCurrentOne );
|
ui.newTabsOpenAfterCurrentOne->setChecked( p.newTabsOpenAfterCurrentOne );
|
||||||
ui.newTabsOpenInBackground->setChecked( p.newTabsOpenInBackground );
|
ui.newTabsOpenInBackground->setChecked( p.newTabsOpenInBackground );
|
||||||
ui.hideSingleTab->setChecked( p.hideSingleTab );
|
ui.hideSingleTab->setChecked( p.hideSingleTab );
|
||||||
|
@ -319,6 +325,8 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
|
||||||
ui.disallowContentFromOtherSites->setChecked( p.disallowContentFromOtherSites );
|
ui.disallowContentFromOtherSites->setChecked( p.disallowContentFromOtherSites );
|
||||||
ui.enableWebPlugins->setChecked( p.enableWebPlugins );
|
ui.enableWebPlugins->setChecked( p.enableWebPlugins );
|
||||||
ui.hideGoldenDictHeader->setChecked( p.hideGoldenDictHeader );
|
ui.hideGoldenDictHeader->setChecked( p.hideGoldenDictHeader );
|
||||||
|
ui.maxNetworkCacheSize->setValue( p.maxNetworkCacheSize );
|
||||||
|
ui.clearNetworkCacheOnExit->setChecked( p.clearNetworkCacheOnExit );
|
||||||
|
|
||||||
// Add-on styles
|
// Add-on styles
|
||||||
ui.addonStylesLabel->setVisible( ui.addonStyles->count() > 1 );
|
ui.addonStylesLabel->setVisible( ui.addonStyles->count() > 1 );
|
||||||
|
@ -449,6 +457,8 @@ Config::Preferences Preferences::getPreferences()
|
||||||
p.disallowContentFromOtherSites = ui.disallowContentFromOtherSites->isChecked();
|
p.disallowContentFromOtherSites = ui.disallowContentFromOtherSites->isChecked();
|
||||||
p.enableWebPlugins = ui.enableWebPlugins->isChecked();
|
p.enableWebPlugins = ui.enableWebPlugins->isChecked();
|
||||||
p.hideGoldenDictHeader = ui.hideGoldenDictHeader->isChecked();
|
p.hideGoldenDictHeader = ui.hideGoldenDictHeader->isChecked();
|
||||||
|
p.maxNetworkCacheSize = ui.maxNetworkCacheSize->value();
|
||||||
|
p.clearNetworkCacheOnExit = ui.clearNetworkCacheOnExit->isChecked();
|
||||||
|
|
||||||
p.addonStyle = ui.addonStyles->getCurrentStyle();
|
p.addonStyle = ui.addonStyles->getCurrentStyle();
|
||||||
|
|
||||||
|
@ -639,6 +649,11 @@ void Preferences::customProxyToggled( bool )
|
||||||
&& ui.useProxyServer->isChecked() );
|
&& ui.useProxyServer->isChecked() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Preferences::on_maxNetworkCacheSize_valueChanged( int value )
|
||||||
|
{
|
||||||
|
ui.clearNetworkCacheOnExit->setEnabled( value != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
void Preferences::helpRequested()
|
void Preferences::helpRequested()
|
||||||
{
|
{
|
||||||
if( !helpWindow )
|
if( !helpWindow )
|
||||||
|
|
|
@ -52,6 +52,7 @@ private slots:
|
||||||
void on_useExternalPlayer_toggled( bool enabled );
|
void on_useExternalPlayer_toggled( bool enabled );
|
||||||
|
|
||||||
void customProxyToggled( bool );
|
void customProxyToggled( bool );
|
||||||
|
void on_maxNetworkCacheSize_valueChanged( int value );
|
||||||
|
|
||||||
void helpRequested();
|
void helpRequested();
|
||||||
void closeHelp();
|
void closeHelp();
|
||||||
|
|
|
@ -1152,6 +1152,59 @@ Enable this option to workaround the problem.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="text">
|
||||||
|
<string>Maximum network cache size:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="maxNetworkCacheSize">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Maximum disk space occupied by GoldenDict's network cache in
|
||||||
|
%1
|
||||||
|
If set to 0 the network disk cache will be disabled.</string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> MiB</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>2000</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="clearNetworkCacheOnExit">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>When this option is enabled, GoldenDict
|
||||||
|
clears its network cache from disk during exit.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear network cache on exit</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_15">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_10">
|
<spacer name="verticalSpacer_10">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
Loading…
Reference in a new issue