File indexing completed on 2024-05-12 04:19:47

0001 // vim: set tabstop=4 shiftwidth=4 expandtab:
0002 /*
0003 Gwenview: an image viewer
0004 Copyright 2007 Aurélien Gâteau <agateau@kde.org>
0005 
0006 This program is free software; you can redistribute it and/or
0007 modify it under the terms of the GNU General Public License
0008 as published by the Free Software Foundation; either version 2
0009 of the License, or (at your option) any later version.
0010 
0011 This program is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU General Public License for more details.
0015 
0016 You should have received a copy of the GNU General Public License
0017 along with this program; if not, write to the Free Software
0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0019 
0020 */
0021 // Self
0022 #include "printhelper.h"
0023 
0024 // STD
0025 #include <memory>
0026 
0027 // Qt
0028 #include <QCheckBox>
0029 #include <QPainter>
0030 #include <QPrintDialog>
0031 #include <QPrintPreviewDialog>
0032 #include <QPrinter>
0033 #include <QUrl>
0034 
0035 // KF
0036 #include <KLocalizedString>
0037 
0038 // Local
0039 #include "printoptionspage.h"
0040 
0041 namespace Gwenview
0042 {
0043 struct PrintHelperPrivate {
0044     QWidget *mParent = nullptr;
0045 
0046     QSize adjustSize(PrintOptionsPage *optionsPage, Document::Ptr doc, int printerResolution, const QSize &viewportSize)
0047     {
0048         QSize size = doc->size();
0049         PrintOptionsPage::ScaleMode scaleMode = optionsPage->scaleMode();
0050         if (scaleMode == PrintOptionsPage::ScaleToPage) {
0051             bool imageBiggerThanPaper = size.width() > viewportSize.width() || size.height() > viewportSize.height();
0052 
0053             if (imageBiggerThanPaper || optionsPage->enlargeSmallerImages()) {
0054                 size.scale(viewportSize, Qt::KeepAspectRatio);
0055             }
0056 
0057         } else if (scaleMode == PrintOptionsPage::ScaleToCustomSize) {
0058             double wImg = optionsPage->scaleWidth();
0059             double hImg = optionsPage->scaleHeight();
0060             size.setWidth(int(wImg * printerResolution));
0061             size.setHeight(int(hImg * printerResolution));
0062 
0063         } else {
0064             // No scale
0065             const double INCHES_PER_METER = 100. / 2.54;
0066             const int dpmX = doc->image().dotsPerMeterX();
0067             const int dpmY = doc->image().dotsPerMeterY();
0068             if (dpmX > 0 && dpmY > 0) {
0069                 double wImg = double(size.width()) / double(dpmX) * INCHES_PER_METER;
0070                 double hImg = double(size.height()) / double(dpmY) * INCHES_PER_METER;
0071                 size.setWidth(int(wImg * printerResolution));
0072                 size.setHeight(int(hImg * printerResolution));
0073             }
0074         }
0075         return size;
0076     }
0077 
0078     QPoint adjustPosition(PrintOptionsPage *optionsPage, const QSize &imageSize, const QSize &viewportSize)
0079     {
0080         Qt::Alignment alignment = optionsPage->alignment();
0081         int posX, posY;
0082 
0083         if (alignment & Qt::AlignLeft) {
0084             posX = 0;
0085         } else if (alignment & Qt::AlignHCenter) {
0086             posX = (viewportSize.width() - imageSize.width()) / 2;
0087         } else {
0088             posX = viewportSize.width() - imageSize.width();
0089         }
0090 
0091         if (alignment & Qt::AlignTop) {
0092             posY = 0;
0093         } else if (alignment & Qt::AlignVCenter) {
0094             posY = (viewportSize.height() - imageSize.height()) / 2;
0095         } else {
0096             posY = viewportSize.height() - imageSize.height();
0097         }
0098 
0099         return QPoint(posX, posY);
0100     }
0101 
0102     void setupPrinter(QPrinter *printer, Document::Ptr doc)
0103     {
0104         doc->waitUntilLoaded();
0105         printer->setDocName(doc->url().fileName());
0106         const auto docSize = doc->size();
0107         printer->setPageOrientation(docSize.width() > docSize.height() ? QPageLayout::Landscape : QPageLayout::Portrait);
0108     }
0109 
0110     void print(QPrinter *printer, Document::Ptr doc, bool showPrinterSetupDialog)
0111     {
0112         auto optionsPage = new PrintOptionsPage(doc->size());
0113         optionsPage->loadConfig();
0114 
0115         QScopedPointer<QPrintDialog> dialog;
0116         if (showPrinterSetupDialog) {
0117             dialog.reset(new QPrintDialog(printer, mParent));
0118 #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
0119             dialog->setOptionTabs(QList<QWidget *>() << optionsPage);
0120 #else
0121             optionsPage->setParent(dialog.data());
0122 #endif
0123 
0124             dialog->setWindowTitle(i18n("Print Image"));
0125             bool wantToPrint = dialog->exec();
0126 
0127             optionsPage->saveConfig();
0128             if (!wantToPrint) {
0129                 return;
0130             }
0131         }
0132 
0133         QPainter painter(printer);
0134         const QRect rect = painter.viewport();
0135         const QSize size = adjustSize(optionsPage, doc, printer->resolution(), rect.size());
0136         const QPoint pos = adjustPosition(optionsPage, size, rect.size());
0137         painter.setViewport(pos.x(), pos.y(), size.width(), size.height());
0138         if (!dialog) {
0139             delete optionsPage;
0140         }
0141 
0142         const QImage image = doc->image();
0143         painter.setWindow(image.rect());
0144         painter.drawImage(0, 0, image);
0145     }
0146 };
0147 
0148 PrintHelper::PrintHelper(QWidget *parent)
0149     : d(new PrintHelperPrivate)
0150 {
0151     d->mParent = parent;
0152 }
0153 
0154 PrintHelper::~PrintHelper()
0155 {
0156     delete d;
0157 }
0158 
0159 void PrintHelper::print(Document::Ptr doc)
0160 {
0161     QPrinter printer;
0162     d->setupPrinter(&printer, doc);
0163     d->print(&printer, doc, true);
0164 }
0165 
0166 void PrintHelper::printPreview(Document::Ptr doc)
0167 {
0168     QPrinter printer;
0169     d->setupPrinter(&printer, doc);
0170     QPrintPreviewDialog dlg(&printer, d->mParent);
0171     QObject::connect(&dlg, &QPrintPreviewDialog::paintRequested, [this, doc](QPrinter *printer) {
0172         d->print(printer, doc, false);
0173     });
0174     dlg.exec();
0175 }
0176 
0177 } // namespace