goldendict-ng/preferences.cc

744 lines
26 KiB
C++
Raw Normal View History

#include "preferences.hh"
#include "keyboardstate.hh"
#include "language.hh"
#include "langcoder.hh"
#include <QMessageBox>
2014-06-24 13:55:06 +00:00
#include "mainwindow.hh"
#include <QWebEngineSettings>
#include <QWebEngineProfile>
2014-06-24 13:55:06 +00:00
Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
QDialog( parent ), prevInterfaceLanguage( 0 )
2014-06-24 13:55:06 +00:00
, helpWindow( 0 )
, cfg( cfg_ )
, helpAction( this )
{
2014-06-24 13:55:06 +00:00
Config::Preferences const & p = cfg_.preferences;
ui.setupUi( this );
connect( ui.enableScanPopup, SIGNAL( toggled( bool ) ),
this, SLOT( enableScanPopupToggled( bool ) ) );
connect( ui.enableScanPopupModifiers, SIGNAL( toggled( bool ) ),
this, SLOT( enableScanPopupModifiersToggled( bool ) ) );
connect( ui.showScanFlag, SIGNAL( toggled( bool ) ),
this, SLOT( showScanFlagToggled( bool ) ) );
connect( ui.altKey, SIGNAL( clicked( bool ) ),
this, SLOT( wholeAltClicked( bool ) ) );
connect( ui.ctrlKey, SIGNAL( clicked( bool ) ),
this, SLOT( wholeCtrlClicked( bool ) ) );
connect( ui.shiftKey, SIGNAL( clicked( bool ) ),
this, SLOT( wholeShiftClicked( bool ) ) );
connect( ui.leftAlt, SIGNAL( clicked( bool ) ),
this, SLOT( sideAltClicked( bool ) ) );
connect( ui.rightAlt, SIGNAL( clicked( bool ) ),
this, SLOT( sideAltClicked( bool ) ) );
connect( ui.leftCtrl, SIGNAL( clicked( bool ) ),
this, SLOT( sideCtrlClicked( bool ) ) );
connect( ui.rightCtrl, SIGNAL( clicked( bool ) ),
this, SLOT( sideCtrlClicked( bool ) ) );
connect( ui.leftShift, SIGNAL( clicked( bool ) ),
this, SLOT( sideShiftClicked( bool ) ) );
connect( ui.rightShift, SIGNAL( clicked( bool ) ),
this, SLOT( sideShiftClicked( bool ) ) );
2014-06-24 13:55:06 +00:00
connect( ui.buttonBox, SIGNAL( helpRequested() ),
this, SLOT( helpRequested() ) );
helpAction.setShortcut( QKeySequence( "F1" ) );
helpAction.setShortcutContext( Qt::WidgetWithChildrenShortcut );
connect( &helpAction, SIGNAL( triggered() ),
this, SLOT( helpRequested() ) );
addAction( &helpAction );
// Load values into form
ui.interfaceLanguage->addItem( tr( "System default" ), QString() );
ui.interfaceLanguage->addItem( QIcon( ":/flags/us.png" ), Language::localizedNameForId( LangCoder::code2toInt( "en" ) ), QString( "en_US" ) );
ui.fontFamilies->addItem( tr( "System default" ), QString() );
// See which other translations do we have
QStringList availLocs = QDir( Config::getEmbedLocDir() ).entryList( QStringList( "*.qm" ),
QDir::Files );
// We need to sort by language name -- otherwise list looks really weird
QMultiMap< QString, QPair< QIcon, QString > > sortedLocs;
for( QStringList::iterator i = availLocs.begin(); i != availLocs.end(); ++i )
{
// Here we assume the xx_YY naming, where xx is language and YY is region.
QString lang = i->mid( 0, 2 );
if ( lang == "qt" )
2010-12-03 19:14:14 +00:00
continue; // We skip qt's own localizations
sortedLocs.insert(
Language::localizedNameForId( LangCoder::code2toInt( lang.toLatin1().data() ) ),
QPair< QIcon, QString >(
QIcon( QString( ":/flags/%1.png" ).arg( i->mid( 3, 2 ).toLower() ) ),
i->mid( 0, i->size() - 3 ) ) );
}
for( QMultiMap< QString, QPair< QIcon, QString > >::iterator i = sortedLocs.begin(); i != sortedLocs.end(); ++i )
ui.interfaceLanguage->addItem( i.value().first, i.key(), i.value().second );
for( int x = 0; x < ui.interfaceLanguage->count(); ++x )
if ( ui.interfaceLanguage->itemData( x ).toString() == p.interfaceLanguage )
{
ui.interfaceLanguage->setCurrentIndex( x );
prevInterfaceLanguage = x;
break;
}
#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
const QStringList fontFamilies = QFontDatabase::families();
#else
QFontDatabase fontDb;
const QStringList fontFamilies = fontDb.families();
#endif
for( const QString & family : fontFamilies )
{
ui.fontFamilies->addItem( family );
}
prevWebFontFamily = p.webFontFamily;
if(!p.webFontFamily.isEmpty())
ui.fontFamilies->setCurrentText( p.webFontFamily );
2014-06-25 14:01:11 +00:00
// Fill help languages combobox
ui.helpLanguage->addItem( tr( "Default" ), QString() );
// See which helps do we have
QStringList availHelps = QDir( Config::getHelpDir() ).entryList( QStringList( "*.qch" ),
QDir::Files );
QMultiMap< QString, QPair< QIcon, QString > > sortedHelps;
2014-06-25 14:01:11 +00:00
for( QStringList::iterator i = availHelps.begin(); i != availHelps.end(); ++i )
{
QString loc = i->mid( 7, i->length() - 11 ); // e.g. *i == "gdhelp_en.qch" => loc == "en"
2014-06-25 14:01:11 +00:00
QString lang = loc.mid( 0, 2 );
QString reg;
if(loc.length() >= 5 )
reg = loc.mid( 3, 2 ).toLower();
else
{
if( lang.compare( "en", Qt::CaseInsensitive ) == 0 )
reg = "US";
else
reg = lang.toUpper();
}
sortedHelps.insert(
2014-06-25 14:01:11 +00:00
Language::localizedNameForId( LangCoder::code2toInt( lang.toLatin1().data() ) ),
QPair< QIcon, QString >(
QIcon( QString( ":/flags/%1.png" ).arg( reg.toLower() ) ), lang + "_" + reg ) );
}
for( QMultiMap< QString, QPair< QIcon, QString > >::iterator i = sortedHelps.begin(); i != sortedHelps.end(); ++i )
2014-06-25 14:01:11 +00:00
ui.helpLanguage->addItem( i.value().first, i.key(), i.value().second );
for( int x = 0; x < ui.helpLanguage->count(); ++x )
if ( ui.helpLanguage->itemData( x ).toString() == p.helpLanguage )
{
ui.helpLanguage->setCurrentIndex( x );
break;
}
ui.displayStyle->addItem( QIcon( ":/icons/programicon_old.png" ), tr( "Default" ), QString() );
ui.displayStyle->addItem( QIcon( ":/icons/programicon.png" ), tr( "Classic" ), QString( "classic" ) );
ui.displayStyle->addItem( QIcon( ":/icons/programicon.png" ), tr( "Modern" ), QString( "modern" ) );
ui.displayStyle->addItem( QIcon( ":/icons/icon32_dsl.png" ), tr( "Lingvo" ), QString( "lingvo" ) );
ui.displayStyle->addItem( QIcon( ":/icons/icon32_bgl.png" ), tr( "Babylon" ), QString( "babylon" ) );
ui.displayStyle->addItem( QIcon( ":/icons/icon32_lingoes.png" ), tr( "Lingoes" ), QString( "lingoes" ) );
ui.displayStyle->addItem( QIcon( ":/icons/icon32_lingoes.png" ), tr( "Lingoes-Blue" ), QString( "lingoes-blue" ) );
for( int x = 0; x < ui.displayStyle->count(); ++x )
if ( ui.displayStyle->itemData( x ).toString() == p.displayStyle )
{
ui.displayStyle->setCurrentIndex( x );
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.newTabsOpenInBackground->setChecked( p.newTabsOpenInBackground );
ui.hideSingleTab->setChecked( p.hideSingleTab );
2011-11-02 23:37:50 +00:00
ui.mruTabOrder->setChecked( p.mruTabOrder );
ui.enableTrayIcon->setChecked( p.enableTrayIcon );
ui.startToTray->setChecked( p.startToTray );
ui.closeToTray->setChecked( p.closeToTray );
ui.cbAutostart->setChecked( p.autoStart );
ui.doubleClickTranslates->setChecked( p.doubleClickTranslates );
ui.selectBySingleClick->setChecked( p.selectWordBySingleClick);
Add "Automatically scroll to target article" option When a user clicks on a link in a dictionary or requests translation of a word by double-clicking or translates selection via the context menu, at first the article from the highest-priority dictionary is at the top. Then, after approximately one second, the article from the dictionary, out of which the translation was requested, becomes current and the view scrolls down to this article placing it on top, hiding articles from the dictionaries above it. Such application behavior is inconvenient in some workflows so that the user manually navigates to the top dictionary translation when this automatic scrolling happens. For example: a user has English->Russian dictionaries and English->English dictionaries. The English->Russian dictionaries are higher up in the dictionary order because they provide easier/faster to understand translations. Some rare words and phrases are missing from the English->Russian dictionaries however. Thus the user occasionally reads the English explanation of a word/phrase. When the user double-clicks on a word or follows a link in the English->English dictionary article, she would rather see translations from the preferable English->Russian dictionaries. The new option allows to disable automatic scrolling and ensure that articles from higher-priority dictionaries are visible. The option doesn't affect backward/forward navigation via arrow buttons or Alt+Arrow shortcuts: these still scroll to the stored vertical position among articles. This remaining automatic scrolling happens much faster, is not a problem for the described use case and hopefully for other use cases.
2019-01-11 13:50:40 +00:00
ui.autoScrollToTargetArticle->setChecked( p.autoScrollToTargetArticle );
ui.escKeyHidesMainWindow->setChecked( p.escKeyHidesMainWindow );
ui.enableMainWindowHotkey->setChecked( p.enableMainWindowHotkey );
ui.mainWindowHotkey->setHotKey( p.mainWindowHotkey );
ui.enableClipboardHotkey->setChecked( p.enableClipboardHotkey );
ui.clipboardHotkey->setHotKey( p.clipboardHotkey );
ui.enableScanPopup->setChecked( p.enableScanPopup );
ui.startWithScanPopupOn->setChecked( p.startWithScanPopupOn );
ui.enableScanPopupModifiers->setChecked( p.enableScanPopupModifiers );
ui.altKey->setChecked( p.scanPopupModifiers & KeyboardState::Alt );
ui.ctrlKey->setChecked( p.scanPopupModifiers & KeyboardState::Ctrl );
ui.shiftKey->setChecked( p.scanPopupModifiers & KeyboardState::Shift );
ui.winKey->setChecked( p.scanPopupModifiers & KeyboardState::Win );
ui.leftAlt->setChecked( p.scanPopupModifiers & KeyboardState::LeftAlt );
ui.rightAlt->setChecked( p.scanPopupModifiers & KeyboardState::RightAlt );
ui.leftCtrl->setChecked( p.scanPopupModifiers & KeyboardState::LeftCtrl );
ui.rightCtrl->setChecked( p.scanPopupModifiers & KeyboardState::RightCtrl );
ui.leftShift->setChecked( p.scanPopupModifiers & KeyboardState::LeftShift );
ui.rightShift->setChecked( p.scanPopupModifiers & KeyboardState::RightShift );
ui.scanPopupAltMode->setChecked( p.scanPopupAltMode );
ui.scanPopupAltModeSecs->setValue( p.scanPopupAltModeSecs );
ui.ignoreOwnClipboardChanges->setChecked( p.ignoreOwnClipboardChanges );
ui.scanToMainWindow->setChecked( p.scanToMainWindow );
Allow customizing unpinned scan popup window flags on X11 with Qt5 My tests in many desktop environments and window managers indicate that no single configuration works perfectly in all environments. There are also behavior differences between Qt::Popup and Qt::Tool flags, which are not exactly bugs, so I suppose users might subjectively prefer different options. Customizing the flags allows the user to prevent unpinned scan popup window flickering with Qt5 on Linux. In a way adding these options fixes issue #645, which is: the scan popup window blinks rapidly, barely noticeably in some applications, such as Calibre ebook-viewer and Chromium. In this case the scan popup window usually ends up hidden when selection ends, unless it was finished with a jerk. I have tested the new options in 9 desktop environments and window managers: at least one configuration for each eliminates #645 and makes the scan popup window work the same as with Qt4 in this regard: the popup window remains visible, text in the popup's translation line keeps up with the text selection in the external application, and the selected text is being translated on the fly. Moreover, for each tested DE/WM, at least one configuration makes the scan popup window work perfectly as far as I am concerned. This issue was partially worked around with a 200ms scan popup delay timer in the recent commit 58e41fe3ceb769cab37608e36637044e597ba1f8 for the duplicate issue #854. However the timer solution is incomplete because it requires the user to select text quickly and without delays. If global mouse selection does not change for 200ms while the left mouse button is held down, the user will likely not see the scan popup when (s)he finishes selection, and will have to try selecting again - hopefully faster this time. The 200ms delay is no longer critically important after this commit, but it is still beneficial: the lookup query changes less often, which in turn reduces article definition update frequency. So the delay improves the UI (perhaps subjectively) and performance.
2018-04-09 17:50:23 +00:00
ui.scanPopupUnpinnedWindowFlags->setCurrentIndex( p.scanPopupUnpinnedWindowFlags );
ui.scanPopupUnpinnedBypassWMHint->setChecked( p.scanPopupUnpinnedBypassWMHint );
ui.storeHistory->setChecked( p.storeHistory );
ui.historyMaxSizeField->setValue( p.maxStringsInHistory );
ui.historySaveIntervalField->setValue( p.historyStoreInterval );
ui.alwaysExpandOptionalParts->setChecked( p.alwaysExpandOptionalParts );
ui.favoritesSaveIntervalField->setValue( p.favoritesStoreInterval );
ui.confirmFavoritesDeletion->setChecked( p.confirmFavoritesDeletion );
ui.collapseBigArticles->setChecked( p.collapseBigArticles );
on_collapseBigArticles_toggled( ui.collapseBigArticles->isChecked() );
ui.articleSizeLimit->setValue( p.articleSizeLimit );
Add options to limit input phrase length When a long text is accidentally selected or copied while the scan popup is on, Goldendict spends a lot of CPU time to gradually create a "No translation..." article. When translation of huge (e.g. 15 MB) text from the clipboard is (accidentally) requested, Goldendict freezes for a while. Turning the added input phrase limit option on eliminates this waste of the CPU time. I have implemented these options primarily for selection and clipboard, but they also affect mouse-over translation on Windows and command line translation requests. This is mostly because I did not bother to limit the options' scope. I guess hovering over an extremely long text without spaces (e.g. Base64-encoded) could cause the same performance issue on Windows. The command-line translation could be requested from a script that integrates Goldendict with some other application, from which long text could be sent for translation by accident. I hope that the default value of 200 characters will be sufficient for just about any real-world user input in any language. The option is on by default, because the default length limit is generous and any longer text is unlikely to be sent for translation intentionally. My personal preference for the input phrase length limit is 100 symbols. ArticleView::pasteTriggered() didn't call QString::simplified() on the text retrieved from the clipboard. I assumed this was an oversight, so now it *is* called - indirectly, via Preferences::sanitizeInputPhrase().
2020-11-06 19:51:30 +00:00
ui.limitInputPhraseLength->setChecked( p.limitInputPhraseLength );
on_limitInputPhraseLength_toggled( ui.limitInputPhraseLength->isChecked() );
Add options to limit input phrase length When a long text is accidentally selected or copied while the scan popup is on, Goldendict spends a lot of CPU time to gradually create a "No translation..." article. When translation of huge (e.g. 15 MB) text from the clipboard is (accidentally) requested, Goldendict freezes for a while. Turning the added input phrase limit option on eliminates this waste of the CPU time. I have implemented these options primarily for selection and clipboard, but they also affect mouse-over translation on Windows and command line translation requests. This is mostly because I did not bother to limit the options' scope. I guess hovering over an extremely long text without spaces (e.g. Base64-encoded) could cause the same performance issue on Windows. The command-line translation could be requested from a script that integrates Goldendict with some other application, from which long text could be sent for translation by accident. I hope that the default value of 200 characters will be sufficient for just about any real-world user input in any language. The option is on by default, because the default length limit is generous and any longer text is unlikely to be sent for translation intentionally. My personal preference for the input phrase length limit is 100 symbols. ArticleView::pasteTriggered() didn't call QString::simplified() on the text retrieved from the clipboard. I assumed this was an oversight, so now it *is* called - indirectly, via Preferences::sanitizeInputPhrase().
2020-11-06 19:51:30 +00:00
ui.inputPhraseLengthLimit->setValue( p.inputPhraseLengthLimit );
ui.ignoreDiacritics->setChecked( p.ignoreDiacritics );
2022-04-23 08:15:23 +00:00
ui.ignorePunctuation->setChecked( p.ignorePunctuation );
ui.synonymSearchEnabled->setChecked( p.synonymSearchEnabled );
ui.maxDictsInContextMenu->setValue( p.maxDictionaryRefsInContextMenu );
// Different platforms have different keys available
#ifdef Q_OS_WIN32
ui.winKey->hide();
#else
ui.leftAlt->hide();
ui.rightAlt->hide();
ui.leftCtrl->hide();
ui.rightCtrl->hide();
ui.leftShift->hide();
ui.rightShift->hide();
#ifdef Q_OS_MAC
ui.altKey->setText( "Opt" );
ui.winKey->setText( "Ctrl" );
ui.ctrlKey->setText( "Cmd" );
#endif
#endif
//Platform-specific options
Allow customizing unpinned scan popup window flags on X11 with Qt5 My tests in many desktop environments and window managers indicate that no single configuration works perfectly in all environments. There are also behavior differences between Qt::Popup and Qt::Tool flags, which are not exactly bugs, so I suppose users might subjectively prefer different options. Customizing the flags allows the user to prevent unpinned scan popup window flickering with Qt5 on Linux. In a way adding these options fixes issue #645, which is: the scan popup window blinks rapidly, barely noticeably in some applications, such as Calibre ebook-viewer and Chromium. In this case the scan popup window usually ends up hidden when selection ends, unless it was finished with a jerk. I have tested the new options in 9 desktop environments and window managers: at least one configuration for each eliminates #645 and makes the scan popup window work the same as with Qt4 in this regard: the popup window remains visible, text in the popup's translation line keeps up with the text selection in the external application, and the selected text is being translated on the fly. Moreover, for each tested DE/WM, at least one configuration makes the scan popup window work perfectly as far as I am concerned. This issue was partially worked around with a 200ms scan popup delay timer in the recent commit 58e41fe3ceb769cab37608e36637044e597ba1f8 for the duplicate issue #854. However the timer solution is incomplete because it requires the user to select text quickly and without delays. If global mouse selection does not change for 200ms while the left mouse button is held down, the user will likely not see the scan popup when (s)he finishes selection, and will have to try selecting again - hopefully faster this time. The 200ms delay is no longer critically important after this commit, but it is still beneficial: the lookup query changes less often, which in turn reduces article definition update frequency. So the delay improves the UI (perhaps subjectively) and performance.
2018-04-09 17:50:23 +00:00
#ifndef ENABLE_SPWF_CUSTOMIZATION
ui.groupBox_ScanPopupWindowFlags->hide();
#endif
#ifdef HAVE_X11
ui.showScanFlag->setChecked( p.showScanFlag);
#else
ui.showScanFlag->hide();
ui.ignoreOwnClipboardChanges->hide();
#endif
// Sound
ui.pronounceOnLoadMain->setChecked( p.pronounceOnLoadMain );
ui.pronounceOnLoadPopup->setChecked( p.pronounceOnLoadPopup );
ui.internalPlayerBackend->addItems( Config::InternalPlayerBackend::nameList() );
// Make sure that exactly one radio button in the group is checked and that
// on_useExternalPlayer_toggled() is called.
ui.useExternalPlayer->setChecked( true );
if( ui.internalPlayerBackend->count() > 0 )
{
// Checking ui.useInternalPlayer automatically unchecks ui.useExternalPlayer.
ui.useInternalPlayer->setChecked( p.useInternalPlayer );
int index = ui.internalPlayerBackend->findText( p.internalPlayerBackend.uiName() );
if( index < 0 ) // The specified backend is unavailable.
index = ui.internalPlayerBackend->findText( Config::InternalPlayerBackend::defaultBackend().uiName() );
Q_ASSERT( index >= 0 && "Logic error: the default backend must be present in the backend name list." );
ui.internalPlayerBackend->setCurrentIndex( index );
}
else
{
ui.useInternalPlayer->hide();
ui.internalPlayerBackend->hide();
}
ui.audioPlaybackProgram->setText( p.audioPlaybackProgram );
// Proxy server
ui.useProxyServer->setChecked( p.proxyServer.enabled );
ui.proxyType->addItem( "SOCKS5" );
ui.proxyType->addItem( "HTTP Transp." );
ui.proxyType->addItem( "HTTP Caching" );
ui.proxyType->setCurrentIndex( p.proxyServer.type );
ui.proxyHost->setText( p.proxyServer.host );
ui.proxyPort->setValue( p.proxyServer.port );
ui.proxyUser->setText( p.proxyServer.user );
ui.proxyPassword->setText( p.proxyServer.password );
2014-04-01 17:00:13 +00:00
if( p.proxyServer.useSystemProxy )
{
ui.systemProxy->setChecked( true );
ui.customSettingsGroup->setEnabled( false );
}
else
{
ui.customProxy->setChecked( true );
ui.customSettingsGroup->setEnabled( p.proxyServer.enabled );
}
//anki connect
ui.useAnkiConnect->setChecked( p.ankiConnectServer.enabled );
ui.ankiHost->setText( p.ankiConnectServer.host );
ui.ankiPort->setValue( p.ankiConnectServer.port );
ui.ankiModel->setText( p.ankiConnectServer.model );
ui.ankiDeck->setText(p.ankiConnectServer.deck);
2014-04-01 17:00:13 +00:00
connect( ui.customProxy, SIGNAL( toggled( bool ) ),
this, SLOT( customProxyToggled( bool ) ) );
connect( ui.useProxyServer, SIGNAL( toggled( bool ) ),
this, SLOT( customProxyToggled( bool ) ) );
ui.checkForNewReleases->setChecked( p.checkForNewReleases );
ui.disallowContentFromOtherSites->setChecked( p.disallowContentFromOtherSites );
ui.enableWebPlugins->setChecked( p.enableWebPlugins );
ui.hideGoldenDictHeader->setChecked( p.hideGoldenDictHeader );
ui.maxNetworkCacheSize->setValue( p.maxNetworkCacheSize );
ui.clearNetworkCacheOnExit->setChecked( p.clearNetworkCacheOnExit );
2012-12-10 14:14:13 +00:00
// Add-on styles
ui.addonStylesLabel->setVisible( ui.addonStyles->count() > 1 );
ui.addonStyles->setCurrentStyle( p.addonStyle );
// Full-text search parameters
ui.ftsGroupBox->setChecked( p.fts.enabled );
ui.allowAard->setChecked( !p.fts.disabledTypes.contains( "AARD", Qt::CaseInsensitive ) );
ui.allowBGL->setChecked( !p.fts.disabledTypes.contains( "BGL", Qt::CaseInsensitive ) );
ui.allowDictD->setChecked( !p.fts.disabledTypes.contains( "DICTD", Qt::CaseInsensitive ) );
ui.allowDSL->setChecked( !p.fts.disabledTypes.contains( "DSL", Qt::CaseInsensitive ) );
ui.allowMDict->setChecked( !p.fts.disabledTypes.contains( "MDICT", Qt::CaseInsensitive ) );
ui.allowSDict->setChecked( !p.fts.disabledTypes.contains( "SDICT", Qt::CaseInsensitive ) );
2015-01-22 15:17:05 +00:00
ui.allowSlob->setChecked( !p.fts.disabledTypes.contains( "SLOB", Qt::CaseInsensitive ) );
ui.allowStardict->setChecked( !p.fts.disabledTypes.contains( "STARDICT", Qt::CaseInsensitive ) );
ui.allowXDXF->setChecked( !p.fts.disabledTypes.contains( "XDXF", Qt::CaseInsensitive ) );
ui.allowZim->setChecked( !p.fts.disabledTypes.contains( "ZIM", Qt::CaseInsensitive ) );
2014-05-20 13:59:56 +00:00
ui.allowEpwing->setChecked( !p.fts.disabledTypes.contains( "EPWING", Qt::CaseInsensitive ) );
ui.allowGls->setChecked( !p.fts.disabledTypes.contains( "GLS", Qt::CaseInsensitive ) );
#ifndef MAKE_ZIM_SUPPORT
ui.allowZim->hide();
2015-01-22 15:17:05 +00:00
ui.allowSlob->hide();
2014-05-20 13:59:56 +00:00
#endif
#ifdef NO_EPWING_SUPPORT
ui.allowEpwing->hide();
#endif
ui.maxDictionarySize->setValue( p.fts.maxDictionarySize );
}
Config::Preferences Preferences::getPreferences()
{
Config::Preferences p;
p.interfaceLanguage =
ui.interfaceLanguage->itemData(
ui.interfaceLanguage->currentIndex() ).toString();
//bypass the first default
if(ui.fontFamilies->currentIndex()>0)
p.webFontFamily = ui.fontFamilies->currentText();
else
p.webFontFamily = "";
2014-06-25 14:01:11 +00:00
p.helpLanguage =
ui.helpLanguage->itemData(
ui.helpLanguage->currentIndex() ).toString();
p.displayStyle =
ui.displayStyle->itemData(
ui.displayStyle->currentIndex() ).toString();
p.newTabsOpenAfterCurrentOne = ui.newTabsOpenAfterCurrentOne->isChecked();
p.newTabsOpenInBackground = ui.newTabsOpenInBackground->isChecked();
p.hideSingleTab = ui.hideSingleTab->isChecked();
2011-11-02 23:37:50 +00:00
p.mruTabOrder = ui.mruTabOrder->isChecked();
p.enableTrayIcon = ui.enableTrayIcon->isChecked();
p.startToTray = ui.startToTray->isChecked();
p.closeToTray = ui.closeToTray->isChecked();
p.autoStart = ui.cbAutostart->isChecked();
p.doubleClickTranslates = ui.doubleClickTranslates->isChecked();
p.selectWordBySingleClick = ui.selectBySingleClick->isChecked();
Add "Automatically scroll to target article" option When a user clicks on a link in a dictionary or requests translation of a word by double-clicking or translates selection via the context menu, at first the article from the highest-priority dictionary is at the top. Then, after approximately one second, the article from the dictionary, out of which the translation was requested, becomes current and the view scrolls down to this article placing it on top, hiding articles from the dictionaries above it. Such application behavior is inconvenient in some workflows so that the user manually navigates to the top dictionary translation when this automatic scrolling happens. For example: a user has English->Russian dictionaries and English->English dictionaries. The English->Russian dictionaries are higher up in the dictionary order because they provide easier/faster to understand translations. Some rare words and phrases are missing from the English->Russian dictionaries however. Thus the user occasionally reads the English explanation of a word/phrase. When the user double-clicks on a word or follows a link in the English->English dictionary article, she would rather see translations from the preferable English->Russian dictionaries. The new option allows to disable automatic scrolling and ensure that articles from higher-priority dictionaries are visible. The option doesn't affect backward/forward navigation via arrow buttons or Alt+Arrow shortcuts: these still scroll to the stored vertical position among articles. This remaining automatic scrolling happens much faster, is not a problem for the described use case and hopefully for other use cases.
2019-01-11 13:50:40 +00:00
p.autoScrollToTargetArticle = ui.autoScrollToTargetArticle->isChecked();
p.escKeyHidesMainWindow = ui.escKeyHidesMainWindow->isChecked();
p.enableMainWindowHotkey = ui.enableMainWindowHotkey->isChecked();
p.mainWindowHotkey = ui.mainWindowHotkey->getHotKey();
p.enableClipboardHotkey = ui.enableClipboardHotkey->isChecked();
p.clipboardHotkey = ui.clipboardHotkey->getHotKey();
p.enableScanPopup = ui.enableScanPopup->isChecked();
p.startWithScanPopupOn = ui.startWithScanPopupOn->isChecked();
p.enableScanPopupModifiers = ui.enableScanPopupModifiers->isChecked();
p.scanPopupModifiers += ui.altKey->isChecked() ? KeyboardState::Alt : 0;
p.scanPopupModifiers += ui.ctrlKey->isChecked() ? KeyboardState::Ctrl: 0;
p.scanPopupModifiers += ui.shiftKey->isChecked() ? KeyboardState::Shift: 0;
p.scanPopupModifiers += ui.winKey->isChecked() ? KeyboardState::Win: 0;
p.scanPopupModifiers += ui.leftAlt->isChecked() ? KeyboardState::LeftAlt: 0;
p.scanPopupModifiers += ui.rightAlt->isChecked() ? KeyboardState::RightAlt: 0;
p.scanPopupModifiers += ui.leftCtrl->isChecked() ? KeyboardState::LeftCtrl: 0;
p.scanPopupModifiers += ui.rightCtrl->isChecked() ? KeyboardState::RightCtrl: 0;
p.scanPopupModifiers += ui.leftShift->isChecked() ? KeyboardState::LeftShift: 0;
p.scanPopupModifiers += ui.rightShift->isChecked() ? KeyboardState::RightShift: 0;
p.scanPopupAltMode = ui.scanPopupAltMode->isChecked();
p.scanPopupAltModeSecs = ui.scanPopupAltModeSecs->value();
p.ignoreOwnClipboardChanges = ui.ignoreOwnClipboardChanges->isChecked();
p.scanToMainWindow = ui.scanToMainWindow->isChecked();
#ifdef HAVE_X11
p.showScanFlag= ui.showScanFlag->isChecked();
#endif
Allow customizing unpinned scan popup window flags on X11 with Qt5 My tests in many desktop environments and window managers indicate that no single configuration works perfectly in all environments. There are also behavior differences between Qt::Popup and Qt::Tool flags, which are not exactly bugs, so I suppose users might subjectively prefer different options. Customizing the flags allows the user to prevent unpinned scan popup window flickering with Qt5 on Linux. In a way adding these options fixes issue #645, which is: the scan popup window blinks rapidly, barely noticeably in some applications, such as Calibre ebook-viewer and Chromium. In this case the scan popup window usually ends up hidden when selection ends, unless it was finished with a jerk. I have tested the new options in 9 desktop environments and window managers: at least one configuration for each eliminates #645 and makes the scan popup window work the same as with Qt4 in this regard: the popup window remains visible, text in the popup's translation line keeps up with the text selection in the external application, and the selected text is being translated on the fly. Moreover, for each tested DE/WM, at least one configuration makes the scan popup window work perfectly as far as I am concerned. This issue was partially worked around with a 200ms scan popup delay timer in the recent commit 58e41fe3ceb769cab37608e36637044e597ba1f8 for the duplicate issue #854. However the timer solution is incomplete because it requires the user to select text quickly and without delays. If global mouse selection does not change for 200ms while the left mouse button is held down, the user will likely not see the scan popup when (s)he finishes selection, and will have to try selecting again - hopefully faster this time. The 200ms delay is no longer critically important after this commit, but it is still beneficial: the lookup query changes less often, which in turn reduces article definition update frequency. So the delay improves the UI (perhaps subjectively) and performance.
2018-04-09 17:50:23 +00:00
p.scanPopupUnpinnedWindowFlags = Config::spwfFromInt( ui.scanPopupUnpinnedWindowFlags->currentIndex() );
p.scanPopupUnpinnedBypassWMHint = ui.scanPopupUnpinnedBypassWMHint->isChecked();
p.storeHistory = ui.storeHistory->isChecked();
p.maxStringsInHistory = ui.historyMaxSizeField->text().toUInt();
p.historyStoreInterval = ui.historySaveIntervalField->text().toUInt();
p.alwaysExpandOptionalParts = ui.alwaysExpandOptionalParts->isChecked();
p.favoritesStoreInterval = ui.favoritesSaveIntervalField->text().toUInt();
p.confirmFavoritesDeletion = ui.confirmFavoritesDeletion->isChecked();
p.collapseBigArticles = ui.collapseBigArticles->isChecked();
p.articleSizeLimit = ui.articleSizeLimit->value();
Add options to limit input phrase length When a long text is accidentally selected or copied while the scan popup is on, Goldendict spends a lot of CPU time to gradually create a "No translation..." article. When translation of huge (e.g. 15 MB) text from the clipboard is (accidentally) requested, Goldendict freezes for a while. Turning the added input phrase limit option on eliminates this waste of the CPU time. I have implemented these options primarily for selection and clipboard, but they also affect mouse-over translation on Windows and command line translation requests. This is mostly because I did not bother to limit the options' scope. I guess hovering over an extremely long text without spaces (e.g. Base64-encoded) could cause the same performance issue on Windows. The command-line translation could be requested from a script that integrates Goldendict with some other application, from which long text could be sent for translation by accident. I hope that the default value of 200 characters will be sufficient for just about any real-world user input in any language. The option is on by default, because the default length limit is generous and any longer text is unlikely to be sent for translation intentionally. My personal preference for the input phrase length limit is 100 symbols. ArticleView::pasteTriggered() didn't call QString::simplified() on the text retrieved from the clipboard. I assumed this was an oversight, so now it *is* called - indirectly, via Preferences::sanitizeInputPhrase().
2020-11-06 19:51:30 +00:00
p.limitInputPhraseLength = ui.limitInputPhraseLength->isChecked();
p.inputPhraseLengthLimit = ui.inputPhraseLengthLimit->value();
p.ignoreDiacritics = ui.ignoreDiacritics->isChecked();
2022-04-23 08:15:23 +00:00
p.ignorePunctuation = ui.ignorePunctuation->isChecked();
p.synonymSearchEnabled = ui.synonymSearchEnabled->isChecked();
p.maxDictionaryRefsInContextMenu = ui.maxDictsInContextMenu->text().toInt();
p.pronounceOnLoadMain = ui.pronounceOnLoadMain->isChecked();
p.pronounceOnLoadPopup = ui.pronounceOnLoadPopup->isChecked();
p.useInternalPlayer = ui.useInternalPlayer->isChecked();
p.internalPlayerBackend.setUiName( ui.internalPlayerBackend->currentText() );
p.audioPlaybackProgram = ui.audioPlaybackProgram->text();
p.proxyServer.enabled = ui.useProxyServer->isChecked();
2014-04-01 17:00:13 +00:00
p.proxyServer.useSystemProxy = ui.systemProxy->isChecked();
p.proxyServer.type = ( Config::ProxyServer::Type ) ui.proxyType->currentIndex();
p.proxyServer.host = ui.proxyHost->text();
p.proxyServer.port = ( unsigned ) ui.proxyPort->value();
p.proxyServer.user = ui.proxyUser->text();
p.proxyServer.password = ui.proxyPassword->text();
//anki connect
p.ankiConnectServer.enabled = ui.useAnkiConnect->isChecked();
p.ankiConnectServer.host = ui.ankiHost->text();
p.ankiConnectServer.port = (unsigned)ui.ankiPort->value();
p.ankiConnectServer.deck = ui.ankiDeck->text();
p.ankiConnectServer.model = ui.ankiModel->text();
p.checkForNewReleases = ui.checkForNewReleases->isChecked();
p.disallowContentFromOtherSites = ui.disallowContentFromOtherSites->isChecked();
p.enableWebPlugins = ui.enableWebPlugins->isChecked();
p.hideGoldenDictHeader = ui.hideGoldenDictHeader->isChecked();
p.maxNetworkCacheSize = ui.maxNetworkCacheSize->value();
p.clearNetworkCacheOnExit = ui.clearNetworkCacheOnExit->isChecked();
2012-12-10 14:14:13 +00:00
p.addonStyle = ui.addonStyles->getCurrentStyle();
p.fts.enabled = ui.ftsGroupBox->isChecked();
p.fts.maxDictionarySize = ui.maxDictionarySize->value();
if( !ui.allowAard->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "AARD";
}
if( !ui.allowBGL->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "BGL";
}
if( !ui.allowDictD->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "DICTD";
}
if( !ui.allowDSL->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "DSL";
}
if( !ui.allowMDict->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "MDICT";
}
if( !ui.allowSDict->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "SDICT";
}
2015-01-22 15:17:05 +00:00
if( !ui.allowSlob->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "SLOB";
}
if( !ui.allowStardict->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "STARDICT";
}
if( !ui.allowXDXF->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "XDXF";
}
if( !ui.allowZim->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "ZIM";
}
2014-05-20 13:59:56 +00:00
if( !ui.allowEpwing->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "EPWING";
}
if( !ui.allowGls->isChecked() )
{
if( !p.fts.disabledTypes.isEmpty() )
p.fts.disabledTypes += ',';
p.fts.disabledTypes += "GLS";
}
return p;
}
void Preferences::enableScanPopupToggled( bool b )
{
ui.scanPopupModifiers->setEnabled( b && ui.enableScanPopupModifiers->isChecked() );
}
void Preferences::enableScanPopupModifiersToggled( bool b )
{
ui.scanPopupModifiers->setEnabled( b && ui.enableScanPopup->isChecked() );
if( b )
ui.showScanFlag->setChecked( false );
}
void Preferences::showScanFlagToggled( bool b )
{
if( b )
ui.enableScanPopupModifiers->setChecked( false );
}
Allow customizing unpinned scan popup window flags on X11 with Qt5 My tests in many desktop environments and window managers indicate that no single configuration works perfectly in all environments. There are also behavior differences between Qt::Popup and Qt::Tool flags, which are not exactly bugs, so I suppose users might subjectively prefer different options. Customizing the flags allows the user to prevent unpinned scan popup window flickering with Qt5 on Linux. In a way adding these options fixes issue #645, which is: the scan popup window blinks rapidly, barely noticeably in some applications, such as Calibre ebook-viewer and Chromium. In this case the scan popup window usually ends up hidden when selection ends, unless it was finished with a jerk. I have tested the new options in 9 desktop environments and window managers: at least one configuration for each eliminates #645 and makes the scan popup window work the same as with Qt4 in this regard: the popup window remains visible, text in the popup's translation line keeps up with the text selection in the external application, and the selected text is being translated on the fly. Moreover, for each tested DE/WM, at least one configuration makes the scan popup window work perfectly as far as I am concerned. This issue was partially worked around with a 200ms scan popup delay timer in the recent commit 58e41fe3ceb769cab37608e36637044e597ba1f8 for the duplicate issue #854. However the timer solution is incomplete because it requires the user to select text quickly and without delays. If global mouse selection does not change for 200ms while the left mouse button is held down, the user will likely not see the scan popup when (s)he finishes selection, and will have to try selecting again - hopefully faster this time. The 200ms delay is no longer critically important after this commit, but it is still beneficial: the lookup query changes less often, which in turn reduces article definition update frequency. So the delay improves the UI (perhaps subjectively) and performance.
2018-04-09 17:50:23 +00:00
void Preferences::on_scanPopupUnpinnedWindowFlags_currentIndexChanged( int index )
{
ui.scanPopupUnpinnedBypassWMHint->setEnabled( Config::spwfFromInt( index ) != Config::SPWF_default );
}
void Preferences::wholeAltClicked( bool b )
{
if ( b )
{
ui.leftAlt->setChecked( false );
ui.rightAlt->setChecked( false );
}
}
void Preferences::wholeCtrlClicked( bool b )
{
if ( b )
{
ui.leftCtrl->setChecked( false );
ui.rightCtrl->setChecked( false );
}
}
void Preferences::wholeShiftClicked( bool b )
{
if ( b )
{
ui.leftShift->setChecked( false );
ui.rightShift->setChecked( false );
}
}
void Preferences::sideAltClicked( bool )
{
if ( ui.leftAlt->isChecked() || ui.rightAlt->isChecked() )
ui.altKey->setChecked( false );
}
void Preferences::sideCtrlClicked( bool )
{
if ( ui.leftCtrl->isChecked() || ui.rightCtrl->isChecked() )
ui.ctrlKey->setChecked( false );
}
void Preferences::sideShiftClicked( bool )
{
if ( ui.leftShift->isChecked() || ui.rightShift->isChecked() )
ui.shiftKey->setChecked( false );
}
void Preferences::on_enableMainWindowHotkey_toggled( bool checked )
{
ui.mainWindowHotkey->setEnabled( checked );
}
void Preferences::on_enableClipboardHotkey_toggled( bool checked )
{
ui.clipboardHotkey->setEnabled( checked );
}
void Preferences::on_buttonBox_accepted()
{
if ( prevInterfaceLanguage != ui.interfaceLanguage->currentIndex() )
QMessageBox::information( this, tr( "Changing Language" ),
tr( "Restart the program to apply the language change." ) );
auto currentFontFamily = ui.fontFamilies->currentText();
if( prevWebFontFamily != currentFontFamily )
{
//reset to default font .
if( currentFontFamily.isEmpty() )
{
QWebEngineProfile::defaultProfile()->settings()->resetFontFamily( QWebEngineSettings::StandardFont );
}
else
{
QWebEngineProfile::defaultProfile()->settings()->setFontFamily( QWebEngineSettings::StandardFont,
currentFontFamily );
}
}
}
void Preferences::on_useExternalPlayer_toggled( bool enabled )
{
ui.internalPlayerBackend->setEnabled( !enabled );
ui.audioPlaybackProgram->setEnabled( enabled );
}
2014-04-01 17:00:13 +00:00
void Preferences::customProxyToggled( bool )
{
ui.customSettingsGroup->setEnabled( ui.customProxy->isChecked()
&& ui.useProxyServer->isChecked() );
}
2014-06-24 13:55:06 +00:00
void Preferences::on_maxNetworkCacheSize_valueChanged( int value )
{
ui.clearNetworkCacheOnExit->setEnabled( value != 0 );
}
void Preferences::on_collapseBigArticles_toggled( bool checked )
{
ui.articleSizeLimit->setEnabled( checked );
}
void Preferences::on_limitInputPhraseLength_toggled( bool checked )
{
ui.inputPhraseLengthLimit->setEnabled( checked );
}
2014-06-24 13:55:06 +00:00
void Preferences::helpRequested()
{
if( !helpWindow )
{
MainWindow * mainWindow = qobject_cast< MainWindow * >( parentWidget() );
if( mainWindow )
mainWindow->closeGDHelp();
helpWindow = new Help::HelpWindow( this, cfg );
if( helpWindow )
{
helpWindow->setWindowFlags( Qt::Window );
connect( helpWindow, SIGNAL( needClose() ),
this, SLOT( closeHelp() ) );
helpWindow->showHelpFor( "Preferences" );
helpWindow->show();
}
}
else
{
if( !helpWindow->isVisible() )
helpWindow->show();
helpWindow->activateWindow();
}
}
void Preferences::closeHelp()
{
if( helpWindow )
helpWindow->hide();
}