From 702ee9831601c4d02185aa80295ee8bc458c3940 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Thu, 28 May 2020 19:06:27 +0200 Subject: [PATCH] Reset form action --- PdfForQtLib/sources/pdfform.cpp | 151 +++++++++++++++++++++++-- PdfForQtLib/sources/pdfform.h | 19 ++++ PdfForQtViewer/pdfviewermainwindow.cpp | 6 + 3 files changed, 164 insertions(+), 12 deletions(-) diff --git a/PdfForQtLib/sources/pdfform.cpp b/PdfForQtLib/sources/pdfform.cpp index 68e34e3..7a80f2f 100644 --- a/PdfForQtLib/sources/pdfform.cpp +++ b/PdfForQtLib/sources/pdfform.cpp @@ -911,6 +911,13 @@ bool PDFFormField::setValue(const SetValueParameters& parameters) return false; } +void PDFFormField::resetValue(const ResetValueParameters& parameters) +{ + Q_UNUSED(parameters); + + // Default behaviour: do nothing +} + PDFFormWidget::PDFFormWidget(PDFObjectReference page, PDFObjectReference widget, PDFFormField* parentField, PDFAnnotationAdditionalActions actions) : m_page(page), m_widget(widget), @@ -1047,6 +1054,41 @@ bool PDFFormFieldButton::setValue(const SetValueParameters& parameters) return true; } +void PDFFormFieldButton::resetValue(const ResetValueParameters& parameters) +{ + // Do not allow to reset value of push buttons + if (getFlags().testFlag(PushButton)) + { + return; + } + + Q_ASSERT(parameters.modifier); + Q_ASSERT(parameters.formManager); + + PDFObject defaultValue = getDefaultValue(); + PDFDocumentBuilder* builder = parameters.modifier->getBuilder(); + parameters.modifier->markFormFieldChanged(); + builder->setFormFieldValue(getSelfReference(), defaultValue); + + PDFDocumentDataLoaderDecorator loader(parameters.formManager->getDocument()); + QByteArray defaultState = loader.readString(defaultValue); + + for (const PDFFormWidget& formWidget : getWidgets()) + { + QByteArray onState = PDFFormFieldButton::getOnAppearanceState(parameters.formManager, &formWidget); + if (defaultState == onState) + { + builder->setAnnotationAppearanceState(formWidget.getWidget(), onState); + } + else + { + QByteArray offState = PDFFormFieldButton::getOffAppearanceState(parameters.formManager, &formWidget); + builder->setAnnotationAppearanceState(formWidget.getWidget(), offState); + } + parameters.modifier->markAnnotationsChanged(); + } +} + PDFFormManager::PDFFormManager(PDFDrawWidgetProxy* proxy, QObject* parent) : BaseClass(parent), m_proxy(proxy), @@ -1712,6 +1754,57 @@ PDFFormFieldWidgetEditor* PDFFormManager::getEditor(const PDFFormField* formFiel return nullptr; } +void PDFFormManager::performResetAction(const PDFActionResetForm* action) +{ + Q_ASSERT(action); + Q_ASSERT(m_document); + + PDFDocumentModifier modifier(m_document); + modifier.getBuilder()->setFormManager(this); + + auto resetFieldValue = [this, action, &modifier](PDFFormField* formField) + { + const PDFFormAction::FieldList& fieldList = action->getFieldList(); + + // Akceptujeme form field dle daného filtru? + bool accept = false; + bool isInFieldList = std::find(fieldList.fieldReferences.cbegin(), fieldList.fieldReferences.cend(), formField->getSelfReference()) != fieldList.fieldReferences.cend() || + fieldList.qualifiedNames.contains(formField->getName(PDFFormField::NameType::FullyQualified)); + switch (action->getFieldScope()) + { + case PDFFormAction::FieldScope::All: + accept = true; + break; + + case PDFFormAction::FieldScope::Include: + accept = isInFieldList; + break; + + case PDFFormAction::FieldScope::Exclude: + accept = !isInFieldList; + break; + + default: + Q_ASSERT(false); + break; + } + + if (accept) + { + PDFFormField::ResetValueParameters parameters; + parameters.formManager = this; + parameters.modifier = &modifier; + formField->resetValue(parameters); + } + }; + modify(resetFieldValue); + + if (modifier.finalize()) + { + emit documentModified(PDFModifiedDocument(modifier.getDocument(), nullptr, modifier.getFlags())); + } +} + PDFFormFieldWidgetEditor::PDFFormFieldWidgetEditor(PDFFormManager* formManager, PDFFormWidget formWidget) : m_formManager(formManager), m_formWidget(formWidget), @@ -3346,12 +3439,6 @@ int PDFTextEditPseudowidget::getCursorLineDown() const bool PDFFormFieldText::setValue(const SetValueParameters& parameters) { - // Do not allow to set value to push buttons - if (getFlags().testFlag(PushButton)) - { - return false; - } - // If form field is readonly, and scope is user (form field is changed by user, // not by calculated value), then we must not allow value change. if (getFlags().testFlag(ReadOnly) && parameters.scope == SetValueParameters::Scope::User) @@ -3377,6 +3464,25 @@ bool PDFFormFieldText::setValue(const SetValueParameters& parameters) return true; } +void PDFFormFieldText::resetValue(const ResetValueParameters& parameters) +{ + Q_ASSERT(parameters.formManager); + Q_ASSERT(parameters.modifier); + + PDFObject defaultValue = getDefaultValue(); + PDFDocumentBuilder* builder = parameters.modifier->getBuilder(); + parameters.modifier->markFormFieldChanged(); + builder->setFormFieldValue(getSelfReference(), defaultValue); + m_value = defaultValue; + + // Change widget appearance states + for (const PDFFormWidget& formWidget : getWidgets()) + { + builder->updateAnnotationAppearanceStreams(formWidget.getWidget()); + parameters.modifier->markAnnotationsChanged(); + } +} + PDFListBoxPseudowidget::PDFListBoxPseudowidget(PDFFormField::FieldFlags flags) : m_flags(flags), m_topIndex(0), @@ -3983,12 +4089,6 @@ void PDFFormFieldListBoxEditor::commit() bool PDFFormFieldChoice::setValue(const SetValueParameters& parameters) { - // Do not allow to set value to push buttons - if (getFlags().testFlag(PushButton)) - { - return false; - } - // If form field is readonly, and scope is user (form field is changed by user, // not by calculated value), then we must not allow value change. if (getFlags().testFlag(ReadOnly) && parameters.scope == SetValueParameters::Scope::User) @@ -4027,6 +4127,33 @@ bool PDFFormFieldChoice::setValue(const SetValueParameters& parameters) return true; } +void PDFFormFieldChoice::resetValue(const PDFFormField::ResetValueParameters& parameters) +{ + Q_ASSERT(parameters.formManager); + Q_ASSERT(parameters.modifier); + + PDFObject defaultValue = getDefaultValue(); + PDFDocumentBuilder* builder = parameters.modifier->getBuilder(); + parameters.modifier->markFormFieldChanged(); + builder->setFormFieldValue(getSelfReference(), defaultValue); + m_value = defaultValue; + m_selection = PDFObject(); + + if (isListBox()) + { + // Listbox has special values, which must be set + builder->setFormFieldChoiceTopIndex(getSelfReference(), 0); + builder->setFormFieldChoiceIndices(getSelfReference(), { }); + } + + // Change widget appearance states + for (const PDFFormWidget& formWidget : getWidgets()) + { + builder->updateAnnotationAppearanceStreams(formWidget.getWidget()); + parameters.modifier->markAnnotationsChanged(); + } +} + void PDFFormFieldChoice::reloadValue(const PDFObjectStorage* storage, PDFObject parentValue) { BaseClass::reloadValue(storage, parentValue); diff --git a/PdfForQtLib/sources/pdfform.h b/PdfForQtLib/sources/pdfform.h index d178b82..08f6a83 100644 --- a/PdfForQtLib/sources/pdfform.h +++ b/PdfForQtLib/sources/pdfform.h @@ -250,6 +250,17 @@ public: /// \param parameters Parameters virtual bool setValue(const SetValueParameters& parameters); + struct ResetValueParameters + { + PDFDocumentModifier* modifier = nullptr; + PDFFormManager* formManager = nullptr; + }; + + /// Resets value to the field's default value. Widget annotation + /// appearances are also updated. + /// \param parameters Parameters + virtual void resetValue(const ResetValueParameters& parameters); + protected: PDFObjectReference m_selfReference; FieldType m_fieldType = FieldType::Invalid; @@ -297,6 +308,7 @@ public: static QByteArray getOffAppearanceState(const PDFFormManager* formManager, const PDFFormWidget* widget); virtual bool setValue(const SetValueParameters& parameters) override; + virtual void resetValue(const ResetValueParameters& parameters) override; private: friend static PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObjectReference reference, PDFFormField* parentField); @@ -321,6 +333,7 @@ public: const QString& getRichTextValue() const { return m_richTextValue; } virtual bool setValue(const SetValueParameters& parameters) override; + virtual void resetValue(const ResetValueParameters& parameters) override; private: friend static PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObjectReference reference, PDFFormField* parentField); @@ -366,6 +379,7 @@ public: const PDFObject& getSelection() const { return m_selection; } virtual bool setValue(const SetValueParameters& parameters) override; + virtual void resetValue(const ResetValueParameters& parameters) override; virtual void reloadValue(const PDFObjectStorage* storage, PDFObject parentValue) override; private: @@ -627,6 +641,11 @@ public: /// Is committing data disabled? bool isCommitDisabled() const { return m_isCommitDisabled; } + /// Performs reset action. Action must be valid pointer. Fields are resetted + /// according to the criteria specified in reset action. + /// \param action Reset action + void performResetAction(const PDFActionResetForm* action); + // interface IDrawWidgetInputInterface virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event) override; diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp index cf1d98c..27211f2 100644 --- a/PdfForQtViewer/pdfviewermainwindow.cpp +++ b/PdfForQtViewer/pdfviewermainwindow.cpp @@ -610,6 +610,12 @@ void PDFViewerMainWindow::onActionTriggered(const pdf::PDFAction* action) break; } + case pdf::ActionType::ResetForm: + { + m_formManager->performResetAction(dynamic_cast(action)); + break; + } + default: break; }