Input event processing refactoring

This commit is contained in:
Jakub Melka 2020-04-20 19:03:32 +02:00
parent bf76e3aa22
commit b654ce463a
8 changed files with 181 additions and 131 deletions

View File

@ -1378,7 +1378,7 @@ protected:
/// Annotation manager for GUI rendering, it also manages annotations widgets
/// for parent widget.
class PDFFORQTLIBSHARED_EXPORT PDFWidgetAnnotationManager : public PDFAnnotationManager
class PDFFORQTLIBSHARED_EXPORT PDFWidgetAnnotationManager : public PDFAnnotationManager, public IDrawWidgetInputInterface
{
Q_OBJECT
@ -1392,33 +1392,35 @@ public:
/// Handles key press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// \param event Event
void keyPressEvent(QWidget* widget, QKeyEvent* 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
/// \param event Event
void mousePressEvent(QWidget* widget, QMouseEvent* 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
/// \param event Event
void mouseReleaseEvent(QWidget* widget, QMouseEvent* 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
/// \param event Event
void mouseMoveEvent(QWidget* widget, QMouseEvent* 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
/// \param event Event
void wheelEvent(QWidget* widget, QWheelEvent* event);
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;
/// Returns tooltip generated from annotation
const QString& getTooltip() const { return m_tooltip; }
virtual QString getTooltip() const override { return m_tooltip; }
/// Returns current cursor
const std::optional<QCursor>& getCursor() const { return m_cursor;}
virtual const std::optional<QCursor>& getCursor() const override { return m_cursor; }
virtual int getInputPriority() const override { return AnnotationPriority; }
signals:
void actionTriggered(const pdf::PDFAction* action);

View File

@ -22,6 +22,9 @@
#include "pdfexception.h"
class QPainter;
class QKeyEvent;
class QMouseEvent;
class QWheelEvent;
namespace pdf
{
@ -55,6 +58,71 @@ public:
virtual void drawPostRendering(QPainter* painter, QRect rect) const;
};
/// Input interface for handling events. Implementations should react on these events,
/// and set it to accepted, if they were consumed by the interface. Interface, which
/// consumes mouse press event, should also consume mouse release event.
class IDrawWidgetInputInterface
{
public:
explicit inline IDrawWidgetInputInterface() = default;
virtual ~IDrawWidgetInputInterface() = default;
enum InputPriority
{
ToolPriority = 10,
FormPriority = 20,
AnnotationPriority = 30
};
/// Handles key press event from widget
/// \param widget Widget
/// \param event Event
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) = 0;
/// Handles mouse press event from widget
/// \param widget Widget
/// \param event Event
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) = 0;
/// Handles mouse release event from widget
/// \param widget Widget
/// \param event Event
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) = 0;
/// Handles mouse move event from widget
/// \param widget Widget
/// \param event Event
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) = 0;
/// Handles mouse wheel event from widget
/// \param widget Widget
/// \param event Event
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) = 0;
/// Returns tooltip
virtual QString getTooltip() const = 0;
/// Returns current cursor
virtual const std::optional<QCursor>& getCursor() const = 0;
/// Returns input priority (interfaces with higher priority
/// will get input events before interfaces with lower priority)
virtual int getInputPriority() const = 0;
class Comparator
{
public:
explicit constexpr inline Comparator() = default;
bool operator()(IDrawWidgetInputInterface* left, IDrawWidgetInputInterface* right) const
{
return std::make_pair(left->getInputPriority(), left) < std::make_pair(right->getInputPriority(), right);
}
};
static constexpr Comparator getComparator() { return Comparator(); }
};
} // namespace pdf
#endif // PDFDOCUMENTDRAWINTERFACE_H

View File

@ -395,7 +395,6 @@ PDFDrawWidgetProxy::PDFDrawWidgetProxy(QObject* parent) :
m_textLayoutCompiler(new PDFAsynchronousTextLayoutCompiler(this)),
m_rasterizer(new PDFRasterizer(this)),
m_progress(nullptr),
m_annotationManager(nullptr),
m_useOpenGL(false)
{
m_controller = new PDFDrawSpaceController(this);
@ -832,7 +831,7 @@ QImage PDFDrawWidgetProxy::drawThumbnailImage(PDFInteger pageIndex, int pixelSiz
if (compiledPage && compiledPage->isValid())
{
// Rasterize the image.
image = m_rasterizer->render(pageIndex, page, compiledPage, imageSize, m_features, m_annotationManager);
image = m_rasterizer->render(pageIndex, page, compiledPage, imageSize, m_features, m_widget->getAnnotationManager());
}
if (image.isNull())
@ -1296,12 +1295,7 @@ void PDFDrawWidgetProxy::updateVerticalScrollbarFromOffset()
PDFWidgetAnnotationManager* PDFDrawWidgetProxy::getAnnotationManager() const
{
return m_annotationManager;
}
void PDFDrawWidgetProxy::setAnnotationManager(PDFWidgetAnnotationManager* annotationManager)
{
m_annotationManager = annotationManager;
return m_widget->getAnnotationManager();
}
PDFRenderer::Features PDFDrawWidgetProxy::getFeatures() const

View File

@ -358,7 +358,6 @@ public:
PDFWidgetSnapshot getSnapshot() const;
PDFWidgetAnnotationManager* getAnnotationManager() const;
void setAnnotationManager(PDFWidgetAnnotationManager* annotationManager);
signals:
void drawSpaceChanged();
@ -496,9 +495,6 @@ private:
/// Progress
PDFProgress* m_progress;
/// Annotation manager
PDFWidgetAnnotationManager* m_annotationManager;
/// Additional drawing interfaces
std::set<IDocumentDrawInterface*> m_drawInterfaces;

View File

@ -173,6 +173,38 @@ IDrawWidget* PDFWidget::createDrawWidget(RendererEngine rendererEngine, int samp
return nullptr;
}
void PDFWidget::removeInputInterface(IDrawWidgetInputInterface* inputInterface)
{
auto it = std::find(m_inputInterfaces.begin(), m_inputInterfaces.end(), inputInterface);
if (it != m_inputInterfaces.end())
{
m_inputInterfaces.erase(it);
}
}
void PDFWidget::addInputInterface(IDrawWidgetInputInterface* inputInterface)
{
if (inputInterface)
{
m_inputInterfaces.push_back(inputInterface);
std::sort(m_inputInterfaces.begin(), m_inputInterfaces.end(), IDrawWidgetInputInterface::Comparator());
}
}
void PDFWidget::setToolManager(PDFToolManager* toolManager)
{
removeInputInterface(m_toolManager);
m_toolManager = toolManager;
addInputInterface(m_toolManager);
}
void PDFWidget::setAnnotationManager(PDFWidgetAnnotationManager* annotationManager)
{
removeInputInterface(m_annotationManager);
m_annotationManager = annotationManager;
addInputInterface(m_annotationManager);
}
template<typename BaseWidget>
PDFDrawWidgetBase<BaseWidget>::PDFDrawWidgetBase(PDFWidget* widget, QWidget* parent) :
BaseWidget(parent),
@ -217,31 +249,42 @@ void PDFDrawWidgetBase<BaseWidget>::performMouseOperation(QPoint currentMousePos
}
}
template<typename BaseWidget>
template<typename Event, void (IDrawWidgetInputInterface::* Function)(QWidget*, Event*)>
bool PDFDrawWidgetBase<BaseWidget>::processEvent(Event* event)
{
QString tooltip;
for (IDrawWidgetInputInterface* inputInterface : m_widget->getInputInterfaces())
{
(inputInterface->*Function)(this, event);
// Update tooltip
if (tooltip.isEmpty())
{
tooltip = inputInterface->getTooltip();
}
// If event is accepted, then update cursor/tooltip and return
if (event->isAccepted())
{
setToolTip(tooltip);
updateCursor();
return true;
}
}
setToolTip(tooltip);
return false;
}
template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::keyPressEvent(QKeyEvent* event)
{
event->ignore();
// Try to pass event to tool manager
if (PDFToolManager* toolManager = getPDFWidget()->getToolManager())
if (processEvent<QKeyEvent, &IDrawWidgetInputInterface::keyPressEvent>(event))
{
toolManager->keyPressEvent(this, event);
if (event->isAccepted())
{
updateCursor();
return;
}
}
if (PDFWidgetAnnotationManager* annotationManager = getPDFWidget()->getDrawWidgetProxy()->getAnnotationManager())
{
annotationManager->keyPressEvent(this, event);
setToolTip(annotationManager->getTooltip());
if (event->isAccepted())
{
updateCursor();
return;
}
return;
}
// Vertical navigation
@ -276,26 +319,9 @@ void PDFDrawWidgetBase<BaseWidget>::mousePressEvent(QMouseEvent* event)
{
event->ignore();
// Try to pass event to tool manager
if (PDFToolManager* toolManager = getPDFWidget()->getToolManager())
if (processEvent<QMouseEvent, &IDrawWidgetInputInterface::mousePressEvent>(event))
{
toolManager->mousePressEvent(this, event);
if (event->isAccepted())
{
updateCursor();
return;
}
}
if (PDFWidgetAnnotationManager* annotationManager = getPDFWidget()->getDrawWidgetProxy()->getAnnotationManager())
{
annotationManager->mousePressEvent(this, event);
setToolTip(annotationManager->getTooltip());
if (event->isAccepted())
{
updateCursor();
return;
}
return;
}
if (event->button() == Qt::LeftButton)
@ -313,26 +339,9 @@ void PDFDrawWidgetBase<BaseWidget>::mouseReleaseEvent(QMouseEvent* event)
{
event->ignore();
// Try to pass event to tool manager
if (PDFToolManager* toolManager = getPDFWidget()->getToolManager())
if (processEvent<QMouseEvent, &IDrawWidgetInputInterface::mouseReleaseEvent>(event))
{
toolManager->mouseReleaseEvent(this, event);
if (event->isAccepted())
{
updateCursor();
return;
}
}
if (PDFWidgetAnnotationManager* annotationManager = getPDFWidget()->getDrawWidgetProxy()->getAnnotationManager())
{
annotationManager->mouseReleaseEvent(this, event);
setToolTip(annotationManager->getTooltip());
if (event->isAccepted())
{
updateCursor();
return;
}
return;
}
performMouseOperation(event->pos());
@ -361,26 +370,9 @@ void PDFDrawWidgetBase<BaseWidget>::mouseMoveEvent(QMouseEvent* event)
{
event->ignore();
// Try to pass event to tool manager
if (PDFToolManager* toolManager = getPDFWidget()->getToolManager())
if (processEvent<QMouseEvent, &IDrawWidgetInputInterface::mouseMoveEvent>(event))
{
toolManager->mouseMoveEvent(this, event);
if (event->isAccepted())
{
updateCursor();
return;
}
}
if (PDFWidgetAnnotationManager* annotationManager = getPDFWidget()->getDrawWidgetProxy()->getAnnotationManager())
{
annotationManager->mouseMoveEvent(this, event);
setToolTip(annotationManager->getTooltip());
if (event->isAccepted())
{
updateCursor();
return;
}
return;
}
performMouseOperation(event->pos());
@ -392,16 +384,15 @@ template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::updateCursor()
{
std::optional<QCursor> cursor;
if (PDFToolManager* toolManager = m_widget->getToolManager())
{
cursor = toolManager->getCursor();
}
if (!cursor)
for (IDrawWidgetInputInterface* inputInterface : m_widget->getInputInterfaces())
{
if (PDFWidgetAnnotationManager* annotationManager = m_widget->getDrawWidgetProxy()->getAnnotationManager())
cursor = inputInterface->getCursor();
if (cursor)
{
cursor = annotationManager->getCursor();
// We have found cursor
break;
}
}
@ -438,26 +429,9 @@ void PDFDrawWidgetBase<BaseWidget>::wheelEvent(QWheelEvent* event)
{
event->ignore();
// Try to pass event to tool manager
if (PDFToolManager* toolManager = getPDFWidget()->getToolManager())
if (processEvent<QWheelEvent, &IDrawWidgetInputInterface::wheelEvent>(event))
{
toolManager->wheelEvent(this, event);
if (event->isAccepted())
{
updateCursor();
return;
}
}
if (PDFWidgetAnnotationManager* annotationManager = getPDFWidget()->getDrawWidgetProxy()->getAnnotationManager())
{
annotationManager->wheelEvent(this, event);
setToolTip(annotationManager->getTooltip());
if (event->isAccepted())
{
updateCursor();
return;
}
return;
}
Qt::KeyboardModifiers keyboardModifiers = QApplication::keyboardModifiers();

View File

@ -32,6 +32,8 @@ class PDFCMSManager;
class PDFToolManager;
class PDFDrawWidget;
class PDFDrawWidgetProxy;
class PDFWidgetAnnotationManager;
class IDrawWidgetInputInterface;
class IDrawWidget
{
@ -79,14 +81,17 @@ public:
const PDFCMSManager* getCMSManager() const { return m_cmsManager; }
PDFToolManager* getToolManager() const { return m_toolManager; }
PDFWidgetAnnotationManager* getAnnotationManager() const { return m_annotationManager; }
IDrawWidget* getDrawWidget() const { return m_drawWidget; }
QScrollBar* getHorizontalScrollbar() const { return m_horizontalScrollBar; }
QScrollBar* getVerticalScrollbar() const { return m_verticalScrollBar; }
PDFDrawWidgetProxy* getDrawWidgetProxy() const { return m_proxy; }
const PageRenderingErrors* getPageRenderingErrors() const { return &m_pageRenderingErrors; }
int getPageRenderingErrorCount() const;
const std::vector<IDrawWidgetInputInterface*>& getInputInterfaces() const { return m_inputInterfaces; }
void setToolManager(PDFToolManager* toolManager) { m_toolManager = toolManager; }
void setToolManager(PDFToolManager* toolManager);
void setAnnotationManager(PDFWidgetAnnotationManager* annotationManager);
signals:
void pageRenderingErrorsChanged(PDFInteger pageIndex, int errorsCount);
@ -98,13 +103,18 @@ private:
IDrawWidget* createDrawWidget(RendererEngine rendererEngine, int samplesCount);
void removeInputInterface(IDrawWidgetInputInterface* inputInterface);
void addInputInterface(IDrawWidgetInputInterface* inputInterface);
const PDFCMSManager* m_cmsManager;
PDFToolManager* m_toolManager;
PDFWidgetAnnotationManager* m_annotationManager;
IDrawWidget* m_drawWidget;
QScrollBar* m_horizontalScrollBar;
QScrollBar* m_verticalScrollBar;
PDFDrawWidgetProxy* m_proxy;
PageRenderingErrors m_pageRenderingErrors;
std::vector<IDrawWidgetInputInterface*> m_inputInterfaces;
};
template<typename BaseWidget>
@ -132,6 +142,9 @@ protected:
private:
void updateCursor();
template<typename Event, void(IDrawWidgetInputInterface::* Function)(QWidget*, Event*)>
bool processEvent(Event* event);
enum class MouseOperation
{
None,

View File

@ -386,7 +386,7 @@ private:
/// Manager used for managing tools, their activity, availability
/// and other settings. It also defines a predefined set of tools,
/// available for various purposes (text searching, magnifier tool etc.)
class PDFFORQTLIBSHARED_EXPORT PDFToolManager : public QObject
class PDFFORQTLIBSHARED_EXPORT PDFToolManager : public QObject, public IDrawWidgetInputInterface
{
Q_OBJECT
@ -444,31 +444,34 @@ public:
/// Handles key press event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// \param event Event
void keyPressEvent(QWidget* widget, QKeyEvent* 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
/// \param event Event
void mousePressEvent(QWidget* widget, QMouseEvent* 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
/// \param event Event
void mouseReleaseEvent(QWidget* widget, QMouseEvent* 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
/// \param event Event
void mouseMoveEvent(QWidget* widget, QMouseEvent* 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
/// \param event Event
void wheelEvent(QWidget* widget, QWheelEvent* event);
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;
/// Returns actual cursor defined by the tool. Cursor can be undefined,
/// in this case, optional will be set to nullopt.
const std::optional<QCursor>& getCursor() const;
virtual const std::optional<QCursor>& getCursor() const override;
virtual QString getTooltip() const override { return QString(); }
virtual int getInputPriority() const override { return ToolPriority; }
signals:
/// This is signal is set, when we want to display information message

View File

@ -266,7 +266,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_annotationManager = new pdf::PDFWidgetAnnotationManager(m_pdfWidget->getDrawWidgetProxy(), this);
connect(m_annotationManager, &pdf::PDFWidgetAnnotationManager::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered);
m_pdfWidget->getDrawWidgetProxy()->setAnnotationManager(m_annotationManager);
m_pdfWidget->setAnnotationManager(m_annotationManager);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::drawSpaceChanged, this, &PDFViewerMainWindow::onDrawSpaceChanged);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::pageLayoutChanged, this, &PDFViewerMainWindow::onPageLayoutChanged);