diff options
author | ZackaryWelch <welch.zackary@gmail.com> | 2017-12-26 18:20:40 -0500 |
---|---|---|
committer | ZackaryWelch <welch.zackary@gmail.com> | 2017-12-26 18:20:40 -0500 |
commit | a32c6a9fd54fd400db0b729e826bc9a06297a3d7 (patch) | |
tree | a2fed348100dd0b36761f86cb020219091085bad | |
parent | Made improvements to focus setting and the find widget in lumina-pdf (diff) | |
download | lumina-a32c6a9fd54fd400db0b729e826bc9a06297a3d7.tar.gz lumina-a32c6a9fd54fd400db0b729e826bc9a06297a3d7.tar.bz2 lumina-a32c6a9fd54fd400db0b729e826bc9a06297a3d7.zip |
Began creating custom QPrintPreviewWidget for lumina-pdf
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h | 34 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp | 352 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/PrintWidget.h | 114 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro | 5 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/mainUI.cpp | 6 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-pdf/mainUI.h | 3 |
6 files changed, 474 insertions, 40 deletions
diff --git a/src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h b/src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h deleted file mode 100644 index ac457a10..00000000 --- a/src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h +++ /dev/null @@ -1,34 +0,0 @@ -//=========================================== -// Lumina Desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// Simple subclass of QPrintPreviewWidget to provide -// notification when a context menu is requested -//=========================================== -#ifndef _CONTEXT_MENU_PRINT_PREVIEW_WIDGET_H -#define _CONTEXT_MENU_PRINT_PREVIEW_WIDGET_H - -#include <QPrintPreviewWidget> -#include <QMouseEvent> -#include <QDebug> - -class CM_PrintPreviewWidget : public QPrintPreviewWidget{ - Q_OBJECT -signals: - void customContextMenuRequested(const QPoint&); - -public: - CM_PrintPreviewWidget(QPrinter * printer = 0, QWidget *parent = 0) : QPrintPreviewWidget(printer, parent){ - this->setMouseTracking(true); - QList<QWidget*> children = this->findChildren<QWidget*>("",Qt::FindChildrenRecursively); - for(int i=0; i<children.length(); i++){ - children[i]->setContextMenuPolicy(Qt::CustomContextMenu); - connect(children[i], SIGNAL(customContextMenuRequested(const QPoint&)), this, SIGNAL(customContextMenuRequested(const QPoint&)) ); - } - } - -}; - -#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp new file mode 100644 index 00000000..3fa87367 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp @@ -0,0 +1,352 @@ +#include "PrintWidget.h" + +class PageItem : public QGraphicsItem +{ +public: + PageItem(int _pageNum, const QPicture* _pagePicture, QSize _paperSize, QRect _pageRect) + : pageNum(_pageNum), pagePicture(_pagePicture), + paperSize(_paperSize), pageRect(_pageRect) + { + qreal border = qMax(paperSize.height(), paperSize.width()) / 25; + brect = QRectF(QPointF(-border, -border), + QSizeF(paperSize)+QSizeF(2*border, 2*border)); + setCacheMode(DeviceCoordinateCache); + } + + QRectF boundingRect() const Q_DECL_OVERRIDE + { return brect; } + + inline int pageNumber() const + { return pageNum; } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) Q_DECL_OVERRIDE; + +private: + int pageNum; + const QPicture* pagePicture; + QSize paperSize; + QRect pageRect; + QRectF brect; +}; + +void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + + QRectF paperRect(0,0, paperSize.width(), paperSize.height()); + + // Draw shadow + painter->setClipRect(option->exposedRect); + qreal shWidth = paperRect.width()/100; + QRectF rshadow(paperRect.topRight() + QPointF(0, shWidth), + paperRect.bottomRight() + QPointF(shWidth, 0)); + QLinearGradient rgrad(rshadow.topLeft(), rshadow.topRight()); + rgrad.setColorAt(0.0, QColor(0,0,0,255)); + rgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(rshadow, QBrush(rgrad)); + QRectF bshadow(paperRect.bottomLeft() + QPointF(shWidth, 0), + paperRect.bottomRight() + QPointF(0, shWidth)); + QLinearGradient bgrad(bshadow.topLeft(), bshadow.bottomLeft()); + bgrad.setColorAt(0.0, QColor(0,0,0,255)); + bgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(bshadow, QBrush(bgrad)); + QRectF cshadow(paperRect.bottomRight(), + paperRect.bottomRight() + QPointF(shWidth, shWidth)); + QRadialGradient cgrad(cshadow.topLeft(), shWidth, cshadow.topLeft()); + cgrad.setColorAt(0.0, QColor(0,0,0,255)); + cgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(cshadow, QBrush(cgrad)); + + painter->setClipRect(paperRect & option->exposedRect); + painter->fillRect(paperRect, Qt::white); + if (!pagePicture) + return; + painter->drawPicture(pageRect.topLeft(), *pagePicture); + + // Effect: make anything drawn in the margins look washed out. + QPainterPath path; + path.addRect(paperRect); + path.addRect(pageRect); + painter->setPen(QPen(Qt::NoPen)); + painter->setBrush(QColor(255, 255, 255, 180)); + painter->drawPath(path); +} +PrintWidget::PrintWidget(QPrinter *printer, QWidget *parent) : QWidget(parent), scene(0), curPage(1), viewMode(SinglePageView), zoomMode(FitInView), zoomFactor(1), initialized(false), fitting(true) { + this->printer = printer; + this->setMouseTracking(true); + QList<QWidget*> children = this->findChildren<QWidget*>("",Qt::FindChildrenRecursively); + for(int i=0; i<children.length(); i++){ + children[i]->setContextMenuPolicy(Qt::CustomContextMenu); + connect(children[i], SIGNAL(customContextMenuRequested(const QPoint&)), this, SIGNAL(customContextMenuRequested(const QPoint&)) ); + } + graphicsView = new GraphicsView; + graphicsView->setInteractive(false); + graphicsView->setDragMode(QGraphicsView::ScrollHandDrag); + graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + QObject::connect(graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), + this, SLOT(updateCurrentPage())); + QObject::connect(graphicsView, SIGNAL(resized()), this, SLOT(fit())); + + scene = new QGraphicsScene(graphicsView); + scene->setBackgroundBrush(Qt::gray); + graphicsView->setScene(scene); + + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(graphicsView); +} + +PrintWidget::~PrintWidget() { + //Nothing here for now +} + +//Public Slots + +void PrintWidget::fitInView() { + setZoomMode(FitToWidth); +} + +void PrintWidget::fitToWidget() { + setZoomMode(FitInView); +} + +void PrintWidget::setZoomMode(ZoomMode mode) { + zoomMode = mode; + fitting = true; + fit(true); +} + +void PrintWidget::setAllPagesViewMode() { + setViewMode(AllPagesView); +} + +void PrintWidget::setSinglePageViewMode() { + setViewMode(SinglePageView); +} + +void PrintWidget::setFacingPagesViewMode() { + setViewMode(FacingPagesView); +} + +void PrintWidget::setViewMode(ViewMode mode) { + viewMode = mode; + layoutPages(); + if (viewMode == AllPagesView) { + graphicsView->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio); + fitting = false; + zoomMode = CustomZoom; + zoomFactor = graphicsView->transform().m11() * (double(printer->logicalDpiY()) / logicalDpiY()); + emit previewChanged(); + } else { + fitting = true; + fit(); + } +} + +void PrintWidget::zoomIn(double factor) { + fitting = false; + zoomMode = CustomZoom; + zoomFactor *= factor; + graphicsView->scale(factor, factor); +} + +void PrintWidget::zoomOut(double factor) { + fitting = false; + zoomMode = CustomZoom; + zoomFactor *= factor; + graphicsView->scale(1/factor, 1/factor); +} + +void PrintWidget::updatePreview() { + initialized = true; + generatePreview(); + graphicsView->updateGeometry(); +} + +void PrintWidget::setOrientation(QPrinter::Orientation orientation) { + printer->setOrientation(orientation); + generatePreview(); +} + +void PrintWidget::setVisible(bool visible) { + if(visible and !initialized) + updatePreview(); + QWidget::setVisible(visible); +} + +void PrintWidget::setCurrentPage(int pageNumber) { + if(pageNumber < 1 || pageNumber > pages.count()) + return; + + int lastPage = curPage; + curPage = pageNumber; + + if (lastPage != curPage && lastPage > 0 && lastPage <= pages.count()) { + if (zoomMode != FitInView) { + QScrollBar *hsc = graphicsView->horizontalScrollBar(); + QScrollBar *vsc = graphicsView->verticalScrollBar(); + QPointF pt = graphicsView->transform().map(pages.at(curPage-1)->pos()); + vsc->setValue(int(pt.y()) - 10); + hsc->setValue(int(pt.x()) - 10); + } else { + graphicsView->centerOn(pages.at(curPage-1)); + } + } +} + +//Private functions + +void PrintWidget::generatePreview() { + //printer->d_func()->setPreviewMode(true); + emit paintRequested(printer); + //printer->d_func()->setPreviewMode(false); + //pictures = printer->previewPages(); + populateScene(); // i.e. setPreviewPrintedPictures() e.l. + layoutPages(); + curPage = qBound(1, curPage, pages.count()); + if (fitting) + fit(); + emit previewChanged(); +} + +void PrintWidget::layoutPages() { + int numPages = pages.count(); + if (numPages < 1) + return; + + int numPagePlaces = numPages; + int cols = 1; // singleMode and default + if (viewMode == AllPagesView) { + if (printer->orientation() == QPrinter::Portrait) + cols = qCeil(qSqrt(numPages)); + else + cols = qFloor(qSqrt(numPages)); + cols += cols % 2; // Nicer with an even number of cols + } + else if (viewMode == FacingPagesView) { + cols = 2; + numPagePlaces += 1; + } + int rows = qCeil(double(numPagePlaces) / cols); + + double itemWidth = pages.at(0)->boundingRect().width(); + double itemHeight = pages.at(0)->boundingRect().height(); + int pageNum = 1; + for (int i = 0; i < rows && pageNum <= numPages; i++) { + for (int j = 0; j < cols && pageNum <= numPages; j++) { + if (!i && !j && viewMode == FacingPagesView) { + continue; + } else { + pages.at(pageNum-1)->setPos(QPointF(j*itemWidth, i*itemHeight)); + pageNum++; + } + } + } + scene->setSceneRect(scene->itemsBoundingRect()); +} + +void PrintWidget::populateScene() +{ + for (int i = 0; i < pages.size(); i++) + scene->removeItem(pages.at(i)); + qDeleteAll(pages); + pages.clear(); + + int numPages = pictures.count(); + QSize paperSize = printer->pageLayout().fullRectPixels(printer->resolution()).size(); + QRect pageRect = printer->pageLayout().paintRectPixels(printer->resolution()); + + for (int i = 0; i < numPages; i++) { + PageItem* item = new PageItem(i+1, pictures.at(i), paperSize, pageRect); + scene->addItem(item); + pages.append(item); + } +} + + +//Private Slots +void PrintWidget::updateCurrentPage() { + if (viewMode == AllPagesView) + return; + + int newPage = calcCurrentPage(); + if (newPage != curPage) { + curPage = newPage; + emit previewChanged(); + } +} + +int PrintWidget::calcCurrentPage() { + int maxArea = 0; + int newPage = curPage; + QRect viewRect = graphicsView->viewport()->rect(); + QList<QGraphicsItem*> items = graphicsView->items(viewRect); + for (int i=0; i<items.size(); ++i) { + PageItem* pg = static_cast<PageItem*>(items.at(i)); + QRect overlap = graphicsView->mapFromScene(pg->sceneBoundingRect()).boundingRect() & viewRect; + int area = overlap.width() * overlap.height(); + if (area > maxArea) { + maxArea = area; + newPage = pg->pageNumber(); + } else if (area == maxArea && pg->pageNumber() < newPage) { + newPage = pg->pageNumber(); + } + } + return newPage; +} + +void PrintWidget::fit(bool doFitting) { + if (curPage < 1 || curPage > pages.count()) + return; + if (!doFitting && !fitting) + return; + + if (doFitting && fitting) { + QRect viewRect = graphicsView->viewport()->rect(); + if (zoomMode == FitInView) { + QList<QGraphicsItem*> containedItems = graphicsView->items(viewRect, Qt::ContainsItemBoundingRect); + foreach(QGraphicsItem* item, containedItems) { + PageItem* pg = static_cast<PageItem*>(item); + if (pg->pageNumber() == curPage) + return; + } + } + + int newPage = calcCurrentPage(); + if (newPage != curPage) + curPage = newPage; + } + + QRectF target = pages.at(curPage-1)->sceneBoundingRect(); + if (viewMode == FacingPagesView) { + if (curPage % 2) + target.setLeft(target.left() - target.width()); + else + target.setRight(target.right() + target.width()); + } else if (viewMode == AllPagesView) { + target = scene->itemsBoundingRect(); + } + + if (zoomMode == FitToWidth) { + QTransform t; + qreal scale = graphicsView->viewport()->width() / target.width(); + t.scale(scale, scale); + graphicsView->setTransform(t); + if (doFitting && fitting) { + QRectF viewSceneRect = graphicsView->viewportTransform().mapRect(graphicsView->viewport()->rect()); + viewSceneRect.moveTop(target.top()); + graphicsView->ensureVisible(viewSceneRect); // Nah... + } + } else { + graphicsView->fitInView(target, Qt::KeepAspectRatio); + if (zoomMode == FitInView) { + int step = qRound(graphicsView->matrix().mapRect(target).height()); + graphicsView->verticalScrollBar()->setSingleStep(step); + graphicsView->verticalScrollBar()->setPageStep(step); + } + } + + zoomFactor = graphicsView->transform().m11() * (float(printer->logicalDpiY()) / this->logicalDpiY()); + emit previewChanged(); +} diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h new file mode 100644 index 00000000..061aef49 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h @@ -0,0 +1,114 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// Simple subclass of QPrintPreviewWidget to provide +// notification when a context menu is requested +//=========================================== +#ifndef _PRINT_PREVIEW_WIDGET_H +#define _PRINT_PREVIEW_WIDGET_H + +#include <QMouseEvent> +#include <QDebug> +#include <QGraphicsView> +#include <QGraphicsItem> +#include <QBoxLayout> +#include <QScrollBar> +#include <QStyleOptionGraphicsItem> +#include <QtMath> +#include <QPrinter> + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(QWidget *parent = 0) : QGraphicsView(parent) { } +signals: + void resized(); +protected: + void resizeEvent(QResizeEvent* e) Q_DECL_OVERRIDE { + /*{ + const QSignalBlocker blocker(verticalScrollBar()); // Don't change page, QTBUG-14517 + QGraphicsView::resizeEvent(e); + }*/ + QGraphicsView::resizeEvent(e); + emit resized(); + } + + void showEvent(QShowEvent* e) Q_DECL_OVERRIDE { + QGraphicsView::showEvent(e); + emit resized(); + } +}; + +class PrintWidget: public QWidget{ + Q_OBJECT +public: + enum ViewMode { + SinglePageView, + FacingPagesView, + AllPagesView + }; + + enum ZoomMode { + CustomZoom, + FitToWidth, + FitInView + }; + + PrintWidget(QPrinter *printer = 0, QWidget *parent = 0); + ~PrintWidget(); + + int currentPage() const { return curPage; }; + double getZoomFactor() const { return this->zoomFactor; }; + QPrinter::Orientation orientation() const { return printer->orientation(); }; + ZoomMode getZoomMode() const { return this->zoomMode; }; + void setVisible(bool); + +public slots: + void zoomIn(double factor=1.2); + void zoomOut(double factor=1.2); + void setOrientation(QPrinter::Orientation); + void setCurrentPage(int); + + void fitInView(); + void fitToWidget(); + void setAllPagesViewMode(); + void setSinglePageViewMode(); + void setFacingPagesViewMode(); + + void updatePreview(); + +private slots: + void updateCurrentPage(); + int calcCurrentPage(); + void fit(bool doFitting=false); + +signals: + void customContextMenuRequested(const QPoint&); + void paintRequested(QPrinter*); + void previewChanged(); + +private: + void generatePreview(); + void layoutPages(); + void populateScene(); + void setViewMode(ViewMode viewMode); + void setZoomMode(ZoomMode viewMode); + + QPrinter *printer; + GraphicsView *graphicsView; + QGraphicsScene *scene; + int curPage; + QList<const QPicture *> pictures; + QList<QGraphicsItem *> pages; + + ViewMode viewMode; + ZoomMode zoomMode; + double zoomFactor; + bool initialized, fitting; +}; + +#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro index 3a031067..8ee67d06 100644 --- a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro +++ b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro @@ -19,10 +19,11 @@ message("Qt Modules Needed: $${QT}") SOURCES += main.cpp \ mainUI.cpp \ - propDialog.cpp + propDialog.cpp \ + PrintWidget.cpp HEADERS += mainUI.h \ - CM_PrintPreviewWidget.h \ + PrintWidget.h \ PresentationLabel.h \ PropDialog.h diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp index c5de3015..6c5b762c 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp @@ -21,7 +21,7 @@ #include <QtConcurrent> #include <LuminaXDG.h> -#include "CM_PrintPreviewWidget.h" +#include "PrintWidget.h" MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ ui->setupUi(this); @@ -33,7 +33,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ lastdir = QDir::homePath(); Printer = new QPrinter(); //Create the interface widgets - WIDGET = new CM_PrintPreviewWidget(Printer,this); + WIDGET = new PrintWidget(Printer,this); clockTimer = new QTimer(this); clockTimer->setInterval(1000); //1-second updates to clock connect(clockTimer, SIGNAL(timeout()), this, SLOT(updateClock()) ); @@ -53,7 +53,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(newFocus(QWidget*, QWidget*))); connect(WIDGET, SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(showContextMenu(const QPoint&)) ); - connect(WIDGET, &QPrintPreviewWidget::paintRequested, this, + connect(WIDGET, &PrintWidget::paintRequested, this, [=](QPrinter *printer) { this->paintOnWidget(printer, this->highlight); }); DOC = 0; connect(this, SIGNAL(PageLoaded(int)), this, SLOT(slotPageLoaded(int)) ); diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.h b/src-qt5/desktop-utils/lumina-pdf/mainUI.h index 60a1beb9..cce04cd4 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.h +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.h @@ -22,6 +22,7 @@ #include <poppler/qt5/poppler-qt5.h> #include "PresentationLabel.h" #include "propDialog.h" +#include "PrintWidget.h" namespace Ui{ class MainUI; @@ -37,7 +38,7 @@ public: private: Poppler::Document *DOC; - QPrintPreviewWidget *WIDGET; + PrintWidget *WIDGET; Ui::MainUI *ui; PropDialog *PROPDIALOG; QPrinter* Printer; |