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

View File

@ -134,6 +134,11 @@ public:
PDFObject takeObject(); 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: private:
void addObject(PDFObject object); void addObject(PDFObject object);

View File

@ -773,6 +773,12 @@ const PDFAction* PDFFormManager::getAction(PDFAnnotationAdditionalActions::Actio
void PDFFormManager::setFormFieldValue(PDFFormField::SetValueParameters parameters) 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.invokingFormField);
Q_ASSERT(parameters.invokingWidget.isValid()); Q_ASSERT(parameters.invokingWidget.isValid());
@ -1154,6 +1160,11 @@ void PDFFormManager::updateFieldValues()
{ {
childField->reloadValue(&m_document->getStorage(), PDFObject()); 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.setCursorPosition(m_textEdit.getPositionEnd(), false);
m_textEdit.performSelectAll(); 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) : 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) 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); m_textEdit.keyPressEvent(widget, event);
if (event->isAccepted()) 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 void PDFFormFieldTextBoxEditor::draw(AnnotationDrawParameters& parameters) const
{ {
m_textEdit.draw(parameters, true); 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(); const int position = (event->modifiers().testFlag(Qt::ControlModifier)) ? getCursorWordForward() : getCursorCharacterForward();
setCursorPosition(position, event->modifiers().testFlag(Qt::ShiftModifier)); 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 else
{ {
QString text = event->text(); QString text = event->text();
@ -2442,4 +2496,37 @@ int PDFTextEditPseudowidget::getCursorLineDown() const
return m_positionCursor; 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 } // namespace pdf

View File

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