Issue #118: Refactoring of forms finished

This commit is contained in:
Jakub Melka 2023-12-07 17:53:50 +01:00
parent b4d123baac
commit 0e1959b3aa
6 changed files with 203 additions and 150 deletions

View File

@ -1424,11 +1424,9 @@ bool PDFAnnotationManager::isAnnotationDrawnByEditor(const PageAnnotation& annot
return false;
}
const PDFFormFieldWidgetEditor* editor = nullptr;
if (annotation.annotation->getType() == AnnotationType::Widget)
{
editor = m_formManager->getEditor(m_formManager->getFormFieldForWidget(annotation.annotation->getSelfReference()));
return editor && editor->isEditorDrawEnabled();
return m_formManager->isEditorDrawEnabled(annotation.annotation->getSelfReference());
}
return false;
@ -3105,10 +3103,9 @@ void PDFWidgetAnnotation::draw(AnnotationDrawParameters& parameters) const
PDFPainterStateGuard guard(parameters.painter);
parameters.painter->setCompositionMode(getCompositionMode());
const PDFFormFieldWidgetEditor* editor = parameters.formManager->getEditor(formField);
if (editor && editor->isEditorDrawEnabled())
if (parameters.formManager->isEditorDrawEnabled(formField))
{
editor->draw(parameters, true);
parameters.formManager->drawFormField(formField, parameters, true);
}
else
{
@ -3117,7 +3114,7 @@ void PDFWidgetAnnotation::draw(AnnotationDrawParameters& parameters) const
case PDFFormField::FieldType::Text:
case PDFFormField::FieldType::Choice:
{
editor->draw(parameters, false);
m_parameters.formManager->drawFormField(parameters, false);
break;
}
@ -3146,8 +3143,6 @@ void PDFWidgetAnnotation::draw(AnnotationDrawParameters& parameters) const
font.setPixelSize(qCeil(fontSize));
font.setStyleStrategy(QFont::ForceOutline);
QFontMetrics fontMetrics(font);
QPainter* painter = parameters.painter;
painter->translate(rectangle.bottomLeft());
painter->scale(1.0, -1.0);

View File

@ -15,9 +15,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#include "pdfdrawspacecontroller.h"
#include "pdfdrawwidget.h"
#include "pdfrenderer.h"
#include "pdfpainter.h"
#include "pdfcompiler.h"

View File

@ -17,7 +17,6 @@
#include "pdfform.h"
#include "pdfdocument.h"
#include "pdftexteditpseudowidget.h"
#include "pdfdrawspacecontroller.h"
#include "pdfdocumentbuilder.h"
#include "pdfpainterutils.h"
@ -26,141 +25,6 @@
namespace pdf
{
/// "Pseudo" widget, which is emulating list box. It can contain scrollbar.
class PDFListBoxPseudowidget
{
public:
explicit PDFListBoxPseudowidget(PDFFormField::FieldFlags flags);
using Options = PDFFormFieldChoice::Options;
inline bool isReadonly() const { return m_flags.testFlag(PDFFormField::ReadOnly); }
inline bool isMultiSelect() const { return m_flags.testFlag(PDFFormField::MultiSelect); }
inline bool isCommitOnSelectionChange() const { return m_flags.testFlag(PDFFormField::CommitOnSelectionChange); }
void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event);
void keyPressEvent(QWidget* widget, QKeyEvent* event);
/// Sets widget appearance, such as font, font size, color, text alignment,
/// and rectangle, in which widget resides on page (in page coordinates)
/// \param appearance Appearance
/// \param textAlignment Text alignment
/// \param rect Widget rectangle in page coordinates
/// \param options Options selectable by list box
/// \param topIndex Index of first visible item
void setAppearance(const PDFAnnotationDefaultAppearance& appearance,
Qt::Alignment textAlignment,
QRectF rect,
const Options& options,
int topIndex,
std::set<int> selection);
/// Draw text edit using given parameters
/// \param parameters Parameters
void draw(AnnotationDrawParameters& parameters, bool edit) const;
/// Sets current selection. If commit on selection change flag
/// is set, then contents of the widgets are commited. New selection
/// is not set, if field is readonly and \p force is false
/// \param selection New selection
/// \param force Set selection even if readonly
void setSelection(std::set<int> selection, bool force);
/// Returns active item selection
const std::set<int>& getSelection() const { return m_selection; }
/// Returns top index
int getTopItemIndex() const { return m_topIndex; }
/// Set top item index
/// \param index Top item index
void setTopItemIndex(int index);
/// Scrolls the list box in such a way, that index is visible
/// \param index Index to scroll to
void scrollTo(int index);
/// Returns valid index from index (i.e. index which ranges from first
/// row to the last one). If index itself is valid, then it is returned.
/// \param index Index, from which we want to get valid one
int getValidIndex(int index) const;
/// Returns true, if index is valid
bool isValidIndex(int index) const { return index == getValidIndex(index); }
/// Returns number of rows in the viewport
int getViewportRowCount() const { return qFloor(m_widgetRect.height() / m_lineSpacing); }
/// Returns item index from widget position (i.e. transforms
/// point in the widget to the index of item, which is under the point)
/// \param point Widget point
int getIndexFromWidgetPosition(const QPointF& point) const;
/// Sets current item and updates selection based on keyboard modifiers
/// \param index New index
/// \param modifiers Keyboard modifiers
void setCurrentItem(int index, Qt::KeyboardModifiers modifiers);
/// Returns text of selected item text. If no item is selected,
/// or multiple items are selected, then empty string is returned.
/// \returns Selected text
QString getSelectedItemText() const;
/// Returns true, if single item is selected
bool isSingleItemSelected() const { return m_selection.size() == 1; }
/// Returns index of option, in the list box option list.
/// If option is not found, then -1 is returned.
/// \param option Option
int findOption(const QString& option) const;
/// Sets widget appearance, such as font, font size, color, text alignment,
/// and rectangle, in which widget resides on page (in page coordinates)
/// \param font Font
/// \param fontColor Font color
/// \param textAlignment Text alignment
/// \param rect Widget rectangle in page coordinates
/// \param options Options selectable by list box
/// \param topIndex Index of first visible item
void initialize(QFont font, QColor fontColor, Qt::Alignment textAlignment, QRectF rect,
const Options& options, int topIndex, std::set<int> selection);
private:
int getStartItemIndex() const { return 0; }
int getEndItemIndex() const { return m_options.empty() ? 0 : int(m_options.size() - 1); }
int getSingleStep() const { return 1; }
int getPageStep() const { return qMax(getViewportRowCount() - 1, getSingleStep()); }
/// Returns true, if row with this index is visible in the widget
/// (it is in viewport).
/// \param index Index
bool isVisible(int index) const;
/// Moves current item by offset (negative is up, positive is down)
/// \param offset Offset
/// \param modifiers Keyboard modifiers
void moveCurrentItemIndexByOffset(int offset, Qt::KeyboardModifiers modifiers) { setCurrentItem(m_currentIndex + offset, modifiers); }
/// Returns true, if list box has continuous selection
bool hasContinuousSelection() const;
/// Creates transformation matrix, which transforms widget coordinates to page coordinates
QTransform createListBoxTransformMatrix() const;
PDFFormField::FieldFlags m_flags;
Options m_options;
Qt::Alignment m_textAlignment = Qt::Alignment();
int m_topIndex = 0;
int m_currentIndex = 0;
std::set<int> m_selection;
QFont m_font;
PDFReal m_lineSpacing = 0.0;
QRectF m_widgetRect;
QColor m_textColor;
};
PDFForm PDFForm::parse(const PDFDocument* document, PDFObject object)
{
PDFForm form;
@ -807,7 +671,7 @@ void PDFFormManager::setDocument(const PDFModifiedDocument& document)
m_form = PDFForm();
}
updateFormWidgetEditors();
onDocumentReset();
}
else if (document.hasFlag(PDFModifiedDocument::FormField))
{
@ -1036,6 +900,18 @@ void PDFFormManager::performPaging()
}
}
bool PDFFormManager::isFocused(PDFObjectReference widget) const
{
Q_UNUSED(widget);
return false;
}
bool PDFFormManager::isEditorDrawEnabled(const PDFObjectReference& reference) const
{
Q_UNUSED(reference);
return false;
}
void PDFFormManager::updateFieldValues()
{
if (m_document)

View File

@ -591,8 +591,25 @@ public:
/// is emitted.
void performPaging();
/// Returns true, if widget is focused.
/// \param widget Widget annotation reference
virtual bool isFocused(PDFObjectReference widget) const;
/// Is editor draw enabled?
virtual bool isEditorDrawEnabled(const PDFObjectReference& reference) const;
virtual bool isEditorDrawEnabled(const PDFFormField* formField) const;
/// Draw form field widget using given parameters. It is used, when
/// we want to draw editor contents on the painter using parameters.
/// Parameter \p edit decides, if editor is drawn, or static contents
/// based on field value is drawn.
/// \param parameters Parameters
/// \param edit Draw editor or static contents
virtual void drawFormField(const PDFFormField* formField, AnnotationDrawParameters& parameters, bool edit) const;
protected:
virtual void updateFieldValues();
virtual void onDocumentReset() { }
signals:
void actionTriggered(const pdf::PDFAction* action);

View File

@ -27,6 +27,142 @@
namespace pdf
{
/// "Pseudo" widget, which is emulating list box. It can contain scrollbar.
class PDFListBoxPseudowidget
{
public:
explicit PDFListBoxPseudowidget(PDFFormField::FieldFlags flags);
using Options = PDFFormFieldChoice::Options;
inline bool isReadonly() const { return m_flags.testFlag(PDFFormField::ReadOnly); }
inline bool isMultiSelect() const { return m_flags.testFlag(PDFFormField::MultiSelect); }
inline bool isCommitOnSelectionChange() const { return m_flags.testFlag(PDFFormField::CommitOnSelectionChange); }
void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event);
void keyPressEvent(QWidget* widget, QKeyEvent* event);
/// Sets widget appearance, such as font, font size, color, text alignment,
/// and rectangle, in which widget resides on page (in page coordinates)
/// \param appearance Appearance
/// \param textAlignment Text alignment
/// \param rect Widget rectangle in page coordinates
/// \param options Options selectable by list box
/// \param topIndex Index of first visible item
void setAppearance(const PDFAnnotationDefaultAppearance& appearance,
Qt::Alignment textAlignment,
QRectF rect,
const Options& options,
int topIndex,
std::set<int> selection);
/// Draw text edit using given parameters
/// \param parameters Parameters
void draw(AnnotationDrawParameters& parameters, bool edit) const;
/// Sets current selection. If commit on selection change flag
/// is set, then contents of the widgets are commited. New selection
/// is not set, if field is readonly and \p force is false
/// \param selection New selection
/// \param force Set selection even if readonly
void setSelection(std::set<int> selection, bool force);
/// Returns active item selection
const std::set<int>& getSelection() const { return m_selection; }
/// Returns top index
int getTopItemIndex() const { return m_topIndex; }
/// Set top item index
/// \param index Top item index
void setTopItemIndex(int index);
/// Scrolls the list box in such a way, that index is visible
/// \param index Index to scroll to
void scrollTo(int index);
/// Returns valid index from index (i.e. index which ranges from first
/// row to the last one). If index itself is valid, then it is returned.
/// \param index Index, from which we want to get valid one
int getValidIndex(int index) const;
/// Returns true, if index is valid
bool isValidIndex(int index) const { return index == getValidIndex(index); }
/// Returns number of rows in the viewport
int getViewportRowCount() const { return qFloor(m_widgetRect.height() / m_lineSpacing); }
/// Returns item index from widget position (i.e. transforms
/// point in the widget to the index of item, which is under the point)
/// \param point Widget point
int getIndexFromWidgetPosition(const QPointF& point) const;
/// Sets current item and updates selection based on keyboard modifiers
/// \param index New index
/// \param modifiers Keyboard modifiers
void setCurrentItem(int index, Qt::KeyboardModifiers modifiers);
/// Returns text of selected item text. If no item is selected,
/// or multiple items are selected, then empty string is returned.
/// \returns Selected text
QString getSelectedItemText() const;
/// Returns true, if single item is selected
bool isSingleItemSelected() const { return m_selection.size() == 1; }
/// Returns index of option, in the list box option list.
/// If option is not found, then -1 is returned.
/// \param option Option
int findOption(const QString& option) const;
/// Sets widget appearance, such as font, font size, color, text alignment,
/// and rectangle, in which widget resides on page (in page coordinates)
/// \param font Font
/// \param fontColor Font color
/// \param textAlignment Text alignment
/// \param rect Widget rectangle in page coordinates
/// \param options Options selectable by list box
/// \param topIndex Index of first visible item
void initialize(QFont font, QColor fontColor, Qt::Alignment textAlignment, QRectF rect,
const Options& options, int topIndex, std::set<int> selection);
private:
int getStartItemIndex() const { return 0; }
int getEndItemIndex() const { return m_options.empty() ? 0 : int(m_options.size() - 1); }
int getSingleStep() const { return 1; }
int getPageStep() const { return qMax(getViewportRowCount() - 1, getSingleStep()); }
/// Returns true, if row with this index is visible in the widget
/// (it is in viewport).
/// \param index Index
bool isVisible(int index) const;
/// Moves current item by offset (negative is up, positive is down)
/// \param offset Offset
/// \param modifiers Keyboard modifiers
void moveCurrentItemIndexByOffset(int offset, Qt::KeyboardModifiers modifiers) { setCurrentItem(m_currentIndex + offset, modifiers); }
/// Returns true, if list box has continuous selection
bool hasContinuousSelection() const;
/// Creates transformation matrix, which transforms widget coordinates to page coordinates
QTransform createListBoxTransformMatrix() const;
PDFFormField::FieldFlags m_flags;
Options m_options;
Qt::Alignment m_textAlignment = Qt::Alignment();
int m_topIndex = 0;
int m_currentIndex = 0;
std::set<int> m_selection;
QFont m_font;
PDFReal m_lineSpacing = 0.0;
QRectF m_widgetRect;
QColor m_textColor;
};
/// Editor for button-like editors
class PDFFormFieldAbstractButtonEditor : public PDFFormFieldWidgetEditor
{
@ -2016,4 +2152,30 @@ void PDFFormFieldListBoxEditor::commit()
}
}
PDFWidgetFormManager::isEditorDrawEnabled(const PDFObjectReference& reference) const
{
const PDFFormFieldWidgetEditor* editor = getEditor(getFormFieldForWidget(reference));
return editor && editor->isEditorDrawEnabled();
}
void PDFWidgetFormManager::onDocumentReset()
{
updateFormWidgetEditors();
}
bool PDFWidgetFormManager::isEditorDrawEnabled(const PDFFormField* formField) const
{
const PDFFormFieldWidgetEditor* editor = getEditor(formField);
return editor && editor->isEditorDrawEnabled();
}
void PDFWidgetFormManager::drawFormField(const PDFFormField* formField, AnnotationDrawParameters& parameters, bool edit) const
{
const PDFFormFieldWidgetEditor* editor = getEditor(formField);
if (editor)
{
editor->draw(parameters, edit);
}
}
} // namespace pdf

View File

@ -53,7 +53,7 @@ public:
/// based on field value is drawn.
/// \param parameters Parameters
/// \param edit Draw editor or static contents
virtual void draw(AnnotationDrawParameters& parameters, bool edit) const;
virtual void draw(AnnotationDrawParameters& parameters, bool edit) const override;
protected:
/// This function is called every time, the focus state changes
@ -104,7 +104,7 @@ public:
/// Returns true, if widget is focused.
/// \param widget Widget annotation reference
bool isFocused(PDFObjectReference widget) const;
virtual bool isFocused(PDFObjectReference widget) const override;
/// Returns editor for form field
PDFFormFieldWidgetEditor* getEditor(const PDFFormField* formField) const;
@ -130,8 +130,13 @@ public:
bool isValid() const { return editor != nullptr; }
};
virtual bool isEditorDrawEnabled(const PDFObjectReference& reference) const override;
virtual bool isEditorDrawEnabled(const PDFFormField* formField) const override;
virtual void drawFormField(const PDFFormField* formField, AnnotationDrawParameters& parameters, bool edit) const override;
protected:
virtual void updateFieldValues() override;
virtual void onDocumentReset() override;
private:
void updateFormWidgetEditors();