Text form field bugfixing

This commit is contained in:
Jakub Melka 2020-05-11 19:34:17 +02:00
parent ce585262c2
commit 0f4eeeacb7
4 changed files with 106 additions and 5 deletions

View File

@ -541,7 +541,7 @@ PDFObjectFactory& PDFObjectFactory::operator<<(WrapEmptyArray)
return *this;
}
PDFObjectFactory& PDFObjectFactory::operator<<(QString textString)
PDFObject PDFObjectFactory::createTextString(QString textString)
{
if (!PDFEncoding::canConvertToEncoding(textString, PDFEncoding::Encoding::PDFDoc))
{
@ -555,14 +555,18 @@ PDFObjectFactory& PDFObjectFactory::operator<<(QString textString)
textStream << textString;
}
addObject(PDFObject::createString(std::make_shared<PDFString>(qMove(ba))));
return PDFObject::createString(std::make_shared<PDFString>(qMove(ba)));
}
else
{
// Use PDF document encoding
addObject(PDFObject::createString(std::make_shared<PDFString>(PDFEncoding::convertToEncoding(textString, PDFEncoding::Encoding::PDFDoc))));
return PDFObject::createString(std::make_shared<PDFString>(PDFEncoding::convertToEncoding(textString, PDFEncoding::Encoding::PDFDoc)));
}
}
PDFObjectFactory& PDFObjectFactory::operator<<(QString textString)
{
addObject(createTextString(textString));
return *this;
}
@ -764,8 +768,10 @@ void PDFDocumentBuilder::updateAnnotationAppearanceStreams(PDFObjectReference an
PDFContentStreamBuilder builder(mediaBox.size(), PDFContentStreamBuilder::CoordinateSystem::PDF);
AnnotationDrawParameters parameters;
parameters.annotation = annotation.data();
parameters.key = key;
parameters.painter = builder.begin();
parameters.formManager = m_formManager;
annotation->draw(parameters);
PDFContentStreamBuilder::ContentStream contentStream = builder.end(parameters.painter);

View File

@ -134,6 +134,11 @@ public:
PDFObject takeObject();
/// Creates text string object from QString, using PDFDocEncoding, if possible,
/// if not, then UTF-16 BE encoding is used
/// \param textString Text to be converted
static PDFObject createTextString(QString textString);
private:
void addObject(PDFObject object);

View File

@ -773,6 +773,12 @@ const PDFAction* PDFFormManager::getAction(PDFAnnotationAdditionalActions::Actio
void PDFFormManager::setFormFieldValue(PDFFormField::SetValueParameters parameters)
{
if (!m_document)
{
// This can happen, when we are closing the document and some editor is opened
return;
}
Q_ASSERT(parameters.invokingFormField);
Q_ASSERT(parameters.invokingWidget.isValid());
@ -1154,6 +1160,11 @@ void PDFFormManager::updateFieldValues()
{
childField->reloadValue(&m_document->getStorage(), PDFObject());
}
for (PDFFormFieldWidgetEditor* editor : m_widgetEditors)
{
editor->reloadValue();
}
}
}
@ -1496,6 +1507,22 @@ void PDFFormFieldTextBoxEditor::setFocusImpl(bool focused)
m_textEdit.setCursorPosition(m_textEdit.getPositionEnd(), false);
m_textEdit.performSelectAll();
}
else if (!m_textEdit.isPassword()) // Passwords are not saved in the document
{
// If text has been changed, then commit it
PDFObject object = PDFObjectFactory::createTextString(m_textEdit.getText());
if (object != m_formWidget.getParent()->getValue())
{
PDFFormField::SetValueParameters parameters;
parameters.formManager = m_formManager;
parameters.invokingWidget = m_formWidget.getWidget();
parameters.invokingFormField = m_formWidget.getParent();
parameters.scope = PDFFormField::SetValueParameters::Scope::User;
parameters.value = qMove(object);
m_formManager->setFormFieldValue(parameters);
}
}
}
PDFFormFieldTextBoxEditor::PDFFormFieldTextBoxEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent) :
@ -1514,6 +1541,23 @@ void PDFFormFieldTextBoxEditor::shortcutOverrideEvent(QWidget* widget, QKeyEvent
void PDFFormFieldTextBoxEditor::keyPressEvent(QWidget* widget, QKeyEvent* event)
{
if (!m_textEdit.isMultiline() && (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return))
{
// Commit the editor
m_formManager->setFocusToEditor(nullptr);
event->accept();
return;
}
if (event->key() == Qt::Key_Escape)
{
// Cancel the editor
reloadValue();
m_formManager->setFocusToEditor(nullptr);
event->accept();
return;
}
m_textEdit.keyPressEvent(widget, event);
if (event->isAccepted())
@ -1562,6 +1606,12 @@ void PDFFormFieldTextBoxEditor::mouseMoveEvent(QWidget* widget, QMouseEvent* eve
}
}
void PDFFormFieldTextBoxEditor::reloadValue()
{
PDFDocumentDataLoaderDecorator loader(m_formManager->getDocument());
m_textEdit.setText(loader.readTextString(m_formWidget.getParent()->getValue(), QString()));
}
void PDFFormFieldTextBoxEditor::draw(AnnotationDrawParameters& parameters) const
{
m_textEdit.draw(parameters, true);
@ -1846,6 +1896,10 @@ void PDFTextEditPseudowidget::keyPressEvent(QWidget* widget, QKeyEvent* event)
const int position = (event->modifiers().testFlag(Qt::ControlModifier)) ? getCursorWordForward() : getCursorCharacterForward();
setCursorPosition(position, event->modifiers().testFlag(Qt::ShiftModifier));
}
else if (isMultiline() && (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return))
{
performInsertText(QString::fromUtf16(u"\u2028"));
}
else
{
QString text = event->text();
@ -2442,4 +2496,37 @@ int PDFTextEditPseudowidget::getCursorLineDown() const
return m_positionCursor;
}
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)
{
return false;
}
Q_ASSERT(parameters.formManager);
Q_ASSERT(parameters.modifier);
PDFDocumentBuilder* builder = parameters.modifier->getBuilder();
parameters.modifier->markFormFieldChanged();
builder->setFormFieldValue(getSelfReference(), parameters.value);
m_value = parameters.value;
// Change widget appearance states
for (const PDFFormWidget& formWidget : getWidgets())
{
builder->updateAnnotationAppearanceStreams(formWidget.getWidget());
parameters.modifier->markAnnotationsChanged();
}
return true;
}
} // namespace pdf

View File

@ -316,6 +316,8 @@ public:
const QString& getRichTextDefaultStyle() const { return m_defaultStyle; }
const QString& getRichTextValue() const { return m_richTextValue; }
virtual bool setValue(const SetValueParameters& parameters) override;
private:
friend static PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObjectReference reference, PDFFormField* parentField);
@ -473,6 +475,7 @@ public:
inline void clearSelection() { m_selectionStart = m_selectionEnd = 0; }
inline const QString& getText() const { return m_editText; }
inline QString getSelectedText() const { return m_editText.mid(m_selectionStart, getSelectionLength()); }
/// Sets (updates) text selection
@ -628,7 +631,7 @@ public:
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void reloadValue() { }
virtual bool isEditorDrawEnabled() const { return false; }
const PDFFormWidget* getFormWidget() const { return &m_formWidget; }
@ -723,7 +726,7 @@ public:
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void reloadValue() override;
virtual bool isEditorDrawEnabled() const override { return m_hasFocus; }
virtual void draw(AnnotationDrawParameters& parameters) const override;