Push button implementation

This commit is contained in:
Jakub Melka 2020-04-28 19:55:30 +02:00
parent c5027e9eeb
commit c9d2c3dd8b
10 changed files with 316 additions and 28 deletions

View File

@ -114,7 +114,7 @@ PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFObjectStorage* stora
{
PDFAppeareanceStreams result;
auto processSubdicitonary = [&result, storage](Appearance appearance, PDFObject subdictionaryObject)
auto processSubdictionary = [&result, storage](Appearance appearance, PDFObject subdictionaryObject)
{
subdictionaryObject = storage->getObject(subdictionaryObject);
if (subdictionaryObject.isDictionary())
@ -133,9 +133,9 @@ PDFAppeareanceStreams PDFAppeareanceStreams::parse(const PDFObjectStorage* stora
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
{
processSubdicitonary(Appearance::Normal, dictionary->get("N"));
processSubdicitonary(Appearance::Rollover, dictionary->get("R"));
processSubdicitonary(Appearance::Down, dictionary->get("D"));
processSubdictionary(Appearance::Normal, dictionary->get("N"));
processSubdictionary(Appearance::Rollover, dictionary->get("R"));
processSubdictionary(Appearance::Down, dictionary->get("D"));
}
return result;
@ -507,7 +507,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject
annotation->m_screenTitle = loader.readTextStringFromDictionary(dictionary, "T", QString());
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(storage, dictionary->get("MK"));
annotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"));
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"), dictionary->get("A"));
}
else if (subtype == "Widget")
{
@ -525,7 +525,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject
annotation->m_highlightMode = loader.readEnumByName(dictionary->get("H"), highlightModes.begin(), highlightModes.end(), PDFWidgetAnnotation::HighlightMode::Invert);
annotation->m_appearanceCharacteristics = PDFAnnotationAppearanceCharacteristics::parse(storage, dictionary->get("MK"));
annotation->m_action = PDFAction::parse(storage, dictionary->get("A"));
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"));
annotation->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, dictionary->get("AA"), dictionary->get("A"));
}
else if (subtype == "PrinterMark")
{
@ -866,7 +866,7 @@ PDFAnnotationIconFitInfo PDFAnnotationIconFitInfo::parse(const PDFObjectStorage*
return info;
}
PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFObjectStorage* storage, PDFObject object)
PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFObjectStorage* storage, PDFObject object, PDFObject defaultAction)
{
PDFAnnotationAdditionalActions result;
@ -884,6 +884,7 @@ PDFAnnotationAdditionalActions PDFAnnotationAdditionalActions::parse(const PDFOb
result.m_actions[PageHide] = PDFAction::parse(storage, dictionary->get("PI"));
}
result.m_actions[Default] = PDFAction::parse(storage, defaultAction);
return result;
}
@ -1342,6 +1343,12 @@ void PDFWidgetAnnotationManager::keyPressEvent(QWidget* widget, QKeyEvent* event
Q_UNUSED(event);
}
void PDFWidgetAnnotationManager::keyReleaseEvent(QWidget* widget, QKeyEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFWidgetAnnotationManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
{
Q_UNUSED(widget);

View File

@ -383,6 +383,7 @@ public:
PageClosed,
PageShow,
PageHide,
Default,
End
};
@ -397,7 +398,8 @@ public:
/// empty additional actions is constructed.
/// \param storage Object storage
/// \param object Additional actions object
static PDFAnnotationAdditionalActions parse(const PDFObjectStorage* storage, PDFObject object);
/// \param defaultAction Default action of object (defined in "A" entry of annotation dictionary)
static PDFAnnotationAdditionalActions parse(const PDFObjectStorage* storage, PDFObject object, PDFObject defaultAction);
private:
std::array<PDFActionPtr, End> m_actions;
@ -1409,6 +1411,11 @@ public:
/// \param event Event
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
/// Handles key release event from widget
/// \param widget Widget
/// \param event Event
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
/// Handles mouse press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// \param event Event
@ -1438,7 +1445,7 @@ public:
virtual int getInputPriority() const override { return AnnotationPriority; }
signals:
void actionTriggered(const pdf::PDFAction* action);
void actionTriggered(const PDFAction* action);
private:
void updateFromMouseEvent(QMouseEvent* event);

View File

@ -79,6 +79,11 @@ public:
/// \param event Event
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) = 0;
/// Handles key release event from widget
/// \param widget Widget
/// \param event Event
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) = 0;
/// Handles mouse press event from widget
/// \param widget Widget
/// \param event Event

View File

@ -339,6 +339,19 @@ void PDFDrawWidgetBase<BaseWidget>::keyPressEvent(QKeyEvent* event)
updateCursor();
}
template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::keyReleaseEvent(QKeyEvent* event)
{
event->ignore();
if (processEvent<QKeyEvent, &IDrawWidgetInputInterface::keyReleaseEvent>(event))
{
return;
}
event->accept();
}
template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::mousePressEvent(QMouseEvent* event)
{

View File

@ -139,6 +139,7 @@ public:
protected:
virtual void keyPressEvent(QKeyEvent* event) override;
virtual void keyReleaseEvent(QKeyEvent* event) override;
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;

View File

@ -19,6 +19,10 @@
#include "pdfdocument.h"
#include "pdfdrawspacecontroller.h"
#include <QKeyEvent>
#include <QMouseEvent>
#include <QApplication>
namespace pdf
{
@ -228,7 +232,7 @@ PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObje
formField->m_fieldFlags = fieldDictionary->hasKey("Ff") ? static_cast<FieldFlags>(loader.readIntegerFromDictionary(fieldDictionary, "Ff", 0)) : parentFlags;
formField->m_value = fieldDictionary->hasKey("V") ? fieldDictionary->get("V") : parentV;
formField->m_defaultValue = fieldDictionary->hasKey("DV") ? fieldDictionary->get("DV") : parentDV;
formField->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, fieldDictionary->get("AA"));
formField->m_additionalActions = PDFAnnotationAdditionalActions::parse(storage, fieldDictionary->get("AA"), fieldDictionary->get("A"));
// Generate fully qualified name. If partial name is empty, then fully qualified name
// is generated from parent fully qualified name (i.e. it is same as parent's name).
@ -340,17 +344,23 @@ PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObje
return result;
}
PDFFormWidget::PDFFormWidget(PDFObjectReference widget, PDFFormField* parentField) :
PDFFormWidget::PDFFormWidget(PDFObjectReference widget, PDFFormField* parentField, PDFAnnotationAdditionalActions actions) :
m_widget(widget),
m_parentField(parentField)
m_parentField(parentField),
m_actions(qMove(actions))
{
}
PDFFormWidget PDFFormWidget::parse(const PDFObjectStorage* storage, PDFObjectReference reference, PDFFormField* parentField)
{
Q_UNUSED(storage);
return PDFFormWidget(reference, parentField);
PDFAnnotationAdditionalActions actions;
if (const PDFDictionary* annotationDictionary = storage->getDictionaryFromObject(storage->getObjectByReference(reference)))
{
actions = PDFAnnotationAdditionalActions::parse(storage, annotationDictionary->get("AA"), annotationDictionary->get("A"));
}
return PDFFormWidget(reference, parentField, qMove(actions));
}
PDFFormFieldButton::ButtonType PDFFormFieldButton::getButtonType() const
@ -563,10 +573,38 @@ bool PDFFormManager::isFocused(PDFObjectReference widget) const
return false;
}
const PDFAction* PDFFormManager::getAction(PDFAnnotationAdditionalActions::Action actionType, const PDFFormWidget* widget)
{
if (const PDFAction* action = widget->getAction(actionType))
{
return action;
}
for (const PDFFormField* formField = widget->getParent(); formField; formField = formField->getParentField())
{
if (const PDFAction* action = formField->getAction(actionType))
{
return action;
}
}
return nullptr;
}
void PDFFormManager::keyPressEvent(QWidget* widget, QKeyEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
if (m_focusedEditor)
{
m_focusedEditor->keyPressEvent(widget, event);
}
}
void PDFFormManager::keyReleaseEvent(QWidget* widget, QKeyEvent* event)
{
if (m_focusedEditor)
{
m_focusedEditor->keyReleaseEvent(widget, event);
}
}
void PDFFormManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
@ -695,17 +733,170 @@ PDFFormFieldWidgetEditor::PDFFormFieldWidgetEditor(PDFFormManager* formManager,
Q_ASSERT(m_formManager);
}
void PDFFormFieldWidgetEditor::keyPressEvent(QWidget* widget, QKeyEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFFormFieldWidgetEditor::keyReleaseEvent(QWidget* widget, QKeyEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFFormFieldWidgetEditor::mousePressEvent(QWidget* widget, QMouseEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFFormFieldWidgetEditor::mouseReleaseEvent(QWidget* widget, QMouseEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFFormFieldWidgetEditor::mouseMoveEvent(QWidget* widget, QMouseEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFFormFieldWidgetEditor::setFocus(bool hasFocus)
{
m_hasFocus = hasFocus;
}
void PDFFormFieldWidgetEditor::performKeypadNavigation(QWidget* widget, QKeyEvent* event)
{
int key = event->key();
const bool isLeft = key == Qt::Key_Left;
const bool isRight = key == Qt::Key_Right;
const bool isUp = key == Qt::Key_Up;
const bool isDown = key == Qt::Key_Down;
const bool isHorizontal = isLeft || isRight;
Qt::NavigationMode navigationMode = Qt::NavigationModeKeypadDirectional;
#ifdef QT_KEYPAD_NAVIGATION
navigationMode = QApplication::navigationMode();
#endif
switch (navigationMode)
{
case Qt::NavigationModeKeypadTabOrder:
{
// According the Qt's documentation, Up/Down arrows are used
// to change focus. So, if user pressed Left/Right, we must
// ignore this event.
if (isHorizontal)
{
return;
}
break;
}
case Qt::NavigationModeKeypadDirectional:
// Default behaviour
break;
default:
// Nothing happens
return;
}
bool next = false;
if (isHorizontal)
{
switch (widget->layoutDirection())
{
case Qt::LeftToRight:
case Qt::LayoutDirectionAuto:
next = isRight;
break;
case Qt::RightToLeft:
next = isLeft;
break;
default:
Q_ASSERT(false);
break;
}
}
else
{
// Vertical
next = isDown;
}
m_formManager->focusNextPrevFormField(next);
}
PDFFormFieldPushButtonEditor::PDFFormFieldPushButtonEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent) :
BaseClass(formManager, formWidget, parent)
{
}
void PDFFormFieldPushButtonEditor::keyPressEvent(QWidget* widget, QKeyEvent* event)
{
switch (event->key())
{
case Qt::Key_Enter:
case Qt::Key_Return:
{
click();
event->accept();
break;
}
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Up:
case Qt::Key_Down:
{
performKeypadNavigation(widget, event);
break;
}
default:
break;
}
}
void PDFFormFieldPushButtonEditor::keyReleaseEvent(QWidget* widget, QKeyEvent* event)
{
Q_UNUSED(widget);
switch (event->key())
{
case Qt::Key_Select:
case Qt::Key_Space:
{
click();
event->accept();
break;
}
default:
break;
}
}
void PDFFormFieldPushButtonEditor::click()
{
if (const PDFAction* action = m_formManager->getAction(PDFAnnotationAdditionalActions::MousePressed, getFormWidget()))
{
emit m_formManager->actionTriggered(action);
}
else if (const PDFAction* action = m_formManager->getAction(PDFAnnotationAdditionalActions::Default, getFormWidget()))
{
emit m_formManager->actionTriggered(action);
}
}
PDFFormFieldCheckableButtonEditor::PDFFormFieldCheckableButtonEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent) :
BaseClass(formManager, formWidget, parent)
{

View File

@ -40,10 +40,11 @@ class PDFFormWidget
{
public:
explicit inline PDFFormWidget() = default;
explicit inline PDFFormWidget(PDFObjectReference widget, PDFFormField* parentField);
explicit inline PDFFormWidget(PDFObjectReference widget, PDFFormField* parentField, PDFAnnotationAdditionalActions actions);
PDFObjectReference getWidget() const { return m_widget; }
PDFFormField* getParent() const { return m_parentField; }
const PDFAction* getAction(PDFAnnotationAdditionalActions::Action action) const { return m_actions.getAction(action); }
/// Parses form widget from the object reference. If some error occurs
/// then empty object is returned, no exception is thrown.
@ -55,6 +56,7 @@ public:
private:
PDFObjectReference m_widget;
PDFFormField* m_parentField;
PDFAnnotationAdditionalActions m_actions;
};
using PDFFormWidgets = std::vector<PDFFormWidget>;
@ -198,6 +200,10 @@ public:
/// \param functor Functor to apply
void apply(const std::function<void(const PDFFormField*)>& functor) const;
/// Returns action by type. If action is not found, nullptr is returned
/// \param action Action type
const PDFAction* getAction(PDFAnnotationAdditionalActions::Action action) const { return m_additionalActions.getAction(action); }
/// Parses form field from the object reference. If some error occurs
/// then null pointer is returned, no exception is thrown.
/// \param storage Storage
@ -379,12 +385,21 @@ public:
explicit PDFFormFieldWidgetEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent);
virtual ~PDFFormFieldWidgetEditor() = default;
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event);
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event);
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event);
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event);
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event);
const PDFFormWidget* getFormWidget() const { return &m_formWidget; }
PDFFormField* getFormField() const { return m_formWidget.getParent(); }
PDFObjectReference getWidgetAnnotation() const { return m_formWidget.getWidget(); }
void setFocus(bool hasFocus);
private:
protected:
void performKeypadNavigation(QWidget* widget, QKeyEvent* event);
PDFFormManager* m_formManager;
PDFFormWidget m_formWidget;
bool m_hasFocus;
@ -401,6 +416,12 @@ private:
public:
explicit PDFFormFieldPushButtonEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent);
virtual ~PDFFormFieldPushButtonEditor() = default;
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event);
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event);
private:
void click();
};
/// Editor for check boxes or radio buttons
@ -523,33 +544,44 @@ public:
/// \param widget Widget annotation reference
bool isFocused(PDFObjectReference widget) const;
/// Tries to find appropriate action and returns it. If action is not found,
/// then nullptr is returned.
/// \param actionType Action to be performed
/// \param widget Form field widget
const PDFAction* getAction(PDFAnnotationAdditionalActions::Action actionType, const PDFFormWidget* widget);
/// Returns default form apperance flags
static constexpr FormAppearanceFlags getDefaultApperanceFlags() { return HighlightFields | HighlightRequiredFields; }
// interface IDrawWidgetInputInterface
/// Handles key press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// Handles key press event from widget
/// \param widget Widget
/// \param event Event
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
/// Handles mouse press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// Handles key release event from widget
/// \param widget Widget
/// \param event Event
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
/// Handles mouse press event from widget
/// \param widget Widget
/// \param event Event
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override;
/// Handles mouse release event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// Handles mouse release event from widget
/// \param widget Widget
/// \param event Event
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) override;
/// Handles mouse move event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// Handles mouse move event from widge
/// \param widget Widget
/// \param event Event
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override;
/// Handles mouse wheel event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// Handles mouse wheel event from widget
/// \param widget Widget
/// \param event Event
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;
@ -561,6 +593,9 @@ public:
virtual int getInputPriority() const override { return FormPriority; }
signals:
void actionTriggered(const PDFAction* action);
private:
void updateFormWidgetEditors();
void updateFieldValues();

View File

@ -113,6 +113,14 @@ void PDFWidgetTool::keyPressEvent(QWidget* widget, QKeyEvent* event)
}
}
void PDFWidgetTool::keyReleaseEvent(QWidget* widget, QKeyEvent* event)
{
if (PDFWidgetTool* tool = getTopToolstackTool())
{
tool->keyReleaseEvent(widget, event);
}
}
void PDFWidgetTool::mousePressEvent(QWidget* widget, QMouseEvent* event)
{
if (PDFWidgetTool* tool = getTopToolstackTool())
@ -799,6 +807,16 @@ void PDFToolManager::keyPressEvent(QWidget* widget, QKeyEvent* event)
}
}
void PDFToolManager::keyReleaseEvent(QWidget* widget, QKeyEvent* event)
{
event->ignore();
if (PDFWidgetTool* activeTool = getActiveTool())
{
activeTool->keyReleaseEvent(widget, event);
}
}
void PDFToolManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
{
event->ignore();

View File

@ -66,6 +66,11 @@ public:
/// \param event Event
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event);
/// Handles key release event from widget
/// \param widget Widget
/// \param event Event
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event);
/// Handles mouse press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// \param event Event
@ -446,6 +451,11 @@ public:
/// \param event Event
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
/// Handles key release event from widget
/// \param widget Widget
/// \param event Event
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
/// Handles mouse press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// \param event Event

View File

@ -276,6 +276,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags);
m_annotationManager->setFormManager(m_formManager);
m_pdfWidget->setFormManager(m_formManager);
connect(m_formManager, &pdf::PDFFormManager::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::drawSpaceChanged, this, &PDFViewerMainWindow::onDrawSpaceChanged);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::pageLayoutChanged, this, &PDFViewerMainWindow::onPageLayoutChanged);