File indexing completed on 2024-05-19 16:08:33

0001 /* This file is part of the KDE project
0002  * Copyright 2008-2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0003  * Copyright (C) 2007 Thomas Zander <zander@kde.org>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "PrintJob.h"
0022 
0023 #include "Canvas.h"
0024 #include "Doc.h"
0025 #include "HeaderFooter.h"
0026 #include "Map.h"
0027 #include "PrintSettings.h"
0028 #include "RowColumnFormat.h"
0029 #include "RowFormatStorage.h"
0030 #include "Sheet.h"
0031 #include "SheetPrint.h"
0032 #include "View.h"
0033 
0034 #include "part/dialogs/SheetSelectPage.h"
0035 
0036 #include "ui/Selection.h"
0037 #include "ui/SheetView.h"
0038 
0039 #include <KoGlobal.h>
0040 #include <KoShape.h>
0041 #include <KoShapeManager.h>
0042 #include <KoZoomHandler.h>
0043 #include <KoUnit.h>
0044 
0045 #include <kmessagebox.h>
0046 
0047 #include <QHash>
0048 #include <QPainter>
0049 #include <QPrintPreviewDialog>
0050 
0051 using namespace Calligra::Sheets;
0052 
0053 typedef QHash<Sheet *, SheetPrint *> PageManagerMap;
0054 
0055 class PrintJob::Private
0056 {
0057 public:
0058     View* view;
0059     SheetSelectPage* sheetSelectPage;
0060     PageManagerMap pageManagers;
0061 
0062 public:
0063     int setupPages(const QPrinter& printer, bool forceRecreation = false);
0064     Sheet* getSheetPageNumber(int* sheetPageNumber) const;
0065 
0066     /**
0067      * Checks whether the page has content to print.
0068      * \param sheet the page's sheet
0069      * \param cellRange the page's cell range to check
0070      */
0071     bool pageNeedsPrinting(Sheet *sheet, const QRect &cellRange) const;
0072 
0073     /**
0074      * Prints the header and footer on a page.
0075      * \param painter the painter to use
0076      * \param sheet the page's sheet
0077      * \param page the page number
0078      */
0079     void printHeaderFooter(QPainter &painter, Sheet *sheet, int page) const;
0080 };
0081 
0082 int PrintJob::Private::setupPages(const QPrinter& printer, bool forceRecreation)
0083 {
0084     // Create the list of sheet, that should be printed.
0085     pageManagers.clear();
0086     if (printer.printRange() == QPrinter::Selection)
0087         pageManagers.insert(view->activeSheet(), view->activeSheet()->print());
0088     else if (sheetSelectPage->m_ui.allSheetsButton->isChecked()) {
0089         const QList<Sheet *> sheets = view->doc()->map()->sheetList();
0090         for (int i = 0; i < sheets.count(); ++i) {
0091             pageManagers.insert(sheets[i], sheets[i]->print());
0092         }
0093     } else if (sheetSelectPage->m_ui.activeSheetButton->isChecked()) {
0094         pageManagers.insert(view->activeSheet(), view->activeSheet()->print());
0095     } else if (sheetSelectPage->m_ui.selectedSheetsButton->isChecked()) {
0096         const QStringList sheetNames = sheetSelectPage->selectedSheets();
0097         for (int i = 0; i < sheetNames.count(); ++i) {
0098             Sheet* sheet = view->doc()->map()->findSheet(sheetNames[i]);
0099             if (sheet == 0) {
0100                 warnSheetsUI << i18n("Sheet %1 could not be found for printing", sheetNames[i]);
0101                 continue;
0102             }
0103             pageManagers.insert(sheet, sheet->print());
0104         }
0105     }
0106 
0107     // (Re-)Create the pages of the sheets.
0108     int pageCount = 0;
0109     const PageManagerMap::ConstIterator end(pageManagers.constEnd());
0110     for (PageManagerMap::ConstIterator it(pageManagers.constBegin()); it != end; ++it) {
0111         SheetPrint *const pageManager = *it;
0112         PrintSettings settings = *pageManager->settings();
0113         // Set the print region, if the selection should be painted.
0114         // Temporarily! The print region is solely used for the page creation
0115         // of the current printout, but we are working with the permanent
0116         // SheetPrint object in this case.
0117         const Region printRegion = settings.printRegion();
0118         if (printer.printRange() == QPrinter::Selection)
0119             settings.setPrintRegion(*view->selection());
0120         pageManager->setSettings(settings, forceRecreation);
0121         pageCount += pageManager->pageCount();
0122         if (printer.printRange() == QPrinter::Selection) {
0123             // Restore the former print region.
0124             settings.setPrintRegion(printRegion);
0125             pageManager->setSettings(settings, true);
0126         }
0127     }
0128     return pageCount;
0129 }
0130 
0131 Sheet* PrintJob::Private::getSheetPageNumber(int* sheetPageNumber) const
0132 {
0133     Q_ASSERT(sheetPageNumber);
0134     // Find the sheet specific page number.
0135     Sheet* sheet = 0;
0136     const PageManagerMap::ConstIterator end(pageManagers.constEnd());
0137     for (PageManagerMap::ConstIterator it(pageManagers.constBegin()); it != end; ++it) {
0138         sheet = it.key();
0139         SheetPrint *const pageManager = *it;
0140         if (*sheetPageNumber <= pageManager->pageCount())
0141             break;
0142         *sheetPageNumber -= pageManager->pageCount();
0143     }
0144     return sheet;
0145 }
0146 
0147 bool PrintJob::Private::pageNeedsPrinting(Sheet * sheet, const QRect& cellRange) const
0148 {
0149     // TODO Stefan: Is there a better, faster approach?
0150     for (int row = cellRange.top(); row <= cellRange.bottom() ; ++row) {
0151         for (int col = cellRange.left(); col <= cellRange.right(); ++col) {
0152             if (Cell(sheet, col, row).needsPrinting()) {
0153                 return true;
0154             }
0155         }
0156     }
0157 
0158     QRectF shapesBoundingRect;
0159     const QList<KoShape*> shapes = sheet->shapes();
0160     for (int i = 0; i < shapes.count(); ++i) {
0161         shapesBoundingRect |= shapes[i]->boundingRect();
0162     }
0163     const QRect shapesCellRange = sheet->documentToCellCoordinates(shapesBoundingRect);
0164     return !(cellRange & shapesCellRange).isEmpty();
0165 }
0166 
0167 void PrintJob::Private::printHeaderFooter(QPainter &painter, Sheet *sheet, int pageNo) const
0168 {
0169     const SheetPrint *const pageManager = pageManagers[sheet];
0170     const PrintSettings *const settings = pageManager->settings();
0171     const KoPageLayout pageLayout = settings->pageLayout();
0172 
0173     const HeaderFooter *const headerFooter = pageManager->headerFooter();
0174 #if 1 // debug header/footer
0175     const QString headLeft = headerFooter->headLeft(pageNo, sheet->sheetName());
0176     const QString headMid = headerFooter->headMid(pageNo, sheet->sheetName());
0177     const QString headRight = headerFooter->headRight(pageNo, sheet->sheetName());
0178     const QString footLeft = headerFooter->footLeft(pageNo, sheet->sheetName());
0179     const QString footMid = headerFooter->footMid(pageNo, sheet->sheetName());
0180     const QString footRight = headerFooter->footRight(pageNo, sheet->sheetName());
0181 #else // debug header/footer
0182     const QString headLeft = "HeaderLeft";
0183     const QString headMid = "HeaderMid";
0184     const QString headRight = "HeaderRight";
0185     const QString footLeft = "FooterLeft";
0186     const QString footMid = "FooterMid";
0187     const QString footRight = "FooterRight";
0188 #endif // debug header/footer
0189     debugSheets << headLeft << headMid << headRight << footLeft << footMid << footRight;
0190 
0191     qreal textWidth;
0192     const qreal headFootDistance = MM_TO_POINT(5.0 /*mm*/);
0193     const qreal leftMarginDistance = MM_TO_POINT(5.0 /*mm*/);
0194     painter.setFont(KoGlobal::defaultFont());
0195     const QFontMetricsF fontMetrics = painter.fontMetrics();
0196     const qreal ascent = fontMetrics.ascent();
0197 
0198     // print head line left
0199     textWidth = fontMetrics.width(headLeft);
0200     if (textWidth > 0) {
0201         painter.drawText(leftMarginDistance,
0202                          headFootDistance + ascent,
0203                          headLeft);
0204     }
0205 
0206     // print head line middle
0207     textWidth = fontMetrics.width(headMid);
0208     if (textWidth > 0) {
0209         painter.drawText((pageLayout.width - textWidth) / 2.0,
0210                          headFootDistance + ascent,
0211                          headMid);
0212     }
0213 
0214     // print head line right
0215     textWidth = fontMetrics.width(headRight);
0216     if (textWidth > 0) {
0217         painter.drawText(pageLayout.width - textWidth - leftMarginDistance,
0218                          headFootDistance + ascent,
0219                          headRight);
0220     }
0221 
0222     // print foot line left
0223     textWidth = fontMetrics.width(footLeft);
0224     if (textWidth > 0) {
0225         painter.drawText(leftMarginDistance,
0226                          pageLayout.height - headFootDistance,
0227                          footLeft);
0228     }
0229 
0230     // print foot line middle
0231     textWidth = fontMetrics.width(footMid);
0232     if (textWidth > 0) {
0233         painter.drawText((pageLayout.width - textWidth) / 2.0,
0234                          pageLayout.height - headFootDistance,
0235                          footMid);
0236     }
0237 
0238     // print foot line right
0239     textWidth = fontMetrics.width(footRight);
0240     if (textWidth > 0) {
0241         painter.drawText(pageLayout.width - textWidth - leftMarginDistance,
0242                          pageLayout.height - headFootDistance,
0243                          footRight);
0244     }
0245 }
0246 
0247 
0248 PrintJob::PrintJob(View *view)
0249         : KoPrintingDialog(view)
0250         , d(new Private)
0251 {
0252     d->view = view;
0253     d->sheetSelectPage = new SheetSelectPage();
0254 
0255     setShapeManager(static_cast<Canvas*>(d->view->canvas())->shapeManager());
0256 
0257     // Setup the pages.
0258     // Force the creation of pages.
0259     const int pageCount = d->setupPages(printer(), true);
0260     printer().setFromTo(1, pageCount);
0261 
0262     //apply page layout parameters
0263     Sheet *const sheet = d->view->activeSheet();
0264     const PrintSettings* settings = d->pageManagers[sheet]->settings();
0265     const KoPageLayout pageLayout = settings->pageLayout();
0266     const KoPageFormat::Format pageFormat = pageLayout.format;
0267     printer().setPaperSize(static_cast<QPrinter::PageSize>(KoPageFormat::printerPageSize(pageFormat)));
0268     if (pageLayout.orientation == KoPageFormat::Landscape || pageFormat == KoPageFormat::ScreenSize)
0269         printer().setOrientation(QPrinter::Landscape);
0270     else
0271         printer().setOrientation(QPrinter::Portrait);
0272     printer().setPageMargins(pageLayout.leftMargin, pageLayout.topMargin,
0273                              pageLayout.rightMargin, pageLayout.bottomMargin,
0274                              QPrinter::Point);
0275     printer().setFullPage(true);
0276 
0277     //debugSheetsUI <<"Iterating through available sheets and initializing list of available sheets.";
0278     QList<Sheet*> sheetList = d->view->doc()->map()->sheetList();
0279     for (int i = sheetList.count() - 1; i >= 0; --i) {
0280         Sheet* sheet = sheetList[ i ];
0281         //debugSheetsUI <<"Adding" << sheet->sheetName();
0282         d->sheetSelectPage->prependAvailableSheet(sheet->sheetName());
0283     }
0284 }
0285 
0286 PrintJob::~PrintJob()
0287 {
0288 //     delete d->sheetSelectPage; // QPrintDialog takes ownership
0289     delete d;
0290 }
0291 
0292 int PrintJob::documentFirstPage() const
0293 {
0294     return d->pageManagers.isEmpty() ? 0 : 1;
0295 }
0296 
0297 int PrintJob::documentLastPage() const
0298 {
0299     int pageCount = 0;
0300     const PageManagerMap::ConstIterator end(d->pageManagers.constEnd());
0301     for (PageManagerMap::ConstIterator it(d->pageManagers.constBegin()); it != end; ++it) {
0302         pageCount += (*it)->pageCount();
0303     }
0304     return pageCount;
0305 }
0306 
0307 void PrintJob::startPrinting(RemovePolicy removePolicy)
0308 {
0309     // Setup the pages.
0310     // No recreation forced, because the sheet contents remained the same since the dialog was created.
0311     const int pageCount = d->setupPages(printer());
0312 
0313     // If there's nothing to print and this slot was not called by the print preview dialog ...
0314     if (pageCount == 0 && (!sender() || !qobject_cast<QPrintPreviewDialog*>(sender()))) {
0315         QStringList sheetNames;
0316         const PageManagerMap::ConstIterator end(d->pageManagers.constEnd());
0317         for (PageManagerMap::ConstIterator it(d->pageManagers.constBegin()); it != end; ++it) {
0318             sheetNames.append(it.key()->sheetName());
0319         }
0320         KMessageBox::information(d->view, i18n("Nothing to print for sheet(s) %1.", sheetNames.join(", ")));
0321         return;
0322     }
0323 
0324     // Start the printing.
0325     KoPrintingDialog::startPrinting(removePolicy);
0326 }
0327 
0328 QRectF PrintJob::preparePage(int pageNumber)
0329 {
0330     // The printing of shapes is done by KoPrintingDialog, which needs the
0331     // QPainter set up properly. Otherwise, the separation into preparePage()
0332     // and printPage() would not have been necessary - at least for Calligra Sheets.
0333     // In printPage() the painting of the sheet contents is done; some of the
0334     // QPainter settings from preparePage() get reverted.
0335 
0336     int sheetPageNumber = pageNumber;
0337     Sheet* sheet = d->getSheetPageNumber(&sheetPageNumber);
0338     if (!sheet)
0339         return QRectF();
0340 
0341     // Move the painter offset according to the page layout.
0342     const SheetPrint *const pageManager = d->pageManagers[sheet];
0343     const PrintSettings *const settings = pageManager->settings();
0344     // Everything in the painting logic is done in logical, device-independent
0345     // coordinates. The painting logic uses KoZoomHandler/KoViewConverter. The
0346     // mapping between logical and physical coordinates has to be done by
0347     // QPainter, merely QPaintEngine.
0348     // For screen painting: QWidget's paint engine does not seem to do the mapping,
0349     // otherwise we would not have to take the screen resolution into account by
0350     // KoZoomHandler.
0351     // Question is: Does QPrinter's engine maps the logical to physical points?
0352     // Seems not: KoPrintingDialog uses KoZoomHandler in conjunction with the
0353     // printer's resolution and a zoom factor of 1 for the shape painting.
0354     // QPrinter::ScreenResolution is default
0355     //
0356     // So, what's left is to apply the zoom factor.
0357     // And, to scale the coordinates with the logical-to-physical factor.
0358     //
0359     // POINT_TO_INCH(x) = x / 72 = x * 0.01388888888889
0360     //
0361     // Example: screen resolution = 86 dpi, zoom = 2
0362     // Screen: 86 / 72 * 2 = 2.39 [pixels/inch / points/inch = pixels/points = physical points/logical points]
0363     // Example: printer resolution 300 dpi, zoom = 2
0364     // Printer: 300 / 72 * 2 = 8.33 [physical points/logical points]
0365     const double scale = POINT_TO_INCH(printer().resolution());
0366     const KoPageLayout pageLayout = settings->pageLayout();
0367     painter().translate(pageLayout.leftMargin * scale, pageLayout.topMargin * scale);
0368 
0369     // Apply the print zoom factor,
0370     const double zoom = settings->zoom();
0371     painter().scale(zoom, zoom);
0372 
0373     // Prepare the page for shape printing.
0374     const QRect cellRange = pageManager->cellRange(sheetPageNumber);
0375     QRectF pageRect = pageManager->documentArea(sheetPageNumber);
0376     painter().translate(-pageRect.left() * scale, -pageRect.top() * scale);
0377 
0378     // Calculate the dimensions of the repeated columns/rows first.
0379     double repeatedWidth = 0.0;
0380     const QPair<int, int> repeatedColumns = settings->repeatedColumns();
0381     if (repeatedColumns.first != 0 && cellRange.left() > repeatedColumns.second) {
0382         for (int col = repeatedColumns.first; col <= repeatedColumns.second; ++col) {
0383             repeatedWidth += sheet->columnFormat(col)->visibleWidth();
0384         }
0385     }
0386     double repeatedHeight = 0.0;
0387     const QPair<int, int> repeatedRows = settings->repeatedRows();
0388     if (repeatedRows.first != 0 && cellRange.top() > repeatedRows.second) {
0389         repeatedHeight += sheet->rowFormats()->totalVisibleRowHeight(repeatedRows.first, repeatedRows.second);
0390     }
0391 
0392     // Center the table on the page.
0393     if (settings->centerHorizontally()) {
0394         const double pageWidth = pageRect.width() + repeatedWidth;
0395         const double printWidth = settings->printWidth();
0396         const double offset = 0.5 * (printWidth / zoom - pageWidth);
0397         painter().translate(offset * scale, 0.0);
0398         pageRect.moveLeft(offset); // scale will be applied below
0399     }
0400     if (settings->centerVertically()) {
0401         const double pageHeight = pageRect.height() + repeatedHeight;
0402         const double printHeight = settings->printHeight();
0403         const double offset = 0.5 * (printHeight / zoom - pageHeight);
0404         painter().translate(0.0, offset * scale);
0405         pageRect.moveTop(offset); // scale will be applied below
0406     }
0407     return QRectF(pageRect.left() * scale, pageRect.top() * scale,
0408                   pageRect.width() * scale, pageRect.height() * scale);
0409 }
0410 
0411 void PrintJob::printPage(int pageNumber, QPainter &painter)
0412 {
0413     // See first comment in preparePage() about the distinction between the
0414     // printing of the sheet contents and shapes.
0415 
0416     debugSheetsRender << "Printing page" << pageNumber;
0417     int sheetPageNumber = pageNumber;
0418     Sheet* sheet = d->getSheetPageNumber(&sheetPageNumber);
0419 
0420     // Print the cells.
0421     if (!sheet) {
0422         return;
0423     }
0424 
0425     // Reset the offset made for shape printing.
0426     const double scale = POINT_TO_INCH(printer().resolution());
0427     const QRect cellRange = d->pageManagers[sheet]->cellRange(sheetPageNumber);
0428     const QRectF pageRect = d->pageManagers[sheet]->documentArea(sheetPageNumber);
0429     painter.translate(pageRect.left() * scale, pageRect.top() * scale);
0430 
0431     // Scale according to the printer's resolution.
0432     painter.scale(scale, scale);
0433 
0434     const SheetPrint *const pageManager = d->pageManagers[sheet];
0435     const PrintSettings *const settings = pageManager->settings();
0436     const KoPageLayout pageLayout = settings->pageLayout();
0437     const double zoom = settings->zoom();
0438     debugSheets << "printing page" << sheetPageNumber << "; cell range" << cellRange;
0439 
0440     if (settings->printHeaders()) {
0441         painter.save();
0442         painter.resetMatrix();
0443         painter.scale(scale, scale); // no zooming; just resolution
0444         painter.setClipping(false);
0445         d->printHeaderFooter(painter, sheet, pageNumber);
0446         painter.restore();
0447     }
0448 
0449     // setup the QPainter
0450     painter.save();
0451     painter.setClipRect(0.0, 0.0, pageLayout.width / zoom, pageLayout.height / zoom);
0452 
0453     // setup the SheetView
0454     SheetView *const sheetView = d->view->sheetView(sheet);
0455     const KoViewConverter *const origViewConverter = sheetView->viewConverter();
0456 
0457     KoZoomHandler zoomHandler;
0458     zoomHandler.setZoom(zoom);
0459     sheetView->setViewConverter(&zoomHandler);
0460 
0461     // save and set painting flags
0462     const bool grid = sheet->getShowGrid();
0463     const bool commentIndicator = sheet->getShowCommentIndicator();
0464     const bool formulaIndicator = sheet->getShowFormulaIndicator();
0465     sheet->setShowGrid(settings->printGrid());
0466     sheet->setShowCommentIndicator(settings->printCommentIndicator());
0467     sheet->setShowFormulaIndicator(settings->printFormulaIndicator());
0468 
0469     // Calculate the dimensions of the repeated columns/rows first.
0470     double repeatedWidth = 0.0;
0471     const QPair<int, int> repeatedColumns = settings->repeatedColumns();
0472     if (repeatedColumns.first != 0 && cellRange.left() > repeatedColumns.second) {
0473         for (int col = repeatedColumns.first; col <= repeatedColumns.second; ++col) {
0474             repeatedWidth += sheet->columnFormat(col)->visibleWidth();
0475         }
0476     }
0477     double repeatedHeight = 0.0;
0478     const QPair<int, int> repeatedRows = settings->repeatedRows();
0479     if (repeatedRows.first != 0 && cellRange.top() > repeatedRows.second) {
0480         repeatedHeight += sheet->rowFormats()->totalVisibleRowHeight(repeatedRows.first, repeatedRows.second);
0481     }
0482 
0483     // Paint top left part of the repeated columns/rows, if both are present.
0484     if (repeatedWidth > 0.0 && repeatedHeight > 0.0) {
0485         const QPointF topLeft(0, 0);
0486         const QRect range = QRect(QPoint(repeatedColumns.first, repeatedRows.first),
0487                                   QPoint(repeatedColumns.second, repeatedRows.second));
0488         const QRectF paintRect(0.0, 0.0, repeatedWidth, repeatedHeight);
0489         sheetView->setPaintCellRange(range);
0490         sheetView->paintCells(painter, paintRect, topLeft);
0491     }
0492 
0493     // Paint top part: the repeated rows, if present.
0494     if (repeatedHeight > 0.0) {
0495         const QPointF topLeft(repeatedWidth, 0);
0496         const QRect range = QRect(QPoint(cellRange.left(), repeatedRows.first),
0497                                   QPoint(cellRange.right(), repeatedRows.second));
0498         const QRectF paintRect(repeatedWidth, 0.0, pageRect.width(), repeatedHeight);
0499         sheetView->setPaintCellRange(range);
0500         sheetView->paintCells(painter, paintRect, topLeft);
0501     }
0502 
0503     // Paint left part: the repeated columns, if present.
0504     if (repeatedWidth > 0.0) {
0505         const QPointF topLeft(0, repeatedHeight);
0506         const QRect range = QRect(QPoint(repeatedColumns.first, cellRange.top()),
0507                                   QPoint(repeatedColumns.second, cellRange.bottom()));
0508         const QRectF paintRect(0.0, repeatedHeight, repeatedWidth, pageRect.height());
0509         sheetView->setPaintCellRange(range);
0510         sheetView->paintCells(painter, paintRect, topLeft);
0511     }
0512 
0513     // Paint the actual cell range.
0514     const QPointF topLeft(repeatedWidth, repeatedHeight);
0515     const QRectF paintRect(topLeft, pageRect.size());
0516     sheetView->setPaintCellRange(cellRange);
0517     sheetView->paintCells(painter, paintRect, topLeft);
0518 
0519     // restore painting flags
0520     sheet->setShowGrid(grid);
0521     sheet->setShowCommentIndicator(commentIndicator);
0522     sheet->setShowFormulaIndicator(formulaIndicator);
0523     sheetView->setViewConverter(origViewConverter);
0524     painter.restore();
0525 }
0526 
0527 QList<KoShape*> PrintJob::shapesOnPage(int pageNumber)
0528 {
0529     // This method is called only for page preparation; to determine the shapes to wait for.
0530     int sheetPageNumber = pageNumber;
0531     Sheet* sheet = d->getSheetPageNumber(&sheetPageNumber);
0532     if (!sheet)
0533         return QList<KoShape*>();
0534 
0535     const QRectF documentArea = d->pageManagers[sheet]->documentArea(sheetPageNumber);
0536     return shapeManager()->shapesAt(documentArea);
0537 }
0538 
0539 QList<QWidget*> PrintJob::createOptionWidgets() const
0540 {
0541     return QList<QWidget*>() << d->sheetSelectPage;
0542 }
0543 
0544 QAbstractPrintDialog::PrintDialogOptions PrintJob::printDialogOptions() const
0545 {
0546     return QAbstractPrintDialog::PrintToFile |
0547            QAbstractPrintDialog::PrintSelection |
0548            QAbstractPrintDialog::PrintPageRange |
0549            QAbstractPrintDialog::PrintCollateCopies |
0550            QAbstractPrintDialog::DontUseSheet;
0551 }