2012-02-20 21:47:14 +00:00
|
|
|
/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
|
2009-01-28 20:55:45 +00:00
|
|
|
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
|
|
|
|
|
|
#include "scanpopup.hh"
|
2021-06-30 15:54:35 +00:00
|
|
|
#include "folding.hh"
|
2009-02-01 00:08:08 +00:00
|
|
|
#include <QCursor>
|
|
|
|
#include <QPixmap>
|
|
|
|
#include <QBitmap>
|
|
|
|
#include <QMenu>
|
2009-02-06 13:05:25 +00:00
|
|
|
#include <QMouseEvent>
|
2022-02-27 14:42:40 +00:00
|
|
|
#if ( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
|
2009-02-08 16:35:30 +00:00
|
|
|
#include <QDesktopWidget>
|
2023-05-30 06:31:07 +00:00
|
|
|
#include <QScreen>
|
2023-01-02 14:00:42 +00:00
|
|
|
#include <QStringList>
|
2022-02-27 05:17:37 +00:00
|
|
|
#endif
|
2013-11-16 18:34:09 +00:00
|
|
|
#include "gddebug.hh"
|
2014-02-05 13:41:49 +00:00
|
|
|
#include "gestures.hh"
|
2009-02-01 00:08:08 +00:00
|
|
|
|
2014-05-12 13:53:13 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2023-04-18 00:00:36 +00:00
|
|
|
#include "macos/macmouseover.hh"
|
2013-04-10 13:31:44 +00:00
|
|
|
#define MouseOver MacMouseOver
|
|
|
|
#endif
|
2023-04-17 20:12:27 +00:00
|
|
|
#include "base_type.hh"
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2013-01-28 12:19:11 +00:00
|
|
|
/// We use different window flags under Windows and X11 due to slight differences
|
|
|
|
/// in their behavior on those platforms.
|
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
|
|
|
static const Qt::WindowFlags defaultUnpinnedWindowFlags =
|
2013-01-28 12:19:11 +00:00
|
|
|
|
2021-11-18 06:28:12 +00:00
|
|
|
#if defined( Q_OS_WIN )
|
2013-01-28 12:19:11 +00:00
|
|
|
Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint
|
|
|
|
#else
|
|
|
|
Qt::Popup
|
|
|
|
#endif
|
|
|
|
;
|
2010-01-02 12:51:53 +00:00
|
|
|
|
2019-05-11 10:55:52 +00:00
|
|
|
static const Qt::WindowFlags pinnedWindowFlags =
|
|
|
|
#ifdef HAVE_X11
|
|
|
|
/// With the Qt::Dialog flag, scan popup is always on top of the main window
|
|
|
|
/// on Linux/X11 with Qt 4, Qt 5 since version 5.12.1 (QTBUG-74309).
|
|
|
|
/// Qt::Window allows to use the scan popup and the main window independently.
|
|
|
|
Qt::Window
|
|
|
|
#else
|
|
|
|
Qt::Dialog
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
|
2018-04-17 17:52:39 +00:00
|
|
|
#ifdef HAVE_X11
|
2018-04-16 12:23:22 +00:00
|
|
|
static bool ownsClipboardMode( QClipboard::Mode mode )
|
|
|
|
{
|
|
|
|
const QClipboard & clipboard = *QApplication::clipboard();
|
|
|
|
switch ( mode ) {
|
|
|
|
case QClipboard::Clipboard:
|
|
|
|
return clipboard.ownsClipboard();
|
|
|
|
case QClipboard::Selection:
|
|
|
|
return clipboard.ownsSelection();
|
|
|
|
case QClipboard::FindBuffer:
|
|
|
|
return clipboard.ownsFindBuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
gdWarning( "Unknown clipboard mode: %d\n", static_cast< int >( mode ) );
|
|
|
|
return false;
|
|
|
|
}
|
2018-04-17 17:52:39 +00:00
|
|
|
#endif
|
2018-04-16 12:23:22 +00:00
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
ScanPopup::ScanPopup( QWidget * parent,
|
2009-02-06 17:04:11 +00:00
|
|
|
Config::Class & cfg_,
|
2017-06-05 13:15:38 +00:00
|
|
|
ArticleNetworkAccessManager & articleNetMgr,
|
2018-03-21 17:49:34 +00:00
|
|
|
AudioPlayerPtr const & audioPlayer_,
|
2009-02-01 00:08:08 +00:00
|
|
|
std::vector< sptr< Dictionary::Class > > const & allDictionaries_,
|
2009-10-21 19:37:07 +00:00
|
|
|
Instances::Groups const & groups_,
|
|
|
|
History & history_ ):
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow( parent ),
|
2009-02-05 20:55:00 +00:00
|
|
|
cfg( cfg_ ),
|
2009-02-01 00:08:08 +00:00
|
|
|
allDictionaries( allDictionaries_ ),
|
|
|
|
groups( groups_ ),
|
2009-10-21 19:37:07 +00:00
|
|
|
history( history_ ),
|
2009-05-16 11:14:43 +00:00
|
|
|
escapeAction( this ),
|
2012-09-16 10:19:47 +00:00
|
|
|
switchExpandModeAction( this ),
|
2013-01-25 15:42:44 +00:00
|
|
|
focusTranslateLineAction( this ),
|
2014-04-16 16:18:28 +00:00
|
|
|
openSearchAction( this ),
|
2009-02-06 13:05:25 +00:00
|
|
|
wordFinder( this ),
|
2013-06-11 18:31:01 +00:00
|
|
|
dictionaryBar( this, configEvents, cfg.editDictionaryCommandLine, cfg.preferences.maxDictionaryRefsInContextMenu ),
|
2023-05-13 14:06:36 +00:00
|
|
|
hideTimer( this )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
ui.setupUi( this );
|
2009-03-26 19:00:08 +00:00
|
|
|
|
2014-04-16 16:18:28 +00:00
|
|
|
openSearchAction.setShortcut( QKeySequence( "Ctrl+F" ) );
|
|
|
|
|
2014-03-20 13:44:46 +00:00
|
|
|
if ( layoutDirection() == Qt::RightToLeft ) {
|
|
|
|
// Adjust button icons for Right-To-Left layout
|
2022-01-24 14:23:38 +00:00
|
|
|
ui.goBackButton->setIcon( QIcon( ":/icons/next.svg" ) );
|
|
|
|
ui.goForwardButton->setIcon( QIcon( ":/icons/previous.svg" ) );
|
2014-03-20 13:44:46 +00:00
|
|
|
}
|
|
|
|
|
2011-07-14 08:17:59 +00:00
|
|
|
mainStatusBar = new MainStatusBar( this );
|
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
ui.queryError->hide();
|
|
|
|
|
2018-03-21 17:49:34 +00:00
|
|
|
definition = new ArticleView( ui.outerFrame,
|
|
|
|
articleNetMgr,
|
|
|
|
audioPlayer_,
|
|
|
|
allDictionaries,
|
|
|
|
groups,
|
|
|
|
true,
|
|
|
|
cfg,
|
2014-04-16 16:18:28 +00:00
|
|
|
openSearchAction,
|
2023-03-16 11:55:47 +00:00
|
|
|
ui.translateBox->translateLine(),
|
2012-09-26 13:13:47 +00:00
|
|
|
dictionaryBar.toggleViewAction() );
|
2009-04-30 20:20:05 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( definition, &ArticleView::inspectSignal, this, &ScanPopup::inspectElementWhenPinned );
|
|
|
|
connect( definition, &ArticleView::forceAddWordToHistory, this, &ScanPopup::forceAddWordToHistory );
|
|
|
|
connect( this, &ScanPopup::closeMenu, definition, &ArticleView::closePopupMenu );
|
|
|
|
connect( definition, &ArticleView::sendWordToHistory, this, &ScanPopup::sendWordToHistory );
|
|
|
|
connect( definition, &ArticleView::typingEvent, this, &ScanPopup::typingEvent );
|
|
|
|
|
2023-06-05 13:22:20 +00:00
|
|
|
wordListDefaultFont = ui.translateBox->completerWidget()->font();
|
2017-07-14 13:02:21 +00:00
|
|
|
translateLineDefaultFont = ui.translateBox->font();
|
2019-01-26 19:11:27 +00:00
|
|
|
groupListDefaultFont = ui.groupList->font();
|
2017-07-14 13:02:21 +00:00
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
ui.mainLayout->addWidget( definition );
|
|
|
|
|
2013-01-25 15:42:44 +00:00
|
|
|
ui.translateBox->translateLine()->installEventFilter( this );
|
2023-04-17 15:19:29 +00:00
|
|
|
definition->installEventFilter( this );
|
|
|
|
this->installEventFilter( this );
|
2013-01-25 15:42:44 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( ui.translateBox->translateLine(), &QLineEdit::textChanged, this, &ScanPopup::translateInputChanged );
|
2013-01-25 15:42:44 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( ui.translateBox->translateLine(), &QLineEdit::returnPressed, this, &ScanPopup::translateInputFinished );
|
2013-01-25 15:42:44 +00:00
|
|
|
|
2023-04-30 03:39:28 +00:00
|
|
|
ui.pronounceButton->setDisabled( true );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
ui.groupList->fill( groups );
|
2009-04-10 12:48:40 +00:00
|
|
|
ui.groupList->setCurrentGroup( cfg.lastPopupGroupId );
|
2009-02-06 17:04:11 +00:00
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
dictionaryBar.setFloatable( false );
|
|
|
|
|
2012-09-26 13:13:47 +00:00
|
|
|
Instances::Group const * igrp = groups.findGroup( cfg.lastPopupGroupId );
|
|
|
|
if ( cfg.lastPopupGroupId == Instances::Group::AllGroupId ) {
|
|
|
|
if ( igrp )
|
|
|
|
igrp->checkMutedDictionaries( &cfg.popupMutedDictionaries );
|
|
|
|
dictionaryBar.setMutedDictionaries( &cfg.popupMutedDictionaries );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Config::Group * grp = cfg.getGroup( cfg.lastPopupGroupId );
|
|
|
|
if ( igrp && grp )
|
|
|
|
igrp->checkMutedDictionaries( &grp->popupMutedDictionaries );
|
2023-06-05 13:22:20 +00:00
|
|
|
dictionaryBar.setMutedDictionaries( grp ? &grp->popupMutedDictionaries : nullptr );
|
2012-09-26 13:13:47 +00:00
|
|
|
}
|
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
addToolBar( Qt::RightToolBarArea, &dictionaryBar );
|
|
|
|
|
2023-06-11 11:51:24 +00:00
|
|
|
connect( &dictionaryBar, &DictionaryBar::editGroupRequested, this, &ScanPopup::editGroupRequested );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( this, &ScanPopup::closeMenu, &dictionaryBar, &DictionaryBar::closePopupMenu );
|
|
|
|
connect( &dictionaryBar, &DictionaryBar::showDictionaryInfo, this, &ScanPopup::showDictionaryInfo );
|
|
|
|
connect( &dictionaryBar, &DictionaryBar::openDictionaryFolder, this, &ScanPopup::openDictionaryFolder );
|
|
|
|
|
2023-02-14 14:51:03 +00:00
|
|
|
pinnedGeometry = cfg.popupWindowGeometry;
|
2022-12-26 02:08:17 +00:00
|
|
|
if ( cfg.popupWindowGeometry.size() )
|
2010-03-30 20:15:55 +00:00
|
|
|
restoreGeometry( cfg.popupWindowGeometry );
|
|
|
|
|
|
|
|
if ( cfg.popupWindowState.size() )
|
2023-06-09 11:56:04 +00:00
|
|
|
restoreState( cfg.popupWindowState );
|
2010-03-30 20:15:55 +00:00
|
|
|
|
2017-07-13 15:00:19 +00:00
|
|
|
ui.onTopButton->setChecked( cfg.popupWindowAlwaysOnTop );
|
|
|
|
ui.onTopButton->setVisible( cfg.pinPopupWindow );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( ui.onTopButton, &QAbstractButton::clicked, this, &ScanPopup::alwaysOnTopClicked );
|
2017-07-13 15:00:19 +00:00
|
|
|
|
2011-05-01 23:52:11 +00:00
|
|
|
ui.pinButton->setChecked( cfg.pinPopupWindow );
|
|
|
|
|
|
|
|
if ( cfg.pinPopupWindow ) {
|
|
|
|
dictionaryBar.setMovable( true );
|
2019-05-11 10:55:52 +00:00
|
|
|
Qt::WindowFlags flags = pinnedWindowFlags;
|
2017-07-13 15:00:19 +00:00
|
|
|
if ( cfg.popupWindowAlwaysOnTop )
|
|
|
|
flags |= Qt::WindowStaysOnTopHint;
|
|
|
|
setWindowFlags( flags );
|
2022-10-19 12:19:02 +00:00
|
|
|
#ifdef Q_OS_MACOS
|
|
|
|
setAttribute( Qt::WA_MacAlwaysShowToolWindow );
|
|
|
|
#endif
|
2011-05-01 23:52:11 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
dictionaryBar.setMovable( 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
|
|
|
setWindowFlags( unpinnedWindowFlags() );
|
2022-10-19 12:19:02 +00:00
|
|
|
#ifdef Q_OS_MACOS
|
|
|
|
setAttribute( Qt::WA_MacAlwaysShowToolWindow, false );
|
|
|
|
#endif
|
2011-05-01 23:52:11 +00:00
|
|
|
}
|
2009-02-01 00:08:08 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &configEvents, &Config::Events::mutedDictionariesChanged, this, &ScanPopup::mutedDictionariesChanged );
|
2009-02-06 17:16:33 +00:00
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
definition->focus();
|
2009-02-06 13:05:25 +00:00
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
#if 0 // Experimental code to give window a non-rectangular shape (i.e. \
|
|
|
|
// balloon) using a colorkey mask.
|
|
|
|
QPixmap pixMask( size() );
|
|
|
|
render( &pixMask );
|
|
|
|
|
|
|
|
setMask( pixMask.createMaskFromColor( QColor( 255, 0, 0 ) ) );
|
|
|
|
|
|
|
|
// This helps against flickering
|
|
|
|
setAttribute( Qt::WA_NoSystemBackground );
|
|
|
|
#endif
|
|
|
|
|
2009-05-16 11:14:43 +00:00
|
|
|
escapeAction.setShortcut( QKeySequence( "Esc" ) );
|
|
|
|
addAction( &escapeAction );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &escapeAction, &QAction::triggered, this, &ScanPopup::escapePressed );
|
2009-05-16 11:14:43 +00:00
|
|
|
|
2013-01-25 15:42:44 +00:00
|
|
|
focusTranslateLineAction.setShortcutContext( Qt::WidgetWithChildrenShortcut );
|
|
|
|
addAction( &focusTranslateLineAction );
|
|
|
|
focusTranslateLineAction.setShortcuts( QList< QKeySequence >()
|
|
|
|
<< QKeySequence( "Alt+D" ) << QKeySequence( "Ctrl+L" ) );
|
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &focusTranslateLineAction, &QAction::triggered, this, &ScanPopup::focusTranslateLine );
|
2013-01-25 15:42:44 +00:00
|
|
|
|
2018-05-16 11:48:27 +00:00
|
|
|
QAction * const focusArticleViewAction = new QAction( this );
|
|
|
|
focusArticleViewAction->setShortcutContext( Qt::WidgetWithChildrenShortcut );
|
|
|
|
focusArticleViewAction->setShortcut( QKeySequence( "Ctrl+N" ) );
|
|
|
|
addAction( focusArticleViewAction );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( focusArticleViewAction, &QAction::triggered, definition, &ArticleView::focus );
|
2012-09-16 10:19:47 +00:00
|
|
|
|
|
|
|
switchExpandModeAction.setShortcuts( QList< QKeySequence >() << QKeySequence( Qt::CTRL | Qt::Key_8 )
|
2022-02-27 05:17:37 +00:00
|
|
|
<< QKeySequence( Qt::CTRL | Qt::Key_Asterisk )
|
|
|
|
<< QKeySequence( Qt::CTRL | Qt::SHIFT | Qt::Key_8 ) );
|
2012-09-16 10:19:47 +00:00
|
|
|
|
|
|
|
addAction( &switchExpandModeAction );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &switchExpandModeAction, &QAction::triggered, this, &ScanPopup::switchExpandOptionalPartsMode );
|
2012-09-16 10:19:47 +00:00
|
|
|
|
2022-02-27 06:26:49 +00:00
|
|
|
connect( ui.groupList, &QComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged );
|
2009-02-01 00:08:08 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &wordFinder, &WordFinder::finished, this, &ScanPopup::prefixMatchFinished );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( ui.pinButton, &QAbstractButton::clicked, this, &ScanPopup::pinButtonClicked );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( definition, &ArticleView::pageLoaded, this, &ScanPopup::pageLoaded );
|
2009-04-10 21:07:03 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( definition, &ArticleView::statusBarMessage, this, &ScanPopup::showStatusBarMessage );
|
2011-07-14 08:17:59 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( definition, &ArticleView::titleChanged, this, &ScanPopup::titleChanged );
|
2017-11-07 14:46:59 +00:00
|
|
|
|
2022-02-24 23:55:32 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &MouseOver::instance(), &MouseOver::hovered, this, &ScanPopup::handleInputWord );
|
2022-02-24 23:55:32 +00:00
|
|
|
#endif
|
2009-04-10 13:56:38 +00:00
|
|
|
|
|
|
|
hideTimer.setSingleShot( true );
|
|
|
|
hideTimer.setInterval( 400 );
|
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &hideTimer, &QTimer::timeout, this, &ScanPopup::hideTimerExpired );
|
2009-04-11 16:44:14 +00:00
|
|
|
|
2010-07-03 16:24:30 +00:00
|
|
|
mouseGrabPollTimer.setSingleShot( false );
|
|
|
|
mouseGrabPollTimer.setInterval( 10 );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( &mouseGrabPollTimer, &QTimer::timeout, this, &ScanPopup::mouseGrabPoll );
|
2022-02-24 23:55:32 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2011-07-28 13:04:06 +00:00
|
|
|
MouseOver::instance().setPreferencesPtr( &( cfg.preferences ) );
|
2022-02-24 23:55:32 +00:00
|
|
|
#endif
|
2012-12-24 12:59:46 +00:00
|
|
|
ui.goBackButton->setEnabled( false );
|
|
|
|
ui.goForwardButton->setEnabled( false );
|
2013-02-27 13:12:46 +00:00
|
|
|
|
2014-02-05 13:41:49 +00:00
|
|
|
grabGesture( Gestures::GDPinchGestureType );
|
|
|
|
grabGesture( Gestures::GDSwipeGestureType );
|
2017-06-05 13:15:38 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_X11
|
2017-06-06 15:00:48 +00:00
|
|
|
scanFlag = new ScanFlag( this );
|
2017-06-05 13:15:38 +00:00
|
|
|
|
2023-06-05 13:22:20 +00:00
|
|
|
connect( scanFlag, &ScanFlag::requestScanPopup, this, [ this ] {
|
2022-11-20 05:39:41 +00:00
|
|
|
translateWordFromSelection();
|
2023-06-05 13:22:20 +00:00
|
|
|
} );
|
2017-06-13 15:00:16 +00:00
|
|
|
|
2023-06-05 11:30:14 +00:00
|
|
|
// Use delay show to prevent popup from showing up while selection is still in progress
|
|
|
|
// Only certain software has this problem (e.g. Chrome)
|
2022-12-29 02:36:02 +00:00
|
|
|
selectionDelayTimer.setSingleShot( true );
|
2023-06-05 11:30:14 +00:00
|
|
|
selectionDelayTimer.setInterval( cfg.preferences.selectionChangeDelayTimer );
|
2017-06-13 15:00:16 +00:00
|
|
|
|
2022-12-29 02:36:02 +00:00
|
|
|
connect( &selectionDelayTimer, &QTimer::timeout, this, &ScanPopup::translateWordFromSelection );
|
2017-06-05 13:15:38 +00:00
|
|
|
#endif
|
2019-01-28 12:43:06 +00:00
|
|
|
|
|
|
|
applyZoomFactor();
|
|
|
|
applyWordsZoomLevel();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-02-23 00:44:29 +00:00
|
|
|
void ScanPopup::refresh()
|
|
|
|
{
|
|
|
|
|
|
|
|
// TODO: GroupCombox's update should be moved inside GroupCombox
|
|
|
|
|
|
|
|
// currentIndexChanged() signal is very trigger-happy. To avoid triggering
|
|
|
|
// it, we disconnect it while we're clearing and filling back groups.
|
|
|
|
disconnect( ui.groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged );
|
2023-04-28 14:21:33 +00:00
|
|
|
|
|
|
|
auto OldGroupID = ui.groupList->getCurrentGroup();
|
|
|
|
|
|
|
|
// repopulate
|
2023-02-23 00:44:29 +00:00
|
|
|
ui.groupList->clear();
|
2023-04-28 14:21:33 +00:00
|
|
|
ui.groupList->fill( groups );
|
|
|
|
|
|
|
|
ui.groupList->setCurrentGroup( OldGroupID ); // This does nothing if OldGroupID doesn't exist;
|
|
|
|
|
2023-02-23 00:44:29 +00:00
|
|
|
ui.groupList->setVisible( !cfg.groups.empty() );
|
|
|
|
|
|
|
|
updateDictionaryBar();
|
|
|
|
|
|
|
|
connect( ui.groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged );
|
2023-06-05 11:30:14 +00:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
selectionDelayTimer.setInterval( cfg.preferences.selectionChangeDelayTimer );
|
|
|
|
#endif
|
2023-02-23 00:44:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-08 20:20:02 +00:00
|
|
|
ScanPopup::~ScanPopup()
|
|
|
|
{
|
2018-03-27 18:01:33 +00:00
|
|
|
saveConfigData();
|
2010-03-30 20:15:55 +00:00
|
|
|
|
2014-02-05 13:41:49 +00:00
|
|
|
ungrabGesture( Gestures::GDPinchGestureType );
|
|
|
|
ungrabGesture( Gestures::GDSwipeGestureType );
|
2009-02-08 20:20:02 +00:00
|
|
|
}
|
|
|
|
|
2018-03-27 18:01:33 +00:00
|
|
|
void ScanPopup::saveConfigData()
|
|
|
|
{
|
|
|
|
// Save state, geometry and pin status
|
2023-06-09 11:56:04 +00:00
|
|
|
cfg.popupWindowState = saveState();
|
|
|
|
cfg.popupWindowGeometry = saveGeometry();
|
2018-03-27 18:01:33 +00:00
|
|
|
cfg.pinPopupWindow = ui.pinButton->isChecked();
|
|
|
|
cfg.popupWindowAlwaysOnTop = ui.onTopButton->isChecked();
|
|
|
|
}
|
|
|
|
|
2022-09-08 13:11:25 +00:00
|
|
|
void ScanPopup::inspectElementWhenPinned( QWebEnginePage * page )
|
|
|
|
{
|
|
|
|
if ( cfg.pinPopupWindow )
|
|
|
|
emit inspectSignal( page );
|
|
|
|
}
|
|
|
|
|
2009-04-30 20:20:05 +00:00
|
|
|
void ScanPopup::applyZoomFactor()
|
|
|
|
{
|
|
|
|
definition->setZoomFactor( cfg.preferences.zoomFactor );
|
|
|
|
}
|
|
|
|
|
2017-07-14 13:02:21 +00:00
|
|
|
void ScanPopup::applyWordsZoomLevel()
|
|
|
|
{
|
|
|
|
QFont font( wordListDefaultFont );
|
|
|
|
int ps = font.pointSize();
|
|
|
|
|
|
|
|
if ( cfg.preferences.wordsZoomLevel != 0 ) {
|
|
|
|
ps += cfg.preferences.wordsZoomLevel;
|
|
|
|
if ( ps < 1 )
|
|
|
|
ps = 1;
|
|
|
|
font.setPointSize( ps );
|
|
|
|
}
|
|
|
|
|
2023-06-05 13:22:20 +00:00
|
|
|
if ( ui.translateBox->completerWidget()->font().pointSize() != ps )
|
|
|
|
ui.translateBox->completerWidget()->setFont( font );
|
2017-07-14 13:02:21 +00:00
|
|
|
|
|
|
|
font = translateLineDefaultFont;
|
2023-06-05 13:22:20 +00:00
|
|
|
ps = font.pointSize();
|
2017-07-14 13:02:21 +00:00
|
|
|
|
|
|
|
if ( cfg.preferences.wordsZoomLevel != 0 ) {
|
|
|
|
ps += cfg.preferences.wordsZoomLevel;
|
|
|
|
if ( ps < 1 )
|
|
|
|
ps = 1;
|
|
|
|
font.setPointSize( ps );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ui.translateBox->translateLine()->font().pointSize() != ps )
|
|
|
|
ui.translateBox->translateLine()->setFont( font );
|
|
|
|
|
2019-01-26 19:11:27 +00:00
|
|
|
font = groupListDefaultFont;
|
|
|
|
ps = font.pointSize();
|
|
|
|
|
|
|
|
if ( cfg.preferences.wordsZoomLevel != 0 ) {
|
|
|
|
ps += cfg.preferences.wordsZoomLevel;
|
|
|
|
if ( ps < 1 )
|
|
|
|
ps = 1;
|
|
|
|
font.setPointSize( ps );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ui.groupList->font().pointSize() != ps ) {
|
2022-04-01 15:32:11 +00:00
|
|
|
disconnect( ui.groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged );
|
2019-01-26 19:11:27 +00:00
|
|
|
int n = ui.groupList->currentIndex();
|
|
|
|
ui.groupList->clear();
|
|
|
|
ui.groupList->setFont( font );
|
|
|
|
ui.groupList->fill( groups );
|
|
|
|
ui.groupList->setCurrentIndex( n );
|
2022-04-01 15:32:11 +00:00
|
|
|
connect( ui.groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged );
|
2019-01-26 19:11:27 +00:00
|
|
|
}
|
2017-07-14 13:02:21 +00:00
|
|
|
|
2019-01-26 19:11:27 +00:00
|
|
|
ui.outerFrame->layout()->activate();
|
2017-07-14 13:02:21 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
Qt::WindowFlags ScanPopup::unpinnedWindowFlags() const
|
|
|
|
{
|
|
|
|
return defaultUnpinnedWindowFlags;
|
|
|
|
}
|
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
void ScanPopup::translateWordFromClipboard()
|
|
|
|
{
|
2023-06-05 13:22:20 +00:00
|
|
|
return translateWordFromClipboard( QClipboard::Clipboard );
|
2009-07-31 11:40:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::translateWordFromSelection()
|
|
|
|
{
|
2023-06-05 13:22:20 +00:00
|
|
|
return translateWordFromClipboard( QClipboard::Selection );
|
2009-07-31 11:40:54 +00:00
|
|
|
}
|
|
|
|
|
2010-05-08 14:01:59 +00:00
|
|
|
void ScanPopup::editGroupRequested()
|
|
|
|
{
|
2023-06-11 11:51:24 +00:00
|
|
|
emit editGroupRequest( ui.groupList->getCurrentGroup() );
|
2010-05-08 14:01:59 +00:00
|
|
|
}
|
|
|
|
|
2009-07-31 11:40:54 +00:00
|
|
|
void ScanPopup::translateWordFromClipboard( QClipboard::Mode m )
|
|
|
|
{
|
2022-08-14 15:13:35 +00:00
|
|
|
qDebug() << "translating from clipboard or selection";
|
2009-04-21 18:27:26 +00:00
|
|
|
|
|
|
|
QString subtype = "plain";
|
|
|
|
|
2009-07-31 11:40:54 +00:00
|
|
|
QString str = QApplication::clipboard()->text( subtype, m );
|
2022-08-14 15:13:35 +00:00
|
|
|
qDebug() << "clipboard data:" << str;
|
2011-11-16 13:02:56 +00:00
|
|
|
translateWord( str );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::translateWord( QString const & word )
|
|
|
|
{
|
2023-05-28 16:01:54 +00:00
|
|
|
pendingWord = cfg.preferences.sanitizeInputPhrase( word );
|
2009-04-21 18:27:26 +00:00
|
|
|
|
2023-05-28 16:01:54 +00:00
|
|
|
if ( pendingWord.isEmpty() )
|
2009-04-21 18:27:26 +00:00
|
|
|
return; // Nothing there
|
|
|
|
|
2017-06-06 15:00:48 +00:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
emit hideScanFlag();
|
|
|
|
#endif
|
|
|
|
|
2013-01-28 12:19:11 +00:00
|
|
|
engagePopup( false,
|
2013-05-31 04:28:29 +00:00
|
|
|
#ifdef Q_OS_WIN
|
2013-01-28 12:19:11 +00:00
|
|
|
true // We only focus popup under Windows when activated via Ctrl+C+C
|
|
|
|
// -- on Linux it already has an implicit focus
|
|
|
|
#else
|
|
|
|
false
|
|
|
|
#endif
|
|
|
|
);
|
2009-04-21 18:27:26 +00:00
|
|
|
}
|
|
|
|
|
2023-05-28 16:01:54 +00:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
void ScanPopup::showEngagePopup()
|
2009-02-02 20:28:53 +00:00
|
|
|
{
|
2023-05-28 16:01:54 +00:00
|
|
|
engagePopup( false );
|
2009-02-02 20:28:53 +00:00
|
|
|
}
|
2023-05-28 16:01:54 +00:00
|
|
|
#endif
|
2009-02-02 20:28:53 +00:00
|
|
|
|
2012-09-24 13:20:58 +00:00
|
|
|
[[deprecated]] void ScanPopup::handleInputWord( QString const & str, bool forcePopup )
|
2009-02-02 20:28:53 +00:00
|
|
|
{
|
2023-05-28 16:01:54 +00:00
|
|
|
auto sanitizedPhrase = cfg.preferences.sanitizeInputPhrase( str );
|
2010-12-03 20:10:18 +00:00
|
|
|
|
2023-05-28 16:01:54 +00:00
|
|
|
if ( isVisible() && sanitizedPhrase == pendingWord ) {
|
2010-12-03 20:10:18 +00:00
|
|
|
// Attempt to translate the same word we already have shown in scan popup.
|
|
|
|
// Ignore it, as it is probably a spurious mouseover event.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-28 16:01:54 +00:00
|
|
|
pendingWord = sanitizedPhrase;
|
2009-04-11 16:44:14 +00:00
|
|
|
|
2017-06-05 13:15:38 +00:00
|
|
|
#ifdef HAVE_X11
|
|
|
|
if ( cfg.preferences.showScanFlag ) {
|
2022-11-20 05:14:36 +00:00
|
|
|
emit showScanFlag();
|
2017-06-05 13:15:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-09-24 13:20:58 +00:00
|
|
|
engagePopup( forcePopup );
|
2009-04-11 16:44:14 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 13:20:58 +00:00
|
|
|
void ScanPopup::engagePopup( bool forcePopup, bool giveFocus )
|
2009-04-11 16:44:14 +00:00
|
|
|
{
|
2012-09-24 13:20:58 +00:00
|
|
|
if ( cfg.preferences.scanToMainWindow && !forcePopup ) {
|
2011-11-16 12:52:25 +00:00
|
|
|
// Send translated word to main window istead of show popup
|
2023-05-31 08:17:16 +00:00
|
|
|
emit sendPhraseToMainWindow( pendingWord );
|
2011-11-16 12:52:25 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-26 13:59:48 +00:00
|
|
|
definition->setSelectionBySingleClick( cfg.preferences.selectWordBySingleClick );
|
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
if ( !isVisible() ) {
|
2009-12-27 12:00:59 +00:00
|
|
|
// Need to show the window
|
2009-02-08 16:35:30 +00:00
|
|
|
|
2009-12-27 12:00:59 +00:00
|
|
|
if ( !ui.pinButton->isChecked() ) {
|
|
|
|
// Decide where should the window land
|
|
|
|
|
|
|
|
QPoint currentPos = QCursor::pos();
|
|
|
|
|
2023-05-13 12:05:47 +00:00
|
|
|
auto screen = QGuiApplication::screenAt( currentPos );
|
|
|
|
if ( !screen )
|
|
|
|
return;
|
|
|
|
|
|
|
|
QRect desktop = screen->geometry();
|
2009-12-27 12:00:59 +00:00
|
|
|
|
|
|
|
QSize windowSize = geometry().size();
|
|
|
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
/// Try the to-the-right placement
|
|
|
|
if ( currentPos.x() + 4 + windowSize.width() <= desktop.topRight().x() )
|
|
|
|
x = currentPos.x() + 4;
|
|
|
|
else
|
|
|
|
/// Try the to-the-left placement
|
|
|
|
if ( currentPos.x() - 4 - windowSize.width() >= desktop.x() )
|
|
|
|
x = currentPos.x() - 4 - windowSize.width();
|
|
|
|
else
|
|
|
|
// Center it
|
|
|
|
x = desktop.x() + ( desktop.width() - windowSize.width() ) / 2;
|
|
|
|
|
|
|
|
/// Try the to-the-bottom placement
|
|
|
|
if ( currentPos.y() + 15 + windowSize.height() <= desktop.bottomLeft().y() )
|
|
|
|
y = currentPos.y() + 15;
|
|
|
|
else
|
|
|
|
/// Try the to-the-top placement
|
|
|
|
if ( currentPos.y() - 15 - windowSize.height() >= desktop.y() )
|
|
|
|
y = currentPos.y() - 15 - windowSize.height();
|
|
|
|
else
|
|
|
|
// Center it
|
|
|
|
y = desktop.y() + ( desktop.height() - windowSize.height() ) / 2;
|
|
|
|
|
|
|
|
move( x, y );
|
|
|
|
}
|
2023-02-14 14:51:03 +00:00
|
|
|
else {
|
|
|
|
if ( pinnedGeometry.size() > 0 )
|
|
|
|
restoreGeometry( pinnedGeometry );
|
|
|
|
}
|
2009-02-01 00:08:08 +00:00
|
|
|
|
|
|
|
show();
|
|
|
|
|
2022-09-25 04:49:22 +00:00
|
|
|
#if defined( HAVE_X11 )
|
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
|
|
|
// Ensure that the window always has focus on X11 with Qt::Tool flag.
|
|
|
|
// This also often prevents the window from disappearing prematurely with Qt::Popup flag,
|
|
|
|
// especially when combined with Qt::X11BypassWindowManagerHint flag.
|
|
|
|
if ( !ui.pinButton->isChecked() )
|
|
|
|
giveFocus = true;
|
|
|
|
#endif
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
if ( giveFocus ) {
|
|
|
|
activateWindow();
|
|
|
|
raise();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !ui.pinButton->isChecked() ) {
|
|
|
|
mouseEnteredOnce = false;
|
|
|
|
// Need to monitor the mouse so we know when to hide the window
|
|
|
|
interceptMouse();
|
|
|
|
}
|
|
|
|
|
2009-02-08 16:35:30 +00:00
|
|
|
// This produced some funky mouse grip-related bugs so we commented it out
|
|
|
|
//QApplication::processEvents(); // Make window appear immediately no matter what
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
2023-03-17 01:54:45 +00:00
|
|
|
else if ( ui.pinButton->isChecked() ) {
|
2009-12-27 12:00:59 +00:00
|
|
|
// Pinned-down window isn't always on top, so we need to raise it
|
|
|
|
show();
|
2023-03-17 01:54:45 +00:00
|
|
|
if ( cfg.preferences.raiseWindowOnSearch ) {
|
|
|
|
activateWindow();
|
|
|
|
raise();
|
|
|
|
}
|
2009-12-27 12:00:59 +00:00
|
|
|
}
|
2022-09-25 04:49:22 +00:00
|
|
|
#if defined( HAVE_X11 )
|
2023-03-17 01:54:45 +00:00
|
|
|
else if ( ( windowFlags() & Qt::Tool ) == Qt::Tool && cfg.preferences.raiseWindowOnSearch ) {
|
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
|
|
|
// Ensure that the window with Qt::Tool flag always has focus on X11.
|
|
|
|
activateWindow();
|
|
|
|
raise();
|
|
|
|
}
|
|
|
|
#endif
|
2009-02-01 00:08:08 +00:00
|
|
|
|
2013-01-26 15:55:17 +00:00
|
|
|
if ( ui.pinButton->isChecked() )
|
2013-02-01 12:36:01 +00:00
|
|
|
setWindowTitle( tr( "%1 - %2" ).arg( elideInputWord(), "GoldenDict" ) );
|
2013-01-26 15:55:17 +00:00
|
|
|
|
2014-05-09 18:53:19 +00:00
|
|
|
/// Too large strings make window expand which is probably not what user
|
|
|
|
/// wants
|
2023-05-28 16:01:54 +00:00
|
|
|
ui.translateBox->setText( Folding::escapeWildcardSymbols( pendingWord ), false );
|
2014-05-09 18:53:19 +00:00
|
|
|
|
2023-05-28 16:01:54 +00:00
|
|
|
showTranslationFor( pendingWord );
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2009-02-05 20:55:00 +00:00
|
|
|
QString ScanPopup::elideInputWord()
|
|
|
|
{
|
2023-05-28 16:01:54 +00:00
|
|
|
return pendingWord.size() > 32 ? pendingWord.mid( 0, 32 ) + "..." : pendingWord;
|
2009-02-05 20:55:00 +00:00
|
|
|
}
|
2023-05-28 16:01:54 +00:00
|
|
|
|
2022-02-27 06:26:49 +00:00
|
|
|
void ScanPopup::currentGroupChanged( int )
|
2009-02-01 00:08:08 +00:00
|
|
|
{
|
2012-09-26 13:13:47 +00:00
|
|
|
cfg.lastPopupGroupId = ui.groupList->getCurrentGroup();
|
|
|
|
Instances::Group const * igrp = groups.findGroup( cfg.lastPopupGroupId );
|
|
|
|
if ( cfg.lastPopupGroupId == Instances::Group::AllGroupId ) {
|
|
|
|
if ( igrp )
|
|
|
|
igrp->checkMutedDictionaries( &cfg.popupMutedDictionaries );
|
|
|
|
dictionaryBar.setMutedDictionaries( &cfg.popupMutedDictionaries );
|
2023-07-20 08:02:22 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-09-26 13:13:47 +00:00
|
|
|
Config::Group * grp = cfg.getGroup( cfg.lastPopupGroupId );
|
2010-04-30 09:56:40 +00:00
|
|
|
if ( grp ) {
|
2012-09-26 13:13:47 +00:00
|
|
|
if ( igrp )
|
|
|
|
igrp->checkMutedDictionaries( &grp->popupMutedDictionaries );
|
|
|
|
dictionaryBar.setMutedDictionaries( &grp->popupMutedDictionaries );
|
|
|
|
}
|
|
|
|
else
|
2023-06-05 13:22:20 +00:00
|
|
|
dictionaryBar.setMutedDictionaries( nullptr );
|
2012-09-26 13:13:47 +00:00
|
|
|
}
|
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
updateDictionaryBar();
|
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
if ( isVisible() ) {
|
2021-06-10 16:13:11 +00:00
|
|
|
updateSuggestionList();
|
2013-01-27 22:12:00 +00:00
|
|
|
translateInputFinished();
|
|
|
|
}
|
2009-02-06 17:04:11 +00:00
|
|
|
|
2009-04-10 12:48:40 +00:00
|
|
|
cfg.lastPopupGroupId = ui.groupList->getCurrentGroup();
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-25 15:42:44 +00:00
|
|
|
void ScanPopup::translateInputChanged( QString const & text )
|
2021-06-10 16:13:11 +00:00
|
|
|
{
|
|
|
|
updateSuggestionList( text );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::updateSuggestionList()
|
|
|
|
{
|
|
|
|
updateSuggestionList( ui.translateBox->translateLine()->text() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::updateSuggestionList( QString const & text )
|
2013-01-25 15:42:44 +00:00
|
|
|
{
|
|
|
|
mainStatusBar->clearMessage();
|
|
|
|
|
|
|
|
QString req = text.trimmed();
|
|
|
|
|
|
|
|
if ( !req.size() ) {
|
|
|
|
// An empty request always results in an empty result
|
|
|
|
wordFinder.cancel();
|
|
|
|
|
|
|
|
// Reset the noResults mark if it's on right now
|
|
|
|
if ( ui.translateBox->translateLine()->property( "noResults" ).toBool() ) {
|
2023-03-22 01:01:22 +00:00
|
|
|
auto translateLine = ui.translateBox->translateLine();
|
|
|
|
translateLine->setProperty( "noResults", false );
|
|
|
|
|
|
|
|
Utils::Widget::setNoResultColor( translateLine, false );
|
2013-01-25 15:42:44 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wordFinder.prefixMatch( req, getActiveDicts() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::translateInputFinished()
|
|
|
|
{
|
2023-05-28 16:01:54 +00:00
|
|
|
pendingWord = Folding::unescapeWildcardSymbols( ui.translateBox->translateLine()->text().trimmed() );
|
|
|
|
showTranslationFor( pendingWord );
|
2013-01-25 15:42:44 +00:00
|
|
|
}
|
|
|
|
|
2023-05-28 16:01:54 +00:00
|
|
|
void ScanPopup::showTranslationFor( QString const & word )
|
2013-01-25 15:42:44 +00:00
|
|
|
{
|
2023-04-30 03:39:28 +00:00
|
|
|
ui.pronounceButton->setDisabled( true );
|
2009-04-11 16:44:14 +00:00
|
|
|
|
2017-10-23 14:21:43 +00:00
|
|
|
unsigned groupId = ui.groupList->getCurrentGroup();
|
2023-05-28 16:01:54 +00:00
|
|
|
definition->showDefinition( word, groupId );
|
2013-01-25 15:42:44 +00:00
|
|
|
definition->focus();
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vector< sptr< Dictionary::Class > > const & ScanPopup::getActiveDicts()
|
|
|
|
{
|
2010-04-30 09:56:40 +00:00
|
|
|
int current = ui.groupList->currentIndex();
|
2009-02-01 00:08:08 +00:00
|
|
|
|
2023-02-23 00:44:29 +00:00
|
|
|
Q_ASSERT( 0 <= current || current <= groups.size() );
|
2010-04-30 09:56:40 +00:00
|
|
|
|
2012-09-26 13:13:47 +00:00
|
|
|
Config::MutedDictionaries const * mutedDictionaries = dictionaryBar.getMutedDictionaries();
|
2010-04-30 09:56:40 +00:00
|
|
|
|
2023-04-10 14:12:54 +00:00
|
|
|
if ( !dictionaryBar.toggleViewAction()->isChecked() || mutedDictionaries == nullptr ) {
|
2023-02-23 00:44:29 +00:00
|
|
|
return groups[ current ].dictionaries;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector< sptr< Dictionary::Class > > const & activeDicts = groups[ current ].dictionaries;
|
2010-04-30 09:56:40 +00:00
|
|
|
|
2023-02-23 00:44:29 +00:00
|
|
|
// Populate the special dictionariesUnmuted array with only unmuted
|
|
|
|
// dictionaries
|
2010-04-30 09:56:40 +00:00
|
|
|
|
2023-02-23 00:44:29 +00:00
|
|
|
dictionariesUnmuted.clear();
|
|
|
|
dictionariesUnmuted.reserve( activeDicts.size() );
|
2010-04-30 09:56:40 +00:00
|
|
|
|
2023-02-23 00:44:29 +00:00
|
|
|
for ( const auto & activeDict : activeDicts ) {
|
|
|
|
if ( !mutedDictionaries->contains( QString::fromStdString( activeDict->getId() ) ) ) {
|
|
|
|
dictionariesUnmuted.push_back( activeDict );
|
|
|
|
}
|
2010-04-30 09:56:40 +00:00
|
|
|
}
|
2023-02-23 00:44:29 +00:00
|
|
|
|
|
|
|
return dictionariesUnmuted;
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-25 15:42:44 +00:00
|
|
|
void ScanPopup::typingEvent( QString const & t )
|
|
|
|
{
|
2023-04-17 15:19:29 +00:00
|
|
|
if ( t == "\n" || t == "\r" ) {
|
2013-01-25 15:42:44 +00:00
|
|
|
focusTranslateLine();
|
|
|
|
}
|
2023-04-17 15:19:29 +00:00
|
|
|
else {
|
|
|
|
ui.translateBox->translateLine()->clear();
|
|
|
|
ui.translateBox->translateLine()->setFocus();
|
|
|
|
ui.translateBox->setText( t, true );
|
|
|
|
ui.translateBox->translateLine()->setCursorPosition( t.size() );
|
2013-01-25 15:42:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
bool ScanPopup::eventFilter( QObject * watched, QEvent * event )
|
|
|
|
{
|
2023-04-10 14:12:54 +00:00
|
|
|
if ( watched == ui.translateBox->translateLine() && event->type() == QEvent::FocusIn ) {
|
|
|
|
const QFocusEvent * focusEvent = static_cast< QFocusEvent * >( event );
|
2013-01-25 15:42:44 +00:00
|
|
|
|
2023-04-10 14:12:54 +00:00
|
|
|
// select all on mouse click
|
|
|
|
if ( focusEvent->reason() == Qt::MouseFocusReason ) {
|
|
|
|
QTimer::singleShot( 0, this, &ScanPopup::focusTranslateLine );
|
2019-01-29 11:01:30 +00:00
|
|
|
}
|
2023-04-10 14:12:54 +00:00
|
|
|
return false;
|
2013-01-25 15:42:44 +00:00
|
|
|
}
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
if ( mouseIntercepted ) {
|
|
|
|
// We're only interested in our events
|
|
|
|
|
|
|
|
if ( event->type() == QEvent::MouseMove ) {
|
|
|
|
QMouseEvent * mouseEvent = (QMouseEvent *)event;
|
2010-07-03 16:24:30 +00:00
|
|
|
reactOnMouseMove( mouseEvent->globalPos() );
|
|
|
|
}
|
|
|
|
}
|
2010-01-02 23:26:09 +00:00
|
|
|
|
2023-04-17 15:19:29 +00:00
|
|
|
if ( event->type() == QEvent::KeyPress && watched != ui.translateBox->translateLine() ) {
|
|
|
|
|
|
|
|
if ( const auto key_event = dynamic_cast< QKeyEvent * >( event ); key_event->modifiers() == Qt::NoModifier ) {
|
|
|
|
const QString text = key_event->text();
|
|
|
|
|
|
|
|
if ( Utils::ignoreKeyEvent( key_event ) || key_event->key() == Qt::Key_Return
|
|
|
|
|| key_event->key() == Qt::Key_Enter )
|
|
|
|
return false; // Those key have other uses than to start typing
|
|
|
|
// or don't make sense
|
|
|
|
if ( !text.isEmpty() ) {
|
|
|
|
typingEvent( text );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-03 16:24:30 +00:00
|
|
|
return QMainWindow::eventFilter( watched, event );
|
|
|
|
}
|
2010-01-02 23:26:09 +00:00
|
|
|
|
2010-07-03 16:24:30 +00:00
|
|
|
void ScanPopup::reactOnMouseMove( QPoint const & p )
|
|
|
|
{
|
|
|
|
if ( geometry().contains( p ) ) {
|
2022-01-15 07:29:20 +00:00
|
|
|
// GD_DPRINTF( "got inside\n" );
|
2010-01-02 23:26:09 +00:00
|
|
|
|
2010-07-03 16:24:30 +00:00
|
|
|
hideTimer.stop();
|
|
|
|
mouseEnteredOnce = true;
|
|
|
|
uninterceptMouse();
|
|
|
|
}
|
|
|
|
else {
|
2022-01-15 07:29:20 +00:00
|
|
|
// GD_DPRINTF( "outside\n" );
|
2010-07-03 16:24:30 +00:00
|
|
|
// We're in grab mode and outside the window - calculate the
|
|
|
|
// distance from it. We might want to hide it.
|
|
|
|
|
|
|
|
// When the mouse has entered once, we don't allow it stayng outside,
|
|
|
|
// but we give a grace period for it to return.
|
|
|
|
int proximity = mouseEnteredOnce ? 0 : 60;
|
|
|
|
|
|
|
|
// Note: watched == this ensures no other child objects popping out are
|
|
|
|
// receiving this event, meaning there's basically nothing under the
|
|
|
|
// cursor.
|
|
|
|
if ( /*watched == this &&*/
|
|
|
|
!frameGeometry().adjusted( -proximity, -proximity, proximity, proximity ).contains( p ) ) {
|
|
|
|
// We've way too far from the window -- hide the popup
|
|
|
|
|
|
|
|
// If the mouse never entered the popup, hide the window instantly --
|
|
|
|
// the user just moved the cursor further away from the window.
|
|
|
|
|
|
|
|
if ( !mouseEnteredOnce )
|
|
|
|
hideWindow();
|
|
|
|
else
|
|
|
|
hideTimer.start();
|
2010-01-02 23:26:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-06 18:43:07 +00:00
|
|
|
void ScanPopup::mousePressEvent( QMouseEvent * ev )
|
|
|
|
{
|
2010-01-02 23:26:09 +00:00
|
|
|
// With mouse grabs, the press can occur anywhere on the screen, which
|
|
|
|
// might mean hiding the window.
|
|
|
|
|
|
|
|
if ( !frameGeometry().contains( ev->globalPos() ) ) {
|
|
|
|
hideWindow();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
if ( ev->button() == Qt::LeftButton ) {
|
|
|
|
startPos = ev->globalPos();
|
|
|
|
setCursor( Qt::ClosedHandCursor );
|
|
|
|
}
|
2009-02-06 18:43:07 +00:00
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow::mousePressEvent( ev );
|
2009-02-06 18:43:07 +00:00
|
|
|
}
|
|
|
|
|
2009-02-06 13:05:25 +00:00
|
|
|
void ScanPopup::mouseMoveEvent( QMouseEvent * event )
|
|
|
|
{
|
2010-01-02 23:26:09 +00:00
|
|
|
if ( event->buttons() && cursor().shape() == Qt::ClosedHandCursor ) {
|
2009-02-06 18:43:07 +00:00
|
|
|
QPoint newPos = event->globalPos();
|
|
|
|
|
|
|
|
QPoint delta = newPos - startPos;
|
|
|
|
|
|
|
|
startPos = newPos;
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
// Move the window
|
2009-02-06 18:43:07 +00:00
|
|
|
|
|
|
|
move( pos() + delta );
|
|
|
|
}
|
2017-06-05 13:15:38 +00:00
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow::mouseMoveEvent( event );
|
2009-02-06 13:05:25 +00:00
|
|
|
}
|
|
|
|
|
2009-02-06 18:43:07 +00:00
|
|
|
void ScanPopup::mouseReleaseEvent( QMouseEvent * ev )
|
|
|
|
{
|
|
|
|
unsetCursor();
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow::mouseReleaseEvent( ev );
|
2009-02-06 18:43:07 +00:00
|
|
|
}
|
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
void ScanPopup::leaveEvent( QEvent * event )
|
|
|
|
{
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow::leaveEvent( event );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
// We hide the popup when the mouse leaves it.
|
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
// Combo-boxes seem to generate leave events for their parents when
|
|
|
|
// unfolded, so we check coordinates as well.
|
2009-02-06 18:43:07 +00:00
|
|
|
// If the dialog is pinned, we don't hide the popup.
|
|
|
|
// If some mouse buttons are pressed, we don't hide the popup either,
|
|
|
|
// since it indicates the move operation is underway.
|
|
|
|
if ( !ui.pinButton->isChecked() && !geometry().contains( QCursor::pos() )
|
|
|
|
&& QApplication::mouseButtons() == Qt::NoButton ) {
|
2009-04-10 13:56:38 +00:00
|
|
|
hideTimer.start();
|
2009-02-06 18:43:07 +00:00
|
|
|
}
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2022-02-27 05:17:37 +00:00
|
|
|
#if ( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) )
|
|
|
|
void ScanPopup::enterEvent( QEnterEvent * event )
|
|
|
|
#else
|
2009-04-10 13:56:38 +00:00
|
|
|
void ScanPopup::enterEvent( QEvent * event )
|
2022-02-27 05:17:37 +00:00
|
|
|
#endif
|
2009-04-10 13:56:38 +00:00
|
|
|
{
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow::enterEvent( event );
|
2009-04-10 13:56:38 +00:00
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
if ( mouseEnteredOnce ) {
|
|
|
|
// We "enter" first time via our event filter. This seems to evade some
|
|
|
|
// unexpected behavior under Windows.
|
|
|
|
|
|
|
|
// If there was a countdown to hide the window, stop it.
|
|
|
|
hideTimer.stop();
|
|
|
|
}
|
2009-04-10 13:56:38 +00:00
|
|
|
}
|
|
|
|
|
2013-01-29 21:30:24 +00:00
|
|
|
void ScanPopup::requestWindowFocus()
|
|
|
|
{
|
|
|
|
// One of the rare, actually working workarounds for requesting a user keyboard focus on X11,
|
|
|
|
// works for Qt::Popup windows, exactly like our Scan Popup (in unpinned state).
|
|
|
|
// Modern window managers actively resist to automatically focus pop-up windows.
|
|
|
|
}
|
|
|
|
|
2009-02-08 21:26:35 +00:00
|
|
|
void ScanPopup::showEvent( QShowEvent * ev )
|
|
|
|
{
|
2010-03-30 20:15:55 +00:00
|
|
|
QMainWindow::showEvent( ev );
|
2013-01-29 21:30:24 +00:00
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
QTimer::singleShot( 100, this, &ScanPopup::requestWindowFocus );
|
2017-06-05 13:15:38 +00:00
|
|
|
|
2009-05-18 18:01:50 +00:00
|
|
|
if ( groups.size() <= 1 ) // Only the default group? Hide then.
|
2009-02-08 21:26:35 +00:00
|
|
|
ui.groupList->hide();
|
2010-03-30 20:15:55 +00:00
|
|
|
|
|
|
|
if ( ui.showDictionaryBar->isChecked() != dictionaryBar.isVisible() ) {
|
|
|
|
ui.showDictionaryBar->setChecked( dictionaryBar.isVisible() );
|
|
|
|
updateDictionaryBar();
|
|
|
|
}
|
2009-02-08 21:26:35 +00:00
|
|
|
}
|
|
|
|
|
2023-02-14 14:51:03 +00:00
|
|
|
void ScanPopup::closeEvent( QCloseEvent * ev )
|
|
|
|
{
|
|
|
|
if ( isVisible() && ui.pinButton->isChecked() )
|
|
|
|
pinnedGeometry = saveGeometry();
|
|
|
|
|
|
|
|
QMainWindow::closeEvent( ev );
|
|
|
|
}
|
|
|
|
|
2023-02-14 19:40:08 +00:00
|
|
|
void ScanPopup::moveEvent( QMoveEvent * ev )
|
|
|
|
{
|
|
|
|
if ( isVisible() && ui.pinButton->isChecked() )
|
|
|
|
pinnedGeometry = saveGeometry();
|
|
|
|
|
|
|
|
QMainWindow::moveEvent( ev );
|
|
|
|
}
|
|
|
|
|
2009-03-26 19:00:08 +00:00
|
|
|
void ScanPopup::prefixMatchFinished()
|
2009-02-01 00:08:08 +00:00
|
|
|
{
|
2009-03-26 19:00:08 +00:00
|
|
|
// Check that there's a window there at all
|
|
|
|
if ( isVisible() ) {
|
|
|
|
if ( wordFinder.getErrorString().size() ) {
|
|
|
|
ui.queryError->setToolTip( wordFinder.getErrorString() );
|
|
|
|
ui.queryError->show();
|
2023-06-05 13:22:20 +00:00
|
|
|
showStatusBarMessage( tr( "WARNING: %1" ).arg( wordFinder.getErrorString() ),
|
|
|
|
20000,
|
|
|
|
QPixmap( ":/icons/error.svg" ) );
|
2009-03-26 19:00:08 +00:00
|
|
|
}
|
2023-06-05 13:22:20 +00:00
|
|
|
else {
|
2009-03-26 19:00:08 +00:00
|
|
|
ui.queryError->hide();
|
2023-06-05 13:22:20 +00:00
|
|
|
auto results = wordFinder.getResults();
|
|
|
|
QStringList _results;
|
|
|
|
for ( auto const & [ fst, snd ] : results ) {
|
|
|
|
_results << fst;
|
|
|
|
}
|
|
|
|
|
|
|
|
ui.translateBox->setModel( _results );
|
|
|
|
}
|
2009-04-10 15:52:08 +00:00
|
|
|
}
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2009-04-10 21:07:03 +00:00
|
|
|
void ScanPopup::on_pronounceButton_clicked()
|
|
|
|
{
|
|
|
|
definition->playSound();
|
|
|
|
}
|
|
|
|
|
2009-02-01 00:08:08 +00:00
|
|
|
void ScanPopup::pinButtonClicked( bool checked )
|
|
|
|
{
|
|
|
|
if ( checked ) {
|
2010-01-02 23:26:09 +00:00
|
|
|
uninterceptMouse();
|
|
|
|
|
2017-07-13 15:00:19 +00:00
|
|
|
ui.onTopButton->setVisible( true );
|
2019-05-11 10:55:52 +00:00
|
|
|
Qt::WindowFlags flags = pinnedWindowFlags;
|
2017-07-13 15:00:19 +00:00
|
|
|
if ( ui.onTopButton->isChecked() )
|
|
|
|
flags |= Qt::WindowStaysOnTopHint;
|
|
|
|
setWindowFlags( flags );
|
|
|
|
|
2022-10-19 12:19:02 +00:00
|
|
|
#ifdef Q_OS_MACOS
|
|
|
|
setAttribute( Qt::WA_MacAlwaysShowToolWindow );
|
|
|
|
#endif
|
|
|
|
|
2013-02-01 12:36:01 +00:00
|
|
|
setWindowTitle( tr( "%1 - %2" ).arg( elideInputWord(), "GoldenDict" ) );
|
2010-03-30 20:15:55 +00:00
|
|
|
dictionaryBar.setMovable( true );
|
2009-04-10 13:56:38 +00:00
|
|
|
hideTimer.stop();
|
2009-02-05 20:55:00 +00:00
|
|
|
}
|
2009-02-01 00:08:08 +00:00
|
|
|
else {
|
2017-07-13 15:00:19 +00:00
|
|
|
ui.onTopButton->setVisible( false );
|
2010-03-30 20:15:55 +00:00
|
|
|
dictionaryBar.setMovable( 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
|
|
|
setWindowFlags( unpinnedWindowFlags() );
|
2010-01-02 23:26:09 +00:00
|
|
|
|
2022-10-19 12:19:02 +00:00
|
|
|
#ifdef Q_OS_MACOS
|
|
|
|
setAttribute( Qt::WA_MacAlwaysShowToolWindow, false );
|
|
|
|
#endif
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
mouseEnteredOnce = true;
|
|
|
|
}
|
2022-09-08 13:11:25 +00:00
|
|
|
cfg.pinPopupWindow = checked;
|
2009-02-01 00:08:08 +00:00
|
|
|
|
|
|
|
show();
|
2023-02-14 19:40:08 +00:00
|
|
|
|
|
|
|
if ( checked )
|
|
|
|
pinnedGeometry = saveGeometry();
|
2009-02-01 00:08:08 +00:00
|
|
|
}
|
2009-04-10 13:56:38 +00:00
|
|
|
|
2013-01-25 15:42:44 +00:00
|
|
|
void ScanPopup::focusTranslateLine()
|
|
|
|
{
|
|
|
|
if ( !isActiveWindow() )
|
|
|
|
activateWindow();
|
|
|
|
|
|
|
|
ui.translateBox->translateLine()->setFocus();
|
|
|
|
ui.translateBox->translateLine()->selectAll();
|
|
|
|
}
|
|
|
|
|
2010-03-30 20:15:55 +00:00
|
|
|
void ScanPopup::on_showDictionaryBar_clicked( bool checked )
|
|
|
|
{
|
|
|
|
dictionaryBar.setVisible( checked );
|
|
|
|
updateDictionaryBar();
|
|
|
|
definition->updateMutedContents();
|
|
|
|
}
|
|
|
|
|
2009-04-10 13:56:38 +00:00
|
|
|
void ScanPopup::hideTimerExpired()
|
|
|
|
{
|
|
|
|
if ( isVisible() )
|
2010-01-02 23:26:09 +00:00
|
|
|
hideWindow();
|
2009-04-10 13:56:38 +00:00
|
|
|
}
|
2009-04-10 21:07:03 +00:00
|
|
|
|
2009-05-14 19:42:04 +00:00
|
|
|
void ScanPopup::pageLoaded( ArticleView * )
|
2009-04-10 21:07:03 +00:00
|
|
|
{
|
2022-10-03 02:35:47 +00:00
|
|
|
if ( !isVisible() )
|
|
|
|
return;
|
|
|
|
auto pronounceBtn = ui.pronounceButton;
|
|
|
|
definition->hasSound( [ pronounceBtn ]( bool has ) {
|
|
|
|
if ( pronounceBtn )
|
2023-04-30 03:39:28 +00:00
|
|
|
pronounceBtn->setDisabled( !has );
|
2022-10-03 02:35:47 +00:00
|
|
|
} );
|
2009-04-10 21:07:03 +00:00
|
|
|
|
2012-12-24 12:59:46 +00:00
|
|
|
updateBackForwardButtons();
|
2009-04-10 21:07:03 +00:00
|
|
|
}
|
2009-05-16 11:14:43 +00:00
|
|
|
|
2011-07-14 20:11:57 +00:00
|
|
|
void ScanPopup::showStatusBarMessage( QString const & message, int timeout, QPixmap const & icon )
|
2011-07-14 08:17:59 +00:00
|
|
|
{
|
2011-07-14 20:11:57 +00:00
|
|
|
mainStatusBar->showMessage( message, timeout, icon );
|
2011-07-14 08:17:59 +00:00
|
|
|
}
|
|
|
|
|
2009-05-16 11:14:43 +00:00
|
|
|
void ScanPopup::escapePressed()
|
|
|
|
{
|
|
|
|
if ( !definition->closeSearch() )
|
2010-01-02 23:26:09 +00:00
|
|
|
hideWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::hideWindow()
|
|
|
|
{
|
|
|
|
uninterceptMouse();
|
|
|
|
|
2012-09-12 14:18:16 +00:00
|
|
|
emit closeMenu();
|
2010-01-02 23:26:09 +00:00
|
|
|
hideTimer.stop();
|
|
|
|
unsetCursor();
|
2013-01-27 22:12:00 +00:00
|
|
|
ui.translateBox->setPopupEnabled( false );
|
2013-01-29 22:04:18 +00:00
|
|
|
ui.translateBox->translateLine()->deselect();
|
2010-01-02 23:26:09 +00:00
|
|
|
hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::interceptMouse()
|
|
|
|
{
|
|
|
|
if ( !mouseIntercepted ) {
|
2010-07-03 16:24:30 +00:00
|
|
|
// We used to grab the mouse -- but this doesn't always work reliably
|
|
|
|
// (e.g. doesn't work at all in Windows 7 for some reason). Therefore
|
|
|
|
// we use a polling timer now.
|
|
|
|
|
|
|
|
// grabMouse();
|
|
|
|
mouseGrabPollTimer.start();
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
qApp->installEventFilter( this );
|
|
|
|
|
|
|
|
mouseIntercepted = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-03 16:24:30 +00:00
|
|
|
void ScanPopup::mouseGrabPoll()
|
|
|
|
{
|
|
|
|
if ( mouseIntercepted )
|
|
|
|
reactOnMouseMove( QCursor::pos() );
|
|
|
|
}
|
|
|
|
|
2010-01-02 23:26:09 +00:00
|
|
|
void ScanPopup::uninterceptMouse()
|
|
|
|
{
|
|
|
|
if ( mouseIntercepted ) {
|
|
|
|
qApp->removeEventFilter( this );
|
2010-07-03 16:24:30 +00:00
|
|
|
mouseGrabPollTimer.stop();
|
|
|
|
// releaseMouse();
|
2010-01-02 23:26:09 +00:00
|
|
|
|
|
|
|
mouseIntercepted = false;
|
2009-05-16 11:14:43 +00:00
|
|
|
}
|
|
|
|
}
|
2010-03-30 20:15:55 +00:00
|
|
|
|
|
|
|
void ScanPopup::updateDictionaryBar()
|
|
|
|
{
|
|
|
|
if ( !dictionaryBar.toggleViewAction()->isChecked() )
|
|
|
|
return; // It's not enabled, therefore hidden -- don't waste time
|
|
|
|
|
2012-09-26 13:13:47 +00:00
|
|
|
unsigned currentId = ui.groupList->getCurrentGroup();
|
|
|
|
Instances::Group const * grp = groups.findGroup( currentId );
|
2010-04-30 09:56:40 +00:00
|
|
|
|
|
|
|
if ( grp ) // Should always be !0, but check as a safeguard
|
|
|
|
dictionaryBar.setDictionaries( grp->dictionaries );
|
2012-09-26 13:13:47 +00:00
|
|
|
|
|
|
|
if ( currentId == Instances::Group::AllGroupId )
|
|
|
|
dictionaryBar.setMutedDictionaries( &cfg.popupMutedDictionaries );
|
2023-06-05 13:22:20 +00:00
|
|
|
else {
|
|
|
|
Config::Group * group = cfg.getGroup( currentId );
|
|
|
|
dictionaryBar.setMutedDictionaries( group ? &group->popupMutedDictionaries : nullptr );
|
2012-09-26 13:13:47 +00:00
|
|
|
}
|
2013-02-27 13:12:46 +00:00
|
|
|
|
|
|
|
setDictionaryIconSize();
|
2010-03-30 20:15:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::mutedDictionariesChanged()
|
|
|
|
{
|
2021-06-10 16:13:11 +00:00
|
|
|
updateSuggestionList();
|
2010-03-30 20:15:55 +00:00
|
|
|
if ( dictionaryBar.toggleViewAction()->isChecked() )
|
|
|
|
definition->updateMutedContents();
|
|
|
|
}
|
2011-11-16 12:52:25 +00:00
|
|
|
|
|
|
|
void ScanPopup::on_sendWordButton_clicked()
|
|
|
|
{
|
|
|
|
if ( !isVisible() )
|
|
|
|
return;
|
|
|
|
if ( !ui.pinButton->isChecked() ) {
|
|
|
|
definition->closeSearch();
|
|
|
|
hideWindow();
|
|
|
|
}
|
2023-05-28 16:01:54 +00:00
|
|
|
emit sendPhraseToMainWindow( definition->getWord() );
|
2011-11-16 12:52:25 +00:00
|
|
|
}
|
2012-09-16 10:19:47 +00:00
|
|
|
|
2017-05-15 15:08:06 +00:00
|
|
|
void ScanPopup::on_sendWordToFavoritesButton_clicked()
|
|
|
|
{
|
|
|
|
if ( !isVisible() )
|
|
|
|
return;
|
2023-04-25 00:12:21 +00:00
|
|
|
unsigned groupId = ui.groupList->getCurrentGroup();
|
|
|
|
auto current_exist = isWordPresentedInFavorites( definition->getTitle(), groupId );
|
|
|
|
//if current_exist=false( not exist ), after click ,the word should be in the favorite which is blueStar
|
|
|
|
ui.sendWordToFavoritesButton->setIcon( !current_exist ? blueStarIcon : starIcon );
|
|
|
|
emit sendWordToFavorites( definition->getTitle(), cfg.lastPopupGroupId, current_exist );
|
2017-05-15 15:08:06 +00:00
|
|
|
}
|
|
|
|
|
2012-09-16 10:19:47 +00:00
|
|
|
void ScanPopup::switchExpandOptionalPartsMode()
|
|
|
|
{
|
|
|
|
if ( isVisible() )
|
|
|
|
emit switchExpandMode();
|
|
|
|
}
|
2012-12-24 12:59:46 +00:00
|
|
|
|
|
|
|
void ScanPopup::updateBackForwardButtons()
|
|
|
|
{
|
|
|
|
ui.goBackButton->setEnabled( definition->canGoBack() );
|
|
|
|
ui.goForwardButton->setEnabled( definition->canGoForward() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::on_goBackButton_clicked()
|
|
|
|
{
|
|
|
|
definition->back();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::on_goForwardButton_clicked()
|
|
|
|
{
|
|
|
|
definition->forward();
|
|
|
|
}
|
2013-02-27 13:12:46 +00:00
|
|
|
|
|
|
|
void ScanPopup::setDictionaryIconSize()
|
|
|
|
{
|
|
|
|
int extent = cfg.usingSmallIconsInToolbars ? QApplication::style()->pixelMetric( QStyle::PM_SmallIconSize ) :
|
2022-01-23 11:41:50 +00:00
|
|
|
QApplication::style()->pixelMetric( QStyle::PM_ToolBarIconSize );
|
2013-02-27 13:12:46 +00:00
|
|
|
dictionaryBar.setDictionaryIconSize( extent );
|
|
|
|
}
|
2017-03-10 13:29:23 +00:00
|
|
|
|
|
|
|
void ScanPopup::setGroupByName( QString const & name )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for ( i = 0; i < ui.groupList->count(); i++ ) {
|
|
|
|
if ( ui.groupList->itemText( i ) == name ) {
|
|
|
|
ui.groupList->setCurrentIndex( i );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( i >= ui.groupList->count() )
|
|
|
|
gdWarning( "Group \"%s\" for popup window is not found\n", name.toUtf8().data() );
|
|
|
|
}
|
2017-07-13 15:00:19 +00:00
|
|
|
|
|
|
|
void ScanPopup::alwaysOnTopClicked( bool checked )
|
|
|
|
{
|
|
|
|
bool wasVisible = isVisible();
|
|
|
|
if ( ui.pinButton->isChecked() ) {
|
|
|
|
Qt::WindowFlags flags = this->windowFlags();
|
|
|
|
if ( checked )
|
|
|
|
setWindowFlags( flags | Qt::WindowStaysOnTopHint );
|
|
|
|
else
|
|
|
|
setWindowFlags( flags ^ Qt::WindowStaysOnTopHint );
|
|
|
|
if ( wasVisible )
|
|
|
|
show();
|
|
|
|
}
|
|
|
|
}
|
2017-11-07 14:46:59 +00:00
|
|
|
|
|
|
|
void ScanPopup::titleChanged( ArticleView *, QString const & title )
|
|
|
|
{
|
|
|
|
unsigned groupId = ui.groupList->getCurrentGroup();
|
|
|
|
|
|
|
|
// Set icon for "Add to Favorites" button
|
|
|
|
ui.sendWordToFavoritesButton->setIcon( isWordPresentedInFavorites( title, groupId ) ? blueStarIcon : starIcon );
|
|
|
|
}
|
2022-11-20 06:19:27 +00:00
|
|
|
|
2023-04-25 00:12:21 +00:00
|
|
|
bool ScanPopup::isWordPresentedInFavorites( QString const & word, unsigned groupId ) const
|
|
|
|
{
|
|
|
|
QString folder = GlobalBroadcaster::instance()->groupFolderMap[ groupId ];
|
|
|
|
|
|
|
|
return GlobalBroadcaster::instance()->folderFavoritesMap[ folder ].contains( word );
|
|
|
|
}
|
|
|
|
|
2022-11-20 06:51:23 +00:00
|
|
|
#ifdef HAVE_X11
|
2022-11-20 06:19:27 +00:00
|
|
|
void ScanPopup::showScanFlag()
|
|
|
|
{
|
|
|
|
scanFlag->showScanFlag();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanPopup::hideScanFlag()
|
|
|
|
{
|
|
|
|
scanFlag->hideWindow();
|
|
|
|
}
|
2022-11-20 06:51:23 +00:00
|
|
|
#endif
|