KD Reports API Documentation 2.2
Loading...
Searching...
No Matches
KDReportsPreviewWidget.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Reports library.
4**
5** SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10
12#include "KDReportsReport.h"
13#include <QDebug>
14#include <QKeyEvent>
15#include <QPainter>
16#include <QPointer>
17#include <QPrintDialog>
18#include <QProgressDialog>
19#include <QShortcut>
20#include <QTime>
21#include <QTimer>
22#include <qmath.h> // qCeil
23
24#include "ui_previewdialogbase.h"
25
26enum
27{
28 PreviewSize = 200
29};
30
33class PagePreviewWidget : public QWidget
34{
36public:
37 PagePreviewWidget(QWidget *parent = nullptr)
39 {
40 // For link hovered functionality
41 setMouseTracking(true);
42 }
43 void setPixmap(const QPixmap &pixmap)
44 {
45 m_pixmap = pixmap;
46 update();
47 }
48 int pixmapWidth() const
49 {
50 return m_pixmap.width();
51 }
52 int pixmapHeight() const
53 {
54 return m_pixmap.height();
55 }
56 QSize pixmapSize() const
57 {
58 return m_pixmap.size();
59 }
60
62 void mouseMoved(QPoint pos);
63 void mouseClicked(QPoint pos);
64
65protected:
66 QPoint pixmapOffset() const
67 {
68 return QPoint((width() - m_pixmap.width()) / 2, (height() - m_pixmap.height()) / 2);
69 }
70
71 void paintEvent(QPaintEvent *) override
72 {
73 QPainter painter(this);
74 // painter.fillRect( event->rect(), QColor(224,224,224) );
75 painter.drawPixmap(pixmapOffset(), m_pixmap);
76 }
78 void mouseMoveEvent(QMouseEvent *ev) override
79 {
80 Q_EMIT mouseMoved(ev->pos() - pixmapOffset());
81 }
83 void mouseReleaseEvent(QMouseEvent *ev) override
84 {
85 Q_EMIT mouseClicked(ev->pos() - pixmapOffset());
86 }
87
88private:
89 QPixmap m_pixmap;
90};
91
92class KDReports::PreviewWidgetPrivate : public Ui::PreviewWidgetBase
93{
94public:
95 PreviewWidgetPrivate(KDReports::PreviewWidget *w);
96
97 // not in ctor because the init calls q->slotFoo which uses d->, so d must be set first.
98 void init();
99
100 void paintItem(QListWidgetItem *item, int index) const;
101 QPixmap paintPreview(int index) const;
102 void printSelectedPages();
103 void setupComboBoxes();
104 void pageCountChanged();
105 void centerPreview();
106 void zoomChanged();
107 void fillZoomCombo();
108 void updatePageButtons();
109 void updatePreview();
110 void pageNumberReturnPressed();
111 void setReport(KDReports::Report *report);
112
113 void handleMouseMove(QPoint pos);
114 void handleMouseRelease(QPoint pos);
115 void slotCurrentPageChanged();
116 void slotFirstPage();
117 void slotPrevPage();
118 void slotNextPage();
119 void slotLastPage();
120 void slotPaperSizeActivated(int);
121 void slotPaperOrientationActivated(int);
122 void slotZoomIn();
123 void slotZoomOut();
124 void slotZoomChanged();
125 void previewNextItems();
126
127 PagePreviewWidget *m_previewWidget;
128 QPrinter m_printer;
129 qreal m_zoomFactor = 1.0;
130 qreal m_endlessPrinterWidth = 114.0;
131 KDReports::Report *m_report = nullptr;
132 QTimer m_previewTimer;
134 int m_pageCount = 0;
135 int m_firstDirtyPreviewItem = -1;
136 bool m_eatPageNumberClick = false;
137 bool m_onAnchor = false;
138};
139
140KDReports::PreviewWidgetPrivate::PreviewWidgetPrivate(KDReports::PreviewWidget *w)
141 : m_previewWidget(new PagePreviewWidget)
142 , q(w)
143{
144 QObject::connect(&m_previewTimer, &QTimer::timeout, q, [this]() { previewNextItems(); });
145 QObject::connect(m_previewWidget, &PagePreviewWidget::mouseMoved, q, [this](QPoint pos) {
146 handleMouseMove(pos);
147 });
148 QObject::connect(m_previewWidget, &PagePreviewWidget::mouseClicked, q, [this](QPoint pos) {
149 handleMouseRelease(pos);
150 });
151}
152
153void KDReports::PreviewWidgetPrivate::init()
154{
155 setupUi(q);
156 actionBar->setEnabled(false);
157
158 m_printer.setFullPage(true);
159
160 pageList->setIconSize(QSize(PreviewSize, PreviewSize));
161 pageList->setViewMode(QListView::IconMode);
162 pageList->setMovement(QListView::Static);
163 previewArea->setWidget(m_previewWidget);
164 setupComboBoxes();
165 previewArea->setFocus();
166 fillZoomCombo();
167
168 // m_tableBreakingButton = buttonBox->addButton( tr("Table Breaking / Font Scaling..." ), QDialogButtonBox::ActionRole );
169 QObject::connect(tableBreakingButton, &QAbstractButton::clicked, q, &PreviewWidget::tableSettingsClicked);
170
171 QObject::connect(firstPage, &QAbstractButton::clicked, q, [this]() { slotFirstPage(); });
172 QObject::connect(prevPage, &QAbstractButton::clicked, q, [this]() { slotPrevPage(); });
173 QObject::connect(nextPage, &QAbstractButton::clicked, q, [this]() { slotNextPage(); });
174 QObject::connect(lastPage, &QAbstractButton::clicked, q, [this]() { slotLastPage(); });
175 QObject::connect(zoomIn, &QAbstractButton::clicked, q, [this]() { slotZoomIn(); });
176 QObject::connect(zoomOut, &QAbstractButton::clicked, q, [this]() { slotZoomOut(); });
177 QObject::connect(zoomCombo, QOverload<int>::of(&QComboBox::activated), q, [this]() { slotZoomChanged(); });
178 QObject::connect(pageList, &QListWidget::currentRowChanged, q, [this]() { slotCurrentPageChanged(); });
179 QObject::connect(paperSizeCombo, QOverload<int>::of(&QComboBox::activated), q, [this](int idx) { slotPaperSizeActivated(idx); });
180 QObject::connect(paperOrientationCombo, QOverload<int>::of(&QComboBox::activated), q, [this](int idx) { slotPaperOrientationActivated(idx); });
181
182 auto *nextPageShortcut = new QShortcut(q);
183 nextPageShortcut->setKey(Qt::CTRL | Qt::Key_PageDown);
184 QObject::connect(nextPageShortcut, &QShortcut::activated, q, [this]() { slotNextPage(); });
185 auto *prevPageShortcut = new QShortcut(q);
186 prevPageShortcut->setKey(Qt::CTRL | Qt::Key_PageUp);
187 QObject::connect(prevPageShortcut, &QShortcut::activated, q, [this]() { slotPrevPage(); });
188 pageNumber->setValidator(new QIntValidator(1, 100000, pageNumber));
189 pageNumber->installEventFilter(q);
190}
191
192void KDReports::PreviewWidgetPrivate::paintItem(QListWidgetItem *item, int index) const
193{
194 // qDebug() << "paintItem" << index;
195
196 // Use a QImage so that the raster paint engine is used.
197 // Gives a 7.7 times speedup (!) compared to X11.
199 const QSizeF paperSize = m_report->paperSize();
200 const qreal longestSide = qMax(paperSize.width(), paperSize.height());
201 qreal width = img.width() * paperSize.width() / longestSide;
202 qreal height = img.height() * paperSize.height() / longestSide;
203 // img.fill( QColor( Qt::white ).rgb() );
204 img.fill(qRgba(0, 0, 0, 0)); // transparent
205 QPainter painter(&img);
206 painter.setRenderHint(QPainter::Antialiasing);
207 painter.translate((img.width() - width) / 2, (img.height() - height) / 2);
208 painter.fillRect(QRectF(0, 0, width, height), QBrush(Qt::white));
209 painter.scale(img.width() / longestSide, img.height() / longestSide);
210 m_report->paintPage(index, painter);
211 painter.setPen(QPen(1));
212 painter.drawRect(QRectF(0, 0, paperSize.width(), paperSize.height()));
213
214 item->setIcon(QIcon(QPixmap::fromImage(img)));
215}
216
217void KDReports::PreviewWidgetPrivate::previewNextItems()
218{
219 if (m_firstDirtyPreviewItem == -1 || m_firstDirtyPreviewItem >= m_pageCount) {
220 m_previewTimer.stop();
221 m_firstDirtyPreviewItem = -1;
222 } else {
223 // Do next preview
224 paintItem(pageList->item(m_firstDirtyPreviewItem), m_firstDirtyPreviewItem);
225 ++m_firstDirtyPreviewItem;
226 }
227}
228
229QPixmap KDReports::PreviewWidgetPrivate::paintPreview(int index) const
230{
231 const QSizeF paperSize = m_report->paperSize();
232 const int width = qCeil(paperSize.width() * m_zoomFactor);
233 const int height = qCeil(paperSize.height() * m_zoomFactor);
234
235 QPixmap pixmap(width, height);
236 // qDebug() << width << "," << height;
237
238 // qDebug() << "paintPreview " << index;
239
240 QPainter painter(&pixmap);
241 painter.setRenderHint(QPainter::Antialiasing);
242 painter.setRenderHint(QPainter::SmoothPixmapTransform);
243 painter.fillRect(QRectF(0, 0, width, height), QBrush(Qt::white));
244 painter.scale(m_zoomFactor, m_zoomFactor);
245 m_report->paintPage(index, painter);
246 painter.setPen(QPen(1));
247 painter.drawRect(QRectF(0, 0, paperSize.width(), paperSize.height()));
248
249 return pixmap;
250}
251
252void KDReports::PreviewWidgetPrivate::handleMouseMove(QPoint pos)
253{
254 const QPoint unscaledPos = pos / m_zoomFactor;
255 const QString link = m_report->anchorAt(pageList->currentRow(), unscaledPos);
256 if (link.isEmpty()) { // restore cursor
257 q->unsetCursor();
258 m_onAnchor = false;
259 } else if (!m_onAnchor) {
260 q->setCursor(Qt::PointingHandCursor);
261 m_onAnchor = true;
262 }
263}
264
265void KDReports::PreviewWidgetPrivate::handleMouseRelease(QPoint pos)
266{
267 const QPoint unscaledPos = pos / m_zoomFactor;
268 const QString link = m_report->anchorAt(pageList->currentRow(), unscaledPos);
269 if (!link.isEmpty()) {
270 Q_EMIT q->linkActivated(link);
271 }
272}
273
274void KDReports::PreviewWidgetPrivate::printSelectedPages()
275{
276 // Well, the user can modify the page size in the printer dialog too - ensure layout matches
277 // qDebug() << "pageSize: " << m_printer.pageSize();
278 m_report->setPageSize(m_printer.pageLayout().pageSize());
279 m_report->setPageOrientation(m_printer.pageLayout().orientation());
280 pageCountChanged();
281
282 // ### But how do we match "marked pages" from a previous layout into the new layout?
283 // ### Hardly makes sense...
284
285 int markedPages = 0;
286 for (int pageIndex = 0; pageIndex < pageList->count(); ++pageIndex) {
287 if (pageList->item(pageIndex)->checkState() == Qt::Checked)
288 ++markedPages;
289 }
290
291 QProgressDialog dialog(QObject::tr("Printing"), QObject::tr("Cancel"), 0, markedPages, q);
292 dialog.setWindowModality(Qt::ApplicationModal);
293
294 QPainter painter;
295 painter.begin(&m_printer);
296
297 int printed = 0;
298 bool firstPage = true;
299 for (int pageIndex = 0; pageIndex < m_pageCount; ++pageIndex) {
300
301 // OK because the dialog is modal
302 qApp->processEvents();
303
304 if (dialog.wasCanceled())
305 break;
306
307 if (q->isSelected(pageIndex)) {
308 // Print all pages that are marked
309 if (!firstPage)
310 m_printer.newPage();
311
312 m_report->paintPage(pageIndex, painter);
313 dialog.setValue(++printed);
314 firstPage = false;
315 }
316 }
317 painter.end();
318}
319
320void KDReports::PreviewWidgetPrivate::setupComboBoxes()
321{
322 paperSizeCombo->addItem(PreviewWidget::tr("A0 (841 x 1189 mm)"), QPageSize::A0);
323 paperSizeCombo->addItem(PreviewWidget::tr("A1 (594 x 841 mm)"), QPageSize::A1);
324 paperSizeCombo->addItem(PreviewWidget::tr("A2 (420 x 594 mm)"), QPageSize::A2);
325 paperSizeCombo->addItem(PreviewWidget::tr("A3 (297 x 420 mm)"), QPageSize::A3);
326 paperSizeCombo->addItem(PreviewWidget::tr("A4 (210 x 297 mm)"), QPageSize::A4);
327 paperSizeCombo->addItem(PreviewWidget::tr("A5 (148 x 210 mm)"), QPageSize::A5);
328 paperSizeCombo->addItem(PreviewWidget::tr("A6 (105 x 148 mm)"), QPageSize::A6);
329 paperSizeCombo->addItem(PreviewWidget::tr("A7 (74 x 105 mm)"), QPageSize::A7);
330 paperSizeCombo->addItem(PreviewWidget::tr("A8 (52 x 74 mm)"), QPageSize::A8);
331 // paperSizeCombo->addItem(PreviewWidget::tr("A9 (37 x 52 mm)"), QPageSize::A9);
332 paperSizeCombo->addItem(PreviewWidget::tr("B0 (1000 x 1414 mm)"), QPageSize::B0);
333 paperSizeCombo->addItem(PreviewWidget::tr("B1 (707 x 1000 mm)"), QPageSize::B1);
334 paperSizeCombo->addItem(PreviewWidget::tr("B2 (500 x 707 mm)"), QPageSize::B2);
335 paperSizeCombo->addItem(PreviewWidget::tr("B3 (353 x 500 mm)"), QPageSize::B3);
336 paperSizeCombo->addItem(PreviewWidget::tr("B4 (250 x 353 mm)"), QPageSize::B4);
337 paperSizeCombo->addItem(PreviewWidget::tr("B5 (176 x 250 mm)"), QPageSize::B5);
338 paperSizeCombo->addItem(PreviewWidget::tr("B6 (125 x 176 mm)"), QPageSize::B6);
339 paperSizeCombo->addItem(PreviewWidget::tr("B7 (88 x 125 mm)"), QPageSize::B7);
340 paperSizeCombo->addItem(PreviewWidget::tr("B8 (62 x 88 mm)"), QPageSize::B8);
341 // paperSizeCombo->addItem(PreviewWidget::tr("B9 (44 x 62 mm)"), QPageSize::B9);
342 // paperSizeCombo->addItem(PreviewWidget::tr("B10 (31 x 44 mm)"), QPageSize::B10);
343 paperSizeCombo->addItem(PreviewWidget::tr("C5E (163 x 229 mm)"), QPageSize::C5E);
344 paperSizeCombo->addItem(PreviewWidget::tr("DLE (110 x 220 mm)"), QPageSize::DLE);
345 paperSizeCombo->addItem(PreviewWidget::tr("Executive (7.5 x 10 inches)"), QPageSize::Executive);
346 paperSizeCombo->addItem(PreviewWidget::tr("Folio (210 x 330 mm)"), QPageSize::Folio);
347 paperSizeCombo->addItem(PreviewWidget::tr("Ledger (432 x 279 mm)"), QPageSize::Ledger);
348 paperSizeCombo->addItem(PreviewWidget::tr("Legal (8.5 x 14 inches)"), QPageSize::Legal);
349 paperSizeCombo->addItem(PreviewWidget::tr("Letter (8.5 x 11 inches)"), QPageSize::Letter);
350 paperSizeCombo->addItem(PreviewWidget::tr("Tabloid (279 x 432 mm)"), QPageSize::Tabloid);
351 paperSizeCombo->addItem(PreviewWidget::tr("US #10 Envelope (105 x 241 mm)"), QPageSize::Comm10E);
352 paperSizeCombo->addItem(PreviewWidget::tr("Endless printer (%1 mm wide)").arg(m_endlessPrinterWidth), QPageSize::Custom);
353
354 paperOrientationCombo->addItem(PreviewWidget::tr("Portrait"), QPageLayout::Portrait);
355 paperOrientationCombo->addItem(PreviewWidget::tr("Landscape"), QPageLayout::Landscape);
356}
357
358void KDReports::PreviewWidgetPrivate::slotCurrentPageChanged()
359{
360 updatePreview();
361 updatePageButtons();
362}
363
364void KDReports::PreviewWidgetPrivate::updatePageButtons()
365{
366 prevPage->setEnabled(pageList->currentRow() > 0);
367 nextPage->setEnabled(pageList->currentRow() < pageList->count() - 1);
368 pageNumber->setText(QString::number(pageList->currentRow() + 1));
369}
370
371void KDReports::PreviewWidgetPrivate::updatePreview()
372{
373 if (!pageList->currentItem())
374 return;
375 const QSize oldSize = m_previewWidget->pixmapSize();
376 const QPixmap pixmap = paintPreview(pageList->currentRow());
377 m_previewWidget->setPixmap(pixmap);
378 if (pixmap.size() != oldSize) {
379 centerPreview();
380 }
381}
382
383void KDReports::PreviewWidgetPrivate::pageNumberReturnPressed()
384{
385 bool ok;
386 const int newPageNumber = pageNumber->text().toInt(&ok) - 1;
387 if (!ok || newPageNumber < 0 || newPageNumber > pageList->count() - 1)
388 return;
389 pageList->setCurrentRow(newPageNumber);
390}
391
392void KDReports::PreviewWidgetPrivate::slotFirstPage()
393{
394 pageList->setCurrentRow(0);
395}
396
397void KDReports::PreviewWidgetPrivate::slotPrevPage()
398{
399 if (!pageList->currentItem() || pageList->currentRow() == 0)
400 return;
401 pageList->setCurrentRow(pageList->currentRow() - 1);
402}
403
404void KDReports::PreviewWidgetPrivate::slotNextPage()
405{
406 if (!pageList->currentItem() || pageList->currentRow() >= pageList->count() - 1)
407 return;
408 pageList->setCurrentRow(pageList->currentRow() + 1);
409}
410
411void KDReports::PreviewWidgetPrivate::slotLastPage()
412{
413 if (pageList->count() == 0) // can't happen
414 return;
415 pageList->setCurrentRow(pageList->count() - 1);
416}
417
418void KDReports::PreviewWidgetPrivate::slotPaperSizeActivated(int index)
419{
420 const QPageSize qPageSize(static_cast<QPageSize::PageSizeId>(paperSizeCombo->itemData(index).toInt()));
421 m_printer.setPageSize(qPageSize);
422 if (qPageSize.id() == QPageSize::Custom) {
423 m_report->setWidthForEndlessPrinter(m_endlessPrinterWidth);
424 } else {
425 m_report->setWidthForEndlessPrinter(0);
426 m_report->setPageSize(qPageSize);
427 }
428 pageCountChanged();
429#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
430 emit q->pageSizeChanged(static_cast<QPrinter::PageSize>(qPageSize.id()));
431#else
432 emit q->pageSizeChanged(qPageSize);
433#endif
434}
435
436void KDReports::PreviewWidgetPrivate::slotPaperOrientationActivated(int index)
437{
438 const QPageLayout::Orientation orientation = static_cast<QPageLayout::Orientation>(paperOrientationCombo->itemData(index).toInt());
439 m_printer.setPageOrientation(orientation);
440 m_report->setPageOrientation(orientation);
441 pageCountChanged();
442#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
443 emit q->orientationChanged(static_cast<QPrinter::Orientation>(orientation));
444#else
445 emit q->orientationChanged(orientation);
446#endif
447}
448
449void KDReports::PreviewWidgetPrivate::pageCountChanged()
450{
451 qApp->setOverrideCursor(Qt::WaitCursor); // layouting could take a long time
452 if (m_printer.pageLayout().pageSize().id() == QPageSize::Custom) {
453 // Printing without page breaks -> only one page
454 m_pageCount = 1;
455 } else {
456 m_pageCount = m_report->numberOfPages();
457 // qDebug() << "Report has" << m_pageCount << "pages";
458 }
459
460#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
461 int numberWidth = 20 + pageNumber->fontMetrics().width(QString::number(m_pageCount));
462#else
463 int numberWidth = 20 + pageNumber->fontMetrics().horizontalAdvance(QString::number(m_pageCount));
464#endif
465 pageNumber->setMinimumWidth(numberWidth);
466 pageNumber->setMaximumWidth(numberWidth);
467 pageCount->setText(QStringLiteral(" / ") + QString::number(m_pageCount));
468
469 // Ensure that the treewidget has the right number of items
470 int numberOfItems = pageList->count();
471 while (numberOfItems < m_pageCount) {
472 auto *item = new QListWidgetItem(pageList);
473 item->setText(QString::number(numberOfItems + 1));
475 ++numberOfItems;
476 }
477 if (pageList->currentRow() >= m_pageCount) { // avoid crash
478 // qDebug() << "Adjusting current row to" << m_pageCount - 1;
479 pageList->setCurrentRow(m_pageCount - 1);
480 }
481 while (numberOfItems > m_pageCount) {
482 delete pageList->item(numberOfItems - 1);
483 --numberOfItems;
484 }
485
486 QPixmap whitePixmap(PreviewSize, PreviewSize);
487 whitePixmap.fill(Qt::white);
488
489 for (int index = 0; index < m_pageCount; ++index)
490 pageList->item(index)->setIcon(whitePixmap);
491
492 m_firstDirtyPreviewItem = 0;
493// #define PAINT_ALL_PREVIEWS
494#ifdef PAINT_ALL_PREVIEWS
495 QTime dt;
496 dt.start();
497 while (m_firstDirtyPreviewItem != -1) {
498 previewNextItems();
499 }
500 // Debug mode:
501 // 500 rows, Qt-4.5 or 4.6, no antialiasing, T500 laptop, -O0 or -O2: 42 previews in 8.2s to 8.8s
502 qDebug() << m_pageCount << "previews in" << dt.elapsed() / 1000.0 << "s";
503#else
504 m_previewTimer.start(0);
505#endif
506
507 updatePageButtons();
508 updatePreview();
509 centerPreview();
510 qApp->restoreOverrideCursor();
511}
512
513void KDReports::PreviewWidgetPrivate::centerPreview()
514{
515#if 0 // extreme flicker, due to QScrollArea doing a move(0,0) every time (issue N152085)
516 // TT suggested as workaround to use QAbstractScrollArea instead, didn't try yet.
517 const QPoint offset( ( previewArea->width() - m_previewWidget->width() ) / 2,
518 ( previewArea->height() - m_previewWidget->height() ) / 2 );
519 qDebug() << "Moving to " << offset;
520 m_previewWidget->move( offset );
521#endif
522 // So: make it big, instead. At least as big as the viewport.
523 int width = qMax(m_previewWidget->pixmapWidth(), previewArea->viewport()->width());
524 int height = qMax(m_previewWidget->pixmapHeight(), previewArea->viewport()->height());
525 m_previewWidget->resize(width, height);
526}
527
528void KDReports::PreviewWidgetPrivate::slotZoomIn()
529{
530 if (m_zoomFactor > 1.99)
531 m_zoomFactor = qMin<qreal>(4.0, m_zoomFactor + 0.5);
532 else if (m_zoomFactor > 0.99)
533 m_zoomFactor += 0.2;
534 else
535 m_zoomFactor += 0.1;
536 fillZoomCombo();
537 zoomChanged();
538}
539
540void KDReports::PreviewWidgetPrivate::slotZoomOut()
541{
542 if (m_zoomFactor > 1.99)
543 m_zoomFactor -= 0.5;
544 else if (m_zoomFactor > 0.99)
545 m_zoomFactor -= 0.2;
546 else if (m_zoomFactor >= 0.2)
547 m_zoomFactor -= 0.1;
548 fillZoomCombo();
549 zoomChanged();
550}
551
552void KDReports::PreviewWidgetPrivate::slotZoomChanged()
553{
554 QString str = zoomCombo->currentText();
555 m_zoomFactor = str.remove(str.indexOf(QChar::fromLatin1('%')), 1).toDouble() / 100.0;
556 zoomChanged();
557}
558
559void KDReports::PreviewWidgetPrivate::zoomChanged()
560{
561 // qDebug() << m_zoomFactor;
562 updatePreview();
563 centerPreview();
564}
565
566void KDReports::PreviewWidgetPrivate::fillZoomCombo()
567{
568 static const double s_zoomFactors[] = {0.125, 0.25, 0.333, 0.5, 0.667, 0.75, 1, 1.25, 1.50, 2, 4};
569
570 zoomCombo->clear();
571 bool currentZoomFound = false;
572 for (const qreal val : s_zoomFactors) {
573 if (!currentZoomFound && m_zoomFactor <= val - 0.001) {
574 zoomCombo->addItem(QString::number(m_zoomFactor * 100) + QChar::fromLatin1('%'), QVariant(val));
575 zoomCombo->setCurrentIndex(zoomCombo->count() - 1);
576 currentZoomFound = true;
577 }
578 zoomCombo->addItem(QString::number(val * 100) + QChar::fromLatin1('%'), QVariant(val));
579 if (m_zoomFactor > val - 0.001 && m_zoomFactor < val + 0.001) {
580 zoomCombo->setCurrentIndex(zoomCombo->count() - 1);
581 currentZoomFound = true;
582 }
583 }
584}
585
587
589 : QWidget(parent)
590 , d(new PreviewWidgetPrivate(this))
591{
592 d->init();
593}
594
598
599bool KDReports::PreviewWidget::isSelected(int pageNumber) const
600{
601 if (pageNumber >= 0 && pageNumber < d->pageList->count())
602 return (d->pageList->item(pageNumber)->checkState() == Qt::Checked);
603 else
604 return false;
605}
606
608{
609 d->centerPreview();
610}
611
613{
614 d->paperSizeCombo->setVisible(b);
615 d->paperOrientationCombo->setVisible(b);
616 d->labelPaperSize->setVisible(b);
617 d->labelOrientation->setVisible(b);
618}
619
621{
622 d->tableBreakingButton->setVisible(b);
623}
624
626{
627 // Watch for Return in the pageNumber lineedit.
628 // We could just connect to returnPressed(), but the dialog's OK button would still trigger.
629 if (obj == d->pageNumber) {
630 if (ev->type() == QEvent::KeyPress) {
631 auto *keyev = static_cast<QKeyEvent *>(ev);
632 if (keyev->key() == Qt::Key_Enter || keyev->key() == Qt::Key_Return) {
633 d->pageNumberReturnPressed();
634 keyev->accept();
635 d->previewArea->setFocus();
636 return true;
637 }
638 } else if (ev->type() == QEvent::FocusIn) {
639 d->m_eatPageNumberClick = true;
640 d->pageNumber->selectAll();
641 } else if (ev->type() == QEvent::MouseButtonPress && d->m_eatPageNumberClick) {
642 d->m_eatPageNumberClick = false;
643 return true;
644 }
645 }
646
647 return QWidget::eventFilter(obj, ev);
648}
649
651{
652 d->m_endlessPrinterWidth = widthMM;
653}
654
656{
657 return d->m_report;
658}
659
661{
662 QPointer<QPrintDialog> dialog = new QPrintDialog(&d->m_printer, this);
663 dialog->setOption(QAbstractPrintDialog::PrintSelection, true);
664 dialog->setOption(QAbstractPrintDialog::PrintPageRange, true);
665 bool ok = false;
666 /* cppcheck-suppress nullPointerRedundantCheck */
667 if (dialog->exec() == QDialog::Accepted && dialog) {
668 if (dialog->printRange() == QAbstractPrintDialog::AllPages) {
669 // Select all pages
670 for (int pageIndex = 0; pageIndex < d->pageList->count(); ++pageIndex) {
671 d->pageList->item(pageIndex)->setCheckState(Qt::Checked);
672 }
673 } else if (dialog->printRange() == QAbstractPrintDialog::PageRange) {
674 const int fromPage = dialog->fromPage() - 1; // dialog is 1 based
675 const int toPage = dialog->toPage() - 1;
676 // Select only pages from <fromPage> to <toPage>
677 for (int pageIndex = 0; pageIndex < d->pageList->count(); ++pageIndex) {
678 const bool checked = (pageIndex >= fromPage && pageIndex <= toPage);
679 d->pageList->item(pageIndex)->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
680 }
681 }
682 d->printSelectedPages();
683 ok = true;
684 }
685 delete dialog;
686 return ok;
687}
688
690{
691 d->setReport(report);
692}
693
694void KDReports::PreviewWidgetPrivate::setReport(KDReports::Report *report)
695{
696 Q_ASSERT(report);
697 m_report = report;
698 actionBar->setEnabled(true);
699
700 // initialize combos from report
701#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
702 paperSizeCombo->setCurrentIndex(paperSizeCombo->findData(m_report->pageSize()));
703#else
704 paperSizeCombo->setCurrentIndex(paperSizeCombo->findData(m_report->pageSize().id()));
705#endif
706 paperOrientationCombo->setCurrentIndex(paperOrientationCombo->findData(m_report->pageOrientation()));
707
708 tableBreakingButton->setVisible(m_report->reportMode() == KDReports::Report::SpreadSheet);
709
710 m_report->setupPrinter(&m_printer);
711 pageCountChanged();
712 if (!pageList->currentItem()) {
713 // No page selected yet - select the first one
714 pageList->setCurrentItem(pageList->item(0));
715 }
716 slotCurrentPageChanged(); // update preview and buttons
717 pageList->scrollToTop();
718}
719
721{
722 d->pageList->setVisible(show);
723}
724
726{
727 d->pageCountChanged();
728 d->slotCurrentPageChanged(); // update preview and buttons
729}
730
732{
733 return QSize(800, 600);
734}
735
736#include "KDReportsPreviewWidget.moc"
PreviewWidget(QWidget *parent=nullptr)
void resizeEvent(QResizeEvent *) override
Reimplemented for internal purposes. .
bool isSelected(int pageNumber) const
void setWidthForEndlessPrinter(qreal widthMM)
void setReport(KDReports::Report *report)
bool eventFilter(QObject *, QEvent *) override
Reimplemented for internal purposes. .
KDReports::Report * report() const
void clicked(bool checked)
QChar fromLatin1(char c)
void activated(int index)
void accept()
QEvent::Type type() const const
Format_ARGB32_Premultiplied
void currentRowChanged(int currentRow)
void setCheckState(Qt::CheckState state)
void setIcon(const QIcon &icon)
void setText(const QString &text)
QPoint pos() const const
Q_EMITQ_EMIT
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool begin(QPaintDevice *device)
bool end()
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
QSize size() const const
void activated()
qreal height() const const
qreal width() const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString number(int n, int base)
QString & remove(int position, int n)
double toDouble(bool *ok) const const
PointingHandCursor
Key_PageDown
ApplicationModal
int elapsed() const const
void start()
void timeout()
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
void setMouseTracking(bool enable)
virtual void paintEvent(QPaintEvent *event)
void update()

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-reports/
Generated on Wed Apr 24 2024 04:08:14 for KD Reports API Documentation by doxygen 1.9.8