mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 20:14:05 +00:00
311 lines
8.3 KiB
C++
311 lines
8.3 KiB
C++
/* This file is (c) 2012 Tvangeste <i.4m.l33t@yandex.ru>
|
|
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
|
|
#include "translatebox.hh"
|
|
|
|
#include <QHBoxLayout>
|
|
#include <QEvent>
|
|
#include <QKeyEvent>
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QModelIndex>
|
|
#include <QScrollBar>
|
|
#include <QStyle>
|
|
|
|
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, SIGNAL( activated( QModelIndex ) ),
|
|
this, SLOT( acceptCurrentEntry() ) );
|
|
|
|
connect(this, SIGNAL( itemClicked( QListWidgetItem * ) ),
|
|
this, SLOT( 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
|
|
{
|
|
const QSize itemSizeHint = itemDelegate()->sizeHint(viewOptions(), model()->index( 0, 0 ) );
|
|
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) : QWidget(parent),
|
|
word_list(new CompletionList(this)), translate_line(new ExtLineEdit(this)), m_popupEnabled(false)
|
|
{
|
|
// initially hidden
|
|
word_list->hide();
|
|
|
|
resize(200, 90);
|
|
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
|
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" ) );
|
|
word_list->setTranslateLine(translate_line);
|
|
|
|
// completer = new QCompleter(m_completionList->model(), this);
|
|
// completer->setCaseSensitivity(Qt::CaseInsensitive);
|
|
// completer->setCompletionMode(QCompleter::InlineCompletion);
|
|
|
|
QHBoxLayout *layout = new QHBoxLayout(this);
|
|
setLayout(layout);
|
|
layout->setContentsMargins(0,0,0,0);
|
|
layout->addWidget(translate_line);
|
|
|
|
QPixmap image(":/icons/system-search.svg");
|
|
|
|
translate_line->setButtonPixmap(ExtLineEdit::Left, image);
|
|
// translate_line->setButtonToolTip(ExtLineEdit::Left, tr("Options"));
|
|
translate_line->setButtonVisible(ExtLineEdit::Left, true);
|
|
translate_line->setButtonFocusPolicy(ExtLineEdit::Left, Qt::ClickFocus);
|
|
|
|
QPixmap right(":/icons/1downarrow.svg");
|
|
translate_line->setButtonPixmap(ExtLineEdit::Right, right);
|
|
translate_line->setButtonToolTip(ExtLineEdit::Right, tr("Drop-down"));
|
|
translate_line->setButtonVisible(ExtLineEdit::Right, true);
|
|
translate_line->setButtonFocusPolicy(ExtLineEdit::Right, Qt::NoFocus);
|
|
|
|
translate_line->setFocusPolicy(Qt::ClickFocus);
|
|
|
|
translate_line->installEventFilter( this );
|
|
this->installEventFilter( this );
|
|
|
|
connect(translate_line, SIGNAL( textChanged( QString const & ) ),
|
|
this, SLOT( onTextEdit() ) );
|
|
|
|
connect(translate_line, SIGNAL( rightButtonClicked() ),
|
|
this, SLOT( rightButtonClicked() ) );
|
|
|
|
connect(word_list, SIGNAL( contentChanged() ),
|
|
this, SLOT( showPopup() ) );
|
|
}
|
|
|
|
bool TranslateBox::eventFilter(QObject *obj, QEvent *event)
|
|
{
|
|
// 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 );
|
|
translate_line->setText( text );
|
|
}
|
|
|
|
void TranslateBox::setPopupEnabled( bool enable )
|
|
{
|
|
m_popupEnabled = enable;
|
|
showPopup();
|
|
}
|
|
|
|
void TranslateBox::setSizePolicy( QSizePolicy policy )
|
|
{
|
|
QWidget::setSizePolicy( policy );
|
|
if ( translate_line )
|
|
translate_line->setSizePolicy( policy );
|
|
}
|
|
|
|
void TranslateBox::showPopup()
|
|
{
|
|
// completer->setCompletionPrefix( m_fileLineEdit->text() );
|
|
// qDebug() << "COMPLETION:" << completer->currentCompletion();
|
|
|
|
// Don't allow recursive call
|
|
if( translateBoxMutex.tryLock() )
|
|
translateBoxMutex.unlock();
|
|
else
|
|
return;
|
|
Mutex::Lock _( 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;
|
|
}
|
|
|
|
if ( !m_popupEnabled )
|
|
{
|
|
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()
|
|
{
|
|
return translate_line;
|
|
}
|
|
|
|
WordList * TranslateBox::wordList()
|
|
{
|
|
return word_list;
|
|
}
|
|
|
|
void TranslateBox::rightButtonClicked()
|
|
{
|
|
setPopupEnabled( !m_popupEnabled );
|
|
}
|
|
|
|
void TranslateBox::onTextEdit()
|
|
{
|
|
if ( translate_line->hasFocus() )
|
|
setPopupEnabled( true );
|
|
}
|