DtkWidget
DTK Widget module
载入中...
搜索中...
未找到
dprintpreviewwidget_p.h
1// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5#ifndef DPRINTPREVIEWWIDGET_P_H
6#define DPRINTPREVIEWWIDGET_P_H
7
8#include <dprintpreviewwidget.h>
9#include "dframe_p.h"
10
11#include <DIconButton>
12
13#include <QGraphicsScene>
14#include <QGraphicsView>
15#include <QWheelEvent>
16#include <QPicture>
17#include <qmath.h>
18#include <QBasicTimer>
19
20DWIDGET_BEGIN_NAMESPACE
21
22#define PREVIEW_WIDGET_MARGIN_RATIO 50
23#define PREVIEW_ENLARGE_RATIO 1.25
24#define PREVIEW_NARROW_RATIO 0.8
25#define PREVIEW_SCALEBUTTON_MARGIN 10
26#define PREVIEW_WATER_COUNT_WIDTH 28
27#define PREVIEW_WATER_COUNT_HEIGHT 20
28#define PREVIEW_WATER_COUNT_SPACE 10
29#define NUMBERUP_SCALE_RATIO 1.05
30#define NUMBERUP_SPACE_SCALE_RATIO 0.05
31
32class GraphicsView : public QGraphicsView
33{
34 Q_OBJECT
35public:
36 GraphicsView(QWidget *parent = nullptr);
37
38public Q_SLOTS:
39 void resetScale(bool autoReset = true);
40
41Q_SIGNALS:
42 void resized();
43
44protected:
45 void mousePressEvent(QMouseEvent *e) override;
46 void mouseReleaseEvent(QMouseEvent *e) override;
47 void wheelEvent(QWheelEvent *e) override;
48 void resizeEvent(QResizeEvent *e) override;
49 void showEvent(QShowEvent *e) override;
50 void changeEvent(QEvent *e) override;
51
52private Q_SLOTS:
53 void onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType);
54
55private:
56 DIconButton *scaleResetButton;
57 double scaleRatio;
58};
59
60class ContentItem : public QGraphicsItem
61{
62public:
63 ContentItem(const QPicture *_pagePicture, QRect _pageRect, QGraphicsItem *parent = nullptr)
64 : QGraphicsItem(parent)
65 , pagePicture(_pagePicture)
66 , pageRect(_pageRect)
67 {
68 brect = QRectF(QPointF(0, 0), QSizeF(pageRect.size()));
69 setCacheMode(DeviceCoordinateCache);
70 setPos(pageRect.topLeft());
71 }
72
73 QRectF boundingRect() const override
74 {
75 return brect;
76 }
77
78 void setRect(const QRectF &rect)
79 {
80 setPos(rect.topLeft());
81 brect = QRectF(QPointF(0, 0), QSizeF(rect.size()));
82 }
83
84 void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
85 void updateGrayContent();
86 void drawNumberUpPictures(QPainter *painter);
87
88protected:
89 QPicture grayscalePaint(const QPicture &picture);
90 QImage imageGrayscale(const QImage *origin);
91
92private:
93 const QPicture *pagePicture;
94 QRect pageRect;
95 QRectF brect;
96 QPicture grayPicture;
97};
98
99class WaterMark : public QGraphicsItem
100{
101public:
102 enum Type {
103 None,
104 Text,
105 Image
106 };
107 enum Layout {
108 Center,
109 Tiled
110 };
111 WaterMark(QGraphicsItem *parent = nullptr)
112 : QGraphicsItem(parent)
113 , type(None)
114 , layout(Center)
115 {
116 }
117
118 inline void setType(Type t)
119 {
120 type = t;
121 }
122 inline Type getType() const
123 {
124 return type;
125 }
126 inline void setLayoutType(Layout l)
127 {
128 layout = l;
129 }
130 inline void setScaleFactor(qreal scale)
131 {
132 mScaleFactor = scale;
133 }
134 void setImage(const QImage &img);
135 inline void setText(const QString str)
136 {
137 type = Text;
138 text = str;
139 }
140 inline void setFont(const QFont &f)
141 {
142 font = f;
143 }
144 inline QFont getFont() const
145 {
146 return font;
147 }
148 inline void setColor(const QColor &c)
149 {
150 color = c;
151 }
152 inline QColor getColor() const
153 {
154 return color;
155 }
156 inline void setBoundingRect(const QRectF &rect)
157 {
158 qreal rotate = rotation();
159 setRotation(0);
160 brect = rect;
161 brectPolygon = mapToScene(brect);
162 qreal width = brect.width();
163 qreal height = brect.height();
164 // 取斜边为宽度的矩形 使旋转时始终保持页面在水印内部
165 qreal maxDis = qSqrt(qPow(width, 2) + qPow(height, 2));
166 twoPolygon = mapToScene(QRectF(QPointF(brect.center().x() - maxDis / 2, brect.center().y() - maxDis / 2), QSizeF(maxDis, maxDis)));
167 setTransformOriginPoint(brect.center());
168 setRotation(rotate);
169 }
170 QRectF boundingRect() const override
171 {
172 return mapToScene(brect.toRect()).boundingRect();
173 }
174 inline QPolygonF itemMaxPolygon() const
175 {
176 return twoPolygon;
177 }
178 void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
179 void updatePicture(QPainter *painter, bool isPreview);
180
181 void setNumberUpScale(const qreal &value);
182
183protected:
184 QPainterPath itemClipPath() const;
185
186private:
187 Type type;
188 Layout layout;
189 QImage sourceImage;
190 QImage graySourceImage;
191 QImage targetImage;
192 QRectF brect;
193 qreal mScaleFactor = 1.0;
194 QGraphicsTextItem textItem;
195 QString text;
196 QFont font;
197 QColor color;
198 qreal numberUpScale = 1;
199
200 QPolygonF brectPolygon;
201 QPolygonF twoPolygon;
202 friend class DPrintPreviewWidgetPrivate;
203};
204
205class PageItem : public QGraphicsItem
206{
207public:
208 PageItem(int _pageNum, const QPicture *_pagePicture, QSize _paperSize, QRect _pageRect)
209 : pageNum(_pageNum)
210 , pagePicture(_pagePicture)
211 , paperSize(_paperSize)
212 , pageRect(_pageRect)
213 , content(new ContentItem(_pagePicture, _pageRect, this))
214 {
215 qreal border = qMax(paperSize.height(), paperSize.width()) / PREVIEW_WIDGET_MARGIN_RATIO;
216 brect = QRectF(QPointF(-border, -border),
217 QSizeF(paperSize) + QSizeF(2 * border, 2 * border));
218 setCacheMode(DeviceCoordinateCache);
219 }
220
221 QRectF boundingRect() const override
222 {
223 return brect;
224 }
225
226 inline int pageNumber() const
227 {
228 return pageNum;
229 }
230
231 void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
232
233 void setVisible(bool isVisible);
234
235private:
236 int pageNum;
237 const QPicture *pagePicture;
238 QSize paperSize;
239 QRect pageRect;
240 QRectF brect;
241 ContentItem *content;
242};
243
244typedef QList<QPair<QByteArray, QByteArray>> PrintOptions;
246{
247public:
248 // 水印刷新机制,包括立刻刷新和延时刷新
249 enum RefreshMode { RefreshImmediately,
250 RefreshDelay };
252
253 void init();
254 void populateScene();
255 void updatePreview();
256 void generatePreview();
257 void fitView();
258 void print(bool printAsPicture = false);
259 void updatePageByPagePrintVector(QVector<int> &pageVector, QList<const QPicture *> &pictures) const;
260 void asynPrint(const QPointF &leftTop, const QRect &pageRect, const QVector<int> &pageVector);
261 void syncPrint(const QPointF &leftTop, const QRect &pageRect, const QVector<int> &pageVector);
262 void printAsImage(const QSize &paperSize, QVector<int> &pageVector);
263 void printSinglePageDrawUtil(QPainter *painter, const QSize &translateSize, const QPointF &leftTop, const QImage &waterImage, const QPicture *picture);
264 void printMultiPageDrawUtil(QPainter *painter, const QPointF &leftTop, const QImage &waterImage);
265
266 void setPageRangeAll();
267 void setCurrentPage(int page);
268 int pagesCount();
269 int targetPage(int page);
270 int index2page(int index);
271 int page2index(int page);
272#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
273 D_DECL_DEPRECATED void impositionPages(); // 拼版
274#endif
275 int impositionPages(DPrintPreviewWidget::Imposition im); // 每页版数
276 QImage generateWaterMarkImage() const;
277 PrintOptions printerOptions();
278 void printByCups();
279
280 void generatePreviewPicture();// 发送requestPaint信号,重新获取原文档数据
281 void calculateNumberUpPage();// 重绘页面,当拼版数改变、纸张大小等操作时必须调用,
282 void calculateNumberPagePosition();// 计算每小页面的显示位置
283
284 void updateNumberUpContent();
285 QVector<int> requestPages(int page);// 取处理后page页的小页面
286 void releaseImpositionData();// 并打切换单页时需要释放水印、页面拼版数据
287
288 void displayWaterMarkItem();// 添加或更新水印效果,
289 void calculateNumberPageScale();// 计算缩放比,拼版数发生改变需要调用
290 void calculateCurrentNumberPage();// page是相对于原文档,添加page页需要显示的小页面到Vector
291 QByteArray foundColorModelByCups() const;
292
293 inline void setCurrentPageNumber(int page)
294 {
295 currentPageNumber = page;
296 }
297
298 GraphicsView *graphicsView;
299 QGraphicsScene *scene;
300
301 QList<QPicture> targetPictures;
302 QList<const QPicture *> pictures;
303 QList<QGraphicsItem *> pages;
304 QGraphicsRectItem *background;
305 WaterMark *waterMark;
306 QVector<int> pageRange; // 选择的页码
307 int currentPageNumber = 0; // 处理以后当前页,值一定是连续的,比如处理共10页,那么取值就是1到10
308 DPrinter::ColorMode colorMode;
309 DPrintPreviewWidget::Imposition imposition;
310 DPrintPreviewWidget::Order order;
311 qreal scale = 1.0;
312 DPrintPreviewWidget::PageRange pageRangeMode = DPrintPreviewWidget::AllPage;
313#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
314 D_DECL_DEPRECATED bool reviewChanged = true; // 预览页面是否发生改变
315#endif
316 DPrinter *previewPrinter;
317 RefreshMode refreshMode;
318
319 QString printFromPath;
320 DPrintPreviewWidget::PrintMode printMode;
321 bool isAsynPreview;
322 QVector<int> previewPages;
323 bool asynPreviewNeedUpdate;
324 int asynPreviewTotalPage;
325 int pageCopyCount = 0;
326 bool isFirstPage;
327
328 struct NumberUpData;
329 NumberUpData *numberUpPrintData;
330 QBasicTimer updateTimer;
331 Q_DECLARE_PUBLIC(DPrintPreviewWidget)
332};
333
335 class NumberItem : public QGraphicsItem
336 {
337 public:
338 NumberItem(QVector<int> _pageNumberVector, QVector<QPointF> _numberPointVector, QRect _pageRect)
339 : numberVector(_pageNumberVector)
340 , numberPointVector(_numberPointVector)
341 {
342 brect = QRectF(QPointF(0, 0), QSizeF(_pageRect.size()));
343 setCacheMode(DeviceCoordinateCache);
344 setPos(_pageRect.topLeft());
345 }
346
347 inline void setPageNumbers(const QVector<int> &pageNumber)
348 {
349 numberVector = pageNumber;
350 }
351
352 inline void setNumberPositon(const QVector<QPointF> &numberPos)
353 {
354 numberPointVector = numberPos;
355 }
356
357 QRectF boundingRect() const override
358 {
359 return brect;
360 }
361
362 void setRect(const QRectF &rect)
363 {
364 setPos(rect.topLeft());
365 brect = QRectF(QPointF(0, 0), QSizeF(rect.size()));
366 }
367
368 void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
369
370 private:
371 QRectF brect;
372 QVector<int> numberVector; // 页码
373 QVector<QPointF> numberPointVector; // 坐标
374 };
375
377 WaterMark::Layout layout;
378 WaterMark::Type type;
379 qreal rotation;
380 qreal scale;
381 qreal opacity;
382 QColor color;
383 QString text;
384 QImage sourceImage;
385 QImage grayImage;
386 QFont font;
387 };
388
389 QVector<QPair<int, const QPicture *>> previewPictures; // 并打当前页面属性列表(页码,图片)
390 QVector<QPointF> paintPoints; // 并打单页位置属性列表
391 qreal scaleRatio; // 并打页面缩放因子
392 int rowCount; // 并打页面行数
393 int columnCount; // 并打页面列数
394 QPointF pageStartPoint; // 并打单页起始位置
395 QList<WaterMark *> waterList; // 并打时水印
396 WaterMarkProperty *waterProperty;
397 NumberItem *numberItem;
398 QGraphicsRectItem *waterParentItem;
399 bool needRecreateWater; // 重绘时不管当前页面水印数量和内容数量一致 都要重新生成页面 因为页面大小发生了变化
401
402 void resetData()
403 {
404 scaleRatio = 1;
405 rowCount = 0;
406 columnCount = 0;
407 pageStartPoint = QPointF(0, 0);
408 }
409
410 QVector<QPointF> updatePositions(const qreal &scale)
411 {
412#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
413 QRectF pageRect = parent->previewPrinter->pageLayout().paintRectPixels(parent->previewPrinter->resolution());
414#else
415 QRectF pageRect = parent->previewPrinter->pageRect();
416#endif
417 QVector<QPointF> posList;
418 QPointF startP(0, 0);
419
420 QPointF topLeft;
421 if (scale >= 1.0) {
422 topLeft = QPointF(0, 0);
423 if ((parent->imposition == DPrintPreviewWidget::OneRowTwoCol) || (parent->imposition == DPrintPreviewWidget::TwoRowThreeCol)) {
424 topLeft.setY(pageStartPoint.y() * (scale - 1.0));
425 }
426 } else {
427 topLeft.setX(pageRect.width() * (1.0 - scale) / 2.0);
428 topLeft.setY((NUMBERUP_SCALE_RATIO * rowCount - NUMBERUP_SPACE_SCALE_RATIO) * pageRect.height() * scaleRatio * (1.0 - scale) / 2.0);
429 }
430
431 switch (parent->order) {
432 case DPrintPreviewWidget::Copy:
433 case DPrintPreviewWidget::L2R_T2B: {
434 startP = pageStartPoint + topLeft;
435 for (int i = 0; i < rowCount; ++i) {
436 for (int j = 0; j < columnCount; ++j) {
437 posList.append(startP + QPointF(NUMBERUP_SCALE_RATIO * j * pageRect.width(), NUMBERUP_SCALE_RATIO * i * pageRect.height()) * scaleRatio * scale);
438 }
439 }
440 } break;
441 // R2L 从右往左扩大 应为从0,0开始扩大 需增加一个expanding使其从左往右扩张
442 case DPrintPreviewWidget::R2L_T2B: {
443 qreal expanding = scale > 1 ? pageRect.width() * (scale - 1) : 0;
444 startP = pageStartPoint - QPointF(topLeft.x() - expanding - pageRect.width(), -topLeft.y());
445 for (int i = 0; i < rowCount; ++i) {
446 for (int j = 0; j < columnCount; ++j) {
447 posList.append(startP - QPointF((NUMBERUP_SCALE_RATIO * j + 1) * pageRect.width(), -(NUMBERUP_SCALE_RATIO * i) * pageRect.height()) * scaleRatio * scale);
448 }
449 }
450 } break;
451 case DPrintPreviewWidget::T2B_L2R: {
452 startP = pageStartPoint + topLeft;
453 for (int i = 0; i < columnCount; ++i) {
454 for (int j = 0; j < rowCount; ++j) {
455 posList.append(startP + QPointF(NUMBERUP_SCALE_RATIO * i * pageRect.width(), NUMBERUP_SCALE_RATIO * j * pageRect.height()) * scaleRatio * scale);
456 }
457 }
458 } break;
459 case DPrintPreviewWidget::T2B_R2L: {
460 qreal expanding = scale > 1 ? pageRect.width() * (scale - 1) : 0;
461 startP = pageStartPoint - QPointF(topLeft.x() - expanding - pageRect.width(), -topLeft.y());
462 for (int i = 0; i < columnCount; ++i) {
463 for (int j = 0; j < rowCount; ++j) {
464 posList.append(startP - QPointF((NUMBERUP_SCALE_RATIO * i + 1) * pageRect.width(), -(NUMBERUP_SCALE_RATIO * j) * pageRect.height()) * scaleRatio * scale);
465 }
466 }
467 } break;
468 }
469
470 return posList;
471 }
472
473 void setWaterMarksScale(qreal scale)
474 {
475 if (waterList.isEmpty())
476 return;
477#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
478 QRectF pageRect = parent->previewPrinter->pageLayout().paintRectPixels(parent->previewPrinter->resolution());
479#else
480 QRectF pageRect = parent->previewPrinter->pageRect();
481#endif
482 QMargins pageMargins = parent->previewPrinter->pageLayout().marginsPixels(parent->previewPrinter->resolution());
483 const QVector<QPointF> &posList = updatePositions(scale);
484
485 for (int c = 0; c < waterList.count(); ++c) {
486 WaterMark *item = waterList.at(c);
487 item->setBoundingRect(QRectF(QPointF(pageMargins.left(), pageMargins.top()) + posList.at(c), pageRect.size() * scaleRatio * scale));
488 item->update();
489 }
490
491 if (numberItem)
492 numberItem->update();
493 }
494
495 void setWaterMarkOriginProperties(WaterMark *wm)
496 {
497 if (!wm || !waterProperty)
498 return;
499
500 wm->type = waterProperty->type;
501 wm->layout = waterProperty->layout;
502 wm->mScaleFactor = waterProperty->scale;
503 wm->color = waterProperty->color;
504 wm->text = waterProperty->text;
505 wm->sourceImage = waterProperty->sourceImage;
506 wm->graySourceImage = waterProperty->grayImage;
507 wm->font = waterProperty->font;
508 wm->setRotation(waterProperty->rotation);
509 wm->setOpacity(waterProperty->opacity);
510 }
511
512 void copyWaterMarkProperties()
513 {
514 // 当并打属性发生变化的时候 需要删除当前页面中的水印层
515 // 因此需要保存当前层的水印效果以便创建时直接添加
516 if (!parent->waterMark && waterList.isEmpty())
517 return;
518
519 WaterMark *wm;
520 if (waterList.isEmpty()) {
521 wm = parent->waterMark;
522 } else {
523 wm = waterList.first();
524 }
525
526 if (!waterProperty)
527 waterProperty = new WaterMarkProperty;
528
529 waterProperty->type = wm->type;
530 waterProperty->layout = wm->layout;
531 waterProperty->rotation = wm->rotation();
532 waterProperty->scale = wm->mScaleFactor;
533 waterProperty->opacity = wm->opacity();
534 waterProperty->color = wm->color;
535 waterProperty->text = wm->text;
536 waterProperty->sourceImage = wm->sourceImage;
537 waterProperty->grayImage = wm->graySourceImage;
538 waterProperty->font = wm->font;
539 }
540
541 void updateWaterMarks()
542 {
543 if (waterList.isEmpty())
544 return;
545
546 for (auto *item : qAsConst(waterList))
547 item->update();
548 }
549
550 template<typename T>
551 void setWaterMarkProperty(T outFunction)
552 {
553 if (waterList.isEmpty())
554 return;
555
556 auto *firstWm = waterList.first();
557 outFunction(firstWm);
558
559 for (auto *item : qAsConst(waterList)) {
560 if (item == firstWm)
561 continue;
562
563 // TODO: remove it in dtkwidget 5.6.
564 item->type = firstWm->type;
565 item->layout = firstWm->layout;
566 item->mScaleFactor = firstWm->mScaleFactor;
567 item->color = firstWm->color;
568 item->text = firstWm->text;
569 item->sourceImage = firstWm->sourceImage;
570 item->graySourceImage = firstWm->graySourceImage;
571 item->font = firstWm->font;
572 item->setRotation(firstWm->rotation());
573 item->setOpacity(firstWm->opacity());
574 }
575 }
576
577 NumberUpData(DPrintPreviewWidgetPrivate *parent)
578 : previewPictures(0)
579 , paintPoints(0)
580 , scaleRatio(1)
581 , rowCount(0)
582 , columnCount(0)
583 , pageStartPoint(0, 0)
584 , waterProperty(nullptr)
585 , numberItem(nullptr)
586 , waterParentItem(nullptr)
587 , needRecreateWater(false)
588 , parent(parent)
589 {
590 }
591
592 ~NumberUpData()
593 {
594 delete waterProperty;
595 delete numberItem;
596 delete waterParentItem;
597 }
598};
599
600DWIDGET_END_NAMESPACE
601Q_DECLARE_TYPEINFO(DTK_WIDGET_NAMESPACE::DPrintPreviewWidgetPrivate::NumberUpData::WaterMarkProperty, Q_PRIMITIVE_TYPE);
602#endif // DPRINTPREVIEWWIDGET_P_H
Definition dprintpreviewwidget_p.h:61
Definition dframe_p.h:17
按钮的图标
Definition diconbutton.h:24
Definition dprintpreviewwidget_p.h:246
Definition dprintpreviewwidget.h:45
Definition dprintpreviewwidget.h:30
Definition dprintpreviewwidget_p.h:33
Definition dprintpreviewwidget_p.h:206
Definition dprintpreviewwidget_p.h:100
Definition dprintpreviewwidget_p.h:334