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.
198 const qreal dpr = q->devicePixelRatioF();
200 img.setDevicePixelRatio(dpr);
201 img.fill(Qt::transparent);
202 const QSizeF paperSize = m_report->paperSize();
203 const qreal paperWidth = paperSize.width();
204 const qreal paperHeight = paperSize.height();
205 const qreal longestSide = qMax(paperWidth, paperHeight);
206 const qreal width = PreviewSize * paperWidth / longestSide;
207 const qreal height = PreviewSize * paperHeight / longestSide;
208 QPainter painter(&img);
210 painter.translate((PreviewSize - width) / 2, (PreviewSize - height) / 2);
211 painter.fillRect(QRectF(0, 0, width, height), QBrush(Qt::white));
212 painter.scale(PreviewSize / longestSide, PreviewSize / longestSide);
213 m_report->paintPage(index, painter);
214 painter.setPen(QPen(1));
215 painter.drawRect(QRectF(0, 0, paperWidth, paperHeight));
216
217 item->setIcon(QIcon(QPixmap::fromImage(img)));
218}
219
220void KDReports::PreviewWidgetPrivate::previewNextItems()
221{
222 if (m_firstDirtyPreviewItem == -1 || m_firstDirtyPreviewItem >= m_pageCount) {
223 m_previewTimer.stop();
224 m_firstDirtyPreviewItem = -1;
225 } else {
226 // Do next preview
227 paintItem(pageList->item(m_firstDirtyPreviewItem), m_firstDirtyPreviewItem);
228 ++m_firstDirtyPreviewItem;
229 }
230}
231
232QPixmap KDReports::PreviewWidgetPrivate::paintPreview(int index) const
233{
234 const QSizeF paperSize = m_report->paperSize();
235 const int width = qCeil(paperSize.width() * m_zoomFactor);
236 const int height = qCeil(paperSize.height() * m_zoomFactor);
237 const qreal dpr = q->devicePixelRatioF();
238
239 QPixmap pixmap(width * dpr, height * dpr);
240 pixmap.setDevicePixelRatio(dpr);
241 pixmap.fill(Qt::transparent);
242 // qDebug() << width << "," << height;
243
244 // qDebug() << "paintPreview " << index;
245
246 QPainter painter(&pixmap);
248
249 painter.fillRect(QRectF(0, 0, width, height), QBrush(Qt::white));
250 painter.scale(m_zoomFactor, m_zoomFactor);
251 m_report->paintPage(index, painter);
252 painter.setPen(QPen(1));
253 painter.drawRect(QRectF(0, 0, paperSize.width(), paperSize.height()));
254
255 return pixmap;
256}
257
258void KDReports::PreviewWidgetPrivate::handleMouseMove(QPoint pos)
259{
260 const QPoint unscaledPos = pos / m_zoomFactor;
261 const QString link = m_report->anchorAt(pageList->currentRow(), unscaledPos);
262 if (link.isEmpty()) { // restore cursor
263 q->unsetCursor();
264 m_onAnchor = false;
265 } else if (!m_onAnchor) {
266 q->setCursor(Qt::PointingHandCursor);
267 m_onAnchor = true;
268 }
269}
270
271void KDReports::PreviewWidgetPrivate::handleMouseRelease(QPoint pos)
272{
273 const QPoint unscaledPos = pos / m_zoomFactor;
274 const QString link = m_report->anchorAt(pageList->currentRow(), unscaledPos);
275 if (!link.isEmpty()) {
276 Q_EMIT q->linkActivated(link);
277 }
278}
279
280void KDReports::PreviewWidgetPrivate::printSelectedPages()
281{
282 // Well, the user can modify the page size in the printer dialog too - ensure layout matches
283 // qDebug() << "pageSize: " << m_printer.pageSize();
284 m_report->setPageSize(m_printer.pageLayout().pageSize());
285 m_report->setPageOrientation(m_printer.pageLayout().orientation());
286 pageCountChanged();
287
288 // ### But how do we match "marked pages" from a previous layout into the new layout?
289 // ### Hardly makes sense...
290
291 int markedPages = 0;
292 for (int pageIndex = 0; pageIndex < pageList->count(); ++pageIndex) {
293 if (pageList->item(pageIndex)->checkState() == Qt::Checked)
294 ++markedPages;
295 }
296
297 QProgressDialog dialog(QObject::tr("Printing"), QObject::tr("Cancel"), 0, markedPages, q);
298 dialog.setWindowModality(Qt::ApplicationModal);
299
300 QPainter painter;
301 painter.begin(&m_printer);
302
303 int printed = 0;
304 bool firstPage = true;
305 for (int pageIndex = 0; pageIndex < m_pageCount; ++pageIndex) {
306
307 // OK because the dialog is modal
308 qApp->processEvents();
309
310 if (dialog.wasCanceled())
311 break;
312
313 if (q->isSelected(pageIndex)) {
314 // Print all pages that are marked
315 if (!firstPage)
316 m_printer.newPage();
317
318 m_report->paintPage(pageIndex, painter);
319 dialog.setValue(++printed);
320 firstPage = false;
321 }
322 }
323 painter.end();
324}
325
326void KDReports::PreviewWidgetPrivate::setupComboBoxes()
327{
328 paperSizeCombo->addItem(PreviewWidget::tr("A0 (841 x 1189 mm)"), QPageSize::A0);
329 paperSizeCombo->addItem(PreviewWidget::tr("A1 (594 x 841 mm)"), QPageSize::A1);
330 paperSizeCombo->addItem(PreviewWidget::tr("A2 (420 x 594 mm)"), QPageSize::A2);
331 paperSizeCombo->addItem(PreviewWidget::tr("A3 (297 x 420 mm)"), QPageSize::A3);
332 paperSizeCombo->addItem(PreviewWidget::tr("A4 (210 x 297 mm)"), QPageSize::A4);
333 paperSizeCombo->addItem(PreviewWidget::tr("A5 (148 x 210 mm)"), QPageSize::A5);
334 paperSizeCombo->addItem(PreviewWidget::tr("A6 (105 x 148 mm)"), QPageSize::A6);
335 paperSizeCombo->addItem(PreviewWidget::tr("A7 (74 x 105 mm)"), QPageSize::A7);
336 paperSizeCombo->addItem(PreviewWidget::tr("A8 (52 x 74 mm)"), QPageSize::A8);
337 // paperSizeCombo->addItem(PreviewWidget::tr("A9 (37 x 52 mm)"), QPageSize::A9);
338 paperSizeCombo->addItem(PreviewWidget::tr("B0 (1000 x 1414 mm)"), QPageSize::B0);
339 paperSizeCombo->addItem(PreviewWidget::tr("B1 (707 x 1000 mm)"), QPageSize::B1);
340 paperSizeCombo->addItem(PreviewWidget::tr("B2 (500 x 707 mm)"), QPageSize::B2);
341 paperSizeCombo->addItem(PreviewWidget::tr("B3 (353 x 500 mm)"), QPageSize::B3);
342 paperSizeCombo->addItem(PreviewWidget::tr("B4 (250 x 353 mm)"), QPageSize::B4);
343 paperSizeCombo->addItem(PreviewWidget::tr("B5 (176 x 250 mm)"), QPageSize::B5);
344 paperSizeCombo->addItem(PreviewWidget::tr("B6 (125 x 176 mm)"), QPageSize::B6);
345 paperSizeCombo->addItem(PreviewWidget::tr("B7 (88 x 125 mm)"), QPageSize::B7);
346 paperSizeCombo->addItem(PreviewWidget::tr("B8 (62 x 88 mm)"), QPageSize::B8);
347 // paperSizeCombo->addItem(PreviewWidget::tr("B9 (44 x 62 mm)"), QPageSize::B9);
348 // paperSizeCombo->addItem(PreviewWidget::tr("B10 (31 x 44 mm)"), QPageSize::B10);
349 paperSizeCombo->addItem(PreviewWidget::tr("C5E (163 x 229 mm)"), QPageSize::C5E);
350 paperSizeCombo->addItem(PreviewWidget::tr("DLE (110 x 220 mm)"), QPageSize::DLE);
351 paperSizeCombo->addItem(PreviewWidget::tr("Executive (7.5 x 10 inches)"), QPageSize::Executive);
352 paperSizeCombo->addItem(PreviewWidget::tr("Folio (210 x 330 mm)"), QPageSize::Folio);
353 paperSizeCombo->addItem(PreviewWidget::tr("Ledger (432 x 279 mm)"), QPageSize::Ledger);
354 paperSizeCombo->addItem(PreviewWidget::tr("Legal (8.5 x 14 inches)"), QPageSize::Legal);
355 paperSizeCombo->addItem(PreviewWidget::tr("Letter (8.5 x 11 inches)"), QPageSize::Letter);
356 paperSizeCombo->addItem(PreviewWidget::tr("Tabloid (279 x 432 mm)"), QPageSize::Tabloid);
357 paperSizeCombo->addItem(PreviewWidget::tr("US #10 Envelope (105 x 241 mm)"), QPageSize::Comm10E);
358 paperSizeCombo->addItem(PreviewWidget::tr("Endless printer (%1 mm wide)").arg(m_endlessPrinterWidth), QPageSize::Custom);
359
360 paperOrientationCombo->addItem(PreviewWidget::tr("Portrait"), QPageLayout::Portrait);
361 paperOrientationCombo->addItem(PreviewWidget::tr("Landscape"), QPageLayout::Landscape);
362}
363
364void KDReports::PreviewWidgetPrivate::slotCurrentPageChanged()
365{
366 updatePreview();
367 updatePageButtons();
368}
369
370void KDReports::PreviewWidgetPrivate::updatePageButtons()
371{
372 prevPage->setEnabled(pageList->currentRow() > 0);
373 nextPage->setEnabled(pageList->currentRow() < pageList->count() - 1);
374 pageNumber->setText(QString::number(pageList->currentRow() + 1));
375}
376
377void KDReports::PreviewWidgetPrivate::updatePreview()
378{
379 if (!pageList->currentItem())
380 return;
381 const QSize oldSize = m_previewWidget->pixmapSize();
382 const QPixmap pixmap = paintPreview(pageList->currentRow());
383 m_previewWidget->setPixmap(pixmap);
384 if (pixmap.size() != oldSize) {
385 centerPreview();
386 }
387}
388
389void KDReports::PreviewWidgetPrivate::pageNumberReturnPressed()
390{
391 bool ok;
392 const int newPageNumber = pageNumber->text().toInt(&ok) - 1;
393 if (!ok || newPageNumber < 0 || newPageNumber > pageList->count() - 1)
394 return;
395 pageList->setCurrentRow(newPageNumber);
396}
397
398void KDReports::PreviewWidgetPrivate::slotFirstPage()
399{
400 pageList->setCurrentRow(0);
401}
402
403void KDReports::PreviewWidgetPrivate::slotPrevPage()
404{
405 if (!pageList->currentItem() || pageList->currentRow() == 0)
406 return;
407 pageList->setCurrentRow(pageList->currentRow() - 1);
408}
409
410void KDReports::PreviewWidgetPrivate::slotNextPage()
411{
412 if (!pageList->currentItem() || pageList->currentRow() >= pageList->count() - 1)
413 return;
414 pageList->setCurrentRow(pageList->currentRow() + 1);
415}
416
417void KDReports::PreviewWidgetPrivate::slotLastPage()
418{
419 if (pageList->count() == 0) // can't happen
420 return;
421 pageList->setCurrentRow(pageList->count() - 1);
422}
423
424void KDReports::PreviewWidgetPrivate::slotPaperSizeActivated(int index)
425{
426 const QPageSize qPageSize(static_cast<QPageSize::PageSizeId>(paperSizeCombo->itemData(index).toInt()));
427 m_printer.setPageSize(qPageSize);
428 if (qPageSize.id() == QPageSize::Custom) {
429 m_report->setWidthForEndlessPrinter(m_endlessPrinterWidth);
430 } else {
431 m_report->setWidthForEndlessPrinter(0);
432 m_report->setPageSize(qPageSize);
433 }
434 pageCountChanged();
435#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
436 emit q->pageSizeChanged(static_cast<QPrinter::PageSize>(qPageSize.id()));
437#else
438 emit q->pageSizeChanged(qPageSize);
439#endif
440}
441
442void KDReports::PreviewWidgetPrivate::slotPaperOrientationActivated(int index)
443{
444 const QPageLayout::Orientation orientation = static_cast<QPageLayout::Orientation>(paperOrientationCombo->itemData(index).toInt());
445 m_printer.setPageOrientation(orientation);
446 m_report->setPageOrientation(orientation);
447 pageCountChanged();
448#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
449 emit q->orientationChanged(static_cast<QPrinter::Orientation>(orientation));
450#else
451 emit q->orientationChanged(orientation);
452#endif
453}
454
455void KDReports::PreviewWidgetPrivate::pageCountChanged()
456{
457 qApp->setOverrideCursor(Qt::WaitCursor); // layouting could take a long time
458 if (m_printer.pageLayout().pageSize().id() == QPageSize::Custom) {
459 // Printing without page breaks -> only one page
460 m_pageCount = 1;
461 } else {
462 m_pageCount = m_report->numberOfPages();
463 // qDebug() << "Report has" << m_pageCount << "pages";
464 }
465
466#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
467 int numberWidth = 20 + pageNumber->fontMetrics().width(QString::number(m_pageCount));
468#else
469 int numberWidth = 20 + pageNumber->fontMetrics().horizontalAdvance(QString::number(m_pageCount));
470#endif
471 pageNumber->setMinimumWidth(numberWidth);
472 pageNumber->setMaximumWidth(numberWidth);
473 pageCount->setText(QStringLiteral(" / ") + QString::number(m_pageCount));
474
475 // Ensure that the treewidget has the right number of items
476 int numberOfItems = pageList->count();
477 while (numberOfItems < m_pageCount) {
478 auto *item = new QListWidgetItem(pageList);
479 item->setText(QString::number(numberOfItems + 1));
481 ++numberOfItems;
482 }
483 if (pageList->currentRow() >= m_pageCount) { // avoid crash
484 // qDebug() << "Adjusting current row to" << m_pageCount - 1;
485 pageList->setCurrentRow(m_pageCount - 1);
486 }
487 while (numberOfItems > m_pageCount) {
488 delete pageList->item(numberOfItems - 1);
489 --numberOfItems;
490 }
491
492 QPixmap whitePixmap(PreviewSize, PreviewSize);
493 whitePixmap.fill(Qt::white);
494
495 for (int index = 0; index < m_pageCount; ++index)
496 pageList->item(index)->setIcon(whitePixmap);
497
498 m_firstDirtyPreviewItem = 0;
499// #define PAINT_ALL_PREVIEWS
500#ifdef PAINT_ALL_PREVIEWS
501 QTime dt;
502 dt.start();
503 while (m_firstDirtyPreviewItem != -1) {
504 previewNextItems();
505 }
506 // Debug mode:
507 // 500 rows, Qt-4.5 or 4.6, no antialiasing, T500 laptop, -O0 or -O2: 42 previews in 8.2s to 8.8s
508 qDebug() << m_pageCount << "previews in" << dt.elapsed() / 1000.0 << "s";
509#else
510 m_previewTimer.start(0);
511#endif
512
513 updatePageButtons();
514 updatePreview();
515 centerPreview();
516 qApp->restoreOverrideCursor();
517}
518
519void KDReports::PreviewWidgetPrivate::centerPreview()
520{
521#if 0 // extreme flicker, due to QScrollArea doing a move(0,0) every time (issue N152085)
522 // TT suggested as workaround to use QAbstractScrollArea instead, didn't try yet.
523 const QPoint offset( ( previewArea->width() - m_previewWidget->width() ) / 2,
524 ( previewArea->height() - m_previewWidget->height() ) / 2 );
525 qDebug() << "Moving to " << offset;
526 m_previewWidget->move( offset );
527#endif
528 // So: make it big, instead. At least as big as the viewport.
529 int width = qMax(m_previewWidget->pixmapWidth(), previewArea->viewport()->width());
530 int height = qMax(m_previewWidget->pixmapHeight(), previewArea->viewport()->height());
531 m_previewWidget->resize(width, height);
532}
533
534void KDReports::PreviewWidgetPrivate::slotZoomIn()
535{
536 if (m_zoomFactor > 1.99)
537 m_zoomFactor = qMin<qreal>(4.0, m_zoomFactor + 0.5);
538 else if (m_zoomFactor > 0.99)
539 m_zoomFactor += 0.2;
540 else
541 m_zoomFactor += 0.1;
542 fillZoomCombo();
543 zoomChanged();
544}
545
546void KDReports::PreviewWidgetPrivate::slotZoomOut()
547{
548 if (m_zoomFactor > 1.99)
549 m_zoomFactor -= 0.5;
550 else if (m_zoomFactor > 0.99)
551 m_zoomFactor -= 0.2;
552 else if (m_zoomFactor >= 0.2)
553 m_zoomFactor -= 0.1;
554 fillZoomCombo();
555 zoomChanged();
556}
557
558void KDReports::PreviewWidgetPrivate::slotZoomChanged()
559{
560 QString str = zoomCombo->currentText();
561 m_zoomFactor = str.remove(str.indexOf(QChar::fromLatin1('%')), 1).toDouble() / 100.0;
562 zoomChanged();
563}
564
565void KDReports::PreviewWidgetPrivate::zoomChanged()
566{
567 // qDebug() << m_zoomFactor;
568 updatePreview();
569 centerPreview();
570}
571
572void KDReports::PreviewWidgetPrivate::fillZoomCombo()
573{
574 static const double s_zoomFactors[] = {0.125, 0.25, 0.333, 0.5, 0.667, 0.75, 1, 1.25, 1.50, 2, 4};
575
576 zoomCombo->clear();
577 bool currentZoomFound = false;
578 for (const qreal val : s_zoomFactors) {
579 if (!currentZoomFound && m_zoomFactor <= val - 0.001) {
580 zoomCombo->addItem(QString::number(m_zoomFactor * 100) + QChar::fromLatin1('%'), QVariant(val));
581 zoomCombo->setCurrentIndex(zoomCombo->count() - 1);
582 currentZoomFound = true;
583 }
584 zoomCombo->addItem(QString::number(val * 100) + QChar::fromLatin1('%'), QVariant(val));
585 if (m_zoomFactor > val - 0.001 && m_zoomFactor < val + 0.001) {
586 zoomCombo->setCurrentIndex(zoomCombo->count() - 1);
587 currentZoomFound = true;
588 }
589 }
590}
591
593
595 : QWidget(parent)
596 , d(new PreviewWidgetPrivate(this))
597{
598 d->init();
599}
600
604
605bool KDReports::PreviewWidget::isSelected(int pageNumber) const
606{
607 if (pageNumber >= 0 && pageNumber < d->pageList->count())
608 return (d->pageList->item(pageNumber)->checkState() == Qt::Checked);
609 else
610 return false;
611}
612
614{
615 d->centerPreview();
616}
617
619{
620 d->paperSizeCombo->setVisible(b);
621 d->paperOrientationCombo->setVisible(b);
622 d->labelPaperSize->setVisible(b);
623 d->labelOrientation->setVisible(b);
624}
625
627{
628 d->tableBreakingButton->setVisible(b);
629}
630
632{
633 // Watch for Return in the pageNumber lineedit.
634 // We could just connect to returnPressed(), but the dialog's OK button would still trigger.
635 if (obj == d->pageNumber) {
636 if (ev->type() == QEvent::KeyPress) {
637 auto *keyev = static_cast<QKeyEvent *>(ev);
638 if (keyev->key() == Qt::Key_Enter || keyev->key() == Qt::Key_Return) {
639 d->pageNumberReturnPressed();
640 keyev->accept();
641 d->previewArea->setFocus();
642 return true;
643 }
644 } else if (ev->type() == QEvent::FocusIn) {
645 d->m_eatPageNumberClick = true;
646 d->pageNumber->selectAll();
647 } else if (ev->type() == QEvent::MouseButtonPress && d->m_eatPageNumberClick) {
648 d->m_eatPageNumberClick = false;
649 return true;
650 }
651 }
652
653 return QWidget::eventFilter(obj, ev);
654}
655
657{
658 d->m_endlessPrinterWidth = widthMM;
659}
660
662{
663 return d->m_report;
664}
665
667{
668 QPointer<QPrintDialog> dialog = new QPrintDialog(&d->m_printer, this);
669 // cppcheck-suppress nullPointerRedundantCheck
670 dialog->setOption(QAbstractPrintDialog::PrintSelection, true);
671 // cppcheck-suppress nullPointerRedundantCheck
672 dialog->setOption(QAbstractPrintDialog::PrintPageRange, true);
673 bool ok = false;
674 // cppcheck-suppress nullPointerRedundantCheck
675 if (dialog->exec() == QDialog::Accepted && dialog) {
676 if (dialog->printRange() == QAbstractPrintDialog::AllPages) {
677 // Select all pages
678 for (int pageIndex = 0; pageIndex < d->pageList->count(); ++pageIndex) {
679 d->pageList->item(pageIndex)->setCheckState(Qt::Checked);
680 }
681 } else if (dialog->printRange() == QAbstractPrintDialog::PageRange) {
682 const int fromPage = dialog->fromPage() - 1; // dialog is 1 based
683 const int toPage = dialog->toPage() - 1;
684 // Select only pages from <fromPage> to <toPage>
685 for (int pageIndex = 0; pageIndex < d->pageList->count(); ++pageIndex) {
686 const bool checked = (pageIndex >= fromPage && pageIndex <= toPage);
687 d->pageList->item(pageIndex)->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
688 }
689 }
690 d->printSelectedPages();
691 ok = true;
692 }
693 delete dialog;
694 return ok;
695}
696
698{
699 d->setReport(report);
700}
701
702void KDReports::PreviewWidgetPrivate::setReport(KDReports::Report *report)
703{
704 Q_ASSERT(report);
705 m_report = report;
706 actionBar->setEnabled(true);
707
708 // initialize combos from report
709#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
710 paperSizeCombo->setCurrentIndex(paperSizeCombo->findData(m_report->pageSize()));
711#else
712 paperSizeCombo->setCurrentIndex(paperSizeCombo->findData(m_report->pageSize().id()));
713#endif
714 paperOrientationCombo->setCurrentIndex(paperOrientationCombo->findData(m_report->pageOrientation()));
715
716 tableBreakingButton->setVisible(m_report->reportMode() == KDReports::Report::SpreadSheet);
717
718 m_report->setupPrinter(&m_printer);
719 pageCountChanged();
720 if (!pageList->currentItem()) {
721 // No page selected yet - select the first one
722 pageList->setCurrentItem(pageList->item(0));
723 }
724 slotCurrentPageChanged(); // update preview and buttons
725 pageList->scrollToTop();
726}
727
729{
730 d->pageList->setVisible(show);
731}
732
734{
735 d->pageCountChanged();
736 d->slotCurrentPageChanged(); // update preview and buttons
737}
738
740{
741 return QSize(800, 600);
742}
743
744#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
transparent
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 Tue Jul 9 2024 00:04:17 for KD Reports API Documentation by doxygen 1.9.8