Enable OpenGL drawing

This commit is contained in:
Jakub Melka
2019-09-01 18:26:52 +02:00
parent 69ba66ae04
commit 135fa6fc86
4 changed files with 166 additions and 64 deletions

View File

@ -373,7 +373,7 @@ void PDFDrawWidgetProxy::init(PDFWidget* widget)
connect(m_horizontalScrollbar, &QScrollBar::valueChanged, this, &PDFDrawWidgetProxy::onHorizontalScrollbarValueChanged); connect(m_horizontalScrollbar, &QScrollBar::valueChanged, this, &PDFDrawWidgetProxy::onHorizontalScrollbarValueChanged);
connect(m_verticalScrollbar, &QScrollBar::valueChanged, this, &PDFDrawWidgetProxy::onVerticalScrollbarValueChanged); connect(m_verticalScrollbar, &QScrollBar::valueChanged, this, &PDFDrawWidgetProxy::onVerticalScrollbarValueChanged);
connect(this, &PDFDrawWidgetProxy::drawSpaceChanged, m_widget, QOverload<void>::of(&PDFDrawWidget::update)); connect(this, &PDFDrawWidgetProxy::drawSpaceChanged, m_widget->getWidget(), QOverload<void>::of(&PDFDrawWidget::update));
// We must update the draw space - widget has been set // We must update the draw space - widget has been set
update(); update();
@ -391,9 +391,11 @@ void PDFDrawWidgetProxy::update()
Q_ASSERT(m_horizontalScrollbar); Q_ASSERT(m_horizontalScrollbar);
Q_ASSERT(m_verticalScrollbar); Q_ASSERT(m_verticalScrollbar);
QWidget* widget = m_widget->getWidget();
// First, we must calculate pixel per mm ratio to obtain DPMM (device pixel per mm), // First, we must calculate pixel per mm ratio to obtain DPMM (device pixel per mm),
// we also assume, that zoom is correctly set. // we also assume, that zoom is correctly set.
m_pixelPerMM = static_cast<PDFReal>(m_widget->width()) / static_cast<PDFReal>(m_widget->widthMM()); m_pixelPerMM = static_cast<PDFReal>(widget->width()) / static_cast<PDFReal>(widget->widthMM());
Q_ASSERT(m_zoom > 0.0); Q_ASSERT(m_zoom > 0.0);
Q_ASSERT(m_pixelPerMM > 0.0); Q_ASSERT(m_pixelPerMM > 0.0);
@ -438,7 +440,7 @@ void PDFDrawWidgetProxy::update()
} }
QSize blockSize = m_layout.blockRect.size(); QSize blockSize = m_layout.blockRect.size();
QSize widgetSize = m_widget->size(); QSize widgetSize = widget->size();
// Horizontal scrollbar // Horizontal scrollbar
const int horizontalDifference = blockSize.width() - widgetSize.width(); const int horizontalDifference = blockSize.width() - widgetSize.width();

View File

@ -33,7 +33,7 @@ class QScrollBar;
namespace pdf namespace pdf
{ {
class PDFWidget; class PDFWidget;
class PDFDrawWidget; class IDrawWidget;
/// This class controls draw space - page layout. Pages are divided into blocks /// This class controls draw space - page layout. Pages are divided into blocks
/// each block can contain one or multiple pages. Units are in milimeters. /// each block can contain one or multiple pages. Units are in milimeters.
@ -319,7 +319,7 @@ private:
PDFDrawSpaceController* m_controller; PDFDrawSpaceController* m_controller;
/// Controlled draw widget (proxy is for this widget) /// Controlled draw widget (proxy is for this widget)
PDFDrawWidget* m_widget; IDrawWidget* m_widget;
/// Vertical scrollbar /// Vertical scrollbar
QScrollBar* m_verticalScrollbar; QScrollBar* m_verticalScrollbar;

View File

@ -33,24 +33,24 @@ PDFWidget::PDFWidget(QWidget* parent) :
m_verticalScrollBar(nullptr), m_verticalScrollBar(nullptr),
m_proxy(nullptr) m_proxy(nullptr)
{ {
m_drawWidget = new PDFDrawWidget(this, this); m_drawWidget = new PDFOpenGLDrawWidget(this, this);
m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this); m_horizontalScrollBar = new QScrollBar(Qt::Horizontal, this);
m_verticalScrollBar = new QScrollBar(Qt::Vertical, this); m_verticalScrollBar = new QScrollBar(Qt::Vertical, this);
QGridLayout* layout = new QGridLayout(this); QGridLayout* layout = new QGridLayout(this);
layout->setSpacing(0); layout->setSpacing(0);
layout->addWidget(m_drawWidget, 0, 0); layout->addWidget(m_drawWidget->getWidget(), 0, 0);
layout->addWidget(m_horizontalScrollBar, 1, 0); layout->addWidget(m_horizontalScrollBar, 1, 0);
layout->addWidget(m_verticalScrollBar, 0, 1); layout->addWidget(m_verticalScrollBar, 0, 1);
layout->setMargin(0); layout->setMargin(0);
setLayout(layout); setLayout(layout);
setFocusProxy(m_drawWidget); setFocusProxy(m_drawWidget->getWidget());
m_proxy = new PDFDrawWidgetProxy(this); m_proxy = new PDFDrawWidgetProxy(this);
m_proxy->init(this); m_proxy->init(this);
connect(m_proxy, &PDFDrawWidgetProxy::renderingError, this, &PDFWidget::onRenderingError); connect(m_proxy, &PDFDrawWidgetProxy::renderingError, this, &PDFWidget::onRenderingError);
connect(m_proxy, &PDFDrawWidgetProxy::repaintNeeded, m_drawWidget, QOverload<>::of(&PDFDrawWidget::update)); connect(m_proxy, &PDFDrawWidgetProxy::repaintNeeded, m_drawWidget->getWidget(), QOverload<>::of(&QWidget::update));
} }
PDFWidget::~PDFWidget() PDFWidget::~PDFWidget()
@ -82,45 +82,51 @@ void PDFWidget::onRenderingError(PDFInteger pageIndex, const QList<PDFRenderErro
emit pageRenderingErrorsChanged(pageIndex, errors.size()); emit pageRenderingErrorsChanged(pageIndex, errors.size());
} }
PDFDrawWidget::PDFDrawWidget(PDFWidget* widget, QWidget* parent) : template<typename BaseWidget>
QWidget(parent), PDFDrawWidgetBase<BaseWidget>::PDFDrawWidgetBase(PDFWidget* widget, QWidget* parent) :
BaseWidget(parent),
m_widget(widget), m_widget(widget),
m_mouseOperation(MouseOperation::None) m_mouseOperation(MouseOperation::None)
{ {
setFocusPolicy(Qt::StrongFocus); this->setFocusPolicy(Qt::StrongFocus);
} }
PDFDrawWidget::~PDFDrawWidget() template<typename BaseWidget>
std::vector<PDFInteger> PDFDrawWidgetBase<BaseWidget>::getCurrentPages() const
{ {
return this->m_widget->getDrawWidgetProxy()->getPagesIntersectingRect(this->rect());
} }
std::vector<PDFInteger> PDFDrawWidget::getCurrentPages() const template<typename BaseWidget>
{ QSize PDFDrawWidgetBase<BaseWidget>::minimumSizeHint() const
return m_widget->getDrawWidgetProxy()->getPagesIntersectingRect(this->rect());
}
QSize PDFDrawWidget::minimumSizeHint() const
{ {
return QSize(200, 200); return QSize(200, 200);
} }
void PDFDrawWidget::paintEvent(QPaintEvent* event) template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::performMouseOperation(QPoint currentMousePosition)
{ {
Q_UNUSED(event); switch (m_mouseOperation)
{
case MouseOperation::None:
// No operation performed
break;
QPainter painter(this); case MouseOperation::Translate:
m_widget->getDrawWidgetProxy()->draw(&painter, this->rect()); {
QPoint difference = currentMousePosition - m_lastMousePosition;
m_widget->getDrawWidgetProxy()->scrollByPixels(difference);
m_lastMousePosition = currentMousePosition;
break;
}
default:
Q_ASSERT(false);
}
} }
void PDFDrawWidget::resizeEvent(QResizeEvent* event) template<typename BaseWidget>
{ void PDFDrawWidgetBase<BaseWidget>::keyPressEvent(QKeyEvent* event)
QWidget::resizeEvent(event);
m_widget->getDrawWidgetProxy()->update();
}
void PDFDrawWidget::keyPressEvent(QKeyEvent* event)
{ {
QScrollBar* verticalScrollbar = m_widget->getVerticalScrollbar(); QScrollBar* verticalScrollbar = m_widget->getVerticalScrollbar();
@ -149,7 +155,8 @@ void PDFDrawWidget::keyPressEvent(QKeyEvent* event)
event->accept(); event->accept();
} }
void PDFDrawWidget::mousePressEvent(QMouseEvent* event) template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::mousePressEvent(QMouseEvent* event)
{ {
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
{ {
@ -161,7 +168,8 @@ void PDFDrawWidget::mousePressEvent(QMouseEvent* event)
event->accept(); event->accept();
} }
void PDFDrawWidget::mouseReleaseEvent(QMouseEvent* event) template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::mouseReleaseEvent(QMouseEvent* event)
{ {
performMouseOperation(event->pos()); performMouseOperation(event->pos());
@ -184,13 +192,15 @@ void PDFDrawWidget::mouseReleaseEvent(QMouseEvent* event)
event->accept(); event->accept();
} }
void PDFDrawWidget::mouseMoveEvent(QMouseEvent* event) template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::mouseMoveEvent(QMouseEvent* event)
{ {
performMouseOperation(event->pos()); performMouseOperation(event->pos());
event->accept(); event->accept();
} }
void PDFDrawWidget::wheelEvent(QWheelEvent* event) template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::wheelEvent(QWheelEvent* event)
{ {
Qt::KeyboardModifiers keyboardModifiers = QApplication::keyboardModifiers(); Qt::KeyboardModifiers keyboardModifiers = QApplication::keyboardModifiers();
@ -256,25 +266,67 @@ void PDFDrawWidget::wheelEvent(QWheelEvent* event)
event->accept(); event->accept();
} }
void PDFDrawWidget::performMouseOperation(QPoint currentMousePosition) PDFOpenGLDrawWidget::PDFOpenGLDrawWidget(PDFWidget* widget, QWidget* parent) :
BaseClass(widget, parent)
{ {
switch (m_mouseOperation) QSurfaceFormat format = this->format();
{ format.setProfile(QSurfaceFormat::CoreProfile);
case MouseOperation::None: format.setSamples(16);
// No operation performed format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
break; format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
setFormat(format);
case MouseOperation::Translate:
{
QPoint difference = currentMousePosition - m_lastMousePosition;
m_widget->getDrawWidgetProxy()->scrollByPixels(difference);
m_lastMousePosition = currentMousePosition;
break;
}
default:
Q_ASSERT(false);
}
} }
PDFOpenGLDrawWidget::~PDFOpenGLDrawWidget()
{
}
void PDFOpenGLDrawWidget::resizeGL(int w, int h)
{
QOpenGLWidget::resizeGL(w, h);
getPDFWidget()->getDrawWidgetProxy()->update();
}
void PDFOpenGLDrawWidget::initializeGL()
{
QOpenGLWidget::initializeGL();
}
void PDFOpenGLDrawWidget::paintGL()
{
QPainter painter(this);
getPDFWidget()->getDrawWidgetProxy()->draw(&painter, this->rect());
}
PDFDrawWidget::PDFDrawWidget(PDFWidget* widget, QWidget* parent) :
BaseClass(widget, parent)
{
}
PDFDrawWidget::~PDFDrawWidget()
{
}
void PDFDrawWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
getPDFWidget()->getDrawWidgetProxy()->draw(&painter, this->rect());
}
void PDFDrawWidget::resizeEvent(QResizeEvent* event)
{
BaseClass::resizeEvent(event);
getPDFWidget()->getDrawWidgetProxy()->update();
}
template class PDFDrawWidgetBase<QOpenGLWidget>;
template class PDFDrawWidgetBase<QWidget>;
} // namespace pdf } // namespace pdf

View File

@ -24,6 +24,7 @@
#include <QWidget> #include <QWidget>
#include <QScrollBar> #include <QScrollBar>
#include <QOpenGLWidget>
namespace pdf namespace pdf
{ {
@ -31,6 +32,17 @@ class PDFDocument;
class PDFDrawWidget; class PDFDrawWidget;
class PDFDrawWidgetProxy; class PDFDrawWidgetProxy;
class IDrawWidget
{
public:
virtual ~IDrawWidget() = default;
virtual QWidget* getWidget() = 0;
/// Returns page indices, which are currently displayed in the widget
virtual std::vector<PDFInteger> getCurrentPages() const = 0;
};
class PDFFORQTLIBSHARED_EXPORT PDFWidget : public QWidget class PDFFORQTLIBSHARED_EXPORT PDFWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -48,7 +60,7 @@ public:
/// \param optionalContentActivity Optional content activity /// \param optionalContentActivity Optional content activity
void setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity); void setDocument(const PDFDocument* document, const PDFOptionalContentActivity* optionalContentActivity);
PDFDrawWidget* getDrawWidget() const { return m_drawWidget; } IDrawWidget* getDrawWidget() const { return m_drawWidget; }
QScrollBar* getHorizontalScrollbar() const { return m_horizontalScrollBar; } QScrollBar* getHorizontalScrollbar() const { return m_horizontalScrollBar; }
QScrollBar* getVerticalScrollbar() const { return m_verticalScrollBar; } QScrollBar* getVerticalScrollbar() const { return m_verticalScrollBar; }
PDFDrawWidgetProxy* getDrawWidgetProxy() const { return m_proxy; } PDFDrawWidgetProxy* getDrawWidgetProxy() const { return m_proxy; }
@ -61,35 +73,35 @@ signals:
private: private:
void onRenderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors); void onRenderingError(PDFInteger pageIndex, const QList<PDFRenderError>& errors);
PDFDrawWidget* m_drawWidget; IDrawWidget* m_drawWidget;
QScrollBar* m_horizontalScrollBar; QScrollBar* m_horizontalScrollBar;
QScrollBar* m_verticalScrollBar; QScrollBar* m_verticalScrollBar;
PDFDrawWidgetProxy* m_proxy; PDFDrawWidgetProxy* m_proxy;
PageRenderingErrors m_pageRenderingErrors; PageRenderingErrors m_pageRenderingErrors;
}; };
class PDFFORQTLIBSHARED_EXPORT PDFDrawWidget : public QWidget template<typename BaseWidget>
class PDFDrawWidgetBase : public BaseWidget, public IDrawWidget
{ {
Q_OBJECT
public: public:
explicit PDFDrawWidget(PDFWidget* widget, QWidget* parent); explicit PDFDrawWidgetBase(PDFWidget* widget, QWidget* parent);
virtual ~PDFDrawWidget() override; virtual ~PDFDrawWidgetBase() override = default;
/// Returns page indices, which are currently displayed in the widget /// Returns page indices, which are currently displayed in the widget
std::vector<PDFInteger> getCurrentPages() const; virtual std::vector<PDFInteger> getCurrentPages() const override;
virtual QSize minimumSizeHint() const override; virtual QSize minimumSizeHint() const override;
virtual QWidget* getWidget() override { return this; }
protected: protected:
virtual void paintEvent(QPaintEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void keyPressEvent(QKeyEvent* event) override; virtual void keyPressEvent(QKeyEvent* event) override;
virtual void mousePressEvent(QMouseEvent* event) override; virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override; virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override; virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void wheelEvent(QWheelEvent* event) override; virtual void wheelEvent(QWheelEvent* event) override;
PDFWidget* getPDFWidget() const { return m_widget; }
private: private:
enum class MouseOperation enum class MouseOperation
{ {
@ -106,6 +118,42 @@ private:
MouseOperation m_mouseOperation; MouseOperation m_mouseOperation;
}; };
class PDFOpenGLDrawWidget : public PDFDrawWidgetBase<QOpenGLWidget>
{
Q_OBJECT
private:
using BaseClass = PDFDrawWidgetBase<QOpenGLWidget>;
public:
explicit PDFOpenGLDrawWidget(PDFWidget* widget, QWidget* parent);
virtual ~PDFOpenGLDrawWidget() override;
protected:
virtual void resizeGL(int w, int h) override;
virtual void initializeGL() override;
virtual void paintGL() override;
};
class PDFDrawWidget : public PDFDrawWidgetBase<QWidget>
{
Q_OBJECT
private:
using BaseClass = PDFDrawWidgetBase<QWidget>;
public:
explicit PDFDrawWidget(PDFWidget* widget, QWidget* parent);
virtual ~PDFDrawWidget() override;
protected:
virtual void paintEvent(QPaintEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
};
extern template class PDFDrawWidgetBase<QOpenGLWidget>;
extern template class PDFDrawWidgetBase<QWidget>;
} // namespace pdf } // namespace pdf
#endif // PDFDRAWWIDGET_H #endif // PDFDRAWWIDGET_H