File indexing completed on 2024-05-19 15:27:52

0001 /* This file is part of KGraphViewer.
0002    Copyright (C) 2005-2007 Gael de Chalendar <kleag@free.fr>
0003 
0004    KGraphViewer is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU General Public
0006    License as published by the Free Software Foundation, version 2.
0007 
0008    This program is distributed in the hope that it will be useful,
0009    but WITHOUT ANY WARRANTY; without even the implied warranty of
0010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0011    General Public License for more details.
0012 
0013    You should have received a copy of the GNU General Public License
0014    along with this program; if not, write to the Free Software
0015    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0016    02110-1301, USA
0017 */
0018 
0019 /* This file was part of the KDE project
0020    Copyright (C) 2005 Jarosław Staniek <staniek@kde.org>
0021 
0022    This program is free software; you can redistribute it and/or
0023    modify it under the terms of the GNU Library General Public
0024    License as published by the Free Software Foundation; either
0025    version 2 of the License, or (at your option) any later version.
0026  */
0027 
0028 #include "simpleprintingengine.h"
0029 #include "kgraphviewerlib_debug.h"
0030 #include "simpleprintingsettings.h"
0031 
0032 #include <QApplication>
0033 #include <QDebug>
0034 #include <QFontDialog>
0035 #include <QIcon>
0036 #include <kconfig.h>
0037 #include <kurllabel.h>
0038 
0039 #include <qcheckbox.h>
0040 #include <qimage.h>
0041 #include <qlabel.h>
0042 #include <qlayout.h>
0043 #include <qpainter.h>
0044 
0045 #include <QDateTime>
0046 #include <QGraphicsScene>
0047 #include <QPaintDevice>
0048 #include <QPixmap>
0049 #include <klocalizedstring.h>
0050 #include <math.h>
0051 
0052 namespace KGraphViewer
0053 {
0054 KGVSimplePrintingEngine::KGVSimplePrintingEngine(KGVSimplePrintingSettings *settings, QObject *parent)
0055     : QObject(parent)
0056     , m_settings(settings)
0057     , m_data(nullptr)
0058 {
0059     setObjectName("KGVSimplePrintingEngine");
0060     clear();
0061 }
0062 
0063 KGVSimplePrintingEngine::~KGVSimplePrintingEngine()
0064 {
0065     done();
0066 }
0067 
0068 bool KGVSimplePrintingEngine::init(DotGraphView &data, const QString &titleText, QString &errorMessage)
0069 {
0070     errorMessage.clear();
0071     done();
0072     m_headerText = titleText;
0073 
0074     m_data = &data;
0075     m_eof = false;
0076 
0077     m_painting = QPixmap(m_data->scene()->sceneRect().size().toSize());
0078     QPainter p(&m_painting);
0079     m_data->scene()->render(&p);
0080 
0081     return true;
0082 }
0083 
0084 bool KGVSimplePrintingEngine::done()
0085 {
0086     bool result = true;
0087     m_data = nullptr;
0088     m_pagesCount = 0;
0089     m_paintInitialized = false;
0090     return result;
0091 }
0092 
0093 void KGVSimplePrintingEngine::clear()
0094 {
0095     m_eof = false;
0096     m_pagesCount = 0;
0097     m_paintInitialized = false;
0098 }
0099 
0100 void KGVSimplePrintingEngine::paintPage(int pageNumber, QPainter &painter, bool paint)
0101 {
0102     qCDebug(KGRAPHVIEWERLIB_LOG) << pageNumber << "/" << m_pagesCount << paint;
0103 
0104     uint y = 0;
0105 
0106     if (pageNumber <= m_pagesCount) {
0107         m_eof = false;
0108     }
0109     int w = 0, h = 0;
0110     QPaintDevice *pdm = painter.device();
0111     const bool printer = pdm->devType() == QInternal::Printer;
0112     qCDebug(KGRAPHVIEWERLIB_LOG) << "printer:" << printer;
0113 
0114     if (!printer) {
0115         w = pdm->width();
0116         h = pdm->height();
0117     } else { // QPrinter...
0118         w = pdm->widthMM();
0119         h = pdm->heightMM();
0120     }
0121 
0122     if (!m_paintInitialized) {
0123         qCDebug(KGRAPHVIEWERLIB_LOG) << "initializing";
0124         // HACK: some functions here do not work properly if were
0125         // are not in a paint event, so repeat this until we actually paint.
0126         m_paintInitialized = paint;
0127 
0128         double widthMM = KgvPageFormat::width(m_settings->pageLayout.format, m_settings->pageLayout.orientation);
0129         double heightMM = KgvPageFormat::height(m_settings->pageLayout.format, m_settings->pageLayout.orientation);
0130 
0131         m_dpiY = pdm->logicalDpiY();
0132         m_dpiX = pdm->logicalDpiX();
0133 #ifdef Q_WS_WIN // fix for 120dpi
0134         if (!printer) {
0135             //          m_dpiY = 96;
0136             //          m_dpiX = 96;
0137             m_dpiY = 86;
0138             m_dpiX = 86;
0139         }
0140 #endif
0141         int pdWidthMM = pdm->widthMM();
0142         int pdHeightMM = pdm->heightMM();
0143 
0144         double screenF;
0145         //      if (printer)
0146         screenF = 1.0;
0147         //      else
0148         //          screenF = (double)96.0/120.0;
0149 
0150         leftMargin = POINT_TO_INCH(m_settings->pageLayout.ptLeft) * m_dpiX * screenF;
0151         rightMargin = POINT_TO_INCH(m_settings->pageLayout.ptRight) * m_dpiX * screenF;
0152         topMargin = POINT_TO_INCH(m_settings->pageLayout.ptTop) * m_dpiY * screenF;
0153         bottomMargin = POINT_TO_INCH(m_settings->pageLayout.ptBottom) * m_dpiY * screenF;
0154 
0155         m_fx = widthMM / (pdWidthMM * screenF);
0156         m_fy = heightMM / (pdHeightMM * screenF);
0157 
0158         // screen only
0159         //  painter.fillRect(QRect(0,0,w,h), QBrush(white));
0160         m_pageWidth = int(m_fx * (double)pdm->width() - leftMargin - rightMargin);
0161         m_pageHeight = int(m_fy * (double)pdm->height() - topMargin - bottomMargin);
0162 
0163         //! @todo add setting
0164         m_mainFont = m_settings->pageTitleFont;
0165         if (!printer) {
0166             int pixelSize = int(POINT_TO_INCH(m_mainFont.pointSizeF()) * m_dpiX);
0167             m_mainFont.setPixelSize(pixelSize);
0168         }
0169         painter.setFont(m_mainFont);
0170 
0171         m_dateTimeText = QLocale().toString(QDateTime::currentDateTime());
0172         m_dateTimeWidth = 0;
0173         if (m_settings->addDateAndTime) {
0174             m_dateTimeWidth = painter.boundingRect(leftMargin, topMargin, m_pageWidth, m_pageHeight, Qt::AlignRight, m_dateTimeText + "   ").width();
0175         }
0176         m_mainLineSpacing = painter.fontMetrics().lineSpacing();
0177         m_headerTextRect = painter.boundingRect((int)leftMargin, (int)topMargin, m_pageWidth - m_dateTimeWidth, m_pageHeight, Qt::AlignLeft | Qt::TextWordWrap, m_headerText);
0178         m_headerTextRect.setRight(m_headerTextRect.right() + 10);
0179         m_headerTextRect.setWidth(qMin(int(m_pageWidth - m_dateTimeWidth), m_headerTextRect.width()));
0180     }
0181     qCDebug(KGRAPHVIEWERLIB_LOG) << "after initialization";
0182 
0183     // screen only
0184     if (!printer) {
0185         painter.setWindow(0, 0, int((double)w * m_fx), int((double)h * m_fy));
0186     }
0187 
0188     painter.setFont(m_mainFont);
0189     if (paint) {
0190         // paint header
0191         painter.drawText(m_headerTextRect, Qt::AlignLeft | Qt::TextWordWrap, m_headerText);
0192         if (m_settings->addDateAndTime) {
0193             painter.drawText((int)leftMargin + m_pageWidth - m_dateTimeWidth, (int)topMargin, m_dateTimeWidth, m_headerTextRect.height(), Qt::AlignRight, m_dateTimeText);
0194         }
0195 
0196         // footer
0197         if (m_settings->addPageNumbers) {
0198             QString pageNumString;
0199             if (m_pagesCount > 0) {
0200                 pageNumString = i18nc("Page (number) of (total)", "Page %1 of %2", pageNumber + 1, m_pagesCount);
0201             } else {
0202                 pageNumString = i18n("Page %1", pageNumber + 1);
0203             }
0204             painter.drawText((int)leftMargin, (int)topMargin + m_pageHeight - m_mainLineSpacing, m_pageWidth, m_mainLineSpacing, Qt::AlignRight | Qt::AlignBottom, pageNumString);
0205         }
0206     }
0207 
0208     w = m_pageWidth;
0209     h = m_pageHeight;
0210     y = (int)topMargin;
0211     h -= (m_headerTextRect.height() + 1);
0212     y += (m_headerTextRect.height());
0213     if (m_settings->addTableBorders) {
0214         w -= 2;
0215         h -= 2;
0216     }
0217     if (m_settings->addPageNumbers) {
0218         h -= (m_mainLineSpacing * 3 / 2 + 1);
0219     }
0220 
0221     qCDebug(KGRAPHVIEWERLIB_LOG) << "(w, h) = (" << w << ", " << h << ")";
0222     if (((m_settings->fitToOnePage) || (m_painting.width() <= w && m_painting.height() <= h)) && !m_eof) {
0223         qCDebug(KGRAPHVIEWERLIB_LOG) << "single-page printing";
0224         if (paint) {
0225             QPixmap pix = m_painting.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
0226             qCDebug(KGRAPHVIEWERLIB_LOG) << "drawPixmap";
0227             painter.drawPixmap((int)leftMargin, y, pix);
0228         }
0229         m_eof = true;
0230     } else if (m_settings->horizFitting != 0 || m_settings->vertFitting != 0) {
0231         qCDebug(KGRAPHVIEWERLIB_LOG) << "fitted multi-pages printing page " << pageNumber;
0232         int nbTilesByRow = (int)(ceil((double)m_painting.width()) / w) + 1;
0233         qCDebug(KGRAPHVIEWERLIB_LOG) << "  nb tiles by row = " << nbTilesByRow;
0234 
0235         int tileWidth = w;
0236         int tileHeight = h;
0237 
0238         if (m_settings->horizFitting != 0) {
0239             tileWidth = int(ceil(((double)m_painting.width()) / m_settings->horizFitting));
0240             nbTilesByRow = m_settings->horizFitting;
0241         }
0242         if (m_settings->vertFitting != 0) {
0243             tileHeight = int(ceil(((double)m_painting.height()) / m_settings->vertFitting));
0244         }
0245         qCDebug(KGRAPHVIEWERLIB_LOG) << "  tile size = " << tileWidth << "/" << tileHeight;
0246         int rowNum = pageNumber / nbTilesByRow;
0247         int columnNum = pageNumber % nbTilesByRow;
0248         int x1, y1, x2, y2;
0249         x1 = int(tileWidth * columnNum);
0250         x2 = int(tileWidth * (columnNum + 1));
0251         y1 = int(tileHeight * rowNum);
0252         y2 = int(tileHeight * (rowNum + 1));
0253         qCDebug(KGRAPHVIEWERLIB_LOG) << "(x1, y1, x2, 2) = (" << x1 << "," << y1 << "," << x2 << "," << y2 << ")";
0254         qCDebug(KGRAPHVIEWERLIB_LOG) << "painting size = (" << m_painting.width() << "/" << m_painting.height() << ")";
0255         if (paint) {
0256             Qt::AspectRatioMode scaleMode = Qt::IgnoreAspectRatio;
0257             if (m_settings->chainedFittings) {
0258                 scaleMode = Qt::KeepAspectRatio;
0259             }
0260             QPixmap pix = m_painting.copy(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
0261             if (m_settings->horizFitting == 0) {
0262                 pix = pix.scaled(pix.width(), h, scaleMode, Qt::SmoothTransformation);
0263             } else if (m_settings->vertFitting == 0) {
0264                 pix = pix.scaled(w, pix.height(), scaleMode, Qt::SmoothTransformation);
0265             } else {
0266                 pix = pix.scaled(w, h, scaleMode, Qt::SmoothTransformation);
0267             }
0268             painter.drawPixmap((int)leftMargin, y, pix);
0269         }
0270         if (x2 >= m_painting.width() && y2 >= m_painting.height()) {
0271             m_eof = true;
0272         }
0273     } else {
0274         qCDebug(KGRAPHVIEWERLIB_LOG) << "multi-pages printing page " << pageNumber;
0275         int nbTilesByRow = (int)(((double)m_painting.width()) / w) + 1;
0276         int rowNum = pageNumber / nbTilesByRow;
0277         int columnNum = pageNumber % nbTilesByRow;
0278         int x1, y1, x2, y2;
0279         x1 = int(w * columnNum);
0280         x2 = int(w * (columnNum + 1));
0281         y1 = int(h * rowNum);
0282         y2 = int(h * (rowNum + 1));
0283         qCDebug(KGRAPHVIEWERLIB_LOG) << "(x1, y1, x2, 2) = (" << x1 << "," << y1 << "," << x2 << "," << y2 << ")";
0284         if (paint) {
0285             painter.drawPixmap((int)leftMargin, y, m_painting.copy(x1, y1, x2 - x1 + 1, y2 - y1 + 1));
0286         }
0287         if (x2 >= m_painting.width() && y2 >= m_painting.height()) {
0288             m_eof = true;
0289         }
0290     }
0291 
0292     if (m_settings->addTableBorders) {
0293         qCDebug(KGRAPHVIEWERLIB_LOG) << "Adding table borders";
0294         int y1 = (int)topMargin;
0295         y1 += (m_headerTextRect.height());
0296         int y2 = (int)topMargin + m_pageHeight;
0297         if (m_settings->addPageNumbers) {
0298             y2 -= (m_headerTextRect.height() /*+ m_mainLineSpacing*3/2*/ + 1);
0299         }
0300         if (paint) {
0301             painter.drawLine((int)leftMargin, y1, (int)leftMargin + m_pageWidth - 1, y1);
0302             painter.drawLine((int)leftMargin + m_pageWidth - 1, y1, (int)leftMargin + m_pageWidth - 1, y2);
0303             painter.drawLine((int)leftMargin + m_pageWidth - 1, y2, (int)leftMargin, y2);
0304             painter.drawLine((int)leftMargin, y2, (int)leftMargin, y1);
0305         }
0306     }
0307     qCDebug(KGRAPHVIEWERLIB_LOG) << "paintPage done";
0308 }
0309 
0310 void KGVSimplePrintingEngine::calculatePagesCount(QPainter &painter)
0311 {
0312     if (m_eof || !m_data) {
0313         m_pagesCount = 0;
0314         return;
0315     }
0316 
0317     uint pageNumber = 0;
0318     if (m_settings->fitToOnePage) {
0319         m_pagesCount = 1;
0320     } else {
0321         for (; !m_eof; ++pageNumber) {
0322             paintPage(pageNumber, painter, false /* !paint */);
0323         }
0324         m_pagesCount = pageNumber;
0325     }
0326 }
0327 
0328 void KGVSimplePrintingEngine::setTitleText(const QString &titleText)
0329 {
0330     m_headerText = titleText;
0331 }
0332 
0333 uint KGVSimplePrintingEngine::maxHorizFit() const
0334 {
0335     uint w = m_pageWidth;
0336     if (m_settings->addTableBorders) {
0337         w -= 2;
0338     }
0339     //   () << "maxHorizFit: " << m_painting.width() << " / " << w
0340     //     << " = " << m_painting.width()/w;
0341     return (uint)ceil(((double)m_painting.width()) / w) + 1;
0342 }
0343 
0344 uint KGVSimplePrintingEngine::maxVertFit() const
0345 {
0346     uint h = m_pageHeight;
0347     h -= (m_headerTextRect.height() + 1);
0348     if (m_settings->addTableBorders) {
0349         h -= 2;
0350     }
0351     if (m_settings->addPageNumbers) {
0352         h -= (m_mainLineSpacing * 3 / 2 + 1);
0353     }
0354     //   qCDebug(KGRAPHVIEWERLIB_LOG) << "maxVertFit: " << m_painting.height() << " / " << h
0355     //     << " = " << m_painting.height()/h;
0356     return (uint)ceil(((double)m_painting.height())) / h + 1;
0357 }
0358 
0359 }
0360 
0361 #include "moc_simpleprintingengine.cpp"