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"