Help/litehtml: Support scaling

Scale the paint area for the HTML document

Change-Id: I75aa5f2bf057df7b2b160b2a005172ff88dbb2b7
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Eike Ziller
2019-09-17 12:33:01 +02:00
parent 93ed44bfea
commit 12ea33446d
4 changed files with 93 additions and 24 deletions

View File

@@ -65,6 +65,7 @@ LiteHtmlHelpViewer::LiteHtmlHelpViewer(QWidget *parent)
, m_viewer(new QLiteHtmlWidget) , m_viewer(new QLiteHtmlWidget)
{ {
m_viewer->setResourceHandler([](const QUrl &url) { return getData(url); }); m_viewer->setResourceHandler([](const QUrl &url) { return getData(url); });
m_viewer->viewport()->installEventFilter(this);
connect(m_viewer, &QLiteHtmlWidget::linkClicked, this, &LiteHtmlHelpViewer::setSource); connect(m_viewer, &QLiteHtmlWidget::linkClicked, this, &LiteHtmlHelpViewer::setSource);
connect(m_viewer, connect(m_viewer,
&QLiteHtmlWidget::contextMenuRequested, &QLiteHtmlWidget::contextMenuRequested,
@@ -99,28 +100,28 @@ void LiteHtmlHelpViewer::setViewerFont(const QFont &newFont)
void LiteHtmlHelpViewer::scaleUp() void LiteHtmlHelpViewer::scaleUp()
{ {
// TODO setScale(scale() * 1.1);
} }
void LiteHtmlHelpViewer::scaleDown() void LiteHtmlHelpViewer::scaleDown()
{ {
// TODO setScale(scale() * .9);
} }
void LiteHtmlHelpViewer::resetScale() void LiteHtmlHelpViewer::resetScale()
{ {
// TODO m_viewer->setZoomFactor(1);
} }
qreal LiteHtmlHelpViewer::scale() const qreal LiteHtmlHelpViewer::scale() const
{ {
// TODO return m_viewer->zoomFactor();
return 1;
} }
void LiteHtmlHelpViewer::setScale(qreal scale) void LiteHtmlHelpViewer::setScale(qreal scale)
{ {
// TODO // interpret 0 as "default"
m_viewer->setZoomFactor(scale == 0 ? qreal(1) : scale);
} }
QString LiteHtmlHelpViewer::title() const QString LiteHtmlHelpViewer::title() const
@@ -253,6 +254,16 @@ void LiteHtmlHelpViewer::print(QPrinter *printer)
// TODO // TODO
} }
bool LiteHtmlHelpViewer::eventFilter(QObject *src, QEvent *e)
{
if (isScrollWheelZoomingEnabled() && e->type() == QEvent::Wheel) {
auto we = static_cast<QWheelEvent *>(e);
if (we->modifiers() == Qt::ControlModifier)
return true;
}
return HelpViewer::eventFilter(src, e);
}
void LiteHtmlHelpViewer::setSourceInternal(const QUrl &url, Utils::optional<int> vscroll) void LiteHtmlHelpViewer::setSourceInternal(const QUrl &url, Utils::optional<int> vscroll)
{ {
slotLoadStarted(); slotLoadStarted();

View File

@@ -77,6 +77,8 @@ public:
void backward() override; void backward() override;
void print(QPrinter *printer) override; void print(QPrinter *printer) override;
bool eventFilter(QObject *src, QEvent *e) override;
private: private:
void goForward(int count); void goForward(int count);
void goBackward(int count); void goBackward(int count);

View File

@@ -373,6 +373,7 @@ public:
litehtml::context context; litehtml::context context;
QUrl url; QUrl url;
DocumentContainer documentContainer; DocumentContainer documentContainer;
qreal zoomFactor = 1;
}; };
QLiteHtmlWidget::QLiteHtmlWidget(QWidget *parent) QLiteHtmlWidget::QLiteHtmlWidget(QWidget *parent)
@@ -434,6 +435,18 @@ QString QLiteHtmlWidget::title() const
return d->documentContainer.caption(); return d->documentContainer.caption();
} }
void QLiteHtmlWidget::setZoomFactor(qreal scale)
{
Q_ASSERT(scale != 0);
d->zoomFactor = scale;
render();
}
qreal QLiteHtmlWidget::zoomFactor() const
{
return d->zoomFactor;
}
bool QLiteHtmlWidget::findText(const QString &text, bool QLiteHtmlWidget::findText(const QString &text,
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
bool incremental, bool incremental,
@@ -451,13 +464,14 @@ bool QLiteHtmlWidget::findText(const QString &text,
if (success && verticalScrollBar()->value() > newSelectionCombined.top()) { if (success && verticalScrollBar()->value() > newSelectionCombined.top()) {
verticalScrollBar()->setValue(newSelectionCombined.top()); verticalScrollBar()->setValue(newSelectionCombined.top());
} else if (success } else if (success
&& verticalScrollBar()->value() + viewport()->height() && verticalScrollBar()->value() + toVirtual(viewport()->size()).height()
< newSelectionCombined.bottom()) { < newSelectionCombined.bottom()) {
verticalScrollBar()->setValue(newSelectionCombined.bottom() - viewport()->height()); verticalScrollBar()->setValue(newSelectionCombined.bottom()
- toVirtual(viewport()->size()).height());
} else { } else {
viewport()->update(newSelectionCombined.translated(-scrollPosition())); viewport()->update(fromVirtual(newSelectionCombined.translated(-scrollPosition())));
for (const QRect &r : oldSelection) for (const QRect &r : oldSelection)
viewport()->update(r.translated(-scrollPosition())); viewport()->update(fromVirtual(r.translated(-scrollPosition())));
} }
return success; return success;
} }
@@ -510,9 +524,10 @@ void QLiteHtmlWidget::paintEvent(QPaintEvent *event)
return; return;
d->documentContainer.setScrollPosition(scrollPosition()); d->documentContainer.setScrollPosition(scrollPosition());
const QPoint pos = -scrollPosition(); const QPoint pos = -scrollPosition();
const QRect r = event->rect(); const QRect r = toVirtual(event->rect());
const litehtml::position clip = {r.x(), r.y(), r.width(), r.height()}; const litehtml::position clip = {r.x(), r.y(), r.width(), r.height()};
QPainter p(viewport()); QPainter p(viewport());
p.setWorldTransform(QTransform().scale(d->zoomFactor, d->zoomFactor));
d->documentContainer.document()->draw(reinterpret_cast<litehtml::uint_ptr>(&p), d->documentContainer.document()->draw(reinterpret_cast<litehtml::uint_ptr>(&p),
pos.x(), pos.x(),
pos.y(), pos.y(),
@@ -531,7 +546,7 @@ void QLiteHtmlWidget::mouseMoveEvent(QMouseEvent *event)
QPoint pos; QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos); htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : d->documentContainer.mouseMoveEvent(pos, viewportPos)) for (const QRect &r : d->documentContainer.mouseMoveEvent(pos, viewportPos))
viewport()->update(r.translated(-scrollPosition())); viewport()->update(fromVirtual(r.translated(-scrollPosition())));
} }
void QLiteHtmlWidget::mousePressEvent(QMouseEvent *event) void QLiteHtmlWidget::mousePressEvent(QMouseEvent *event)
@@ -540,7 +555,7 @@ void QLiteHtmlWidget::mousePressEvent(QMouseEvent *event)
QPoint pos; QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos); htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : d->documentContainer.mousePressEvent(pos, viewportPos, event->button())) for (const QRect &r : d->documentContainer.mousePressEvent(pos, viewportPos, event->button()))
viewport()->update(r.translated(-scrollPosition())); viewport()->update(fromVirtual(r.translated(-scrollPosition())));
} }
void QLiteHtmlWidget::mouseReleaseEvent(QMouseEvent *event) void QLiteHtmlWidget::mouseReleaseEvent(QMouseEvent *event)
@@ -549,7 +564,7 @@ void QLiteHtmlWidget::mouseReleaseEvent(QMouseEvent *event)
QPoint pos; QPoint pos;
htmlPos(event->pos(), &viewportPos, &pos); htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : d->documentContainer.mouseReleaseEvent(pos, viewportPos, event->button())) for (const QRect &r : d->documentContainer.mouseReleaseEvent(pos, viewportPos, event->button()))
viewport()->update(r.translated(-scrollPosition())); viewport()->update(fromVirtual(r.translated(-scrollPosition())));
} }
void QLiteHtmlWidget::mouseDoubleClickEvent(QMouseEvent *event) void QLiteHtmlWidget::mouseDoubleClickEvent(QMouseEvent *event)
@@ -559,7 +574,7 @@ void QLiteHtmlWidget::mouseDoubleClickEvent(QMouseEvent *event)
htmlPos(event->pos(), &viewportPos, &pos); htmlPos(event->pos(), &viewportPos, &pos);
for (const QRect &r : for (const QRect &r :
d->documentContainer.mouseDoubleClickEvent(pos, viewportPos, event->button())) { d->documentContainer.mouseDoubleClickEvent(pos, viewportPos, event->button())) {
viewport()->update(r.translated(-scrollPosition())); viewport()->update(fromVirtual(r.translated(-scrollPosition())));
} }
} }
@@ -567,7 +582,7 @@ void QLiteHtmlWidget::leaveEvent(QEvent *event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
for (const QRect &r : d->documentContainer.leaveEvent()) for (const QRect &r : d->documentContainer.leaveEvent())
viewport()->update(r.translated(-scrollPosition())); viewport()->update(fromVirtual(r.translated(-scrollPosition())));
} }
void QLiteHtmlWidget::contextMenuEvent(QContextMenuEvent *event) void QLiteHtmlWidget::contextMenuEvent(QContextMenuEvent *event)
@@ -582,17 +597,19 @@ void QLiteHtmlWidget::render()
{ {
if (!d->documentContainer.document()) if (!d->documentContainer.document())
return; return;
const int fullWidth = width() / d->zoomFactor;
const QSize vViewportSize = toVirtual(viewport()->size());
const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, this); const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, this);
const int w = width() - scrollbarWidth - 2; const int w = fullWidth - scrollbarWidth - 2;
d->documentContainer.render(w, viewport()->height()); d->documentContainer.render(w, vViewportSize.height());
horizontalScrollBar()->setPageStep(viewport()->width()); // scroll bars reflect virtual/scaled size of html document
horizontalScrollBar() horizontalScrollBar()->setPageStep(vViewportSize.width());
->setRange(0, std::max(0, d->documentContainer.document()->width() - viewport()->width())); horizontalScrollBar()->setRange(0, std::max(0, d->documentContainer.document()->width() - w));
verticalScrollBar()->setPageStep(viewport()->height()); verticalScrollBar()->setPageStep(vViewportSize.height());
verticalScrollBar()->setRange(0, verticalScrollBar()->setRange(0,
std::max(0, std::max(0,
d->documentContainer.document()->height() d->documentContainer.document()->height()
- viewport()->height())); - vViewportSize.height()));
viewport()->update(); viewport()->update();
} }
@@ -603,6 +620,36 @@ QPoint QLiteHtmlWidget::scrollPosition() const
void QLiteHtmlWidget::htmlPos(const QPoint &pos, QPoint *viewportPos, QPoint *htmlPos) const void QLiteHtmlWidget::htmlPos(const QPoint &pos, QPoint *viewportPos, QPoint *htmlPos) const
{ {
*viewportPos = viewport()->mapFromParent(pos); *viewportPos = toVirtual(viewport()->mapFromParent(pos));
*htmlPos = *viewportPos + scrollPosition(); *htmlPos = *viewportPos + scrollPosition();
} }
QPoint QLiteHtmlWidget::toVirtual(const QPoint &p) const
{
return {int(p.x() / d->zoomFactor), int(p.y() / d->zoomFactor)};
}
QPoint QLiteHtmlWidget::fromVirtual(const QPoint &p) const
{
return {int(p.x() * d->zoomFactor), int(p.y() * d->zoomFactor)};
}
QSize QLiteHtmlWidget::toVirtual(const QSize &s) const
{
return {int(s.width() / d->zoomFactor), int(s.height() / d->zoomFactor)};
}
QSize QLiteHtmlWidget::fromVirtual(const QSize &s) const
{
return {int(s.width() * d->zoomFactor + 0.5), int(s.height() * d->zoomFactor + 0.5)};
}
QRect QLiteHtmlWidget::toVirtual(const QRect &r) const
{
return {toVirtual(r.topLeft()), toVirtual(r.size())};
}
QRect QLiteHtmlWidget::fromVirtual(const QRect &r) const
{
return {fromVirtual(r.topLeft()), fromVirtual(r.size())};
}

View File

@@ -44,6 +44,9 @@ public:
void setHtml(const QString &content); void setHtml(const QString &content);
QString title() const; QString title() const;
void setZoomFactor(qreal scale);
qreal zoomFactor() const;
bool findText(const QString &text, bool findText(const QString &text,
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
bool incremental, bool incremental,
@@ -77,6 +80,12 @@ private:
void render(); void render();
QPoint scrollPosition() const; QPoint scrollPosition() const;
void htmlPos(const QPoint &pos, QPoint *viewportPos, QPoint *htmlPos) const; void htmlPos(const QPoint &pos, QPoint *viewportPos, QPoint *htmlPos) const;
QPoint toVirtual(const QPoint &p) const;
QPoint fromVirtual(const QPoint &p) const;
QSize toVirtual(const QSize &s) const;
QSize fromVirtual(const QSize &s) const;
QRect toVirtual(const QRect &r) const;
QRect fromVirtual(const QRect &r) const;
QLiteHtmlWidgetPrivate *d; QLiteHtmlWidgetPrivate *d;
}; };