Skip to content

Commit 7584539

Browse files
committed
src/qml/controls: make modifier searches trigger on press
Make it so modifier searches trigger when a modifier key is pressed. Previously modifier searches only triggered on a hover index change. This created an issue where if the cursor was already over the search target, the search wouldn't occur. This fixes the issue by making KeyTracker an event filter for QGuiApplication that looks for KeyPress and KeyRelease events and triggers a signal when modifiers change. Some additional code is added to Player, SearchableText, and ManualSearchPage to handle this modifiersChanged signal and start a search.
1 parent 3416d68 commit 7584539

9 files changed

Lines changed: 156 additions & 23 deletions

File tree

src/main.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ static void registerQmlTypes(Context &context)
246246
MEMENTO_URI, 1, 0, "FileOpenHandler", context.fileOpenHandler()
247247
);
248248
qmlRegisterSingletonInstance<KeyTracker>(
249-
MEMENTO_URI, 1, 0, "KeyTracker", new KeyTracker(&context)
249+
MEMENTO_URI, 1, 0, "KeyTracker", context.keyTracker()
250250
);
251251
qmlRegisterSingletonInstance<Paths>(
252252
MEMENTO_URI, 1, 0, "MementoPaths", new Paths(&context)
@@ -435,9 +435,8 @@ static int runApplication()
435435
QQmlApplicationEngine::setObjectOwnership(
436436
&context, QQmlEngine::CppOwnership
437437
);
438-
QCoreApplication::instance()->installEventFilter(
439-
context.fileOpenHandler()
440-
);
438+
QCoreApplication::instance()->installEventFilter(context.fileOpenHandler());
439+
QCoreApplication::instance()->installEventFilter(context.keyTracker());
441440

442441
QTranslator translator;
443442
installTranslator(translator, context);

src/qml/controls/ManualSearchPage.qml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Page {
3636
*/
3737
function searchIndex(index) {
3838
dictionarySearch.clearResults();
39-
if (index < text.length)
39+
if (index >= 0 && index < text.length)
4040
{
4141
dictionarySearch.searchTerms(text.substring(index), text, index);
4242
dictionarySearch.searchKanji(text.charAt(index), text, index);
@@ -45,6 +45,7 @@ Page {
4545

4646
Layout.fillWidth: true
4747
Layout.margins: 5
48+
hoverEnabled: true
4849
placeholderText: qsTr("Search")
4950
onTextChanged: Qt.callLater(searchTextField.searchIndex, 0)
5051
onHoverIndexChanged: {
@@ -54,6 +55,17 @@ Page {
5455
}
5556
}
5657

58+
Connections {
59+
target: KeyTracker
60+
function onModifiersChanged() {
61+
if (searchTextField.hovered &&
62+
KeyTracker.modifierHeld(MementoSettings.searchModifier))
63+
{
64+
Qt.callLater(searchTextField.searchIndex, searchTextField.hoverIndex);
65+
}
66+
}
67+
}
68+
5769
MouseArea {
5870
anchors.fill: parent
5971
acceptedButtons: Qt.MiddleButton

src/qml/controls/Player.qml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,18 @@ MpvPlayer {
644644
Qt.callLater(definitionPopup.search, subtitleText.hoverIndex);
645645
}
646646
}
647+
648+
Connections {
649+
target: KeyTracker
650+
function onModifiersChanged() {
651+
if (MementoSettings.searchMethod === MementoSetting.SearchMethodModifier &&
652+
subtitleHover.hovered &&
653+
KeyTracker.modifierHeld(MementoSettings.searchModifier))
654+
{
655+
Qt.callLater(definitionPopup.search, subtitleText.hoverIndex);
656+
}
657+
}
658+
}
647659
}
648660

649661
PlayerMenu {

src/qml/controls/SearchableText.qml

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,32 @@ TextEdit {
7979
popupLoader.item.y = y;
8080
}
8181

82+
readOnly: true
83+
selectByMouse: false
84+
selectByKeyboard: false
85+
textFormat: TextEdit.PlainText
86+
color: MementoPalette.text
87+
selectionColor: MementoPalette.highlight
88+
89+
onHoverIndexChanged: {
90+
if (!KeyTracker.modifierHeld(MementoSettings.searchModifier))
91+
{
92+
return;
93+
}
94+
Qt.callLater(root.searchIndex, root.hoverIndex);
95+
}
96+
97+
Connections {
98+
target: KeyTracker
99+
function onModifiersChanged() {
100+
if (hoverHandler.hovered &&
101+
KeyTracker.modifierHeld(MementoSettings.searchModifier))
102+
{
103+
Qt.callLater(root.searchIndex, root.hoverIndex);
104+
}
105+
}
106+
}
107+
82108
Connections {
83109
target: popupLoader.item
84110
function onClosed() {
@@ -100,19 +126,8 @@ TextEdit {
100126
}
101127
}
102128

103-
readOnly: true
104-
selectByMouse: false
105-
selectByKeyboard: false
106-
textFormat: TextEdit.PlainText
107-
color: MementoPalette.text
108-
selectionColor: MementoPalette.highlight
109-
110-
onHoverIndexChanged: {
111-
if (!KeyTracker.modifierHeld(MementoSettings.searchModifier))
112-
{
113-
return;
114-
}
115-
Qt.callLater(root.searchIndex, root.hoverIndex);
129+
HoverHandler {
130+
id: hoverHandler
116131
}
117132

118133
MouseArea {

src/quick/keytracker.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "quick/keytracker.h"
2222

2323
#include <QGuiApplication>
24+
#include <QKeyEvent>
2425
#include <QKeySequence>
2526

2627
KeyTracker::KeyTracker(QObject *parent) : QObject(parent)
@@ -33,12 +34,22 @@ KeyTracker::~KeyTracker()
3334

3435
}
3536

36-
Qt::KeyboardModifiers KeyTracker::modifiers()
37+
Qt::KeyboardModifiers KeyTracker::modifiers() const
3738
{
38-
return QGuiApplication::keyboardModifiers();
39+
return m_modifiers;
3940
}
4041

41-
bool KeyTracker::modifierHeld(Setting::Modifier key)
42+
void KeyTracker::setModifiers(Qt::KeyboardModifiers value)
43+
{
44+
if (m_modifiers == value)
45+
{
46+
return;
47+
}
48+
m_modifiers = value;
49+
emit modifiersChanged(m_modifiers);
50+
}
51+
52+
bool KeyTracker::modifierHeld(Setting::Modifier key) const
4253
{
4354
switch (key)
4455
{
@@ -58,3 +69,34 @@ QString KeyTracker::keyComboToString(int key, int modifiers)
5869
{
5970
return QKeySequence(key | modifiers).toString();
6071
}
72+
73+
bool KeyTracker::eventFilter(QObject *obj, QEvent *event)
74+
{
75+
switch (event->type())
76+
{
77+
case QEvent::KeyPress:
78+
case QEvent::KeyRelease:
79+
{
80+
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
81+
setModifiers(keyEvent->modifiers());
82+
break;
83+
}
84+
85+
case QEvent::ApplicationDeactivate:
86+
case QEvent::WindowDeactivate:
87+
case QEvent::FocusOut:
88+
setModifiers(Qt::NoModifier);
89+
break;
90+
91+
case QEvent::ApplicationActivate:
92+
case QEvent::WindowActivate:
93+
case QEvent::FocusIn:
94+
setModifiers(QGuiApplication::queryKeyboardModifiers());
95+
break;
96+
97+
default:
98+
break;
99+
}
100+
101+
return QObject::eventFilter(obj, event);
102+
}

src/quick/keytracker.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ class KeyTracker : public QObject
3131
{
3232
Q_OBJECT
3333

34+
Q_PROPERTY(
35+
Qt::KeyboardModifiers modifiers
36+
READ modifiers
37+
NOTIFY modifiersChanged
38+
)
39+
3440
public:
3541
KeyTracker(QObject *parent = nullptr);
3642
~KeyTracker();
@@ -41,7 +47,7 @@ class KeyTracker : public QObject
4147
* @return The currently held modifiers.
4248
*/
4349
[[nodiscard]]
44-
Q_INVOKABLE static Qt::KeyboardModifiers modifiers();
50+
Q_INVOKABLE Qt::KeyboardModifiers modifiers() const;
4551

4652
/**
4753
* @brief Get if the modifier is held.
@@ -51,7 +57,7 @@ class KeyTracker : public QObject
5157
* @return false otherwise.
5258
*/
5359
[[nodiscard]]
54-
Q_INVOKABLE static bool modifierHeld(Setting::Modifier key);
60+
Q_INVOKABLE bool modifierHeld(Setting::Modifier key) const;
5561

5662
/**
5763
* @brief Get a sequence string from a key combination.
@@ -62,4 +68,33 @@ class KeyTracker : public QObject
6268
*/
6369
[[nodiscard]]
6470
Q_INVOKABLE static QString keyComboToString(int key, int modifiers);
71+
72+
/**
73+
* @brief Filter events to find key presses and releases.
74+
*
75+
* @param obj The object this event came from.
76+
* @param event The event to filter.
77+
* @return Always returns false so as to not filter any events.
78+
*/
79+
bool eventFilter(QObject *obj, QEvent *event) override;
80+
81+
signals:
82+
/**
83+
* @brief Emitted when the held modifiers changes.
84+
*
85+
* @param modifiers The newly held modifiers
86+
*/
87+
void modifiersChanged(Qt::KeyboardModifiers modifiers);
88+
89+
private:
90+
/**
91+
* @brief Set the currently held modifiers and notify if modifiers have been
92+
* updated.
93+
*
94+
* @param value The new modifiers to set.
95+
*/
96+
void setModifiers(Qt::KeyboardModifiers value);
97+
98+
/* The currently held modifiers */
99+
Qt::KeyboardModifiers m_modifiers{};
65100
};

src/state/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ target_link_libraries(
1212
PUBLIC audioplayer
1313
PUBLIC dictionary
1414
PUBLIC fileopenhandler
15+
PUBLIC keytracker
1516
PUBLIC mpvplayer
1617
PUBLIC Qt6::Core
1718
PUBLIC settings

src/state/context.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ FileOpenHandler *Context::fileOpenHandler() const noexcept
6565
return m_fileOpenHandler;
6666
}
6767

68+
KeyTracker *Context::keyTracker() const noexcept
69+
{
70+
return m_keyTracker;
71+
}
72+
6873
MpvPlayer *Context::player() const noexcept
6974
{
7075
return m_player;

src/state/context.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "dict/dictionarycontroller.h"
2929
#include "player/mpvplayer.h"
3030
#include "quick/fileopenhandler.h"
31+
#include "quick/keytracker.h"
3132
#include "setting/settings.h"
3233
#include "subtitle/subtitlelists.h"
3334
#include "util/utils.h"
@@ -99,6 +100,14 @@ class Context : public QObject
99100
[[nodiscard]]
100101
FileOpenHandler *fileOpenHandler() const noexcept;
101102

103+
/**
104+
* @brief Get the global key tracker.
105+
*
106+
* @return The global key tracker.
107+
*/
108+
[[nodiscard]]
109+
KeyTracker *keyTracker() const noexcept;
110+
102111
/**
103112
* @brief Get the application MpvPlayer instance.
104113
*
@@ -140,6 +149,9 @@ class Context : public QObject
140149
/* The application file open handler. Has ownership. */
141150
FileOpenHandler *m_fileOpenHandler{new FileOpenHandler(this)};
142151

152+
/* The application key tracker. Has ownership. */
153+
KeyTracker *m_keyTracker{new KeyTracker(this)};
154+
143155
/* The main application MpvPlayer. Does not have ownership. */
144156
MpvPlayer *m_player{nullptr};
145157
};

0 commit comments

Comments
 (0)