#include "continuous_page_widget.h" #include "continuous_view_model.h" #include "render.h" #include #include ContinuousPageWidget::ContinuousPageWidget(QWidget *parent) : QWidget(parent) { QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred); sp.setHeightForWidth(true); setSizePolicy(sp); setMouseTracking(true); initTheme(this); } void ContinuousPageWidget::applyTheme(const Theme &) { update(); } void ContinuousPageWidget::setRender(Render *r) { render = r; } void ContinuousPageWidget::setViewModel(ContinuousViewModel *viewModel) { if (continuousViewModel == viewModel) { return; } if (continuousViewModel) { disconnect(continuousViewModel, &ContinuousViewModel::stateChanged, this, QOverload<>::of(&ContinuousPageWidget::update)); } continuousViewModel = viewModel; if (continuousViewModel) { connect(continuousViewModel, &ContinuousViewModel::stateChanged, this, QOverload<>::of(&ContinuousPageWidget::update)); } updateGeometry(); update(); } void ContinuousPageWidget::reset() { setMinimumHeight(0); setMaximumHeight(QWIDGETSIZE_MAX); updateGeometry(); update(); } bool ContinuousPageWidget::hasHeightForWidth() const { return true; } int ContinuousPageWidget::heightForWidth(int w) const { if (!continuousViewModel || w <= 0) { return 0; } Q_UNUSED(w) return continuousViewModel->totalHeight(); } QSize ContinuousPageWidget::sizeHint() const { if (!continuousViewModel) { return QSize(800, 0); } return QSize(width(), continuousViewModel->totalHeight()); } void ContinuousPageWidget::onPageAvailable(int absolutePageIndex) { if (!render || !continuousViewModel || absolutePageIndex < 0 || absolutePageIndex >= continuousViewModel->numPages()) { return; } const QImage *img = render->bufferedImage(absolutePageIndex); if (!img || img->isNull()) { return; } // repaint the region where this page lives if (absolutePageIndex < continuousViewModel->numPages()) { QSize scaled = continuousViewModel->scaledPageSize(absolutePageIndex); const int y = continuousViewModel->yPositionForPage(absolutePageIndex); int x = (width() - scaled.width()) / 2; if (x < 0) { x = 0; } QRect pageRect(x, y, scaled.width(), scaled.height()); update(pageRect); } } void ContinuousPageWidget::paintEvent(QPaintEvent *event) { if (!continuousViewModel || continuousViewModel->numPages() == 0 || !render) { return; } QPainter painter(this); QRect visibleRect = event->rect(); int firstPage = continuousViewModel->pageAtY(visibleRect.top()); int lastPage = continuousViewModel->pageAtY(visibleRect.bottom()); int w = width(); for (int i = firstPage; i <= lastPage && i < continuousViewModel->numPages(); ++i) { int y = continuousViewModel->yPositionForPage(i); QSize scaled = continuousViewModel->scaledPageSize(i); // center horizontally if page is narrower than widget int x = (w - scaled.width()) / 2; if (x < 0) { x = 0; } QRect pageRect(x, y, scaled.width(), scaled.height()); const QImage *img = render->bufferedImage(i); if (img && !img->isNull()) { if (img->size() != scaled) { painter.drawImage(pageRect, img->scaled(scaled, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } else { painter.drawImage(pageRect, *img); } } else { // placeholder painter.fillRect(pageRect, QColor(45, 45, 45)); painter.setPen(theme.viewer.defaultTextColor); painter.drawText(pageRect, Qt::AlignCenter, tr("Loading page %1").arg(i + 1)); } } } void ContinuousPageWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); if (continuousViewModel) { continuousViewModel->setViewportSize(width(), continuousViewModel->viewportHeight()); } }