From d1ecad897c8aafa952d0b04dc88f7682179fd6ad Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Fri, 21 Jan 2022 18:59:20 +0100 Subject: [PATCH] Implement keystroke commit events When a form field loses focus a special keystroke event with willCommit=true is sent. This is based on work by Joao Netto --- autotests/CMakeLists.txt | 5 ++ autotests/data/keystroketest.pdf | Bin 0 -> 13971 bytes autotests/keystroketest.cpp | 106 +++++++++++++++++++++++++++++++ core/document.cpp | 29 +++++++++ core/document.h | 8 +++ core/script/event.cpp | 12 ++++ core/script/event_p.h | 3 + core/script/kjs_event.cpp | 6 +- part/formwidgets.cpp | 10 +++ 9 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 autotests/data/keystroketest.pdf create mode 100644 autotests/keystroketest.cpp diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index fd9872cee..47b350989 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -48,6 +48,11 @@ if(Poppler_Qt5_FOUND) LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore ) + ecm_add_test(keystroketest.cpp + TEST_NAME "keystroketest" + LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore + ) + ecm_add_test(signunsignedfieldtest TEST_NAME "signunsignedfieldtest" LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore diff --git a/autotests/data/keystroketest.pdf b/autotests/data/keystroketest.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ab65eb9afe7ee052568ef040e754c444ab1bf617 GIT binary patch literal 13971 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 literal 0 HcmV?d00001 diff --git a/autotests/keystroketest.cpp b/autotests/keystroketest.cpp new file mode 100644 index 000000000..9277b96e2 --- /dev/null +++ b/autotests/keystroketest.cpp @@ -0,0 +1,106 @@ +/* + SPDX-FileCopyrightText: 2019 João Netto + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include + +#include "../settings_core.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../generators/poppler/config-okular-poppler.h" + +class KeystrokeTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void testCommit(); + void testKeystroke(); + +private: + Okular::Document *m_document; + QMap m_fields; +}; + +void KeystrokeTest::initTestCase() +{ + Okular::SettingsCore::instance(QStringLiteral("keystroketest")); + m_document = new Okular::Document(nullptr); + + // Force consistent locale + QLocale locale(QStringLiteral("en_US")); + QLocale::setDefault(locale); + + const QString testFile = QStringLiteral(KDESRCDIR "data/keystroketest.pdf"); + QMimeDatabase db; + const QMimeType mime = db.mimeTypeForFile(testFile); + QCOMPARE(m_document->openDocument(testFile, QUrl(), mime), Okular::Document::OpenSuccess); + + const Okular::Page *page = m_document->page(0); + const QLinkedList pageFormFields = page->formFields(); + for (Okular::FormField *ff : pageFormFields) { + m_fields.insert(ff->name(), ff); + } +} + +void KeystrokeTest::testCommit() +{ + Okular::FormFieldText *fft = reinterpret_cast(m_fields[QStringLiteral("field2")]); + + // text that will be accepted + fft->setText(QStringLiteral("Lorem ipsum")); + m_document->processKeystrokeCommitAction(fft->additionalAction(Okular::FormField::FieldModified), fft); + QCOMPARE(fft->text(), QStringLiteral("Lorem ipsum")); + + // text that will be rejected + fft->setText(QStringLiteral("foo")); + m_document->processKeystrokeCommitAction(fft->additionalAction(Okular::FormField::FieldModified), fft); + QEXPECT_FAIL("", "reset to commited value not implemented", Continue); + QCOMPARE(fft->text(), QStringLiteral("Lorem ipsum")); +} + +void KeystrokeTest::testKeystroke() +{ + Okular::FormFieldText *fft = reinterpret_cast(m_fields[QStringLiteral("field3")]); + + // accept + m_document->processKeystrokeAction(fft->additionalAction(Okular::FormField::FieldModified), fft, QStringLiteral("hello")); + QCOMPARE(fft->text(), QStringLiteral("hello")); + + // accept + m_document->processKeystrokeAction(fft->additionalAction(Okular::FormField::FieldModified), fft, QStringLiteral("e")); + QCOMPARE(fft->text(), QStringLiteral("e")); + + // accept + m_document->processKeystrokeAction(fft->additionalAction(Okular::FormField::FieldModified), fft, QStringLiteral("ee")); + QCOMPARE(fft->text(), QStringLiteral("ee")); + + // accept + m_document->processKeystrokeAction(fft->additionalAction(Okular::FormField::FieldModified), fft, QStringLiteral("eee")); + QCOMPARE(fft->text(), QStringLiteral("eee")); + + // reject + m_document->processKeystrokeAction(fft->additionalAction(Okular::FormField::FieldModified), fft, QStringLiteral("eeef")); + QCOMPARE(fft->text(), QStringLiteral("eee")); +} + +void KeystrokeTest::cleanupTestCase() +{ + m_document->closeDocument(); + delete m_document; +} + +QTEST_MAIN(KeystrokeTest) +#include "keystroketest.moc" diff --git a/core/document.cpp b/core/document.cpp index ecb4b6c85..73f6a5344 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -4162,6 +4162,35 @@ void Document::processKeystrokeAction(const Action *action, Okular::FormFieldTex } } +void Document::processKeystrokeCommitAction(const Action *action, Okular::FormFieldText *fft) +{ + if (action->actionType() != Action::Script) { + qCDebug(OkularCoreDebug) << "Unsupported action type" << action->actionType() << "for keystroke."; + return; + } + // Lookup the page of the FormFieldText + int foundPage = d->findFieldPageNumber(fft); + + if (foundPage == -1) { + qCDebug(OkularCoreDebug) << "Could not find page for formfield!"; + return; + } + + std::shared_ptr event = Event::createKeystrokeEvent(fft, d->m_pagesVector[foundPage]); + event->setWillCommit(true); + + const ScriptAction *linkscript = static_cast(action); + + d->executeScriptEvent(event, linkscript); + + if (event->returnCode()) { + fft->setText(event->value().toString()); + // TODO commit value + } else { + // TODO reset to committed value + } +} + void Document::processFocusAction(const Action *action, Okular::FormField *field) { if (!action || action->actionType() != Action::Script) diff --git a/core/document.h b/core/document.h index 6cb2d7f8f..558d94ddd 100644 --- a/core/document.h +++ b/core/document.h @@ -688,6 +688,14 @@ public: */ void processKeystrokeAction(const Action *action, Okular::FormFieldText *fft, const QVariant &newValue); + /** + * Processes the given keystroke @p action on @p fft. + * This will set event.willCommit=true + * + * @since 22.04 + */ + void processKeystrokeCommitAction(const Action *action, Okular::FormFieldText *fft); + /** * Processes the given focus action on the field. * diff --git a/core/script/event.cpp b/core/script/event.cpp index 19b846e9d..ec0f93efb 100644 --- a/core/script/event.cpp +++ b/core/script/event.cpp @@ -22,6 +22,7 @@ public: , m_eventType(eventType) , m_returnCode(false) , m_shiftModifier(false) + , m_willCommit(false) { } @@ -34,6 +35,7 @@ public: QVariant m_value; bool m_returnCode; bool m_shiftModifier; + bool m_willCommit; }; Event::Event() @@ -169,6 +171,16 @@ void Event::setShiftModifier(bool shiftModifier) d->m_shiftModifier = shiftModifier; } +bool Event::willCommit() const +{ + return d->m_willCommit; +} + +void Event::setWillCommit(bool willCommit) +{ + d->m_willCommit = willCommit; +} + // static std::shared_ptr Event::createFormCalculateEvent(FormField *target, Page *targetPage, FormField *source, Page *sourcePage, const QString &targetName) { diff --git a/core/script/event_p.h b/core/script/event_p.h index 9e3a3890d..f3772722d 100644 --- a/core/script/event_p.h +++ b/core/script/event_p.h @@ -105,6 +105,9 @@ public: bool shiftModifier() const; void setShiftModifier(bool shiftModifier); + bool willCommit() const; + void setWillCommit(bool willCommit); + static std::shared_ptr createFormCalculateEvent(FormField *target, Page *targetPage, FormField *source = nullptr, Page *sourcePage = nullptr, const QString &targetName = QString()); static std::shared_ptr createFormatEvent(FormField *target, Page *targetPage, const QString &targetName = QString()); static std::shared_ptr createKeystrokeEvent(FormField *target, Page *targetPage); diff --git a/core/script/kjs_event.cpp b/core/script/kjs_event.cpp index 40af6f79d..108be68d5 100644 --- a/core/script/kjs_event.cpp +++ b/core/script/kjs_event.cpp @@ -115,10 +115,10 @@ static void eventSetReturnCode(KJSContext *ctx, void *object, KJSObject value) } // Event.willCommit (getter) -static KJSObject eventGetWillCommit(KJSContext *, void * /*object*/) +static KJSObject eventGetWillCommit(KJSContext *, void *object) { - // TODO Someone try to understand the defintion of willCommit better from js_api_reference.pdf - return KJSBoolean(true); + const Event *event = reinterpret_cast(object); + return KJSBoolean(event->willCommit()); } void JSEvent::initType(KJSContext *ctx) diff --git a/part/formwidgets.cpp b/part/formwidgets.cpp index c28bd3702..a6b570fb7 100644 --- a/part/formwidgets.cpp +++ b/part/formwidgets.cpp @@ -502,6 +502,11 @@ bool FormLineEdit::event(QEvent *e) if (focusEvent->reason() == Qt::OtherFocusReason || focusEvent->reason() == Qt::ActiveWindowFocusReason) return true; + if (m_ff->additionalAction(Okular::FormField::FieldModified) && !m_ff->isReadOnly()) { + Okular::FormFieldText *form = static_cast(m_ff); + m_controller->document()->processKeystrokeCommitAction(m_ff->additionalAction(Okular::FormField::FieldModified), form); + } + if (const Okular::Action *action = m_ff->additionalAction(Okular::Annotation::FocusOut)) { bool ok = false; m_controller->document()->processValidateAction(action, static_cast(m_ff), ok); @@ -637,6 +642,11 @@ bool TextAreaEdit::event(QEvent *e) m_editing = true; } else if (e->type() == QEvent::FocusOut) { m_editing = false; + + if (m_ff->additionalAction(Okular::FormField::FieldModified) && !m_ff->isReadOnly()) { + m_controller->document()->processKeystrokeCommitAction(m_ff->additionalAction(Okular::FormField::FieldModified), static_cast(m_ff)); + } + if (const Okular::Action *action = m_ff->additionalAction(Okular::FormField::FormatField)) { m_controller->document()->processFormatAction(action, static_cast(m_ff)); }