mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 20:14:05 +00:00
fix: replace suggestion list with QCompleter (#808)
* fix: replace suggestionList with QCompleter
* 🎨 apply clang-format changes
* fix: code smells
---------
Co-authored-by: xiaoyifang <xiaoyifang@users.noreply.github.com>
This commit is contained in:
parent
32a583c16a
commit
671427803a
|
@ -409,7 +409,6 @@ HEADERS += \
|
||||||
src/webmultimediadownload.hh \
|
src/webmultimediadownload.hh \
|
||||||
src/weburlrequestinterceptor.hh \
|
src/weburlrequestinterceptor.hh \
|
||||||
src/wordfinder.hh \
|
src/wordfinder.hh \
|
||||||
src/wordlist.hh \
|
|
||||||
src/zipfile.hh \
|
src/zipfile.hh \
|
||||||
thirdparty/tomlplusplus/toml++/toml.h
|
thirdparty/tomlplusplus/toml++/toml.h
|
||||||
|
|
||||||
|
@ -530,7 +529,6 @@ SOURCES += \
|
||||||
src/webmultimediadownload.cc \
|
src/webmultimediadownload.cc \
|
||||||
src/weburlrequestinterceptor.cc \
|
src/weburlrequestinterceptor.cc \
|
||||||
src/wordfinder.cc \
|
src/wordfinder.cc \
|
||||||
src/wordlist.cc \
|
|
||||||
src/zipfile.cc \
|
src/zipfile.cc \
|
||||||
thirdparty/fmt/format.cc
|
thirdparty/fmt/format.cc
|
||||||
|
|
||||||
|
|
|
@ -220,16 +220,21 @@ class WordSearchRequestInstant: public WordSearchRequest
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WordSearchRequestInstant()
|
WordSearchRequestInstant()
|
||||||
{ finish(); }
|
{
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void cancel()
|
void cancel() override {}
|
||||||
{}
|
|
||||||
|
|
||||||
vector< WordMatch > & getMatches()
|
vector< WordMatch > & getMatches()
|
||||||
{ return matches; }
|
{
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
void setUncertain( bool value )
|
void setUncertain( bool value )
|
||||||
{ uncertain = value; }
|
{
|
||||||
|
uncertain = value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A helper class for synchronous data read implementations.
|
/// A helper class for synchronous data read implementations.
|
||||||
|
|
|
@ -123,7 +123,7 @@ MediaWikiWordSearchRequest::MediaWikiWordSearchRequest( wstring const & str,
|
||||||
QNetworkAccessManager & mgr ) :
|
QNetworkAccessManager & mgr ) :
|
||||||
isCancelling( false )
|
isCancelling( false )
|
||||||
{
|
{
|
||||||
GD_DPRINTF( "request begin\n" );
|
GD_DPRINTF( "wiki request begin\n" );
|
||||||
QUrl reqUrl( url + "/api.php?action=query&list=allpages&aplimit=40&format=xml" );
|
QUrl reqUrl( url + "/api.php?action=query&list=allpages&aplimit=40&format=xml" );
|
||||||
|
|
||||||
GlobalBroadcaster::instance()->addWhitelist( reqUrl.host() );
|
GlobalBroadcaster::instance()->addWhitelist( reqUrl.host() );
|
||||||
|
@ -188,8 +188,9 @@ void MediaWikiWordSearchRequest::downloadFinished()
|
||||||
|
|
||||||
QMutexLocker _( &dataMutex );
|
QMutexLocker _( &dataMutex );
|
||||||
|
|
||||||
for( int x = 0; x < nl.length(); ++x )
|
qDebug() << "matches" << matches.size();
|
||||||
matches.push_back( gd::toWString( nl.item( x ).toElement().attribute( "title" ) ) );
|
for ( int x = 0; x < nl.length(); ++x )
|
||||||
|
matches.emplace_back( gd::toWString( nl.item( x ).toElement().attribute( "title" ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GD_DPRINTF( "done.\n" );
|
GD_DPRINTF( "done.\n" );
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
#include <QSslConfiguration>
|
#include <QSslConfiguration>
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
|
#include "weburlrequestinterceptor.hh"
|
||||||
|
#include "folding.hh"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -46,6 +48,7 @@
|
||||||
#include "help.hh"
|
#include "help.hh"
|
||||||
#include "ui_authentication.h"
|
#include "ui_authentication.h"
|
||||||
#include "resourceschemehandler.hh"
|
#include "resourceschemehandler.hh"
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
|
||||||
#include "globalregex.hh"
|
#include "globalregex.hh"
|
||||||
|
|
||||||
|
@ -55,8 +58,6 @@
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "wstring.hh"
|
|
||||||
#include "wstring_qt.hh"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QWebEngineSettings>
|
#include <QWebEngineSettings>
|
||||||
|
@ -315,22 +316,19 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||||
{
|
{
|
||||||
groupList = groupListInDock;
|
groupList = groupListInDock;
|
||||||
translateLine = ui.translateLine;
|
translateLine = ui.translateLine;
|
||||||
wordList = ui.wordList;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
groupList = groupListInToolbar;
|
groupList = groupListInToolbar;
|
||||||
translateLine = translateBox->translateLine();
|
translateLine = translateBox->translateLine();
|
||||||
wordList = translateBox->wordList();
|
|
||||||
}
|
}
|
||||||
wordList->attachFinder( &wordFinder );
|
connect( &wordFinder, &WordFinder::updated, this, &MainWindow::prefixMatchUpdated );
|
||||||
|
connect( &wordFinder, &WordFinder::finished, this, &MainWindow::prefixMatchFinished );
|
||||||
|
|
||||||
// for the old UI:
|
|
||||||
ui.wordList->setTranslateLine( ui.translateLine );
|
|
||||||
|
|
||||||
groupList->setFocusPolicy( Qt::ClickFocus );
|
groupList->setFocusPolicy( Qt::ClickFocus );
|
||||||
wordList->setFocusPolicy( Qt::ClickFocus );
|
ui.wordList->setFocusPolicy( Qt::ClickFocus );
|
||||||
|
|
||||||
wordListDefaultFont = wordList->font();
|
wordListDefaultFont = ui.wordList->font();
|
||||||
translateLineDefaultFont = translateLine->font();
|
translateLineDefaultFont = translateLine->font();
|
||||||
groupListDefaultFont = groupList->font();
|
groupListDefaultFont = groupList->font();
|
||||||
|
|
||||||
|
@ -627,7 +625,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||||
|
|
||||||
connect( ui.translateLine, &QLineEdit::textChanged, this, &MainWindow::translateInputChanged );
|
connect( ui.translateLine, &QLineEdit::textChanged, this, &MainWindow::translateInputChanged );
|
||||||
|
|
||||||
connect( translateBox->translateLine(), &QLineEdit::textChanged, this, &MainWindow::translateInputChanged );
|
connect( translateBox->translateLine(), &QLineEdit::textEdited, this, &MainWindow::translateInputChanged );
|
||||||
|
|
||||||
connect( ui.translateLine, &QLineEdit::returnPressed, [ this ]() {
|
connect( ui.translateLine, &QLineEdit::returnPressed, [ this ]() {
|
||||||
translateInputFinished( true );
|
translateInputFinished( true );
|
||||||
|
@ -638,17 +636,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||||
|
|
||||||
connect( ui.wordList, &QListWidget::itemSelectionChanged, this, &MainWindow::wordListSelectionChanged );
|
connect( ui.wordList, &QListWidget::itemSelectionChanged, this, &MainWindow::wordListSelectionChanged );
|
||||||
|
|
||||||
connect( translateBox->wordList(),
|
|
||||||
SIGNAL( itemDoubleClicked( QListWidgetItem * ) ),
|
|
||||||
this,
|
|
||||||
SLOT( wordListItemActivated( QListWidgetItem * ) ) );
|
|
||||||
|
|
||||||
connect( ui.wordList, &QListWidget::itemClicked, this, &MainWindow::wordListItemActivated );
|
connect( ui.wordList, &QListWidget::itemClicked, this, &MainWindow::wordListItemActivated );
|
||||||
|
|
||||||
connect( ui.wordList, &WordList::statusBarMessage, this, &MainWindow::showStatusBarMessage );
|
|
||||||
|
|
||||||
connect( translateBox->wordList(), &WordList::statusBarMessage, this, &MainWindow::showStatusBarMessage );
|
|
||||||
|
|
||||||
connect( ui.dictsList, &QListWidget::itemSelectionChanged, this, &MainWindow::dictsListSelectionChanged );
|
connect( ui.dictsList, &QListWidget::itemSelectionChanged, this, &MainWindow::dictsListSelectionChanged );
|
||||||
|
|
||||||
connect( ui.dictsList, &QListWidget::itemDoubleClicked, this, &MainWindow::dictsListItemActivated );
|
connect( ui.dictsList, &QListWidget::itemDoubleClicked, this, &MainWindow::dictsListItemActivated );
|
||||||
|
@ -661,10 +650,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||||
translateBox->translateLine()->installEventFilter( this );
|
translateBox->translateLine()->installEventFilter( this );
|
||||||
|
|
||||||
ui.wordList->installEventFilter( this );
|
ui.wordList->installEventFilter( this );
|
||||||
translateBox->wordList()->installEventFilter( this );
|
|
||||||
|
|
||||||
ui.wordList->viewport()->installEventFilter( this );
|
ui.wordList->viewport()->installEventFilter( this );
|
||||||
translateBox->wordList()->viewport()->installEventFilter( this );
|
|
||||||
|
|
||||||
ui.dictsList->installEventFilter( this );
|
ui.dictsList->installEventFilter( this );
|
||||||
ui.dictsList->viewport()->installEventFilter( this );
|
ui.dictsList->viewport()->installEventFilter( this );
|
||||||
|
@ -889,6 +876,83 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
|
||||||
useSmallIconsInToolbarsTriggered();
|
useSmallIconsInToolbarsTriggered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::prefixMatchUpdated()
|
||||||
|
{
|
||||||
|
updateMatchResults( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::prefixMatchFinished()
|
||||||
|
{
|
||||||
|
updateMatchResults( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateMatchResults( bool finished )
|
||||||
|
{
|
||||||
|
WordFinder::SearchResults const & results = wordFinder.getResults();
|
||||||
|
|
||||||
|
if ( cfg.preferences.searchInDock ) {
|
||||||
|
ui.wordList->setUpdatesEnabled( false );
|
||||||
|
//clear all existed items
|
||||||
|
ui.wordList->clear();
|
||||||
|
|
||||||
|
for ( const auto & result : results ) {
|
||||||
|
auto i = new QListWidgetItem( result.first, ui.wordList );
|
||||||
|
i->setToolTip( result.first );
|
||||||
|
|
||||||
|
if ( result.second ) {
|
||||||
|
QFont f = i->font();
|
||||||
|
f.setItalic( true );
|
||||||
|
i->setFont( f );
|
||||||
|
}
|
||||||
|
|
||||||
|
i->setTextAlignment( Qt::AlignLeft );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ui.wordList->count() ) {
|
||||||
|
ui.wordList->scrollToItem( ui.wordList->item( 0 ), QAbstractItemView::PositionAtTop );
|
||||||
|
ui.wordList->setCurrentItem( nullptr, QItemSelectionModel::Clear );
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.wordList->setUpdatesEnabled( true );
|
||||||
|
ui.wordList->unsetCursor();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
QStringList _results;
|
||||||
|
_results.clear();
|
||||||
|
|
||||||
|
for ( const auto & result : results ) {
|
||||||
|
_results << result.first;
|
||||||
|
}
|
||||||
|
translateBox->setModel( _results );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( finished ) {
|
||||||
|
|
||||||
|
refreshTranslateLine();
|
||||||
|
|
||||||
|
if ( !wordFinder.getErrorString().isEmpty() )
|
||||||
|
emit showStatusBarMessage( tr( "WARNING: %1" ).arg( wordFinder.getErrorString() ),
|
||||||
|
20000,
|
||||||
|
QPixmap( ":/icons/error.svg" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::refreshTranslateLine()
|
||||||
|
{
|
||||||
|
if ( !translateLine )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Visually mark the input line to mark if there's no results
|
||||||
|
bool setMark = wordFinder.getResults().empty() && !wordFinder.wasSearchUncertain();
|
||||||
|
|
||||||
|
if ( translateLine->property( "noResults" ).toBool() != setMark ) {
|
||||||
|
translateLine->setProperty( "noResults", setMark );
|
||||||
|
|
||||||
|
Utils::Widget::setNoResultColor( translateLine, setMark );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::clipboardChange( QClipboard::Mode m )
|
void MainWindow::clipboardChange( QClipboard::Mode m )
|
||||||
{
|
{
|
||||||
if ( !scanPopup ) {
|
if ( !scanPopup ) {
|
||||||
|
@ -963,9 +1027,10 @@ void MainWindow::updateSearchPaneAndBar( bool searchInDock )
|
||||||
|
|
||||||
groupList = groupListInDock;
|
groupList = groupListInDock;
|
||||||
translateLine = ui.translateLine;
|
translateLine = ui.translateLine;
|
||||||
wordList = ui.wordList;
|
|
||||||
|
|
||||||
translateBoxToolBarAction->setVisible( false );
|
translateBoxToolBarAction->setVisible( false );
|
||||||
|
|
||||||
|
translateBox->setPopupEnabled( false );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -988,7 +1053,6 @@ void MainWindow::updateSearchPaneAndBar( bool searchInDock )
|
||||||
|
|
||||||
groupList = groupListInToolbar;
|
groupList = groupListInToolbar;
|
||||||
translateLine = translateBox->translateLine();
|
translateLine = translateBox->translateLine();
|
||||||
wordList = translateBox->wordList();
|
|
||||||
|
|
||||||
translateBoxToolBarAction->setVisible( true );
|
translateBoxToolBarAction->setVisible( true );
|
||||||
}
|
}
|
||||||
|
@ -1003,8 +1067,6 @@ void MainWindow::updateSearchPaneAndBar( bool searchInDock )
|
||||||
// reset the flag when switching UI modes
|
// reset the flag when switching UI modes
|
||||||
wordListSelChanged = false;
|
wordListSelChanged = false;
|
||||||
|
|
||||||
wordList->attachFinder( &wordFinder );
|
|
||||||
|
|
||||||
updateGroupList();
|
updateGroupList();
|
||||||
applyWordsZoomLevel();
|
applyWordsZoomLevel();
|
||||||
|
|
||||||
|
@ -1014,7 +1076,6 @@ void MainWindow::updateSearchPaneAndBar( bool searchInDock )
|
||||||
|
|
||||||
void MainWindow::mousePressEvent( QMouseEvent * event )
|
void MainWindow::mousePressEvent( QMouseEvent * event )
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( handleBackForwardMouseButtons( event ) ) {
|
if ( handleBackForwardMouseButtons( event ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2197,7 +2258,7 @@ void MainWindow::updateCurrentGroupProperty()
|
||||||
|
|
||||||
if ( grp && translateLine->property( "currentGroup" ).toString() != grp->name ) {
|
if ( grp && translateLine->property( "currentGroup" ).toString() != grp->name ) {
|
||||||
translateLine->setProperty( "currentGroup", grp->name );
|
translateLine->setProperty( "currentGroup", grp->name );
|
||||||
wordList->setProperty( "currentGroup", grp->name );
|
ui.wordList->setProperty( "currentGroup", grp->name );
|
||||||
QString ss = styleSheet();
|
QString ss = styleSheet();
|
||||||
|
|
||||||
// Only update stylesheet if it mentions currentGroup, as updating the
|
// Only update stylesheet if it mentions currentGroup, as updating the
|
||||||
|
@ -2231,8 +2292,8 @@ void MainWindow::updateSuggestionList( QString const & newValue )
|
||||||
// If some word is selected in the word list, unselect it. This prevents
|
// If some word is selected in the word list, unselect it. This prevents
|
||||||
// triggering a set of spurious activation signals when the list changes.
|
// triggering a set of spurious activation signals when the list changes.
|
||||||
|
|
||||||
if ( wordList->selectionModel()->hasSelection() )
|
if ( ui.wordList->selectionModel()->hasSelection() )
|
||||||
wordList->setCurrentItem( 0, QItemSelectionModel::Clear );
|
ui.wordList->setCurrentItem( 0, QItemSelectionModel::Clear );
|
||||||
|
|
||||||
QString req = newValue.trimmed();
|
QString req = newValue.trimmed();
|
||||||
|
|
||||||
|
@ -2240,8 +2301,8 @@ void MainWindow::updateSuggestionList( QString const & newValue )
|
||||||
{
|
{
|
||||||
// An empty request always results in an empty result
|
// An empty request always results in an empty result
|
||||||
wordFinder.cancel();
|
wordFinder.cancel();
|
||||||
wordList->clear();
|
ui.wordList->clear();
|
||||||
wordList->unsetCursor();
|
ui.wordList->unsetCursor();
|
||||||
|
|
||||||
// Reset the noResults mark if it's on right now
|
// Reset the noResults mark if it's on right now
|
||||||
if ( translateLine->property( "noResults" ).toBool() )
|
if ( translateLine->property( "noResults" ).toBool() )
|
||||||
|
@ -2253,8 +2314,7 @@ void MainWindow::updateSuggestionList( QString const & newValue )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wordList->setCursor( Qt::WaitCursor );
|
ui.wordList->setCursor( Qt::WaitCursor );
|
||||||
|
|
||||||
wordFinder.prefixMatch( req, getActiveDicts() );
|
wordFinder.prefixMatch( req, getActiveDicts() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2393,19 +2453,14 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
|
||||||
if ( ev->type() == QEvent::MouseButtonPress ) {
|
if ( ev->type() == QEvent::MouseButtonPress ) {
|
||||||
QMouseEvent * event = static_cast< QMouseEvent * >( ev );
|
QMouseEvent * event = static_cast< QMouseEvent * >( ev );
|
||||||
|
|
||||||
// clicks outside of the word list should hide it.
|
|
||||||
if ( obj != translateBox->wordList() && obj != translateBox->wordList()->viewport() ) {
|
|
||||||
translateBox->setPopupEnabled( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
return handleBackForwardMouseButtons( event );
|
return handleBackForwardMouseButtons( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ev->type() == QEvent::KeyPress ) {
|
if ( ev->type() == QEvent::KeyPress ) {
|
||||||
QKeyEvent * keyevent = static_cast< QKeyEvent * >( ev );
|
auto keyevent = dynamic_cast< QKeyEvent * >( ev );
|
||||||
|
|
||||||
bool handleCtrlTab = ( obj == translateLine || obj == wordList || obj == ui.historyList || obj == ui.favoritesTree
|
bool handleCtrlTab = ( obj == translateLine || obj == ui.wordList || obj == ui.historyList
|
||||||
|| obj == ui.dictsList || obj == groupList );
|
|| obj == ui.favoritesTree || obj == ui.dictsList || obj == groupList );
|
||||||
|
|
||||||
if ( keyevent->modifiers() == Qt::ControlModifier && keyevent->key() == Qt::Key_Tab ) {
|
if ( keyevent->modifiers() == Qt::ControlModifier && keyevent->key() == Qt::Key_Tab ) {
|
||||||
if ( cfg.preferences.mruTabOrder ) {
|
if ( cfg.preferences.mruTabOrder ) {
|
||||||
|
@ -2436,10 +2491,10 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
|
||||||
|
|
||||||
if ( cfg.preferences.searchInDock )
|
if ( cfg.preferences.searchInDock )
|
||||||
{
|
{
|
||||||
if ( keyEvent->matches( QKeySequence::MoveToNextLine ) && wordList->count() )
|
if ( keyEvent->matches( QKeySequence::MoveToNextLine ) && ui.wordList->count() )
|
||||||
{
|
{
|
||||||
wordList->setFocus( Qt::ShortcutFocusReason );
|
ui.wordList->setFocus( Qt::ShortcutFocusReason );
|
||||||
wordList->setCurrentRow( 0, QItemSelectionModel::ClearAndSelect );
|
ui.wordList->setCurrentRow( 0, QItemSelectionModel::ClearAndSelect );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2451,18 +2506,18 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( obj == wordList ) {
|
else if ( obj == ui.wordList ) {
|
||||||
if ( ev->type() == QEvent::KeyPress ) {
|
if ( ev->type() == QEvent::KeyPress ) {
|
||||||
QKeyEvent * keyEvent = static_cast< QKeyEvent * >( ev );
|
QKeyEvent * keyEvent = static_cast< QKeyEvent * >( ev );
|
||||||
|
|
||||||
if ( keyEvent->matches( QKeySequence::MoveToPreviousLine ) && !wordList->currentRow() ) {
|
if ( keyEvent->matches( QKeySequence::MoveToPreviousLine ) && !ui.wordList->currentRow() ) {
|
||||||
wordList->setCurrentRow( 0, QItemSelectionModel::Clear );
|
ui.wordList->setCurrentRow( 0, QItemSelectionModel::Clear );
|
||||||
translateLine->setFocus( Qt::ShortcutFocusReason );
|
translateLine->setFocus( Qt::ShortcutFocusReason );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( keyEvent->matches( QKeySequence::InsertParagraphSeparator ) &&
|
if ( keyEvent->matches( QKeySequence::InsertParagraphSeparator ) &&
|
||||||
wordList->selectedItems().size() )
|
ui.wordList->selectedItems().size() )
|
||||||
{
|
{
|
||||||
if ( cfg.preferences.searchInDock )
|
if ( cfg.preferences.searchInDock )
|
||||||
{
|
{
|
||||||
|
@ -2508,7 +2563,7 @@ void MainWindow::wordListItemActivated( QListWidgetItem * item )
|
||||||
|
|
||||||
void MainWindow::wordListSelectionChanged()
|
void MainWindow::wordListSelectionChanged()
|
||||||
{
|
{
|
||||||
QList< QListWidgetItem * > selected = wordList->selectedItems();
|
QList< QListWidgetItem * > selected = ui.wordList->selectedItems();
|
||||||
|
|
||||||
if ( selected.size() )
|
if ( selected.size() )
|
||||||
{
|
{
|
||||||
|
@ -3438,8 +3493,8 @@ void MainWindow::applyWordsZoomLevel()
|
||||||
font.setPointSize( ps );
|
font.setPointSize( ps );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( wordList->font().pointSize() != ps )
|
if ( ui.wordList->font().pointSize() != ps )
|
||||||
wordList->setFont( font );
|
ui.wordList->setFont( font );
|
||||||
|
|
||||||
font = translateLineDefaultFont;
|
font = translateLineDefaultFont;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "folding.hh"
|
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "dict/dictionary.hh"
|
#include "dict/dictionary.hh"
|
||||||
#include "article_netmgr.hh"
|
#include "article_netmgr.hh"
|
||||||
|
@ -26,13 +25,11 @@
|
||||||
#include "mainstatusbar.hh"
|
#include "mainstatusbar.hh"
|
||||||
#include "mruqmenu.hh"
|
#include "mruqmenu.hh"
|
||||||
#include "translatebox.hh"
|
#include "translatebox.hh"
|
||||||
#include "wordlist.hh"
|
|
||||||
#include "dictheadwords.hh"
|
#include "dictheadwords.hh"
|
||||||
#include "fulltextsearch.hh"
|
#include "fulltextsearch.hh"
|
||||||
#include "base_type.hh"
|
#include "base_type.hh"
|
||||||
|
|
||||||
#include "hotkeywrapper.hh"
|
#include "hotkeywrapper.hh"
|
||||||
#include "weburlrequestinterceptor.hh"
|
|
||||||
#include "resourceschemehandler.hh"
|
#include "resourceschemehandler.hh"
|
||||||
#include "iframeschemehandler.hh"
|
#include "iframeschemehandler.hh"
|
||||||
#ifdef HAVE_X11
|
#ifdef HAVE_X11
|
||||||
|
@ -141,7 +138,7 @@ private:
|
||||||
// in a separate thread
|
// in a separate thread
|
||||||
AudioPlayerFactory audioPlayerFactory;
|
AudioPlayerFactory audioPlayerFactory;
|
||||||
|
|
||||||
WordList * wordList;
|
//current active translateLine;
|
||||||
QLineEdit * translateLine;
|
QLineEdit * translateLine;
|
||||||
|
|
||||||
WordFinder wordFinder;
|
WordFinder wordFinder;
|
||||||
|
@ -462,7 +459,10 @@ private slots:
|
||||||
void clipboardChange( QClipboard::Mode m );
|
void clipboardChange( QClipboard::Mode m );
|
||||||
|
|
||||||
void inspectElement( QWebEnginePage * );
|
void inspectElement( QWebEnginePage * );
|
||||||
|
void prefixMatchUpdated();
|
||||||
|
void prefixMatchFinished();
|
||||||
|
void updateMatchResults( bool finished );
|
||||||
|
void refreshTranslateLine();
|
||||||
signals:
|
signals:
|
||||||
/// Retranslate Ctrl(Shift) + Click on dictionary pane to dictionary toolbar
|
/// Retranslate Ctrl(Shift) + Click on dictionary pane to dictionary toolbar
|
||||||
void clickOnDictPane( QString const & id );
|
void clickOnDictPane( QString const & id );
|
||||||
|
|
|
@ -192,7 +192,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="WordList" name="wordList"/>
|
<widget class="QListWidget" name="wordList"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -607,11 +607,6 @@
|
||||||
<header>historypanewidget.hh</header>
|
<header>historypanewidget.hh</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>WordList</class>
|
|
||||||
<extends>QListWidget</extends>
|
|
||||||
<header>wordlist.hh</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>FavoritesPaneWidget</class>
|
<class>FavoritesPaneWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
|
|
|
@ -111,14 +111,12 @@ ScanPopup::ScanPopup( QWidget * parent,
|
||||||
connect( definition, &ArticleView::sendWordToHistory, this, &ScanPopup::sendWordToHistory );
|
connect( definition, &ArticleView::sendWordToHistory, this, &ScanPopup::sendWordToHistory );
|
||||||
connect( definition, &ArticleView::typingEvent, this, &ScanPopup::typingEvent );
|
connect( definition, &ArticleView::typingEvent, this, &ScanPopup::typingEvent );
|
||||||
|
|
||||||
wordListDefaultFont = ui.translateBox->wordList()->font();
|
wordListDefaultFont = ui.translateBox->completerWidget()->font();
|
||||||
translateLineDefaultFont = ui.translateBox->font();
|
translateLineDefaultFont = ui.translateBox->font();
|
||||||
groupListDefaultFont = ui.groupList->font();
|
groupListDefaultFont = ui.groupList->font();
|
||||||
|
|
||||||
ui.mainLayout->addWidget( definition );
|
ui.mainLayout->addWidget( definition );
|
||||||
|
|
||||||
ui.translateBox->wordList()->attachFinder( &wordFinder );
|
|
||||||
ui.translateBox->wordList()->setFocusPolicy(Qt::ClickFocus);
|
|
||||||
ui.translateBox->translateLine()->installEventFilter( this );
|
ui.translateBox->translateLine()->installEventFilter( this );
|
||||||
definition->installEventFilter(this);
|
definition->installEventFilter(this);
|
||||||
this->installEventFilter(this);
|
this->installEventFilter(this);
|
||||||
|
@ -127,15 +125,6 @@ ScanPopup::ScanPopup( QWidget * parent,
|
||||||
|
|
||||||
connect( ui.translateBox->translateLine(), &QLineEdit::returnPressed, this, &ScanPopup::translateInputFinished );
|
connect( ui.translateBox->translateLine(), &QLineEdit::returnPressed, this, &ScanPopup::translateInputFinished );
|
||||||
|
|
||||||
connect( ui.translateBox->wordList(), &QListWidget::itemClicked, this, &ScanPopup::wordListItemActivated );
|
|
||||||
|
|
||||||
connect( ui.translateBox->wordList(),
|
|
||||||
SIGNAL( itemDoubleClicked( QListWidgetItem * ) ),
|
|
||||||
this,
|
|
||||||
SLOT( wordListItemActivated( QListWidgetItem * ) ) );
|
|
||||||
|
|
||||||
connect( ui.translateBox->wordList(), &WordList::statusBarMessage, this, &ScanPopup::showStatusBarMessage );
|
|
||||||
|
|
||||||
ui.pronounceButton->setDisabled( true );
|
ui.pronounceButton->setDisabled( true );
|
||||||
|
|
||||||
ui.groupList->fill( groups );
|
ui.groupList->fill( groups );
|
||||||
|
@ -155,7 +144,7 @@ ScanPopup::ScanPopup( QWidget * parent,
|
||||||
Config::Group * grp = cfg.getGroup( cfg.lastPopupGroupId );
|
Config::Group * grp = cfg.getGroup( cfg.lastPopupGroupId );
|
||||||
if( igrp && grp )
|
if( igrp && grp )
|
||||||
igrp->checkMutedDictionaries( &grp->popupMutedDictionaries );
|
igrp->checkMutedDictionaries( &grp->popupMutedDictionaries );
|
||||||
dictionaryBar.setMutedDictionaries( grp ? &grp->popupMutedDictionaries : 0 );
|
dictionaryBar.setMutedDictionaries( grp ? &grp->popupMutedDictionaries : nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
addToolBar( Qt::RightToolBarArea, &dictionaryBar );
|
addToolBar( Qt::RightToolBarArea, &dictionaryBar );
|
||||||
|
@ -280,10 +269,9 @@ ScanPopup::ScanPopup( QWidget * parent,
|
||||||
#ifdef HAVE_X11
|
#ifdef HAVE_X11
|
||||||
scanFlag = new ScanFlag( this );
|
scanFlag = new ScanFlag( this );
|
||||||
|
|
||||||
connect( scanFlag, &ScanFlag::requestScanPopup,
|
connect( scanFlag, &ScanFlag::requestScanPopup, this, [ this ] {
|
||||||
this, [=]{
|
|
||||||
translateWordFromSelection();
|
translateWordFromSelection();
|
||||||
});
|
} );
|
||||||
|
|
||||||
// Use delay show to prevent multiple popups while selection in progress
|
// Use delay show to prevent multiple popups while selection in progress
|
||||||
selectionDelayTimer.setSingleShot( true );
|
selectionDelayTimer.setSingleShot( true );
|
||||||
|
@ -362,11 +350,11 @@ void ScanPopup::applyWordsZoomLevel()
|
||||||
font.setPointSize( ps );
|
font.setPointSize( ps );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ui.translateBox->wordList()->font().pointSize() != ps )
|
if ( ui.translateBox->completerWidget()->font().pointSize() != ps )
|
||||||
ui.translateBox->wordList()->setFont( font );
|
ui.translateBox->completerWidget()->setFont( font );
|
||||||
|
|
||||||
font = translateLineDefaultFont;
|
font = translateLineDefaultFont;
|
||||||
ps = font.pointSize();
|
ps = font.pointSize();
|
||||||
|
|
||||||
if ( cfg.preferences.wordsZoomLevel != 0 )
|
if ( cfg.preferences.wordsZoomLevel != 0 )
|
||||||
{
|
{
|
||||||
|
@ -413,12 +401,12 @@ Qt::WindowFlags ScanPopup::unpinnedWindowFlags() const
|
||||||
|
|
||||||
void ScanPopup::translateWordFromClipboard()
|
void ScanPopup::translateWordFromClipboard()
|
||||||
{
|
{
|
||||||
return translateWordFromClipboard(QClipboard::Clipboard);
|
return translateWordFromClipboard( QClipboard::Clipboard );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanPopup::translateWordFromSelection()
|
void ScanPopup::translateWordFromSelection()
|
||||||
{
|
{
|
||||||
return translateWordFromClipboard(QClipboard::Selection);
|
return translateWordFromClipboard( QClipboard::Selection );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanPopup::editGroupRequested()
|
void ScanPopup::editGroupRequested()
|
||||||
|
@ -627,7 +615,7 @@ void ScanPopup::currentGroupChanged( int )
|
||||||
dictionaryBar.setMutedDictionaries( &grp->popupMutedDictionaries );
|
dictionaryBar.setMutedDictionaries( &grp->popupMutedDictionaries );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dictionaryBar.setMutedDictionaries( 0 );
|
dictionaryBar.setMutedDictionaries( nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDictionaryBar();
|
updateDictionaryBar();
|
||||||
|
@ -641,11 +629,6 @@ void ScanPopup::currentGroupChanged( int )
|
||||||
cfg.lastPopupGroupId = ui.groupList->getCurrentGroup();
|
cfg.lastPopupGroupId = ui.groupList->getCurrentGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanPopup::wordListItemActivated( QListWidgetItem * item )
|
|
||||||
{
|
|
||||||
showTranslationFor( item->text() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScanPopup::translateInputChanged( QString const & text )
|
void ScanPopup::translateInputChanged( QString const & text )
|
||||||
{
|
{
|
||||||
updateSuggestionList( text );
|
updateSuggestionList( text );
|
||||||
|
@ -659,7 +642,6 @@ void ScanPopup::updateSuggestionList()
|
||||||
void ScanPopup::updateSuggestionList( QString const & text )
|
void ScanPopup::updateSuggestionList( QString const & text )
|
||||||
{
|
{
|
||||||
mainStatusBar->clearMessage();
|
mainStatusBar->clearMessage();
|
||||||
ui.translateBox->wordList()->setCurrentItem( 0, QItemSelectionModel::Clear );
|
|
||||||
|
|
||||||
QString req = text.trimmed();
|
QString req = text.trimmed();
|
||||||
|
|
||||||
|
@ -667,8 +649,6 @@ void ScanPopup::updateSuggestionList( QString const & text )
|
||||||
{
|
{
|
||||||
// An empty request always results in an empty result
|
// An empty request always results in an empty result
|
||||||
wordFinder.cancel();
|
wordFinder.cancel();
|
||||||
ui.translateBox->wordList()->clear();
|
|
||||||
ui.translateBox->wordList()->unsetCursor();
|
|
||||||
|
|
||||||
// Reset the noResults mark if it's on right now
|
// Reset the noResults mark if it's on right now
|
||||||
if ( ui.translateBox->translateLine()->property( "noResults" ).toBool() )
|
if ( ui.translateBox->translateLine()->property( "noResults" ).toBool() )
|
||||||
|
@ -681,8 +661,6 @@ void ScanPopup::updateSuggestionList( QString const & text )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.translateBox->wordList()->setCursor( Qt::WaitCursor );
|
|
||||||
|
|
||||||
wordFinder.prefixMatch( req, getActiveDicts() );
|
wordFinder.prefixMatch( req, getActiveDicts() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,9 +937,20 @@ void ScanPopup::prefixMatchFinished()
|
||||||
{
|
{
|
||||||
ui.queryError->setToolTip( wordFinder.getErrorString() );
|
ui.queryError->setToolTip( wordFinder.getErrorString() );
|
||||||
ui.queryError->show();
|
ui.queryError->show();
|
||||||
|
showStatusBarMessage( tr( "WARNING: %1" ).arg( wordFinder.getErrorString() ),
|
||||||
|
20000,
|
||||||
|
QPixmap( ":/icons/error.svg" ) );
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
ui.queryError->hide();
|
ui.queryError->hide();
|
||||||
|
auto results = wordFinder.getResults();
|
||||||
|
QStringList _results;
|
||||||
|
for ( auto const & [ fst, snd ] : results ) {
|
||||||
|
_results << fst;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.translateBox->setModel( _results );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,10 +1110,9 @@ void ScanPopup::updateDictionaryBar()
|
||||||
|
|
||||||
if( currentId == Instances::Group::AllGroupId )
|
if( currentId == Instances::Group::AllGroupId )
|
||||||
dictionaryBar.setMutedDictionaries( &cfg.popupMutedDictionaries );
|
dictionaryBar.setMutedDictionaries( &cfg.popupMutedDictionaries );
|
||||||
else
|
else {
|
||||||
{
|
Config::Group * group = cfg.getGroup( currentId );
|
||||||
Config::Group * grp = cfg.getGroup( currentId );
|
dictionaryBar.setMutedDictionaries( group ? &group->popupMutedDictionaries : nullptr );
|
||||||
dictionaryBar.setMutedDictionaries( grp ? &grp->popupMutedDictionaries : 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setDictionaryIconSize();
|
setDictionaryIconSize();
|
||||||
|
|
|
@ -222,7 +222,6 @@ private slots:
|
||||||
|
|
||||||
void translateInputChanged(QString const & text);
|
void translateInputChanged(QString const & text);
|
||||||
void translateInputFinished();
|
void translateInputFinished();
|
||||||
void wordListItemActivated( QListWidgetItem * );
|
|
||||||
|
|
||||||
void focusTranslateLine();
|
void focusTranslateLine();
|
||||||
|
|
||||||
|
|
|
@ -11,209 +11,50 @@
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
|
#include <QStringListModel>
|
||||||
namespace
|
|
||||||
{
|
|
||||||
#define MAX_POPUP_ROWS 17
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletionList::CompletionList(TranslateBox * parent) : WordList(parent),
|
|
||||||
translateBox(parent)
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
setWindowFlags(Qt::ToolTip);
|
|
||||||
#else
|
|
||||||
setParent( parent->window() );
|
|
||||||
setAutoFillBackground( true );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
connect( this, &QAbstractItemView::activated, this, &CompletionList::acceptCurrentEntry );
|
|
||||||
|
|
||||||
connect( this, &QListWidget::itemClicked, this, &CompletionList::acceptCurrentEntry );
|
|
||||||
|
|
||||||
translateBox->window()->installEventFilter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CompletionList::eventFilter( QObject * obj, QEvent * ev )
|
|
||||||
{
|
|
||||||
// when the main window is moved or resized, hide the word list suggestions
|
|
||||||
if ( obj != this && !isAncestorOf( qobject_cast< QWidget * >( obj ) )
|
|
||||||
&& ( ev->type() == QEvent::Move || ev->type() == QEvent::Resize ) )
|
|
||||||
{
|
|
||||||
translateBox->setPopupEnabled( false );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QWidget::eventFilter( obj, ev );
|
|
||||||
}
|
|
||||||
|
|
||||||
int CompletionList::preferredHeight() const
|
|
||||||
{
|
|
||||||
#if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
|
|
||||||
const QSize itemSizeHint = itemDelegate()->sizeHint( viewOptions(), model()->index( 0, 0 ) );
|
|
||||||
#else
|
|
||||||
QStyleOptionViewItem option;
|
|
||||||
initViewItemOption( &option );
|
|
||||||
const QSize itemSizeHint = itemDelegate()->sizeHint(option, model()->index( 0, 0 ) );
|
|
||||||
#endif
|
|
||||||
int rows = qMin( count(), MAX_POPUP_ROWS );
|
|
||||||
|
|
||||||
int scrollBarHeight = 0;
|
|
||||||
|
|
||||||
bool hBarIsVisible = horizontalScrollBar()->maximum() > 0;
|
|
||||||
|
|
||||||
if ( hBarIsVisible )
|
|
||||||
scrollBarHeight += QApplication::style()->pixelMetric( QStyle::PM_ScrollBarExtent );
|
|
||||||
|
|
||||||
return rows == 0 ? 0 : itemSizeHint.height() * rows + frameWidth() * 2 + scrollBarHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CompletionList::acceptCurrentEntry()
|
|
||||||
{
|
|
||||||
if (!isVisible())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QModelIndex index = currentIndex();
|
|
||||||
if ( !index.isValid() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit doubleClicked(index);
|
|
||||||
translateBox->setPopupEnabled( false );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TranslateBox::TranslateBox( QWidget * parent ):
|
TranslateBox::TranslateBox( QWidget * parent ):
|
||||||
QWidget( parent ),
|
QWidget( parent ),
|
||||||
word_list( new CompletionList( this ) ),
|
translate_line( new QLineEdit( this ) ),
|
||||||
translate_line( new QLineEdit( this ) ),
|
m_popupEnabled( false )
|
||||||
m_popupEnabled( false )
|
|
||||||
{
|
{
|
||||||
// initially hidden
|
completer = new QCompleter( words, this );
|
||||||
word_list->hide();
|
resize( 200, 90 );
|
||||||
|
QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred );
|
||||||
|
sizePolicy.setHorizontalStretch( 0 );
|
||||||
|
sizePolicy.setVerticalStretch( 0 );
|
||||||
|
setSizePolicy( sizePolicy );
|
||||||
|
|
||||||
resize(200, 90);
|
setFocusProxy( translate_line );
|
||||||
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
translate_line->setObjectName( "translateLine" );
|
||||||
sizePolicy.setHorizontalStretch(0);
|
|
||||||
sizePolicy.setVerticalStretch(0);
|
|
||||||
setSizePolicy(sizePolicy);
|
|
||||||
// setMinimumSize(QSize(800, 0));
|
|
||||||
|
|
||||||
setFocusProxy(translate_line);
|
|
||||||
translate_line->setObjectName("translateLine");
|
|
||||||
translate_line->setPlaceholderText( tr( "Type a word or phrase to search dictionaries" ) );
|
translate_line->setPlaceholderText( tr( "Type a word or phrase to search dictionaries" ) );
|
||||||
word_list->setTranslateLine(translate_line);
|
|
||||||
|
|
||||||
// completer = new QCompleter(m_completionList->model(), this);
|
auto layout = new QHBoxLayout( this );
|
||||||
// completer->setCaseSensitivity(Qt::CaseInsensitive);
|
setLayout( layout );
|
||||||
// completer->setCompletionMode(QCompleter::InlineCompletion);
|
layout->setContentsMargins( 0, 0, 0, 0 );
|
||||||
|
layout->addWidget( translate_line );
|
||||||
|
|
||||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
auto dropdown = new QAction( QIcon( ":/icons/1downarrow.svg" ), tr( "Drop-down" ), this );
|
||||||
setLayout(layout);
|
connect( dropdown, &QAction::triggered, this, &TranslateBox::rightButtonClicked );
|
||||||
layout->setContentsMargins(0,0,0,0);
|
|
||||||
layout->addWidget(translate_line);
|
|
||||||
|
|
||||||
QAction * dropdown = new QAction( QIcon(":/icons/1downarrow.svg"), tr("Drop-down"),this);
|
translate_line->addAction( dropdown, QLineEdit::TrailingPosition );
|
||||||
connect( dropdown,&QAction::triggered,this, &TranslateBox::rightButtonClicked );
|
translate_line->addAction( new QAction( QIcon( ":/icons/system-search.svg" ), "", this ),
|
||||||
|
QLineEdit::LeadingPosition );
|
||||||
|
|
||||||
translate_line->addAction( dropdown,QLineEdit::TrailingPosition);
|
translate_line->setFocusPolicy( Qt::ClickFocus );
|
||||||
translate_line->addAction( new QAction(QIcon(":/icons/system-search.svg"),"",this),QLineEdit::LeadingPosition);
|
|
||||||
|
|
||||||
translate_line->setFocusPolicy(Qt::ClickFocus);
|
|
||||||
|
|
||||||
translate_line->installEventFilter( this );
|
translate_line->installEventFilter( this );
|
||||||
this->installEventFilter( this );
|
|
||||||
|
|
||||||
connect( translate_line, &QLineEdit::textChanged, this, &TranslateBox::onTextEdit );
|
translate_line->setCompleter( completer );
|
||||||
|
completer->setCompletionMode( QCompleter::UnfilteredPopupCompletion );
|
||||||
|
completer->setMaxVisibleItems( 16 );
|
||||||
|
|
||||||
|
connect( completer, QOverload< const QString & >::of( &QCompleter::activated ), this, [ = ]( const QString & text ) {
|
||||||
connect( word_list, &WordList::contentChanged, this, &TranslateBox::showPopup );
|
emit translate_line->returnPressed();
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslateBox::eventFilter(QObject *obj, QEvent *event)
|
void TranslateBox::setText( const QString & text, bool showPopup )
|
||||||
{
|
|
||||||
// hide the suggestions list when the window is not active
|
|
||||||
if ( event->type() == QEvent::WindowDeactivate )
|
|
||||||
{
|
|
||||||
if (!word_list->isActiveWindow())
|
|
||||||
{
|
|
||||||
setPopupEnabled( false );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj == translate_line && event->type() == QEvent::KeyPress) {
|
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
|
||||||
switch (keyEvent->key()) {
|
|
||||||
case Qt::Key_Up:
|
|
||||||
case Qt::Key_Down:
|
|
||||||
case Qt::Key_PageUp:
|
|
||||||
case Qt::Key_PageDown:
|
|
||||||
if ( !word_list->isVisible() )
|
|
||||||
{
|
|
||||||
setPopupEnabled( true );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QApplication::sendEvent(word_list, event);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case Qt::Key_Enter:
|
|
||||||
case Qt::Key_Return:
|
|
||||||
return word_list->acceptCurrentEntry();
|
|
||||||
case Qt::Key_Escape:
|
|
||||||
setPopupEnabled( false );
|
|
||||||
return true;
|
|
||||||
case Qt::Key_Tab:
|
|
||||||
if ( !word_list->isVisible() )
|
|
||||||
{
|
|
||||||
setPopupEnabled( true );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QKeyEvent event( QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier );
|
|
||||||
QApplication::sendEvent( word_list, &event );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case Qt::Key_Backtab:
|
|
||||||
if ( !word_list->isVisible() )
|
|
||||||
{
|
|
||||||
setPopupEnabled( true );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QKeyEvent event( QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier );
|
|
||||||
QApplication::sendEvent( word_list, &event );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (obj == translate_line && event->type() == QEvent::FocusOut) {
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
QFocusEvent *fev = static_cast<QFocusEvent*>(event);
|
|
||||||
if (fev->reason() != Qt::ActiveWindowFocusReason ||
|
|
||||||
(fev->reason() == Qt::ActiveWindowFocusReason && !word_list->isActiveWindow()))
|
|
||||||
#endif
|
|
||||||
setPopupEnabled( false );
|
|
||||||
} else if (obj == translate_line && event->type() == QEvent::FocusIn) {
|
|
||||||
// By default, focusing the traslate line does not show
|
|
||||||
// the popup window.
|
|
||||||
} else if (obj == this && event->type() == QEvent::ShortcutOverride) {
|
|
||||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
|
||||||
if (ke->key() == Qt::Key_Escape && !ke->modifiers() && word_list->isVisible() ) {
|
|
||||||
event->accept();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QWidget::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TranslateBox::setText( QString text, bool showPopup )
|
|
||||||
{
|
{
|
||||||
setPopupEnabled( showPopup );
|
setPopupEnabled( showPopup );
|
||||||
translate_line->setText( text );
|
translate_line->setText( text );
|
||||||
|
@ -232,56 +73,22 @@ void TranslateBox::setSizePolicy( QSizePolicy policy )
|
||||||
translate_line->setSizePolicy( policy );
|
translate_line->setSizePolicy( policy );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TranslateBox::setModel( QStringList & _words )
|
||||||
|
{
|
||||||
|
auto model = (QStringListModel *)( completer->model() );
|
||||||
|
|
||||||
|
model->setStringList( _words );
|
||||||
|
}
|
||||||
|
|
||||||
void TranslateBox::showPopup()
|
void TranslateBox::showPopup()
|
||||||
{
|
{
|
||||||
// completer->setCompletionPrefix( m_fileLineEdit->text() );
|
if ( m_popupEnabled ) {
|
||||||
// qDebug() << "COMPLETION:" << completer->currentCompletion();
|
completer->popup()->show();
|
||||||
|
completer->complete();
|
||||||
// Don't allow recursive call
|
|
||||||
if( translateBoxMutex.tryLock() )
|
|
||||||
translateBoxMutex.unlock();
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
QMutexLocker _( &translateBoxMutex );
|
|
||||||
|
|
||||||
if (translate_line->text().trimmed().isEmpty() || word_list->count() == 0)
|
|
||||||
{
|
|
||||||
// nothing to show
|
|
||||||
if (word_list->isVisible())
|
|
||||||
{
|
|
||||||
word_list->hide();
|
|
||||||
translate_line->setFocus();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if ( !m_popupEnabled )
|
completer->popup()->hide();
|
||||||
{
|
|
||||||
word_list->hide();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int preferredHeight = word_list->preferredHeight();
|
|
||||||
|
|
||||||
QPoint origin( translate_line->x(), translate_line->y() + translate_line->height() );
|
|
||||||
|
|
||||||
if ( word_list->isWindow() )
|
|
||||||
{
|
|
||||||
origin = mapToGlobal( origin );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
origin = mapTo( window(), origin );
|
|
||||||
preferredHeight = qMin( translate_line->window()->height() - origin.y(), preferredHeight );
|
|
||||||
}
|
|
||||||
|
|
||||||
const QSize size(width(), preferredHeight);
|
|
||||||
const QRect rect( origin, size );
|
|
||||||
|
|
||||||
word_list->setGeometry(rect);
|
|
||||||
word_list->show();
|
|
||||||
word_list->raise();
|
|
||||||
translate_line->setFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit * TranslateBox::translateLine()
|
QLineEdit * TranslateBox::translateLine()
|
||||||
|
@ -289,18 +96,16 @@ QLineEdit * TranslateBox::translateLine()
|
||||||
return translate_line;
|
return translate_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
WordList * TranslateBox::wordList()
|
QWidget * TranslateBox::completerWidget()
|
||||||
{
|
{
|
||||||
return word_list;
|
return completer->widget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslateBox::rightButtonClicked()
|
void TranslateBox::rightButtonClicked()
|
||||||
{
|
{
|
||||||
setPopupEnabled( !m_popupEnabled );
|
setPopupEnabled( !m_popupEnabled );
|
||||||
}
|
}
|
||||||
|
void TranslateBox::setSizePolicy( QSizePolicy::Policy hor, QSizePolicy::Policy ver )
|
||||||
void TranslateBox::onTextEdit()
|
|
||||||
{
|
{
|
||||||
if ( translate_line->hasFocus() )
|
setSizePolicy( QSizePolicy( hor, ver ) );
|
||||||
setPopupEnabled( true );
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,51 +4,25 @@
|
||||||
#ifndef TRANSLATEBOX_HH
|
#ifndef TRANSLATEBOX_HH
|
||||||
#define TRANSLATEBOX_HH
|
#define TRANSLATEBOX_HH
|
||||||
|
|
||||||
#include "wordlist.hh"
|
|
||||||
|
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QFocusEvent>
|
#include <QFocusEvent>
|
||||||
|
#include <QCompleter>
|
||||||
class TranslateBox;
|
|
||||||
|
|
||||||
class CompletionList : public WordList
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
CompletionList(TranslateBox * parent);
|
|
||||||
int preferredHeight() const;
|
|
||||||
virtual void setTranslateLine(QLineEdit * line)
|
|
||||||
{
|
|
||||||
WordList::setTranslateLine( line );
|
|
||||||
setFocusProxy( line );
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
bool acceptCurrentEntry();
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual bool eventFilter( QObject *, QEvent * );
|
|
||||||
TranslateBox * translateBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TranslateBox : public QWidget
|
class TranslateBox : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TranslateBox(QWidget * parent = 0);
|
explicit TranslateBox( QWidget * parent = nullptr );
|
||||||
QLineEdit * translateLine();
|
QLineEdit * translateLine();
|
||||||
WordList * wordList();
|
QWidget * completerWidget();
|
||||||
void setText(QString text, bool showPopup=true);
|
void setText( const QString & text, bool showPopup = true );
|
||||||
void setSizePolicy(QSizePolicy policy);
|
void setSizePolicy( QSizePolicy policy );
|
||||||
inline void setSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver)
|
void setSizePolicy( QSizePolicy::Policy hor, QSizePolicy::Policy ver );
|
||||||
{ setSizePolicy(QSizePolicy(hor, ver)); }
|
|
||||||
|
|
||||||
signals:
|
void setModel( QStringList & _words );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setPopupEnabled(bool enable);
|
void setPopupEnabled(bool enable);
|
||||||
|
@ -56,15 +30,12 @@ public slots:
|
||||||
private slots:
|
private slots:
|
||||||
void showPopup();
|
void showPopup();
|
||||||
void rightButtonClicked();
|
void rightButtonClicked();
|
||||||
void onTextEdit();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool eventFilter(QObject *obj, QEvent *event);
|
|
||||||
CompletionList * word_list;
|
|
||||||
QLineEdit * translate_line;
|
QLineEdit * translate_line;
|
||||||
bool m_popupEnabled;
|
bool m_popupEnabled;
|
||||||
QMutex translateBoxMutex;
|
QCompleter * completer;
|
||||||
// QCompleter * completer; // disabled for now
|
QStringList words;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRANSLATEBOX_HH
|
#endif // TRANSLATEBOX_HH
|
||||||
|
|
|
@ -131,28 +131,23 @@ void WordFinder::startSearch()
|
||||||
|
|
||||||
allWordWritings[ 0 ] = gd::toWString( inputWord );
|
allWordWritings[ 0 ] = gd::toWString( inputWord );
|
||||||
|
|
||||||
for( size_t x = 0; x < inputDicts->size(); ++x )
|
for ( const auto & inputDict : *inputDicts ) {
|
||||||
{
|
vector< wstring > writings = inputDict->getAlternateWritings( allWordWritings[ 0 ] );
|
||||||
vector< wstring > writings = (*inputDicts)[ x ]->getAlternateWritings( allWordWritings[ 0 ] );
|
|
||||||
|
|
||||||
allWordWritings.insert( allWordWritings.end(), writings.begin(), writings.end() );
|
allWordWritings.insert( allWordWritings.end(), writings.begin(), writings.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query each dictionary for all word writings
|
// Query each dictionary for all word writings
|
||||||
|
|
||||||
for( size_t x = 0; x < inputDicts->size(); ++x )
|
for ( const auto & inputDict : *inputDicts ) {
|
||||||
{
|
if ( ( inputDict->getFeatures() & requestedFeatures ) != requestedFeatures )
|
||||||
if ( ( (*inputDicts)[ x ]->getFeatures() & requestedFeatures ) != requestedFeatures )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for( size_t y = 0; y < allWordWritings.size(); ++y )
|
for ( const auto & allWordWriting : allWordWritings ) {
|
||||||
{
|
try {
|
||||||
try
|
sptr< Dictionary::WordSearchRequest > sr = ( searchType == PrefixMatch || searchType == ExpressionMatch ) ?
|
||||||
{
|
inputDict->prefixMatch( allWordWriting, requestedMaxResults ) :
|
||||||
sptr< Dictionary::WordSearchRequest > sr =
|
inputDict->stemmedMatch( allWordWriting, stemmedMinLength, stemmedMaxSuffixVariation, requestedMaxResults );
|
||||||
( searchType == PrefixMatch || searchType == ExpressionMatch ) ?
|
|
||||||
(*inputDicts)[ x ]->prefixMatch( allWordWritings[ y ], requestedMaxResults ) :
|
|
||||||
(*inputDicts)[ x ]->stemmedMatch( allWordWritings[ y ], stemmedMinLength, stemmedMaxSuffixVariation, requestedMaxResults );
|
|
||||||
|
|
||||||
connect( sr.get(), &Dictionary::Request::finished, this, &WordFinder::requestFinished, Qt::QueuedConnection );
|
connect( sr.get(), &Dictionary::Request::finished, this, &WordFinder::requestFinished, Qt::QueuedConnection );
|
||||||
|
|
||||||
|
@ -161,7 +156,9 @@ void WordFinder::startSearch()
|
||||||
catch( std::exception & e )
|
catch( std::exception & e )
|
||||||
{
|
{
|
||||||
gdWarning( "Word \"%s\" search error (%s) in \"%s\"\n",
|
gdWarning( "Word \"%s\" search error (%s) in \"%s\"\n",
|
||||||
inputWord.toUtf8().data(), e.what(), (*inputDicts)[ x ]->getName().c_str() );
|
inputWord.toUtf8().data(),
|
||||||
|
e.what(),
|
||||||
|
inputDict->getName().c_str() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,15 +188,12 @@ void WordFinder::requestFinished()
|
||||||
bool newResults = false;
|
bool newResults = false;
|
||||||
|
|
||||||
// See how many new requests have finished, and if we have any new results
|
// See how many new requests have finished, and if we have any new results
|
||||||
for( list< sptr< Dictionary::WordSearchRequest > >::iterator i =
|
for ( auto i = queuedRequests.begin(); i != queuedRequests.end(); ) {
|
||||||
queuedRequests.begin(); i != queuedRequests.end(); )
|
if ( ( *i )->isFinished() ) {
|
||||||
{
|
if ( searchInProgress && !( *i )->getErrorString().isEmpty() )
|
||||||
if ( (*i)->isFinished() )
|
|
||||||
{
|
|
||||||
if ( searchInProgress && !(*i)->getErrorString().isEmpty() )
|
|
||||||
searchErrorString = tr( "Failed to query some dictionaries." );
|
searchErrorString = tr( "Failed to query some dictionaries." );
|
||||||
|
|
||||||
if ( (*i)->isUncertain() )
|
if ( ( *i )->isUncertain() )
|
||||||
searchResultsUncertain = true;
|
searchResultsUncertain = true;
|
||||||
|
|
||||||
if ( (*i)->matchesCount() )
|
if ( (*i)->matchesCount() )
|
||||||
|
@ -233,8 +227,7 @@ void WordFinder::requestFinished()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( newResults && queuedRequests.size() && !updateResultsTimer.isActive() )
|
if ( newResults && !queuedRequests.empty() && !updateResultsTimer.isActive() ) {
|
||||||
{
|
|
||||||
// If we have got some new results, but not all of them, we would start a
|
// If we have got some new results, but not all of them, we would start a
|
||||||
// timer to update a user some time in the future
|
// timer to update a user some time in the future
|
||||||
updateResultsTimer.start();
|
updateResultsTimer.start();
|
||||||
|
@ -297,17 +290,13 @@ void WordFinder::updateResults()
|
||||||
|
|
||||||
wstring original = Folding::applySimpleCaseOnly( allWordWritings[ 0 ] );
|
wstring original = Folding::applySimpleCaseOnly( allWordWritings[ 0 ] );
|
||||||
|
|
||||||
for( list< sptr< Dictionary::WordSearchRequest > >::iterator i =
|
for ( auto i = finishedRequests.begin(); i != finishedRequests.end(); ) {
|
||||||
finishedRequests.begin(); i != finishedRequests.end(); )
|
for ( size_t count = ( *i )->matchesCount(), x = 0; x < count; ++x ) {
|
||||||
{
|
wstring match = ( **i )[ x ].word;
|
||||||
for( size_t count = (*i)->matchesCount(), x = 0; x < count; ++x )
|
int weight = ( **i )[ x ].weight;
|
||||||
{
|
|
||||||
wstring match = (**i)[ x ].word;
|
|
||||||
int weight = (**i)[ x ].weight;
|
|
||||||
wstring lowerCased = Folding::applySimpleCaseOnly( match );
|
wstring lowerCased = Folding::applySimpleCaseOnly( match );
|
||||||
|
|
||||||
if( searchType == ExpressionMatch )
|
if ( searchType == ExpressionMatch ) {
|
||||||
{
|
|
||||||
unsigned ws;
|
unsigned ws;
|
||||||
|
|
||||||
for( ws = 0; ws < allWordWritings.size(); ws++ )
|
for( ws = 0; ws < allWordWritings.size(); ws++ )
|
||||||
|
@ -330,9 +319,8 @@ void WordFinder::updateResults()
|
||||||
}
|
}
|
||||||
weight = ws;
|
weight = ws;
|
||||||
}
|
}
|
||||||
pair< ResultsIndex::iterator, bool > insertResult =
|
auto insertResult =
|
||||||
resultsIndex.insert( pair< wstring, ResultsArray::iterator >( lowerCased,
|
resultsIndex.insert( pair< wstring, ResultsArray::iterator >( lowerCased, resultsArray.end() ) );
|
||||||
resultsArray.end() ) );
|
|
||||||
|
|
||||||
if ( !insertResult.second )
|
if ( !insertResult.second )
|
||||||
{
|
{
|
||||||
|
@ -347,7 +335,7 @@ void WordFinder::updateResults()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resultsArray.push_back( OneResult() );
|
resultsArray.emplace_back();
|
||||||
|
|
||||||
resultsArray.back().word = match;
|
resultsArray.back().word = match;
|
||||||
resultsArray.back().rank = INT_MAX;
|
resultsArray.back().rank = INT_MAX;
|
||||||
|
@ -361,14 +349,11 @@ void WordFinder::updateResults()
|
||||||
|
|
||||||
size_t maxSearchResults = 500;
|
size_t maxSearchResults = 500;
|
||||||
|
|
||||||
if ( resultsArray.size() )
|
if ( !resultsArray.empty() ) {
|
||||||
{
|
if ( searchType == PrefixMatch ) {
|
||||||
if ( searchType == PrefixMatch )
|
|
||||||
{
|
|
||||||
/// Assign each result a category, storing it in the rank's field
|
/// Assign each result a category, storing it in the rank's field
|
||||||
|
|
||||||
enum Category
|
enum Category {
|
||||||
{
|
|
||||||
ExactMatch,
|
ExactMatch,
|
||||||
ExactNoFullCaseMatch,
|
ExactNoFullCaseMatch,
|
||||||
ExactNoDiaMatch,
|
ExactNoDiaMatch,
|
||||||
|
@ -385,66 +370,55 @@ void WordFinder::updateResults()
|
||||||
Multiplier = 256 // Categories should be multiplied by Multiplier
|
Multiplier = 256 // Categories should be multiplied by Multiplier
|
||||||
};
|
};
|
||||||
|
|
||||||
for( unsigned wr = 0; wr < allWordWritings.size(); ++wr )
|
for ( const auto & allWordWriting : allWordWritings ) {
|
||||||
{
|
wstring target = Folding::applySimpleCaseOnly( allWordWriting );
|
||||||
wstring target = Folding::applySimpleCaseOnly( allWordWritings[ wr ] );
|
|
||||||
wstring targetNoFullCase = Folding::applyFullCaseOnly( target );
|
wstring targetNoFullCase = Folding::applyFullCaseOnly( target );
|
||||||
wstring targetNoDia = Folding::applyDiacriticsOnly( targetNoFullCase );
|
wstring targetNoDia = Folding::applyDiacriticsOnly( targetNoFullCase );
|
||||||
wstring targetNoPunct = Folding::applyPunctOnly( targetNoDia );
|
wstring targetNoPunct = Folding::applyPunctOnly( targetNoDia );
|
||||||
wstring targetNoWs = Folding::applyWhitespaceOnly( targetNoPunct );
|
wstring targetNoWs = Folding::applyWhitespaceOnly( targetNoPunct );
|
||||||
|
|
||||||
wstring::size_type matchPos = 0;
|
wstring::size_type matchPos = 0;
|
||||||
|
|
||||||
for( ResultsIndex::const_iterator i = resultsIndex.begin(), j = resultsIndex.end();
|
for ( const auto & i : resultsIndex ) {
|
||||||
i != j; ++i )
|
|
||||||
{
|
|
||||||
wstring resultNoFullCase, resultNoDia, resultNoPunct, resultNoWs;
|
wstring resultNoFullCase, resultNoDia, resultNoPunct, resultNoWs;
|
||||||
|
|
||||||
int rank;
|
int rank;
|
||||||
|
|
||||||
if ( i->first == target )
|
if ( i.first == target )
|
||||||
rank = ExactMatch * Multiplier;
|
rank = ExactMatch * Multiplier;
|
||||||
else
|
else if ( ( resultNoFullCase = Folding::applyFullCaseOnly( i.first ) ) == targetNoFullCase )
|
||||||
if ( ( resultNoFullCase = Folding::applyFullCaseOnly( i->first ) ) == targetNoFullCase )
|
|
||||||
rank = ExactNoFullCaseMatch * Multiplier;
|
rank = ExactNoFullCaseMatch * Multiplier;
|
||||||
else
|
else if ( ( resultNoDia = Folding::applyDiacriticsOnly( resultNoFullCase ) ) == targetNoDia )
|
||||||
if ( ( resultNoDia = Folding::applyDiacriticsOnly( resultNoFullCase ) ) == targetNoDia )
|
|
||||||
rank = ExactNoDiaMatch * Multiplier;
|
rank = ExactNoDiaMatch * Multiplier;
|
||||||
else
|
else if ( ( resultNoPunct = Folding::applyPunctOnly( resultNoDia ) ) == targetNoPunct )
|
||||||
if ( ( resultNoPunct = Folding::applyPunctOnly( resultNoDia ) ) == targetNoPunct )
|
|
||||||
rank = ExactNoPunctMatch * Multiplier;
|
rank = ExactNoPunctMatch * Multiplier;
|
||||||
else
|
else if ( ( resultNoWs = Folding::applyWhitespaceOnly( resultNoPunct ) ) == targetNoWs )
|
||||||
if ( ( resultNoWs = Folding::applyWhitespaceOnly( resultNoPunct ) ) == targetNoWs )
|
|
||||||
rank = ExactNoWsMatch * Multiplier;
|
rank = ExactNoWsMatch * Multiplier;
|
||||||
else
|
else if ( hasSurroundedWithWs( i.first, target, matchPos ) )
|
||||||
if ( hasSurroundedWithWs( i->first, target, matchPos ) )
|
|
||||||
rank = ExactInsideMatch * Multiplier + matchPos;
|
rank = ExactInsideMatch * Multiplier + matchPos;
|
||||||
else
|
else if ( hasSurroundedWithWs( resultNoDia, targetNoDia, matchPos ) )
|
||||||
if ( hasSurroundedWithWs( resultNoDia, targetNoDia, matchPos ) )
|
|
||||||
rank = ExactNoDiaInsideMatch * Multiplier + matchPos;
|
rank = ExactNoDiaInsideMatch * Multiplier + matchPos;
|
||||||
else
|
else if ( hasSurroundedWithWs( resultNoPunct, targetNoPunct, matchPos ) )
|
||||||
if ( hasSurroundedWithWs( resultNoPunct, targetNoPunct, matchPos ) )
|
|
||||||
rank = ExactNoPunctInsideMatch * Multiplier + matchPos;
|
rank = ExactNoPunctInsideMatch * Multiplier + matchPos;
|
||||||
else
|
else if ( i.first.size() > target.size() && i.first.compare( 0, target.size(), target ) == 0 )
|
||||||
if ( i->first.size() > target.size() && i->first.compare( 0, target.size(), target ) == 0 )
|
rank = PrefixMatch * Multiplier + saturated( i.first.size() );
|
||||||
rank = PrefixMatch * Multiplier + saturated( i->first.size() );
|
else if ( resultNoDia.size() > targetNoDia.size()
|
||||||
else
|
&& resultNoDia.compare( 0, targetNoDia.size(), targetNoDia ) == 0 )
|
||||||
if ( resultNoDia.size() > targetNoDia.size() && resultNoDia.compare( 0, targetNoDia.size(), targetNoDia ) == 0 )
|
rank = PrefixNoDiaMatch * Multiplier + saturated( i.first.size() );
|
||||||
rank = PrefixNoDiaMatch * Multiplier + saturated( i->first.size() );
|
else if ( resultNoPunct.size() > targetNoPunct.size()
|
||||||
else
|
&& resultNoPunct.compare( 0, targetNoPunct.size(), targetNoPunct ) == 0 )
|
||||||
if ( resultNoPunct.size() > targetNoPunct.size() && resultNoPunct.compare( 0, targetNoPunct.size(), targetNoPunct ) == 0 )
|
rank = PrefixNoPunctMatch * Multiplier + saturated( i.first.size() );
|
||||||
rank = PrefixNoPunctMatch * Multiplier + saturated( i->first.size() );
|
else if ( resultNoWs.size() > targetNoWs.size()
|
||||||
else
|
&& resultNoWs.compare( 0, targetNoWs.size(), targetNoWs ) == 0 )
|
||||||
if ( resultNoWs.size() > targetNoWs.size() && resultNoWs.compare( 0, targetNoWs.size(), targetNoWs ) == 0 )
|
rank = PrefixNoWsMatch * Multiplier + saturated( i.first.size() );
|
||||||
rank = PrefixNoWsMatch * Multiplier + saturated( i->first.size() );
|
|
||||||
else
|
else
|
||||||
rank = WorstMatch * Multiplier;
|
rank = WorstMatch * Multiplier;
|
||||||
|
|
||||||
if ( i->second->rank > rank )
|
if ( i.second->rank > rank )
|
||||||
i->second->rank = rank; // We store the best rank of any writing
|
i.second->rank = rank; // We store the best rank of any writing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultsArray.sort( SortByRank() );
|
resultsArray.sort( SortByRank() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -456,29 +430,26 @@ void WordFinder::updateResults()
|
||||||
// in their beginnings, and second, the length of the strings. Here we assign
|
// in their beginnings, and second, the length of the strings. Here we assign
|
||||||
// only the first one, storing it in rank. Then we sort the results using
|
// only the first one, storing it in rank. Then we sort the results using
|
||||||
// SortByRankAndLength.
|
// SortByRankAndLength.
|
||||||
for( unsigned wr = 0; wr < allWordWritings.size(); ++wr )
|
for ( const auto & allWordWriting : allWordWritings ) {
|
||||||
{
|
wstring target = Folding::apply( allWordWriting );
|
||||||
wstring target = Folding::apply( allWordWritings[ wr ] );
|
|
||||||
|
for ( const auto & i : resultsIndex ) {
|
||||||
for( ResultsIndex::const_iterator i = resultsIndex.begin(), j = resultsIndex.end();
|
wstring resultFolded = Folding::apply( i.first );
|
||||||
i != j; ++i )
|
|
||||||
{
|
|
||||||
wstring resultFolded = Folding::apply( i->first );
|
|
||||||
|
|
||||||
int charsInCommon = 0;
|
int charsInCommon = 0;
|
||||||
|
|
||||||
for( wchar const * t = target.c_str(), * r = resultFolded.c_str();
|
for ( wchar const *t = target.c_str(), *r = resultFolded.c_str(); *t && *t == *r; ++t, ++r, ++charsInCommon )
|
||||||
*t && *t == *r; ++t, ++r, ++charsInCommon ) ;
|
;
|
||||||
|
|
||||||
int rank = -charsInCommon; // Negated so the lesser-than
|
int rank = -charsInCommon; // Negated so the lesser-than
|
||||||
// comparison would yield right
|
// comparison would yield right
|
||||||
// results.
|
// results.
|
||||||
|
|
||||||
if ( i->second->rank > rank )
|
if ( i.second->rank > rank )
|
||||||
i->second->rank = rank; // We store the best rank of any writing
|
i.second->rank = rank; // We store the best rank of any writing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultsArray.sort( SortByRankAndLength() );
|
resultsArray.sort( SortByRankAndLength() );
|
||||||
|
|
||||||
maxSearchResults = 15;
|
maxSearchResults = 15;
|
||||||
|
@ -488,24 +459,18 @@ void WordFinder::updateResults()
|
||||||
searchResults.clear();
|
searchResults.clear();
|
||||||
searchResults.reserve( resultsArray.size() < maxSearchResults ? resultsArray.size() : maxSearchResults );
|
searchResults.reserve( resultsArray.size() < maxSearchResults ? resultsArray.size() : maxSearchResults );
|
||||||
|
|
||||||
for( ResultsArray::const_iterator i = resultsArray.begin(), j = resultsArray.end();
|
for ( const auto & i : resultsArray ) {
|
||||||
i != j; ++i )
|
|
||||||
{
|
|
||||||
//GD_DPRINTF( "%d: %ls\n", i->second, i->first.c_str() );
|
|
||||||
|
|
||||||
if ( searchResults.size() < maxSearchResults )
|
if ( searchResults.size() < maxSearchResults )
|
||||||
searchResults.push_back( std::pair< QString, bool >( QString::fromStdU32String( i->word ), i->wasSuggested ) );
|
searchResults.emplace_back( QString::fromStdU32String( i.word ), i.wasSuggested );
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( queuedRequests.size() )
|
if ( !queuedRequests.empty() ) {
|
||||||
{
|
|
||||||
// There are still some unhandled results.
|
// There are still some unhandled results.
|
||||||
emit updated();
|
emit updated();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// That were all of them.
|
// That were all of them.
|
||||||
searchInProgress = false;
|
searchInProgress = false;
|
||||||
emit finished();
|
emit finished();
|
||||||
|
@ -514,8 +479,6 @@ void WordFinder::updateResults()
|
||||||
|
|
||||||
void WordFinder::cancelSearches()
|
void WordFinder::cancelSearches()
|
||||||
{
|
{
|
||||||
for( list< sptr< Dictionary::WordSearchRequest > >::iterator i =
|
for ( auto & queuedRequest : queuedRequests )
|
||||||
queuedRequests.begin(); i != queuedRequests.end(); ++i )
|
queuedRequest->cancel();
|
||||||
(*i)->cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,14 @@ class WordFinder: public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector< std::pair< QString, bool > > SearchResults; // bool is a "was suggested" flag
|
using SearchResults = std::vector< std::pair< QString, bool > >; // bool is a "was suggested" flag
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SearchResults searchResults;
|
SearchResults searchResults;
|
||||||
QString searchErrorString;
|
QString searchErrorString;
|
||||||
bool searchResultsUncertain;
|
bool searchResultsUncertain;
|
||||||
std::list< sptr< Dictionary::WordSearchRequest > > queuedRequests,
|
std::list< sptr< Dictionary::WordSearchRequest > > queuedRequests, finishedRequests;
|
||||||
finishedRequests;
|
|
||||||
bool searchInProgress;
|
bool searchInProgress;
|
||||||
|
|
||||||
QTimer updateResultsTimer;
|
QTimer updateResultsTimer;
|
||||||
|
|
109
src/wordlist.cc
109
src/wordlist.cc
|
@ -1,109 +0,0 @@
|
||||||
/* This file is (c) 2013 Tvangeste <i.4m.l33t@yandex.ru>
|
|
||||||
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
||||||
|
|
||||||
|
|
||||||
#include "wordlist.hh"
|
|
||||||
|
|
||||||
WordList::WordList( QWidget * parent ) : QListWidget( parent )
|
|
||||||
, listItemDelegate( itemDelegate() )
|
|
||||||
{
|
|
||||||
wordFinder = 0;
|
|
||||||
translateLine = 0;
|
|
||||||
setItemDelegate( &listItemDelegate );
|
|
||||||
}
|
|
||||||
|
|
||||||
void WordList::attachFinder( WordFinder * finder )
|
|
||||||
{
|
|
||||||
// qDebug() << "Attaching the word finder..." << finder;
|
|
||||||
|
|
||||||
if ( wordFinder == finder )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( wordFinder )
|
|
||||||
{
|
|
||||||
disconnect( wordFinder, &WordFinder::updated, this, &WordList::prefixMatchUpdated );
|
|
||||||
disconnect( wordFinder, &WordFinder::finished, this, &WordList::prefixMatchFinished );
|
|
||||||
}
|
|
||||||
|
|
||||||
wordFinder = finder;
|
|
||||||
|
|
||||||
connect( wordFinder, &WordFinder::updated, this, &WordList::prefixMatchUpdated );
|
|
||||||
connect( wordFinder, &WordFinder::finished, this, &WordList::prefixMatchFinished );
|
|
||||||
}
|
|
||||||
|
|
||||||
void WordList::prefixMatchUpdated()
|
|
||||||
{
|
|
||||||
updateMatchResults( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
void WordList::prefixMatchFinished()
|
|
||||||
{
|
|
||||||
updateMatchResults( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void WordList::updateMatchResults( bool finished )
|
|
||||||
{
|
|
||||||
WordFinder::SearchResults const & results = wordFinder->getResults();
|
|
||||||
|
|
||||||
setUpdatesEnabled( false );
|
|
||||||
//clear all existed items
|
|
||||||
clear();
|
|
||||||
|
|
||||||
for( unsigned x = 0; x < results.size(); ++x )
|
|
||||||
{
|
|
||||||
QListWidgetItem * i = new QListWidgetItem( results[ x ].first, this );
|
|
||||||
i->setToolTip( results[ x ].first );
|
|
||||||
|
|
||||||
if( results[ x ].second )
|
|
||||||
{
|
|
||||||
QFont f = i->font();
|
|
||||||
f.setItalic( true );
|
|
||||||
i->setFont( f );
|
|
||||||
}
|
|
||||||
|
|
||||||
i->setTextAlignment( Qt::AlignLeft );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( count() )
|
|
||||||
{
|
|
||||||
scrollToItem( item( 0 ), QAbstractItemView::PositionAtTop );
|
|
||||||
setCurrentItem( 0, QItemSelectionModel::Clear );
|
|
||||||
}
|
|
||||||
|
|
||||||
setUpdatesEnabled( true );
|
|
||||||
|
|
||||||
if ( finished )
|
|
||||||
{
|
|
||||||
unsetCursor();
|
|
||||||
|
|
||||||
refreshTranslateLine();
|
|
||||||
|
|
||||||
if ( !wordFinder->getErrorString().isEmpty() )
|
|
||||||
emit statusBarMessage(tr("WARNING: %1").arg(wordFinder->getErrorString()),
|
|
||||||
20000, QPixmap(":/icons/error.svg"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !results.empty() && results.front().first.isRightToLeft() )
|
|
||||||
setLayoutDirection( Qt::RightToLeft );
|
|
||||||
else
|
|
||||||
setLayoutDirection( Qt::LeftToRight );
|
|
||||||
|
|
||||||
emit contentChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WordList::refreshTranslateLine()
|
|
||||||
{
|
|
||||||
if ( !translateLine )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Visually mark the input line to mark if there's no results
|
|
||||||
bool setMark = wordFinder->getResults().empty() && !wordFinder->wasSearchUncertain();
|
|
||||||
|
|
||||||
if ( translateLine->property( "noResults" ).toBool() != setMark )
|
|
||||||
{
|
|
||||||
translateLine->setProperty( "noResults", setMark );
|
|
||||||
|
|
||||||
Utils::Widget::setNoResultColor( translateLine, setMark );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* This file is (c) 2013 Tvangeste <i.4m.l33t@yandex.ru>
|
|
||||||
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
||||||
|
|
||||||
#ifndef WORDLIST_HH
|
|
||||||
#define WORDLIST_HH
|
|
||||||
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QLineEdit>
|
|
||||||
|
|
||||||
#include "wordfinder.hh"
|
|
||||||
#include "delegate.hh"
|
|
||||||
|
|
||||||
class WordList : public QListWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit WordList(QWidget * parent = 0);
|
|
||||||
void attachFinder(WordFinder * finder);
|
|
||||||
virtual void setTranslateLine(QLineEdit * line)
|
|
||||||
{ translateLine = line; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void statusBarMessage(QString const & message, int timeout = 0, QPixmap const & pixmap = QPixmap());
|
|
||||||
void contentChanged();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void prefixMatchUpdated();
|
|
||||||
void prefixMatchFinished();
|
|
||||||
void updateMatchResults( bool finished );
|
|
||||||
|
|
||||||
private:
|
|
||||||
void refreshTranslateLine();
|
|
||||||
|
|
||||||
WordFinder * wordFinder;
|
|
||||||
QLineEdit * translateLine;
|
|
||||||
WordListItemDelegate listItemDelegate;
|
|
||||||
|
|
||||||
QVector< QSize > resizedSizes;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WORDLIST_HH
|
|
Loading…
Reference in a new issue